aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorDiva Canto2012-11-27 14:43:01 -0800
committerDiva Canto2012-11-27 14:43:01 -0800
commita82f699f4348ea1ab139ab338973c9cee04df712 (patch)
treed1bf4948670e1d207fe4f6c60f6b7771e1625839 /OpenSim
parentPrevent the core Groups module from being enabled when its name doesn't match... (diff)
parentBulletSim: reorganize linear movement routine into separate subroutines enabl... (diff)
downloadopensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.zip
opensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.tar.gz
opensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.tar.bz2
opensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to '')
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs2
-rw-r--r--OpenSim/Data/IXGroupData.cs71
-rw-r--r--OpenSim/Data/Null/NullGenericDataHandler.cs67
-rw-r--r--OpenSim/Data/Null/NullXGroupData.cs90
-rw-r--r--OpenSim/Data/Tests/AssetTests.cs2
-rw-r--r--OpenSim/Data/Tests/BasicDataServiceTest.cs7
-rw-r--r--OpenSim/Data/Tests/PropertyCompareConstraint.cs3
-rw-r--r--OpenSim/Data/Tests/PropertyScrambler.cs3
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs31
-rwxr-xr-xOpenSim/Framework/Console/ConsoleBase.cs10
-rw-r--r--OpenSim/Framework/Console/MockConsole.cs7
-rw-r--r--OpenSim/Framework/ICommandConsole.cs5
-rw-r--r--OpenSim/Framework/IConsole.cs2
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs5
-rw-r--r--OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs2
-rw-r--r--OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs2
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs466
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs60
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs677
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs3
-rw-r--r--OpenSim/Framework/Servers/Tests/VersionInfoTests.cs3
-rw-r--r--OpenSim/Framework/Tests/AgentCircuitDataTest.cs5
-rw-r--r--OpenSim/Framework/Tests/AnimationTests.cs2
-rw-r--r--OpenSim/Framework/Tests/AssetBaseTest.cs3
-rw-r--r--OpenSim/Framework/Tests/CacheTests.cs3
-rw-r--r--OpenSim/Framework/Tests/LocationTest.cs3
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs3
-rw-r--r--OpenSim/Framework/Tests/PrimeNumberHelperTests.cs3
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs2
-rw-r--r--OpenSim/Framework/Util.cs16
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs205
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs78
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs137
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs113
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs89
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs317
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs128
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs53
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs83
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs15
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs127
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs39
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs579
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs191
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs273
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs9
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs120
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs80
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs75
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs421
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs170
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs339
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs262
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs220
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs2
-rw-r--r--OpenSim/Server/Base/HttpServerBase.cs2
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs177
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs15
-rw-r--r--OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs110
-rw-r--r--OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs77
-rw-r--r--OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs25
-rw-r--r--OpenSim/Tests/ConfigurationLoaderTest.cs3
-rw-r--r--OpenSim/Tests/Performance/NPCPerformanceTests.cs2
-rw-r--r--OpenSim/Tests/Performance/ObjectPerformanceTests.cs2
-rw-r--r--OpenSim/Tests/Performance/ScriptPerformanceTests.cs2
120 files changed, 3739 insertions, 2727 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
index 761e4e7..d4d6d10 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common.Mock;
42namespace OpenSim.Capabilities.Handlers.GetTexture.Tests 42namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class GetTextureHandlerTests 45 public class GetTextureHandlerTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestTextureNotFound() 48 public void TestTextureNotFound()
diff --git a/OpenSim/Data/IXGroupData.cs b/OpenSim/Data/IXGroupData.cs
new file mode 100644
index 0000000..2965e8c
--- /dev/null
+++ b/OpenSim/Data/IXGroupData.cs
@@ -0,0 +1,71 @@
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 OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Data
34{
35 public class XGroup
36 {
37 public UUID groupID;
38 public UUID ownerRoleID;
39 public string name;
40 public string charter;
41 public bool showInList;
42 public UUID insigniaID;
43 public int membershipFee;
44 public bool openEnrollment;
45 public bool allowPublish;
46 public bool maturePublish;
47 public UUID founderID;
48 public ulong everyonePowers;
49 public ulong ownersPowers;
50
51 public XGroup Clone()
52 {
53 return (XGroup)MemberwiseClone();
54 }
55 }
56
57 /// <summary>
58 /// Early stub interface for groups data, not final.
59 /// </summary>
60 /// <remarks>
61 /// Currently in-use only for regression test purposes. Needs to be filled out over time.
62 /// </remarks>
63 public interface IXGroupData
64 {
65 bool StoreGroup(XGroup group);
66 XGroup[] GetGroups(string field, string val);
67 XGroup[] GetGroups(string[] fields, string[] vals);
68 bool DeleteGroups(string field, string val);
69 bool DeleteGroups(string[] fields, string[] vals);
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Data/Null/NullGenericDataHandler.cs b/OpenSim/Data/Null/NullGenericDataHandler.cs
new file mode 100644
index 0000000..dd9d190
--- /dev/null
+++ b/OpenSim/Data/Null/NullGenericDataHandler.cs
@@ -0,0 +1,67 @@
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.Linq;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Data;
36
37namespace OpenSim.Data.Null
38{
39 /// <summary>
40 /// Not a proper generic data handler yet - probably needs to actually store the data as well instead of relying
41 /// on descendent classes
42 /// </summary>
43 public class NullGenericDataHandler
44 {
45 protected List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
46 {
47 List<T> entities = inputEntities;
48
49 for (int i = 0; i < fields.Length; i++)
50 {
51 entities
52 = entities.Where(
53 e =>
54 {
55 FieldInfo fi = typeof(T).GetField(fields[i]);
56 if (fi == null)
57 throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
58
59 return fi.GetValue(e).ToString() == vals[i];
60 }
61 ).ToList();
62 }
63
64 return entities;
65 }
66 }
67} \ No newline at end of file
diff --git a/OpenSim/Data/Null/NullXGroupData.cs b/OpenSim/Data/Null/NullXGroupData.cs
new file mode 100644
index 0000000..7a86b9f
--- /dev/null
+++ b/OpenSim/Data/Null/NullXGroupData.cs
@@ -0,0 +1,90 @@
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;
30using System.Collections.Generic;
31using System.Linq;
32using System.Reflection;
33using System.Threading;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Data;
38
39namespace OpenSim.Data.Null
40{
41 public class NullXGroupData : NullGenericDataHandler, IXGroupData
42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private Dictionary<UUID, XGroup> m_groups = new Dictionary<UUID, XGroup>();
46
47 public NullXGroupData(string connectionString, string realm) {}
48
49 public bool StoreGroup(XGroup group)
50 {
51 lock (m_groups)
52 {
53 m_groups[group.groupID] = group.Clone();
54 }
55
56 return true;
57 }
58
59 public XGroup[] GetGroups(string field, string val)
60 {
61 return GetGroups(new string[] { field }, new string[] { val });
62 }
63
64 public XGroup[] GetGroups(string[] fields, string[] vals)
65 {
66 lock (m_groups)
67 {
68 List<XGroup> origGroups = Get<XGroup>(fields, vals, m_groups.Values.ToList());
69
70 return origGroups.Select(g => g.Clone()).ToArray();
71 }
72 }
73
74 public bool DeleteGroups(string field, string val)
75 {
76 return DeleteGroups(new string[] { field }, new string[] { val });
77 }
78
79 public bool DeleteGroups(string[] fields, string[] vals)
80 {
81 lock (m_groups)
82 {
83 XGroup[] groupsToDelete = GetGroups(fields, vals);
84 Array.ForEach(groupsToDelete, g => m_groups.Remove(g.groupID));
85 }
86
87 return true;
88 }
89 }
90} \ No newline at end of file
diff --git a/OpenSim/Data/Tests/AssetTests.cs b/OpenSim/Data/Tests/AssetTests.cs
index 1174e2f..8cb2ee0 100644
--- a/OpenSim/Data/Tests/AssetTests.cs
+++ b/OpenSim/Data/Tests/AssetTests.cs
@@ -49,7 +49,7 @@ using OpenSim.Data.SQLite;
49namespace OpenSim.Data.Tests 49namespace OpenSim.Data.Tests
50{ 50{
51 [TestFixture(Description = "Asset store tests (SQLite)")] 51 [TestFixture(Description = "Asset store tests (SQLite)")]
52 public class SQLiteAssetTests : AssetTests<SqliteConnection, SQLiteAssetData> 52 public class SQLiteAssetTests : AssetTests<SqliteConnection, SQLiteAssetData>
53 { 53 {
54 } 54 }
55 55
diff --git a/OpenSim/Data/Tests/BasicDataServiceTest.cs b/OpenSim/Data/Tests/BasicDataServiceTest.cs
index 7d85f0c..69b79bf 100644
--- a/OpenSim/Data/Tests/BasicDataServiceTest.cs
+++ b/OpenSim/Data/Tests/BasicDataServiceTest.cs
@@ -33,6 +33,7 @@ using NUnit.Framework;
33using NUnit.Framework.Constraints; 33using NUnit.Framework.Constraints;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Tests.Common;
36using log4net; 37using log4net;
37using System.Data; 38using System.Data;
38using System.Data.Common; 39using System.Data.Common;
@@ -43,6 +44,12 @@ namespace OpenSim.Data.Tests
43 /// <summary>This is a base class for testing any Data service for any DBMS. 44 /// <summary>This is a base class for testing any Data service for any DBMS.
44 /// Requires NUnit 2.5 or better (to support the generics). 45 /// Requires NUnit 2.5 or better (to support the generics).
45 /// </summary> 46 /// </summary>
47 /// <remarks>
48 /// FIXME: Should extend OpenSimTestCase but compile on mono 2.4.3 currently fails with
49 /// AssetTests`2 : System.MemberAccessException : Cannot create an instance of OpenSim.Data.Tests.AssetTests`2[TConn,TAssetData] because Type.ContainsGenericParameters is true.
50 /// and similar on EstateTests, InventoryTests and RegionTests.
51 /// Runs fine with mono 2.10.8.1, so easiest thing is to wait until min Mono version uplifts.
52 /// </remarks>
46 /// <typeparam name="TConn"></typeparam> 53 /// <typeparam name="TConn"></typeparam>
47 /// <typeparam name="TService"></typeparam> 54 /// <typeparam name="TService"></typeparam>
48 public class BasicDataServiceTest<TConn, TService> 55 public class BasicDataServiceTest<TConn, TService>
diff --git a/OpenSim/Data/Tests/PropertyCompareConstraint.cs b/OpenSim/Data/Tests/PropertyCompareConstraint.cs
index 6c79bda..b99525a 100644
--- a/OpenSim/Data/Tests/PropertyCompareConstraint.cs
+++ b/OpenSim/Data/Tests/PropertyCompareConstraint.cs
@@ -36,6 +36,7 @@ using NUnit.Framework;
36using NUnit.Framework.Constraints; 36using NUnit.Framework.Constraints;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Tests.Common;
39 40
40namespace OpenSim.Data.Tests 41namespace OpenSim.Data.Tests
41{ 42{
@@ -254,7 +255,7 @@ namespace OpenSim.Data.Tests
254 } 255 }
255 256
256 [TestFixture] 257 [TestFixture]
257 public class PropertyCompareConstraintTest 258 public class PropertyCompareConstraintTest : OpenSimTestCase
258 { 259 {
259 public class HasInt 260 public class HasInt
260 { 261 {
diff --git a/OpenSim/Data/Tests/PropertyScrambler.cs b/OpenSim/Data/Tests/PropertyScrambler.cs
index c5d40c2..e0f5862 100644
--- a/OpenSim/Data/Tests/PropertyScrambler.cs
+++ b/OpenSim/Data/Tests/PropertyScrambler.cs
@@ -34,6 +34,7 @@ using System.Text;
34using NUnit.Framework; 34using NUnit.Framework;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Tests.Common;
37 38
38namespace OpenSim.Data.Tests 39namespace OpenSim.Data.Tests
39{ 40{
@@ -158,7 +159,7 @@ namespace OpenSim.Data.Tests
158 } 159 }
159 160
160 [TestFixture] 161 [TestFixture]
161 public class PropertyScramblerTests 162 public class PropertyScramblerTests : OpenSimTestCase
162 { 163 {
163 [Test] 164 [Test]
164 public void TestScramble() 165 public void TestScramble()
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index bd23d1c..de30414 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -83,7 +83,8 @@ namespace OpenSim.Framework.Console
83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n"; 83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n";
84 84
85 public const string ItemHelpText 85 public const string ItemHelpText
86 = "For more information, type 'help <item>' where <item> is one of the following:"; 86= @"For more information, type 'help all' to get a list of all commands,
87 or type help <item>' where <item> is one of the following:";
87 88
88 /// <value> 89 /// <value>
89 /// Commands organized by keyword in a tree 90 /// Commands organized by keyword in a tree
@@ -117,6 +118,10 @@ namespace OpenSim.Framework.Console
117 help.Add(ItemHelpText); 118 help.Add(ItemHelpText);
118 help.AddRange(CollectModulesHelp(tree)); 119 help.AddRange(CollectModulesHelp(tree));
119 } 120 }
121 else if (helpParts.Count == 1 && helpParts[0] == "all")
122 {
123 help.AddRange(CollectAllCommandsHelp());
124 }
120 else 125 else
121 { 126 {
122 help.AddRange(CollectHelp(helpParts)); 127 help.AddRange(CollectHelp(helpParts));
@@ -124,6 +129,28 @@ namespace OpenSim.Framework.Console
124 129
125 return help; 130 return help;
126 } 131 }
132
133 /// <summary>
134 /// Collects the help from all commands and return in alphabetical order.
135 /// </summary>
136 /// <returns></returns>
137 private List<string> CollectAllCommandsHelp()
138 {
139 List<string> help = new List<string>();
140
141 lock (m_modulesCommands)
142 {
143 foreach (List<CommandInfo> commands in m_modulesCommands.Values)
144 {
145 var ourHelpText = commands.ConvertAll(c => string.Format("{0} - {1}", c.help_text, c.long_help));
146 help.AddRange(ourHelpText);
147 }
148 }
149
150 help.Sort();
151
152 return help;
153 }
127 154
128 /// <summary> 155 /// <summary>
129 /// See if we can find the requested command in order to display longer help 156 /// See if we can find the requested command in order to display longer help
@@ -711,7 +738,7 @@ namespace OpenSim.Framework.Console
711 /// </summary> 738 /// </summary>
712 public void Prompt() 739 public void Prompt()
713 { 740 {
714 string line = ReadLine(m_defaultPrompt + "# ", true, true); 741 string line = ReadLine(DefaultPrompt + "# ", true, true);
715 742
716 if (line != String.Empty) 743 if (line != String.Empty)
717 Output("Invalid command"); 744 Output("Invalid command");
diff --git a/OpenSim/Framework/Console/ConsoleBase.cs b/OpenSim/Framework/Console/ConsoleBase.cs
index 4b375d9..2d8e723 100755
--- a/OpenSim/Framework/Console/ConsoleBase.cs
+++ b/OpenSim/Framework/Console/ConsoleBase.cs
@@ -43,15 +43,7 @@ namespace OpenSim.Framework.Console
43 43
44 public object ConsoleScene { get; set; } 44 public object ConsoleScene { get; set; }
45 45
46 /// <summary> 46 public string DefaultPrompt { get; set; }
47 /// The default prompt text.
48 /// </summary>
49 public string DefaultPrompt
50 {
51 set { m_defaultPrompt = value; }
52 get { return m_defaultPrompt; }
53 }
54 protected string m_defaultPrompt;
55 47
56 public ConsoleBase(string defaultPrompt) 48 public ConsoleBase(string defaultPrompt)
57 { 49 {
diff --git a/OpenSim/Framework/Console/MockConsole.cs b/OpenSim/Framework/Console/MockConsole.cs
index b489f93..8ba58e4 100644
--- a/OpenSim/Framework/Console/MockConsole.cs
+++ b/OpenSim/Framework/Console/MockConsole.cs
@@ -46,13 +46,18 @@ namespace OpenSim.Framework.Console
46 46
47 public ICommands Commands { get { return m_commands; } } 47 public ICommands Commands { get { return m_commands; } }
48 48
49 public string DefaultPrompt { get; set; }
50
49 public void Prompt() {} 51 public void Prompt() {}
50 52
51 public void RunCommand(string cmd) {} 53 public void RunCommand(string cmd) {}
52 54
53 public string ReadLine(string p, bool isCommand, bool e) { return ""; } 55 public string ReadLine(string p, bool isCommand, bool e) { return ""; }
54 56
55 public object ConsoleScene { get { return null; } } 57 public object ConsoleScene {
58 get { return null; }
59 set {}
60 }
56 61
57 public void Output(string text, string level) {} 62 public void Output(string text, string level) {}
58 public void Output(string text) {} 63 public void Output(string text) {}
diff --git a/OpenSim/Framework/ICommandConsole.cs b/OpenSim/Framework/ICommandConsole.cs
index 8cd20da..a6573f8 100644
--- a/OpenSim/Framework/ICommandConsole.cs
+++ b/OpenSim/Framework/ICommandConsole.cs
@@ -83,6 +83,11 @@ namespace OpenSim.Framework
83 ICommands Commands { get; } 83 ICommands Commands { get; }
84 84
85 /// <summary> 85 /// <summary>
86 /// The default prompt text.
87 /// </summary>
88 string DefaultPrompt { get; set; }
89
90 /// <summary>
86 /// Display a command prompt on the console and wait for user input 91 /// Display a command prompt on the console and wait for user input
87 /// </summary> 92 /// </summary>
88 void Prompt(); 93 void Prompt();
diff --git a/OpenSim/Framework/IConsole.cs b/OpenSim/Framework/IConsole.cs
index 33024b2..79560d8 100644
--- a/OpenSim/Framework/IConsole.cs
+++ b/OpenSim/Framework/IConsole.cs
@@ -32,7 +32,7 @@ namespace OpenSim.Framework
32{ 32{
33 public interface IConsole 33 public interface IConsole
34 { 34 {
35 object ConsoleScene { get; } 35 object ConsoleScene { get; set; }
36 36
37 void Output(string text, string level); 37 void Output(string text, string level);
38 void Output(string text); 38 void Output(string text);
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 48f1c4f..0c12787 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -154,6 +154,11 @@ namespace OpenSim.Framework.Serialization
154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; 154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
155 } 155 }
156 156
157 public static string CreateOarLandDataPath(LandData ld)
158 {
159 return string.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, ld.GlobalID);
160 }
161
157 /// <summary> 162 /// <summary>
158 /// Create the filename used to store an object in an OpenSim Archive. 163 /// Create the filename used to store an object in an OpenSim Archive.
159 /// </summary> 164 /// </summary>
diff --git a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
index 8b9756b..ea100ee 100644
--- a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Framework.Serialization.Tests 37namespace OpenSim.Framework.Serialization.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class LandDataSerializerTest 40 public class LandDataSerializerTest : OpenSimTestCase
41 { 41 {
42 private LandData land; 42 private LandData land;
43 private LandData landWithParcelAccessList; 43 private LandData landWithParcelAccessList;
diff --git a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
index 09b6f6d..142726b 100644
--- a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
+++ b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Framework.Serialization.Tests 37namespace OpenSim.Framework.Serialization.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class RegionSettingsSerializerTests 40 public class RegionSettingsSerializerTests : OpenSimTestCase
41 { 41 {
42 private string m_serializedRs = @"<?xml version=""1.0"" encoding=""utf-16""?> 42 private string m_serializedRs = @"<?xml version=""1.0"" encoding=""utf-16""?>
43<RegionSettings> 43<RegionSettings>
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 5b2d7dc..c0dc907 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -27,7 +27,6 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
31using System.IO; 30using System.IO;
32using System.Reflection; 31using System.Reflection;
33using System.Text; 32using System.Text;
@@ -38,6 +37,8 @@ using log4net;
38using log4net.Appender; 37using log4net.Appender;
39using log4net.Core; 38using log4net.Core;
40using log4net.Repository; 39using log4net.Repository;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
41using OpenSim.Framework; 42using OpenSim.Framework;
42using OpenSim.Framework.Console; 43using OpenSim.Framework.Console;
43using OpenSim.Framework.Monitoring; 44using OpenSim.Framework.Monitoring;
@@ -45,16 +46,12 @@ using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer; 46using OpenSim.Framework.Servers.HttpServer;
46using Timer=System.Timers.Timer; 47using Timer=System.Timers.Timer;
47 48
48using OpenMetaverse;
49using OpenMetaverse.StructuredData;
50
51
52namespace OpenSim.Framework.Servers 49namespace OpenSim.Framework.Servers
53{ 50{
54 /// <summary> 51 /// <summary>
55 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc) 52 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc)
56 /// </summary> 53 /// </summary>
57 public abstract class BaseOpenSimServer 54 public abstract class BaseOpenSimServer : ServerBase
58 { 55 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 57
@@ -63,27 +60,6 @@ namespace OpenSim.Framework.Servers
63 /// server. 60 /// server.
64 /// </summary> 61 /// </summary>
65 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); 62 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
66
67 protected CommandConsole m_console;
68 protected OpenSimAppender m_consoleAppender;
69 protected IAppender m_logFileAppender = null;
70
71 /// <summary>
72 /// Time at which this server was started
73 /// </summary>
74 protected DateTime m_startuptime;
75
76 /// <summary>
77 /// Record the initial startup directory for info purposes
78 /// </summary>
79 protected string m_startupDirectory = Environment.CurrentDirectory;
80
81 /// <summary>
82 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
83 /// </summary>
84 protected string m_version;
85
86 protected string m_pidFile = String.Empty;
87 63
88 /// <summary> 64 /// <summary>
89 /// Random uuid for private data 65 /// Random uuid for private data
@@ -96,30 +72,13 @@ namespace OpenSim.Framework.Servers
96 get { return m_httpServer; } 72 get { return m_httpServer; }
97 } 73 }
98 74
99 public BaseOpenSimServer() 75 public BaseOpenSimServer() : base()
100 { 76 {
101 m_startuptime = DateTime.Now;
102 m_version = VersionInfo.Version;
103
104 // Random uuid for private data 77 // Random uuid for private data
105 m_osSecret = UUID.Random().ToString(); 78 m_osSecret = UUID.Random().ToString();
106 79
107 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 80 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
108 m_periodicDiagnosticsTimer.Enabled = true; 81 m_periodicDiagnosticsTimer.Enabled = true;
109
110 // This thread will go on to become the console listening thread
111 Thread.CurrentThread.Name = "ConsoleThread";
112
113 ILoggerRepository repository = LogManager.GetRepository();
114 IAppender[] appenders = repository.GetAppenders();
115
116 foreach (IAppender appender in appenders)
117 {
118 if (appender.Name == "LogFileAppender")
119 {
120 m_logFileAppender = appender;
121 }
122 }
123 } 82 }
124 83
125 /// <summary> 84 /// <summary>
@@ -127,83 +86,18 @@ namespace OpenSim.Framework.Servers
127 /// </summary> 86 /// </summary>
128 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
129 { 88 {
130 if (m_console != null) 89 if (m_console == null)
131 { 90 return;
132 ILoggerRepository repository = LogManager.GetRepository();
133 IAppender[] appenders = repository.GetAppenders();
134
135 foreach (IAppender appender in appenders)
136 {
137 if (appender.Name == "Console")
138 {
139 m_consoleAppender = (OpenSimAppender)appender;
140 break;
141 }
142 }
143
144 if (null == m_consoleAppender)
145 {
146 Notice("No appender named Console found (see the log4net config file for this executable)!");
147 }
148 else
149 {
150 m_consoleAppender.Console = m_console;
151
152 // If there is no threshold set then the threshold is effectively everything.
153 if (null == m_consoleAppender.Threshold)
154 m_consoleAppender.Threshold = Level.All;
155
156 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
157 }
158
159 m_console.Commands.AddCommand("General", false, "quit",
160 "quit",
161 "Quit the application", HandleQuit);
162
163 m_console.Commands.AddCommand("General", false, "shutdown",
164 "shutdown",
165 "Quit the application", HandleQuit);
166
167 m_console.Commands.AddCommand("General", false, "set log level",
168 "set log level <level>",
169 "Set the console logging level", HandleLogLevel);
170
171 m_console.Commands.AddCommand("General", false, "show info",
172 "show info",
173 "Show general information about the server", HandleShow);
174
175 m_console.Commands.AddCommand("General", false, "show threads",
176 "show threads",
177 "Show thread status", HandleShow);
178
179 m_console.Commands.AddCommand("General", false, "show uptime",
180 "show uptime",
181 "Show server uptime", HandleShow);
182
183 m_console.Commands.AddCommand("General", false, "show version",
184 "show version",
185 "Show server version", HandleShow);
186
187 m_console.Commands.AddCommand("General", false, "threads abort",
188 "threads abort <thread-id>",
189 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
190
191 m_console.Commands.AddCommand("General", false, "threads show",
192 "threads show",
193 "Show thread status. Synonym for \"show threads\"",
194 (string module, string[] args) => Notice(GetThreadsReport()));
195 91
196 m_console.Commands.AddCommand("General", false, "force gc", 92 RegisterCommonCommands();
197 "force gc", 93
198 "Manually invoke runtime garbage collection. For debugging purposes", 94 m_console.Commands.AddCommand("General", false, "quit",
199 HandleForceGc); 95 "quit",
200 } 96 "Quit the application", HandleQuit);
201 }
202 97
203 private void HandleForceGc(string module, string[] args) 98 m_console.Commands.AddCommand("General", false, "shutdown",
204 { 99 "shutdown",
205 MainConsole.Instance.Output("Manually invoking runtime garbage collection"); 100 "Quit the application", HandleQuit);
206 GC.Collect();
207 } 101 }
208 102
209 /// <summary> 103 /// <summary>
@@ -236,74 +130,11 @@ namespace OpenSim.Framework.Servers
236 } 130 }
237 131
238 /// <summary> 132 /// <summary>
239 /// Get a report about the registered threads in this server.
240 /// </summary>
241 protected string GetThreadsReport()
242 {
243 // This should be a constant field.
244 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
245
246 StringBuilder sb = new StringBuilder();
247 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
248
249 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
250
251 int timeNow = Environment.TickCount & Int32.MaxValue;
252
253 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
254 sb.Append(Environment.NewLine);
255
256 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
257 {
258 Thread t = twi.Thread;
259
260 sb.AppendFormat(
261 reportFormat,
262 t.ManagedThreadId,
263 t.Name,
264 timeNow - twi.LastTick,
265 timeNow - twi.FirstTick,
266 t.Priority,
267 t.ThreadState);
268
269 sb.Append("\n");
270 }
271
272 sb.Append("\n");
273
274 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
275 // zero active threads.
276 int totalThreads = Process.GetCurrentProcess().Threads.Count;
277 if (totalThreads > 0)
278 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
279
280 sb.Append("Main threadpool (excluding script engine pools)\n");
281 sb.Append(Util.GetThreadPoolReport());
282
283 return sb.ToString();
284 }
285
286 /// <summary>
287 /// Return a report about the uptime of this server
288 /// </summary>
289 /// <returns></returns>
290 protected string GetUptimeReport()
291 {
292 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
293 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
294 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
295
296 return sb.ToString();
297 }
298
299 /// <summary>
300 /// Performs initialisation of the scene, such as loading configuration from disk. 133 /// Performs initialisation of the scene, such as loading configuration from disk.
301 /// </summary> 134 /// </summary>
302 public virtual void Startup() 135 public virtual void Startup()
303 { 136 {
304 m_log.Info("[STARTUP]: Beginning startup processing"); 137 m_log.Info("[STARTUP]: Beginning startup processing");
305
306 EnhanceVersionInformation();
307 138
308 m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine); 139 m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine);
309 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and 140 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
@@ -338,257 +169,7 @@ namespace OpenSim.Framework.Servers
338 private void HandleQuit(string module, string[] args) 169 private void HandleQuit(string module, string[] args)
339 { 170 {
340 Shutdown(); 171 Shutdown();
341 } 172 }
342
343 private void HandleLogLevel(string module, string[] cmd)
344 {
345 if (null == m_consoleAppender)
346 {
347 Notice("No appender named Console found (see the log4net config file for this executable)!");
348 return;
349 }
350
351 if (cmd.Length > 3)
352 {
353 string rawLevel = cmd[3];
354
355 ILoggerRepository repository = LogManager.GetRepository();
356 Level consoleLevel = repository.LevelMap[rawLevel];
357
358 if (consoleLevel != null)
359 m_consoleAppender.Threshold = consoleLevel;
360 else
361 Notice(
362 String.Format(
363 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
364 rawLevel));
365 }
366
367 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
368 }
369
370 /// <summary>
371 /// Show help information
372 /// </summary>
373 /// <param name="helpArgs"></param>
374 protected virtual void ShowHelp(string[] helpArgs)
375 {
376 Notice("");
377
378 if (helpArgs.Length == 0)
379 {
380 Notice("set log level [level] - change the console logging level only. For example, off or debug.");
381 Notice("show info - show server information (e.g. startup path).");
382 Notice("show threads - list tracked threads");
383 Notice("show uptime - show server startup time and uptime.");
384 Notice("show version - show server version.");
385 Notice("");
386
387 return;
388 }
389 }
390
391 public virtual void HandleShow(string module, string[] cmd)
392 {
393 List<string> args = new List<string>(cmd);
394
395 args.RemoveAt(0);
396
397 string[] showParams = args.ToArray();
398
399 switch (showParams[0])
400 {
401 case "info":
402 ShowInfo();
403 break;
404
405 case "threads":
406 Notice(GetThreadsReport());
407 break;
408
409 case "uptime":
410 Notice(GetUptimeReport());
411 break;
412
413 case "version":
414 Notice(GetVersionText());
415 break;
416 }
417 }
418
419 public virtual void HandleThreadsAbort(string module, string[] cmd)
420 {
421 if (cmd.Length != 3)
422 {
423 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
424 return;
425 }
426
427 int threadId;
428 if (!int.TryParse(cmd[2], out threadId))
429 {
430 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
431 return;
432 }
433
434 if (Watchdog.AbortThread(threadId))
435 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
436 else
437 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
438 }
439
440 protected void ShowInfo()
441 {
442 Notice(GetVersionText());
443 Notice("Startup directory: " + m_startupDirectory);
444 if (null != m_consoleAppender)
445 Notice(String.Format("Console log level: {0}", m_consoleAppender.Threshold));
446 }
447
448 protected string GetVersionText()
449 {
450 return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
451 }
452
453 /// <summary>
454 /// Console output is only possible if a console has been established.
455 /// That is something that cannot be determined within this class. So
456 /// all attempts to use the console MUST be verified.
457 /// </summary>
458 /// <param name="msg"></param>
459 protected void Notice(string msg)
460 {
461 if (m_console != null)
462 {
463 m_console.Output(msg);
464 }
465 }
466
467 /// <summary>
468 /// Console output is only possible if a console has been established.
469 /// That is something that cannot be determined within this class. So
470 /// all attempts to use the console MUST be verified.
471 /// </summary>
472 /// <param name="format"></param>
473 /// <param name="components"></param>
474 protected void Notice(string format, params string[] components)
475 {
476 if (m_console != null)
477 m_console.OutputFormat(format, components);
478 }
479
480 /// <summary>
481 /// Enhance the version string with extra information if it's available.
482 /// </summary>
483 protected void EnhanceVersionInformation()
484 {
485 string buildVersion = string.Empty;
486
487 // The subversion information is deprecated and will be removed at a later date
488 // Add subversion revision information if available
489 // Try file "svn_revision" in the current directory first, then the .svn info.
490 // This allows to make the revision available in simulators not running from the source tree.
491 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
492 // elsewhere as well
493 string gitDir = "../.git/";
494 string gitRefPointerPath = gitDir + "HEAD";
495
496 string svnRevisionFileName = "svn_revision";
497 string svnFileName = ".svn/entries";
498 string manualVersionFileName = ".version";
499 string inputLine;
500 int strcmp;
501
502 if (File.Exists(manualVersionFileName))
503 {
504 using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
505 buildVersion = CommitFile.ReadLine();
506
507 m_version += buildVersion ?? "";
508 }
509 else if (File.Exists(gitRefPointerPath))
510 {
511// m_log.DebugFormat("[OPENSIM]: Found {0}", gitRefPointerPath);
512
513 string rawPointer = "";
514
515 using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
516 rawPointer = pointerFile.ReadLine();
517
518// m_log.DebugFormat("[OPENSIM]: rawPointer [{0}]", rawPointer);
519
520 Match m = Regex.Match(rawPointer, "^ref: (.+)$");
521
522 if (m.Success)
523 {
524// m_log.DebugFormat("[OPENSIM]: Matched [{0}]", m.Groups[1].Value);
525
526 string gitRef = m.Groups[1].Value;
527 string gitRefPath = gitDir + gitRef;
528 if (File.Exists(gitRefPath))
529 {
530// m_log.DebugFormat("[OPENSIM]: Found gitRefPath [{0}]", gitRefPath);
531
532 using (StreamReader refFile = File.OpenText(gitRefPath))
533 {
534 string gitHash = refFile.ReadLine();
535 m_version += gitHash.Substring(0, 7);
536 }
537 }
538 }
539 }
540 else
541 {
542 // Remove the else logic when subversion mirror is no longer used
543 if (File.Exists(svnRevisionFileName))
544 {
545 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
546 buildVersion = RevisionFile.ReadLine();
547 buildVersion.Trim();
548 RevisionFile.Close();
549 }
550
551 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
552 {
553 StreamReader EntriesFile = File.OpenText(svnFileName);
554 inputLine = EntriesFile.ReadLine();
555 while (inputLine != null)
556 {
557 // using the dir svn revision at the top of entries file
558 strcmp = String.Compare(inputLine, "dir");
559 if (strcmp == 0)
560 {
561 buildVersion = EntriesFile.ReadLine();
562 break;
563 }
564 else
565 {
566 inputLine = EntriesFile.ReadLine();
567 }
568 }
569 EntriesFile.Close();
570 }
571
572 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
573 }
574 }
575
576 protected void CreatePIDFile(string path)
577 {
578 try
579 {
580 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
581 FileStream fs = File.Create(path);
582
583 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
584 fs.Write(buf, 0, buf.Length);
585 fs.Close();
586 m_pidFile = path;
587 }
588 catch (Exception)
589 {
590 }
591 }
592 173
593 public string osSecret { 174 public string osSecret {
594 // Secret uuid for the simulator 175 // Secret uuid for the simulator
@@ -607,20 +188,5 @@ namespace OpenSim.Framework.Servers
607 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); 188 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
608 } 189 }
609 } 190 }
610
611 protected void RemovePIDFile()
612 {
613 if (m_pidFile != String.Empty)
614 {
615 try
616 {
617 File.Delete(m_pidFile);
618 m_pidFile = String.Empty;
619 }
620 catch (Exception)
621 {
622 }
623 }
624 }
625 } 191 }
626} 192} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 410a76a..2cd626f 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -719,8 +719,11 @@ namespace OpenSim.Framework.Servers.HttpServer
719 if (DebugLevel == 5) 719 if (DebugLevel == 5)
720 { 720 {
721 const int sampleLength = 80; 721 const int sampleLength = 80;
722 char[] sampleChars = new char[sampleLength]; 722 char[] sampleChars = new char[sampleLength + 3];
723 reader.Read(sampleChars, 0, sampleLength); 723 reader.Read(sampleChars, 0, sampleLength);
724 sampleChars[80] = '.';
725 sampleChars[81] = '.';
726 sampleChars[82] = '.';
724 output = new string(sampleChars); 727 output = new string(sampleChars);
725 } 728 }
726 else 729 else
@@ -728,7 +731,7 @@ namespace OpenSim.Framework.Servers.HttpServer
728 output = reader.ReadToEnd(); 731 output = reader.ReadToEnd();
729 } 732 }
730 733
731 m_log.DebugFormat("[BASE HTTP SERVER]: {0}...", output.Replace("\n", @"\n")); 734 m_log.DebugFormat("[BASE HTTP SERVER]: {0}", output.Replace("\n", @"\n"));
732 } 735 }
733 } 736 }
734 737
@@ -1279,59 +1282,6 @@ namespace OpenSim.Framework.Servers.HttpServer
1279 map["login"] = OSD.FromString("false"); 1282 map["login"] = OSD.FromString("false");
1280 return map; 1283 return map;
1281 } 1284 }
1282 /// <summary>
1283 /// A specific agent handler was provided. Such a handler is expecetd to have an
1284 /// intimate, and highly specific relationship with the client. Consequently,
1285 /// nothing is done here.
1286 /// </summary>
1287 /// <param name="handler"></param>
1288 /// <param name="request"></param>
1289 /// <param name="response"></param>
1290
1291 private bool HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response)
1292 {
1293 // In the case of REST, then handler is responsible for ALL aspects of
1294 // the request/response handling. Nothing is done here, not even encoding.
1295
1296 try
1297 {
1298 return handler.Handle(request, response);
1299 }
1300 catch (Exception e)
1301 {
1302 // If the handler did in fact close the stream, then this will blow
1303 // chunks. So that that doesn't disturb anybody we throw away any
1304 // and all exceptions raised. We've done our best to release the
1305 // client.
1306 try
1307 {
1308 m_log.Warn("[HTTP-AGENT]: Error - " + e.Message);
1309 response.SendChunked = false;
1310 response.KeepAlive = true;
1311 response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError;
1312 //response.OutputStream.Close();
1313 try
1314 {
1315 response.Send();
1316 //response.FreeContext();
1317 }
1318 catch (SocketException f)
1319 {
1320 // This has to be here to prevent a Linux/Mono crash
1321 m_log.Warn(
1322 String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", f.Message), f);
1323 }
1324 }
1325 catch(Exception)
1326 {
1327 }
1328 }
1329
1330 // Indicate that the request has been "handled"
1331
1332 return true;
1333
1334 }
1335 1285
1336 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) 1286 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
1337 { 1287 {
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
new file mode 100644
index 0000000..47baac8
--- /dev/null
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -0,0 +1,677 @@
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.Diagnostics;
31using System.IO;
32using System.Reflection;
33using System.Text;
34using System.Text.RegularExpressions;
35using System.Threading;
36using log4net;
37using log4net.Appender;
38using log4net.Core;
39using log4net.Repository;
40using Nini.Config;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43
44namespace OpenSim.Framework.Servers
45{
46 public class ServerBase
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 public IConfigSource Config { get; protected set; }
51
52 /// <summary>
53 /// Console to be used for any command line output. Can be null, in which case there should be no output.
54 /// </summary>
55 protected ICommandConsole m_console;
56
57 protected OpenSimAppender m_consoleAppender;
58 protected FileAppender m_logFileAppender;
59
60 protected DateTime m_startuptime;
61 protected string m_startupDirectory = Environment.CurrentDirectory;
62
63 protected string m_pidFile = String.Empty;
64
65 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary>
68 protected string m_version;
69
70 public ServerBase()
71 {
72 m_startuptime = DateTime.Now;
73 m_version = VersionInfo.Version;
74 EnhanceVersionInformation();
75 }
76
77 protected void CreatePIDFile(string path)
78 {
79 try
80 {
81 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
82
83 using (FileStream fs = File.Create(path))
84 {
85 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
86 fs.Write(buf, 0, buf.Length);
87 }
88
89 m_pidFile = path;
90
91 m_log.InfoFormat("[SERVER BASE]: Created pid file {0}", m_pidFile);
92 }
93 catch (Exception e)
94 {
95 m_log.Warn(string.Format("[SERVER BASE]: Could not create PID file at {0} ", path), e);
96 }
97 }
98
99 protected void RemovePIDFile()
100 {
101 if (m_pidFile != String.Empty)
102 {
103 try
104 {
105 File.Delete(m_pidFile);
106 }
107 catch (Exception e)
108 {
109 m_log.Error(string.Format("[SERVER BASE]: Error whilst removing {0} ", m_pidFile), e);
110 }
111
112 m_pidFile = String.Empty;
113 }
114 }
115
116 public void RegisterCommonAppenders(IConfig startupConfig)
117 {
118 ILoggerRepository repository = LogManager.GetRepository();
119 IAppender[] appenders = repository.GetAppenders();
120
121 foreach (IAppender appender in appenders)
122 {
123 if (appender.Name == "Console")
124 {
125 m_consoleAppender = (OpenSimAppender)appender;
126 }
127 else if (appender.Name == "LogFileAppender")
128 {
129 m_logFileAppender = (FileAppender)appender;
130 }
131 }
132
133 if (null == m_consoleAppender)
134 {
135 Notice("No appender named Console found (see the log4net config file for this executable)!");
136 }
137 else
138 {
139 // FIXME: This should be done through an interface rather than casting.
140 m_consoleAppender.Console = (ConsoleBase)m_console;
141
142 // If there is no threshold set then the threshold is effectively everything.
143 if (null == m_consoleAppender.Threshold)
144 m_consoleAppender.Threshold = Level.All;
145
146 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
147 }
148
149 if (m_logFileAppender != null && startupConfig != null)
150 {
151 string cfgFileName = startupConfig.GetString("LogFile", null);
152 if (cfgFileName != null)
153 {
154 m_logFileAppender.File = cfgFileName;
155 m_logFileAppender.ActivateOptions();
156 }
157
158 m_log.InfoFormat("[SERVER BASE]: Logging started to file {0}", m_logFileAppender.File);
159 }
160 }
161
162 /// <summary>
163 /// Register common commands once m_console has been set if it is going to be set
164 /// </summary>
165 public void RegisterCommonCommands()
166 {
167 if (m_console == null)
168 return;
169
170 m_console.Commands.AddCommand(
171 "General", false, "show info", "show info", "Show general information about the server", HandleShow);
172
173 m_console.Commands.AddCommand(
174 "General", false, "show version", "show version", "Show server version", HandleShow);
175
176 m_console.Commands.AddCommand(
177 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow);
178
179 m_console.Commands.AddCommand(
180 "General", false, "get log level", "get log level", "Get the current console logging level",
181 (mod, cmd) => ShowLogLevel());
182
183 m_console.Commands.AddCommand(
184 "General", false, "set log level", "set log level <level>",
185 "Set the console logging level for this session.", HandleSetLogLevel);
186
187 m_console.Commands.AddCommand(
188 "General", false, "config set",
189 "config set <section> <key> <value>",
190 "Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
191
192 m_console.Commands.AddCommand(
193 "General", false, "config get",
194 "config get [<section>] [<key>]",
195 "Synonym for config show",
196 HandleConfig);
197
198 m_console.Commands.AddCommand(
199 "General", false, "config show",
200 "config show [<section>] [<key>]",
201 "Show config information",
202 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
203 + "If a section is given but not a field, then all fields in that section are printed.",
204 HandleConfig);
205
206 m_console.Commands.AddCommand(
207 "General", false, "config save",
208 "config save <path>",
209 "Save current configuration to a file at the given path", HandleConfig);
210
211 m_console.Commands.AddCommand(
212 "General", false, "command-script",
213 "command-script <script>",
214 "Run a command script from file", HandleScript);
215
216 m_console.Commands.AddCommand(
217 "General", false, "show threads",
218 "show threads",
219 "Show thread status", HandleShow);
220
221 m_console.Commands.AddCommand(
222 "General", false, "threads abort",
223 "threads abort <thread-id>",
224 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
225
226 m_console.Commands.AddCommand(
227 "General", false, "threads show",
228 "threads show",
229 "Show thread status. Synonym for \"show threads\"",
230 (string module, string[] args) => Notice(GetThreadsReport()));
231
232 m_console.Commands.AddCommand(
233 "General", false, "force gc",
234 "force gc",
235 "Manually invoke runtime garbage collection. For debugging purposes",
236 HandleForceGc);
237 }
238
239 private void HandleForceGc(string module, string[] args)
240 {
241 Notice("Manually invoking runtime garbage collection");
242 GC.Collect();
243 }
244
245 public virtual void HandleShow(string module, string[] cmd)
246 {
247 List<string> args = new List<string>(cmd);
248
249 args.RemoveAt(0);
250
251 string[] showParams = args.ToArray();
252
253 switch (showParams[0])
254 {
255 case "info":
256 ShowInfo();
257 break;
258
259 case "version":
260 Notice(GetVersionText());
261 break;
262
263 case "uptime":
264 Notice(GetUptimeReport());
265 break;
266
267 case "threads":
268 Notice(GetThreadsReport());
269 break;
270 }
271 }
272
273 /// <summary>
274 /// Change and load configuration file data.
275 /// </summary>
276 /// <param name="module"></param>
277 /// <param name="cmd"></param>
278 private void HandleConfig(string module, string[] cmd)
279 {
280 List<string> args = new List<string>(cmd);
281 args.RemoveAt(0);
282 string[] cmdparams = args.ToArray();
283
284 if (cmdparams.Length > 0)
285 {
286 string firstParam = cmdparams[0].ToLower();
287
288 switch (firstParam)
289 {
290 case "set":
291 if (cmdparams.Length < 4)
292 {
293 Notice("Syntax: config set <section> <key> <value>");
294 Notice("Example: config set ScriptEngine.DotNetEngine NumberOfScriptThreads 5");
295 }
296 else
297 {
298 IConfig c;
299 IConfigSource source = new IniConfigSource();
300 c = source.AddConfig(cmdparams[1]);
301 if (c != null)
302 {
303 string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3);
304 c.Set(cmdparams[2], _value);
305 Config.Merge(source);
306
307 Notice("In section [{0}], set {1} = {2}", c.Name, cmdparams[2], _value);
308 }
309 }
310 break;
311
312 case "get":
313 case "show":
314 if (cmdparams.Length == 1)
315 {
316 foreach (IConfig config in Config.Configs)
317 {
318 Notice("[{0}]", config.Name);
319 string[] keys = config.GetKeys();
320 foreach (string key in keys)
321 Notice(" {0} = {1}", key, config.GetString(key));
322 }
323 }
324 else if (cmdparams.Length == 2 || cmdparams.Length == 3)
325 {
326 IConfig config = Config.Configs[cmdparams[1]];
327 if (config == null)
328 {
329 Notice("Section \"{0}\" does not exist.",cmdparams[1]);
330 break;
331 }
332 else
333 {
334 if (cmdparams.Length == 2)
335 {
336 Notice("[{0}]", config.Name);
337 foreach (string key in config.GetKeys())
338 Notice(" {0} = {1}", key, config.GetString(key));
339 }
340 else
341 {
342 Notice(
343 "config get {0} {1} : {2}",
344 cmdparams[1], cmdparams[2], config.GetString(cmdparams[2]));
345 }
346 }
347 }
348 else
349 {
350 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
351 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
352 }
353
354 break;
355
356 case "save":
357 if (cmdparams.Length < 2)
358 {
359 Notice("Syntax: config save <path>");
360 return;
361 }
362
363 string path = cmdparams[1];
364 Notice("Saving configuration file: {0}", path);
365
366 if (Config is IniConfigSource)
367 {
368 IniConfigSource iniCon = (IniConfigSource)Config;
369 iniCon.Save(path);
370 }
371 else if (Config is XmlConfigSource)
372 {
373 XmlConfigSource xmlCon = (XmlConfigSource)Config;
374 xmlCon.Save(path);
375 }
376
377 break;
378 }
379 }
380 }
381
382 private void HandleSetLogLevel(string module, string[] cmd)
383 {
384 if (cmd.Length != 4)
385 {
386 Notice("Usage: set log level <level>");
387 return;
388 }
389
390 if (null == m_consoleAppender)
391 {
392 Notice("No appender named Console found (see the log4net config file for this executable)!");
393 return;
394 }
395
396 string rawLevel = cmd[3];
397
398 ILoggerRepository repository = LogManager.GetRepository();
399 Level consoleLevel = repository.LevelMap[rawLevel];
400
401 if (consoleLevel != null)
402 m_consoleAppender.Threshold = consoleLevel;
403 else
404 Notice(
405 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
406 rawLevel);
407
408 ShowLogLevel();
409 }
410
411 private void ShowLogLevel()
412 {
413 Notice("Console log level is {0}", m_consoleAppender.Threshold);
414 }
415
416 protected virtual void HandleScript(string module, string[] parms)
417 {
418 if (parms.Length != 2)
419 {
420 Notice("Usage: command-script <path-to-script");
421 return;
422 }
423
424 RunCommandScript(parms[1]);
425 }
426
427 /// <summary>
428 /// Run an optional startup list of commands
429 /// </summary>
430 /// <param name="fileName"></param>
431 protected void RunCommandScript(string fileName)
432 {
433 if (m_console == null)
434 return;
435
436 if (File.Exists(fileName))
437 {
438 m_log.Info("[SERVER BASE]: Running " + fileName);
439
440 using (StreamReader readFile = File.OpenText(fileName))
441 {
442 string currentCommand;
443 while ((currentCommand = readFile.ReadLine()) != null)
444 {
445 currentCommand = currentCommand.Trim();
446 if (!(currentCommand == ""
447 || currentCommand.StartsWith(";")
448 || currentCommand.StartsWith("//")
449 || currentCommand.StartsWith("#")))
450 {
451 m_log.Info("[SERVER BASE]: Running '" + currentCommand + "'");
452 m_console.RunCommand(currentCommand);
453 }
454 }
455 }
456 }
457 }
458
459 /// <summary>
460 /// Return a report about the uptime of this server
461 /// </summary>
462 /// <returns></returns>
463 protected string GetUptimeReport()
464 {
465 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
466 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
467 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
468
469 return sb.ToString();
470 }
471
472 protected void ShowInfo()
473 {
474 Notice(GetVersionText());
475 Notice("Startup directory: " + m_startupDirectory);
476 if (null != m_consoleAppender)
477 Notice(String.Format("Console log level: {0}", m_consoleAppender.Threshold));
478 }
479
480 /// <summary>
481 /// Enhance the version string with extra information if it's available.
482 /// </summary>
483 protected void EnhanceVersionInformation()
484 {
485 string buildVersion = string.Empty;
486
487 // The subversion information is deprecated and will be removed at a later date
488 // Add subversion revision information if available
489 // Try file "svn_revision" in the current directory first, then the .svn info.
490 // This allows to make the revision available in simulators not running from the source tree.
491 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
492 // elsewhere as well
493 string gitDir = "../.git/";
494 string gitRefPointerPath = gitDir + "HEAD";
495
496 string svnRevisionFileName = "svn_revision";
497 string svnFileName = ".svn/entries";
498 string manualVersionFileName = ".version";
499 string inputLine;
500 int strcmp;
501
502 if (File.Exists(manualVersionFileName))
503 {
504 using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
505 buildVersion = CommitFile.ReadLine();
506
507 m_version += buildVersion ?? "";
508 }
509 else if (File.Exists(gitRefPointerPath))
510 {
511// m_log.DebugFormat("[SERVER BASE]: Found {0}", gitRefPointerPath);
512
513 string rawPointer = "";
514
515 using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
516 rawPointer = pointerFile.ReadLine();
517
518// m_log.DebugFormat("[SERVER BASE]: rawPointer [{0}]", rawPointer);
519
520 Match m = Regex.Match(rawPointer, "^ref: (.+)$");
521
522 if (m.Success)
523 {
524// m_log.DebugFormat("[SERVER BASE]: Matched [{0}]", m.Groups[1].Value);
525
526 string gitRef = m.Groups[1].Value;
527 string gitRefPath = gitDir + gitRef;
528 if (File.Exists(gitRefPath))
529 {
530// m_log.DebugFormat("[SERVER BASE]: Found gitRefPath [{0}]", gitRefPath);
531
532 using (StreamReader refFile = File.OpenText(gitRefPath))
533 {
534 string gitHash = refFile.ReadLine();
535 m_version += gitHash.Substring(0, 7);
536 }
537 }
538 }
539 }
540 else
541 {
542 // Remove the else logic when subversion mirror is no longer used
543 if (File.Exists(svnRevisionFileName))
544 {
545 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
546 buildVersion = RevisionFile.ReadLine();
547 buildVersion.Trim();
548 RevisionFile.Close();
549 }
550
551 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
552 {
553 StreamReader EntriesFile = File.OpenText(svnFileName);
554 inputLine = EntriesFile.ReadLine();
555 while (inputLine != null)
556 {
557 // using the dir svn revision at the top of entries file
558 strcmp = String.Compare(inputLine, "dir");
559 if (strcmp == 0)
560 {
561 buildVersion = EntriesFile.ReadLine();
562 break;
563 }
564 else
565 {
566 inputLine = EntriesFile.ReadLine();
567 }
568 }
569 EntriesFile.Close();
570 }
571
572 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
573 }
574 }
575
576 protected string GetVersionText()
577 {
578 return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
579 }
580
581 /// <summary>
582 /// Get a report about the registered threads in this server.
583 /// </summary>
584 protected string GetThreadsReport()
585 {
586 // This should be a constant field.
587 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
588
589 StringBuilder sb = new StringBuilder();
590 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
591
592 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
593
594 int timeNow = Environment.TickCount & Int32.MaxValue;
595
596 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
597 sb.Append(Environment.NewLine);
598
599 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
600 {
601 Thread t = twi.Thread;
602
603 sb.AppendFormat(
604 reportFormat,
605 t.ManagedThreadId,
606 t.Name,
607 timeNow - twi.LastTick,
608 timeNow - twi.FirstTick,
609 t.Priority,
610 t.ThreadState);
611
612 sb.Append("\n");
613 }
614
615 sb.Append("\n");
616
617 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
618 // zero active threads.
619 int totalThreads = Process.GetCurrentProcess().Threads.Count;
620 if (totalThreads > 0)
621 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
622
623 sb.Append("Main threadpool (excluding script engine pools)\n");
624 sb.Append(Util.GetThreadPoolReport());
625
626 return sb.ToString();
627 }
628
629 public virtual void HandleThreadsAbort(string module, string[] cmd)
630 {
631 if (cmd.Length != 3)
632 {
633 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
634 return;
635 }
636
637 int threadId;
638 if (!int.TryParse(cmd[2], out threadId))
639 {
640 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
641 return;
642 }
643
644 if (Watchdog.AbortThread(threadId))
645 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
646 else
647 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
648 }
649
650 /// <summary>
651 /// Console output is only possible if a console has been established.
652 /// That is something that cannot be determined within this class. So
653 /// all attempts to use the console MUST be verified.
654 /// </summary>
655 /// <param name="msg"></param>
656 protected void Notice(string msg)
657 {
658 if (m_console != null)
659 {
660 m_console.Output(msg);
661 }
662 }
663
664 /// <summary>
665 /// Console output is only possible if a console has been established.
666 /// That is something that cannot be determined within this class. So
667 /// all attempts to use the console MUST be verified.
668 /// </summary>
669 /// <param name="format"></param>
670 /// <param name="components"></param>
671 protected void Notice(string format, params object[] components)
672 {
673 if (m_console != null)
674 m_console.OutputFormat(format, components);
675 }
676 }
677} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index dc4eb8f..3412e0f 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -35,11 +35,12 @@ using HttpServer;
35using HttpServer.FormDecoders; 35using HttpServer.FormDecoders;
36using NUnit.Framework; 36using NUnit.Framework;
37using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Tests.Common;
38 39
39namespace OpenSim.Framework.Servers.Tests 40namespace OpenSim.Framework.Servers.Tests
40{ 41{
41 [TestFixture] 42 [TestFixture]
42 public class OSHttpTests 43 public class OSHttpTests : OpenSimTestCase
43 { 44 {
44 // we need an IHttpClientContext for our tests 45 // we need an IHttpClientContext for our tests
45 public class TestHttpClientContext: IHttpClientContext 46 public class TestHttpClientContext: IHttpClientContext
diff --git a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
index 49e5061..480f2bb 100644
--- a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
+++ b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
@@ -29,11 +29,12 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using NUnit.Framework; 31using NUnit.Framework;
32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Framework.Servers.Tests 34namespace OpenSim.Framework.Servers.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class VersionInfoTests 37 public class VersionInfoTests : OpenSimTestCase
37 { 38 {
38 [Test] 39 [Test]
39 public void TestVersionLength() 40 public void TestVersionLength()
diff --git a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
index 0dce414..95e9439 100644
--- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
+++ b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
@@ -24,16 +24,17 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
27using System.Collections.Generic; 28using System.Collections.Generic;
28using OpenMetaverse; 29using OpenMetaverse;
29using OpenMetaverse.StructuredData; 30using OpenMetaverse.StructuredData;
30using NUnit.Framework; 31using NUnit.Framework;
31 32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Framework.Tests 34namespace OpenSim.Framework.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class AgentCircuitDataTest 37 public class AgentCircuitDataTest : OpenSimTestCase
37 { 38 {
38 private UUID AgentId; 39 private UUID AgentId;
39 private AvatarAppearance AvAppearance; 40 private AvatarAppearance AvAppearance;
diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs
index 967a355..f3be81b 100644
--- a/OpenSim/Framework/Tests/AnimationTests.cs
+++ b/OpenSim/Framework/Tests/AnimationTests.cs
@@ -38,7 +38,7 @@ using Animation = OpenSim.Framework.Animation;
38namespace OpenSim.Framework.Tests 38namespace OpenSim.Framework.Tests
39{ 39{
40 [TestFixture] 40 [TestFixture]
41 public class AnimationTests 41 public class AnimationTests : OpenSimTestCase
42 { 42 {
43 private Animation anim1 = null; 43 private Animation anim1 = null;
44 private Animation anim2 = null; 44 private Animation anim2 = null;
diff --git a/OpenSim/Framework/Tests/AssetBaseTest.cs b/OpenSim/Framework/Tests/AssetBaseTest.cs
index 6db1aa0..25d2393 100644
--- a/OpenSim/Framework/Tests/AssetBaseTest.cs
+++ b/OpenSim/Framework/Tests/AssetBaseTest.cs
@@ -30,11 +30,12 @@ using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using NUnit.Framework; 31using NUnit.Framework;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Tests.Common;
33 34
34namespace OpenSim.Framework.Tests 35namespace OpenSim.Framework.Tests
35{ 36{
36 [TestFixture] 37 [TestFixture]
37 public class AssetBaseTest 38 public class AssetBaseTest : OpenSimTestCase
38 { 39 {
39 [Test] 40 [Test]
40 public void TestContainsReferences() 41 public void TestContainsReferences()
diff --git a/OpenSim/Framework/Tests/CacheTests.cs b/OpenSim/Framework/Tests/CacheTests.cs
index c3613e6..c709860 100644
--- a/OpenSim/Framework/Tests/CacheTests.cs
+++ b/OpenSim/Framework/Tests/CacheTests.cs
@@ -28,11 +28,12 @@
28using System; 28using System;
29using NUnit.Framework; 29using NUnit.Framework;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenSim.Tests.Common;
31 32
32namespace OpenSim.Framework.Tests 33namespace OpenSim.Framework.Tests
33{ 34{
34 [TestFixture] 35 [TestFixture]
35 public class CacheTests 36 public class CacheTests : OpenSimTestCase
36 { 37 {
37 private Cache cache; 38 private Cache cache;
38 private UUID cacheItemUUID; 39 private UUID cacheItemUUID;
diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs
index 2707afa..a56ecb4 100644
--- a/OpenSim/Framework/Tests/LocationTest.cs
+++ b/OpenSim/Framework/Tests/LocationTest.cs
@@ -26,11 +26,12 @@
26 */ 26 */
27 27
28using NUnit.Framework; 28using NUnit.Framework;
29using OpenSim.Tests.Common;
29 30
30namespace OpenSim.Framework.Tests 31namespace OpenSim.Framework.Tests
31{ 32{
32 [TestFixture] 33 [TestFixture]
33 public class LocationTest 34 public class LocationTest : OpenSimTestCase
34 { 35 {
35 [Test] 36 [Test]
36 public void locationRegionHandleRegionHandle() 37 public void locationRegionHandleRegionHandle()
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 672847d..47fe599 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -32,11 +32,12 @@ using OpenMetaverse.StructuredData;
32using System; 32using System;
33using System.Globalization; 33using System.Globalization;
34using System.Threading; 34using System.Threading;
35using OpenSim.Tests.Common;
35 36
36namespace OpenSim.Framework.Tests 37namespace OpenSim.Framework.Tests
37{ 38{
38 [TestFixture] 39 [TestFixture]
39 public class MundaneFrameworkTests 40 public class MundaneFrameworkTests : OpenSimTestCase
40 { 41 {
41 private bool m_RegionSettingsOnSaveEventFired; 42 private bool m_RegionSettingsOnSaveEventFired;
42 private bool m_RegionLightShareDataOnSaveEventFired; 43 private bool m_RegionLightShareDataOnSaveEventFired;
diff --git a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs
index 36bc6e7..82e13e5 100644
--- a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs
+++ b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs
@@ -31,11 +31,12 @@ using NUnit.Framework;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Tests.Common;
34 35
35namespace OpenSim.Framework.Tests 36namespace OpenSim.Framework.Tests
36{ 37{
37 [TestFixture] 38 [TestFixture]
38 public class PrimeNumberHelperTests 39 public class PrimeNumberHelperTests : OpenSimTestCase
39 { 40 {
40 [Test] 41 [Test]
41 public void TestGetPrime() 42 public void TestGetPrime()
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index f0d2a3f..11ca068 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -33,7 +33,7 @@ using OpenSim.Tests.Common;
33namespace OpenSim.Framework.Tests 33namespace OpenSim.Framework.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class UtilTests 36 public class UtilTests : OpenSimTestCase
37 { 37 {
38 [Test] 38 [Test]
39 public void VectorOperationTests() 39 public void VectorOperationTests()
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index c369dbc..a0c54a0 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1741,12 +1741,16 @@ namespace OpenSim.Framework
1741 StringBuilder sb = new StringBuilder(); 1741 StringBuilder sb = new StringBuilder();
1742 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 1742 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1743 { 1743 {
1744 threadPoolUsed = "SmartThreadPool"; 1744 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1745 maxThreads = m_ThreadPool.MaxThreads; 1745 if (m_ThreadPool != null)
1746 minThreads = m_ThreadPool.MinThreads; 1746 {
1747 inUseThreads = m_ThreadPool.InUseThreads; 1747 threadPoolUsed = "SmartThreadPool";
1748 allocatedThreads = m_ThreadPool.ActiveThreads; 1748 maxThreads = m_ThreadPool.MaxThreads;
1749 waitingCallbacks = m_ThreadPool.WaitingCallbacks; 1749 minThreads = m_ThreadPool.MinThreads;
1750 inUseThreads = m_ThreadPool.InUseThreads;
1751 allocatedThreads = m_ThreadPool.ActiveThreads;
1752 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1753 }
1750 } 1754 }
1751 else if ( 1755 else if (
1752 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem 1756 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index 8d95c41..fc3999f 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -188,7 +188,6 @@ namespace OpenSim
188 // Make sure command line options take precedence 188 // Make sure command line options take precedence
189 m_config.Source.Merge(argvSource); 189 m_config.Source.Merge(argvSource);
190 190
191
192 IConfig enVars = m_config.Source.Configs["Environment"]; 191 IConfig enVars = m_config.Source.Configs["Environment"];
193 192
194 if( enVars != null ) 193 if( enVars != null )
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 47252f6..cffbb3b 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -82,8 +82,8 @@ namespace OpenSim
82 { 82 {
83 base.ReadExtraConfigSettings(); 83 base.ReadExtraConfigSettings();
84 84
85 IConfig startupConfig = m_config.Source.Configs["Startup"]; 85 IConfig startupConfig = Config.Configs["Startup"];
86 IConfig networkConfig = m_config.Source.Configs["Network"]; 86 IConfig networkConfig = Config.Configs["Network"];
87 87
88 int stpMaxThreads = 15; 88 int stpMaxThreads = 15;
89 89
@@ -106,22 +106,6 @@ namespace OpenSim
106 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200); 106 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
107 } 107 }
108 108
109 if (m_logFileAppender != null)
110 {
111 if (m_logFileAppender is log4net.Appender.FileAppender)
112 {
113 log4net.Appender.FileAppender appender =
114 (log4net.Appender.FileAppender)m_logFileAppender;
115 string fileName = startupConfig.GetString("LogFile", String.Empty);
116 if (fileName != String.Empty)
117 {
118 appender.File = fileName;
119 appender.ActivateOptions();
120 }
121 m_log.InfoFormat("[LOGGING]: Logging started to file {0}", appender.File);
122 }
123 }
124
125 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty); 109 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty);
126 FireAndForgetMethod asyncCallMethod; 110 FireAndForgetMethod asyncCallMethod;
127 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 111 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
@@ -164,7 +148,7 @@ namespace OpenSim
164 break; 148 break;
165 case "rest": 149 case "rest":
166 m_console = new RemoteConsole("Region"); 150 m_console = new RemoteConsole("Region");
167 ((RemoteConsole)m_console).ReadConfig(m_config.Source); 151 ((RemoteConsole)m_console).ReadConfig(Config);
168 break; 152 break;
169 default: 153 default:
170 m_console = new LocalConsole("Region"); 154 m_console = new LocalConsole("Region");
@@ -174,6 +158,7 @@ namespace OpenSim
174 158
175 MainConsole.Instance = m_console; 159 MainConsole.Instance = m_console;
176 160
161 RegisterCommonAppenders(Config.Configs["Startup"]);
177 RegisterConsoleCommands(); 162 RegisterConsoleCommands();
178 163
179 base.StartupSpecific(); 164 base.StartupSpecific();
@@ -372,26 +357,6 @@ namespace OpenSim
372 "restart", 357 "restart",
373 "Restart all sims in this instance", RunCommand); 358 "Restart all sims in this instance", RunCommand);
374 359
375 m_console.Commands.AddCommand("General", false, "config set",
376 "config set <section> <key> <value>",
377 "Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
378
379 m_console.Commands.AddCommand("General", false, "config get",
380 "config get [<section>] [<key>]",
381 "Synonym for config show",
382 HandleConfig);
383
384 m_console.Commands.AddCommand("General", false, "config show",
385 "config show [<section>] [<key>]",
386 "Show config information",
387 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
388 + "If a section is given but not a field, then all fields in that section are printed.",
389 HandleConfig);
390
391 m_console.Commands.AddCommand("General", false, "config save",
392 "config save <path>",
393 "Save current configuration to a file at the given path", HandleConfig);
394
395 m_console.Commands.AddCommand("General", false, "command-script", 360 m_console.Commands.AddCommand("General", false, "command-script",
396 "command-script <script>", 361 "command-script <script>",
397 "Run a command script from file", RunCommand); 362 "Run a command script from file", RunCommand);
@@ -502,35 +467,6 @@ namespace OpenSim
502 } 467 }
503 468
504 /// <summary> 469 /// <summary>
505 /// Run an optional startup list of commands
506 /// </summary>
507 /// <param name="fileName"></param>
508 private void RunCommandScript(string fileName)
509 {
510 if (File.Exists(fileName))
511 {
512 m_log.Info("[COMMANDFILE]: Running " + fileName);
513
514 using (StreamReader readFile = File.OpenText(fileName))
515 {
516 string currentCommand;
517 while ((currentCommand = readFile.ReadLine()) != null)
518 {
519 currentCommand = currentCommand.Trim();
520 if (!(currentCommand == ""
521 || currentCommand.StartsWith(";")
522 || currentCommand.StartsWith("//")
523 || currentCommand.StartsWith("#")))
524 {
525 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'");
526 m_console.RunCommand(currentCommand);
527 }
528 }
529 }
530 }
531 }
532
533 /// <summary>
534 /// Opens a file and uses it as input to the console command parser. 470 /// Opens a file and uses it as input to the console command parser.
535 /// </summary> 471 /// </summary>
536 /// <param name="fileName">name of file to use as input to the console</param> 472 /// <param name="fileName">name of file to use as input to the console</param>
@@ -634,111 +570,9 @@ namespace OpenSim
634 bool changed = PopulateRegionEstateInfo(regInfo); 570 bool changed = PopulateRegionEstateInfo(regInfo);
635 IScene scene; 571 IScene scene;
636 CreateRegion(regInfo, true, out scene); 572 CreateRegion(regInfo, true, out scene);
637 if (changed)
638 regInfo.EstateSettings.Save();
639 }
640 573
641 /// <summary> 574 if (changed)
642 /// Change and load configuration file data. 575 regInfo.EstateSettings.Save();
643 /// </summary>
644 /// <param name="module"></param>
645 /// <param name="cmd"></param>
646 private void HandleConfig(string module, string[] cmd)
647 {
648 List<string> args = new List<string>(cmd);
649 args.RemoveAt(0);
650 string[] cmdparams = args.ToArray();
651
652 if (cmdparams.Length > 0)
653 {
654 string firstParam = cmdparams[0].ToLower();
655
656 switch (firstParam)
657 {
658 case "set":
659 if (cmdparams.Length < 4)
660 {
661 Notice("Syntax: config set <section> <key> <value>");
662 Notice("Example: config set ScriptEngine.DotNetEngine NumberOfScriptThreads 5");
663 }
664 else
665 {
666 IConfig c;
667 IConfigSource source = new IniConfigSource();
668 c = source.AddConfig(cmdparams[1]);
669 if (c != null)
670 {
671 string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3);
672 c.Set(cmdparams[2], _value);
673 m_config.Source.Merge(source);
674
675 Notice("In section [{0}], set {1} = {2}", c.Name, cmdparams[2], _value);
676 }
677 }
678 break;
679
680 case "get":
681 case "show":
682 if (cmdparams.Length == 1)
683 {
684 foreach (IConfig config in m_config.Source.Configs)
685 {
686 Notice("[{0}]", config.Name);
687 string[] keys = config.GetKeys();
688 foreach (string key in keys)
689 Notice(" {0} = {1}", key, config.GetString(key));
690 }
691 }
692 else if (cmdparams.Length == 2 || cmdparams.Length == 3)
693 {
694 IConfig config = m_config.Source.Configs[cmdparams[1]];
695 if (config == null)
696 {
697 Notice("Section \"{0}\" does not exist.",cmdparams[1]);
698 break;
699 }
700 else
701 {
702 if (cmdparams.Length == 2)
703 {
704 Notice("[{0}]", config.Name);
705 foreach (string key in config.GetKeys())
706 Notice(" {0} = {1}", key, config.GetString(key));
707 }
708 else
709 {
710 Notice(
711 "config get {0} {1} : {2}",
712 cmdparams[1], cmdparams[2], config.GetString(cmdparams[2]));
713 }
714 }
715 }
716 else
717 {
718 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
719 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
720 }
721
722 break;
723
724 case "save":
725 if (cmdparams.Length < 2)
726 {
727 Notice("Syntax: config save <path>");
728 return;
729 }
730
731 if (Application.iniFilePath == cmdparams[1])
732 {
733 Notice("Path can not be " + Application.iniFilePath);
734 return;
735 }
736
737 Notice("Saving configuration file: " + cmdparams[1]);
738 m_config.Save(cmdparams[1]);
739 break;
740 }
741 }
742 } 576 }
743 577
744 /// <summary> 578 /// <summary>
@@ -787,13 +621,6 @@ namespace OpenSim
787 621
788 switch (command) 622 switch (command)
789 { 623 {
790 case "command-script":
791 if (cmdparams.Length > 0)
792 {
793 RunCommandScript(cmdparams[0]);
794 }
795 break;
796
797 case "backup": 624 case "backup":
798 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); 625 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
799 SceneManager.BackupCurrentScene(); 626 SceneManager.BackupCurrentScene();
@@ -837,12 +664,20 @@ namespace OpenSim
837 664
838 if (!SceneManager.TrySetCurrentScene(newRegionName)) 665 if (!SceneManager.TrySetCurrentScene(newRegionName))
839 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); 666 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
667 else
668 RefreshPrompt();
840 } 669 }
841 else 670 else
842 { 671 {
843 MainConsole.Instance.Output("Usage: change region <region name>"); 672 MainConsole.Instance.Output("Usage: change region <region name>");
844 } 673 }
674 }
845 675
676 /// <summary>
677 /// Refreshs prompt with the current selection details.
678 /// </summary>
679 private void RefreshPrompt()
680 {
846 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName); 681 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
847 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); 682 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
848 683
@@ -864,6 +699,18 @@ namespace OpenSim
864 m_console.ConsoleScene = SceneManager.CurrentScene; 699 m_console.ConsoleScene = SceneManager.CurrentScene;
865 } 700 }
866 701
702 protected override void HandleRestartRegion(RegionInfo whichRegion)
703 {
704 base.HandleRestartRegion(whichRegion);
705
706 // Where we are restarting multiple scenes at once, a previous call to RefreshPrompt may have set the
707 // m_console.ConsoleScene to null (indicating all scenes).
708 if (m_console.ConsoleScene != null && whichRegion.RegionName == ((Scene)m_console.ConsoleScene).Name)
709 SceneManager.TrySetCurrentScene(whichRegion.RegionName);
710
711 RefreshPrompt();
712 }
713
867 /// <summary> 714 /// <summary>
868 /// Turn on some debugging values for OpenSim. 715 /// Turn on some debugging values for OpenSim.
869 /// </summary> 716 /// </summary>
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 808c760..c3c87e7 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -100,13 +100,7 @@ namespace OpenSim
100 /// <value> 100 /// <value>
101 /// The config information passed into the OpenSimulator region server. 101 /// The config information passed into the OpenSimulator region server.
102 /// </value> 102 /// </value>
103 public OpenSimConfigSource ConfigSource 103 public OpenSimConfigSource ConfigSource { get; private set; }
104 {
105 get { return m_config; }
106 set { m_config = value; }
107 }
108
109 protected OpenSimConfigSource m_config;
110 104
111 public List<IClientNetworkServer> ClientServers 105 public List<IClientNetworkServer> ClientServers
112 { 106 {
@@ -146,13 +140,14 @@ namespace OpenSim
146 protected virtual void LoadConfigSettings(IConfigSource configSource) 140 protected virtual void LoadConfigSettings(IConfigSource configSource)
147 { 141 {
148 m_configLoader = new ConfigurationLoader(); 142 m_configLoader = new ConfigurationLoader();
149 m_config = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo); 143 ConfigSource = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo);
144 Config = ConfigSource.Source;
150 ReadExtraConfigSettings(); 145 ReadExtraConfigSettings();
151 } 146 }
152 147
153 protected virtual void ReadExtraConfigSettings() 148 protected virtual void ReadExtraConfigSettings()
154 { 149 {
155 IConfig networkConfig = m_config.Source.Configs["Network"]; 150 IConfig networkConfig = Config.Configs["Network"];
156 if (networkConfig != null) 151 if (networkConfig != null)
157 { 152 {
158 proxyUrl = networkConfig.GetString("proxy_url", ""); 153 proxyUrl = networkConfig.GetString("proxy_url", "");
@@ -185,7 +180,7 @@ namespace OpenSim
185 /// </summary> 180 /// </summary>
186 protected override void StartupSpecific() 181 protected override void StartupSpecific()
187 { 182 {
188 IConfig startupConfig = m_config.Source.Configs["Startup"]; 183 IConfig startupConfig = Config.Configs["Startup"];
189 if (startupConfig != null) 184 if (startupConfig != null)
190 { 185 {
191 string pidFile = startupConfig.GetString("PIDFile", String.Empty); 186 string pidFile = startupConfig.GetString("PIDFile", String.Empty);
@@ -196,7 +191,7 @@ namespace OpenSim
196 } 191 }
197 192
198 // Load the simulation data service 193 // Load the simulation data service
199 IConfig simDataConfig = m_config.Source.Configs["SimulationDataStore"]; 194 IConfig simDataConfig = Config.Configs["SimulationDataStore"];
200 if (simDataConfig == null) 195 if (simDataConfig == null)
201 throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); 196 throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
202 197
@@ -204,7 +199,7 @@ namespace OpenSim
204 if (String.IsNullOrEmpty(module)) 199 if (String.IsNullOrEmpty(module))
205 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section."); 200 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section.");
206 201
207 m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { m_config.Source }); 202 m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { Config });
208 if (m_simulationDataService == null) 203 if (m_simulationDataService == null)
209 throw new Exception( 204 throw new Exception(
210 string.Format( 205 string.Format(
@@ -212,7 +207,7 @@ namespace OpenSim
212 module)); 207 module));
213 208
214 // Load the estate data service 209 // Load the estate data service
215 IConfig estateDataConfig = m_config.Source.Configs["EstateDataStore"]; 210 IConfig estateDataConfig = Config.Configs["EstateDataStore"];
216 if (estateDataConfig == null) 211 if (estateDataConfig == null)
217 throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); 212 throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
218 213
@@ -220,7 +215,7 @@ namespace OpenSim
220 if (String.IsNullOrEmpty(module)) 215 if (String.IsNullOrEmpty(module))
221 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section"); 216 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section");
222 217
223 m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { m_config.Source }); 218 m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { Config });
224 if (m_estateDataService == null) 219 if (m_estateDataService == null)
225 throw new Exception( 220 throw new Exception(
226 string.Format( 221 string.Format(
@@ -242,7 +237,7 @@ namespace OpenSim
242 } 237 }
243 } 238 }
244 239
245 protected virtual void AddPluginCommands(CommandConsole console) 240 protected virtual void AddPluginCommands(ICommandConsole console)
246 { 241 {
247 List<string> topics = GetHelpTopics(); 242 List<string> topics = GetHelpTopics();
248 243
@@ -304,7 +299,7 @@ namespace OpenSim
304 // Called from base.StartUp() 299 // Called from base.StartUp()
305 300
306 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 301 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
307 SceneManager.OnRestartSim += handleRestartRegion; 302 SceneManager.OnRestartSim += HandleRestartRegion;
308 303
309 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is 304 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
310 // heavily used during initial startup. 305 // heavily used during initial startup.
@@ -369,7 +364,7 @@ namespace OpenSim
369 } 364 }
370 365
371 IClientNetworkServer clientServer; 366 IClientNetworkServer clientServer;
372 Scene scene = SetupScene(regionInfo, proxyOffset, m_config.Source, out clientServer); 367 Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServer);
373 368
374 m_log.Info("[MODULES]: Loading Region's modules (old style)"); 369 m_log.Info("[MODULES]: Loading Region's modules (old style)");
375 370
@@ -451,10 +446,10 @@ namespace OpenSim
451 string estateOwnerPassword = null; 446 string estateOwnerPassword = null;
452 string rawEstateOwnerUuid = null; 447 string rawEstateOwnerUuid = null;
453 448
454 if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null) 449 if (Config.Configs[ESTATE_SECTION_NAME] != null)
455 { 450 {
456 string defaultEstateOwnerName 451 string defaultEstateOwnerName
457 = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim(); 452 = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim();
458 string[] ownerNames = defaultEstateOwnerName.Split(' '); 453 string[] ownerNames = defaultEstateOwnerName.Split(' ');
459 454
460 if (ownerNames.Length >= 2) 455 if (ownerNames.Length >= 2)
@@ -464,9 +459,9 @@ namespace OpenSim
464 } 459 }
465 460
466 // Info to be used only on Standalone Mode 461 // Info to be used only on Standalone Mode
467 rawEstateOwnerUuid = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null); 462 rawEstateOwnerUuid = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null);
468 estateOwnerEMail = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null); 463 estateOwnerEMail = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null);
469 estateOwnerPassword = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null); 464 estateOwnerPassword = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null);
470 } 465 }
471 466
472 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName); 467 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName);
@@ -713,7 +708,7 @@ namespace OpenSim
713 return new Scene( 708 return new Scene(
714 regionInfo, circuitManager, sceneGridService, 709 regionInfo, circuitManager, sceneGridService,
715 simDataService, estateDataService, false, 710 simDataService, estateDataService, false,
716 m_config.Source, m_version); 711 Config, m_version);
717 } 712 }
718 713
719 protected void ShutdownClientServer(RegionInfo whichRegion) 714 protected void ShutdownClientServer(RegionInfo whichRegion)
@@ -740,9 +735,11 @@ namespace OpenSim
740 } 735 }
741 } 736 }
742 737
743 public void handleRestartRegion(RegionInfo whichRegion) 738 protected virtual void HandleRestartRegion(RegionInfo whichRegion)
744 { 739 {
745 m_log.Info("[OPENSIM]: Got restart signal from SceneManager"); 740 m_log.InfoFormat(
741 "[OPENSIM]: Got restart signal from SceneManager for region {0} ({1},{2})",
742 whichRegion.RegionName, whichRegion.RegionLocX, whichRegion.RegionLocY);
746 743
747 ShutdownClientServer(whichRegion); 744 ShutdownClientServer(whichRegion);
748 IScene scene; 745 IScene scene;
@@ -754,7 +751,7 @@ namespace OpenSim
754 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier) 751 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier)
755 { 752 {
756 return GetPhysicsScene( 753 return GetPhysicsScene(
757 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, m_config.Source, osSceneIdentifier); 754 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier);
758 } 755 }
759 756
760 /// <summary> 757 /// <summary>
@@ -888,7 +885,6 @@ namespace OpenSim
888 m_log.Info("[SHUTDOWN]: Closing all threads"); 885 m_log.Info("[SHUTDOWN]: Closing all threads");
889 m_log.Info("[SHUTDOWN]: Killing listener thread"); 886 m_log.Info("[SHUTDOWN]: Killing listener thread");
890 m_log.Info("[SHUTDOWN]: Killing clients"); 887 m_log.Info("[SHUTDOWN]: Killing clients");
891 // TODO: implement this
892 m_log.Info("[SHUTDOWN]: Closing console and terminating"); 888 m_log.Info("[SHUTDOWN]: Closing console and terminating");
893 889
894 try 890 try
@@ -897,7 +893,7 @@ namespace OpenSim
897 } 893 }
898 catch (Exception e) 894 catch (Exception e)
899 { 895 {
900 m_log.ErrorFormat("[SHUTDOWN]: Ignoring failure during shutdown - {0}", e); 896 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
901 } 897 }
902 } 898 }
903 899
@@ -991,9 +987,9 @@ namespace OpenSim
991 987
992 string defaultEstateName = null; 988 string defaultEstateName = null;
993 989
994 if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null) 990 if (Config.Configs[ESTATE_SECTION_NAME] != null)
995 { 991 {
996 defaultEstateName = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null); 992 defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null);
997 993
998 if (defaultEstateName != null) 994 if (defaultEstateName != null)
999 { 995 {
@@ -1076,28 +1072,14 @@ namespace OpenSim
1076 MainConsole.Instance.Output("Joining the estate failed. Please try again."); 1072 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
1077 } 1073 }
1078 } 1074 }
1079 } 1075 }
1080 1076
1081 return true; // need to update the database 1077 return true; // need to update the database
1082 } 1078 }
1083 } 1079 }
1084 1080
1085 public class OpenSimConfigSource 1081 public class OpenSimConfigSource
1086 { 1082 {
1087 public IConfigSource Source; 1083 public IConfigSource Source;
1088
1089 public void Save(string path)
1090 {
1091 if (Source is IniConfigSource)
1092 {
1093 IniConfigSource iniCon = (IniConfigSource) Source;
1094 iniCon.Save(path);
1095 }
1096 else if (Source is XmlConfigSource)
1097 {
1098 XmlConfigSource xmlCon = (XmlConfigSource) Source;
1099 xmlCon.Save(path);
1100 }
1101 }
1102 } 1084 }
1103} 1085} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index d604cf6..ed8ec16 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.ClientStack.Linden.Tests 44namespace OpenSim.Region.ClientStack.Linden.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class EventQueueTests 47 public class EventQueueTests : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 50
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 5fcf376..7d9f581 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common.Mock;
43namespace OpenSim.Region.ClientStack.LindenUDP.Tests 43namespace OpenSim.Region.ClientStack.LindenUDP.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class LLImageManagerTests 46 public class LLImageManagerTests : OpenSimTestCase
47 { 47 {
48 private AssetBase m_testImageAsset; 48 private AssetBase m_testImageAsset;
49 private Scene scene; 49 private Scene scene;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
index 0f88ec6..5f73a94 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
39 /// Tests for the LL packet handler 39 /// Tests for the LL packet handler
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class PacketHandlerTests 42 public class PacketHandlerTests : OpenSimTestCase
43 { 43 {
44// [Test] 44// [Test]
45// /// <summary> 45// /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 1c2bfd0..0872cc8 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. 47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
48 /// </summary> 48 /// </summary>
49 [TestFixture] 49 [TestFixture]
50 public class FlotsamAssetCacheTests 50 public class FlotsamAssetCacheTests : OpenSimTestCase
51 { 51 {
52 protected TestScene m_scene; 52 protected TestScene m_scene;
53 protected FlotsamAssetCache m_cache; 53 protected FlotsamAssetCache m_cache;
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 848b3bf..1830d41 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common.Mock;
39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
40{ 40{
41 [TestFixture] 41 [TestFixture]
42 public class AvatarFactoryModuleTests 42 public class AvatarFactoryModuleTests : OpenSimTestCase
43 { 43 {
44 /// <summary> 44 /// <summary>
45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. 45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service.
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index 7a197f7..961117e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests 40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class FriendsModuleTests 43 public class FriendsModuleTests : OpenSimTestCase
44 { 44 {
45 private FriendsModule m_fm; 45 private FriendsModule m_fm;
46 private TestScene m_scene; 46 private TestScene m_scene;
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index 21d8bd7..b768257 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -49,7 +49,7 @@ using OpenSim.Tests.Common.Mock;
49namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests 49namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
50{ 50{
51 [TestFixture] 51 [TestFixture]
52 public class InventoryAccessModuleTests 52 public class InventoryAccessModuleTests : OpenSimTestCase
53 { 53 {
54 protected TestScene m_scene; 54 protected TestScene m_scene;
55 protected BasicInventoryAccessModule m_iam; 55 protected BasicInventoryAccessModule m_iam;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
new file mode 100644
index 0000000..fdbe10a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
@@ -0,0 +1,137 @@
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;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Server.Base;
38using OpenSim.Services.Interfaces;
39using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
42{
43 public class BasePresenceServiceConnector : IPresenceService
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 protected bool m_Enabled;
48
49 protected PresenceDetector m_PresenceDetector;
50
51 /// <summary>
52 /// Underlying presence service. Do not use directly.
53 /// </summary>
54 public IPresenceService m_PresenceService;
55
56 public Type ReplaceableInterface
57 {
58 get { return null; }
59 }
60
61 public void AddRegion(Scene scene)
62 {
63 if (!m_Enabled)
64 return;
65
66 // m_log.DebugFormat(
67 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
68
69 scene.RegisterModuleInterface<IPresenceService>(this);
70 m_PresenceDetector.AddRegion(scene);
71
72 m_log.InfoFormat("[BASE PRESENCE SERVICE CONNECTOR]: Enabled for region {0}", scene.Name);
73 }
74
75 public void RemoveRegion(Scene scene)
76 {
77 if (!m_Enabled)
78 return;
79
80 m_PresenceDetector.RemoveRegion(scene);
81 }
82
83 public void RegionLoaded(Scene scene)
84 {
85 if (!m_Enabled)
86 return;
87
88 }
89
90 public void PostInitialise()
91 {
92 }
93
94 public void Close()
95 {
96 }
97
98 #region IPresenceService
99
100 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
101 {
102 m_log.Warn("[BASE PRESENCE SERVICE CONNECTOR]: LoginAgent connector not implemented at the simulators");
103 return false;
104 }
105
106 public bool LogoutAgent(UUID sessionID)
107 {
108 return m_PresenceService.LogoutAgent(sessionID);
109 }
110
111 public bool LogoutRegionAgents(UUID regionID)
112 {
113 return m_PresenceService.LogoutRegionAgents(regionID);
114 }
115
116 public bool ReportAgent(UUID sessionID, UUID regionID)
117 {
118 return m_PresenceService.ReportAgent(sessionID, regionID);
119 }
120
121 public PresenceInfo GetAgent(UUID sessionID)
122 {
123 return m_PresenceService.GetAgent(sessionID);
124 }
125
126 public PresenceInfo[] GetAgents(string[] userIDs)
127 {
128 // Don't bother potentially making a useless network call if we not going to ask for any users anyway.
129 if (userIDs.Length == 0)
130 return new PresenceInfo[0];
131
132 return m_PresenceService.GetAgents(userIDs);
133 }
134
135 #endregion
136 }
137} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
index d8bed1b..db5c520 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
@@ -24,53 +24,29 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
27using System; 28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30 31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
31using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
33using OpenSim.Server.Base; 37using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
35using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 39using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
36 40
37using OpenMetaverse;
38using log4net;
39using Mono.Addins;
40using Nini.Config;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
43{ 42{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalPresenceServicesConnector")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalPresenceServicesConnector")]
45 public class LocalPresenceServicesConnector : ISharedRegionModule, IPresenceService 44 public class LocalPresenceServicesConnector : BasePresenceServiceConnector, ISharedRegionModule, IPresenceService
46 { 45 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 47
49 private bool m_Enabled = false;
50
51 private PresenceDetector m_PresenceDetector;
52
53 /// <summary>
54 /// Underlying presence service. Do not use directly.
55 /// </summary>
56 public IPresenceService m_PresenceService;
57
58 public LocalPresenceServicesConnector()
59 {
60 }
61
62 public LocalPresenceServicesConnector(IConfigSource source)
63 {
64 Initialise(source);
65 }
66
67 #region ISharedRegionModule 48 #region ISharedRegionModule
68 49
69 public Type ReplaceableInterface
70 {
71 get { return null; }
72 }
73
74 public string Name 50 public string Name
75 { 51 {
76 get { return "LocalPresenceServicesConnector"; } 52 get { return "LocalPresenceServicesConnector"; }
@@ -121,81 +97,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
121 } 97 }
122 } 98 }
123 99
124 public void PostInitialise()
125 {
126 }
127
128 public void Close()
129 {
130 }
131
132 public void AddRegion(Scene scene)
133 {
134 if (!m_Enabled)
135 return;
136
137 // m_log.DebugFormat(
138 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
139
140 scene.RegisterModuleInterface<IPresenceService>(this);
141 m_PresenceDetector.AddRegion(scene);
142
143 m_log.InfoFormat("[LOCAL PRESENCE CONNECTOR]: Enabled local presence for region {0}", scene.RegionInfo.RegionName);
144
145 }
146
147 public void RemoveRegion(Scene scene)
148 {
149 if (!m_Enabled)
150 return;
151
152 m_PresenceDetector.RemoveRegion(scene);
153 }
154
155 public void RegionLoaded(Scene scene)
156 {
157 if (!m_Enabled)
158 return;
159
160 }
161
162 #endregion 100 #endregion
163
164 #region IPresenceService
165
166 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
167 {
168 m_log.Warn("[LOCAL PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
169 return false;
170 }
171
172 public bool LogoutAgent(UUID sessionID)
173 {
174 return m_PresenceService.LogoutAgent(sessionID);
175 }
176
177
178 public bool LogoutRegionAgents(UUID regionID)
179 {
180 return m_PresenceService.LogoutRegionAgents(regionID);
181 }
182
183 public bool ReportAgent(UUID sessionID, UUID regionID)
184 {
185 return m_PresenceService.ReportAgent(sessionID, regionID);
186 }
187
188 public PresenceInfo GetAgent(UUID sessionID)
189 {
190 return m_PresenceService.GetAgent(sessionID);
191 }
192
193 public PresenceInfo[] GetAgents(string[] userIDs)
194 {
195 return m_PresenceService.GetAgents(userIDs);
196 }
197
198 #endregion
199
200 } 101 }
201} 102} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
index be73932..6ca5c28 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
@@ -43,22 +43,12 @@ using Nini.Config;
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
44{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemotePresenceServicesConnector")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemotePresenceServicesConnector")]
46 public class RemotePresenceServicesConnector : ISharedRegionModule, IPresenceService 46 public class RemotePresenceServicesConnector : BasePresenceServiceConnector, ISharedRegionModule
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 #region ISharedRegionModule 50 #region ISharedRegionModule
51 51
52 private bool m_Enabled = false;
53
54 private PresenceDetector m_PresenceDetector;
55 private IPresenceService m_RemoteConnector;
56
57 public Type ReplaceableInterface
58 {
59 get { return null; }
60 }
61
62 public string Name 52 public string Name
63 { 53 {
64 get { return "RemotePresenceServicesConnector"; } 54 get { return "RemotePresenceServicesConnector"; }
@@ -72,7 +62,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
72 string name = moduleConfig.GetString("PresenceServices", ""); 62 string name = moduleConfig.GetString("PresenceServices", "");
73 if (name == Name) 63 if (name == Name)
74 { 64 {
75 m_RemoteConnector = new PresenceServicesConnector(source); 65 m_PresenceService = new PresenceServicesConnector(source);
76 66
77 m_Enabled = true; 67 m_Enabled = true;
78 68
@@ -81,81 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
81 m_log.Info("[REMOTE PRESENCE CONNECTOR]: Remote presence enabled"); 71 m_log.Info("[REMOTE PRESENCE CONNECTOR]: Remote presence enabled");
82 } 72 }
83 } 73 }
84
85 }
86
87 public void PostInitialise()
88 {
89 }
90
91 public void Close()
92 {
93 }
94
95 public void AddRegion(Scene scene)
96 {
97 if (!m_Enabled)
98 return;
99
100 scene.RegisterModuleInterface<IPresenceService>(this);
101 m_PresenceDetector.AddRegion(scene);
102
103 m_log.InfoFormat("[REMOTE PRESENCE CONNECTOR]: Enabled remote presence for region {0}", scene.RegionInfo.RegionName);
104
105 }
106
107 public void RemoveRegion(Scene scene)
108 {
109 if (!m_Enabled)
110 return;
111
112 m_PresenceDetector.RemoveRegion(scene);
113 }
114
115 public void RegionLoaded(Scene scene)
116 {
117 if (!m_Enabled)
118 return;
119
120 }
121
122 #endregion
123
124 #region IPresenceService
125
126 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
127 {
128 m_log.Warn("[REMOTE PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
129 return false;
130 }
131
132 public bool LogoutAgent(UUID sessionID)
133 {
134 return m_RemoteConnector.LogoutAgent(sessionID);
135 }
136
137
138 public bool LogoutRegionAgents(UUID regionID)
139 {
140 return m_RemoteConnector.LogoutRegionAgents(regionID);
141 }
142
143 public bool ReportAgent(UUID sessionID, UUID regionID)
144 {
145 return m_RemoteConnector.ReportAgent(sessionID, regionID);
146 }
147
148 public PresenceInfo GetAgent(UUID sessionID)
149 {
150 return m_RemoteConnector.GetAgent(sessionID);
151 }
152
153 public PresenceInfo[] GetAgents(string[] userIDs)
154 {
155 return m_RemoteConnector.GetAgents(userIDs);
156 } 74 }
157 75
158 #endregion 76 #endregion
159
160 } 77 }
161} 78} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
index 4556df3..7e365ca 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -35,7 +35,6 @@ using NUnit.Framework;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using Nini.Config; 37using Nini.Config;
38
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; 38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 40using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
@@ -44,7 +43,7 @@ using OpenSim.Tests.Common;
44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
45{ 44{
46 [TestFixture] 45 [TestFixture]
47 public class PresenceConnectorsTests 46 public class PresenceConnectorsTests : OpenSimTestCase
48 { 47 {
49 LocalPresenceServicesConnector m_LocalConnector; 48 LocalPresenceServicesConnector m_LocalConnector;
50 private void SetUp() 49 private void SetUp()
@@ -56,7 +55,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
56 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService"); 55 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService");
57 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); 56 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
58 57
59 m_LocalConnector = new LocalPresenceServicesConnector(config); 58 m_LocalConnector = new LocalPresenceServicesConnector();
59 m_LocalConnector.Initialise(config);
60 60
61 // Let's stick in a test presence 61 // Let's stick in a test presence
62 m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); 62 m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index ea806ec..c810242 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -552,13 +552,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
552 552
553 // Validate User and Group UUID's 553 // Validate User and Group UUID's
554 554
555 if (!ResolveUserUuid(scene, parcel.OwnerID)) 555 if (parcel.IsGroupOwned)
556 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
557
558 if (!ResolveGroupUuid(parcel.GroupID))
559 { 556 {
560 parcel.GroupID = UUID.Zero; 557 if (!ResolveGroupUuid(parcel.GroupID))
561 parcel.IsGroupOwned = false; 558 {
559 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
560 parcel.GroupID = UUID.Zero;
561 parcel.IsGroupOwned = false;
562 }
563 }
564 else
565 {
566 if (!ResolveUserUuid(scene, parcel.OwnerID))
567 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
568
569 if (!ResolveGroupUuid(parcel.GroupID))
570 parcel.GroupID = UUID.Zero;
562 } 571 }
563 572
564 List<LandAccessEntry> accessList = new List<LandAccessEntry>(); 573 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
@@ -571,8 +580,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
571 parcel.ParcelAccessList = accessList; 580 parcel.ParcelAccessList = accessList;
572 581
573// m_log.DebugFormat( 582// m_log.DebugFormat(
574// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 583// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
575// parcel.Name, parcel.LocalID, parcel.Area); 584// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
576 585
577 landData.Add(parcel); 586 landData.Add(parcel);
578 } 587 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index d751b1c..7bdd65c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -167,7 +167,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
167 } 167 }
168 scenesGroup.CalcSceneLocations(); 168 scenesGroup.CalcSceneLocations();
169 169
170
171 m_archiveWriter = new TarArchiveWriter(m_saveStream); 170 m_archiveWriter = new TarArchiveWriter(m_saveStream);
172 171
173 try 172 try
@@ -216,7 +215,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 215 }
217 } 216 }
218 217
219
220 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 218 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
221 { 219 {
222 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 220 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
@@ -540,7 +538,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
540 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 538 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
541 } 539 }
542 540
543
544 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir) 541 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
545 { 542 {
546 if (regionDir != string.Empty) 543 if (regionDir != string.Empty)
@@ -560,8 +557,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
560 foreach (ILandObject lo in landObjects) 557 foreach (ILandObject lo in landObjects)
561 { 558 {
562 LandData landData = lo.LandData; 559 LandData landData = lo.LandData;
563 string landDataPath = String.Format("{0}{1}{2}.xml", 560 string landDataPath
564 regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); 561 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData));
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); 562 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 } 563 }
567 564
@@ -604,7 +601,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
604 601
605 CloseArchive(String.Empty); 602 CloseArchive(String.Empty);
606 } 603 }
607
608 604
609 /// <summary> 605 /// <summary>
610 /// Closes the archive and notifies that we're done. 606 /// Closes the archive and notifies that we're done.
@@ -629,6 +625,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver
629 625
630 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); 626 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
631 } 627 }
632
633 } 628 }
634} 629} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 82f49b0..eec1cec 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -31,16 +31,19 @@ using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Threading; 32using System.Threading;
33using log4net.Config; 33using log4net.Config;
34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Serialization; 39using OpenSim.Framework.Serialization;
39using OpenSim.Framework.Serialization.External; 40using OpenSim.Framework.Serialization.External;
41using OpenSim.Region.CoreModules.World.Land;
40using OpenSim.Region.CoreModules.World.Serialiser; 42using OpenSim.Region.CoreModules.World.Serialiser;
41using OpenSim.Region.CoreModules.World.Terrain; 43using OpenSim.Region.CoreModules.World.Terrain;
42using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 45using OpenSim.Region.Framework.Scenes.Serialization;
46using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
44using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
45using OpenSim.Tests.Common.Mock; 48using OpenSim.Tests.Common.Mock;
46using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; 49using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
@@ -69,9 +72,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
69 { 72 {
70 base.SetUp(); 73 base.SetUp();
71 74
72 // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
73 new SceneManager();
74
75 m_archiverModule = new ArchiverModule(); 75 m_archiverModule = new ArchiverModule();
76 m_serialiserModule = new SerialiserModule(); 76 m_serialiserModule = new SerialiserModule();
77 TerrainModule terrainModule = new TerrainModule(); 77 TerrainModule terrainModule = new TerrainModule();
@@ -127,6 +127,53 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
127 127
128 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; 128 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
129 } 129 }
130
131 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
132 {
133 SceneObjectPart part1 = CreateSceneObjectPart1();
134 sog1 = new SceneObjectGroup(part1);
135 scene.AddNewSceneObject(sog1, false);
136
137 AssetNotecard nc = new AssetNotecard();
138 nc.BodyText = "Hello World!";
139 nc.Encode();
140 ncAssetUuid = UUID.Random();
141 UUID ncItemUuid = UUID.Random();
142 AssetBase ncAsset
143 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
144 m_scene.AssetService.Store(ncAsset);
145
146 TaskInventoryItem ncItem
147 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
148 SceneObjectPart part2 = CreateSceneObjectPart2();
149 sog2 = new SceneObjectGroup(part2);
150 part2.Inventory.AddInventoryItem(ncItem, true);
151
152 scene.AddNewSceneObject(sog2, false);
153 }
154
155 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
156 {
157 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
158 {
159 using (BinaryReader br = new BinaryReader(resource))
160 {
161 // FIXME: Use the inspector instead
162 soundData = br.ReadBytes(99999999);
163 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
164 string soundAssetFileName
165 = ArchiveConstants.ASSETS_PATH + soundUuid
166 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
167 tar.WriteFile(soundAssetFileName, soundData);
168
169 /*
170 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
171 scene.AssetService.Store(soundAsset);
172 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
173 */
174 }
175 }
176 }
130 177
131 /// <summary> 178 /// <summary>
132 /// Test saving an OpenSim Region Archive. 179 /// Test saving an OpenSim Region Archive.
@@ -204,30 +251,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
204 // TODO: Test presence of more files and contents of files. 251 // TODO: Test presence of more files and contents of files.
205 } 252 }
206 253
207 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
208 {
209 SceneObjectPart part1 = CreateSceneObjectPart1();
210 sog1 = new SceneObjectGroup(part1);
211 scene.AddNewSceneObject(sog1, false);
212
213 AssetNotecard nc = new AssetNotecard();
214 nc.BodyText = "Hello World!";
215 nc.Encode();
216 ncAssetUuid = UUID.Random();
217 UUID ncItemUuid = UUID.Random();
218 AssetBase ncAsset
219 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
220 m_scene.AssetService.Store(ncAsset);
221
222 TaskInventoryItem ncItem
223 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
224 SceneObjectPart part2 = CreateSceneObjectPart2();
225 sog2 = new SceneObjectGroup(part2);
226 part2.Inventory.AddInventoryItem(ncItem, true);
227
228 scene.AddNewSceneObject(sog2, false);
229 }
230
231 /// <summary> 254 /// <summary>
232 /// Test saving an OpenSim Region Archive with the no assets option 255 /// Test saving an OpenSim Region Archive with the no assets option
233 /// </summary> 256 /// </summary>
@@ -309,59 +332,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
309 } 332 }
310 333
311 /// <summary> 334 /// <summary>
312 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
313 /// 2 can come after 3).
314 /// </summary>
315 [Test]
316 public void TestLoadOarUnorderedParts()
317 {
318 TestHelpers.InMethod();
319
320 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
321
322 MemoryStream archiveWriteStream = new MemoryStream();
323 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
324
325 tar.WriteFile(
326 ArchiveConstants.CONTROL_FILE_PATH,
327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
328
329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
330 SceneObjectPart sop2
331 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
332 SceneObjectPart sop3
333 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
334
335 // Add the parts so they will be written out in reverse order to the oar
336 sog1.AddPart(sop3);
337 sop3.LinkNum = 3;
338 sog1.AddPart(sop2);
339 sop2.LinkNum = 2;
340
341 tar.WriteFile(
342 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
343 SceneObjectSerializer.ToXml2Format(sog1));
344
345 tar.Close();
346
347 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
348
349 lock (this)
350 {
351 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
352 m_archiverModule.DearchiveRegion(archiveReadStream);
353 }
354
355 Assert.That(m_lastErrorMessage, Is.Null);
356
357 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
358 Assert.That(part2.LinkNum, Is.EqualTo(2));
359
360 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
361 Assert.That(part3.LinkNum, Is.EqualTo(3));
362 }
363
364 /// <summary>
365 /// Test loading an OpenSim Region Archive. 335 /// Test loading an OpenSim Region Archive.
366 /// </summary> 336 /// </summary>
367 [Test] 337 [Test]
@@ -435,50 +405,57 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
435 TestLoadedRegion(part1, soundItemName, soundData); 405 TestLoadedRegion(part1, soundItemName, soundData);
436 } 406 }
437 407
438 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) 408 /// <summary>
409 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
410 /// 2 can come after 3).
411 /// </summary>
412 [Test]
413 public void TestLoadOarUnorderedParts()
439 { 414 {
440 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) 415 TestHelpers.InMethod();
441 {
442 using (BinaryReader br = new BinaryReader(resource))
443 {
444 // FIXME: Use the inspector instead
445 soundData = br.ReadBytes(99999999);
446 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
447 string soundAssetFileName
448 = ArchiveConstants.ASSETS_PATH + soundUuid
449 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
450 tar.WriteFile(soundAssetFileName, soundData);
451 416
452 /* 417 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
453 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
454 scene.AssetService.Store(soundAsset);
455 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
456 */
457 }
458 }
459 }
460 418
461 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) 419 MemoryStream archiveWriteStream = new MemoryStream();
462 { 420 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
464 421
465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 422 tar.WriteFile(
466 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); 423 ArchiveConstants.CONTROL_FILE_PATH,
467 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); 424 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
468 Assert.That(
469 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
470 Assert.That(
471 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
472 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
473 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
474 425
475 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; 426 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
476 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); 427 SceneObjectPart sop2
477 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); 428 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
478 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); 429 SceneObjectPart sop3
479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 430 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
480 431
481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 432 // Add the parts so they will be written out in reverse order to the oar
433 sog1.AddPart(sop3);
434 sop3.LinkNum = 3;
435 sog1.AddPart(sop2);
436 sop2.LinkNum = 2;
437
438 tar.WriteFile(
439 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
440 SceneObjectSerializer.ToXml2Format(sog1));
441
442 tar.Close();
443
444 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
445
446 lock (this)
447 {
448 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
449 m_archiverModule.DearchiveRegion(archiveReadStream);
450 }
451
452 Assert.That(m_lastErrorMessage, Is.Null);
453
454 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
455 Assert.That(part2.LinkNum, Is.EqualTo(2));
456
457 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
458 Assert.That(part3.LinkNum, Is.EqualTo(3));
482 } 459 }
483 460
484 /// <summary> 461 /// <summary>
@@ -538,8 +515,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
538 SerialiserModule serialiserModule = new SerialiserModule(); 515 SerialiserModule serialiserModule = new SerialiserModule();
539 TerrainModule terrainModule = new TerrainModule(); 516 TerrainModule terrainModule = new TerrainModule();
540 517
541 m_sceneHelpers = new SceneHelpers(); 518 SceneHelpers m_sceneHelpers2 = new SceneHelpers();
542 TestScene scene2 = m_sceneHelpers.SetupScene(); 519 TestScene scene2 = m_sceneHelpers2.SetupScene();
543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
544 521
545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -563,6 +540,71 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
563 } 540 }
564 541
565 /// <summary> 542 /// <summary>
543 /// Test OAR loading where the land parcel is group deeded.
544 /// </summary>
545 /// <remarks>
546 /// In this situation, the owner ID is set to the group ID.
547 /// </remarks>
548 [Test]
549 public void TestLoadOarDeededLand()
550 {
551 TestHelpers.InMethod();
552// TestHelpers.EnableLogging();
553
554 UUID landID = TestHelpers.ParseTail(0x10);
555
556 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector();
557
558 IConfigSource configSource = new IniConfigSource();
559 IConfig config = configSource.AddConfig("Groups");
560 config.Set("Enabled", true);
561 config.Set("Module", "GroupsModule");
562 config.Set("DebugEnabled", true);
563 SceneHelpers.SetupSceneModules(
564 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() });
565
566 // Create group in scene for loading
567 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests.
568 UUID groupID
569 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero);
570
571 // Construct OAR
572 MemoryStream oarStream = new MemoryStream();
573 TarArchiveWriter tar = new TarArchiveWriter(oarStream);
574
575 tar.WriteDir(ArchiveConstants.LANDDATA_PATH);
576 tar.WriteFile(
577 ArchiveConstants.CONTROL_FILE_PATH,
578 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
579
580 LandObject lo = new LandObject(groupID, true, null);
581 lo.SetLandBitmap(lo.BasicFullRegionLandBitmap());
582 LandData ld = lo.LandData;
583 ld.GlobalID = landID;
584
585 string ldPath = ArchiveConstants.CreateOarLandDataPath(ld);
586 tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null));
587 tar.Close();
588
589 oarStream = new MemoryStream(oarStream.ToArray());
590
591 // Load OAR
592 lock (this)
593 {
594 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
595 m_archiverModule.DearchiveRegion(oarStream);
596 }
597
598 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
599 LandData rLd = rLo.LandData;
600
601 Assert.That(rLd.GlobalID, Is.EqualTo(landID));
602 Assert.That(rLd.OwnerID, Is.EqualTo(groupID));
603 Assert.That(rLd.GroupID, Is.EqualTo(groupID));
604 Assert.That(rLd.IsGroupOwned, Is.EqualTo(true));
605 }
606
607 /// <summary>
566 /// Test loading the region settings of an OpenSim Region Archive. 608 /// Test loading the region settings of an OpenSim Region Archive.
567 /// </summary> 609 /// </summary>
568 [Test] 610 [Test]
@@ -781,9 +823,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
781 } 823 }
782 } 824 }
783 825
784
785 // Save OAR 826 // Save OAR
786
787 MemoryStream archiveWriteStream = new MemoryStream(); 827 MemoryStream archiveWriteStream = new MemoryStream();
788 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 828 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
789 829
@@ -800,7 +840,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
800 840
801 841
802 // Check that the OAR contains the expected data 842 // Check that the OAR contains the expected data
803
804 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 843 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
805 844
806 byte[] archive = archiveWriteStream.ToArray(); 845 byte[] archive = archiveWriteStream.ToArray();
@@ -892,7 +931,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
892 } 931 }
893 932
894 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); 933 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
895 SceneManager.Instance.ForEachScene(delegate(Scene scene) 934 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
896 { 935 {
897 scenesGroup.AddScene(scene); 936 scenesGroup.AddScene(scene);
898 }); 937 });
@@ -950,13 +989,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
950 989
951 // Delete the current objects, to test that they're loaded from the OAR and didn't 990 // Delete the current objects, to test that they're loaded from the OAR and didn't
952 // just remain in the scene. 991 // just remain in the scene.
953 SceneManager.Instance.ForEachScene(delegate(Scene scene) 992 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
954 { 993 {
955 scene.DeleteAllSceneObjects(); 994 scene.DeleteAllSceneObjects();
956 }); 995 });
957 996
958 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR 997 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
959 SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); 998 m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]);
960 999
961 1000
962 // Check thay the OAR file contains the expected data 1001 // Check thay the OAR file contains the expected data
@@ -971,10 +1010,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
971 1010
972 Assert.That(m_lastErrorMessage, Is.Null); 1011 Assert.That(m_lastErrorMessage, Is.Null);
973 1012
974 Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); 1013 Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count);
975 1014
976 TestLoadedRegion(part1, soundItemName, soundData); 1015 TestLoadedRegion(part1, soundItemName, soundData);
977 } 1016 }
978 1017
1018 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
1019 {
1020 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
1021
1022 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
1023 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
1024 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
1025 Assert.That(
1026 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
1027 Assert.That(
1028 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
1029 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
1030 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
1031
1032 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
1033 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
1034 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString());
1035 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null");
1036 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
1037
1038 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
1039 }
979 } 1040 }
980} 1041} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 39cc93d..eb06fcc 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -53,6 +53,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
53 53
54 protected EstateManagementCommands m_commands; 54 protected EstateManagementCommands m_commands;
55 55
56 /// <summary>
57 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate.
58 /// </summary>
59 public bool AllowRegionRestartFromClient { get; set; }
60
56 private EstateTerrainXferHandler TerrainUploader; 61 private EstateTerrainXferHandler TerrainUploader;
57 public TelehubManager m_Telehub; 62 public TelehubManager m_Telehub;
58 63
@@ -60,6 +65,53 @@ namespace OpenSim.Region.CoreModules.World.Estate
60 public event ChangeDelegate OnEstateInfoChange; 65 public event ChangeDelegate OnEstateInfoChange;
61 public event MessageDelegate OnEstateMessage; 66 public event MessageDelegate OnEstateMessage;
62 67
68 #region Region Module interface
69
70 public string Name { get { return "EstateManagementModule"; } }
71
72 public Type ReplaceableInterface { get { return null; } }
73
74 public void Initialise(IConfigSource source)
75 {
76 AllowRegionRestartFromClient = true;
77
78 IConfig config = source.Configs["EstateManagement"];
79
80 if (config != null)
81 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true);
82 }
83
84 public void AddRegion(Scene scene)
85 {
86 Scene = scene;
87 Scene.RegisterModuleInterface<IEstateModule>(this);
88 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
89 Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
90
91 m_Telehub = new TelehubManager(scene);
92
93 m_commands = new EstateManagementCommands(this);
94 m_commands.Initialise();
95 }
96
97 public void RemoveRegion(Scene scene) {}
98
99 public void RegionLoaded(Scene scene)
100 {
101 // Sets up the sun module based no the saved Estate and Region Settings
102 // DO NOT REMOVE or the sun will stop working
103 scene.TriggerEstateSunUpdate();
104
105 UserManager = scene.RequestModuleInterface<IUserManagement>();
106 }
107
108 public void Close()
109 {
110 m_commands.Close();
111 }
112
113 #endregion
114
63 #region Packet Data Responders 115 #region Packet Data Responders
64 116
65 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) 117 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice)
@@ -184,6 +236,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
184 Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; 236 Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
185 break; 237 break;
186 } 238 }
239
187 Scene.RegionInfo.RegionSettings.Save(); 240 Scene.RegionInfo.RegionSettings.Save();
188 TriggerRegionInfoChange(); 241 TriggerRegionInfoChange();
189 sendRegionInfoPacketToAll(); 242 sendRegionInfoPacketToAll();
@@ -215,6 +268,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
215 Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; 268 Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
216 break; 269 break;
217 } 270 }
271
218 Scene.RegionInfo.RegionSettings.Save(); 272 Scene.RegionInfo.RegionSettings.Save();
219 TriggerRegionInfoChange(); 273 TriggerRegionInfoChange();
220 sendRegionHandshakeToAll(); 274 sendRegionHandshakeToAll();
@@ -255,6 +309,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
255 309
256 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) 310 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds)
257 { 311 {
312 if (!AllowRegionRestartFromClient)
313 {
314 remoteClient.SendAlertMessage("Region restart has been disabled on this simulator.");
315 return;
316 }
317
258 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 318 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
259 if (restartModule != null) 319 if (restartModule != null)
260 { 320 {
@@ -271,6 +331,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
271 } 331 }
272 332
273 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); 333 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true);
334
335 m_log.InfoFormat(
336 "User {0} requested restart of region {1} in {2} seconds",
337 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0);
274 } 338 }
275 } 339 }
276 340
@@ -295,7 +359,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
295 359
296 if ((estateAccessType & 4) != 0) // User add 360 if ((estateAccessType & 4) != 0) // User add
297 { 361 {
298 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 362 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
299 { 363 {
300 if ((estateAccessType & 1) != 0) // All estates 364 if ((estateAccessType & 1) != 0) // All estates
301 { 365 {
@@ -325,9 +389,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
325 } 389 }
326 390
327 } 391 }
392
328 if ((estateAccessType & 8) != 0) // User remove 393 if ((estateAccessType & 8) != 0) // User remove
329 { 394 {
330 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 395 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
331 { 396 {
332 if ((estateAccessType & 1) != 0) // All estates 397 if ((estateAccessType & 1) != 0) // All estates
333 { 398 {
@@ -356,9 +421,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
356 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 421 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
357 } 422 }
358 } 423 }
424
359 if ((estateAccessType & 16) != 0) // Group add 425 if ((estateAccessType & 16) != 0) // Group add
360 { 426 {
361 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 427 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
362 { 428 {
363 if ((estateAccessType & 1) != 0) // All estates 429 if ((estateAccessType & 1) != 0) // All estates
364 { 430 {
@@ -387,9 +453,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
387 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 453 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
388 } 454 }
389 } 455 }
456
390 if ((estateAccessType & 32) != 0) // Group remove 457 if ((estateAccessType & 32) != 0) // Group remove
391 { 458 {
392 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 459 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
393 { 460 {
394 if ((estateAccessType & 1) != 0) // All estates 461 if ((estateAccessType & 1) != 0) // All estates
395 { 462 {
@@ -418,9 +485,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
418 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 485 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
419 } 486 }
420 } 487 }
488
421 if ((estateAccessType & 64) != 0) // Ban add 489 if ((estateAccessType & 64) != 0) // Ban add
422 { 490 {
423 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || Scene.Permissions.BypassPermissions()) 491 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
424 { 492 {
425 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 493 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
426 494
@@ -495,9 +563,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
495 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 563 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
496 } 564 }
497 } 565 }
566
498 if ((estateAccessType & 128) != 0) // Ban remove 567 if ((estateAccessType & 128) != 0) // Ban remove
499 { 568 {
500 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || Scene.Permissions.BypassPermissions()) 569 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
501 { 570 {
502 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 571 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
503 572
@@ -550,9 +619,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
550 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 619 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
551 } 620 }
552 } 621 }
622
553 if ((estateAccessType & 256) != 0) // Manager add 623 if ((estateAccessType & 256) != 0) // Manager add
554 { 624 {
555 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 625 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
556 { 626 {
557 if ((estateAccessType & 1) != 0) // All estates 627 if ((estateAccessType & 1) != 0) // All estates
558 { 628 {
@@ -581,9 +651,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
581 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 651 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
582 } 652 }
583 } 653 }
654
584 if ((estateAccessType & 512) != 0) // Manager remove 655 if ((estateAccessType & 512) != 0) // Manager remove
585 { 656 {
586 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 657 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
587 { 658 {
588 if ((estateAccessType & 1) != 0) // All estates 659 if ((estateAccessType & 1) != 0) // All estates
589 { 660 {
@@ -614,7 +685,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
614 } 685 }
615 } 686 }
616 687
617 public void handleOnEstateManageTelehub (IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 688 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
618 { 689 {
619 SceneObjectPart part; 690 SceneObjectPart part;
620 691
@@ -1072,45 +1143,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
1072 1143
1073 #endregion 1144 #endregion
1074 1145
1075 #region Region Module interface
1076
1077 public string Name { get { return "EstateManagementModule"; } }
1078
1079 public Type ReplaceableInterface { get { return null; } }
1080
1081 public void Initialise(IConfigSource source) {}
1082
1083 public void AddRegion(Scene scene)
1084 {
1085 Scene = scene;
1086 Scene.RegisterModuleInterface<IEstateModule>(this);
1087 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
1088 Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
1089
1090 m_Telehub = new TelehubManager(scene);
1091
1092 m_commands = new EstateManagementCommands(this);
1093 m_commands.Initialise();
1094 }
1095
1096 public void RemoveRegion(Scene scene) {}
1097
1098 public void RegionLoaded(Scene scene)
1099 {
1100 // Sets up the sun module based no the saved Estate and Region Settings
1101 // DO NOT REMOVE or the sun will stop working
1102 scene.TriggerEstateSunUpdate();
1103
1104 UserManager = scene.RequestModuleInterface<IUserManagement>();
1105 }
1106
1107 public void Close()
1108 {
1109 m_commands.Close();
1110 }
1111
1112 #endregion
1113
1114 #region Other Functions 1146 #region Other Functions
1115 1147
1116 public void changeWaterHeight(float height) 1148 public void changeWaterHeight(float height)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 8682798..7149aad 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -1378,10 +1378,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1378 1378
1379 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1379 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1380 { 1380 {
1381// m_log.DebugFormat(
1382// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name);
1383
1381 for (int i = 0; i < data.Count; i++) 1384 for (int i = 0; i < data.Count; i++)
1382 {
1383 IncomingLandObjectFromStorage(data[i]); 1385 IncomingLandObjectFromStorage(data[i]);
1384 }
1385 } 1386 }
1386 1387
1387 public void IncomingLandObjectFromStorage(LandData data) 1388 public void IncomingLandObjectFromStorage(LandData data)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 8829f27..5969d45 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -727,9 +727,10 @@ namespace OpenSim.Region.CoreModules.World.Land
727 int ty = min_y * 4; 727 int ty = min_y * 4;
728 if (ty > ((int)Constants.RegionSize - 1)) 728 if (ty > ((int)Constants.RegionSize - 1))
729 ty = ((int)Constants.RegionSize - 1); 729 ty = ((int)Constants.RegionSize - 1);
730
730 LandData.AABBMin = 731 LandData.AABBMin =
731 new Vector3((float) (min_x * 4), (float) (min_y * 4), 732 new Vector3(
732 (float) m_scene.Heightmap[tx, ty]); 733 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
733 734
734 tx = max_x * 4; 735 tx = max_x * 4;
735 if (tx > ((int)Constants.RegionSize - 1)) 736 if (tx > ((int)Constants.RegionSize - 1))
@@ -737,9 +738,11 @@ namespace OpenSim.Region.CoreModules.World.Land
737 ty = max_y * 4; 738 ty = max_y * 4;
738 if (ty > ((int)Constants.RegionSize - 1)) 739 if (ty > ((int)Constants.RegionSize - 1))
739 ty = ((int)Constants.RegionSize - 1); 740 ty = ((int)Constants.RegionSize - 1);
740 LandData.AABBMax = 741
741 new Vector3((float) (max_x * 4), (float) (max_y * 4), 742 LandData.AABBMax
742 (float) m_scene.Heightmap[tx, ty]); 743 = new Vector3(
744 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
745
743 LandData.Area = tempArea; 746 LandData.Area = tempArea;
744 } 747 }
745 748
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index b5ee4d2..14eca42 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common.Mock;
41namespace OpenSim.Region.CoreModules.World.Land.Tests 41namespace OpenSim.Region.CoreModules.World.Land.Tests
42{ 42{
43 [TestFixture] 43 [TestFixture]
44 public class PrimCountModuleTests 44 public class PrimCountModuleTests : OpenSimTestCase
45 { 45 {
46 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); 46 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000");
47 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); 47 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000");
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index 396095a..ba4b041 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests 44namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class MoapTests 47 public class MoapTests : OpenSimTestCase
48 { 48 {
49 protected TestScene m_scene; 49 protected TestScene m_scene;
50 protected MoapModule m_module; 50 protected MoapModule m_module;
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index fea4de0..249a40d 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Linq;
29using System.Reflection; 30using System.Reflection;
30using System.Timers; 31using System.Timers;
31using System.Threading; 32using System.Threading;
@@ -264,7 +265,10 @@ namespace OpenSim.Region.CoreModules.World.Region
264 for (int i = 4 ; i < args.Length ; i++) 265 for (int i = 4 ; i < args.Length ; i++)
265 times.Add(Convert.ToInt32(args[i])); 266 times.Add(Convert.ToInt32(args[i]));
266 267
268 MainConsole.Instance.OutputFormat(
269 "Region {0} scheduled for restart in {1} seconds", m_Scene.Name, times.Sum());
270
267 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 271 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
268 } 272 }
269 } 273 }
270} 274} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index 7825e3e..bcb8e2f 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common;
39namespace OpenSim.Region.CoreModules.World.Serialiser.Tests 39namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
40{ 40{
41 [TestFixture] 41 [TestFixture]
42 public class SerialiserTests 42 public class SerialiserTests : OpenSimTestCase
43 { 43 {
44 private string xml = @" 44 private string xml = @"
45 <SceneObjectGroup> 45 <SceneObjectGroup>
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 513a8f5..089fcda 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -43,8 +43,8 @@ namespace OpenSim.Region.CoreModules.World.Sound
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
44 public class SoundModule : INonSharedRegionModule, ISoundModule 44 public class SoundModule : INonSharedRegionModule, ISoundModule
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger( 46// private static readonly ILog m_log = LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType); 47// MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 3d4f762..be719ea 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -30,11 +30,12 @@ using NUnit.Framework;
30using OpenSim.Framework; 30using OpenSim.Framework;
31using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; 31using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
32using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Tests.Common;
33 34
34namespace OpenSim.Region.CoreModules.World.Terrain.Tests 35namespace OpenSim.Region.CoreModules.World.Terrain.Tests
35{ 36{
36 [TestFixture] 37 [TestFixture]
37 public class TerrainTest 38 public class TerrainTest : OpenSimTestCase
38 { 39 {
39 [Test] 40 [Test]
40 public void BrushTest() 41 public void BrushTest()
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index fd8e2b4..9de588c 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules
66 public void Initialise(IConfigSource config) 66 public void Initialise(IConfigSource config)
67 { 67 {
68 m_windConfig = config.Configs["Wind"]; 68 m_windConfig = config.Configs["Wind"];
69 string desiredWindPlugin = m_dWindPluginName; 69// string desiredWindPlugin = m_dWindPluginName;
70 70
71 if (m_windConfig != null) 71 if (m_windConfig != null)
72 { 72 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index db45d6b..1ad5edd 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -740,7 +740,12 @@ namespace OpenSim.Region.Framework.Scenes
740 // 740 //
741 // Out of memory 741 // Out of memory
742 // Operating system has killed the plugin 742 // Operating system has killed the plugin
743 m_sceneGraph.UnRecoverableError += RestartNow; 743 m_sceneGraph.UnRecoverableError
744 += () =>
745 {
746 m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name);
747 RestartNow();
748 };
744 749
745 RegisterDefaultSceneEvents(); 750 RegisterDefaultSceneEvents();
746 751
@@ -1134,15 +1139,9 @@ namespace OpenSim.Region.Framework.Scenes
1134 } 1139 }
1135 } 1140 }
1136 1141
1137 m_log.Error("[REGION]: Closing"); 1142 m_log.InfoFormat("[REGION]: Restarting region {0}", Name);
1138 Close();
1139 1143
1140 if (PhysicsScene != null) 1144 Close();
1141 {
1142 PhysicsScene.Dispose();
1143 }
1144
1145 m_log.Error("[REGION]: Firing Region Restart Message");
1146 1145
1147 base.Restart(); 1146 base.Restart();
1148 } 1147 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 9bd27d3..1e2e973 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -100,23 +100,25 @@ namespace OpenSim.Region.Framework.Scenes
100 } 100 }
101 101
102 private readonly List<Scene> m_localScenes = new List<Scene>(); 102 private readonly List<Scene> m_localScenes = new List<Scene>();
103 private Scene m_currentScene = null;
104 103
105 public List<Scene> Scenes 104 public List<Scene> Scenes
106 { 105 {
107 get { return new List<Scene>(m_localScenes); } 106 get { return new List<Scene>(m_localScenes); }
108 } 107 }
109 108
110 public Scene CurrentScene 109 /// <summary>
111 { 110 /// Scene selected from the console.
112 get { return m_currentScene; } 111 /// </summary>
113 } 112 /// <value>
113 /// If null, then all scenes are considered selected (signalled as "Root" on the console).
114 /// </value>
115 public Scene CurrentScene { get; private set; }
114 116
115 public Scene CurrentOrFirstScene 117 public Scene CurrentOrFirstScene
116 { 118 {
117 get 119 get
118 { 120 {
119 if (m_currentScene == null) 121 if (CurrentScene == null)
120 { 122 {
121 lock (m_localScenes) 123 lock (m_localScenes)
122 { 124 {
@@ -128,7 +130,7 @@ namespace OpenSim.Region.Framework.Scenes
128 } 130 }
129 else 131 else
130 { 132 {
131 return m_currentScene; 133 return CurrentScene;
132 } 134 }
133 } 135 }
134 } 136 }
@@ -141,6 +143,13 @@ namespace OpenSim.Region.Framework.Scenes
141 143
142 public void Close() 144 public void Close()
143 { 145 {
146 lock (m_localScenes)
147 {
148 for (int i = 0; i < m_localScenes.Count; i++)
149 {
150 m_localScenes[i].Close();
151 }
152 }
144 } 153 }
145 154
146 public void Close(Scene cscene) 155 public void Close(Scene cscene)
@@ -171,8 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
171 180
172 public void HandleRestart(RegionInfo rdata) 181 public void HandleRestart(RegionInfo rdata)
173 { 182 {
174 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 183 Scene restartedScene = null;
175 int RegionSceneElement = -1;
176 184
177 lock (m_localScenes) 185 lock (m_localScenes)
178 { 186 {
@@ -180,19 +188,18 @@ namespace OpenSim.Region.Framework.Scenes
180 { 188 {
181 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName) 189 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
182 { 190 {
183 RegionSceneElement = i; 191 restartedScene = m_localScenes[i];
192 m_localScenes.RemoveAt(i);
193 break;
184 } 194 }
185 } 195 }
186
187 // Now we make sure the region is no longer known about by the SceneManager
188 // Prevents duplicates.
189
190 if (RegionSceneElement >= 0)
191 {
192 m_localScenes.RemoveAt(RegionSceneElement);
193 }
194 } 196 }
195 197
198 // If the currently selected scene has been restarted, then we can't reselect here since we the scene
199 // hasn't yet been recreated. We will have to leave this to the caller.
200 if (CurrentScene == restartedScene)
201 CurrentScene = null;
202
196 // Send signal to main that we're restarting this sim. 203 // Send signal to main that we're restarting this sim.
197 OnRestartSim(rdata); 204 OnRestartSim(rdata);
198 } 205 }
@@ -334,14 +341,14 @@ namespace OpenSim.Region.Framework.Scenes
334 341
335 private void ForEachCurrentScene(Action<Scene> func) 342 private void ForEachCurrentScene(Action<Scene> func)
336 { 343 {
337 if (m_currentScene == null) 344 if (CurrentScene == null)
338 { 345 {
339 lock (m_localScenes) 346 lock (m_localScenes)
340 m_localScenes.ForEach(func); 347 m_localScenes.ForEach(func);
341 } 348 }
342 else 349 else
343 { 350 {
344 func(m_currentScene); 351 func(CurrentScene);
345 } 352 }
346 } 353 }
347 354
@@ -361,7 +368,7 @@ namespace OpenSim.Region.Framework.Scenes
361 || (String.Compare(regionName, "..") == 0) 368 || (String.Compare(regionName, "..") == 0)
362 || (String.Compare(regionName, "/") == 0)) 369 || (String.Compare(regionName, "/") == 0))
363 { 370 {
364 m_currentScene = null; 371 CurrentScene = null;
365 return true; 372 return true;
366 } 373 }
367 else 374 else
@@ -372,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
372 { 379 {
373 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0) 380 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
374 { 381 {
375 m_currentScene = scene; 382 CurrentScene = scene;
376 return true; 383 return true;
377 } 384 }
378 } 385 }
@@ -392,7 +399,7 @@ namespace OpenSim.Region.Framework.Scenes
392 { 399 {
393 if (scene.RegionInfo.RegionID == regionID) 400 if (scene.RegionInfo.RegionID == regionID)
394 { 401 {
395 m_currentScene = scene; 402 CurrentScene = scene;
396 return true; 403 return true;
397 } 404 }
398 } 405 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 96bca3e..6f36c0b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1698,8 +1698,16 @@ namespace OpenSim.Region.Framework.Scenes
1698// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}", 1698// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
1699// Name, pos, m_scene.RegionInfo.RegionName); 1699// Name, pos, m_scene.RegionInfo.RegionName);
1700 1700
1701 if (pos.X < 0 || pos.X >= Constants.RegionSize 1701 // Allow move to another sub-region within a megaregion
1702 || pos.Y < 0 || pos.Y >= Constants.RegionSize 1702 Vector2 regionSize;
1703 IRegionCombinerModule regionCombinerModule = m_scene.RequestModuleInterface<IRegionCombinerModule>();
1704 if (regionCombinerModule != null)
1705 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
1706 else
1707 regionSize = new Vector2(Constants.RegionSize);
1708
1709 if (pos.X < 0 || pos.X >= regionSize.X
1710 || pos.Y < 0 || pos.Y >= regionSize.Y
1703 || pos.Z < 0) 1711 || pos.Z < 0)
1704 return; 1712 return;
1705 1713
@@ -1713,7 +1721,16 @@ namespace OpenSim.Region.Framework.Scenes
1713// pos.Z = AbsolutePosition.Z; 1721// pos.Z = AbsolutePosition.Z;
1714// } 1722// }
1715 1723
1716 float terrainHeight = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1724 // Get terrain height for sub-region in a megaregion if necessary
1725 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
1726 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
1727 UUID target_regionID = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y).RegionID;
1728 Scene targetScene = m_scene;
1729
1730 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
1731 targetScene = m_scene;
1732
1733 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
1717 pos.Z = Math.Max(terrainHeight, pos.Z); 1734 pos.Z = Math.Max(terrainHeight, pos.Z);
1718 1735
1719 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 1736 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
diff --git a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
index 4a21dc9..e209221 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Region.Framework.Scenes.Tests 37namespace OpenSim.Region.Framework.Scenes.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class BorderTests 40 public class BorderTests : OpenSimTestCase
41 { 41 {
42 [Test] 42 [Test]
43 public void TestCross() 43 public void TestCross()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
index ea9fc93..766ce83 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common;
41namespace OpenSim.Region.Framework.Scenes.Tests 41namespace OpenSim.Region.Framework.Scenes.Tests
42{ 42{
43 [TestFixture, LongRunning] 43 [TestFixture, LongRunning]
44 public class EntityManagerTests 44 public class EntityManagerTests : OpenSimTestCase
45 { 45 {
46 static public Random random; 46 static public Random random;
47 SceneObjectGroup found; 47 SceneObjectGroup found;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index d23c965..575a081 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneGraphTests 43 public class SceneGraphTests : OpenSimTestCase
44 { 44 {
45 [Test] 45 [Test]
46 public void TestDuplicateObject() 46 public void TestDuplicateObject()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
new file mode 100644
index 0000000..2d831fa
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
@@ -0,0 +1,58 @@
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 System.Threading;
32using NUnit.Framework;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces;
38using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock;
40
41namespace OpenSim.Region.Framework.Scenes.Tests
42{
43 [TestFixture]
44 public class SceneManagerTests : OpenSimTestCase
45 {
46 [Test]
47 public void TestClose()
48 {
49 TestHelpers.InMethod();
50
51 SceneHelpers sh = new SceneHelpers();
52 Scene scene = sh.SetupScene();
53
54 sh.SceneManager.Close();
55 Assert.That(scene.ShuttingDown, Is.True);
56 }
57 }
58} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 5b334c6..a07d64c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
32using NUnit.Framework; 33using NUnit.Framework;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -182,6 +183,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
182 /// <summary> 183 /// <summary>
183 /// Test deleting an object from a scene. 184 /// Test deleting an object from a scene.
184 /// </summary> 185 /// </summary>
186 /// <remarks>
187 /// This is the most basic form of delete. For all more sophisticated forms of derez (done asynchrnously
188 /// and where object can be taken to user inventory, etc.), see SceneObjectDeRezTests.
189 /// </remarks>
185 [Test] 190 [Test]
186 public void TestDeleteSceneObject() 191 public void TestDeleteSceneObject()
187 { 192 {
@@ -201,100 +206,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
201 } 206 }
202 207
203 /// <summary> 208 /// <summary>
204 /// Test deleting an object asynchronously
205 /// </summary>
206 [Test]
207 public void TestDeleteSceneObjectAsync()
208 {
209 TestHelpers.InMethod();
210 //log4net.Config.XmlConfigurator.Configure();
211
212 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
213
214 TestScene scene = new SceneHelpers().SetupScene();
215
216 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
217 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
218 sogd.Enabled = false;
219
220 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
221
222 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
223 scene.DeRezObjects(client, new System.Collections.Generic.List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero);
224
225 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
226
227 Assert.That(retrievedPart, Is.Not.Null);
228
229 Assert.That(so.IsDeleted, Is.False);
230
231 sogd.InventoryDeQueueAndDelete();
232
233 Assert.That(so.IsDeleted, Is.True);
234
235 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
236 Assert.That(retrievedPart2, Is.Null);
237 }
238
239 /// <summary>
240 /// Test deleting an object asynchronously to user inventory.
241 /// </summary>
242// [Test]
243 public void TestDeleteSceneObjectAsyncToUserInventory()
244 {
245 TestHelpers.InMethod();
246 TestHelpers.EnableLogging();
247
248 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
249 string myObjectName = "Fred";
250
251 TestScene scene = new SceneHelpers().SetupScene();
252
253 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
254 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
255 sogd.Enabled = false;
256
257 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
258
259// Assert.That(
260// scene.CommsManager.UserAdminService.AddUser(
261// "Bob", "Hoskins", "test", "test@test.com", 1000, 1000, agentId),
262// Is.EqualTo(agentId));
263
264 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
265 InventoryFolderBase folder1
266 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
267
268 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
269 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
270
271 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
272
273 Assert.That(retrievedPart, Is.Not.Null);
274 Assert.That(so.IsDeleted, Is.False);
275
276 sogd.InventoryDeQueueAndDelete();
277
278 Assert.That(so.IsDeleted, Is.True);
279
280 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
281 Assert.That(retrievedPart2, Is.Null);
282
283// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
284
285 InventoryItemBase retrievedItem
286 = UserInventoryHelpers.GetInventoryItem(
287 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
288
289 // Check that we now have the taken part in our inventory
290 Assert.That(retrievedItem, Is.Not.Null);
291
292 // Check that the taken part has actually disappeared
293// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
294// Assert.That(retrievedPart, Is.Null);
295 }
296
297 /// <summary>
298 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not 209 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not
299 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by 210 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by
300 /// OpenSim. 211 /// OpenSim.
@@ -329,4 +240,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
329 Assert.That(sog.Parts.Length, Is.EqualTo(2)); 240 Assert.That(sog.Parts.Length, Is.EqualTo(2));
330 } 241 }
331 } 242 }
332} 243} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 0076f41..c1522e7 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,22 +33,24 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess;
36using OpenSim.Region.CoreModules.World.Permissions; 37using OpenSim.Region.CoreModules.World.Permissions;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
38using OpenSim.Tests.Common; 40using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock; 41using OpenSim.Tests.Common.Mock;
40 42
41namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
42{ 44{
43 /// <summary> 45 /// <summary>
44 /// Tests derez of scene objects by users. 46 /// Tests derez of scene objects.
45 /// </summary> 47 /// </summary>
46 /// <remarks> 48 /// <remarks>
47 /// This is at a level above the SceneObjectBasicTests, which act on the scene directly. 49 /// This is at a level above the SceneObjectBasicTests, which act on the scene directly.
48 /// TODO: These tests are very incomplete - they only test for a few conditions. 50 /// TODO: These tests are incomplete - need to test more kinds of derez (e.g. return object).
49 /// </remarks> 51 /// </remarks>
50 [TestFixture] 52 [TestFixture]
51 public class SceneObjectDeRezTests 53 public class SceneObjectDeRezTests : OpenSimTestCase
52 { 54 {
53 /// <summary> 55 /// <summary>
54 /// Test deleting an object from a scene. 56 /// Test deleting an object from a scene.
@@ -76,14 +78,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
76 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero);
77 part.Name = "obj1"; 79 part.Name = "obj1";
78 scene.AddNewSceneObject(new SceneObjectGroup(part), false); 80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81
79 List<uint> localIds = new List<uint>(); 82 List<uint> localIds = new List<uint>();
80 localIds.Add(part.LocalId); 83 localIds.Add(part.LocalId);
81
82 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85
86 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90
83 sogd.InventoryDeQueueAndDelete(); 91 sogd.InventoryDeQueueAndDelete();
84 92
85 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId);
86 Assert.That(retrievedPart, Is.Null); 94 Assert.That(retrievedPart2, Is.Null);
87 } 95 }
88 96
89 /// <summary> 97 /// <summary>
@@ -124,6 +132,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
124 // Object should still be in the scene. 132 // Object should still be in the scene.
125 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 133 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
126 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID)); 134 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID));
127 } 135 }
136
137 /// <summary>
138 /// Test deleting an object asynchronously to user inventory.
139 /// </summary>
140 [Test]
141 public void TestDeleteSceneObjectAsyncToUserInventory()
142 {
143 TestHelpers.InMethod();
144// TestHelpers.EnableLogging();
145
146 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
147 string myObjectName = "Fred";
148
149 TestScene scene = new SceneHelpers().SetupScene();
150
151 IConfigSource configSource = new IniConfigSource();
152 IConfig config = configSource.AddConfig("Modules");
153 config.Set("InventoryAccessModule", "BasicInventoryAccessModule");
154 SceneHelpers.SetupSceneModules(
155 scene, configSource, new object[] { new BasicInventoryAccessModule() });
156
157 SceneHelpers.SetupSceneModules(scene, new object[] { });
158
159 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
160 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
161 sogd.Enabled = false;
162
163 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
164
165 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
166 InventoryFolderBase folder1
167 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
168
169 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
170 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
171
172 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
173
174 Assert.That(retrievedPart, Is.Not.Null);
175 Assert.That(so.IsDeleted, Is.False);
176
177 sogd.InventoryDeQueueAndDelete();
178
179 Assert.That(so.IsDeleted, Is.True);
180
181 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
182 Assert.That(retrievedPart2, Is.Null);
183
184// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
185
186 InventoryItemBase retrievedItem
187 = UserInventoryHelpers.GetInventoryItem(
188 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
189
190 // Check that we now have the taken part in our inventory
191 Assert.That(retrievedItem, Is.Not.Null);
192
193 // Check that the taken part has actually disappeared
194// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
195// Assert.That(retrievedPart, Is.Null);
196 }
128 } 197 }
129} \ No newline at end of file 198} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 0e525c9..9378e20 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -40,7 +40,7 @@ using log4net;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneObjectLinkingTests 43 public class SceneObjectLinkingTests : OpenSimTestCase
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index 89647d6..c264433 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
41 /// Basic scene object resize tests 41 /// Basic scene object resize tests
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class SceneObjectResizeTests 44 public class SceneObjectResizeTests : OpenSimTestCase
45 { 45 {
46 /// <summary> 46 /// <summary>
47 /// Test resizing an object 47 /// Test resizing an object
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
index d2361f8..a58e735 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneObjectScriptTests 43 public class SceneObjectScriptTests : OpenSimTestCase
44 { 44 {
45 [Test] 45 [Test]
46 public void TestAddScript() 46 public void TestAddScript()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
index 6d255aa..abaa1d1 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
@@ -42,14 +42,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.) 42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.)
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectSpatialTests 45 public class SceneObjectSpatialTests : OpenSimTestCase
46 { 46 {
47 TestScene m_scene; 47 TestScene m_scene;
48 UUID m_ownerId = TestHelpers.ParseTail(0x1); 48 UUID m_ownerId = TestHelpers.ParseTail(0x1);
49 49
50 [SetUp] 50 [SetUp]
51 public void SetUp() 51 public override void SetUp()
52 { 52 {
53 base.SetUp();
54
53 m_scene = new SceneHelpers().SetupScene(); 55 m_scene = new SceneHelpers().SetupScene();
54 } 56 }
55 57
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
index 742c769..093cbd2 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Basic scene object status tests 42 /// Basic scene object status tests
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectStatusTests 45 public class SceneObjectStatusTests : OpenSimTestCase
46 { 46 {
47 private TestScene m_scene; 47 private TestScene m_scene;
48 private UUID m_ownerId = TestHelpers.ParseTail(0x1); 48 private UUID m_ownerId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
index 646e5fa..1cd8ae9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
51 /// Scene presence animation tests 51 /// Scene presence animation tests
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class ScenePresenceAnimationTests 54 public class ScenePresenceAnimationTests : OpenSimTestCase
55 { 55 {
56 [Test] 56 [Test]
57 public void TestFlyingAnimation() 57 public void TestFlyingAnimation()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
index 1d1ff88..d80afd3 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common.Mock;
42namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class ScenePresenceAutopilotTests 45 public class ScenePresenceAutopilotTests : OpenSimTestCase
46 { 46 {
47 private TestScene m_scene; 47 private TestScene m_scene;
48 48
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index 493ab70..acaeb90 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -43,7 +43,7 @@ using System.Threading;
43namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class ScenePresenceSitTests 46 public class ScenePresenceSitTests : OpenSimTestCase
47 { 47 {
48 private TestScene m_scene; 48 private TestScene m_scene;
49 private ScenePresence m_sp; 49 private ScenePresence m_sp;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 37b5184..8dd1f3d 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
49 /// Teleport tests in a standalone OpenSim 49 /// Teleport tests in a standalone OpenSim
50 /// </summary> 50 /// </summary>
51 [TestFixture] 51 [TestFixture]
52 public class ScenePresenceTeleportTests 52 public class ScenePresenceTeleportTests : OpenSimTestCase
53 { 53 {
54 [TestFixtureSetUp] 54 [TestFixtureSetUp]
55 public void FixtureInit() 55 public void FixtureInit()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index ac3da1e..9d8eb0b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
50 /// Scene presence tests 50 /// Scene presence tests
51 /// </summary> 51 /// </summary>
52 [TestFixture] 52 [TestFixture]
53 public class SceneTests 53 public class SceneTests : OpenSimTestCase
54 { 54 {
55 /// <summary> 55 /// <summary>
56 /// Very basic scene update test. Should become more elaborate with time. 56 /// Very basic scene update test. Should become more elaborate with time.
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index a51e4e3..0b461f5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -50,7 +50,7 @@ using OpenSim.Tests.Common.Mock;
50namespace OpenSim.Region.Framework.Tests 50namespace OpenSim.Region.Framework.Tests
51{ 51{
52 [TestFixture] 52 [TestFixture]
53 public class TaskInventoryTests 53 public class TaskInventoryTests : OpenSimTestCase
54 { 54 {
55 [Test] 55 [Test]
56 public void TestAddTaskInventoryItem() 56 public void TestAddTaskInventoryItem()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 198e487..dd27294 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -38,7 +38,7 @@ using OpenSim.Tests.Common.Mock;
38namespace OpenSim.Region.Framework.Scenes.Tests 38namespace OpenSim.Region.Framework.Scenes.Tests
39{ 39{
40 [TestFixture] 40 [TestFixture]
41 public class UuidGathererTests 41 public class UuidGathererTests : OpenSimTestCase
42 { 42 {
43 protected IAssetService m_assetService; 43 protected IAssetService m_assetService;
44 protected UuidGatherer m_uuidGatherer; 44 protected UuidGatherer m_uuidGatherer;
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
index 6d26075..6b5b40a 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
@@ -36,7 +36,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
36 { 36 {
37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); 37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID);
38 void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); 38 void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish);
39
40 /// <summary>
41 /// Get the group record.
42 /// </summary>
43 /// <returns></returns>
44 /// <param name='RequestingAgentID'>The UUID of the user making the request.</param>
45 /// <param name='GroupID'>
46 /// The ID of the record to retrieve.
47 /// GroupName may be specified instead, in which case this parameter will be UUID.Zero
48 /// </param>
49 /// <param name='GroupName'>
50 /// The name of the group to retrieve.
51 /// GroupID may be specified instead, in which case this parmeter will be null.
52 /// </param>
39 GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); 53 GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName);
54
40 List<DirGroupsReplyData> FindGroups(UUID RequestingAgentID, string search); 55 List<DirGroupsReplyData> FindGroups(UUID RequestingAgentID, string search);
41 List<GroupMembersData> GetGroupMembers(UUID RequestingAgentID, UUID GroupID); 56 List<GroupMembersData> GetGroupMembers(UUID RequestingAgentID, UUID GroupID);
42 57
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index ac638f1..c1bdacb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
42 /// Basic groups module tests 42 /// Basic groups module tests
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class GroupsModuleTests 45 public class GroupsModuleTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestBasic() 48 public void TestBasic()
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index d0c3ea5..1101851 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -54,13 +54,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
54 54
55 private bool m_debugEnabled = false; 55 private bool m_debugEnabled = false;
56 56
57 public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | 57 public const GroupPowers DefaultEveryonePowers
58 GroupPowers.Accountable | 58 = GroupPowers.AllowSetHome
59 GroupPowers.JoinChat | 59 | GroupPowers.Accountable
60 GroupPowers.AllowVoiceChat | 60 | GroupPowers.JoinChat
61 GroupPowers.ReceiveNotices | 61 | GroupPowers.AllowVoiceChat
62 GroupPowers.StartProposal | 62 | GroupPowers.ReceiveNotices
63 GroupPowers.VoteOnProposal; 63 | GroupPowers.StartProposal
64 | GroupPowers.VoteOnProposal;
65
66 // Would this be cleaner as (GroupPowers)ulong.MaxValue?
67 public const GroupPowers DefaultOwnerPowers
68 = GroupPowers.Accountable
69 | GroupPowers.AllowEditLand
70 | GroupPowers.AllowFly
71 | GroupPowers.AllowLandmark
72 | GroupPowers.AllowRez
73 | GroupPowers.AllowSetHome
74 | GroupPowers.AllowVoiceChat
75 | GroupPowers.AssignMember
76 | GroupPowers.AssignMemberLimited
77 | GroupPowers.ChangeActions
78 | GroupPowers.ChangeIdentity
79 | GroupPowers.ChangeMedia
80 | GroupPowers.ChangeOptions
81 | GroupPowers.CreateRole
82 | GroupPowers.DeedObject
83 | GroupPowers.DeleteRole
84 | GroupPowers.Eject
85 | GroupPowers.FindPlaces
86 | GroupPowers.Invite
87 | GroupPowers.JoinChat
88 | GroupPowers.LandChangeIdentity
89 | GroupPowers.LandDeed
90 | GroupPowers.LandDivideJoin
91 | GroupPowers.LandEdit
92 | GroupPowers.LandEjectAndFreeze
93 | GroupPowers.LandGardening
94 | GroupPowers.LandManageAllowed
95 | GroupPowers.LandManageBanned
96 | GroupPowers.LandManagePasses
97 | GroupPowers.LandOptions
98 | GroupPowers.LandRelease
99 | GroupPowers.LandSetSale
100 | GroupPowers.ModerateChat
101 | GroupPowers.ObjectManipulate
102 | GroupPowers.ObjectSetForSale
103 | GroupPowers.ReceiveNotices
104 | GroupPowers.RemoveMember
105 | GroupPowers.ReturnGroupOwned
106 | GroupPowers.ReturnGroupSet
107 | GroupPowers.ReturnNonGroup
108 | GroupPowers.RoleProperties
109 | GroupPowers.SendNotices
110 | GroupPowers.SetLandingPoint
111 | GroupPowers.StartProposal
112 | GroupPowers.VoteOnProposal;
64 113
65 private bool m_connectorEnabled = false; 114 private bool m_connectorEnabled = false;
66 115
@@ -219,59 +268,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
219 param["AllowPublish"] = allowPublish == true ? 1 : 0; 268 param["AllowPublish"] = allowPublish == true ? 1 : 0;
220 param["MaturePublish"] = maturePublish == true ? 1 : 0; 269 param["MaturePublish"] = maturePublish == true ? 1 : 0;
221 param["FounderID"] = founderID.ToString(); 270 param["FounderID"] = founderID.ToString();
222 param["EveryonePowers"] = ((ulong)m_DefaultEveryonePowers).ToString(); 271 param["EveryonePowers"] = ((ulong)DefaultEveryonePowers).ToString();
223 param["OwnerRoleID"] = OwnerRoleID.ToString(); 272 param["OwnerRoleID"] = OwnerRoleID.ToString();
224 273 param["OwnersPowers"] = ((ulong)DefaultOwnerPowers).ToString();
225 // Would this be cleaner as (GroupPowers)ulong.MaxValue;
226 GroupPowers OwnerPowers = GroupPowers.Accountable
227 | GroupPowers.AllowEditLand
228 | GroupPowers.AllowFly
229 | GroupPowers.AllowLandmark
230 | GroupPowers.AllowRez
231 | GroupPowers.AllowSetHome
232 | GroupPowers.AllowVoiceChat
233 | GroupPowers.AssignMember
234 | GroupPowers.AssignMemberLimited
235 | GroupPowers.ChangeActions
236 | GroupPowers.ChangeIdentity
237 | GroupPowers.ChangeMedia
238 | GroupPowers.ChangeOptions
239 | GroupPowers.CreateRole
240 | GroupPowers.DeedObject
241 | GroupPowers.DeleteRole
242 | GroupPowers.Eject
243 | GroupPowers.FindPlaces
244 | GroupPowers.Invite
245 | GroupPowers.JoinChat
246 | GroupPowers.LandChangeIdentity
247 | GroupPowers.LandDeed
248 | GroupPowers.LandDivideJoin
249 | GroupPowers.LandEdit
250 | GroupPowers.LandEjectAndFreeze
251 | GroupPowers.LandGardening
252 | GroupPowers.LandManageAllowed
253 | GroupPowers.LandManageBanned
254 | GroupPowers.LandManagePasses
255 | GroupPowers.LandOptions
256 | GroupPowers.LandRelease
257 | GroupPowers.LandSetSale
258 | GroupPowers.ModerateChat
259 | GroupPowers.ObjectManipulate
260 | GroupPowers.ObjectSetForSale
261 | GroupPowers.ReceiveNotices
262 | GroupPowers.RemoveMember
263 | GroupPowers.ReturnGroupOwned
264 | GroupPowers.ReturnGroupSet
265 | GroupPowers.ReturnNonGroup
266 | GroupPowers.RoleProperties
267 | GroupPowers.SendNotices
268 | GroupPowers.SetLandingPoint
269 | GroupPowers.StartProposal
270 | GroupPowers.VoteOnProposal;
271 param["OwnersPowers"] = ((ulong)OwnerPowers).ToString();
272
273
274
275 274
276 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); 275 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param);
277 276
@@ -612,8 +611,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
612 } 611 }
613 612
614 return Roles; 613 return Roles;
615
616
617 } 614 }
618 615
619 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID) 616 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID)
@@ -676,7 +673,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
676 } 673 }
677 674
678 return members; 675 return members;
679
680 } 676 }
681 677
682 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) 678 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID)
@@ -727,9 +723,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
727 values.Add(data); 723 values.Add(data);
728 } 724 }
729 } 725 }
730 return values;
731 726
727 return values;
732 } 728 }
729
733 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) 730 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
734 { 731 {
735 Hashtable param = new Hashtable(); 732 Hashtable param = new Hashtable();
@@ -737,7 +734,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
737 734
738 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); 735 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param);
739 736
740
741 if (respData.Contains("error")) 737 if (respData.Contains("error"))
742 { 738 {
743 return null; 739 return null;
@@ -761,6 +757,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
761 757
762 return data; 758 return data;
763 } 759 }
760
764 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) 761 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
765 { 762 {
766 string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); 763 string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, "");
@@ -777,8 +774,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
777 XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); 774 XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param);
778 } 775 }
779 776
780
781
782 #endregion 777 #endregion
783 778
784 #region GroupSessionTracking 779 #region GroupSessionTracking
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 52ed846..a522277 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
48namespace OpenSim.Region.OptionalModules.World.NPC.Tests 48namespace OpenSim.Region.OptionalModules.World.NPC.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class NPCModuleTests 51 public class NPCModuleTests : OpenSimTestCase
52 { 52 {
53 private TestScene m_scene; 53 private TestScene m_scene;
54 private AvatarFactoryModule m_afMod; 54 private AvatarFactoryModule m_afMod;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index f33c124..4c195e1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -78,11 +78,17 @@ public sealed class BSCharacter : BSPhysObject
78 private float _PIDHoverTao; 78 private float _PIDHoverTao;
79 79
80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
81 : base(parent_scene, localID, avName, "BSCharacter")
81 { 82 {
82 base.BaseInitialize(parent_scene, localID, avName, "BSCharacter");
83 _physicsActorType = (int)ActorTypes.Agent; 83 _physicsActorType = (int)ActorTypes.Agent;
84 _position = pos; 84 _position = pos;
85
86 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
87 // replace with the default values.
85 _size = size; 88 _size = size;
89 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
90 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
91
86 _flying = isFlying; 92 _flying = isFlying;
87 _orientation = OMV.Quaternion.Identity; 93 _orientation = OMV.Quaternion.Identity;
88 _velocity = OMV.Vector3.Zero; 94 _velocity = OMV.Vector3.Zero;
@@ -131,6 +137,10 @@ public sealed class BSCharacter : BSPhysObject
131 // Set the velocity and compute the proper friction 137 // Set the velocity and compute the proper friction
132 ForceVelocity = _velocity; 138 ForceVelocity = _velocity;
133 139
140 // This will enable or disable the flying buoyancy of the avatar.
141 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
142 Flying = _flying;
143
134 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); 144 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution);
135 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); 145 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin);
136 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); 146 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
@@ -171,8 +181,7 @@ public sealed class BSCharacter : BSPhysObject
171 get 181 get
172 { 182 {
173 // Avatar capsule size is kept in the scale parameter. 183 // Avatar capsule size is kept in the scale parameter.
174 // return _size; 184 return _size;
175 return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z);
176 } 185 }
177 186
178 set { 187 set {
@@ -180,8 +189,8 @@ public sealed class BSCharacter : BSPhysObject
180 _size = value; 189 _size = value;
181 ComputeAvatarScale(_size); 190 ComputeAvatarScale(_size);
182 ComputeAvatarVolumeAndMass(); 191 ComputeAvatarVolumeAndMass();
183 DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", 192 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
184 LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); 193 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
185 194
186 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 195 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
187 { 196 {
@@ -199,9 +208,9 @@ public sealed class BSCharacter : BSPhysObject
199 set { BaseShape = value; } 208 set { BaseShape = value; }
200 } 209 }
201 // I want the physics engine to make an avatar capsule 210 // I want the physics engine to make an avatar capsule
202 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 211 public override BSPhysicsShapeType PreferredPhysicalShape
203 { 212 {
204 get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } 213 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
205 } 214 }
206 215
207 public override bool Grabbed { 216 public override bool Grabbed {
@@ -610,13 +619,19 @@ public sealed class BSCharacter : BSPhysObject
610 // The 'size' given by the simulator is the mid-point of the avatar 619 // The 'size' given by the simulator is the mid-point of the avatar
611 // and X and Y are unspecified. 620 // and X and Y are unspecified.
612 621
613 OMV.Vector3 newScale = OMV.Vector3.Zero; 622 OMV.Vector3 newScale = size;
614 newScale.X = PhysicsScene.Params.avatarCapsuleRadius; 623 // newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
615 newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; 624 // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;
616 625
617 // From the total height, remove the capsule half spheres that are at each end 626 // From the total height, remove the capsule half spheres that are at each end
618 newScale.Z = size.Z- (newScale.X + newScale.Y); 627 // The 1.15f came from ODE. Not sure what this factors in.
619 Scale = newScale; 628 // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y);
629
630 // The total scale height is the central cylindar plus the caps on the two ends.
631 newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f);
632
633 // Convert diameters to radii and height to half height -- the way Bullet expects it.
634 Scale = newScale / 2f;
620 } 635 }
621 636
622 // set _avatarVolume and _mass based on capsule size, _density and Scale 637 // set _avatarVolume and _mass based on capsule size, _density and Scale
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index dbc9039..74eb9ab 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -80,10 +80,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
80 private Quaternion m_referenceFrame = Quaternion.Identity; 80 private Quaternion m_referenceFrame = Quaternion.Identity;
81 81
82 // Linear properties 82 // Linear properties
83 private BSVMotor m_linearMotor = new BSVMotor("LinearMotor");
83 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 84 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
84 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center 85 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
85 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 86 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
86 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
87 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 87 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
88 private float m_linearMotorDecayTimescale = 0; 88 private float m_linearMotorDecayTimescale = 0;
89 private float m_linearMotorTimescale = 0; 89 private float m_linearMotorTimescale = 0;
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
93 // private Vector3 m_linearMotorOffset = Vector3.Zero; 93 // private Vector3 m_linearMotorOffset = Vector3.Zero;
94 94
95 //Angular properties 95 //Angular properties
96 private BSVMotor m_angularMotor = new BSVMotor("AngularMotor");
96 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 97 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
97 // private int m_angularMotorApply = 0; // application frame counter 98 // private int m_angularMotorApply = 0; // application frame counter
98 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity 99 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
@@ -124,6 +125,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. 125 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
125 126
126 //Attractor properties 127 //Attractor properties
128 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
127 private float m_verticalAttractionEfficiency = 1.0f; // damped 129 private float m_verticalAttractionEfficiency = 1.0f; // damped
128 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 130 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
129 131
@@ -152,10 +154,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
152 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 154 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
153 break; 155 break;
154 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 156 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
155 m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); 157 m_angularMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
158 m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
156 break; 159 break;
157 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 160 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
158 m_angularMotorTimescale = Math.Max(pValue, 0.01f); 161 m_angularMotorTimescale = Math.Max(pValue, 0.01f);
162 m_angularMotor.TimeScale = m_angularMotorTimescale;
159 break; 163 break;
160 case Vehicle.BANKING_EFFICIENCY: 164 case Vehicle.BANKING_EFFICIENCY:
161 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); 165 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f));
@@ -185,33 +189,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin
185 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 189 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
186 break; 190 break;
187 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 191 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
188 m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); 192 m_linearMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
193 m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
189 break; 194 break;
190 case Vehicle.LINEAR_MOTOR_TIMESCALE: 195 case Vehicle.LINEAR_MOTOR_TIMESCALE:
191 m_linearMotorTimescale = Math.Max(pValue, 0.01f); 196 m_linearMotorTimescale = Math.Max(pValue, 0.01f);
197 m_linearMotor.TimeScale = m_linearMotorTimescale;
192 break; 198 break;
193 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 199 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
194 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); 200 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
201 m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
195 break; 202 break;
196 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 203 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
197 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); 204 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
205 m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale;
198 break; 206 break;
199 207
200 // These are vector properties but the engine lets you use a single float value to 208 // These are vector properties but the engine lets you use a single float value to
201 // set all of the components to the same value 209 // set all of the components to the same value
202 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 210 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
203 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 211 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
212 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
204 break; 213 break;
205 case Vehicle.ANGULAR_MOTOR_DIRECTION: 214 case Vehicle.ANGULAR_MOTOR_DIRECTION:
206 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 215 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
207 // m_angularMotorApply = 100; 216 m_angularMotor.SetTarget(m_angularMotorDirection);
208 break; 217 break;
209 case Vehicle.LINEAR_FRICTION_TIMESCALE: 218 case Vehicle.LINEAR_FRICTION_TIMESCALE:
210 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 219 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
220 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
211 break; 221 break;
212 case Vehicle.LINEAR_MOTOR_DIRECTION: 222 case Vehicle.LINEAR_MOTOR_DIRECTION:
213 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 223 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
214 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); 224 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
225 m_linearMotor.SetTarget(m_linearMotorDirection);
215 break; 226 break;
216 case Vehicle.LINEAR_MOTOR_OFFSET: 227 case Vehicle.LINEAR_MOTOR_OFFSET:
217 m_linearMotorOffset = new Vector3(pValue, pValue, pValue); 228 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
@@ -227,6 +238,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
227 { 238 {
228 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 239 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
229 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 240 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
241 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
230 break; 242 break;
231 case Vehicle.ANGULAR_MOTOR_DIRECTION: 243 case Vehicle.ANGULAR_MOTOR_DIRECTION:
232 // Limit requested angular speed to 2 rps= 4 pi rads/sec 244 // Limit requested angular speed to 2 rps= 4 pi rads/sec
@@ -234,14 +246,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
234 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); 246 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f));
235 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); 247 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f));
236 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 248 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
237 // m_angularMotorApply = 100; 249 m_angularMotor.SetTarget(m_angularMotorDirection);
238 break; 250 break;
239 case Vehicle.LINEAR_FRICTION_TIMESCALE: 251 case Vehicle.LINEAR_FRICTION_TIMESCALE:
240 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 252 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
253 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
241 break; 254 break;
242 case Vehicle.LINEAR_MOTOR_DIRECTION: 255 case Vehicle.LINEAR_MOTOR_DIRECTION:
243 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 256 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
244 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); 257 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
258 m_linearMotor.SetTarget(m_linearMotorDirection);
245 break; 259 break;
246 case Vehicle.LINEAR_MOTOR_OFFSET: 260 case Vehicle.LINEAR_MOTOR_OFFSET:
247 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 261 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -303,7 +317,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
303 m_VhoverEfficiency = 0; 317 m_VhoverEfficiency = 0;
304 m_VhoverTimescale = 0; 318 m_VhoverTimescale = 0;
305 m_VehicleBuoyancy = 0; 319 m_VehicleBuoyancy = 0;
306 320
307 m_linearDeflectionEfficiency = 1; 321 m_linearDeflectionEfficiency = 1;
308 m_linearDeflectionTimescale = 1; 322 m_linearDeflectionTimescale = 1;
309 323
@@ -319,6 +333,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
319 333
320 m_referenceFrame = Quaternion.Identity; 334 m_referenceFrame = Quaternion.Identity;
321 m_flags = (VehicleFlag)0; 335 m_flags = (VehicleFlag)0;
336
322 break; 337 break;
323 338
324 case Vehicle.TYPE_SLED: 339 case Vehicle.TYPE_SLED:
@@ -351,10 +366,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
351 m_bankingMix = 1; 366 m_bankingMix = 1;
352 367
353 m_referenceFrame = Quaternion.Identity; 368 m_referenceFrame = Quaternion.Identity;
354 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); 369 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
355 m_flags &= 370 | VehicleFlag.HOVER_TERRAIN_ONLY
356 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 371 | VehicleFlag.HOVER_GLOBAL_HEIGHT
357 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 372 | VehicleFlag.HOVER_UP_ONLY);
373 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
374 | VehicleFlag.LIMIT_ROLL_ONLY
375 | VehicleFlag.LIMIT_MOTOR_UP);
358 break; 376 break;
359 case Vehicle.TYPE_CAR: 377 case Vehicle.TYPE_CAR:
360 m_linearMotorDirection = Vector3.Zero; 378 m_linearMotorDirection = Vector3.Zero;
@@ -510,6 +528,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin
510 | VehicleFlag.HOVER_GLOBAL_HEIGHT); 528 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
511 break; 529 break;
512 } 530 }
531
532 // Update any physical parameters based on this type.
533 Refresh();
534
535 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
536 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
537 1f);
538 m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
539
540 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale,
541 m_angularMotorDecayTimescale, m_angularFrictionTimescale,
542 1f);
543 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
544
545 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
546 BSMotor.Infinite, BSMotor.InfiniteVector,
547 m_verticalAttractionEfficiency);
548 // Z goes away and we keep X and Y
549 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
550 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
551
552 // m_bankingMotor = new BSVMotor("BankingMotor", ...);
513 } 553 }
514 554
515 // Some of the properties of this prim may have changed. 555 // Some of the properties of this prim may have changed.
@@ -518,13 +558,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
518 { 558 {
519 if (IsActive) 559 if (IsActive)
520 { 560 {
521 // Friction effects are handled by this vehicle code 561 m_vehicleMass = Prim.Linkset.LinksetMass;
522 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f);
523 BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f);
524
525 // BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f);
526 562
527 VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID); 563 // Friction effects are handled by this vehicle code
564 float friction = 0f;
565 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction);
566
567 // Moderate angular movement introduced by Bullet.
568 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
569 // Maybe compute linear and angular factor and damping from params.
570 float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
571 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
572
573 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
574 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
575 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
576 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
577
578 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
579 Prim.LocalID, friction, localInertia, angularDamping);
528 } 580 }
529 } 581 }
530 582
@@ -551,111 +603,109 @@ namespace OpenSim.Region.Physics.BulletSPlugin
551 { 603 {
552 if (!IsActive) return; 604 if (!IsActive) return;
553 605
554 // DEBUG
555 // Because Bullet does apply forces to the vehicle, our last computed
556 // linear and angular velocities are not what is happening now.
557 // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity;
558 // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep;
559 // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time
560 // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG:
561 // END DEBUG
562
563 m_vehicleMass = Prim.Linkset.LinksetMass;
564
565 MoveLinear(pTimestep); 606 MoveLinear(pTimestep);
566 // Commented out for debug
567 MoveAngular(pTimestep); 607 MoveAngular(pTimestep);
568 // Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG
569 // Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG
570 608
571 LimitRotation(pTimestep); 609 LimitRotation(pTimestep);
572 610
573 // remember the position so next step we can limit absolute movement effects 611 // remember the position so next step we can limit absolute movement effects
574 m_lastPositionVector = Prim.ForcePosition; 612 m_lastPositionVector = Prim.ForcePosition;
575 613
576 VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG
577 Prim.LocalID,
578 BulletSimAPI.GetFriction2(Prim.PhysBody.ptr),
579 BulletSimAPI.GetGravity2(Prim.PhysBody.ptr),
580 Prim.Inertia,
581 m_vehicleMass
582 );
583 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 614 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
584 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); 615 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
585 }// end Step 616 }
586 617
587 // Apply the effect of the linear motor. 618 // Apply the effect of the linear motor.
588 // Also does hover and float. 619 // Also does hover and float.
589 private void MoveLinear(float pTimestep) 620 private void MoveLinear(float pTimestep)
590 { 621 {
591 // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates 622 Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
592 // m_lastLinearVelocityVector is the current speed we are moving in that direction
593 if (m_linearMotorDirection.LengthSquared() > 0.001f)
594 {
595 Vector3 origDir = m_linearMotorDirection; // DEBUG
596 Vector3 origVel = m_lastLinearVelocityVector; // DEBUG
597 // DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison
598 Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG
599 623
600 // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete 624 // Rotate new object velocity from vehicle relative to world coordinates
601 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; 625 linearMotorContribution *= Prim.ForceOrientation;
602 m_lastLinearVelocityVector += addAmount;
603 626
604 float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; 627 // ==================================================================
605 m_linearMotorDirection *= (1f - decayFactor); 628 // Gravity and Buoyancy
629 // There is some gravity, make a gravity force vector that is applied after object velocity.
630 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
631 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
606 632
607 // Rotate new object velocity from vehicle relative to world coordinates 633 Vector3 pos = Prim.ForcePosition;
608 m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; 634 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
609 635
610 // Apply friction for next time 636 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep, ref pos, terrainHeight);
611 Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep;
612 m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
613 637
614 VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}", 638 Vector3 hoverContribution = ComputeLinearHover(pTimestep, ref pos, terrainHeight);
615 Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, 639
616 m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); 640 ComputeLinearBlockingEndPoint(pTimestep, ref pos);
617 } 641
618 else 642 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep, pos, terrainHeight);
619 { 643
620 // if what remains of direction is very small, zero it. 644 // ==================================================================
621 m_linearMotorDirection = Vector3.Zero; 645 Vector3 newVelocity = linearMotorContribution
622 m_lastLinearVelocityVector = Vector3.Zero; 646 + terrainHeightContribution
623 m_newVelocity = Vector3.Zero; 647 + hoverContribution
648 + limitMotorUpContribution;
649
650 // If not changing some axis, reduce out velocity
651 if ((m_flags & (VehicleFlag.NO_X)) != 0)
652 newVelocity.X = 0;
653 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
654 newVelocity.Y = 0;
655 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
656 newVelocity.Z = 0;
624 657
625 VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); 658 // ==================================================================
659 // Clamp REALLY high or low velocities
660 float newVelocityLengthSq = newVelocity.LengthSquared();
661 if (newVelocityLengthSq > 1e6f)
662 {
663 newVelocity /= newVelocity.Length();
664 newVelocity *= 1000f;
626 } 665 }
666 else if (newVelocityLengthSq < 1e-6f)
667 newVelocity = Vector3.Zero;
627 668
628 // m_newVelocity is velocity computed from linear motor in world coordinates 669 // ==================================================================
670 // Stuff new linear velocity into the vehicle
671 Prim.ForceVelocity = newVelocity;
672 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
629 673
630 // Gravity and Buoyancy 674 // Other linear forces are applied as forces.
631 // There is some gravity, make a gravity force vector that is applied after object velocity. 675 Vector3 totalDownForce = grav * m_vehicleMass;
632 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 676 if (totalDownForce != Vector3.Zero)
633 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); 677 {
678 Prim.AddForce(totalDownForce, false);
679 }
634 680
635 /* 681 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
636 * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... 682 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector,
637 // Preserve the current Z velocity 683 newVelocity, Prim.Velocity, totalDownForce);
638 Vector3 vel_now = m_prim.Velocity;
639 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
640 */
641 684
642 Vector3 pos = Prim.ForcePosition; 685 } // end MoveLinear()
643// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
644 686
687 public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep, ref Vector3 pos, float terrainHeight)
688 {
689 Vector3 ret = Vector3.Zero;
645 // If below the terrain, move us above the ground a little. 690 // If below the terrain, move us above the ground a little.
646 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
647 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. 691 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
648 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. 692 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
649 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; 693 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
650 // if (rotatedSize.Z < terrainHeight) 694 // if (rotatedSize.Z < terrainHeight)
651 if (pos.Z < terrainHeight) 695 if (pos.Z < terrainHeight)
652 { 696 {
697 // TODO: correct position by applying force rather than forcing position.
653 pos.Z = terrainHeight + 2; 698 pos.Z = terrainHeight + 2;
654 Prim.ForcePosition = pos; 699 Prim.ForcePosition = pos;
655 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); 700 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
656 } 701 }
702 return ret;
703 }
704
705 public Vector3 ComputeLinearHover(float pTimestep, ref Vector3 pos, float terrainHeight)
706 {
707 Vector3 ret = Vector3.Zero;
657 708
658 // Check if hovering
659 // m_VhoverEfficiency: 0=bouncy, 1=totally damped 709 // m_VhoverEfficiency: 0=bouncy, 1=totally damped
660 // m_VhoverTimescale: time to achieve height 710 // m_VhoverTimescale: time to achieve height
661 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 711 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
@@ -694,28 +744,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin
694 // RA: where does the 50 come from? 744 // RA: where does the 50 come from?
695 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); 745 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale);
696 // Replace Vertical speed with correction figure if significant 746 // Replace Vertical speed with correction figure if significant
697 if (Math.Abs(verticalError) > 0.01f) 747 if (verticalError > 0.01f)
698 { 748 {
699 m_newVelocity.Z += verticalCorrectionVelocity; 749 ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
700 //KF: m_VhoverEfficiency is not yet implemented 750 //KF: m_VhoverEfficiency is not yet implemented
701 } 751 }
702 else if (verticalError < -0.01) 752 else if (verticalError < -0.01)
703 { 753 {
704 m_newVelocity.Z -= verticalCorrectionVelocity; 754 ret = new Vector3(0f, 0f, -verticalCorrectionVelocity);
705 }
706 else
707 {
708 m_newVelocity.Z = 0f;
709 } 755 }
710 } 756 }
711 757
712 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); 758 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}",
759 Prim.LocalID, pos, ret, m_VhoverHeight, m_VhoverTargetHeight);
713 } 760 }
714 761
762 return ret;
763 }
764
765 public bool ComputeLinearBlockingEndPoint(float pTimestep, ref Vector3 pos)
766 {
767 bool changed = false;
768
715 Vector3 posChange = pos - m_lastPositionVector; 769 Vector3 posChange = pos - m_lastPositionVector;
716 if (m_BlockingEndPoint != Vector3.Zero) 770 if (m_BlockingEndPoint != Vector3.Zero)
717 { 771 {
718 bool changed = false;
719 if (pos.X >= (m_BlockingEndPoint.X - (float)1)) 772 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
720 { 773 {
721 pos.X -= posChange.X + 1; 774 pos.X -= posChange.X + 1;
@@ -748,75 +801,45 @@ namespace OpenSim.Region.Physics.BulletSPlugin
748 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 801 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
749 } 802 }
750 } 803 }
804 return changed;
805 }
751 806
752 #region downForce 807 public Vector3 ComputeLinearMotorUp(float pTimestep, Vector3 pos, float terrainHeight)
753 Vector3 downForce = Vector3.Zero; 808 {
754 809 Vector3 ret = Vector3.Zero;
755 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 810 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
756 { 811 {
757 // If the vehicle is motoring into the sky, get it going back down. 812 // If the vehicle is motoring into the sky, get it going back down.
758 // Is this an angular force or both linear and angular??
759 float distanceAboveGround = pos.Z - terrainHeight; 813 float distanceAboveGround = pos.Z - terrainHeight;
760 if (distanceAboveGround > 2f) 814 if (distanceAboveGround > 1f)
761 { 815 {
762 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 816 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
763 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 817 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
764 downForce = new Vector3(0, 0, -distanceAboveGround); 818 ret = new Vector3(0, 0, -distanceAboveGround);
765 } 819 }
766 // TODO: this calculation is all wrong. From the description at 820 // TODO: this calculation is all wrong. From the description at
767 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce 821 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
768 // has a decay factor. This says this force should 822 // has a decay factor. This says this force should
769 // be computed with a motor. 823 // be computed with a motor.
770 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", 824 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
771 Prim.LocalID, distanceAboveGround, downForce); 825 Prim.LocalID, distanceAboveGround, ret);
772 } 826 }
773 #endregion // downForce 827 return ret;
774 828 }
775 // If not changing some axis, reduce out velocity
776 if ((m_flags & (VehicleFlag.NO_X)) != 0)
777 m_newVelocity.X = 0;
778 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
779 m_newVelocity.Y = 0;
780 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
781 m_newVelocity.Z = 0;
782
783 // Clamp REALLY high or low velocities
784 if (m_newVelocity.LengthSquared() > 1e6f)
785 {
786 m_newVelocity /= m_newVelocity.Length();
787 m_newVelocity *= 1000f;
788 }
789 else if (m_newVelocity.LengthSquared() < 1e-6f)
790 m_newVelocity = Vector3.Zero;
791
792 // Stuff new linear velocity into the vehicle
793 Prim.ForceVelocity = m_newVelocity;
794 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
795
796 Vector3 totalDownForce = downForce + grav;
797 if (totalDownForce != Vector3.Zero)
798 {
799 Prim.AddForce(totalDownForce * m_vehicleMass, false);
800 // Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false);
801 }
802
803 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
804 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce);
805
806 } // end MoveLinear()
807 829
808 // ======================================================================= 830 // =======================================================================
831 // =======================================================================
809 // Apply the effect of the angular motor. 832 // Apply the effect of the angular motor.
810 private void MoveAngular(float pTimestep) 833 private void MoveAngular(float pTimestep)
811 { 834 {
812 // m_angularMotorDirection // angular velocity requested by LSL motor 835 // m_angularMotorDirection // angular velocity requested by LSL motor
813 // m_angularMotorApply // application frame counter
814 // m_angularMotorVelocity // current angular motor velocity (ramps up and down) 836 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
815 // m_angularMotorTimescale // motor angular velocity ramp up rate 837 // m_angularMotorTimescale // motor angular velocity ramp up time
816 // m_angularMotorDecayTimescale // motor angular velocity decay rate 838 // m_angularMotorDecayTimescale // motor angular velocity decay rate
817 // m_angularFrictionTimescale // body angular velocity decay rate 839 // m_angularFrictionTimescale // body angular velocity decay rate
818 // m_lastAngularVelocity // what was last applied to body 840 // m_lastAngularVelocity // what was last applied to body
819 841
842 /*
820 if (m_angularMotorDirection.LengthSquared() > 0.0001) 843 if (m_angularMotorDirection.LengthSquared() > 0.0001)
821 { 844 {
822 Vector3 origVel = m_angularMotorVelocity; 845 Vector3 origVel = m_angularMotorVelocity;
@@ -835,59 +858,152 @@ namespace OpenSim.Region.Physics.BulletSPlugin
835 { 858 {
836 m_angularMotorVelocity = Vector3.Zero; 859 m_angularMotorVelocity = Vector3.Zero;
837 } 860 }
861 */
862
863 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
838 864
839 #region Vertical attactor 865 // ==================================================================
866 // NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
867 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
868 {
869 angularMotorContribution.X = 0f;
870 angularMotorContribution.Y = 0f;
871 VDetailLog("{0},MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
872 }
840 873
841 Vector3 vertattr = Vector3.Zero; 874 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(pTimestep);
842 Vector3 deflection = Vector3.Zero;
843 Vector3 banking = Vector3.Zero;
844 875
845 // If vertical attaction timescale is reasonable and we applied an angular force last time... 876 Vector3 deflectionContribution = ComputeAngularDeflection(pTimestep);
846 if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) 877
878 Vector3 bankingContribution = ComputeAngularBanking(pTimestep);
879
880 // ==================================================================
881 m_lastVertAttractor = verticalAttractionContribution;
882
883 // Sum velocities
884 m_lastAngularVelocity = angularMotorContribution
885 + verticalAttractionContribution
886 + bankingContribution
887 + deflectionContribution;
888
889 // ==================================================================
890 //Offset section
891 if (m_linearMotorOffset != Vector3.Zero)
892 {
893 //Offset of linear velocity doesn't change the linear velocity,
894 // but causes a torque to be applied, for example...
895 //
896 // IIIII >>> IIIII
897 // IIIII >>> IIIII
898 // IIIII >>> IIIII
899 // ^
900 // | Applying a force at the arrow will cause the object to move forward, but also rotate
901 //
902 //
903 // The torque created is the linear velocity crossed with the offset
904
905 // TODO: this computation should be in the linear section
906 // because that is where we know the impulse being applied.
907 Vector3 torqueFromOffset = Vector3.Zero;
908 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
909 if (float.IsNaN(torqueFromOffset.X))
910 torqueFromOffset.X = 0;
911 if (float.IsNaN(torqueFromOffset.Y))
912 torqueFromOffset.Y = 0;
913 if (float.IsNaN(torqueFromOffset.Z))
914 torqueFromOffset.Z = 0;
915 torqueFromOffset *= m_vehicleMass;
916 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
917 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
918 }
919
920 // ==================================================================
921 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
922 {
923 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
924 Prim.ZeroAngularMotion(true);
925 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
926 }
927 else
847 { 928 {
848 float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; 929 // Apply to the body.
849 if (Prim.IsColliding) 930 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
850 VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); 931 // Since we are stuffing the angular velocity directly into the object, the computed
932 // velocity needs to be scaled by the timestep.
933 // Also remove any motion that is on the object so added motion is only from vehicle.
934 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep)
935 - Prim.ForceRotationalVelocity);
936 // Unscale the force by the angular factor so it overwhelmes the Bullet additions.
937 Prim.ForceRotationalVelocity = applyAngularForce;
938
939 VDetailLog("{0},MoveAngular,done,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}",
940 Prim.LocalID,
941 angularMotorContribution, verticalAttractionContribution,
942 bankingContribution, deflectionContribution,
943 applyAngularForce, m_lastAngularVelocity
944 );
945 }
946 }
851 947
852 VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 948 public Vector3 ComputeAngularVerticalAttraction(float pTimestep)
949 {
950 Vector3 ret = Vector3.Zero;
853 951
854 // Create a vector of the vehicle "up" in world coordinates 952 // If vertical attaction timescale is reasonable and we applied an angular force last time...
953 if (m_verticalAttractionTimescale < 500)
954 {
955 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
956 verticalError.Normalize();
957 m_verticalAttractionMotor.SetCurrent(verticalError);
958 m_verticalAttractionMotor.SetTarget(Vector3.UnitZ);
959 ret = m_verticalAttractionMotor.Step(pTimestep);
960 /*
961 // Take a vector pointing up and convert it from world to vehicle relative coords.
855 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; 962 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
856 // verticalError.X and .Y are the World error amounts. They are 0 when there is no 963 verticalError.Normalize();
857 // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its 964
858 // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall 965 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
859 // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be 966 // is now leaning to one side (rotated around the X axis) and the Y value will
860 // modulated to prevent a stable inverted body. 967 // go from zero (nearly straight up) to one (completely to the side) or leaning
861 968 // front-to-back (rotated around the Y axis) and the value of X will be between
862 // Error is 0 (no error) to +/- 2 (max error) 969 // zero and one.
863 if (verticalError.Z < 0.0f) 970 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
971
972 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
973 if (verticalError.Z < 0f)
864 { 974 {
865 verticalError.X = 2.0f - verticalError.X; 975 verticalError.X = 2f - verticalError.X;
866 verticalError.Y = 2.0f - verticalError.Y; 976 verticalError.Y = 2f - verticalError.Y;
867 } 977 }
868 // scale it by VAservo (timestep and timescale)
869 verticalError = verticalError * VAservo;
870 978
871 // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y 979 // Y error means needed rotation around X axis and visa versa.
872 // then .X increases, so change Body angular velocity X based on Y, and Y based on X. 980 verticalAttractionContribution.X = verticalError.Y;
873 // Z is not changed. 981 verticalAttractionContribution.Y = - verticalError.X;
874 vertattr.X = verticalError.Y; 982 verticalAttractionContribution.Z = 0f;
875 vertattr.Y = - verticalError.X; 983
876 vertattr.Z = 0f; 984 // scale by the time scale and timestep
985 Vector3 unscaledContrib = verticalAttractionContribution;
986 verticalAttractionContribution /= m_verticalAttractionTimescale;
987 verticalAttractionContribution *= pTimestep;
877 988
878 // scaling appears better usingsquare-law 989 // apply efficiency
879 Vector3 angularVelocity = Prim.ForceRotationalVelocity; 990 Vector3 preEfficiencyContrib = verticalAttractionContribution;
880 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 991 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
881 vertattr.X += bounce * angularVelocity.X; 992 verticalAttractionContribution *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
882 vertattr.Y += bounce * angularVelocity.Y;
883 993
884 VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}", 994 VDetailLog("{0},MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
885 Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr); 995 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
996 m_verticalAttractionEfficiency, efficencySquared,
997 verticalAttractionContribution);
998 */
886 999
887 } 1000 }
888 #endregion // Vertical attactor 1001 return ret;
1002 }
889 1003
890 #region Deflection 1004 public Vector3 ComputeAngularDeflection(float pTimestep)
1005 {
1006 Vector3 ret = Vector3.Zero;
891 1007
892 if (m_angularDeflectionEfficiency != 0) 1008 if (m_angularDeflectionEfficiency != 0)
893 { 1009 {
@@ -899,32 +1015,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
899 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); 1015 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
900 1016
901 // Scale by efficiency and timescale 1017 // Scale by efficiency and timescale
902 deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; 1018 ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
1019
1020 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", Prim.LocalID, preferredAxisOfMotion, ret);
903 1021
904 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}",
905 Prim.LocalID, preferredAxisOfMotion, deflection);
906 // This deflection computation is not correct. 1022 // This deflection computation is not correct.
907 deflection = Vector3.Zero; 1023 ret = Vector3.Zero;
908 } 1024 }
1025 return ret;
1026 }
909 1027
910 #endregion 1028 public Vector3 ComputeAngularBanking(float pTimestep)
911 1029 {
912 #region Banking 1030 Vector3 ret = Vector3.Zero;
913 1031
914 if (m_bankingEfficiency != 0) 1032 if (m_bankingEfficiency != 0)
915 { 1033 {
916 Vector3 dir = Vector3.One * Prim.ForceOrientation; 1034 Vector3 dir = Vector3.One * Prim.ForceOrientation;
917 float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); 1035 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1);
918 //Changes which way it banks in and out of turns 1036 //Changes which way it banks in and out of turns
919 1037
920 //Use the square of the efficiency, as it looks much more how SL banking works 1038 //Use the square of the efficiency, as it looks much more how SL banking works
921 float effSquared = (m_bankingEfficiency*m_bankingEfficiency); 1039 float effSquared = (m_bankingEfficiency * m_bankingEfficiency);
922 if (m_bankingEfficiency < 0) 1040 if (m_bankingEfficiency < 0)
923 effSquared *= -1; //Keep the negative! 1041 effSquared *= -1; //Keep the negative!
924 1042
925 float mix = Math.Abs(m_bankingMix); 1043 float mix = Math.Abs(m_bankingMix);
926 if (m_angularMotorVelocity.X == 0) 1044 if (m_angularMotorVelocity.X == 0)
927 { 1045 {
1046 // The vehicle is stopped
928 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) 1047 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
929 { 1048 {
930 Vector3 axisAngle; 1049 Vector3 axisAngle;
@@ -938,101 +1057,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
938 }*/ 1057 }*/
939 } 1058 }
940 else 1059 else
941 banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; 1060 {
1061 ret.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4;
1062 }
1063
1064 //If they are colliding, we probably shouldn't shove the prim around... probably
942 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) 1065 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
943 //If they are colliding, we probably shouldn't shove the prim around... probably
944 { 1066 {
945 float angVelZ = m_angularMotorVelocity.X*-1; 1067 float angVelZ = m_angularMotorVelocity.X * -1;
946 /*if(angVelZ > mix) 1068 /*if(angVelZ > mix)
947 angVelZ = mix; 1069 angVelZ = mix;
948 else if(angVelZ < -mix) 1070 else if(angVelZ < -mix)
949 angVelZ = -mix;*/ 1071 angVelZ = -mix;*/
950 //This controls how fast and how far the banking occurs 1072 //This controls how fast and how far the banking occurs
951 Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); 1073 Vector3 bankingRot = new Vector3(angVelZ * (effSquared * mult), 0, 0);
952 if (bankingRot.X > 3) 1074 if (bankingRot.X > 3)
953 bankingRot.X = 3; 1075 bankingRot.X = 3;
954 else if (bankingRot.X < -3) 1076 else if (bankingRot.X < -3)
955 bankingRot.X = -3; 1077 bankingRot.X = -3;
956 bankingRot *= Prim.ForceOrientation; 1078 bankingRot *= Prim.ForceOrientation;
957 banking += bankingRot; 1079 ret += bankingRot;
958 } 1080 }
959 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; 1081 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency;
960 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", 1082 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},effSq={3},mult={4},mix={5},banking={6}",
961 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); 1083 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, effSquared, mult, mix, ret);
962 } 1084 }
1085 return ret;
1086 }
963 1087
964 #endregion
965
966 m_lastVertAttractor = vertattr;
967
968 // Sum velocities
969 m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection;
970
971 #region Linear Motor Offset
972
973 //Offset section
974 if (m_linearMotorOffset != Vector3.Zero)
975 {
976 //Offset of linear velocity doesn't change the linear velocity,
977 // but causes a torque to be applied, for example...
978 //
979 // IIIII >>> IIIII
980 // IIIII >>> IIIII
981 // IIIII >>> IIIII
982 // ^
983 // | Applying a force at the arrow will cause the object to move forward, but also rotate
984 //
985 //
986 // The torque created is the linear velocity crossed with the offset
987
988 // NOTE: this computation does should be in the linear section
989 // because there we know the impulse being applied.
990 Vector3 torqueFromOffset = Vector3.Zero;
991 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
992 if (float.IsNaN(torqueFromOffset.X))
993 torqueFromOffset.X = 0;
994 if (float.IsNaN(torqueFromOffset.Y))
995 torqueFromOffset.Y = 0;
996 if (float.IsNaN(torqueFromOffset.Z))
997 torqueFromOffset.Z = 0;
998 torqueFromOffset *= m_vehicleMass;
999 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
1000 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1001 }
1002
1003 #endregion
1004
1005 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1006 {
1007 m_lastAngularVelocity.X = 0;
1008 m_lastAngularVelocity.Y = 0;
1009 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
1010 }
1011
1012 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
1013 {
1014 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
1015 Prim.ZeroAngularMotion(true);
1016 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
1017 }
1018 else
1019 {
1020 // Apply to the body.
1021 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
1022 // Since we are stuffing the angular velocity directly into the object, the computed
1023 // velocity needs to be scaled by the timestep.
1024 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity);
1025 Prim.ForceRotationalVelocity = applyAngularForce;
1026
1027 // Decay the angular movement for next time
1028 Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep;
1029 m_lastAngularVelocity *= Vector3.One - decayamount;
1030
1031 VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}",
1032 Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity);
1033 }
1034 } //end MoveAngular
1035 1088
1089 // This is from previous instantiations of XXXDynamics.cs.
1090 // Applies roll reference frame.
1091 // TODO: is this the right way to separate the code to do this operation?
1092 // Should this be in MoveAngular()?
1036 internal void LimitRotation(float timestep) 1093 internal void LimitRotation(float timestep)
1037 { 1094 {
1038 Quaternion rotq = Prim.ForceOrientation; 1095 Quaternion rotq = Prim.ForceOrientation;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 436e043..0df4310 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -82,9 +82,9 @@ public abstract class BSLinkset
82 82
83 // Some linksets have a preferred physical shape. 83 // Some linksets have a preferred physical shape.
84 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. 84 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
85 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 85 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
86 { 86 {
87 return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 87 return BSPhysicsShapeType.SHAPE_UNKNOWN;
88 } 88 }
89 89
90 // Linksets move around the children so the linkset might need to compute the child position 90 // Linksets move around the children so the linkset might need to compute the child position
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 3238c85..b9c2cf9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -42,12 +42,12 @@ public sealed class BSLinksetCompound : BSLinkset
42 } 42 }
43 43
44 // For compound implimented linksets, if there are children, use compound shape for the root. 44 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 { 46 {
47 ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren) 48 if (IsRoot(requestor) && HasAnyChildren)
49 { 49 {
50 ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; 50 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
51 } 51 }
52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); 52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
53 return ret; 53 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
new file mode 100755
index 0000000..663b6f4
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
@@ -0,0 +1,191 @@
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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using System.Reflection;
31using Nini.Config;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public struct MaterialAttributes
37{
38 // Material type values that correspond with definitions for LSL
39 public enum Material : int
40 {
41 Stone = 0,
42 Metal,
43 Glass,
44 Wood,
45 Flesh,
46 Plastic,
47 Rubber,
48 Light,
49 // Hereafter are BulletSim additions
50 Avatar,
51 NumberOfTypes // the count of types in the enum.
52 }
53 // Names must be in the order of the above enum.
54 public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
55 "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
56 public static string[] MaterialAttribs = { "Density", "Friction", "Restitution",
57 "ccdMotionThreshold", "ccdSweptSphereRadius" };
58
59 public MaterialAttributes(string t, float d, float f, float r, float ccdM, float ccdS)
60 {
61 type = t;
62 density = d;
63 friction = f;
64 restitution = r;
65 ccdMotionThreshold = ccdM;
66 ccdSweptSphereRadius = ccdS;
67 }
68 public string type;
69 public float density;
70 public float friction;
71 public float restitution;
72 public float ccdMotionThreshold;
73 public float ccdSweptSphereRadius;
74}
75
76public static class BSMaterials
77{
78 public static MaterialAttributes[] Attributes;
79
80 static BSMaterials()
81 {
82 // Attribute sets for both the non-physical and physical instances of materials.
83 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
84 }
85
86 // This is where all the default material attributes are defined.
87 public static void InitializeFromDefaults(ConfigurationParameters parms)
88 {
89 // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
90 // "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
91 float dFriction = parms.defaultFriction;
92 float dRestitution = parms.defaultRestitution;
93 float dDensity = parms.defaultDensity;
94 float dCcdM = parms.ccdMotionThreshold;
95 float dCcdS = parms.ccdSweptSphereRadius;
96 Attributes[(int)MaterialAttributes.Material.Stone] =
97 new MaterialAttributes("stone",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
98 Attributes[(int)MaterialAttributes.Material.Metal] =
99 new MaterialAttributes("metal",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
100 Attributes[(int)MaterialAttributes.Material.Glass] =
101 new MaterialAttributes("glass",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
102 Attributes[(int)MaterialAttributes.Material.Wood] =
103 new MaterialAttributes("wood",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
104 Attributes[(int)MaterialAttributes.Material.Flesh] =
105 new MaterialAttributes("flesh",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
106 Attributes[(int)MaterialAttributes.Material.Plastic] =
107 new MaterialAttributes("plastic",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
108 Attributes[(int)MaterialAttributes.Material.Rubber] =
109 new MaterialAttributes("rubber",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
110 Attributes[(int)MaterialAttributes.Material.Light] =
111 new MaterialAttributes("light",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
112 Attributes[(int)MaterialAttributes.Material.Avatar] =
113 new MaterialAttributes("avatar",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
114
115 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
116 new MaterialAttributes("stonePhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
117 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
118 new MaterialAttributes("metalPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
119 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
120 new MaterialAttributes("glassPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
121 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
122 new MaterialAttributes("woodPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
123 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
124 new MaterialAttributes("fleshPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
125 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
126 new MaterialAttributes("plasticPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
127 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
128 new MaterialAttributes("rubberPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
129 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
130 new MaterialAttributes("lightPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
131 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
132 new MaterialAttributes("avatarPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
133 }
134
135 // Under the [BulletSim] section, one can change the individual material
136 // attribute values. The format of the configuration parameter is:
137 // <materialName><Attribute>["Physical"] = floatValue
138 // For instance:
139 // [BulletSim]
140 // StoneFriction = 0.2
141 // FleshRestitutionPhysical = 0.8
142 // Materials can have different parameters for their static and
143 // physical instantiations. When setting the non-physical value,
144 // both values are changed. Setting the physical value only changes
145 // the physical value.
146 public static void InitializefromParameters(IConfig pConfig)
147 {
148 int matType = 0;
149 foreach (string matName in MaterialAttributes.MaterialNames)
150 {
151 foreach (string attribName in MaterialAttributes.MaterialAttribs)
152 {
153 string paramName = matName + attribName;
154 if (pConfig.Contains(paramName))
155 {
156 float paramValue = pConfig.GetFloat(paramName);
157 SetAttributeValue(matType, attribName, paramValue);
158 // set the physical value also
159 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
160 }
161 paramName += "Physical";
162 if (pConfig.Contains(paramName))
163 {
164 float paramValue = pConfig.GetFloat(paramName);
165 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
166 }
167 }
168 matType++;
169 }
170 }
171
172 private static void SetAttributeValue(int matType, string attribName, float val)
173 {
174 MaterialAttributes thisAttrib = Attributes[matType];
175 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName);
176 if (fieldInfo != null)
177 {
178 fieldInfo.SetValue(thisAttrib, val);
179 Attributes[matType] = thisAttrib;
180 }
181 }
182
183 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
184 {
185 int ind = (int)type;
186 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
187 return Attributes[ind];
188 }
189
190}
191}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index bc6e4c4..e91bfa8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -1,104 +1,169 @@
1using System; 1using System;
2using System.Collections.Generic; 2using System.Collections.Generic;
3using System.Text; 3using System.Text;
4using OpenMetaverse; 4using OpenMetaverse;
5 5
6namespace OpenSim.Region.Physics.BulletSPlugin 6namespace OpenSim.Region.Physics.BulletSPlugin
7{ 7{
8public abstract class BSMotor 8public abstract class BSMotor
9{ 9{
10 public virtual void Reset() { } 10 // Timescales and other things can be turned off by setting them to 'infinite'.
11 public virtual void Zero() { } 11 public const float Infinite = 10000f;
12} 12 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
13// Can all the incremental stepping be replaced with motor classes? 13
14public class BSVMotor : BSMotor 14 public BSMotor(string useName)
15{ 15 {
16 public Vector3 FrameOfReference { get; set; } 16 UseName = useName;
17 public Vector3 Offset { get; set; } 17 PhysicsScene = null;
18 18 }
19 public float TimeScale { get; set; } 19 public virtual void Reset() { }
20 public float TargetValueDecayTimeScale { get; set; } 20 public virtual void Zero() { }
21 public Vector3 CurrentValueReductionTimescale { get; set; } 21
22 public float Efficiency { get; set; } 22 public string UseName { get; private set; }
23 23 // Used only for outputting debug information. Might not be set so check for null.
24 public Vector3 TargetValue { get; private set; } 24 public BSScene PhysicsScene { get; set; }
25 public Vector3 CurrentValue { get; private set; } 25 protected void MDetailLog(string msg, params Object[] parms)
26 26 {
27 27 if (PhysicsScene != null)
28 28 {
29 BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 29 if (PhysicsScene.VehicleLoggingEnabled)
30 { 30 {
31 TimeScale = timeScale; 31 PhysicsScene.DetailLog(msg, parms);
32 TargetValueDecayTimeScale = decayTimeScale; 32 }
33 CurrentValueReductionTimescale = frictionTimeScale; 33 }
34 Efficiency = efficiency; 34 }
35 } 35}
36 public void SetCurrent(Vector3 current) 36// Can all the incremental stepping be replaced with motor classes?
37 { 37public class BSVMotor : BSMotor
38 CurrentValue = current; 38{
39 } 39 public Vector3 FrameOfReference { get; set; }
40 public void SetTarget(Vector3 target) 40 public Vector3 Offset { get; set; }
41 { 41
42 TargetValue = target; 42 public float TimeScale { get; set; }
43 } 43 public float TargetValueDecayTimeScale { get; set; }
44 public Vector3 Step(float timeStep) 44 public Vector3 FrictionTimescale { get; set; }
45 { 45 public float Efficiency { get; set; }
46 if (CurrentValue.LengthSquared() > 0.001f) 46
47 { 47 public Vector3 TargetValue { get; private set; }
48 // Vector3 origDir = Target; // DEBUG 48 public Vector3 CurrentValue { get; private set; }
49 // Vector3 origVel = CurrentValue; // DEBUG 49
50 50 public BSVMotor(string useName)
51 // Add (desiredVelocity - currentAppliedVelocity) / howLongItShouldTakeToComplete 51 : base(useName)
52 Vector3 addAmount = (TargetValue - CurrentValue)/(TargetValue) * timeStep; 52 {
53 CurrentValue += addAmount; 53 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
54 54 Efficiency = 1f;
55 float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; 55 FrictionTimescale = BSMotor.InfiniteVector;
56 TargetValue *= (1f - decayFactor); 56 CurrentValue = TargetValue = Vector3.Zero;
57 57 }
58 Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep; 58 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
59 CurrentValue *= (Vector3.One - frictionFactor); 59 : this(useName)
60 } 60 {
61 else 61 TimeScale = timeScale;
62 { 62 TargetValueDecayTimeScale = decayTimeScale;
63 // if what remains of direction is very small, zero it. 63 FrictionTimescale = frictionTimeScale;
64 TargetValue = Vector3.Zero; 64 Efficiency = efficiency;
65 CurrentValue = Vector3.Zero; 65 CurrentValue = TargetValue = Vector3.Zero;
66 66 }
67 // VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); 67 public void SetCurrent(Vector3 current)
68 } 68 {
69 return CurrentValue; 69 CurrentValue = current;
70 } 70 }
71} 71 public void SetTarget(Vector3 target)
72 72 {
73public class BSFMotor : BSMotor 73 TargetValue = target;
74{ 74 }
75 public float TimeScale { get; set; } 75 public Vector3 Step(float timeStep)
76 public float DecayTimeScale { get; set; } 76 {
77 public float Friction { get; set; } 77 Vector3 returnCurrent = Vector3.Zero;
78 public float Efficiency { get; set; } 78 if (!CurrentValue.ApproxEquals(TargetValue, 0.01f))
79 79 {
80 public float Target { get; private set; } 80 Vector3 origTarget = TargetValue; // DEBUG
81 public float CurrentValue { get; private set; } 81 Vector3 origCurrVal = CurrentValue; // DEBUG
82 82
83 BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency) 83 // Addition = (desiredVector - currentAppliedVector) / secondsItShouldTakeToComplete
84 { 84 Vector3 addAmount = (TargetValue - CurrentValue)/TimeScale * timeStep;
85 } 85 CurrentValue += addAmount;
86 public void SetCurrent(float target) 86
87 { 87 returnCurrent = CurrentValue;
88 } 88
89 public void SetTarget(float target) 89 // The desired value reduces to zero which also reduces the difference with current.
90 { 90 // If the decay time is infinite, don't decay at all.
91 } 91 float decayFactor = 0f;
92 public float Step(float timeStep) 92 if (TargetValueDecayTimeScale != BSMotor.Infinite)
93 { 93 {
94 return 0f; 94 decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
95 } 95 TargetValue *= (1f - decayFactor);
96} 96 }
97public class BSPIDMotor : BSMotor 97
98{ 98 Vector3 frictionFactor = Vector3.Zero;
99 // TODO: write and use this one 99 if (FrictionTimescale != BSMotor.InfiniteVector)
100 BSPIDMotor() 100 {
101 { 101 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
102 } 102 frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep;
103} 103 frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep;
104} 104 frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep;
105 CurrentValue *= (Vector3.One - frictionFactor);
106 }
107
108 MDetailLog("{0},BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
109 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
110 timeStep, TimeScale, addAmount,
111 TargetValueDecayTimeScale, decayFactor,
112 FrictionTimescale, frictionFactor);
113 MDetailLog("{0},BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
114 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue,
115 addAmount, decayFactor, frictionFactor, returnCurrent);
116 }
117 else
118 {
119 // Difference between what we have and target is small. Motor is done.
120 CurrentValue = Vector3.Zero;
121 TargetValue = Vector3.Zero;
122
123 MDetailLog("{0},BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}",
124 BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent);
125
126 }
127 return returnCurrent;
128 }
129 public override string ToString()
130 {
131 return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>",
132 UseName, CurrentValue, TargetValue, TargetValueDecayTimeScale, FrictionTimescale);
133 }
134}
135
136public class BSFMotor : BSMotor
137{
138 public float TimeScale { get; set; }
139 public float DecayTimeScale { get; set; }
140 public float Friction { get; set; }
141 public float Efficiency { get; set; }
142
143 public float Target { get; private set; }
144 public float CurrentValue { get; private set; }
145
146 public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency)
147 : base(useName)
148 {
149 }
150 public void SetCurrent(float target)
151 {
152 }
153 public void SetTarget(float target)
154 {
155 }
156 public float Step(float timeStep)
157 {
158 return 0f;
159 }
160}
161public class BSPIDMotor : BSMotor
162{
163 // TODO: write and use this one
164 public BSPIDMotor(string useName)
165 : base(useName)
166 {
167 }
168}
169}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index e803072..f6a890e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -47,7 +47,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
47 */ 47 */
48public abstract class BSPhysObject : PhysicsActor 48public abstract class BSPhysObject : PhysicsActor
49{ 49{
50 protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) 50 protected BSPhysObject()
51 {
52 }
53 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
51 { 54 {
52 PhysicsScene = parentScene; 55 PhysicsScene = parentScene;
53 LocalID = localID; 56 LocalID = localID;
@@ -91,9 +94,9 @@ public abstract class BSPhysObject : PhysicsActor
91 public PrimitiveBaseShape BaseShape { get; protected set; } 94 public PrimitiveBaseShape BaseShape { get; protected set; }
92 // Some types of objects have preferred physical representations. 95 // Some types of objects have preferred physical representations.
93 // Returns SHAPE_UNKNOWN if there is no preference. 96 // Returns SHAPE_UNKNOWN if there is no preference.
94 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape 97 public virtual BSPhysicsShapeType PreferredPhysicalShape
95 { 98 {
96 get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } 99 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
97 } 100 }
98 101
99 // When the physical properties are updated, an EntityProperty holds the update values. 102 // When the physical properties are updated, an EntityProperty holds the update values.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 14eb505..c62c79a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -47,7 +47,6 @@ public sealed class BSPrim : BSPhysObject
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. 48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
50 // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
51 50
52 private bool _grabbed; 51 private bool _grabbed;
53 private bool _isSelected; 52 private bool _isSelected;
@@ -88,13 +87,13 @@ public sealed class BSPrim : BSPhysObject
88 87
89 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 88 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
90 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 89 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
90 : base(parent_scene, localID, primName, "BSPrim")
91 { 91 {
92 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 92 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
93 base.BaseInitialize(parent_scene, localID, primName, "BSPrim");
94 _physicsActorType = (int)ActorTypes.Prim; 93 _physicsActorType = (int)ActorTypes.Prim;
95 _position = pos; 94 _position = pos;
96 _size = size; 95 _size = size;
97 Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 96 Scale = size; // the scale will be set by CreateGeom depending on object type
98 _orientation = rotation; 97 _orientation = rotation;
99 _buoyancy = 1f; 98 _buoyancy = 1f;
100 _velocity = OMV.Vector3.Zero; 99 _velocity = OMV.Vector3.Zero;
@@ -155,6 +154,8 @@ public sealed class BSPrim : BSPhysObject
155 public override OMV.Vector3 Size { 154 public override OMV.Vector3 Size {
156 get { return _size; } 155 get { return _size; }
157 set { 156 set {
157 // We presume the scale and size are the same. If scale must be changed for
158 // the physical shape, that is done when the geometry is built.
158 _size = value; 159 _size = value;
159 ForceBodyShapeRebuild(false); 160 ForceBodyShapeRebuild(false);
160 } 161 }
@@ -170,7 +171,7 @@ public sealed class BSPrim : BSPhysObject
170 } 171 }
171 } 172 }
172 // Whatever the linkset wants is what I want. 173 // Whatever the linkset wants is what I want.
173 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 174 public override BSPhysicsShapeType PreferredPhysicalShape
174 { get { return Linkset.PreferredPhysicalShape(this); } } 175 { get { return Linkset.PreferredPhysicalShape(this); } }
175 176
176 public override bool ForceBodyShapeRebuild(bool inTaintTime) 177 public override bool ForceBodyShapeRebuild(bool inTaintTime)
@@ -274,19 +275,19 @@ public sealed class BSPrim : BSPhysObject
274 if (!Linkset.IsRoot(this)) 275 if (!Linkset.IsRoot(this))
275 _position = Linkset.Position(this); 276 _position = Linkset.Position(this);
276 277
277 // don't do the GetObjectPosition for root elements because this function is called a zillion times 278 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
278 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 279 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
279 return _position; 280 return _position;
280 } 281 }
281 set { 282 set {
282 // If you must push the position into the physics engine, use ForcePosition. 283 // If the position must be forced into the physics engine, use ForcePosition.
283 if (_position == value) 284 if (_position == value)
284 { 285 {
285 return; 286 return;
286 } 287 }
287 _position = value; 288 _position = value;
288 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 289 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
289 PositionSanityCheck(); 290 PositionSanityCheck(false);
290 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 291 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
291 { 292 {
292 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 293 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
@@ -302,7 +303,7 @@ public sealed class BSPrim : BSPhysObject
302 } 303 }
303 set { 304 set {
304 _position = value; 305 _position = value;
305 PositionSanityCheck(); 306 // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better.
306 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 307 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
307 ActivateIfPhysical(false); 308 ActivateIfPhysical(false);
308 } 309 }
@@ -311,52 +312,42 @@ public sealed class BSPrim : BSPhysObject
311 // Check that the current position is sane and, if not, modify the position to make it so. 312 // Check that the current position is sane and, if not, modify the position to make it so.
312 // Check for being below terrain and being out of bounds. 313 // Check for being below terrain and being out of bounds.
313 // Returns 'true' of the position was made sane by some action. 314 // Returns 'true' of the position was made sane by some action.
314 private bool PositionSanityCheck() 315 private bool PositionSanityCheck(bool inTaintTime)
315 { 316 {
316 bool ret = false; 317 bool ret = false;
317 318
318 // If totally below the ground, move the prim up
319 // TODO: figure out the right solution for this... only for dynamic objects?
320 /*
321 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 319 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
320 OMV.Vector3 upForce = OMV.Vector3.Zero;
322 if (Position.Z < terrainHeight) 321 if (Position.Z < terrainHeight)
323 { 322 {
324 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 323 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
325 _position.Z = terrainHeight + 2.0f; 324 float targetHeight = terrainHeight + (Size.Z / 2f);
325 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
326 upForce.Z = (terrainHeight - Position.Z) * 1f;
326 ret = true; 327 ret = true;
327 } 328 }
328 */ 329
329 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 330 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
330 { 331 {
331 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 332 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
332 // TODO: a floating motor so object will bob in the water 333 // TODO: a floating motor so object will bob in the water
333 if (Position.Z < waterHeight) 334 if (Math.Abs(Position.Z - waterHeight) > 0.1f)
334 { 335 {
335 _position.Z = waterHeight; 336 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
337 upForce.Z = (waterHeight - Position.Z) * 1f;
336 ret = true; 338 ret = true;
337 } 339 }
338 } 340 }
339 341
340 // TODO: check for out of bounds 342 // TODO: check for out of bounds
341 return ret;
342 }
343 343
344 // A version of the sanity check that also makes sure a new position value is 344 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
345 // pushed to the physics engine. This routine would be used by anyone 345 // TODO: This should be intergrated with a geneal physics action mechanism.
346 // who is not already pushing the value. 346 // TODO: This should be moderated with PID'ness.
347 private bool PositionSanityCheck(bool inTaintTime) 347 if (ret)
348 {
349 bool ret = false;
350 if (PositionSanityCheck())
351 { 348 {
352 // The new position value must be pushed into the physics engine but we can't 349 // Apply upforce and overcome gravity.
353 // just assign to "Position" because of potential call loops. 350 AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime);
354 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate()
355 {
356 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
357 ForcePosition = _position;
358 });
359 ret = true;
360 } 351 }
361 return ret; 352 return ret;
362 } 353 }
@@ -940,6 +931,7 @@ public sealed class BSPrim : BSPhysObject
940 public override void AddForce(OMV.Vector3 force, bool pushforce) { 931 public override void AddForce(OMV.Vector3 force, bool pushforce) {
941 AddForce(force, pushforce, false); 932 AddForce(force, pushforce, false);
942 } 933 }
934 // Applying a force just adds this to the total force on the object.
943 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 935 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
944 // for an object, doesn't matter if force is a pushforce or not 936 // for an object, doesn't matter if force is a pushforce or not
945 if (force.IsFinite()) 937 if (force.IsFinite())
@@ -971,6 +963,7 @@ public sealed class BSPrim : BSPhysObject
971 }); 963 });
972 } 964 }
973 965
966 // An impulse force is scaled by the mass of the object.
974 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) 967 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
975 { 968 {
976 OMV.Vector3 applyImpulse = impulse; 969 OMV.Vector3 applyImpulse = impulse;
@@ -1387,67 +1380,34 @@ public sealed class BSPrim : BSPhysObject
1387 1380
1388 public override void UpdateProperties(EntityProperties entprop) 1381 public override void UpdateProperties(EntityProperties entprop)
1389 { 1382 {
1390 /* 1383 // Updates only for individual prims and for the root object of a linkset.
1391 UpdatedProperties changed = 0; 1384 if (Linkset.IsRoot(this))
1392 // assign to the local variables so the normal set action does not happen
1393 // if (_position != entprop.Position)
1394 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1395 {
1396 _position = entprop.Position;
1397 changed |= UpdatedProperties.Position;
1398 }
1399 // if (_orientation != entprop.Rotation)
1400 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1401 {
1402 _orientation = entprop.Rotation;
1403 changed |= UpdatedProperties.Rotation;
1404 }
1405 // if (_velocity != entprop.Velocity)
1406 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1407 {
1408 _velocity = entprop.Velocity;
1409 changed |= UpdatedProperties.Velocity;
1410 }
1411 // if (_acceleration != entprop.Acceleration)
1412 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1413 {
1414 _acceleration = entprop.Acceleration;
1415 changed |= UpdatedProperties.Acceleration;
1416 }
1417 // if (_rotationalVelocity != entprop.RotationalVelocity)
1418 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1419 {
1420 _rotationalVelocity = entprop.RotationalVelocity;
1421 changed |= UpdatedProperties.RotationalVel;
1422 }
1423 if (changed != 0)
1424 { 1385 {
1425 // Only update the position of single objects and linkset roots 1386 // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
1426 if (this._parentPrim == null) 1387 // TODO: handle physics introduced by Bullet with computed vehicle physics.
1388 if (_vehicle.IsActive)
1427 { 1389 {
1428 base.RequestPhysicsterseUpdate(); 1390 entprop.RotationalVelocity = OMV.Vector3.Zero;
1429 } 1391 }
1430 }
1431 */
1432
1433 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1434 1392
1435 // Updates only for individual prims and for the root object of a linkset. 1393 // Assign directly to the local variables so the normal set action does not happen
1436 if (Linkset.IsRoot(this))
1437 {
1438 // Assign to the local variables so the normal set action does not happen
1439 _position = entprop.Position; 1394 _position = entprop.Position;
1440 _orientation = entprop.Rotation; 1395 _orientation = entprop.Rotation;
1441 _velocity = entprop.Velocity; 1396 _velocity = entprop.Velocity;
1442 _acceleration = entprop.Acceleration; 1397 _acceleration = entprop.Acceleration;
1443 _rotationalVelocity = entprop.RotationalVelocity; 1398 _rotationalVelocity = entprop.RotationalVelocity;
1444 1399
1400 // The sanity check can change the velocity and/or position.
1401 if (PositionSanityCheck(true))
1402 {
1403 entprop.Position = _position;
1404 entprop.Velocity = _velocity;
1405 }
1406
1445 // remember the current and last set values 1407 // remember the current and last set values
1446 LastEntityProperties = CurrentEntityProperties; 1408 LastEntityProperties = CurrentEntityProperties;
1447 CurrentEntityProperties = entprop; 1409 CurrentEntityProperties = entprop;
1448 1410
1449 PositionSanityCheck(true);
1450
1451 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; 1411 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1452 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", 1412 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1453 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); 1413 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 1cc607a..09b1423 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,23 +39,10 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Test sculpties (verified that they don't work)
43// Compute physics FPS reasonably
44// Based on material, set density and friction 42// Based on material, set density and friction
45// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
46// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
47// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
48// At the moment, physical and phantom causes object to drop through the terrain
49// Physical phantom objects and related typing (collision options )
50// Check out llVolumeDetect. Must do something for that.
51// Use collision masks for collision with terrain and phantom objects
52// More efficient memory usage when passing hull information from BSPrim to BulletSim 43// More efficient memory usage when passing hull information from BSPrim to BulletSim
53// Should prim.link() and prim.delink() membership checking happen at taint time?
54// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
55// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 44// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
56// Implement LockAngularMotion 45// Implement LockAngularMotion
57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
58// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
59// Add PID movement operations. What does ScenePresence.MoveToTarget do? 46// Add PID movement operations. What does ScenePresence.MoveToTarget do?
60// Check terrain size. 128 or 127? 47// Check terrain size. 128 or 127?
61// Raycast 48// Raycast
@@ -234,6 +221,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
234 if (m_physicsLoggingEnabled) 221 if (m_physicsLoggingEnabled)
235 { 222 {
236 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 223 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
224 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages.
237 } 225 }
238 else 226 else
239 { 227 {
@@ -308,6 +296,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
308 // Do any replacements in the parameters 296 // Do any replacements in the parameters
309 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 297 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
310 } 298 }
299
300 // The material characteristics.
301 BSMaterials.InitializeFromDefaults(Params);
302 if (pConfig != null)
303 {
304 BSMaterials.InitializefromParameters(pConfig);
305 }
311 } 306 }
312 } 307 }
313 308
@@ -520,9 +515,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
520 collidersCount = 0; 515 collidersCount = 0;
521 } 516 }
522 517
523 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 518 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in.
524 519
525 // Get a value for 'now' so all the collision and update routines don't have to get their own 520 // Get a value for 'now' so all the collision and update routines don't have to get their own.
526 SimulationNowTime = Util.EnvironmentTickCount(); 521 SimulationNowTime = Util.EnvironmentTickCount();
527 522
528 // If there were collisions, process them by sending the event to the prim. 523 // If there were collisions, process them by sending the event to the prim.
@@ -568,6 +563,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
568 ObjectsWithCollisions.Remove(po); 563 ObjectsWithCollisions.Remove(po);
569 ObjectsWithNoMoreCollisions.Clear(); 564 ObjectsWithNoMoreCollisions.Clear();
570 } 565 }
566 // Done with collisions.
571 567
572 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 568 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
573 if (updatedEntityCount > 0) 569 if (updatedEntityCount > 0)
@@ -591,9 +587,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
591 587
592 // The physics engine returns the number of milliseconds it simulated this call. 588 // The physics engine returns the number of milliseconds it simulated this call.
593 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 589 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
594 // We multiply by 55 to give a recognizable running rate (55 or less). 590 // Multiply by 55 to give a nominal frame rate of 55.
595 return numSubSteps * m_fixedTimeStep * 1000 * 55; 591 return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f;
596 // return timeStep * 1000 * 55;
597 } 592 }
598 593
599 // Something has collided 594 // Something has collided
@@ -683,7 +678,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
683 #region Taints 678 #region Taints
684 679
685 // Calls to the PhysicsActors can't directly call into the physics engine 680 // Calls to the PhysicsActors can't directly call into the physics engine
686 // because it might be busy. We delay changes to a known time. 681 // because it might be busy. We delay changes to a known time.
687 // We rely on C#'s closure to save and restore the context for the delegate. 682 // We rely on C#'s closure to save and restore the context for the delegate.
688 public void TaintedObject(String ident, TaintCallback callback) 683 public void TaintedObject(String ident, TaintCallback callback)
689 { 684 {
@@ -712,7 +707,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
712 // here just before the physics engine is called to step the simulation. 707 // here just before the physics engine is called to step the simulation.
713 public void ProcessTaints() 708 public void ProcessTaints()
714 { 709 {
715 InTaintTime = true; 710 InTaintTime = true; // Only used for debugging so locking is not necessary.
716 ProcessRegularTaints(); 711 ProcessRegularTaints();
717 ProcessPostTaintTaints(); 712 ProcessPostTaintTaints();
718 InTaintTime = false; 713 InTaintTime = false;
@@ -758,6 +753,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
758 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count); 753 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
759 } 754 }
760 */ 755 */
756
761 // swizzle a new list into the list location so we can process what's there 757 // swizzle a new list into the list location so we can process what's there
762 List<TaintCallbackEntry> oldList; 758 List<TaintCallbackEntry> oldList;
763 lock (_taintLock) 759 lock (_taintLock)
@@ -787,8 +783,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
787 // will replace any previous operation by the same object. 783 // will replace any previous operation by the same object.
788 public void PostTaintObject(String ident, uint ID, TaintCallback callback) 784 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
789 { 785 {
790 if (!m_initialized) return;
791
792 string uniqueIdent = ident + "-" + ID.ToString(); 786 string uniqueIdent = ident + "-" + ID.ToString();
793 lock (_taintLock) 787 lock (_taintLock)
794 { 788 {
@@ -864,13 +858,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
864 } 858 }
865 } 859 }
866 860
861 // Only used for debugging. Does not change state of anything so locking is not necessary.
867 public bool AssertInTaintTime(string whereFrom) 862 public bool AssertInTaintTime(string whereFrom)
868 { 863 {
869 if (!InTaintTime) 864 if (!InTaintTime)
870 { 865 {
871 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); 866 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
872 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); 867 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
873 Util.PrintCallStack(); 868 Util.PrintCallStack(); // Prints the stack into the DEBUG log file.
874 } 869 }
875 return InTaintTime; 870 return InTaintTime;
876 } 871 }
@@ -1069,7 +1064,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1069 (s,p,l,v) => { s.PID_P = v; } ), 1064 (s,p,l,v) => { s.PID_P = v; } ),
1070 1065
1071 new ParameterDefn("DefaultFriction", "Friction factor used on new objects", 1066 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
1072 0.5f, 1067 0.2f,
1073 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); }, 1068 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
1074 (s) => { return s.m_params[0].defaultFriction; }, 1069 (s) => { return s.m_params[0].defaultFriction; },
1075 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ), 1070 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
@@ -1084,7 +1079,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1084 (s) => { return s.m_params[0].defaultRestitution; }, 1079 (s) => { return s.m_params[0].defaultRestitution; },
1085 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ), 1080 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
1086 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", 1081 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
1087 0f, 1082 0.04f,
1088 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); }, 1083 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
1089 (s) => { return s.m_params[0].collisionMargin; }, 1084 (s) => { return s.m_params[0].collisionMargin; },
1090 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ), 1085 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
@@ -1145,8 +1140,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1145 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, 1140 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1146 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), 1141 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1147 1142
1143 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
1144 (float)BSTerrainPhys.TerrainImplementation.Mesh,
1145 (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); },
1146 (s) => { return s.m_params[0].terrainImplementation; },
1147 (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ),
1148 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1148 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1149 0.5f, 1149 0.3f,
1150 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, 1150 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1151 (s) => { return s.m_params[0].terrainFriction; }, 1151 (s) => { return s.m_params[0].terrainFriction; },
1152 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), 1152 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
@@ -1160,13 +1160,19 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1160 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, 1160 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1161 (s) => { return s.m_params[0].terrainRestitution; }, 1161 (s) => { return s.m_params[0].terrainRestitution; },
1162 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), 1162 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1163 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
1164 0.04f,
1165 (s,cf,p,v) => { s.m_params[0].terrainCollisionMargin = cf.GetFloat(p, v); },
1166 (s) => { return s.m_params[0].terrainCollisionMargin; },
1167 (s,p,l,v) => { s.m_params[0].terrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
1168
1163 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1169 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1164 0.2f, 1170 0.2f,
1165 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1171 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1166 (s) => { return s.m_params[0].avatarFriction; }, 1172 (s) => { return s.m_params[0].avatarFriction; },
1167 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), 1173 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1168 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", 1174 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1169 10f, 1175 10.0f,
1170 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, 1176 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1171 (s) => { return s.m_params[0].avatarStandingFriction; }, 1177 (s) => { return s.m_params[0].avatarStandingFriction; },
1172 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), 1178 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
@@ -1180,11 +1186,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1180 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1186 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1181 (s) => { return s.m_params[0].avatarRestitution; }, 1187 (s) => { return s.m_params[0].avatarRestitution; },
1182 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1188 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1183 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1189 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
1184 0.37f, 1190 0.6f,
1185 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1191 (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); },
1186 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1192 (s) => { return s.m_params[0].avatarCapsuleWidth; },
1187 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1193 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ),
1194 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
1195 0.45f,
1196 (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); },
1197 (s) => { return s.m_params[0].avatarCapsuleDepth; },
1198 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ),
1188 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1199 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1189 1.5f, 1200 1.5f,
1190 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1201 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
@@ -1196,6 +1207,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1196 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1207 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1197 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1208 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1198 1209
1210 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
1211 0.95f,
1212 (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); },
1213 (s) => { return s.m_params[0].vehicleAngularDamping; },
1214 (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ),
1199 1215
1200 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1216 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1201 0f, 1217 0f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 29a23c0..892c34b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -178,7 +178,7 @@ public sealed class BSShapeCollection : IDisposable
178 bool ret = false; 178 bool ret = false;
179 switch (shape.type) 179 switch (shape.type)
180 { 180 {
181 case ShapeData.PhysicsShapeType.SHAPE_MESH: 181 case BSPhysicsShapeType.SHAPE_MESH:
182 MeshDesc meshDesc; 182 MeshDesc meshDesc;
183 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) 183 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
184 { 184 {
@@ -201,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable
201 meshDesc.lastReferenced = System.DateTime.Now; 201 meshDesc.lastReferenced = System.DateTime.Now;
202 Meshes[shape.shapeKey] = meshDesc; 202 Meshes[shape.shapeKey] = meshDesc;
203 break; 203 break;
204 case ShapeData.PhysicsShapeType.SHAPE_HULL: 204 case BSPhysicsShapeType.SHAPE_HULL:
205 HullDesc hullDesc; 205 HullDesc hullDesc;
206 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) 206 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
207 { 207 {
@@ -224,7 +224,7 @@ public sealed class BSShapeCollection : IDisposable
224 hullDesc.lastReferenced = System.DateTime.Now; 224 hullDesc.lastReferenced = System.DateTime.Now;
225 Hulls[shape.shapeKey] = hullDesc; 225 Hulls[shape.shapeKey] = hullDesc;
226 break; 226 break;
227 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: 227 case BSPhysicsShapeType.SHAPE_UNKNOWN:
228 break; 228 break;
229 default: 229 default:
230 // Native shapes are not tracked and they don't go into any list 230 // Native shapes are not tracked and they don't go into any list
@@ -255,16 +255,16 @@ public sealed class BSShapeCollection : IDisposable
255 { 255 {
256 switch (shape.type) 256 switch (shape.type)
257 { 257 {
258 case ShapeData.PhysicsShapeType.SHAPE_HULL: 258 case BSPhysicsShapeType.SHAPE_HULL:
259 DereferenceHull(shape, shapeCallback); 259 DereferenceHull(shape, shapeCallback);
260 break; 260 break;
261 case ShapeData.PhysicsShapeType.SHAPE_MESH: 261 case BSPhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback); 262 DereferenceMesh(shape, shapeCallback);
263 break; 263 break;
264 case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: 264 case BSPhysicsShapeType.SHAPE_COMPOUND:
265 DereferenceCompound(shape, shapeCallback); 265 DereferenceCompound(shape, shapeCallback);
266 break; 266 break;
267 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: 267 case BSPhysicsShapeType.SHAPE_UNKNOWN:
268 break; 268 break;
269 default: 269 default:
270 break; 270 break;
@@ -352,28 +352,28 @@ public sealed class BSShapeCollection : IDisposable
352 BulletShape shapeInfo = new BulletShape(cShape); 352 BulletShape shapeInfo = new BulletShape(cShape);
353 if (TryGetMeshByPtr(cShape, out meshDesc)) 353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 { 354 {
355 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; 355 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey; 356 shapeInfo.shapeKey = meshDesc.shapeKey;
357 } 357 }
358 else 358 else
359 { 359 {
360 if (TryGetHullByPtr(cShape, out hullDesc)) 360 if (TryGetHullByPtr(cShape, out hullDesc))
361 { 361 {
362 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; 362 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey; 363 shapeInfo.shapeKey = hullDesc.shapeKey;
364 } 364 }
365 else 365 else
366 { 366 {
367 if (BulletSimAPI.IsCompound2(cShape)) 367 if (BulletSimAPI.IsCompound2(cShape))
368 { 368 {
369 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; 369 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
370 } 370 }
371 else 371 else
372 { 372 {
373 if (BulletSimAPI.IsNativeShape2(cShape)) 373 if (BulletSimAPI.IsNativeShape2(cShape))
374 { 374 {
375 shapeInfo.isNativeShape = true; 375 shapeInfo.isNativeShape = true;
376 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) 376 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
377 } 377 }
378 } 378 }
379 } 379 }
@@ -381,7 +381,7 @@ public sealed class BSShapeCollection : IDisposable
381 381
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); 382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383 383
384 if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) 384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 { 385 {
386 DereferenceShape(shapeInfo, true, null); 386 DereferenceShape(shapeInfo, true, null);
387 } 387 }
@@ -405,11 +405,11 @@ public sealed class BSShapeCollection : IDisposable
405 bool ret = false; 405 bool ret = false;
406 bool haveShape = false; 406 bool haveShape = false;
407 407
408 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 408 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
409 { 409 {
410 // an avatar capsule is close to a native shape (it is not shared) 410 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, 411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
412 ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); 412 FixedShapeKey.KEY_CAPSULE, shapeCallback);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true; 414 ret = true;
415 haveShape = true; 415 haveShape = true;
@@ -417,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable
417 417
418 // Compound shapes are handled special as they are rebuilt from scratch. 418 // Compound shapes are handled special as they are rebuilt from scratch.
419 // This isn't too great a hardship since most of the child shapes will already been created. 419 // This isn't too great a hardship since most of the child shapes will already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) 420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 { 421 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback); 422 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); 423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
@@ -460,11 +460,11 @@ public sealed class BSShapeCollection : IDisposable
460 haveShape = true; 460 haveShape = true;
461 if (forceRebuild 461 if (forceRebuild
462 || prim.Scale != prim.Size 462 || prim.Scale != prim.Size
463 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE 463 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
464 ) 464 )
465 { 465 {
466 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, 466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); 467 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", 468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape); 469 prim.LocalID, forceRebuild, prim.PhysShape);
470 } 470 }
@@ -474,11 +474,11 @@ public sealed class BSShapeCollection : IDisposable
474 haveShape = true; 474 haveShape = true;
475 if (forceRebuild 475 if (forceRebuild
476 || prim.Scale != prim.Size 476 || prim.Scale != prim.Size
477 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX 477 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
478 ) 478 )
479 { 479 {
480 ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, 480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); 481 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", 482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape); 483 prim.LocalID, forceRebuild, prim.PhysShape);
484 } 484 }
@@ -519,15 +519,12 @@ public sealed class BSShapeCollection : IDisposable
519 // Creates a native shape and assignes it to prim.BSShape. 519 // Creates a native shape and assignes it to prim.BSShape.
520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). 520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
521 private bool GetReferenceToNativeShape(BSPhysObject prim, 521 private bool GetReferenceToNativeShape(BSPhysObject prim,
522 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, 522 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
523 ShapeDestructionCallback shapeCallback) 523 ShapeDestructionCallback shapeCallback)
524 { 524 {
525 // release any previous shape 525 // release any previous shape
526 DereferenceShape(prim.PhysShape, true, shapeCallback); 526 DereferenceShape(prim.PhysShape, true, shapeCallback);
527 527
528 // Bullet native objects are scaled by the Bullet engine so pass the size in
529 prim.Scale = prim.Size;
530
531 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
532 529
533 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
@@ -538,8 +535,8 @@ public sealed class BSShapeCollection : IDisposable
538 return true; 535 return true;
539 } 536 }
540 537
541 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, 538 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
542 ShapeData.FixedShapeKey shapeKey) 539 FixedShapeKey shapeKey)
543 { 540 {
544 BulletShape newShape; 541 BulletShape newShape;
545 // Need to make sure the passed shape information is for the native type. 542 // Need to make sure the passed shape information is for the native type.
@@ -547,12 +544,13 @@ public sealed class BSShapeCollection : IDisposable
547 nativeShapeData.Type = shapeType; 544 nativeShapeData.Type = shapeType;
548 nativeShapeData.ID = prim.LocalID; 545 nativeShapeData.ID = prim.LocalID;
549 nativeShapeData.Scale = prim.Scale; 546 nativeShapeData.Scale = prim.Scale;
550 nativeShapeData.Size = prim.Scale; 547 nativeShapeData.Size = prim.Scale; // unneeded, I think.
551 nativeShapeData.MeshKey = (ulong)shapeKey; 548 nativeShapeData.MeshKey = (ulong)shapeKey;
552 nativeShapeData.HullKey = (ulong)shapeKey; 549 nativeShapeData.HullKey = (ulong)shapeKey;
553 550
554 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 551 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
555 { 552 {
553 // The proper scale has been calculated in the prim.
556 newShape = new BulletShape( 554 newShape = new BulletShape(
557 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) 555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
558 , shapeType); 556 , shapeType);
@@ -560,6 +558,9 @@ public sealed class BSShapeCollection : IDisposable
560 } 558 }
561 else 559 else
562 { 560 {
561 // Native shapes are scaled in Bullet so set the scaling to the size
562 prim.Scale = prim.Size;
563 nativeShapeData.Scale = prim.Scale;
563 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); 564 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
564 } 565 }
565 if (newShape.ptr == IntPtr.Zero) 566 if (newShape.ptr == IntPtr.Zero)
@@ -585,7 +586,7 @@ public sealed class BSShapeCollection : IDisposable
585 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 586 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
586 587
587 // if this new shape is the same as last time, don't recreate the mesh 588 // if this new shape is the same as last time, don't recreate the mesh
588 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) 589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
589 return false; 590 return false;
590 591
591 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", 592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
@@ -643,7 +644,7 @@ public sealed class BSShapeCollection : IDisposable
643 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 644 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
644 } 645 }
645 } 646 }
646 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); 647 BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH);
647 newShape.shapeKey = newMeshKey; 648 newShape.shapeKey = newMeshKey;
648 649
649 return newShape; 650 return newShape;
@@ -659,7 +660,7 @@ public sealed class BSShapeCollection : IDisposable
659 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 660 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
660 661
661 // if the hull hasn't changed, don't rebuild it 662 // if the hull hasn't changed, don't rebuild it
662 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) 663 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
663 return false; 664 return false;
664 665
665 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", 666 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
@@ -780,7 +781,7 @@ public sealed class BSShapeCollection : IDisposable
780 } 781 }
781 } 782 }
782 783
783 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); 784 BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
784 newShape.shapeKey = newHullKey; 785 newShape.shapeKey = newHullKey;
785 786
786 return newShape; // 'true' means a new shape has been added to this prim 787 return newShape; // 'true' means a new shape has been added to this prim
@@ -803,7 +804,7 @@ public sealed class BSShapeCollection : IDisposable
803 // DereferenceShape(prim.PhysShape, true, shapeCallback); 804 // DereferenceShape(prim.PhysShape, true, shapeCallback);
804 805
805 BulletShape cShape = new BulletShape( 806 BulletShape cShape = new BulletShape(
806 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); 807 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND);
807 808
808 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 809 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
809 CreateGeomMeshOrHull(prim, shapeCallback); 810 CreateGeomMeshOrHull(prim, shapeCallback);
@@ -894,7 +895,7 @@ public sealed class BSShapeCollection : IDisposable
894 895
895 // While we figure out the real problem, stick a simple native shape on the object. 896 // While we figure out the real problem, stick a simple native shape on the object.
896 BulletShape fillinShape = 897 BulletShape fillinShape =
897 BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); 898 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
898 899
899 return fillinShape; 900 return fillinShape;
900 } 901 }
@@ -940,7 +941,7 @@ public sealed class BSShapeCollection : IDisposable
940 else 941 else
941 { 942 {
942 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 943 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
943 prim.LocalID, prim.ForcePosition, prim.ForceOrientation); 944 prim.LocalID, prim.RawPosition, prim.RawOrientation);
944 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 945 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
945 } 946 }
946 aBody = new BulletBody(prim.LocalID, bodyPtr); 947 aBody = new BulletBody(prim.LocalID, bodyPtr);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index 5e2c4a8..96cd55e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -1,213 +1,208 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Text; 31using System.Text;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35public abstract class BSShape 35public abstract class BSShape
36{ 36{
37 public IntPtr ptr { get; set; } 37 public IntPtr ptr { get; set; }
38 public ShapeData.PhysicsShapeType type { get; set; } 38 public BSPhysicsShapeType type { get; set; }
39 public System.UInt64 key { get; set; } 39 public System.UInt64 key { get; set; }
40 public int referenceCount { get; set; } 40 public int referenceCount { get; set; }
41 public DateTime lastReferenced { get; set; } 41 public DateTime lastReferenced { get; set; }
42 42
43 protected void Initialize() 43 public BSShape()
44 { 44 {
45 ptr = IntPtr.Zero; 45 ptr = IntPtr.Zero;
46 type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 46 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
47 key = 0; 47 key = 0;
48 referenceCount = 0; 48 referenceCount = 0;
49 lastReferenced = DateTime.Now; 49 lastReferenced = DateTime.Now;
50 } 50 }
51 51
52 // Get a reference to a physical shape. Create if it doesn't exist 52 // Get a reference to a physical shape. Create if it doesn't exist
53 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 53 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
54 { 54 {
55 BSShape ret = null; 55 BSShape ret = null;
56 56
57 if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 57 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
58 { 58 {
59 // an avatar capsule is close to a native shape (it is not shared) 59 // an avatar capsule is close to a native shape (it is not shared)
60 ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, 60 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
61 ShapeData.FixedShapeKey.KEY_CAPSULE); 61 FixedShapeKey.KEY_CAPSULE);
62 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); 62 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
63 } 63 }
64 64
65 // Compound shapes are handled special as they are rebuilt from scratch. 65 // Compound shapes are handled special as they are rebuilt from scratch.
66 // This isn't too great a hardship since most of the child shapes will already been created. 66 // This isn't too great a hardship since most of the child shapes will already been created.
67 if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) 67 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
68 { 68 {
69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added 69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
70 ret = BSShapeCompound.GetReference(prim); 70 ret = BSShapeCompound.GetReference(prim);
71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); 71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
72 } 72 }
73 73
74 if (ret == null) 74 if (ret == null)
75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); 75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
76 76
77 return ret; 77 return ret;
78 } 78 }
79 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 79 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
80 { 80 {
81 return null; 81 return null;
82 } 82 }
83 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 83 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
84 { 84 {
85 return null; 85 return null;
86 } 86 }
87 87
88 // Release the use of a physical shape. 88 // Release the use of a physical shape.
89 public abstract void Dereference(BSScene physicsScene); 89 public abstract void Dereference(BSScene physicsScene);
90 90
91 // All shapes have a static call to get a reference to the physical shape 91 // All shapes have a static call to get a reference to the physical shape
92 // protected abstract static BSShape GetReference(); 92 // protected abstract static BSShape GetReference();
93 93
94 public override string ToString() 94 public override string ToString()
95 { 95 {
96 StringBuilder buff = new StringBuilder(); 96 StringBuilder buff = new StringBuilder();
97 buff.Append("<p="); 97 buff.Append("<p=");
98 buff.Append(ptr.ToString("X")); 98 buff.Append(ptr.ToString("X"));
99 buff.Append(",s="); 99 buff.Append(",s=");
100 buff.Append(type.ToString()); 100 buff.Append(type.ToString());
101 buff.Append(",k="); 101 buff.Append(",k=");
102 buff.Append(key.ToString("X")); 102 buff.Append(key.ToString("X"));
103 buff.Append(",c="); 103 buff.Append(",c=");
104 buff.Append(referenceCount.ToString()); 104 buff.Append(referenceCount.ToString());
105 buff.Append(">"); 105 buff.Append(">");
106 return buff.ToString(); 106 return buff.ToString();
107 } 107 }
108} 108}
109 109
110public class BSShapeNull : BSShape 110public class BSShapeNull : BSShape
111{ 111{
112 public BSShapeNull() 112 public BSShapeNull() : base()
113 { 113 {
114 base.Initialize(); 114 }
115 } 115 public static BSShape GetReference() { return new BSShapeNull(); }
116 public static BSShape GetReference() { return new BSShapeNull(); } 116 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
117 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 117}
118} 118
119 119public class BSShapeNative : BSShape
120public class BSShapeNative : BSShape 120{
121{ 121 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
122 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; 122 public BSShapeNative() : base()
123 public BSShapeNative() 123 {
124 { 124 }
125 base.Initialize(); 125 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
126 } 126 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
127 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 127 {
128 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) 128 // Native shapes are not shared and are always built anew.
129 { 129 return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
130 // Native shapes are not shared and are always built anew. 130 }
131 return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); 131
132 } 132 private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
133 133 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
134 private BSShapeNative(BSScene physicsScene, BSPhysObject prim, 134 {
135 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) 135 ShapeData nativeShapeData = new ShapeData();
136 { 136 nativeShapeData.Type = shapeType;
137 ShapeData nativeShapeData = new ShapeData(); 137 nativeShapeData.ID = prim.LocalID;
138 nativeShapeData.Type = shapeType; 138 nativeShapeData.Scale = prim.Scale;
139 nativeShapeData.ID = prim.LocalID; 139 nativeShapeData.Size = prim.Scale;
140 nativeShapeData.Scale = prim.Scale; 140 nativeShapeData.MeshKey = (ulong)shapeKey;
141 nativeShapeData.Size = prim.Scale; 141 nativeShapeData.HullKey = (ulong)shapeKey;
142 nativeShapeData.MeshKey = (ulong)shapeKey; 142
143 nativeShapeData.HullKey = (ulong)shapeKey; 143
144 144 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
145 145 {
146 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 146 ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale);
147 { 147 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
148 ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); 148 }
149 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 149 else
150 } 150 {
151 else 151 ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData);
152 { 152 }
153 ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); 153 if (ptr == IntPtr.Zero)
154 } 154 {
155 if (ptr == IntPtr.Zero) 155 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
156 { 156 LogHeader, prim.LocalID, shapeType);
157 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 157 }
158 LogHeader, prim.LocalID, shapeType); 158 type = shapeType;
159 } 159 key = (UInt64)shapeKey;
160 type = shapeType; 160 }
161 key = (UInt64)shapeKey; 161 // Make this reference to the physical shape go away since native shapes are not shared.
162 } 162 public override void Dereference(BSScene physicsScene)
163 // Make this reference to the physical shape go away since native shapes are not shared. 163 {
164 public override void Dereference(BSScene physicsScene) 164 // Native shapes are not tracked and are released immediately
165 { 165 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
166 // Native shapes are not tracked and are released immediately 166 BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr);
167 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); 167 ptr = IntPtr.Zero;
168 BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); 168 // Garbage collection will free up this instance.
169 ptr = IntPtr.Zero; 169 }
170 // Garbage collection will free up this instance. 170}
171 } 171
172} 172public class BSShapeMesh : BSShape
173 173{
174public class BSShapeMesh : BSShape 174 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
175{ 175 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
176 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 176
177 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 177 public BSShapeMesh() : base()
178 178 {
179 public BSShapeMesh() 179 }
180 { 180 public static BSShape GetReference() { return new BSShapeNull(); }
181 base.Initialize(); 181 public override void Dereference(BSScene physicsScene) { }
182 } 182}
183 public static BSShape GetReference() { return new BSShapeNull(); } 183
184 public override void Dereference(BSScene physicsScene) { } 184public class BSShapeHull : BSShape
185} 185{
186 186 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
187public class BSShapeHull : BSShape 187 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
188{ 188
189 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 189 public BSShapeHull() : base()
190 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 190 {
191 191 }
192 public BSShapeHull() 192 public static BSShape GetReference() { return new BSShapeNull(); }
193 { 193 public override void Dereference(BSScene physicsScene) { }
194 base.Initialize(); 194}
195 } 195
196 public static BSShape GetReference() { return new BSShapeNull(); } 196public class BSShapeCompound : BSShape
197 public override void Dereference(BSScene physicsScene) { } 197{
198} 198 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
199 199 public BSShapeCompound() : base()
200public class BSShapeCompound : BSShape 200 {
201{ 201 }
202 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 202 public static BSShape GetReference(BSPhysObject prim)
203 public BSShapeCompound() 203 {
204 { 204 return new BSShapeNull();
205 base.Initialize(); 205 }
206 } 206 public override void Dereference(BSScene physicsScene) { }
207 public static BSShape GetReference(BSPhysObject prim) 207}
208 { 208}
209 return new BSShapeNull();
210 }
211 public override void Dereference(BSScene physicsScene) { }
212}
213}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
new file mode 100755
index 0000000..1450f66
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -0,0 +1,170 @@
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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainHeightmap : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]";
46
47 BulletHeightMapInfo m_mapInfo = null;
48
49 // Constructor to build a default, flat heightmap terrain.
50 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
51 : base(physicsScene, regionBase, id)
52 {
53 Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE);
54 Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION);
55 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
56 float[] initialMap = new float[totalHeights];
57 for (int ii = 0; ii < totalHeights; ii++)
58 {
59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
60 }
61 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero);
62 m_mapInfo.minCoords = minTerrainCoords;
63 m_mapInfo.maxCoords = maxTerrainCoords;
64 m_mapInfo.terrainRegionBase = TerrainBase;
65 // Don't have to free any previous since we just got here.
66 BuildHeightmapTerrain();
67 }
68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id)
74 {
75 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero);
76 m_mapInfo.minCoords = minCoords;
77 m_mapInfo.maxCoords = maxCoords;
78 m_mapInfo.minZ = minCoords.Z;
79 m_mapInfo.maxZ = maxCoords.Z;
80 m_mapInfo.terrainRegionBase = TerrainBase;
81
82 // Don't have to free any previous since we just got here.
83 BuildHeightmapTerrain();
84 }
85
86 public override void Dispose()
87 {
88 ReleaseHeightMapTerrain();
89 }
90
91 // Using the information in m_mapInfo, create the physical representation of the heightmap.
92 private void BuildHeightmapTerrain()
93 {
94 m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID,
95 m_mapInfo.minCoords, m_mapInfo.maxCoords,
96 m_mapInfo.heightMap, PhysicsScene.Params.terrainCollisionMargin);
97
98 // Create the terrain shape from the mapInfo
99 m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr),
100 BSPhysicsShapeType.SHAPE_TERRAIN);
101
102 // The terrain object initial position is at the center of the object
103 Vector3 centerPos;
104 centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
105 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
106 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
107
108 m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID,
109 BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,
110 m_mapInfo.ID, centerPos, Quaternion.Identity));
111
112 // Set current terrain attributes
113 BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction);
114 BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
115 BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
116 BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
117
118 // Return the new terrain to the world of physical objects
119 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
120
121 // redo its bounding box now that it is in the world
122 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
123
124 BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr,
125 (uint)CollisionFilterGroups.TerrainFilter,
126 (uint)CollisionFilterGroups.TerrainMask);
127
128 // Make it so the terrain will not move or be considered for movement.
129 BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
130
131 return;
132 }
133
134 // If there is information in m_mapInfo pointing to physical structures, release same.
135 private void ReleaseHeightMapTerrain()
136 {
137 if (m_mapInfo != null)
138 {
139 if (m_mapInfo.terrainBody.ptr != IntPtr.Zero)
140 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
142 // Frees both the body and the shape.
143 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
144 BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr);
145 }
146 }
147 m_mapInfo = null;
148 }
149
150 // The passed position is relative to the base of the region.
151 public override float GetHeightAtXYZ(Vector3 pos)
152 {
153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
154
155 int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X;
156 try
157 {
158 ret = m_mapInfo.heightMap[mapIndex];
159 }
160 catch
161 {
162 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
163 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
164 LogHeader, m_mapInfo.terrainRegionBase, pos);
165 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
166 }
167 return ret;
168 }
169}
170}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 7c34af2..cd623f1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -40,6 +40,32 @@ using OpenMetaverse;
40 40
41namespace OpenSim.Region.Physics.BulletSPlugin 41namespace OpenSim.Region.Physics.BulletSPlugin
42{ 42{
43
44// The physical implementation of the terrain is wrapped in this class.
45public abstract class BSTerrainPhys : IDisposable
46{
47 public enum TerrainImplementation
48 {
49 Heightmap = 0,
50 Mesh = 1
51 }
52
53 public BSScene PhysicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; }
57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 {
60 PhysicsScene = physicsScene;
61 TerrainBase = regionBase;
62 ID = id;
63 }
64 public abstract void Dispose();
65 public abstract float GetHeightAtXYZ(Vector3 pos);
66}
67
68// ==========================================================================================
43public sealed class BSTerrainManager 69public sealed class BSTerrainManager
44{ 70{
45 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; 71 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
@@ -54,8 +80,6 @@ public sealed class BSTerrainManager
54 // amount to make sure that a bounding box is built for the terrain. 80 // amount to make sure that a bounding box is built for the terrain.
55 public const float HEIGHT_EQUAL_FUDGE = 0.2f; 81 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
56 82
57 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
58
59 // Until the whole simulator is changed to pass us the region size, we rely on constants. 83 // Until the whole simulator is changed to pass us the region size, we rely on constants.
60 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 84 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
61 85
@@ -67,11 +91,10 @@ public sealed class BSTerrainManager
67 91
68 // If doing mega-regions, if we're region zero we will be managing multiple 92 // If doing mega-regions, if we're region zero we will be managing multiple
69 // region terrains since region zero does the physics for the whole mega-region. 93 // region terrains since region zero does the physics for the whole mega-region.
70 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps; 94 private Dictionary<Vector3, BSTerrainPhys> m_terrains;
71 95
72 // True of the terrain has been modified. 96 // Flags used to know when to recalculate the height.
73 // Used to force recalculation of terrain height after terrain has been modified 97 private bool m_terrainModified = false;
74 private bool m_terrainModified;
75 98
76 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. 99 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
77 // This is incremented before assigning to new region so it is the last ID allocated. 100 // This is incremented before assigning to new region so it is the last ID allocated.
@@ -89,8 +112,7 @@ public sealed class BSTerrainManager
89 public BSTerrainManager(BSScene physicsScene) 112 public BSTerrainManager(BSScene physicsScene)
90 { 113 {
91 PhysicsScene = physicsScene; 114 PhysicsScene = physicsScene;
92 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>(); 115 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
93 m_terrainModified = false;
94 116
95 // Assume one region of default size 117 // Assume one region of default size
96 m_worldOffset = Vector3.Zero; 118 m_worldOffset = Vector3.Zero;
@@ -99,17 +121,15 @@ public sealed class BSTerrainManager
99 } 121 }
100 122
101 // Create the initial instance of terrain and the underlying ground plane. 123 // Create the initial instance of terrain and the underlying ground plane.
102 // The objects are allocated in the unmanaged space and the pointers are tracked
103 // by the managed code.
104 // The terrains and the groundPlane are not added to the list of PhysObjects.
105 // This is called from the initialization routine so we presume it is 124 // This is called from the initialization routine so we presume it is
106 // safe to call Bullet in real time. We hope no one is moving prims around yet. 125 // safe to call Bullet in real time. We hope no one is moving prims around yet.
107 public void CreateInitialGroundPlaneAndTerrain() 126 public void CreateInitialGroundPlaneAndTerrain()
108 { 127 {
109 // The ground plane is here to catch things that are trying to drop to negative infinity 128 // The ground plane is here to catch things that are trying to drop to negative infinity
110 BulletShape groundPlaneShape = new BulletShape( 129 BulletShape groundPlaneShape = new BulletShape(
111 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), 130 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f,
112 ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); 131 PhysicsScene.Params.terrainCollisionMargin),
132 BSPhysicsShapeType.SHAPE_GROUNDPLANE);
113 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, 133 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, 134 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
115 Vector3.Zero, Quaternion.Identity)); 135 Vector3.Zero, Quaternion.Identity));
@@ -121,15 +141,9 @@ public sealed class BSTerrainManager
121 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, 141 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
122 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); 142 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
123 143
124 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); 144 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
125 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); 145 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
126 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; 146 m_terrains.Add(Vector3.Zero, initialTerrain);
127 float[] initialMap = new float[totalHeights];
128 for (int ii = 0; ii < totalHeights; ii++)
129 {
130 initialMap[ii] = HEIGHT_INITIALIZATION;
131 }
132 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
133 } 147 }
134 148
135 // Release all the terrain structures we might have allocated 149 // Release all the terrain structures we might have allocated
@@ -150,21 +164,22 @@ public sealed class BSTerrainManager
150 // Release all the terrain we have allocated 164 // Release all the terrain we have allocated
151 public void ReleaseTerrain() 165 public void ReleaseTerrain()
152 { 166 {
153 foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps) 167 lock (m_terrains)
154 { 168 {
155 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) 169 foreach (KeyValuePair<Vector3, BSTerrainPhys> kvp in m_terrains)
156 { 170 {
157 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); 171 kvp.Value.Dispose();
158 BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
159 } 172 }
173 m_terrains.Clear();
160 } 174 }
161 m_heightMaps.Clear();
162 } 175 }
163 176
164 // The simulator wants to set a new heightmap for the terrain. 177 // The simulator wants to set a new heightmap for the terrain.
165 public void SetTerrain(float[] heightMap) { 178 public void SetTerrain(float[] heightMap) {
166 float[] localHeightMap = heightMap; 179 float[] localHeightMap = heightMap;
167 PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() 180 // If there are multiple requests for changes to the same terrain between ticks,
181 // only do that last one.
182 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
168 { 183 {
169 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 184 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
170 { 185 {
@@ -176,8 +191,9 @@ public sealed class BSTerrainManager
176 { 191 {
177 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", 192 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
178 BSScene.DetailLogZero, m_worldOffset, m_worldMax); 193 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
179 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, 194 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
180 localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); 195 BSScene.CHILDTERRAIN_ID, localHeightMap,
196 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
181 } 197 }
182 } 198 }
183 else 199 else
@@ -185,7 +201,7 @@ public sealed class BSTerrainManager
185 // If not doing the mega-prim thing, just change the terrain 201 // If not doing the mega-prim thing, just change the terrain
186 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); 202 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
187 203
188 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, 204 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
189 m_worldOffset, m_worldOffset + DefaultRegionSize, true); 205 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
190 } 206 }
191 }); 207 });
@@ -195,56 +211,64 @@ public sealed class BSTerrainManager
195 // based on the passed information. The 'id' should be either the terrain id or 211 // based on the passed information. The 'id' should be either the terrain id or
196 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. 212 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
197 // The latter feature is for creating child terrains for mega-regions. 213 // The latter feature is for creating child terrains for mega-regions.
198 // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
199 // then a new body and shape is created and the mapInfo is filled.
200 // This call is used for doing the initial terrain creation.
201 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new 214 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
202 // terrain shape is created and added to the body. 215 // terrain shape is created and added to the body.
203 // This call is most often used to update the heightMap and parameters of the terrain. 216 // This call is most often used to update the heightMap and parameters of the terrain.
204 // (The above does suggest that some simplification/refactoring is in order.) 217 // (The above does suggest that some simplification/refactoring is in order.)
205 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) 218 // Called during taint-time.
219 private void UpdateTerrain(uint id, float[] heightMap,
220 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
206 { 221 {
207 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", 222 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
208 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); 223 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
209 224
225 // Find high and low points of passed heightmap.
226 // The min and max passed in is usually the area objects can be in (maximum
227 // object height, for instance). The terrain wants the bounding box for the
228 // terrain so replace passed min and max Z with the actual terrain min/max Z.
210 float minZ = float.MaxValue; 229 float minZ = float.MaxValue;
211 float maxZ = float.MinValue; 230 float maxZ = float.MinValue;
212 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); 231 foreach (float height in heightMap)
213
214 int heightMapSize = heightMap.Length;
215 for (int ii = 0; ii < heightMapSize; ii++)
216 { 232 {
217 float height = heightMap[ii];
218 if (height < minZ) minZ = height; 233 if (height < minZ) minZ = height;
219 if (height > maxZ) maxZ = height; 234 if (height > maxZ) maxZ = height;
220 } 235 }
221 236 if (minZ == maxZ)
222 // The shape of the terrain is from its base to its extents. 237 {
238 // If min and max are the same, reduce min a little bit so a good bounding box is created.
239 minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE;
240 }
223 minCoords.Z = minZ; 241 minCoords.Z = minZ;
224 maxCoords.Z = maxZ; 242 maxCoords.Z = maxZ;
225 243
226 BulletHeightMapInfo mapInfo; 244 Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f);
227 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) 245
246 lock (m_terrains)
228 { 247 {
229 // If this is terrain we know about, it's easy to update 248 BSTerrainPhys terrainPhys;
230 249 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
231 mapInfo.heightMap = heightMap;
232 mapInfo.minCoords = minCoords;
233 mapInfo.maxCoords = maxCoords;
234 mapInfo.minZ = minZ;
235 mapInfo.maxZ = maxZ;
236 mapInfo.sizeX = maxCoords.X - minCoords.X;
237 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
238 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
239 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
240
241 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate()
242 { 250 {
243 if (MegaRegionParentPhysicsScene != null) 251 // There is already a terrain in this spot. Free the old and build the new.
252 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
253 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
254
255 // Remove old terrain from the collection
256 m_terrains.Remove(terrainRegionBase);
257 // Release any physical memory it may be using.
258 terrainPhys.Dispose();
259
260 if (MegaRegionParentPhysicsScene == null)
261 {
262 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
263 m_terrains.Add(terrainRegionBase, newTerrainPhys);
264
265 m_terrainModified = true;
266 }
267 else
244 { 268 {
245 // It's possible that Combine() was called after this code was queued. 269 // It's possible that Combine() was called after this code was queued.
246 // If we are a child of combined regions, we don't create any terrain for us. 270 // If we are a child of combined regions, we don't create any terrain for us.
247 DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); 271 DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
248 272
249 // Get rid of any terrain that may have been allocated for us. 273 // Get rid of any terrain that may have been allocated for us.
250 ReleaseGroundPlaneAndTerrain(); 274 ReleaseGroundPlaneAndTerrain();
@@ -252,135 +276,56 @@ public sealed class BSTerrainManager
252 // I hate doing this, but just bail 276 // I hate doing this, but just bail
253 return; 277 return;
254 } 278 }
279 }
280 else
281 {
282 // We don't know about this terrain so either we are creating a new terrain or
283 // our mega-prim child is giving us a new terrain to add to the phys world
255 284
256 if (mapInfo.terrainBody.ptr != IntPtr.Zero) 285 // if this is a child terrain, calculate a unique terrain id
257 { 286 uint newTerrainID = id;
258 // Updating an existing terrain. 287 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
259 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", 288 newTerrainID = ++m_terrainCount;
260 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
261
262 // Remove from the dynamics world because we're going to mangle this object
263 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
264
265 // Get rid of the old terrain
266 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
267 BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
268 mapInfo.Ptr = IntPtr.Zero;
269
270 /*
271 // NOTE: This routine is half here because I can't get the terrain shape replacement
272 // to work. In the short term, the above three lines completely delete the old
273 // terrain and the code below recreates one from scratch.
274 // Hopefully the Bullet community will help me out on this one.
275
276 // First, release the old collision shape (there is only one terrain)
277 BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
278
279 // Fill the existing height map info with the new location and size information
280 BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
281 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
282
283 // Create a terrain shape based on the new info
284 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
285
286 // Stuff the shape into the existing terrain body
287 BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
288 */
289 }
290 // else
291 {
292 // Creating a new terrain.
293 DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
294 BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
295
296 mapInfo.ID = id;
297 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
298 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
299
300 // Create the terrain shape from the mapInfo
301 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
302 ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
303
304 // The terrain object initial position is at the center of the object
305 Vector3 centerPos;
306 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
307 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
308 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
309
310 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
311 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
312 id, centerPos, Quaternion.Identity));
313 }
314
315 // Make sure the entry is in the heightmap table
316 m_heightMaps[terrainRegionBase] = mapInfo;
317
318 // Set current terrain attributes
319 BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction);
320 BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
321 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
322 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
323
324 // Return the new terrain to the world of physical objects
325 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
326
327 // redo its bounding box now that it is in the world
328 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
329
330 BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr,
331 (uint)CollisionFilterGroups.TerrainFilter,
332 (uint)CollisionFilterGroups.TerrainMask);
333
334 // Make sure the new shape is processed.
335 // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true);
336 // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING);
337 BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
338
339 m_terrainModified = true;
340 });
341 }
342 else
343 {
344 // We don't know about this terrain so either we are creating a new terrain or
345 // our mega-prim child is giving us a new terrain to add to the phys world
346
347 // if this is a child terrain, calculate a unique terrain id
348 uint newTerrainID = id;
349 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
350 newTerrainID = ++m_terrainCount;
351
352 float[] heightMapX = heightMap;
353 Vector3 minCoordsX = minCoords;
354 Vector3 maxCoordsX = maxCoords;
355
356 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
357 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
358 289
359 // Code that must happen at taint-time 290 DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
360 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() 291 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
361 { 292 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
362 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); 293 m_terrains.Add(terrainRegionBase, newTerrainPhys);
363 // Create a new mapInfo that will be filled with the new info
364 mapInfo = new BulletHeightMapInfo(id, heightMapX,
365 BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID,
366 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
367 // Put the unfilled heightmap info into the collection of same
368 m_heightMaps.Add(terrainRegionBase, mapInfo);
369 // Build the terrain
370 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
371 294
372 m_terrainModified = true; 295 m_terrainModified = true;
373 }); 296 }
374 } 297 }
375 } 298 }
376 299
377 // Someday we will have complex terrain with caves and tunnels 300 // TODO: redo terrain implementation selection to allow other base types than heightMap.
378 public float GetTerrainHeightAtXYZ(Vector3 loc) 301 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
379 { 302 {
380 // For the moment, it's flat and convex 303 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
381 return GetTerrainHeightAtXY(loc.X, loc.Y); 304 LogHeader, PhysicsScene.RegionName, terrainRegionBase,
305 (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation);
306 BSTerrainPhys newTerrainPhys = null;
307 switch ((int)PhysicsScene.Params.terrainImplementation)
308 {
309 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
310 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id,
311 heightMap, minCoords, maxCoords);
312 break;
313 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
314 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id,
315 heightMap, minCoords, maxCoords);
316 break;
317 default:
318 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
319 LogHeader,
320 (int)PhysicsScene.Params.terrainImplementation,
321 PhysicsScene.Params.terrainImplementation,
322 PhysicsScene.RegionName, terrainRegionBase);
323 break;
324 }
325 return newTerrainPhys;
382 } 326 }
383 327
328
384 // Given an X and Y, find the height of the terrain. 329 // Given an X and Y, find the height of the terrain.
385 // Since we could be handling multiple terrains for a mega-region, 330 // Since we could be handling multiple terrains for a mega-region,
386 // the base of the region is calcuated assuming all regions are 331 // the base of the region is calcuated assuming all regions are
@@ -390,12 +335,15 @@ public sealed class BSTerrainManager
390 private float lastHeightTX = 999999f; 335 private float lastHeightTX = 999999f;
391 private float lastHeightTY = 999999f; 336 private float lastHeightTY = 999999f;
392 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; 337 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
393 private float GetTerrainHeightAtXY(float tX, float tY) 338 public float GetTerrainHeightAtXYZ(Vector3 loc)
394 { 339 {
340 float tX = loc.X;
341 float tY = loc.Y;
395 // You'd be surprized at the number of times this routine is called 342 // You'd be surprized at the number of times this routine is called
396 // with the same parameters as last time. 343 // with the same parameters as last time.
397 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) 344 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
398 return lastHeight; 345 return lastHeight;
346 m_terrainModified = false;
399 347
400 lastHeightTX = tX; 348 lastHeightTX = tX;
401 lastHeightTY = tY; 349 lastHeightTY = tY;
@@ -403,34 +351,21 @@ public sealed class BSTerrainManager
403 351
404 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; 352 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
405 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; 353 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
406 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); 354 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
407 355
408 BulletHeightMapInfo mapInfo; 356 lock (m_terrains)
409 if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
410 { 357 {
411 float regionX = tX - offsetX; 358 BSTerrainPhys physTerrain;
412 float regionY = tY - offsetY; 359 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
413 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
414 try
415 { 360 {
416 ret = mapInfo.heightMap[mapIndex]; 361 ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ);
417 } 362 }
418 catch 363 else
419 { 364 {
420 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 365 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
421 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", 366 LogHeader, PhysicsScene.RegionName, tX, tY);
422 LogHeader, terrainBaseXY, regionX, regionY);
423 ret = HEIGHT_GETHEIGHT_RET;
424 } 367 }
425 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
426 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
427 }
428 else
429 {
430 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
431 LogHeader, PhysicsScene.RegionName, tX, tY);
432 } 368 }
433 m_terrainModified = false;
434 lastHeight = ret; 369 lastHeight = ret;
435 return ret; 370 return ret;
436 } 371 }
@@ -466,7 +401,7 @@ public sealed class BSTerrainManager
466 // Unhook all the combining that I know about. 401 // Unhook all the combining that I know about.
467 public void UnCombine(PhysicsScene pScene) 402 public void UnCombine(PhysicsScene pScene)
468 { 403 {
469 // Just like ODE, for the moment a NOP 404 // Just like ODE, we don't do anything yet.
470 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); 405 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
471 } 406 }
472 407
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
new file mode 100755
index 0000000..5f6675d
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -0,0 +1,262 @@
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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainMesh : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MESH]";
46
47 private float[] m_savedHeightMap;
48 int m_sizeX;
49 int m_sizeY;
50
51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody;
53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id)
56 {
57 }
58
59 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */)
60 : base(physicsScene, regionBase, id)
61 {
62 }
63
64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id)
68 {
69 int indicesCount;
70 int[] indices;
71 int verticesCount;
72 float[] vertices;
73
74 m_savedHeightMap = initialMap;
75
76 m_sizeX = (int)(maxCoords.X - minCoords.X);
77 m_sizeY = (int)(maxCoords.Y - minCoords.Y);
78
79 if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap,
80 m_sizeX, m_sizeY,
81 (float)m_sizeX, (float)m_sizeY,
82 Vector3.Zero, 1.0f,
83 out indicesCount, out indices, out verticesCount, out vertices))
84 {
85 // DISASTER!!
86 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
87 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
88 // Something is very messed up and a crash is in our future.
89 return;
90 }
91 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
92 ID, indicesCount, indices.Length, verticesCount, vertices.Length);
93
94 m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
95 indicesCount, indices, verticesCount, vertices),
96 BSPhysicsShapeType.SHAPE_MESH);
97 if (m_terrainShape.ptr == IntPtr.Zero)
98 {
99 // DISASTER!!
100 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
101 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
102 // Something is very messed up and a crash is in our future.
103 return;
104 }
105
106 Vector3 pos = regionBase;
107 Quaternion rot = Quaternion.Identity;
108
109 m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
110 if (m_terrainBody.ptr == IntPtr.Zero)
111 {
112 // DISASTER!!
113 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
114 // Something is very messed up and a crash is in our future.
115 return;
116 }
117
118 // Set current terrain attributes
119 BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction);
120 BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
121 BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
122 BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
123
124 // Static objects are not very massive.
125 BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero);
126
127 // Put the new terrain to the world of physical objects
128 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
129
130 // Redo its bounding box now that it is in the world
131 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
132
133 BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr,
134 (uint)CollisionFilterGroups.TerrainFilter,
135 (uint)CollisionFilterGroups.TerrainMask);
136
137 // Make it so the terrain will not move or be considered for movement.
138 BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
139 }
140
141 public override void Dispose()
142 {
143 if (m_terrainBody.ptr != IntPtr.Zero)
144 {
145 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
146 // Frees both the body and the shape.
147 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr);
148 }
149 }
150
151 public override float GetHeightAtXYZ(Vector3 pos)
152 {
153 // For the moment use the saved heightmap to get the terrain height.
154 // TODO: raycast downward to find the true terrain below the position.
155 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
156
157 int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X;
158 try
159 {
160 ret = m_savedHeightMap[mapIndex];
161 }
162 catch
163 {
164 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
165 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
166 LogHeader, TerrainBase, pos);
167 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
168 }
169 return ret;
170 }
171
172 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
173 // Return 'true' if successfully created.
174 public static bool ConvertHeightmapToMesh(
175 BSScene physicsScene,
176 float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
177 float extentX, float extentY, // zero based range for output vertices
178 Vector3 extentBase, // base to be added to all vertices
179 float magnification, // number of vertices to create between heightMap coords
180 out int indicesCountO, out int[] indicesO,
181 out int verticesCountO, out float[] verticesO)
182 {
183 bool ret = false;
184
185 int indicesCount = 0;
186 int verticesCount = 0;
187 int[] indices = new int[0];
188 float[] vertices = new float[0];
189
190 // Simple mesh creation which assumes magnification == 1.
191 // TODO: do a more general solution that scales, adds new vertices and smoothes the result.
192
193 // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
194 // from zero to <= sizeX). The triangle indices are then generated as two triangles
195 // per heightmap point. There are sizeX by sizeY of these squares. The extra row and
196 // column of vertices are used to complete the triangles of the last row and column
197 // of the heightmap.
198 try
199 {
200 // One vertice per heightmap value plus the vertices off the top and bottom edge.
201 int totalVertices = (sizeX + 1) * (sizeY + 1);
202 vertices = new float[totalVertices * 3];
203 int totalIndices = sizeX * sizeY * 6;
204 indices = new int[totalIndices];
205
206 float magX = (float)sizeX / extentX;
207 float magY = (float)sizeY / extentY;
208 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
209 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
210 float minHeight = float.MaxValue;
211 // Note that sizeX+1 vertices are created since there is land between this and the next region.
212 for (int yy = 0; yy <= sizeY; yy++)
213 {
214 for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times
215 {
216 int offset = yy * sizeX + xx;
217 // Extend the height with the height from the last row or column
218 if (yy == sizeY) offset -= sizeX;
219 if (xx == sizeX) offset -= 1;
220 float height = heightMap[offset];
221 minHeight = Math.Min(minHeight, height);
222 vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
223 vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
224 vertices[verticesCount + 2] = height + extentBase.Z;
225 verticesCount += 3;
226 }
227 }
228 verticesCount = verticesCount / 3;
229
230 for (int yy = 0; yy < sizeY; yy++)
231 {
232 for (int xx = 0; xx < sizeX; xx++)
233 {
234 int offset = yy * (sizeX + 1) + xx;
235 // Each vertices is presumed to be the upper left corner of a box of two triangles
236 indices[indicesCount + 0] = offset;
237 indices[indicesCount + 1] = offset + 1;
238 indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column
239 indices[indicesCount + 3] = offset + 1;
240 indices[indicesCount + 4] = offset + sizeX + 2;
241 indices[indicesCount + 5] = offset + sizeX + 1;
242 indicesCount += 6;
243 }
244 }
245
246 ret = true;
247 }
248 catch (Exception e)
249 {
250 physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
251 LogHeader, physicsScene.RegionName, extentBase, e);
252 }
253
254 indicesCountO = indicesCount;
255 indicesO = indices;
256 verticesCountO = verticesCount;
257 verticesO = vertices;
258
259 return ret;
260 }
261}
262}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 07149d8..1e003e6 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -88,11 +88,11 @@ public struct BulletShape
88 public BulletShape(IntPtr xx) 88 public BulletShape(IntPtr xx)
89 { 89 {
90 ptr = xx; 90 ptr = xx;
91 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 91 type=BSPhysicsShapeType.SHAPE_UNKNOWN;
92 shapeKey = 0; 92 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
93 isNativeShape = false; 93 isNativeShape = false;
94 } 94 }
95 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) 95 public BulletShape(IntPtr xx, BSPhysicsShapeType typ)
96 { 96 {
97 ptr = xx; 97 ptr = xx;
98 type = typ; 98 type = typ;
@@ -100,7 +100,7 @@ public struct BulletShape
100 isNativeShape = false; 100 isNativeShape = false;
101 } 101 }
102 public IntPtr ptr; 102 public IntPtr ptr;
103 public ShapeData.PhysicsShapeType type; 103 public BSPhysicsShapeType type;
104 public System.UInt64 shapeKey; 104 public System.UInt64 shapeKey;
105 public bool isNativeShape; 105 public bool isNativeShape;
106 public override string ToString() 106 public override string ToString()
@@ -152,7 +152,7 @@ public class BulletHeightMapInfo
152 ID = id; 152 ID = id;
153 Ptr = xx; 153 Ptr = xx;
154 heightMap = hm; 154 heightMap = hm;
155 terrainRegionBase = new Vector2(0f, 0f); 155 terrainRegionBase = Vector3.Zero;
156 minCoords = new Vector3(100f, 100f, 25f); 156 minCoords = new Vector3(100f, 100f, 25f);
157 maxCoords = new Vector3(101f, 101f, 26f); 157 maxCoords = new Vector3(101f, 101f, 26f);
158 minZ = maxZ = 0f; 158 minZ = maxZ = 0f;
@@ -161,7 +161,7 @@ public class BulletHeightMapInfo
161 public uint ID; 161 public uint ID;
162 public IntPtr Ptr; 162 public IntPtr Ptr;
163 public float[] heightMap; 163 public float[] heightMap;
164 public Vector2 terrainRegionBase; 164 public Vector3 terrainRegionBase;
165 public Vector3 minCoords; 165 public Vector3 minCoords;
166 public Vector3 maxCoords; 166 public Vector3 maxCoords;
167 public float sizeX, sizeY; 167 public float sizeX, sizeY;
@@ -178,26 +178,39 @@ public struct ConvexHull
178 int VertexCount; 178 int VertexCount;
179 Vector3[] Vertices; 179 Vector3[] Vertices;
180} 180}
181public enum BSPhysicsShapeType
182{
183 SHAPE_UNKNOWN = 0,
184 SHAPE_CAPSULE = 1,
185 SHAPE_BOX = 2,
186 SHAPE_CONE = 3,
187 SHAPE_CYLINDER = 4,
188 SHAPE_SPHERE = 5,
189 SHAPE_MESH = 6,
190 SHAPE_HULL = 7,
191 // following defined by BulletSim
192 SHAPE_GROUNDPLANE = 20,
193 SHAPE_TERRAIN = 21,
194 SHAPE_COMPOUND = 22,
195 SHAPE_HEIGHTMAP = 23,
196};
197
198// The native shapes have predefined shape hash keys
199public enum FixedShapeKey : ulong
200{
201 KEY_NONE = 0,
202 KEY_BOX = 1,
203 KEY_SPHERE = 2,
204 KEY_CONE = 3,
205 KEY_CYLINDER = 4,
206 KEY_CAPSULE = 5,
207}
208
181[StructLayout(LayoutKind.Sequential)] 209[StructLayout(LayoutKind.Sequential)]
182public struct ShapeData 210public struct ShapeData
183{ 211{
184 public enum PhysicsShapeType
185 {
186 SHAPE_UNKNOWN = 0,
187 SHAPE_AVATAR = 1,
188 SHAPE_BOX = 2,
189 SHAPE_CONE = 3,
190 SHAPE_CYLINDER = 4,
191 SHAPE_SPHERE = 5,
192 SHAPE_MESH = 6,
193 SHAPE_HULL = 7,
194 // following defined by BulletSim
195 SHAPE_GROUNDPLANE = 20,
196 SHAPE_TERRAIN = 21,
197 SHAPE_COMPOUND = 22,
198 };
199 public uint ID; 212 public uint ID;
200 public PhysicsShapeType Type; 213 public BSPhysicsShapeType Type;
201 public Vector3 Position; 214 public Vector3 Position;
202 public Quaternion Rotation; 215 public Quaternion Rotation;
203 public Vector3 Velocity; 216 public Vector3 Velocity;
@@ -216,16 +229,6 @@ public struct ShapeData
216 // note that bools are passed as floats since bool size changes by language and architecture 229 // note that bools are passed as floats since bool size changes by language and architecture
217 public const float numericTrue = 1f; 230 public const float numericTrue = 1f;
218 public const float numericFalse = 0f; 231 public const float numericFalse = 0f;
219
220 // The native shapes have predefined shape hash keys
221 public enum FixedShapeKey : ulong
222 {
223 KEY_BOX = 1,
224 KEY_SPHERE = 2,
225 KEY_CONE = 3,
226 KEY_CYLINDER = 4,
227 KEY_CAPSULE = 5,
228 }
229} 232}
230[StructLayout(LayoutKind.Sequential)] 233[StructLayout(LayoutKind.Sequential)]
231public struct SweepHit 234public struct SweepHit
@@ -280,17 +283,23 @@ public struct ConfigurationParameters
280 public float ccdSweptSphereRadius; 283 public float ccdSweptSphereRadius;
281 public float contactProcessingThreshold; 284 public float contactProcessingThreshold;
282 285
286 public float terrainImplementation;
283 public float terrainFriction; 287 public float terrainFriction;
284 public float terrainHitFraction; 288 public float terrainHitFraction;
285 public float terrainRestitution; 289 public float terrainRestitution;
290 public float terrainCollisionMargin;
291
286 public float avatarFriction; 292 public float avatarFriction;
287 public float avatarStandingFriction; 293 public float avatarStandingFriction;
288 public float avatarDensity; 294 public float avatarDensity;
289 public float avatarRestitution; 295 public float avatarRestitution;
290 public float avatarCapsuleRadius; 296 public float avatarCapsuleWidth;
297 public float avatarCapsuleDepth;
291 public float avatarCapsuleHeight; 298 public float avatarCapsuleHeight;
292 public float avatarContactProcessingThreshold; 299 public float avatarContactProcessingThreshold;
293 300
301 public float vehicleAngularDamping;
302
294 public float maxPersistantManifoldPoolSize; 303 public float maxPersistantManifoldPoolSize;
295 public float maxCollisionAlgorithmPoolSize; 304 public float maxCollisionAlgorithmPoolSize;
296 public float shouldDisableContactPoolDynamicAllocation; 305 public float shouldDisableContactPoolDynamicAllocation;
@@ -348,7 +357,7 @@ public enum CollisionFlags : uint
348 CF_CHARACTER_OBJECT = 1 << 4, 357 CF_CHARACTER_OBJECT = 1 << 4,
349 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, 358 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
350 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 359 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
351 // Following used by BulletSim to control collisions 360 // Following used by BulletSim to control collisions and updates
352 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
353 BS_FLOATS_ON_WATER = 1 << 11, 362 BS_FLOATS_ON_WATER = 1 << 11,
354 BS_NONE = 0, 363 BS_NONE = 0,
@@ -388,13 +397,13 @@ public enum CollisionFilterGroups : uint
388 ObjectFilter = BSolidFilter, 397 ObjectFilter = BSolidFilter,
389 ObjectMask = BAllFilter, 398 ObjectMask = BAllFilter,
390 StaticObjectFilter = BStaticFilter, 399 StaticObjectFilter = BStaticFilter,
391 StaticObjectMask = BAllFilter, 400 StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other
392 LinksetFilter = BLinksetFilter, 401 LinksetFilter = BLinksetFilter,
393 LinksetMask = BAllFilter & ~BLinksetFilter, 402 LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other
394 VolumeDetectFilter = BSensorTrigger, 403 VolumeDetectFilter = BSensorTrigger,
395 VolumeDetectMask = ~BSensorTrigger, 404 VolumeDetectMask = ~BSensorTrigger,
396 TerrainFilter = BTerrainFilter, 405 TerrainFilter = BTerrainFilter,
397 TerrainMask = BAllFilter & ~BStaticFilter, 406 TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide
398 GroundPlaneFilter = BGroundPlaneFilter, 407 GroundPlaneFilter = BGroundPlaneFilter,
399 GroundPlaneMask = BAllFilter 408 GroundPlaneMask = BAllFilter
400 409
@@ -429,140 +438,6 @@ static class BulletSimAPI {
429[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 438[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
430public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); 439public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
431 440
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433[return: MarshalAs(UnmanagedType.LPStr)]
434public static extern string GetVersion();
435
436/* Remove the linkage to the old api methods
437[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
438public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
439 int maxCollisions, IntPtr collisionArray,
440 int maxUpdates, IntPtr updateArray,
441 DebugLogCallback logRoutine);
442
443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
444public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
445
446[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
447public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
448
449[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
450public static extern void Shutdown(uint worldID);
451
452[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
453public static extern bool UpdateParameter(uint worldID, uint localID,
454 [MarshalAs(UnmanagedType.LPStr)]string paramCode, float value);
455
456// ===============================================================================
457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
458public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
459 out int updatedEntityCount,
460 out IntPtr updatedEntitiesPtr,
461 out int collidersCount,
462 out IntPtr collidersPtr);
463
464[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
465public static extern bool CreateHull(uint worldID, System.UInt64 meshKey,
466 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls
467 );
468
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey,
471 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
472 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices
473 );
474
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey);
477
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
480
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool CreateObject(uint worldID, ShapeData shapeData);
483
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
486
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern Quaternion GetObjectOrientation(uint WorldID, uint id);
489
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
492
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 velocity);
495
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
498
499// Set the current force acting on the object
500[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
501public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
502
503[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
504public static extern bool SetObjectScaleMass(uint worldID, uint id, Vector3 scale, float mass, bool isDynamic);
505
506[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
507public static extern bool SetObjectCollidable(uint worldID, uint id, bool phantom);
508
509[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
510public static extern bool SetObjectDynamic(uint worldID, uint id, bool isDynamic, float mass);
511
512[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
513public static extern bool SetObjectGhost(uint worldID, uint id, bool ghostly);
514
515[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
516public static extern bool SetObjectProperties(uint worldID, uint id, bool isStatic, bool isSolid, bool genCollisions, float mass);
517
518[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
519public static extern bool SetObjectBuoyancy(uint worldID, uint id, float buoyancy);
520
521[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
522public static extern bool HasObject(uint worldID, uint id);
523
524[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
525public static extern bool DestroyObject(uint worldID, uint id);
526
527// ===============================================================================
528[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
529public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin);
530
531[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
532public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vector3 to);
533
534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
535public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
536
537// ===============================================================================
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern void DumpBulletStatistics();
540*/
541// Log a debug message
542[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
543public static extern void SetDebugLogCallback(DebugLogCallback callback);
544
545// ===============================================================================
546// ===============================================================================
547// ===============================================================================
548// A new version of the API that enables moving all the logic out of the C++ code and into
549// the C# code. This will make modifications easier for the next person.
550// This interface passes the actual pointers to the objects in the unmanaged
551// address space. All the management (calls for creation/destruction/lookup)
552// is done in the C# code.
553// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
554// and the old code is removed.
555
556// Functions use while converting from API1 to API2. Can be removed when totally converted.
557[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
558public static extern IntPtr GetSimHandle2(uint worldID);
559
560[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
561public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
562
563[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
564public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
565
566// =============================================================================== 441// ===============================================================================
567// Initialization and simulation 442// Initialization and simulation
568[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -611,6 +486,9 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData)
611public static extern bool IsNativeShape2(IntPtr shape); 486public static extern bool IsNativeShape2(IntPtr shape);
612 487
613[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 488[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
489public static extern void SetShapeCollisionMargin(IntPtr shape, float margin);
490
491[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
614public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); 492public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
615 493
616[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 494[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
index cbc6b95..16404c6 100644
--- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
@@ -32,13 +32,14 @@ using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.OdePlugin; 34using OpenSim.Region.Physics.OdePlugin;
35using OpenSim.Tests.Common;
35using log4net; 36using log4net;
36using System.Reflection; 37using System.Reflection;
37 38
38namespace OpenSim.Region.Physics.OdePlugin.Tests 39namespace OpenSim.Region.Physics.OdePlugin.Tests
39{ 40{
40 [TestFixture] 41 [TestFixture]
41 public class ODETestClass 42 public class ODETestClass : OpenSimTestCase
42 { 43 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 45
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 7763619..77e087c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
39 /// The generated C# code is compared against the expected C# code. 39 /// The generated C# code is compared against the expected C# code.
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class CSCodeGeneratorTest 42 public class CSCodeGeneratorTest : OpenSimTestCase
43 { 43 {
44 [Test] 44 [Test]
45 public void TestDefaultState() 45 public void TestDefaultState()
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
index 1fa6954..05a8756 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
41 /// the LSL source. 41 /// the LSL source.
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class CompilerTest 44 public class CompilerTest : OpenSimTestCase
45 { 45 {
46 private string m_testDir; 46 private string m_testDir;
47 private CSharpCodeProvider m_CSCodeProvider; 47 private CSharpCodeProvider m_CSCodeProvider;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index c73e22f..2c9d9e8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for inventory functions in LSL 51 /// Tests for inventory functions in LSL
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class LSL_ApiInventoryTests 54 public class LSL_ApiInventoryTests : OpenSimTestCase
55 { 55 {
56 protected Scene m_scene; 56 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
index 2565ae7..57f19b9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests. 56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests.
57 /// </remarks> 57 /// </remarks>
58 [TestFixture] 58 [TestFixture]
59 public class LSL_ApiLinkingTests 59 public class LSL_ApiLinkingTests : OpenSimTestCase
60 { 60 {
61 protected Scene m_scene; 61 protected Scene m_scene;
62 protected XEngine.XEngine m_engine; 62 protected XEngine.XEngine m_engine;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
index dd23be8..182b07b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -46,7 +46,7 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
46namespace OpenSim.Region.ScriptEngine.Shared.Tests 46namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{ 47{
48 [TestFixture] 48 [TestFixture]
49 public class LSL_ApiListTests 49 public class LSL_ApiListTests : OpenSimTestCase
50 { 50 {
51 private LSL_Api m_lslApi; 51 private LSL_Api m_lslApi;
52 52
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
index 3ed2562..c8c7f82 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLFloat 36 public class LSL_TypesTestLSLFloat : OpenSimTestCase
37 { 37 {
38 // Used for testing equality of two floats. 38 // Used for testing equality of two floats.
39 private double _lowPrecisionTolerance = 0.000001; 39 private double _lowPrecisionTolerance = 0.000001;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
index 8d1169a..c664108 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLInteger 36 public class LSL_TypesTestLSLInteger : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, int> m_doubleIntSet; 38 private Dictionary<double, int> m_doubleIntSet;
39 private Dictionary<string, int> m_stringIntSet; 39 private Dictionary<string, int> m_stringIntSet;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
index c4ca1a8..8550f2d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLString 36 public class LSL_TypesTestLSLString : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, string> m_doubleStringSet; 38 private Dictionary<double, string> m_doubleStringSet;
39 39
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
index b81225f..71b88bc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests the LSL_Types.list class. 36 /// Tests the LSL_Types.list class.
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestList 39 public class LSL_TypesTestList : OpenSimTestCase
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// Tests concatenating a string to a list. 42 /// Tests concatenating a string to a list.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
index ebf8001..0c838af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests for Vector3 36 /// Tests for Vector3
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestVector3 39 public class LSL_TypesTestVector3 : OpenSimTestCase
40 { 40 {
41 [Test] 41 [Test]
42 public void TestDotProduct() 42 public void TestDotProduct()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c401794..213f33f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for OSSL_Api 51 /// Tests for OSSL_Api
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class OSSL_ApiAppearanceTest 54 public class OSSL_ApiAppearanceTest : OpenSimTestCase
55 { 55 {
56 protected Scene m_scene; 56 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index f331658..5abfe9a 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
44 /// XEngine tests. 44 /// XEngine tests.
45 /// </summary> 45 /// </summary>
46 [TestFixture] 46 [TestFixture]
47 public class XEngineTest 47 public class XEngineTest : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 private XEngine m_xEngine; 50 private XEngine m_xEngine;
diff --git a/OpenSim/Server/Base/HttpServerBase.cs b/OpenSim/Server/Base/HttpServerBase.cs
index 29b1c00..954783c 100644
--- a/OpenSim/Server/Base/HttpServerBase.cs
+++ b/OpenSim/Server/Base/HttpServerBase.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Server.Base
52 52
53 protected override void ReadConfig() 53 protected override void ReadConfig()
54 { 54 {
55 IConfig networkConfig = m_Config.Configs["Network"]; 55 IConfig networkConfig = Config.Configs["Network"];
56 56
57 if (networkConfig == null) 57 if (networkConfig == null)
58 { 58 {
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index 0cff6ed..5b23149 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -34,6 +34,7 @@ using System.Text;
34using System.Xml; 34using System.Xml;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37using OpenSim.Framework.Servers;
37using log4net; 38using log4net;
38using log4net.Config; 39using log4net.Config;
39using log4net.Appender; 40using log4net.Appender;
@@ -43,7 +44,7 @@ using Nini.Config;
43 44
44namespace OpenSim.Server.Base 45namespace OpenSim.Server.Base
45{ 46{
46 public class ServicesServerBase 47 public class ServicesServerBase : ServerBase
47 { 48 {
48 // Logger 49 // Logger
49 // 50 //
@@ -55,34 +56,14 @@ namespace OpenSim.Server.Base
55 // 56 //
56 protected string[] m_Arguments; 57 protected string[] m_Arguments;
57 58
58 // Configuration
59 //
60 protected IConfigSource m_Config = null;
61
62 public IConfigSource Config
63 {
64 get { return m_Config; }
65 }
66
67 // Run flag 59 // Run flag
68 // 60 //
69 private bool m_Running = true; 61 private bool m_Running = true;
70 62
71 // PID file
72 //
73 private string m_pidFile = String.Empty;
74
75 /// <summary>
76 /// Time at which this server was started
77 /// </summary>
78 protected DateTime m_startuptime;
79
80 // Handle all the automagical stuff 63 // Handle all the automagical stuff
81 // 64 //
82 public ServicesServerBase(string prompt, string[] args) 65 public ServicesServerBase(string prompt, string[] args) : base()
83 { 66 {
84 m_startuptime = DateTime.Now;
85
86 // Save raw arguments 67 // Save raw arguments
87 // 68 //
88 m_Arguments = args; 69 m_Arguments = args;
@@ -128,11 +109,11 @@ namespace OpenSim.Server.Base
128 configUri.Scheme == Uri.UriSchemeHttp) 109 configUri.Scheme == Uri.UriSchemeHttp)
129 { 110 {
130 XmlReader r = XmlReader.Create(iniFile); 111 XmlReader r = XmlReader.Create(iniFile);
131 m_Config = new XmlConfigSource(r); 112 Config = new XmlConfigSource(r);
132 } 113 }
133 else 114 else
134 { 115 {
135 m_Config = new IniConfigSource(iniFile); 116 Config = new IniConfigSource(iniFile);
136 } 117 }
137 } 118 }
138 catch (Exception e) 119 catch (Exception e)
@@ -144,13 +125,13 @@ namespace OpenSim.Server.Base
144 // Merge the configuration from the command line into the 125 // Merge the configuration from the command line into the
145 // loaded file 126 // loaded file
146 // 127 //
147 m_Config.Merge(argvConfig); 128 Config.Merge(argvConfig);
148 129
149 // Refresh the startupConfig post merge 130 // Refresh the startupConfig post merge
150 // 131 //
151 if (m_Config.Configs["Startup"] != null) 132 if (Config.Configs["Startup"] != null)
152 { 133 {
153 startupConfig = m_Config.Configs["Startup"]; 134 startupConfig = Config.Configs["Startup"];
154 } 135 }
155 136
156 prompt = startupConfig.GetString("Prompt", prompt); 137 prompt = startupConfig.GetString("Prompt", prompt);
@@ -180,6 +161,8 @@ namespace OpenSim.Server.Base
180 MainConsole.Instance = new LocalConsole(prompt); 161 MainConsole.Instance = new LocalConsole(prompt);
181 } 162 }
182 163
164 m_console = MainConsole.Instance;
165
183 // Configure the appenders for log4net 166 // Configure the appenders for log4net
184 // 167 //
185 OpenSimAppender consoleAppender = null; 168 OpenSimAppender consoleAppender = null;
@@ -195,54 +178,15 @@ namespace OpenSim.Server.Base
195 XmlConfigurator.Configure(); 178 XmlConfigurator.Configure();
196 } 179 }
197 180
198 ILoggerRepository repository = LogManager.GetRepository(); 181 RegisterCommonAppenders(startupConfig);
199 IAppender[] appenders = repository.GetAppenders();
200
201 foreach (IAppender appender in appenders)
202 {
203 if (appender.Name == "Console")
204 {
205 consoleAppender = (OpenSimAppender)appender;
206 }
207 if (appender.Name == "LogFileAppender")
208 {
209 fileAppender = (FileAppender)appender;
210 }
211 }
212
213 if (consoleAppender == null)
214 {
215 System.Console.WriteLine("No console appender found. Server can't start");
216 Thread.CurrentThread.Abort();
217 }
218 else
219 {
220 consoleAppender.Console = (ConsoleBase)MainConsole.Instance;
221
222 if (null == consoleAppender.Threshold)
223 consoleAppender.Threshold = Level.All;
224 }
225
226 // Set log file
227 //
228 if (fileAppender != null)
229 {
230 if (startupConfig != null)
231 {
232 string cfgFileName = startupConfig.GetString("logfile", null);
233 if (cfgFileName != null)
234 {
235 fileAppender.File = cfgFileName;
236 fileAppender.ActivateOptions();
237 }
238 }
239 }
240 182
241 if (startupConfig.GetString("PIDFile", String.Empty) != String.Empty) 183 if (startupConfig.GetString("PIDFile", String.Empty) != String.Empty)
242 { 184 {
243 CreatePIDFile(startupConfig.GetString("PIDFile")); 185 CreatePIDFile(startupConfig.GetString("PIDFile"));
244 } 186 }
245 187
188 RegisterCommonCommands();
189
246 // Register the quit command 190 // Register the quit command
247 // 191 //
248 MainConsole.Instance.Commands.AddCommand("General", false, "quit", 192 MainConsole.Instance.Commands.AddCommand("General", false, "quit",
@@ -252,16 +196,6 @@ namespace OpenSim.Server.Base
252 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown", 196 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown",
253 "shutdown", 197 "shutdown",
254 "Quit the application", HandleQuit); 198 "Quit the application", HandleQuit);
255
256 // Register a command to read other commands from a file
257 MainConsole.Instance.Commands.AddCommand("General", false, "command-script",
258 "command-script <script>",
259 "Run a command script from file", HandleScript);
260
261 MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
262 "show uptime",
263 "Show server uptime", HandleShow);
264
265 199
266 // Allow derived classes to perform initialization that 200 // Allow derived classes to perform initialization that
267 // needs to be done after the console has opened 201 // needs to be done after the console has opened
@@ -288,8 +222,8 @@ namespace OpenSim.Server.Base
288 } 222 }
289 } 223 }
290 224
291 if (m_pidFile != String.Empty) 225 RemovePIDFile();
292 File.Delete(m_pidFile); 226
293 return 0; 227 return 0;
294 } 228 }
295 229
@@ -297,43 +231,9 @@ namespace OpenSim.Server.Base
297 { 231 {
298 m_Running = false; 232 m_Running = false;
299 m_log.Info("[CONSOLE] Quitting"); 233 m_log.Info("[CONSOLE] Quitting");
300 }
301 234
302 protected virtual void HandleScript(string module, string[] parms)
303 {
304 if (parms.Length != 2)
305 {
306 return;
307 }
308 RunCommandScript(parms[1]);
309 } 235 }
310 236
311 /// <summary>
312 /// Run an optional startup list of commands
313 /// </summary>
314 /// <param name="fileName"></param>
315 private void RunCommandScript(string fileName)
316 {
317 if (File.Exists(fileName))
318 {
319 m_log.Info("[COMMANDFILE]: Running " + fileName);
320
321 using (StreamReader readFile = File.OpenText(fileName))
322 {
323 string currentCommand;
324 while ((currentCommand = readFile.ReadLine()) != null)
325 {
326 if (currentCommand != String.Empty)
327 {
328 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'");
329 MainConsole.Instance.RunCommand(currentCommand);
330 }
331 }
332 }
333 }
334 }
335
336
337 protected virtual void ReadConfig() 237 protected virtual void ReadConfig()
338 { 238 {
339 } 239 }
@@ -341,50 +241,5 @@ namespace OpenSim.Server.Base
341 protected virtual void Initialise() 241 protected virtual void Initialise()
342 { 242 {
343 } 243 }
344
345 protected void CreatePIDFile(string path)
346 {
347 try
348 {
349 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
350 FileStream fs = File.Create(path);
351 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
352 fs.Write(buf, 0, buf.Length);
353 fs.Close();
354 m_pidFile = path;
355 }
356 catch (Exception)
357 {
358 }
359 }
360
361 public virtual void HandleShow(string module, string[] cmd)
362 {
363 List<string> args = new List<string>(cmd);
364
365 args.RemoveAt(0);
366
367 string[] showParams = args.ToArray();
368
369 switch (showParams[0])
370 {
371 case "uptime":
372 MainConsole.Instance.Output(GetUptimeReport());
373 break;
374 }
375 }
376
377 /// <summary>
378 /// Return a report about the uptime of this server
379 /// </summary>
380 /// <returns></returns>
381 protected string GetUptimeReport()
382 {
383 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
384 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
385 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
386
387 return sb.ToString();
388 }
389 } 244 }
390} 245} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
index 87b3d2d..a006fa8 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
@@ -57,14 +57,23 @@ namespace OpenSim.Server.Handlers.Asset
57 public override byte[] Handle(string path, Stream request, 57 public override byte[] Handle(string path, Stream request,
58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 59 {
60 AssetBase asset;
60 XmlSerializer xs = new XmlSerializer(typeof (AssetBase)); 61 XmlSerializer xs = new XmlSerializer(typeof (AssetBase));
61 AssetBase asset = (AssetBase) xs.Deserialize(request); 62
63 try
64 {
65 asset = (AssetBase)xs.Deserialize(request);
66 }
67 catch (XmlException)
68 {
69 httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
70 return null;
71 }
62 72
63 string[] p = SplitParams(path); 73 string[] p = SplitParams(path);
64 if (p.Length > 1) 74 if (p.Length > 1)
65 { 75 {
66 bool result = 76 bool result = m_AssetService.UpdateContent(p[1], asset.Data);
67 m_AssetService.UpdateContent(p[1], asset.Data);
68 77
69 xs = new XmlSerializer(typeof(bool)); 78 xs = new XmlSerializer(typeof(bool));
70 return ServerUtils.SerializeResult(xs, result); 79 return ServerUtils.SerializeResult(xs, result);
diff --git a/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs
new file mode 100644
index 0000000..427fa16
--- /dev/null
+++ b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs
@@ -0,0 +1,110 @@
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.IO;
30using System.Net;
31using System.Text;
32using System.Xml;
33using System.Xml.Serialization;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Server.Handlers.Asset;
39using OpenSim.Services.AssetService;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Server.Handlers.Asset.Test
45{
46 [TestFixture]
47 public class AssetServerPostHandlerTests : OpenSimTestCase
48 {
49 [Test]
50 public void TestGoodAssetStoreRequest()
51 {
52 TestHelpers.InMethod();
53
54 UUID assetId = TestHelpers.ParseTail(0x1);
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("AssetService");
58 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
59
60 AssetService assetService = new AssetService(config);
61
62 AssetServerPostHandler asph = new AssetServerPostHandler(assetService);
63
64 AssetBase asset = AssetHelpers.CreateNotecardAsset(assetId, "Hello World");
65
66 MemoryStream buffer = new MemoryStream();
67
68 XmlWriterSettings settings = new XmlWriterSettings();
69 settings.Encoding = Encoding.UTF8;
70
71 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
72 {
73 XmlSerializer serializer = new XmlSerializer(typeof(AssetBase));
74 serializer.Serialize(writer, asset);
75 writer.Flush();
76 }
77
78 buffer.Position = 0;
79 asph.Handle(null, buffer, null, null);
80
81 AssetBase retrievedAsset = assetService.Get(assetId.ToString());
82
83 Assert.That(retrievedAsset, Is.Not.Null);
84 }
85
86 [Test]
87 public void TestBadXmlAssetStoreRequest()
88 {
89 TestHelpers.InMethod();
90
91 IConfigSource config = new IniConfigSource();
92 config.AddConfig("AssetService");
93 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
94
95 AssetService assetService = new AssetService(config);
96
97 AssetServerPostHandler asph = new AssetServerPostHandler(assetService);
98
99 MemoryStream buffer = new MemoryStream();
100 byte[] badData = new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f };
101 buffer.Write(badData, 0, badData.Length);
102 buffer.Position = 0;
103
104 TestOSHttpResponse response = new TestOSHttpResponse();
105 asph.Handle(null, buffer, null, response);
106
107 Assert.That(response.StatusCode, Is.EqualTo((int)HttpStatusCode.BadRequest));
108 }
109 }
110} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs
index 6fb9df1..3035cea 100644
--- a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs
+++ b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs
@@ -26,12 +26,15 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
34using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Data;
37using OpenSim.Data.Null;
35using OpenSim.Framework; 38using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
@@ -44,6 +47,8 @@ namespace OpenSim.Tests.Common.Mock
44 { 47 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 49
50 IXGroupData m_data = new NullXGroupData(null, null);
51
47 public string Name 52 public string Name
48 { 53 {
49 get { return "MockGroupsServicesConnector"; } 54 get { return "MockGroupsServicesConnector"; }
@@ -84,7 +89,33 @@ namespace OpenSim.Tests.Common.Mock
84 int membershipFee, bool openEnrollment, bool allowPublish, 89 int membershipFee, bool openEnrollment, bool allowPublish,
85 bool maturePublish, UUID founderID) 90 bool maturePublish, UUID founderID)
86 { 91 {
87 return UUID.Zero; 92 XGroup group = new XGroup()
93 {
94 groupID = UUID.Random(),
95 ownerRoleID = UUID.Random(),
96 name = name,
97 charter = charter,
98 showInList = showInList,
99 insigniaID = insigniaID,
100 membershipFee = membershipFee,
101 openEnrollment = openEnrollment,
102 allowPublish = allowPublish,
103 maturePublish = maturePublish,
104 founderID = founderID,
105 everyonePowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultEveryonePowers,
106 ownersPowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultOwnerPowers
107 };
108
109 if (m_data.StoreGroup(group))
110 {
111 m_log.DebugFormat("[MOCK GROUPS SERVICES CONNECTOR]: Created group {0} {1}", group.name, group.groupID);
112 return group.groupID;
113 }
114 else
115 {
116 m_log.ErrorFormat("[MOCK GROUPS SERVICES CONNECTOR]: Failed to create group {0}", name);
117 return UUID.Zero;
118 }
88 } 119 }
89 120
90 public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, 121 public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList,
@@ -107,9 +138,49 @@ namespace OpenSim.Tests.Common.Mock
107 { 138 {
108 } 139 }
109 140
110 public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) 141 public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName)
111 { 142 {
112 return null; 143 m_log.DebugFormat(
144 "[MOCK GROUPS SERVICES CONNECTOR]: Processing GetGroupRecord() for groupID {0}, name {1}",
145 groupID, groupName);
146
147 XGroup[] groups;
148 string field, val;
149
150 if (groupID != UUID.Zero)
151 {
152 field = "groupID";
153 val = groupID.ToString();
154 }
155 else
156 {
157 field = "name";
158 val = groupName;
159 }
160
161 groups = m_data.GetGroups(field, val);
162
163 if (groups.Length == 0)
164 return null;
165
166 XGroup xg = groups[0];
167
168 GroupRecord gr = new GroupRecord()
169 {
170 GroupID = xg.groupID,
171 GroupName = xg.name,
172 AllowPublish = xg.allowPublish,
173 MaturePublish = xg.maturePublish,
174 Charter = xg.charter,
175 FounderID = xg.founderID,
176 // FIXME: group picture storage location unknown
177 MembershipFee = xg.membershipFee,
178 OpenEnrollment = xg.openEnrollment,
179 OwnerRoleID = xg.ownerRoleID,
180 ShowInList = xg.showInList
181 };
182
183 return gr;
113 } 184 }
114 185
115 public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) 186 public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID)
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
index f9bf768..ccbdf81 100644
--- a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -33,10 +33,11 @@ using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Data; 35using OpenSim.Data;
36using OpenSim.Data.Null;
36 37
37namespace OpenSim.Tests.Common.Mock 38namespace OpenSim.Tests.Common.Mock
38{ 39{
39 public class TestXInventoryDataPlugin : IXInventoryData 40 public class TestXInventoryDataPlugin : NullGenericDataHandler, IXInventoryData
40 { 41 {
41 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>(); 42 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
42 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>(); 43 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
@@ -58,28 +59,6 @@ namespace OpenSim.Tests.Common.Mock
58 return origFolders.Select(f => f.Clone()).ToArray(); 59 return origFolders.Select(f => f.Clone()).ToArray();
59 } 60 }
60 61
61 private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
62 {
63 List<T> entities = inputEntities;
64
65 for (int i = 0; i < fields.Length; i++)
66 {
67 entities
68 = entities.Where(
69 e =>
70 {
71 FieldInfo fi = typeof(T).GetField(fields[i]);
72 if (fi == null)
73 throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
74
75 return fi.GetValue(e).ToString() == vals[i];
76 }
77 ).ToList();
78 }
79
80 return entities;
81 }
82
83 public bool StoreFolder(XInventoryFolder folder) 62 public bool StoreFolder(XInventoryFolder folder)
84 { 63 {
85 m_allFolders[folder.folderID] = folder.Clone(); 64 m_allFolders[folder.folderID] = folder.Clone();
diff --git a/OpenSim/Tests/ConfigurationLoaderTest.cs b/OpenSim/Tests/ConfigurationLoaderTest.cs
index 067264d..e5186ae 100644
--- a/OpenSim/Tests/ConfigurationLoaderTest.cs
+++ b/OpenSim/Tests/ConfigurationLoaderTest.cs
@@ -29,11 +29,12 @@ using System.IO;
29using Nini.Config; 29using Nini.Config;
30using NUnit.Framework; 30using NUnit.Framework;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Tests 34namespace OpenSim.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class ConfigurationLoaderTests 37 public class ConfigurationLoaderTests : OpenSimTestCase
37 { 38 {
38 private const string m_testSubdirectory = "test"; 39 private const string m_testSubdirectory = "test";
39 private string m_basePath; 40 private string m_basePath;
diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
index 627765b..2026a88 100644
--- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Performance
58 /// earlier tests. 58 /// earlier tests.
59 /// </remarks> 59 /// </remarks>
60 [TestFixture] 60 [TestFixture]
61 public class NPCPerformanceTests 61 public class NPCPerformanceTests : OpenSimTestCase
62 { 62 {
63 private TestScene scene; 63 private TestScene scene;
64 private AvatarFactoryModule afm; 64 private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
index 2264d86..656a971 100644
--- a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Performance
47 /// earlier tests. 47 /// earlier tests.
48 /// </remarks> 48 /// </remarks>
49 [TestFixture] 49 [TestFixture]
50 public class ObjectPerformanceTests 50 public class ObjectPerformanceTests : OpenSimTestCase
51 { 51 {
52 [TearDown] 52 [TearDown]
53 public void TearDown() 53 public void TearDown()
diff --git a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
index d708abd..4064edc 100644
--- a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Performance
53 /// earlier tests. 53 /// earlier tests.
54 /// </remarks> 54 /// </remarks>
55 [TestFixture] 55 [TestFixture]
56 public class ScriptPerformanceTests 56 public class ScriptPerformanceTests : OpenSimTestCase
57 { 57 {
58 private TestScene m_scene; 58 private TestScene m_scene;
59 private XEngine m_xEngine; 59 private XEngine m_xEngine;