diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 1aecce56f4..558f108c6c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1326,12 +1326,23 @@ namespace OpenSim.Region.Framework.Scenes /// /// Update the position of the given group. /// - /// + /// /// /// - public void UpdatePrimGroupPosition(uint localID, Vector3 pos, IClientAPI remoteClient) + public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient) { - SceneObjectGroup group = GetGroupByPrim(localID); + UpdatePrimGroupPosition(localId, pos, remoteClient.AgentId); + } + + /// + /// Update the position of the given group. + /// + /// + /// + /// + public void UpdatePrimGroupPosition(uint localId, Vector3 pos, UUID updatingAgentId) + { + SceneObjectGroup group = GetGroupByPrim(localId); if (group != null) { @@ -1342,7 +1353,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) + if (m_parentScene.Permissions.CanMoveObject(group.UUID, updatingAgentId) && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos)) { group.UpdateGroupPosition(pos); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs new file mode 100644 index 0000000000..43ac558bea --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs @@ -0,0 +1,161 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Framework.EntityTransfer; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Region.CoreModules.World.Land; +using OpenSim.Region.OptionalModules; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + public class SceneObjectCrossingTests : OpenSimTestCase + { + [TestFixtureSetUp] + public void FixtureInit() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + + /// + /// Test cross with no prim limit module. + /// + [Test] + public void TestCrossOnSameSimulator() + { + TestHelpers.InMethod(); + TestHelpers.EnableLogging(); + + UUID userId = TestHelpers.ParseTail(0x1); + int sceneObjectIdTail = 0x2; + + EntityTransferModule etmA = new EntityTransferModule(); + EntityTransferModule etmB = new EntityTransferModule(); + LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); + + IConfigSource config = new IniConfigSource(); + IConfig modulesConfig = config.AddConfig("Modules"); + modulesConfig.Set("EntityTransferModule", etmA.Name); + modulesConfig.Set("SimulationServices", lscm.Name); +// IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); + + SceneHelpers sh = new SceneHelpers(); + TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); + TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); + + SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); + SceneHelpers.SetupSceneModules(sceneA, config, etmA); + SceneHelpers.SetupSceneModules(sceneB, config, etmB); + + SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); + UUID so1Id = so1.UUID; + so1.AbsolutePosition = new Vector3(128, 10, 20); + + // Cross with a negative value + so1.AbsolutePosition = new Vector3(128, -10, 20); + + Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id)); + Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id)); + } + + /// + /// Test cross with no prim limit module. + /// + /// + /// XXX: This test may be better off in a specific PrimLimitsModuleTest class in optional module tests in the + /// future (though it is configured as active by default, so not really optional). + /// + [Test] + public void TestCrossOnSameSimulatorPrimLimitsOkay() + { + TestHelpers.InMethod(); + TestHelpers.EnableLogging(); + + UUID userId = TestHelpers.ParseTail(0x1); + int sceneObjectIdTail = 0x2; + + EntityTransferModule etmA = new EntityTransferModule(); + EntityTransferModule etmB = new EntityTransferModule(); + LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); + LandManagementModule lmmA = new LandManagementModule(); + LandManagementModule lmmB = new LandManagementModule(); + + IConfigSource config = new IniConfigSource(); + IConfig modulesConfig = config.AddConfig("Modules"); + modulesConfig.Set("EntityTransferModule", etmA.Name); + modulesConfig.Set("SimulationServices", lscm.Name); + + // Remove? +// IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); + + IConfig permissionsConfig = config.AddConfig("Permissions"); + permissionsConfig.Set("permissionmodules", "PrimLimitsModule"); + + SceneHelpers sh = new SceneHelpers(); + TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); + TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); + + SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); + SceneHelpers.SetupSceneModules( + sceneA, config, etmA, lmmA, new PrimLimitsModule(), new PrimCountModule()); + SceneHelpers.SetupSceneModules( + sceneB, config, etmB, lmmB, new PrimLimitsModule(), new PrimCountModule()); + + // We must set up the parcel for this to work. Normally this is taken care of by OpenSimulator startup + // code which is not yet easily invoked by tests. + lmmA.EventManagerOnNoLandDataFromStorage(); + lmmB.EventManagerOnNoLandDataFromStorage(); + + SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); + UUID so1Id = so1.UUID; + so1.AbsolutePosition = new Vector3(128, 10, 20); + + // Cross with a negative value. We must make this call rather than setting AbsolutePosition directly + // because only this will execute permission checks in the source region. + sceneA.SceneGraph.UpdatePrimGroupPosition(so1.LocalId, new Vector3(128, -10, 20), userId); + + Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id)); + Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs index 8b4d231eed..18cec6c30a 100644 --- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs +++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs @@ -58,8 +58,6 @@ namespace OpenSim.Region.OptionalModules public void Initialise(IConfigSource config) { - //IConfig myConfig = config.Configs["Startup"]; - string permissionModules = Util.GetConfigVarFromSections(config, "permissionmodules", new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule"); @@ -129,6 +127,11 @@ namespace OpenSim.Region.OptionalModules ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); + // newParcel will be null only if it outside of our current region. If this is the case, then the + // receiving permissions will perform the check. + if (newParcel == null) + return true; + int usedPrims = newParcel.PrimCounts.Total; int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 584ca17141..345ca8a447 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -595,6 +595,32 @@ namespace OpenSim.Tests.Common return so; } + + /// + /// Add a test object + /// + /// + /// + /// The number of parts that should be in the scene object + /// + /// + /// + /// The prefix to be given to part names. This will be suffixed with "Part" + /// (e.g. mynamePart1 for the root part) + /// + /// + /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" + /// will be given to the root part, and incremented for each part thereafter. + /// + /// + public static SceneObjectGroup AddSceneObject(Scene scene, int parts, UUID ownerId, string partNamePrefix, int uuidTail) + { + SceneObjectGroup so = CreateSceneObject(parts, ownerId, partNamePrefix, uuidTail); + + scene.AddNewSceneObject(so, false); + + return so; + } /// /// Create a scene object part.