aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs9
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs12
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs74
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs47
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs21
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs135
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs107
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs172
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs49
16 files changed, 435 insertions, 251 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..1e14f45 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33 33
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Region.Framework.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.Agent.AssetTransaction 38namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
@@ -119,6 +120,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
119 } 120 }
120 else 121 else
121 { 122 {
123 // Check if the xfer is a terrain xfer
124 IEstateModule estateModule = m_Scene.RequestModuleInterface<IEstateModule>();
125 if (estateModule != null)
126 {
127 if (estateModule.IsTerrainXfer(xferID))
128 return;
129 }
130
122 m_log.ErrorFormat( 131 m_log.ErrorFormat(
123 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", 132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
124 xferID, packetID, data.Length); 133 xferID, packetID, data.Length);
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 2116605..ff87ece 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -42,14 +42,22 @@ using log4net;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Friends 43namespace OpenSim.Region.CoreModules.Avatar.Friends
44{ 44{
45 public class FriendsRequestHandler : BaseStreamHandler 45 public class FriendsRequestHandler : BaseStreamHandlerBasicDOSProtector
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private FriendsModule m_FriendsModule; 49 private FriendsModule m_FriendsModule;
50 50
51 public FriendsRequestHandler(FriendsModule fmodule) 51 public FriendsRequestHandler(FriendsModule fmodule)
52 : base("POST", "/friends") 52 : base("POST", "/friends", new BasicDosProtectorOptions()
53 {
54 AllowXForwardedFor = true,
55 ForgetTimeSpan = TimeSpan.FromMinutes(2),
56 MaxRequestsInTimeframe = 20,
57 ReportingName = "FRIENDSDOSPROTECTOR",
58 RequestTimeSpan = TimeSpan.FromSeconds(5),
59 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
60 })
53 { 61 {
54 m_FriendsModule = fmodule; 62 m_FriendsModule = fmodule;
55 } 63 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index ac4203f..6251266 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -789,83 +789,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
789 789
790 SceneObjectGroup group = null; 790 SceneObjectGroup group = null;
791 791
792 string xmlData = Utils.BytesToString(rezAsset.Data); 792 List<SceneObjectGroup> objlist;
793 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); 793 List<Vector3> veclist;
794 List<Vector3> veclist = new List<Vector3>(); 794 Vector3 bbox;
795 float offsetHeight;
795 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 796 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
796 Vector3 pos; 797 Vector3 pos;
797 798
798 XmlDocument doc = new XmlDocument(); 799 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
799 doc.LoadXml(xmlData);
800 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
801 Vector3 rez_pos;
802 if (e == null || attachment) // Single
803 {
804 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
805 if (!attachment)
806 {
807 g.RootPart.AttachPoint = g.RootPart.Shape.State;
808 g.RootPart.AttachOffset = g.AbsolutePosition;
809 g.RootPart.AttachRotation = g.GroupRotation;
810 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
811 g.RootPart.Shape.PCode != (byte)PCode.Tree)
812 g.RootPart.Shape.State = 0;
813 }
814
815 objlist.Add(g);
816 veclist.Add(Vector3.Zero);
817 800
818 float offsetHeight = 0; 801 if (single)
802 {
819 pos = m_Scene.GetNewRezLocation( 803 pos = m_Scene.GetNewRezLocation(
820 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 804 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
821 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 805 BypassRayCast, bRayEndIsIntersection, true, bbox, false);
822 pos.Z += offsetHeight; 806 pos.Z += offsetHeight;
823 rez_pos = pos;
824 } 807 }
825 else 808 else
826 { 809 {
827 XmlElement coll = (XmlElement)e;
828 float bx = Convert.ToSingle(coll.GetAttribute("x"));
829 float by = Convert.ToSingle(coll.GetAttribute("y"));
830 float bz = Convert.ToSingle(coll.GetAttribute("z"));
831 Vector3 bbox = new Vector3(bx, by, bz);
832
833 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, 810 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
834 RayTargetID, Quaternion.Identity, 811 RayTargetID, Quaternion.Identity,
835 BypassRayCast, bRayEndIsIntersection, true, 812 BypassRayCast, bRayEndIsIntersection, true,
836 bbox, false); 813 bbox, false);
837
838 rez_pos = pos;
839
840 pos -= bbox / 2; 814 pos -= bbox / 2;
841
842 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
843 foreach (XmlNode n in groups)
844 {
845 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
846 g.RootPart.AttachPoint = g.RootPart.Shape.State;
847 g.RootPart.AttachOffset = g.AbsolutePosition;
848 g.RootPart.AttachRotation = g.GroupRotation;
849 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
850 g.RootPart.Shape.PCode != (byte)PCode.Tree)
851 g.RootPart.Shape.State = 0;
852
853 objlist.Add(g);
854 XmlElement el = (XmlElement)n;
855
856 string rawX = el.GetAttribute("offsetx");
857 string rawY = el.GetAttribute("offsety");
858 string rawZ = el.GetAttribute("offsetz");
859//
860// m_log.DebugFormat(
861// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
862// g.Name, rawX, rawY, rawZ);
863
864 float x = Convert.ToSingle(rawX);
865 float y = Convert.ToSingle(rawY);
866 float z = Convert.ToSingle(rawZ);
867 veclist.Add(new Vector3(x, y, z));
868 }
869 } 815 }
870 816
871 int primcount = 0; 817 int primcount = 0;
@@ -873,7 +819,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
873 primcount += g.PrimCount; 819 primcount += g.PrimCount;
874 820
875 if (!m_Scene.Permissions.CanRezObject( 821 if (!m_Scene.Permissions.CanRezObject(
876 primcount, remoteClient.AgentId, rez_pos) 822 primcount, remoteClient.AgentId, pos)
877 && !attachment) 823 && !attachment)
878 { 824 {
879 // The client operates in no fail mode. It will 825 // The client operates in no fail mode. It will
@@ -890,7 +836,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
890 return null; 836 return null;
891 } 837 }
892 838
893 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, rez_pos, veclist, attachment)) 839 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
894 return null; 840 return null;
895 841
896 for (int i = 0; i < objlist.Count; i++) 842 for (int i = 0; i < objlist.Count; i++)
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 487aa09..4750b46 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -839,26 +839,23 @@ namespace OpenSim.Region.CoreModules.World.Estate
839 839
840 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 840 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
841 { 841 {
842 if (TerrainUploader != null) 842 lock (this)
843 { 843 {
844 lock (TerrainUploader) 844 if ((TerrainUploader != null) && (XferID == TerrainUploader.XferID))
845 { 845 {
846 if (XferID == TerrainUploader.XferID) 846 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
847 { 847 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
848 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 848 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
849 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
850 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
851 849
852 TerrainUploader = null; 850 TerrainUploader = null;
853 remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); 851 remoteClient.SendAlertMessage("Terrain Upload aborted by the client");
854 }
855 } 852 }
856 } 853 }
857
858 } 854 }
855
859 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) 856 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient)
860 { 857 {
861 lock (TerrainUploader) 858 lock (this)
862 { 859 {
863 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 860 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
864 remoteClient.OnAbortXfer -= AbortTerrainXferHandler; 861 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
@@ -917,22 +914,32 @@ namespace OpenSim.Region.CoreModules.World.Estate
917 914
918 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) 915 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName)
919 { 916 {
920 if (TerrainUploader == null) 917 lock (this)
921 { 918 {
922 919 if (TerrainUploader == null)
923 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
924 lock (TerrainUploader)
925 { 920 {
921 m_log.DebugFormat("Starting to receive uploaded terrain");
922 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
926 remote_client.OnXferReceive += TerrainUploader.XferReceive; 923 remote_client.OnXferReceive += TerrainUploader.XferReceive;
927 remote_client.OnAbortXfer += AbortTerrainXferHandler; 924 remote_client.OnAbortXfer += AbortTerrainXferHandler;
928 TerrainUploader.TerrainUploadDone += HandleTerrainApplication; 925 TerrainUploader.TerrainUploadDone += HandleTerrainApplication;
926 TerrainUploader.RequestStartXfer(remote_client);
927 }
928 else
929 {
930 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!");
929 } 931 }
930 TerrainUploader.RequestStartXfer(remote_client);
931
932 } 932 }
933 else 933 }
934
935 public bool IsTerrainXfer(ulong xferID)
936 {
937 lock (this)
934 { 938 {
935 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); 939 if (TerrainUploader == null)
940 return false;
941 else
942 return TerrainUploader.XferID == xferID;
936 } 943 }
937 } 944 }
938 945
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
index b8d8b10..2d74eaf 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
@@ -78,7 +78,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
78 /// <param name="data"></param> 78 /// <param name="data"></param>
79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) 79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
80 { 80 {
81 if (mXferID == xferID) 81 if (mXferID != xferID)
82 return;
83
84 lock (this)
82 { 85 {
83 if (m_asset.Data.Length > 1) 86 if (m_asset.Data.Length > 1)
84 { 87 {
@@ -99,7 +102,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 if ((packetID & 0x80000000) != 0) 102 if ((packetID & 0x80000000) != 0)
100 { 103 {
101 SendCompleteMessage(remoteClient); 104 SendCompleteMessage(remoteClient);
102
103 } 105 }
104 } 106 }
105 } 107 }
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index bf18616..98fa763 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -162,7 +162,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
162 regionimage = regionimage.Replace("-", ""); 162 regionimage = regionimage.Replace("-", "");
163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
164 164
165 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); 165 MainServer.Instance.AddHTTPHandler(regionimage,
166 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
167 {
168 AllowXForwardedFor = false,
169 ForgetTimeSpan = TimeSpan.FromMinutes(2),
170 MaxRequestsInTimeframe = 4,
171 ReportingName = "MAPDOSPROTECTOR",
172 RequestTimeSpan = TimeSpan.FromSeconds(10),
173 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
174 }).Process);
166 MainServer.Instance.AddLLSDHandler( 175 MainServer.Instance.AddLLSDHandler(
167 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 176 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
168 177
@@ -1131,6 +1140,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1131 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); 1140 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1132 } 1141 }
1133 1142
1143 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1144 {
1145 Hashtable reply = new Hashtable();
1146 int statuscode = 500;
1147 reply["str_response_string"] = "";
1148 reply["int_response_code"] = statuscode;
1149 reply["content_type"] = "text/plain";
1150 return reply;
1151 }
1152
1134 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1153 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1135 { 1154 {
1136 m_log.Debug("[WORLD MAP]: Sending map image jpeg"); 1155 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 8028d87..eba881f 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -236,15 +236,17 @@ namespace OpenSim.Region.Framework.Interfaces
236 List<TaskInventoryItem> GetInventoryItems(InventoryType type); 236 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
237 237
238 /// <summary> 238 /// <summary>
239 /// Get the scene object referenced by an inventory item. 239 /// Get the scene object(s) referenced by an inventory item.
240 /// </summary> 240 /// </summary>
241 /// 241 ///
242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
243 /// been adjusted to reflect the part and item from which it originates. 243 /// been adjusted to reflect the part and item from which it originates.
244 /// 244 ///
245 /// <param name="item"></param> 245 /// <param name="item">Inventory item</param>
246 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns> 246 /// <param name="objlist">The scene objects</param>
247 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); 247 /// <param name="veclist">Relative offsets for each object</param>
248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index d49b24e..944c66b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 54
55 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); 56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
57
58 /// <summary>
59 /// Returns whether the transfer ID is being used for a terrain transfer.
60 /// </summary>
61 bool IsTerrainXfer(ulong xferID);
57 } 62 }
58} 63}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 659bde9..f384462 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -2301,6 +2302,85 @@ namespace OpenSim.Region.Framework.Scenes
2301 } 2302 }
2302 2303
2303 /// <summary> 2304 /// <summary>
2305 /// Returns the list of Scene Objects in an asset.
2306 /// </summary>
2307 /// <remarks>
2308 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2309 /// </remarks>
2310 /// <param name="assetData">Asset data</param>
2311 /// <param name="attachment">Whether the item is an attachment</param>
2312 /// <param name="objlist">The objects included in the asset</param>
2313 /// <param name="veclist">Relative positions of the objects</param>
2314 /// <param name="bbox">Bounding box of all the objects</param>
2315 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2316 /// to the centre of the root prim (relevant only when returning a single object)</param>
2317 /// <returns>true = returning a single object; false = multiple objects</returns>
2318 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2319 out Vector3 bbox, out float offsetHeight)
2320 {
2321 objlist = new List<SceneObjectGroup>();
2322 veclist = new List<Vector3>();
2323
2324 XmlDocument doc = new XmlDocument();
2325 string xmlData = Utils.BytesToString(assetData);
2326 doc.LoadXml(xmlData);
2327 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2328
2329 if (e == null || attachment) // Single
2330 {
2331 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2332
2333 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2334 g.RootPart.AttachOffset = g.AbsolutePosition;
2335 g.RootPart.AttachRotation = g.GroupRotation;
2336 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2337 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2338 g.RootPart.Shape.State = 0;
2339
2340 objlist.Add(g);
2341 veclist.Add(new Vector3(0, 0, 0));
2342 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2343 return true;
2344 }
2345 else
2346 {
2347 XmlElement coll = (XmlElement)e;
2348 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2349 float by = Convert.ToSingle(coll.GetAttribute("y"));
2350 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2351 bbox = new Vector3(bx, by, bz);
2352 offsetHeight = 0;
2353
2354 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2355 foreach (XmlNode n in groups)
2356 {
2357 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2358
2359 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2360 g.RootPart.AttachOffset = g.AbsolutePosition;
2361 g.RootPart.AttachRotation = g.GroupRotation;
2362 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2363 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2364 g.RootPart.Shape.State = 0;
2365
2366 objlist.Add(g);
2367
2368 XmlElement el = (XmlElement)n;
2369 string rawX = el.GetAttribute("offsetx");
2370 string rawY = el.GetAttribute("offsety");
2371 string rawZ = el.GetAttribute("offsetz");
2372
2373 float x = Convert.ToSingle(rawX);
2374 float y = Convert.ToSingle(rawY);
2375 float z = Convert.ToSingle(rawZ);
2376 veclist.Add(new Vector3(x, y, z));
2377 }
2378 }
2379
2380 return false;
2381 }
2382
2383 /// <summary>
2304 /// Event Handler Rez an object into a scene 2384 /// Event Handler Rez an object into a scene
2305 /// Calls the non-void event handler 2385 /// Calls the non-void event handler
2306 /// </summary> 2386 /// </summary>
@@ -2375,19 +2455,25 @@ namespace OpenSim.Region.Framework.Scenes
2375 /// will be used if it exists.</param> 2455 /// will be used if it exists.</param>
2376 /// <param name="vel">The velocity of the rezzed object.</param> 2456 /// <param name="vel">The velocity of the rezzed object.</param>
2377 /// <param name="param"></param> 2457 /// <param name="param"></param>
2378 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2458 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2379 public virtual SceneObjectGroup RezObject( 2459 public virtual List<SceneObjectGroup> RezObject(
2380 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2460 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2381 { 2461 {
2382 if (null == item) 2462 if (null == item)
2383 return null; 2463 return null;
2464
2465 List<SceneObjectGroup> objlist;
2466 List<Vector3> veclist;
2384 2467
2385 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2468 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2386 2469 if (!success)
2387 if (null == group)
2388 return null; 2470 return null;
2389 2471
2390 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2472 int totalPrims = 0;
2473 foreach (SceneObjectGroup group in objlist)
2474 totalPrims += group.PrimCount;
2475
2476 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2391 return null; 2477 return null;
2392 2478
2393 if (!Permissions.BypassPermissions()) 2479 if (!Permissions.BypassPermissions())
@@ -2396,23 +2482,28 @@ namespace OpenSim.Region.Framework.Scenes
2396 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2482 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2397 } 2483 }
2398 2484
2399 2485 for (int i = 0; i < objlist.Count; i++)
2400 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2401 { 2486 {
2402 group.RootPart.AttachedPos = group.AbsolutePosition; 2487 SceneObjectGroup group = objlist[i];
2403 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; 2488 Vector3 curpos = pos + veclist[i];
2489
2490 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2491 {
2492 group.RootPart.AttachedPos = group.AbsolutePosition;
2493 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2494 }
2495
2496 group.FromPartID = sourcePart.UUID;
2497 AddNewSceneObject(group, true, curpos, rot, vel);
2498
2499 // We can only call this after adding the scene object, since the scene object references the scene
2500 // to find out if scripts should be activated at all.
2501 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2502
2503 group.ScheduleGroupForFullUpdate();
2404 } 2504 }
2405 2505
2406 group.FromPartID = sourcePart.UUID; 2506 return objlist;
2407 AddNewSceneObject(group, true, pos, rot, vel);
2408
2409 // We can only call this after adding the scene object, since the scene object references the scene
2410 // to find out if scripts should be activated at all.
2411 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2412
2413 group.ScheduleGroupForFullUpdate();
2414
2415 return group;
2416 } 2507 }
2417 2508
2418 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2509 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 421cb08..46b2d2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 if (part.ParentGroup.RootPart.LocalId != part.LocalId) 252 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
253 return; 253 return;
254 254
255 bool isAttachment = false;
256
257 // This is wrong, wrong, wrong. Selection should not be 255 // This is wrong, wrong, wrong. Selection should not be
258 // handled by group, but by prim. Legacy cruft. 256 // handled by group, but by prim. Legacy cruft.
259 // TODO: Make selection flagging per prim! 257 // TODO: Make selection flagging per prim!
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes
262 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) 260 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
263 part.ParentGroup.IsSelected = false; 261 part.ParentGroup.IsSelected = false;
264 262
265 if (part.ParentGroup.IsAttachment) 263 part.ParentGroup.ScheduleGroupForFullUpdate();
266 isAttachment = true;
267 else
268 part.ParentGroup.ScheduleGroupForFullUpdate();
269 264
270 // If it's not an attachment, and we are allowed to move it, 265 // If it's not an attachment, and we are allowed to move it,
271 // then we might have done so. If we moved across a parcel 266 // then we might have done so. If we moved across a parcel
272 // boundary, we will need to recount prims on the parcels. 267 // boundary, we will need to recount prims on the parcels.
273 // For attachments, that makes no sense. 268 // For attachments, that makes no sense.
274 // 269 //
275 if (!isAttachment) 270 if (!part.ParentGroup.IsAttachment)
276 { 271 {
277 if (Permissions.CanEditObject( 272 if (Permissions.CanEditObject(
278 part.UUID, remoteClient.AgentId) 273 part.UUID, remoteClient.AgentId)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 66b42a1..f5cb84b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -3158,7 +3158,8 @@ namespace OpenSim.Region.Framework.Scenes
3158 return; 3158 return;
3159 3159
3160 // This was pulled from SceneViewer. Attachments always receive full updates. 3160 // This was pulled from SceneViewer. Attachments always receive full updates.
3161 // I could not verify if this is a requirement but this maintains existing behavior 3161 // This is needed because otherwise if only the root prim changes position, then
3162 // it looks as if the entire object has moved (including the other prims).
3162 if (ParentGroup.IsAttachment) 3163 if (ParentGroup.IsAttachment)
3163 { 3164 {
3164 ScheduleFullUpdate(); 3165 ScheduleFullUpdate();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3be0623..b4fc472 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -881,8 +881,8 @@ namespace OpenSim.Region.Framework.Scenes
881 881
882 return items; 882 return items;
883 } 883 }
884 884
885 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 885 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
886 { 886 {
887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
888 888
@@ -891,70 +891,79 @@ namespace OpenSim.Region.Framework.Scenes
891 m_log.WarnFormat( 891 m_log.WarnFormat(
892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
893 item.AssetID, item.Name, m_part.Name); 893 item.AssetID, item.Name, m_part.Name);
894 return null; 894 objlist = null;
895 veclist = null;
896 return false;
895 } 897 }
896 898
897 string xmlData = Utils.BytesToString(rezAsset.Data); 899 Vector3 bbox;
898 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 900 float offsetHeight;
899 901
900 group.RootPart.AttachPoint = group.RootPart.Shape.State; 902 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
901 group.RootPart.AttachOffset = group.AbsolutePosition;
902 group.RootPart.AttachRotation = group.GroupRotation;
903 903
904 group.ResetIDs(); 904 for (int i = 0; i < objlist.Count; i++)
905 {
906 SceneObjectGroup group = objlist[i];
905 907
906 SceneObjectPart rootPart = group.GetPart(group.UUID); 908 group.RootPart.AttachPoint = group.RootPart.Shape.State;
909 group.RootPart.AttachOffset = group.AbsolutePosition;
910 group.RootPart.AttachRotation = group.GroupRotation;
907 911
908 // Since renaming the item in the inventory does not affect the name stored 912 group.ResetIDs();
909 // in the serialization, transfer the correct name from the inventory to the
910 // object itself before we rez.
911 rootPart.Name = item.Name;
912 rootPart.Description = item.Description;
913 913
914 SceneObjectPart[] partList = group.Parts; 914 SceneObjectPart rootPart = group.GetPart(group.UUID);
915 915
916 group.SetGroup(m_part.GroupID, null); 916 // Since renaming the item in the inventory does not affect the name stored
917 // in the serialization, transfer the correct name from the inventory to the
918 // object itself before we rez.
919 rootPart.Name = item.Name;
920 rootPart.Description = item.Description;
917 921
918 // TODO: Remove magic number badness 922 SceneObjectPart[] partList = group.Parts;
919 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 923
920 { 924 group.SetGroup(m_part.GroupID, null);
921 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) 925
926 // TODO: Remove magic number badness
927 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
922 { 928 {
923 foreach (SceneObjectPart part in partList) 929 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
924 { 930 {
925 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 931 foreach (SceneObjectPart part in partList)
926 part.EveryoneMask = item.EveryonePermissions; 932 {
927 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) 933 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
928 part.NextOwnerMask = item.NextPermissions; 934 part.EveryoneMask = item.EveryonePermissions;
929 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 935 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
930 part.GroupMask = item.GroupPermissions; 936 part.NextOwnerMask = item.NextPermissions;
937 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
938 part.GroupMask = item.GroupPermissions;
939 }
940
941 group.ApplyNextOwnerPermissions();
931 } 942 }
932
933 group.ApplyNextOwnerPermissions();
934 } 943 }
935 }
936 944
937 foreach (SceneObjectPart part in partList) 945 foreach (SceneObjectPart part in partList)
938 {
939 // TODO: Remove magic number badness
940 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
941 { 946 {
942 part.LastOwnerID = part.OwnerID; 947 // TODO: Remove magic number badness
943 part.OwnerID = item.OwnerID; 948 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
944 part.Inventory.ChangeInventoryOwner(item.OwnerID); 949 {
950 part.LastOwnerID = part.OwnerID;
951 part.OwnerID = item.OwnerID;
952 part.Inventory.ChangeInventoryOwner(item.OwnerID);
953 }
954
955 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
956 part.EveryoneMask = item.EveryonePermissions;
957 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
958 part.NextOwnerMask = item.NextPermissions;
959 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
960 part.GroupMask = item.GroupPermissions;
945 } 961 }
946 962
947 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 963 rootPart.TrimPermissions();
948 part.EveryoneMask = item.EveryonePermissions;
949 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
950 part.NextOwnerMask = item.NextPermissions;
951 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
952 part.GroupMask = item.GroupPermissions;
953 } 964 }
954 965
955 rootPart.TrimPermissions(); 966 return true;
956
957 return group;
958 } 967 }
959 968
960 /// <summary> 969 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 8a734e1..d2a6828 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -39,6 +39,7 @@ using OpenSim.Framework.Communications;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using System.Text;
42using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; 43using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
43 44
44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 45namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
@@ -421,44 +422,75 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
421 string Subject = im.message.Substring(0, im.message.IndexOf('|')); 422 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
422 string Message = im.message.Substring(Subject.Length + 1); 423 string Message = im.message.Substring(Subject.Length + 1);
423 424
425 InventoryItemBase item = null;
426 bool hasAttachment = false;
427 UUID itemID = UUID.Zero; //Assignment to quiet compiler
428 UUID ownerID = UUID.Zero; //Assignment to quiet compiler
424 byte[] bucket; 429 byte[] bucket;
425 430
426 if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) 431 if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
427 {
428 bucket = new byte[19];
429 bucket[0] = 0; //dunno
430 bucket[1] = 0; //dunno
431 GroupID.ToBytes(bucket, 2);
432 bucket[18] = 0; //dunno
433 }
434 else
435 { 432 {
436 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); 433 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
437 binBucket = binBucket.Remove(0, 14).Trim(); 434 binBucket = binBucket.Remove(0, 14).Trim();
438 if (m_debugEnabled) 435
436 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
437 if (binBucketOSD is OSD)
439 { 438 {
440 m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); 439 OSDMap binBucketMap = (OSDMap)binBucketOSD;
440
441 itemID = binBucketMap["item_id"].AsUUID();
442 ownerID = binBucketMap["owner_id"].AsUUID();
441 443
442 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); 444 //Attempt to get the details of the attached item.
443 445 //If sender doesn't own the attachment, the item
444 foreach (string key in binBucketOSD.Keys) 446 //variable will be set to null and attachment will
447 //not be included with the group notice.
448 Scene scene = (Scene)remoteClient.Scene;
449 item = new InventoryItemBase(itemID, ownerID);
450 item = scene.InventoryService.GetItem(item);
451
452 if (item != null)
445 { 453 {
446 if (binBucketOSD.ContainsKey(key)) 454 //Got item details so include the attachment.
447 { 455 hasAttachment = true;
448 m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
449 }
450 } 456 }
451 } 457 }
452 458 else
453 // treat as if no attachment 459 {
460 m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
461 }
462 }
463
464 if (hasAttachment)
465 {
466 //Bucket contains information about attachment.
467 //
468 //Byte offset and description of bucket data:
469 //0: 1 byte indicating if attachment is present
470 //1: 1 byte indicating the type of attachment
471 //2: 16 bytes - Group UUID
472 //18: 16 bytes - UUID of the attachment owner
473 //34: 16 bytes - UUID of the attachment
474 //50: variable - Name of the attachment
475 //??: NUL byte to terminate the attachment name
476 byte[] name = Encoding.UTF8.GetBytes(item.Name);
477 bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name
478 bucket[0] = 1; //Has attachment flag
479 bucket[1] = (byte)item.InvType; //Type of Attachment
480 GroupID.ToBytes(bucket, 2);
481 ownerID.ToBytes(bucket, 18);
482 itemID.ToBytes(bucket, 34);
483 name.CopyTo(bucket, 50);
484 }
485 else
486 {
454 bucket = new byte[19]; 487 bucket = new byte[19];
455 bucket[0] = 0; //dunno 488 bucket[0] = 0; //Has attachment flag
456 bucket[1] = 0; //dunno 489 bucket[1] = 0; //Type of attachment
457 GroupID.ToBytes(bucket, 2); 490 GroupID.ToBytes(bucket, 2);
458 bucket[18] = 0; //dunno 491 bucket[18] = 0; //NUL terminate name of attachment
459 } 492 }
460 493
461
462 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); 494 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
463 if (OnNewGroupNotice != null) 495 if (OnNewGroupNotice != null)
464 { 496 {
@@ -483,7 +515,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
483 515
484 if (member.AcceptNotices) 516 if (member.AcceptNotices)
485 { 517 {
486 // Build notice IIM 518 // Build notice IM
487 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); 519 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
488 520
489 msg.toAgentID = member.AgentID.Guid; 521 msg.toAgentID = member.AgentID.Guid;
@@ -492,10 +524,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
492 } 524 }
493 } 525 }
494 } 526 }
495 527
528 if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
529 {
530 //Is bucket large enough to hold UUID of the attachment?
531 if (im.binaryBucket.Length < 16)
532 return;
533
534 UUID noticeID = new UUID(im.imSessionID);
535
536 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
537 if (notice != null)
538 {
539 UUID giver = new UUID(notice.BinaryBucket, 18);
540 UUID attachmentUUID = new UUID(notice.BinaryBucket, 34);
541
542 if (m_debugEnabled)
543 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
544
545 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
546 giver, attachmentUUID);
547
548 if (itemCopy == null)
549 {
550 remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
551 return;
552 }
553
554 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
555 }
556 }
557
496 // Interop, received special 210 code for ejecting a group member 558 // Interop, received special 210 code for ejecting a group member
497 // this only works within the comms servers domain, and won't work hypergrid 559 // this only works within the comms servers domain, and won't work hypergrid
498 // TODO:FIXME: Use a presense server of some kind to find out where the 560 // TODO:FIXME: Use a presence server of some kind to find out where the
499 // client actually is, and try contacting that region directly to notify them, 561 // client actually is, and try contacting that region directly to notify them,
500 // or provide the notification via xmlrpc update queue 562 // or provide the notification via xmlrpc update queue
501 if ((im.dialog == 210)) 563 if ((im.dialog == 210))
@@ -873,26 +935,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
873 935
874 if (data != null) 936 if (data != null)
875 { 937 {
876 GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); 938 GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
877
878 GridInstantMessage msg = new GridInstantMessage();
879 msg.imSessionID = UUID.Zero.Guid;
880 msg.fromAgentID = data.GroupID.Guid;
881 msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
882 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
883 msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
884 msg.message = data.noticeData.Subject + "|" + data.Message;
885 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
886 msg.fromGroup = true;
887 msg.offline = (byte)0;
888 msg.ParentEstateID = 0;
889 msg.Position = Vector3.Zero;
890 msg.RegionID = UUID.Zero.Guid;
891 msg.binaryBucket = data.BinaryBucket;
892 939
893 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); 940 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
894 } 941 }
895
896 } 942 }
897 943
898 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) 944 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
@@ -900,10 +946,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
900 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 946 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
901 947
902 GridInstantMessage msg = new GridInstantMessage(); 948 GridInstantMessage msg = new GridInstantMessage();
903 msg.imSessionID = UUID.Zero.Guid; 949 byte[] bucket;
950
951 msg.imSessionID = groupNoticeID.Guid;
904 msg.toAgentID = agentID.Guid; 952 msg.toAgentID = agentID.Guid;
905 msg.dialog = dialog; 953 msg.dialog = dialog;
906 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
907 msg.fromGroup = true; 954 msg.fromGroup = true;
908 msg.offline = (byte)1; // Allow this message to be stored for offline use 955 msg.offline = (byte)1; // Allow this message to be stored for offline use
909 msg.ParentEstateID = 0; 956 msg.ParentEstateID = 0;
@@ -917,13 +964,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
917 msg.timestamp = info.noticeData.Timestamp; 964 msg.timestamp = info.noticeData.Timestamp;
918 msg.fromAgentName = info.noticeData.FromName; 965 msg.fromAgentName = info.noticeData.FromName;
919 msg.message = info.noticeData.Subject + "|" + info.Message; 966 msg.message = info.noticeData.Subject + "|" + info.Message;
920 msg.binaryBucket = info.BinaryBucket; 967
968 if (info.BinaryBucket[0] > 0)
969 {
970 //32 is due to not needing space for two of the UUIDs.
971 //(Don't need UUID of attachment or its owner in IM)
972 //50 offset gets us to start of attachment name.
973 //We are skipping the attachment flag, type, and
974 //the three UUID fields at the start of the bucket.
975 bucket = new byte[info.BinaryBucket.Length-32];
976 bucket[0] = 1; //Has attachment
977 bucket[1] = info.BinaryBucket[1];
978 Array.Copy(info.BinaryBucket, 50,
979 bucket, 18, info.BinaryBucket.Length-50);
980 }
981 else
982 {
983 bucket = new byte[19];
984 bucket[0] = 0; //No attachment
985 bucket[1] = 0; //Attachment type
986 bucket[18] = 0; //NUL terminate name
987 }
988
989 info.GroupID.ToBytes(bucket, 2);
990 msg.binaryBucket = bucket;
921 } 991 }
922 else 992 else
923 { 993 {
924 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); 994 if (m_debugEnabled)
995 m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID);
996
925 msg.fromAgentID = UUID.Zero.Guid; 997 msg.fromAgentID = UUID.Zero.Guid;
926 msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; 998 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
927 msg.fromAgentName = string.Empty; 999 msg.fromAgentName = string.Empty;
928 msg.message = string.Empty; 1000 msg.message = string.Empty;
929 msg.binaryBucket = new byte[0]; 1001 msg.binaryBucket = new byte[0];
@@ -1047,7 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1047 // Message to ejector 1119 // Message to ejector
1048 // Interop, received special 210 code for ejecting a group member 1120 // Interop, received special 210 code for ejecting a group member
1049 // this only works within the comms servers domain, and won't work hypergrid 1121 // this only works within the comms servers domain, and won't work hypergrid
1050 // TODO:FIXME: Use a presense server of some kind to find out where the 1122 // TODO:FIXME: Use a presence server of some kind to find out where the
1051 // client actually is, and try contacting that region directly to notify them, 1123 // client actually is, and try contacting that region directly to notify them,
1052 // or provide the notification via xmlrpc update queue 1124 // or provide the notification via xmlrpc update queue
1053 1125
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index f0d17d3..7b98f9d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -1125,7 +1125,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1125 { 1125 {
1126 // If body is already heigher, use its height as target height 1126 // If body is already heigher, use its height as target height
1127 if (VehiclePosition.Z > m_VhoverTargetHeight) 1127 if (VehiclePosition.Z > m_VhoverTargetHeight)
1128 {
1128 m_VhoverTargetHeight = VehiclePosition.Z; 1129 m_VhoverTargetHeight = VehiclePosition.Z;
1130
1131 // A 'misfeature' of this flag is that if the vehicle is above it's hover height,
1132 // the vehicle's buoyancy goes away. This is an SL bug that got used by so many
1133 // scripts that it could not be changed.
1134 // So, if above the height, reapply gravity if buoyancy had it turned off.
1135 if (m_VehicleBuoyancy != 0)
1136 {
1137 Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass;
1138 VehicleAddForce(appliedGravity);
1139 }
1140 }
1129 } 1141 }
1130 1142
1131 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1143 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index c4807c4..c016eed 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -354,6 +354,8 @@ public sealed class BSTerrainManager : IDisposable
354 // Return a new position that is over known terrain if the position is outside our terrain. 354 // Return a new position that is over known terrain if the position is outside our terrain.
355 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) 355 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos)
356 { 356 {
357 float edgeEpsilon = 0.1f;
358
357 Vector3 ret = pPos; 359 Vector3 ret = pPos;
358 360
359 // First, base addresses are never negative so correct for that possible problem. 361 // First, base addresses are never negative so correct for that possible problem.
@@ -378,10 +380,19 @@ public sealed class BSTerrainManager : IDisposable
378 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region. 380 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
379 381
380 // Must be off the top of a region. Find an adjacent region to move into. 382 // Must be off the top of a region. Find an adjacent region to move into.
383 // The returned terrain is always 'lower'. That is, closer to <0,0>.
381 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); 384 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
382 385
383 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X)); 386 if (adjacentTerrainBase.X < terrainBaseXYZ.X)
384 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y)); 387 {
388 // moving down into a new region in the X dimension. New position will be the max in the new base.
389 ret.X = adjacentTerrainBase.X + DefaultRegionSize.X - edgeEpsilon;
390 }
391 if (adjacentTerrainBase.Y < terrainBaseXYZ.Y)
392 {
393 // moving down into a new region in the X dimension. New position will be the max in the new base.
394 ret.Y = adjacentTerrainBase.Y + DefaultRegionSize.Y - edgeEpsilon;
395 }
385 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", 396 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
386 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); 397 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
387 398
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8892b69..89f4706 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3247,46 +3247,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3247 // need the magnitude later 3247 // need the magnitude later
3248 // float velmag = (float)Util.GetMagnitude(llvel); 3248 // float velmag = (float)Util.GetMagnitude(llvel);
3249 3249
3250 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 3250 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
3251 3251
3252 // If either of these are null, then there was an unknown error. 3252 // If either of these are null, then there was an unknown error.
3253 if (new_group == null) 3253 if (new_groups == null)
3254 return; 3254 return;
3255 3255
3256 // objects rezzed with this method are die_at_edge by default. 3256 foreach (SceneObjectGroup group in new_groups)
3257 new_group.RootPart.SetDieAtEdge(true); 3257 {
3258 3258 // objects rezzed with this method are die_at_edge by default.
3259 new_group.ResumeScripts(); 3259 group.RootPart.SetDieAtEdge(true);
3260 3260
3261 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3261 group.ResumeScripts();
3262 "object_rez", new Object[] {
3263 new LSL_String(
3264 new_group.RootPart.UUID.ToString()) },
3265 new DetectParams[0]));
3266 3262
3267 // do recoil 3263 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3268 SceneObjectGroup hostgrp = m_host.ParentGroup; 3264 "object_rez", new Object[] {
3269 if (hostgrp == null) 3265 new LSL_String(
3270 return; 3266 group.RootPart.UUID.ToString()) },
3267 new DetectParams[0]));
3271 3268
3272 if (hostgrp.IsAttachment) // don't recoil avatars 3269 float groupmass = group.GetMass();
3273 return;
3274 3270
3275 PhysicsActor pa = new_group.RootPart.PhysActor; 3271 PhysicsActor pa = group.RootPart.PhysActor;
3276 3272
3277 //Recoil. 3273 //Recoil.
3278 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3274 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3279 {
3280 float groupmass = new_group.GetMass();
3281 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3282 if (recoil != Vector3.Zero)
3283 { 3275 {
3284 llApplyImpulse(recoil, 0); 3276 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3277 if (recoil != Vector3.Zero)
3278 {
3279 llApplyImpulse(recoil, 0);
3280 }
3285 } 3281 }
3282 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3286 } 3283 }
3287 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3288 return; 3284 return;
3289
3290 }); 3285 });
3291 3286
3292 //ScriptSleep((int)((groupmass * velmag) / 10)); 3287 //ScriptSleep((int)((groupmass * velmag) / 10));