diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 6286689f70..2498705a82 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1660,19 +1660,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } // Offset the positions for the new region across the border - // NOT here + Vector3 oldGroupPosition = grp.RootPart.GroupPosition; // If we fail to cross the border, then reset the position of the scene object on that border. uint x = 0, y = 0; Utils.LongToUInts(newRegionHandle, out x, out y); GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); - Vector3 oldGroupPosition = grp.RootPart.GroupPosition; - if (destination != null) { - grp.RootPart.GroupPosition = pos; // only change this if we think there is anywhere to go - if (CrossPrimGroupIntoNewRegion(destination, grp, silent)) + if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) return; // we did it } @@ -1701,7 +1698,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// true if the crossing itself was successful, false on failure /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region /// - protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, SceneObjectGroup grp, bool silent) + protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) { //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); @@ -1726,7 +1723,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer //if (m_interregionCommsOut != null) // successYN = m_interregionCommsOut.SendCreateObject(newRegionHandle, grp, true); if (m_aScene.SimulationService != null) - successYN = m_aScene.SimulationService.CreateObject(destination, grp, true); + successYN = m_aScene.SimulationService.CreateObject(destination, newPosition, grp, true); if (successYN) { @@ -1785,7 +1782,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer gobj.IsAttachment = false; //gobj.RootPart.LastOwnerID = gobj.GetFromAssetID(); m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", gobj.UUID, destination.RegionName); - CrossPrimGroupIntoNewRegion(destination, gobj, silent); + CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, gobj, silent); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index faa1def65d..6e75692942 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -328,7 +328,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation * Object-related communications */ - public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) + public bool CreateObject(GridRegion destination, Vector3 newPosition, ISceneObject sog, bool isLocalCall) { if (destination == null) return false; @@ -343,12 +343,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation // We need to make a local copy of the object ISceneObject sogClone = sog.CloneForNewScene(); sogClone.SetState(sog.GetStateSnapshot(), s); - return s.IncomingCreateObject(sogClone); + return s.IncomingCreateObject(newPosition, sogClone); } else { // Use the object as it came through the wire - return s.IncomingCreateObject(sog); + return s.IncomingCreateObject(newPosition, sog); } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 391b1a1eca..4b70692e78 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -297,13 +297,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation * Object-related communications */ - public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) + public bool CreateObject(GridRegion destination, Vector3 newPosition, ISceneObject sog, bool isLocalCall) { if (destination == null) return false; // Try local first - if (m_localBackend.CreateObject(destination, sog, isLocalCall)) + if (m_localBackend.CreateObject(destination, newPosition, sog, isLocalCall)) { //m_log.Debug("[REST COMMS]: LocalBackEnd SendCreateObject succeeded"); return true; @@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation // else do the remote thing if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) - return m_remoteConnector.CreateObject(destination, sog, isLocalCall); + return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); return false; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a7cca4424a..b7162da5b1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2403,7 +2403,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public bool IncomingCreateObject(ISceneObject sog) + public bool IncomingCreateObject(Vector3 newPosition, ISceneObject sog) { //m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition, // ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment); @@ -2419,6 +2419,9 @@ namespace OpenSim.Region.Framework.Scenes return false; } + if (newPosition != Vector3.Zero) + newObject.RootPart.GroupPosition = newPosition; + if (!AddSceneObject(newObject)) { m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName); @@ -4431,10 +4434,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void ForEachRootScenePresence(Action action) { - if (m_sceneGraph != null) - { - m_sceneGraph.ForEachAvatar(action); - } + m_sceneGraph.ForEachAvatar(action); } /// @@ -4443,10 +4443,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void ForEachScenePresence(Action action) { - if (m_sceneGraph != null) - { - m_sceneGraph.ForEachScenePresence(action); - } + m_sceneGraph.ForEachScenePresence(action); } /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ec8716ba6e..a3839c2501 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3297,7 +3297,7 @@ namespace OpenSim.Region.Framework.Scenes ((SceneObjectGroup)so).LocalId = 0; ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); so.SetState(cAgent.AttachmentObjectStates[i++], m_scene); - m_scene.IncomingCreateObject(so); + m_scene.IncomingCreateObject(Vector3.Zero, so); } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 84792c0b1a..d0430f476e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2177,6 +2177,54 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return real_vec; } + public LSL_Integer llSetRegionPos(LSL_Vector pos) + { + return new LSL_Integer(SetRegionPos(m_host, pos)); + } + + protected int SetRegionPos(SceneObjectPart part, LSL_Vector targetPos) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return 0; + + SceneObjectGroup grp = part.ParentGroup; + + if (grp.IsAttachment) + return 0; + + if (grp.RootPart.PhysActor != null && grp.RootPart.PhysActor.IsPhysical) + return 0; + + if (targetPos.x < -10.0f || targetPos.x >= (float)Constants.RegionSize || targetPos.y < -10.0f || targetPos.y >= (float)Constants.RegionSize || targetPos.z < 0 || targetPos.z >= 4096.0f) + return 0; + + float constrainedX = (float)targetPos.x; + float constrainedY = (float)targetPos.y; + + if (constrainedX < 0.0f) + constrainedX = 0.0f; + if (constrainedY < 0.0f) + constrainedY = 0.0f; + if (constrainedX >= (float)Constants.RegionSize) + constrainedX = (float)Constants.RegionSize - 0.1f; + if (constrainedY >= (float)Constants.RegionSize) + constrainedY = (float)Constants.RegionSize -0.1f; + + float ground = World.GetGroundHeight(constrainedX, constrainedY); + + if (targetPos.z < ground) + targetPos.z = ground; + + Vector3 dest = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z); + + if (!World.Permissions.CanObjectEntry(grp.UUID, false, dest)) + return 0; + + grp.UpdateGroupPosition(dest); + + return 1; + } + protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) @@ -2185,11 +2233,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector currentPos = GetPartLocalPos(part); LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos); + if (part.ParentGroup.RootPart == part) { SceneObjectGroup parent = part.ParentGroup; + Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); + if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest)) + return; Util.FireAndForget(delegate(object x) { - parent.UpdateGroupPosition(new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z)); + parent.UpdateGroupPosition(dest); }); } else @@ -5709,7 +5761,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetRegionAgentCount() { m_host.AddScriptLPS(1); - return new LSL_Integer(World.GetRootAgentCount()); + + int count = 0; + World.ForEachRootScenePresence(delegate(ScenePresence sp) { + count++; + }); + + return new LSL_Integer(count); } public LSL_Vector llGetRegionCorner() diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index f2d4399fd7..967979804c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -346,6 +346,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetParcelMusicURL(string url); void llSetPayPrice(int price, LSL_List quick_pay_buttons); void llSetPos(LSL_Vector pos); + LSL_Integer llSetRegionPos(LSL_Vector pos); LSL_Integer llSetPrimMediaParams(int face, LSL_List rules); void llSetPrimitiveParams(LSL_List rules); void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index fad6c350b4..dcaa3b4747 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -1580,6 +1580,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llSetPos(pos); } + public LSL_Integer llSetRegionPos(LSL_Vector pos) + { + return m_LSL_Functions.llSetRegionPos(pos); + } + public void llSetPrimitiveParams(LSL_List rules) { m_LSL_Functions.llSetPrimitiveParams(rules); diff --git a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs index 984b843401..f0d8f69827 100644 --- a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs @@ -136,6 +136,8 @@ namespace OpenSim.Server.Handlers.Simulation int x = 0, y = 0; UUID uuid = UUID.Zero; string regionname = string.Empty; + Vector3 newPosition = Vector3.Zero; + if (args.ContainsKey("destination_x") && args["destination_x"] != null) Int32.TryParse(args["destination_x"].AsString(), out x); if (args.ContainsKey("destination_y") && args["destination_y"] != null) @@ -144,6 +146,8 @@ namespace OpenSim.Server.Handlers.Simulation UUID.TryParse(args["destination_uuid"].AsString(), out uuid); if (args.ContainsKey("destination_name") && args["destination_name"] != null) regionname = args["destination_name"].ToString(); + if (args.ContainsKey("new_position") && args["new_position"] != null) + Vector3.TryParse(args["new_position"], out newPosition); GridRegion destination = new GridRegion(); destination.RegionID = uuid; @@ -199,7 +203,7 @@ namespace OpenSim.Server.Handlers.Simulation try { // This is the meaning of POST object - result = CreateObject(destination, sog); + result = CreateObject(destination, newPosition, sog); } catch (Exception e) { @@ -211,9 +215,9 @@ namespace OpenSim.Server.Handlers.Simulation } // subclasses can override this - protected virtual bool CreateObject(GridRegion destination, ISceneObject sog) + protected virtual bool CreateObject(GridRegion destination, Vector3 newPosition, ISceneObject sog) { - return m_SimulationService.CreateObject(destination, sog, false); + return m_SimulationService.CreateObject(destination, newPosition, sog, false); } protected virtual void DoObjectPut(Hashtable request, Hashtable responsedata, UUID regionID) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 4132ec7c3e..5037543024 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -420,7 +420,7 @@ namespace OpenSim.Services.Connectors.Simulation /// /// /// - public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) + public bool CreateObject(GridRegion destination, Vector3 newPosition, ISceneObject sog, bool isLocalCall) { // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateObject start"); @@ -433,6 +433,7 @@ namespace OpenSim.Services.Connectors.Simulation args["sog"] = OSD.FromString(sog.ToXml2()); args["extra"] = OSD.FromString(sog.ExtraToXmlString()); args["modified"] = OSD.FromBoolean(sog.HasGroupChanged); + args["new_position"] = newPosition.ToString(); string state = sog.GetStateSnapshot(); if (state.Length > 0) diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index ae6bd723b3..7940256ab5 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -106,7 +106,7 @@ namespace OpenSim.Services.Interfaces /// /// /// - bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall); + bool CreateObject(GridRegion destination, Vector3 newPosition, ISceneObject sog, bool isLocalCall); /// /// Create an object from the user's inventory in the destination region.