aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS.txt1
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs30
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs2
-rw-r--r--OpenSim/Data/MSSQL/MSSQLEstateData.cs117
-rw-r--r--OpenSim/Data/MSSQL/MSSQLUserAccountData.cs18
-rw-r--r--OpenSim/Data/MSSQL/Resources/FriendsStore.migrations28
-rw-r--r--OpenSim/Data/MSSQL/Resources/InventoryStore.migrations32
-rw-r--r--OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml23
-rw-r--r--OpenSim/Data/MySQL/MySQLEstateData.cs123
-rw-r--r--OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml23
-rwxr-xr-xOpenSim/Data/Null/NullEstateData.cs5
-rw-r--r--OpenSim/Data/Null/NullSimulationData.cs6
-rw-r--r--OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml20
-rw-r--r--OpenSim/Data/SQLite/SQLiteEstateData.cs126
-rw-r--r--OpenSim/Framework/AssetBase.cs1
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs93
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs1
-rw-r--r--OpenSim/Framework/Console/LocalConsole.cs180
-rw-r--r--OpenSim/Framework/IClientAPI.cs2
-rw-r--r--OpenSim/Framework/Util.cs42
-rw-r--r--OpenSim/Region/Application/OpenSim.cs10
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs69
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs10
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs168
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs127
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs462
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs32
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs16
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs16
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs15
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs106
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs89
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs18
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateDataService.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs (renamed from OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs)54
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScenePresence.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityBase.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs49
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs172
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs54
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs22
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs46
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs66
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs201
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs135
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs11
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs7
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs72
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs16
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs1191
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs65
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs2767
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs776
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs1855
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs197
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs19
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs78
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs58
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs5
-rw-r--r--OpenSim/Services/Connectors/Simulation/EstateDataService.cs7
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs14
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs159
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs2
-rw-r--r--OpenSim/Tests/Common/QuaternionToleranceConstraint.cs82
-rw-r--r--bin/OpenSim.ini.example7
-rw-r--r--bin/Robust.HG.ini.example8
-rw-r--r--bin/Robust.ini.example8
-rw-r--r--bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml10
-rw-r--r--bin/assets/BodyPartsAssetSet/base_eyes.dat26
-rw-r--r--bin/assets/BodyPartsAssetSet/base_hair.dat (renamed from bin/assets/BodyPartsAssetSet/newhair.dat)59
-rw-r--r--bin/assets/BodyPartsAssetSet/base_shape.dat212
-rw-r--r--bin/assets/TexturesAssetSet/TexturesAssetSet.xml7
-rw-r--r--bin/assets/TexturesAssetSet/default_iris.jp2bin0 -> 15719 bytes
-rw-r--r--bin/config-include/Standalone.ini8
-rw-r--r--bin/inventory/TexturesLibrary/TexturesLibraryItems.xml10
-rw-r--r--prebuild.xml59
97 files changed, 2667 insertions, 8312 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 2fe8b46..239b884 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -117,6 +117,7 @@ what it is today.
117* nornalbion 117* nornalbion
118* Omar Vera Ustariz (IBM) 118* Omar Vera Ustariz (IBM)
119* openlifegrid.com 119* openlifegrid.com
120* Oren Hurvitz (Kitely)
120* otakup0pe 121* otakup0pe
121* ralphos 122* ralphos
122* RemedyTomm 123* RemedyTomm
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 93a6915..e20b487 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -709,6 +709,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController
709 // ok, client wants us to use an explicit UUID 709 // ok, client wants us to use an explicit UUID
710 // regardless of what the avatar name provided 710 // regardless of what the avatar name provided
711 userID = new UUID((string) requestData["estate_owner_uuid"]); 711 userID = new UUID((string) requestData["estate_owner_uuid"]);
712
713 // Check that the specified user exists
714 Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene;
715 IUserAccountService accountService = currentOrFirst.UserAccountService;
716 UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID);
717
718 if (user == null)
719 throw new Exception("Specified user was not found.");
712 } 720 }
713 else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last")) 721 else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last"))
714 { 722 {
@@ -720,6 +728,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
720 IUserAccountService accountService = currentOrFirst.UserAccountService; 728 IUserAccountService accountService = currentOrFirst.UserAccountService;
721 UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, 729 UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID,
722 ownerFirst, ownerLast); 730 ownerFirst, ownerLast);
731
732 // Check that the specified user exists
733 if (user == null)
734 throw new Exception("Specified user was not found.");
735
723 userID = user.PrincipalID; 736 userID = user.PrincipalID;
724 } 737 }
725 else 738 else
@@ -728,21 +741,30 @@ namespace OpenSim.ApplicationPlugins.RemoteController
728 } 741 }
729 742
730 // Create a new estate with the name provided 743 // Create a new estate with the name provided
731 region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(region.RegionID, true); 744 region.EstateSettings = m_application.EstateDataService.CreateNewEstate();
732 745
733 region.EstateSettings.EstateName = (string) requestData["estate_name"]; 746 region.EstateSettings.EstateName = (string) requestData["estate_name"];
734 region.EstateSettings.EstateOwner = userID; 747 region.EstateSettings.EstateOwner = userID;
735 // Persistence does not seem to effect the need to save a new estate 748 // Persistence does not seem to effect the need to save a new estate
736 region.EstateSettings.Save(); 749 region.EstateSettings.Save();
750
751 if (!m_application.EstateDataService.LinkRegion(region.RegionID, (int) region.EstateSettings.EstateID))
752 throw new Exception("Failed to join estate.");
737 } 753 }
738 else 754 else
739 { 755 {
740 int estateID = estateIDs[0]; 756 int estateID = estateIDs[0];
741 757
742 region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(estateID); 758 region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(region.RegionID, false);
743 759
744 if (!m_application.EstateDataService.LinkRegion(region.RegionID, estateID)) 760 if (region.EstateSettings.EstateID != estateID)
745 throw new Exception("Failed to join estate."); 761 {
762 // The region is already part of an estate, but not the one we want.
763 region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(estateID);
764
765 if (!m_application.EstateDataService.LinkRegion(region.RegionID, estateID))
766 throw new Exception("Failed to join estate.");
767 }
746 } 768 }
747 769
748 // Create the region and perform any initial initialization 770 // Create the region and perform any initial initialization
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs
index 1023108..b53806c 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs
@@ -169,7 +169,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests
169 float y = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Y]); 169 float y = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Y]);
170 float z = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Z]); 170 float z = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Z]);
171 Vector3 vector = new Vector3(x, y, z); 171 Vector3 vector = new Vector3(x, y, z);
172 presence.MoveToTarget(vector, false); 172 presence.MoveToTarget(vector, false, false);
173 } 173 }
174 catch (Exception e) 174 catch (Exception e)
175 { 175 {
diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs
index 9c54e77..1faa249 100644
--- a/OpenSim/Data/MSSQL/MSSQLEstateData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs
@@ -148,56 +148,29 @@ namespace OpenSim.Data.MSSQL
148 } 148 }
149 } 149 }
150 150
151
152 if (insertEstate && create) 151 if (insertEstate && create)
153 { 152 {
154 List<string> names = new List<string>(FieldList); 153 DoCreate(es);
155 154 LinkRegion(regionID, (int)es.EstateID);
156 names.Remove("EstateID"); 155 }
157
158 sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
159
160 //_Log.Debug("[DB ESTATE]: SQL: " + sql);
161 using (SqlConnection conn = new SqlConnection(m_connectionString))
162 using (SqlCommand insertCommand = new SqlCommand(sql, conn))
163 {
164 insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()";
165 156
166 foreach (string name in names) 157 LoadBanList(es);
167 {
168 insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
169 }
170 SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int);
171 idParameter.Direction = ParameterDirection.Output;
172 insertCommand.Parameters.Add(idParameter);
173 conn.Open();
174 insertCommand.ExecuteNonQuery();
175 158
176 es.EstateID = Convert.ToUInt32(idParameter.Value); 159 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
177 } 160 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
161 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
178 162
179 sql = "INSERT INTO [estate_map] ([RegionID] ,[EstateID]) VALUES (@RegionID, @EstateID)"; 163 //Set event
180 using (SqlConnection conn = new SqlConnection(m_connectionString)) 164 es.OnSave += StoreEstateSettings;
181 using (SqlCommand cmd = new SqlCommand(sql, conn)) 165 return es;
182 { 166 }
183 167
184 cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID)); 168 public EstateSettings CreateNewEstate()
185 cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID)); 169 {
186 // This will throw on dupe key 170 EstateSettings es = new EstateSettings();
187 try 171 es.OnSave += StoreEstateSettings;
188 {
189 conn.Open();
190 cmd.ExecuteNonQuery();
191 }
192 catch (Exception e)
193 {
194 m_log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e);
195 }
196 }
197 172
198 //TODO check if this is needed?? 173 DoCreate(es);
199 es.Save();
200 }
201 174
202 LoadBanList(es); 175 LoadBanList(es);
203 176
@@ -205,11 +178,40 @@ namespace OpenSim.Data.MSSQL
205 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); 178 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
206 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); 179 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
207 180
208 //Set event
209 es.OnSave += StoreEstateSettings;
210 return es; 181 return es;
211 } 182 }
212 183
184 private void DoCreate(EstateSettings es)
185 {
186 List<string> names = new List<string>(FieldList);
187
188 names.Remove("EstateID");
189
190 string sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
191
192 //_Log.Debug("[DB ESTATE]: SQL: " + sql);
193 using (SqlConnection conn = new SqlConnection(m_connectionString))
194 using (SqlCommand insertCommand = new SqlCommand(sql, conn))
195 {
196 insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()";
197
198 foreach (string name in names)
199 {
200 insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
201 }
202 SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int);
203 idParameter.Direction = ParameterDirection.Output;
204 insertCommand.Parameters.Add(idParameter);
205 conn.Open();
206 insertCommand.ExecuteNonQuery();
207
208 es.EstateID = Convert.ToUInt32(idParameter.Value);
209 }
210
211 //TODO check if this is needed??
212 es.Save();
213 }
214
213 /// <summary> 215 /// <summary>
214 /// Stores the estate settings. 216 /// Stores the estate settings.
215 /// </summary> 217 /// </summary>
@@ -498,24 +500,43 @@ namespace OpenSim.Data.MSSQL
498 500
499 public bool LinkRegion(UUID regionID, int estateID) 501 public bool LinkRegion(UUID regionID, int estateID)
500 { 502 {
501 string sql = "insert into estate_map values (@RegionID, @EstateID)"; 503 string deleteSQL = "delete from estate_map where RegionID = @RegionID";
504 string insertSQL = "insert into estate_map values (@RegionID, @EstateID)";
502 using (SqlConnection conn = new SqlConnection(m_connectionString)) 505 using (SqlConnection conn = new SqlConnection(m_connectionString))
503 { 506 {
504 conn.Open(); 507 conn.Open();
508 SqlTransaction transaction = conn.BeginTransaction();
509
505 try 510 try
506 { 511 {
507 using (SqlCommand cmd = new SqlCommand(sql, conn)) 512 using (SqlCommand cmd = new SqlCommand(deleteSQL, conn))
508 { 513 {
509 cmd.Parameters.AddWithValue("@RegionID", regionID); 514 cmd.Transaction = transaction;
515 cmd.Parameters.AddWithValue("@RegionID", regionID.Guid);
516
517 cmd.ExecuteNonQuery();
518 }
519
520 using (SqlCommand cmd = new SqlCommand(insertSQL, conn))
521 {
522 cmd.Transaction = transaction;
523 cmd.Parameters.AddWithValue("@RegionID", regionID.Guid);
510 cmd.Parameters.AddWithValue("@EstateID", estateID); 524 cmd.Parameters.AddWithValue("@EstateID", estateID);
511 525
512 int ret = cmd.ExecuteNonQuery(); 526 int ret = cmd.ExecuteNonQuery();
527
528 if (ret != 0)
529 transaction.Commit();
530 else
531 transaction.Rollback();
532
513 return (ret != 0); 533 return (ret != 0);
514 } 534 }
515 } 535 }
516 catch (Exception ex) 536 catch (Exception ex)
517 { 537 {
518 m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message); 538 m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
539 transaction.Rollback();
519 } 540 }
520 } 541 }
521 return false; 542 return false;
diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
index e7c8dc5..7feec91 100644
--- a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
@@ -218,23 +218,27 @@ namespace OpenSim.Data.MSSQL
218 if (words.Length > 2) 218 if (words.Length > 2)
219 return new UserAccountData[0]; 219 return new UserAccountData[0];
220 220
221 string sql = "";
222
221 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 223 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
222 using (SqlCommand cmd = new SqlCommand()) 224 using (SqlCommand cmd = new SqlCommand())
223 { 225 {
224 if (words.Length == 1) 226 if (words.Length == 1)
225 { 227 {
226 cmd.CommandText = String.Format("select * from {0} where ([ScopeID]=@ScopeID or [ScopeID]='00000000-0000-0000-0000-000000000000') and ([FirstName] like @search or [LastName] like @search)", m_Realm); 228 sql = String.Format("select * from {0} where ([ScopeID]=@ScopeID or [ScopeID]='00000000-0000-0000-0000-000000000000') and ([FirstName] like @search or [LastName] like @search)", m_Realm);
227 cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); 229 cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID));
228 cmd.Parameters.Add(m_database.CreateParameter("@search", "%" + words[0] + "%")); 230 cmd.Parameters.Add(m_database.CreateParameter("@search", "%" + words[0] + "%"));
229 } 231 }
230 else 232 else
231 { 233 {
232 cmd.CommandText = String.Format("select * from {0} where ([ScopeID]=@ScopeID or [ScopeID]='00000000-0000-0000-0000-000000000000') and ([FirstName] like @searchFirst or [LastName] like @searchLast)", m_Realm); 234 sql = String.Format("select * from {0} where ([ScopeID]=@ScopeID or [ScopeID]='00000000-0000-0000-0000-000000000000') and ([FirstName] like @searchFirst or [LastName] like @searchLast)", m_Realm);
233 cmd.Parameters.Add(m_database.CreateParameter("@searchFirst", "%" + words[0] + "%")); 235 cmd.Parameters.Add(m_database.CreateParameter("@searchFirst", "%" + words[0] + "%"));
234 cmd.Parameters.Add(m_database.CreateParameter("@searchLast", "%" + words[1] + "%")); 236 cmd.Parameters.Add(m_database.CreateParameter("@searchLast", "%" + words[1] + "%"));
235 cmd.Parameters.Add(m_database.CreateParameter("@ScopeID", scopeID.ToString())); 237 cmd.Parameters.Add(m_database.CreateParameter("@ScopeID", scopeID.ToString()));
236 } 238 }
237 239 cmd.Connection = conn;
240 cmd.CommandText = sql;
241 conn.Open();
238 return DoQuery(cmd); 242 return DoQuery(cmd);
239 } 243 }
240 } 244 }
diff --git a/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations b/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations
index 4d8ab0f..cc94c4e 100644
--- a/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/FriendsStore.migrations
@@ -19,4 +19,32 @@ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[userf
19INSERT INTO Friends (PrincipalID, Friend, Flags, Offered) 19INSERT INTO Friends (PrincipalID, Friend, Flags, Offered)
20SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; 20SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends;
21 21
22COMMIT
23
24:VERSION 3
25
26BEGIN TRANSACTION
27
28CREATE TABLE [Tmp_Friends]
29 ([PrincipalID] varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
30[Friend] varchar(255) NOT NULL,
31[Flags] char(16) NOT NULL DEFAULT '0',
32[Offered] varchar(32) NOT NULL DEFAULT 0)
33ON [PRIMARY]
34
35
36IF EXISTS(SELECT * FROM dbo.Friends)
37 EXEC('INSERT INTO dbo.Tmp_Friends (PrincipalID, Friend, Flags, Offered)
38 SELECT CONVERT(varchar(255),PrincipalID), Friend, Flags, Offered FROM dbo.Friends WITH (HOLDLOCK TABLOCKX)')
39
40DROP TABLE dbo.Friends
41
42EXECUTE sp_rename N'dbo.Tmp_Friends', N'Friends', 'OBJECT'
43
44ALTER TABLE dbo.Friends ADD
45 PRIMARY KEY CLUSTERED
46(
47 [PrincipalID] ASC, [Friend] ASC
48)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
49
22COMMIT \ No newline at end of file 50COMMIT \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations b/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations
index 4a3cb27..4e43653 100644
--- a/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/InventoryStore.migrations
@@ -244,4 +244,36 @@ ALTER TABLE inventoryitems
244ADD CONSTRAINT DF_inventoryitems_creatorID 244ADD CONSTRAINT DF_inventoryitems_creatorID
245DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID 245DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID
246 246
247:GO
248
249:VERSION 9
250
251BEGIN TRANSACTION
252
253# CreatorID goes up to VARCHAR(255)
254
255exec sp_rename 'inventoryitems.CreatorID', 'cr_old', 'COLUMN'
256
257:GO
258
259alter table inventoryitems
260 add creatorID varchar(255) NULL
261
262:GO
263
264update inventoryitems set creatorID = cr_old
265
266alter table inventoryitems
267drop CONSTRAINT DF_inventoryitems_creatorID
268:GO
269
270alter table inventoryitems
271 drop column cr_old
272 :GO
273COMMIT
274
275ALTER TABLE inventoryitems
276ADD CONSTRAINT DF_inventoryitems_creatorID
277DEFAULT '00000000-0000-0000-0000-000000000000' FOR creatorID
278
247:GO \ No newline at end of file 279:GO \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml b/OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml
deleted file mode 100644
index 15fd29e..0000000
--- a/OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml
+++ /dev/null
@@ -1,23 +0,0 @@
1<Addin id="OpenSim.Data.MSSQL" version="0.1">
2 <Runtime>
3 <Import assembly="OpenSim.Data.MSSQL.dll"/>
4 </Runtime>
5 <Dependencies>
6 <Addin id="OpenSim.Data" version="0.5" />
7 </Dependencies>
8 <Extension path = "/OpenSim/GridData">
9 <Plugin id="MSSQLGridData" provider="OpenSim.Data.MSSQL.dll" type="OpenSim.Data.MSSQL.MSSQLGridData" />
10 </Extension>
11 <Extension path = "/OpenSim/LogData">
12 <Plugin id="MSSQLLogData" provider="OpenSim.Data.MSSQL.dll" type="OpenSim.Data.MSSQL.MSSQLLogData" />
13 </Extension>
14 <Extension path = "/OpenSim/AssetData">
15 <Plugin id="MSSQLAssetData" provider="OpenSim.Data.MSSQL.dll" type="OpenSim.Data.MSSQL.MSSQLAssetData" />
16 </Extension>
17 <Extension path = "/OpenSim/InventoryData">
18 <Plugin id="MSSQLInventoryData" provider="OpenSim.Data.MSSQL.dll" type="OpenSim.Data.MSSQL.MSSQLInventoryData" />
19 </Extension>
20 <Extension path = "/OpenSim/UserData">
21 <Plugin id="MSSQLUserData" provider="OpenSim.Data.MSSQL.dll" type="OpenSim.Data.MSSQL.MSSQLUserData" />
22 </Extension>
23</Addin>
diff --git a/OpenSim/Data/MySQL/MySQLEstateData.cs b/OpenSim/Data/MySQL/MySQLEstateData.cs
index 9dcf5e2..3d647ca 100644
--- a/OpenSim/Data/MySQL/MySQLEstateData.cs
+++ b/OpenSim/Data/MySQL/MySQLEstateData.cs
@@ -149,6 +149,22 @@ namespace OpenSim.Data.MySQL
149 } 149 }
150 } 150 }
151 151
152 public EstateSettings CreateNewEstate()
153 {
154 EstateSettings es = new EstateSettings();
155 es.OnSave += StoreEstateSettings;
156
157 DoCreate(es);
158
159 LoadBanList(es);
160
161 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
162 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
163 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
164
165 return es;
166 }
167
152 private EstateSettings DoLoad(MySqlCommand cmd, UUID regionID, bool create) 168 private EstateSettings DoLoad(MySqlCommand cmd, UUID regionID, bool create)
153 { 169 {
154 EstateSettings es = new EstateSettings(); 170 EstateSettings es = new EstateSettings();
@@ -188,63 +204,65 @@ namespace OpenSim.Data.MySQL
188 204
189 if (!found && create) 205 if (!found && create)
190 { 206 {
191 // Migration case 207 DoCreate(es);
192 List<string> names = new List<string>(FieldList); 208 LinkRegion(regionID, (int)es.EstateID);
209 }
210 }
193 211
194 names.Remove("EstateID"); 212 LoadBanList(es);
195 213
196 string sql = "insert into estate_settings (" + String.Join(",", names.ToArray()) + ") values ( ?" + String.Join(", ?", names.ToArray()) + ")"; 214 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
215 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
216 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
217 return es;
218 }
197 219
198 using (MySqlCommand cmd2 = dbcon.CreateCommand()) 220 private void DoCreate(EstateSettings es)
199 { 221 {
200 cmd2.CommandText = sql; 222 // Migration case
201 cmd2.Parameters.Clear(); 223 List<string> names = new List<string>(FieldList);
202 224
203 foreach (string name in FieldList) 225 names.Remove("EstateID");
204 {
205 if (m_FieldMap[name].GetValue(es) is bool)
206 {
207 if ((bool)m_FieldMap[name].GetValue(es))
208 cmd2.Parameters.AddWithValue("?" + name, "1");
209 else
210 cmd2.Parameters.AddWithValue("?" + name, "0");
211 }
212 else
213 {
214 cmd2.Parameters.AddWithValue("?" + name, m_FieldMap[name].GetValue(es).ToString());
215 }
216 }
217 226
218 cmd2.ExecuteNonQuery(); 227 string sql = "insert into estate_settings (" + String.Join(",", names.ToArray()) + ") values ( ?" + String.Join(", ?", names.ToArray()) + ")";
219 228
220 cmd2.CommandText = "select LAST_INSERT_ID() as id"; 229 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
221 cmd2.Parameters.Clear(); 230 {
231 dbcon.Open();
232 using (MySqlCommand cmd2 = dbcon.CreateCommand())
233 {
234 cmd2.CommandText = sql;
235 cmd2.Parameters.Clear();
222 236
223 using (IDataReader r = cmd2.ExecuteReader()) 237 foreach (string name in FieldList)
238 {
239 if (m_FieldMap[name].GetValue(es) is bool)
240 {
241 if ((bool)m_FieldMap[name].GetValue(es))
242 cmd2.Parameters.AddWithValue("?" + name, "1");
243 else
244 cmd2.Parameters.AddWithValue("?" + name, "0");
245 }
246 else
224 { 247 {
225 r.Read(); 248 cmd2.Parameters.AddWithValue("?" + name, m_FieldMap[name].GetValue(es).ToString());
226 es.EstateID = Convert.ToUInt32(r["id"]);
227 } 249 }
250 }
228 251
229 cmd2.CommandText = "insert into estate_map values (?RegionID, ?EstateID)"; 252 cmd2.ExecuteNonQuery();
230 cmd2.Parameters.AddWithValue("?RegionID", regionID.ToString());
231 cmd2.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
232 253
233 // This will throw on dupe key 254 cmd2.CommandText = "select LAST_INSERT_ID() as id";
234 try { cmd2.ExecuteNonQuery(); } 255 cmd2.Parameters.Clear();
235 catch (Exception) { }
236 256
237 es.Save(); 257 using (IDataReader r = cmd2.ExecuteReader())
258 {
259 r.Read();
260 es.EstateID = Convert.ToUInt32(r["id"]);
238 } 261 }
262
263 es.Save();
239 } 264 }
240 } 265 }
241
242 LoadBanList(es);
243
244 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
245 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
246 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
247 return es;
248 } 266 }
249 267
250 public void StoreEstateSettings(EstateSettings es) 268 public void StoreEstateSettings(EstateSettings es)
@@ -477,7 +495,6 @@ namespace OpenSim.Data.MySQL
477 } 495 }
478 } 496 }
479 497
480
481 dbcon.Close(); 498 dbcon.Close();
482 } 499 }
483 500
@@ -507,7 +524,6 @@ namespace OpenSim.Data.MySQL
507 } 524 }
508 } 525 }
509 526
510
511 dbcon.Close(); 527 dbcon.Close();
512 } 528 }
513 529
@@ -519,16 +535,34 @@ namespace OpenSim.Data.MySQL
519 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 535 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
520 { 536 {
521 dbcon.Open(); 537 dbcon.Open();
538 MySqlTransaction transaction = dbcon.BeginTransaction();
522 539
523 try 540 try
524 { 541 {
542 // Delete any existing association of this region with an estate.
543 using (MySqlCommand cmd = dbcon.CreateCommand())
544 {
545 cmd.Transaction = transaction;
546 cmd.CommandText = "delete from estate_map where RegionID = ?RegionID";
547 cmd.Parameters.AddWithValue("?RegionID", regionID);
548
549 cmd.ExecuteNonQuery();
550 }
551
525 using (MySqlCommand cmd = dbcon.CreateCommand()) 552 using (MySqlCommand cmd = dbcon.CreateCommand())
526 { 553 {
554 cmd.Transaction = transaction;
527 cmd.CommandText = "insert into estate_map values (?RegionID, ?EstateID)"; 555 cmd.CommandText = "insert into estate_map values (?RegionID, ?EstateID)";
528 cmd.Parameters.AddWithValue("?RegionID", regionID); 556 cmd.Parameters.AddWithValue("?RegionID", regionID);
529 cmd.Parameters.AddWithValue("?EstateID", estateID); 557 cmd.Parameters.AddWithValue("?EstateID", estateID);
530 558
531 int ret = cmd.ExecuteNonQuery(); 559 int ret = cmd.ExecuteNonQuery();
560
561 if (ret != 0)
562 transaction.Commit();
563 else
564 transaction.Rollback();
565
532 dbcon.Close(); 566 dbcon.Close();
533 567
534 return (ret != 0); 568 return (ret != 0);
@@ -537,6 +571,7 @@ namespace OpenSim.Data.MySQL
537 catch (MySqlException ex) 571 catch (MySqlException ex)
538 { 572 {
539 m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message); 573 m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
574 transaction.Rollback();
540 } 575 }
541 576
542 dbcon.Close(); 577 dbcon.Close();
diff --git a/OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml b/OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml
deleted file mode 100644
index 9e99547..0000000
--- a/OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml
+++ /dev/null
@@ -1,23 +0,0 @@
1<Addin id="OpenSim.Data.MySQL" version="0.1">
2 <Runtime>
3 <Import assembly="OpenSim.Data.MySQL.dll"/>
4 </Runtime>
5 <Dependencies>
6 <Addin id="OpenSim.Data" version="0.5" />
7 </Dependencies>
8 <Extension path = "/OpenSim/GridData">
9 <Plugin id="MySQLGridData" provider="OpenSim.Data.MySQL.dll" type="OpenSim.Data.MySQL.MySQLGridData" />
10 </Extension>
11 <Extension path = "/OpenSim/LogData">
12 <Plugin id="MySQLLogData" provider="OpenSim.Data.MySQL.dll" type="OpenSim.Data.MySQL.MySQLLogData" />
13 </Extension>
14 <Extension path = "/OpenSim/AssetData">
15 <Plugin id="MySQLAssetData" provider="OpenSim.Data.MySQL.dll" type="OpenSim.Data.MySQL.MySQLAssetData" />
16 </Extension>
17 <Extension path = "/OpenSim/InventoryData">
18 <Plugin id="MySQLInventoryData" provider="OpenSim.Data.MySQL.dll" type="OpenSim.Data.MySQL.MySQLInventoryData" />
19 </Extension>
20 <Extension path = "/OpenSim/UserData">
21 <Plugin id="MySQLUserData" provider="OpenSim.Data.MySQL.dll" type="OpenSim.Data.MySQL.MySQLUserData" />
22 </Extension>
23</Addin>
diff --git a/OpenSim/Data/Null/NullEstateData.cs b/OpenSim/Data/Null/NullEstateData.cs
index 8db8064..d64136d 100755
--- a/OpenSim/Data/Null/NullEstateData.cs
+++ b/OpenSim/Data/Null/NullEstateData.cs
@@ -84,6 +84,11 @@ namespace OpenSim.Data.Null
84 { 84 {
85 return new EstateSettings(); 85 return new EstateSettings();
86 } 86 }
87
88 public EstateSettings CreateNewEstate()
89 {
90 return new EstateSettings();
91 }
87 92
88 public List<EstateSettings> LoadEstateSettingsAll() 93 public List<EstateSettings> LoadEstateSettingsAll()
89 { 94 {
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index c33a6f2..b788976 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -77,8 +77,10 @@ namespace OpenSim.Data.Null
77 } 77 }
78 78
79 public RegionSettings LoadRegionSettings(UUID regionUUID) 79 public RegionSettings LoadRegionSettings(UUID regionUUID)
80 { 80 {
81 return null; 81 RegionSettings rs = new RegionSettings();
82 rs.RegionUUID = regionUUID;
83 return rs;
82 } 84 }
83 85
84 public void StoreObject(SceneObjectGroup obj, UUID regionUUID) 86 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
diff --git a/OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml b/OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml
deleted file mode 100644
index e6764fa..0000000
--- a/OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml
+++ /dev/null
@@ -1,20 +0,0 @@
1<Addin id="OpenSim.Data.SQLite" version="0.1">
2 <Runtime>
3 <Import assembly="OpenSim.Data.SQLite.dll"/>
4 </Runtime>
5 <Dependencies>
6 <Addin id="OpenSim.Data" version="0.5" />
7 </Dependencies>
8 <Extension path = "/OpenSim/GridData">
9 <Plugin id="SQLiteGridData" provider="OpenSim.Data.SQLite.dll" type="OpenSim.Data.SQLite.SQLiteGridData" />
10 </Extension>
11 <Extension path = "/OpenSim/AssetData">
12 <Plugin id="SQLiteAssetData" provider="OpenSim.Data.SQLite.dll" type="OpenSim.Data.SQLite.SQLiteAssetData" />
13 </Extension>
14 <Extension path = "/OpenSim/InventoryData">
15 <Plugin id="SQLiteInventoryData" provider="OpenSim.Data.SQLite.dll" type="OpenSim.Data.SQLite.SQLiteInventoryStore" />
16 </Extension>
17 <Extension path = "/OpenSim/UserData">
18 <Plugin id="SQLiteUserData" provider="OpenSim.Data.SQLite.dll" type="OpenSim.Data.SQLite.SQLiteUserData" />
19 </Extension>
20</Addin>
diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs
index 65719a6..8db9262 100644
--- a/OpenSim/Data/SQLite/SQLiteEstateData.cs
+++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs
@@ -151,67 +151,77 @@ namespace OpenSim.Data.SQLite
151 } 151 }
152 else if (create) 152 else if (create)
153 { 153 {
154 r.Close(); 154 DoCreate(es);
155 LinkRegion(regionID, (int)es.EstateID);
156 }
155 157
156 List<string> names = new List<string>(FieldList); 158 LoadBanList(es);
157 159
158 names.Remove("EstateID"); 160 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
161 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
162 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
163 return es;
164 }
159 165
160 string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")"; 166 public EstateSettings CreateNewEstate()
167 {
168 EstateSettings es = new EstateSettings();
169 es.OnSave += StoreEstateSettings;
161 170
162 cmd.CommandText = sql; 171 DoCreate(es);
163 cmd.Parameters.Clear();
164 172
165 foreach (string name in FieldList) 173 LoadBanList(es);
166 {
167 if (m_FieldMap[name].GetValue(es) is bool)
168 {
169 if ((bool)m_FieldMap[name].GetValue(es))
170 cmd.Parameters.AddWithValue(":"+name, "1");
171 else
172 cmd.Parameters.AddWithValue(":"+name, "0");
173 }
174 else
175 {
176 cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
177 }
178 }
179 174
180 cmd.ExecuteNonQuery(); 175 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
176 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
177 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
181 178
182 cmd.CommandText = "select LAST_INSERT_ROWID() as id"; 179 return es;
183 cmd.Parameters.Clear(); 180 }
184 181
185 r = cmd.ExecuteReader(); 182 private void DoCreate(EstateSettings es)
183 {
184 List<string> names = new List<string>(FieldList);
186 185
187 r.Read(); 186 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand();
187 IDataReader r = null;
188 188
189 es.EstateID = Convert.ToUInt32(r["id"]); 189 names.Remove("EstateID");
190 190
191 r.Close(); 191 string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")";
192 192
193 cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; 193 cmd.CommandText = sql;
194 cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); 194 cmd.Parameters.Clear();
195 cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString());
196 195
197 // This will throw on dupe key 196 foreach (string name in FieldList)
198 try 197 {
198 if (m_FieldMap[name].GetValue(es) is bool)
199 { 199 {
200 cmd.ExecuteNonQuery(); 200 if ((bool)m_FieldMap[name].GetValue(es))
201 cmd.Parameters.AddWithValue(":"+name, "1");
202 else
203 cmd.Parameters.AddWithValue(":"+name, "0");
201 } 204 }
202 catch (Exception) 205 else
203 { 206 {
207 cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
204 } 208 }
205
206 es.Save();
207 } 209 }
208 210
209 LoadBanList(es); 211 cmd.ExecuteNonQuery();
210 212
211 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); 213 cmd.CommandText = "select LAST_INSERT_ROWID() as id";
212 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); 214 cmd.Parameters.Clear();
213 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); 215
214 return es; 216 r = cmd.ExecuteReader();
217
218 r.Read();
219
220 es.EstateID = Convert.ToUInt32(r["id"]);
221
222 r.Close();
223
224 es.Save();
215 } 225 }
216 226
217 public void StoreEstateSettings(EstateSettings es) 227 public void StoreEstateSettings(EstateSettings es)
@@ -440,16 +450,36 @@ namespace OpenSim.Data.SQLite
440 450
441 public bool LinkRegion(UUID regionID, int estateID) 451 public bool LinkRegion(UUID regionID, int estateID)
442 { 452 {
443 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 453 SqliteTransaction transaction = m_connection.BeginTransaction();
444 454
445 cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; 455 // Delete any existing estate mapping for this region.
446 cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); 456 using(SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
447 cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); 457 {
458 cmd.CommandText = "delete from estate_map where RegionID = :RegionID";
459 cmd.Transaction = transaction;
460 cmd.Parameters.AddWithValue(":RegionID", regionID.ToString());
448 461
449 if (cmd.ExecuteNonQuery() == 0) 462 cmd.ExecuteNonQuery();
450 return false; 463 }
451 464
452 return true; 465 using(SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
466 {
467 cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)";
468 cmd.Transaction = transaction;
469 cmd.Parameters.AddWithValue(":RegionID", regionID.ToString());
470 cmd.Parameters.AddWithValue(":EstateID", estateID.ToString());
471
472 if (cmd.ExecuteNonQuery() == 0)
473 {
474 transaction.Rollback();
475 return false;
476 }
477 else
478 {
479 transaction.Commit();
480 return true;
481 }
482 }
453 } 483 }
454 484
455 public List<UUID> GetRegions(int estateID) 485 public List<UUID> GetRegions(int estateID)
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index e8c85c9..d2c6c57 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -167,6 +167,7 @@ namespace OpenSim.Framework
167 get { return m_metadata.FullID; } 167 get { return m_metadata.FullID; }
168 set { m_metadata.FullID = value; } 168 set { m_metadata.FullID = value; }
169 } 169 }
170
170 /// <summary> 171 /// <summary>
171 /// Asset MetaData ID (transferring from UUID to string ID) 172 /// Asset MetaData ID (transferring from UUID to string ID)
172 /// </summary> 173 /// </summary>
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index cce44b0..72b580b 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -225,6 +225,8 @@ namespace OpenSim.Framework
225 /// </summary> 225 /// </summary>
226 public virtual void ResetAppearance() 226 public virtual void ResetAppearance()
227 { 227 {
228// m_log.WarnFormat("[AVATAR APPEARANCE]: Reset appearance");
229
228 m_serial = 0; 230 m_serial = 0;
229 231
230 SetDefaultTexture(); 232 SetDefaultTexture();
@@ -391,10 +393,14 @@ namespace OpenSim.Framework
391 public List<AvatarAttachment> GetAttachments() 393 public List<AvatarAttachment> GetAttachments()
392 { 394 {
393 List<AvatarAttachment> alist = new List<AvatarAttachment>(); 395 List<AvatarAttachment> alist = new List<AvatarAttachment>();
394 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments) 396
397 lock (m_attachments)
395 { 398 {
396 foreach (AvatarAttachment attach in kvp.Value) 399 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
397 alist.Add(new AvatarAttachment(attach)); 400 {
401 foreach (AvatarAttachment attach in kvp.Value)
402 alist.Add(new AvatarAttachment(attach));
403 }
398 } 404 }
399 405
400 return alist; 406 return alist;
@@ -406,10 +412,13 @@ namespace OpenSim.Framework
406// "[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}", 412// "[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}",
407// attach.ItemID, attach.AssetID, attach.AttachPoint); 413// attach.ItemID, attach.AssetID, attach.AttachPoint);
408 414
409 if (!m_attachments.ContainsKey(attach.AttachPoint)) 415 lock (m_attachments)
410 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>(); 416 {
411 417 if (!m_attachments.ContainsKey(attach.AttachPoint))
412 m_attachments[attach.AttachPoint].Add(attach); 418 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
419
420 m_attachments[attach.AttachPoint].Add(attach);
421 }
413 } 422 }
414 423
415 internal void ReplaceAttachment(AvatarAttachment attach) 424 internal void ReplaceAttachment(AvatarAttachment attach)
@@ -418,8 +427,11 @@ namespace OpenSim.Framework
418// "[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}", 427// "[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}",
419// attach.ItemID, attach.AssetID, attach.AttachPoint); 428// attach.ItemID, attach.AssetID, attach.AttachPoint);
420 429
421 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>(); 430 lock (m_attachments)
422 m_attachments[attach.AttachPoint].Add(attach); 431 {
432 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
433 m_attachments[attach.AttachPoint].Add(attach);
434 }
423 } 435 }
424 436
425 /// <summary> 437 /// <summary>
@@ -448,10 +460,13 @@ namespace OpenSim.Framework
448 460
449 if (item == UUID.Zero) 461 if (item == UUID.Zero)
450 { 462 {
451 if (m_attachments.ContainsKey(attachpoint)) 463 lock (m_attachments)
452 { 464 {
453 m_attachments.Remove(attachpoint); 465 if (m_attachments.ContainsKey(attachpoint))
454 return true; 466 {
467 m_attachments.Remove(attachpoint);
468 return true;
469 }
455 } 470 }
456 471
457 return false; 472 return false;
@@ -494,11 +509,14 @@ namespace OpenSim.Framework
494 /// <returns>Returns null if this item is not attached.</returns> 509 /// <returns>Returns null if this item is not attached.</returns>
495 public AvatarAttachment GetAttachmentForItem(UUID itemID) 510 public AvatarAttachment GetAttachmentForItem(UUID itemID)
496 { 511 {
497 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments) 512 lock (m_attachments)
498 { 513 {
499 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); 514 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
500 if (index >= 0) 515 {
501 return kvp.Value[index]; 516 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
517 if (index >= 0)
518 return kvp.Value[index];
519 }
502 } 520 }
503 521
504 return null; 522 return null;
@@ -506,11 +524,14 @@ namespace OpenSim.Framework
506 524
507 public int GetAttachpoint(UUID itemID) 525 public int GetAttachpoint(UUID itemID)
508 { 526 {
509 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments) 527 lock (m_attachments)
510 { 528 {
511 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); 529 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
512 if (index >= 0) 530 {
513 return kvp.Key; 531 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
532 if (index >= 0)
533 return kvp.Key;
534 }
514 } 535 }
515 536
516 return 0; 537 return 0;
@@ -518,27 +539,32 @@ namespace OpenSim.Framework
518 539
519 public bool DetachAttachment(UUID itemID) 540 public bool DetachAttachment(UUID itemID)
520 { 541 {
521 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments) 542 lock (m_attachments)
522 { 543 {
523 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); 544 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
524 if (index >= 0)
525 { 545 {
526 // Remove it from the list of attachments at that attach point 546 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
527 m_attachments[kvp.Key].RemoveAt(index); 547 if (index >= 0)
528 548 {
529 // And remove the list if there are no more attachments here 549 // Remove it from the list of attachments at that attach point
530 if (m_attachments[kvp.Key].Count == 0) 550 m_attachments[kvp.Key].RemoveAt(index);
531 m_attachments.Remove(kvp.Key); 551
532 552 // And remove the list if there are no more attachments here
533 return true; 553 if (m_attachments[kvp.Key].Count == 0)
554 m_attachments.Remove(kvp.Key);
555
556 return true;
557 }
534 } 558 }
535 } 559 }
560
536 return false; 561 return false;
537 } 562 }
538 563
539 public void ClearAttachments() 564 public void ClearAttachments()
540 { 565 {
541 m_attachments.Clear(); 566 lock (m_attachments)
567 m_attachments.Clear();
542 } 568 }
543 569
544 #region Packing Functions 570 #region Packing Functions
@@ -576,7 +602,8 @@ namespace OpenSim.Framework
576 data["visualparams"] = visualparams; 602 data["visualparams"] = visualparams;
577 603
578 // Attachments 604 // Attachments
579 OSDArray attachs = new OSDArray(m_attachments.Count); 605 List<AvatarAttachment> attachments = GetAttachments();
606 OSDArray attachs = new OSDArray(attachments.Count);
580 foreach (AvatarAttachment attach in GetAttachments()) 607 foreach (AvatarAttachment attach in GetAttachments())
581 attachs.Add(attach.Pack()); 608 attachs.Add(attach.Pack());
582 data["attachments"] = attachs; 609 data["attachments"] = attachs;
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index 53ec166..5a4811e 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -441,7 +441,6 @@ namespace OpenSim.Framework
441 args["controllers"] = controls; 441 args["controllers"] = controls;
442 } 442 }
443 443
444
445 if ((CallbackURI != null) && (!CallbackURI.Equals(""))) 444 if ((CallbackURI != null) && (!CallbackURI.Equals("")))
446 args["callback_uri"] = OSD.FromString(CallbackURI); 445 args["callback_uri"] = OSD.FromString(CallbackURI);
447 446
diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs
index eda41b8..7c8626d 100644
--- a/OpenSim/Framework/Console/LocalConsole.cs
+++ b/OpenSim/Framework/Console/LocalConsole.cs
@@ -46,12 +46,11 @@ namespace OpenSim.Framework.Console
46 // private readonly object m_syncRoot = new object(); 46 // private readonly object m_syncRoot = new object();
47 private const string LOGLEVEL_NONE = "(none)"; 47 private const string LOGLEVEL_NONE = "(none)";
48 48
49 private int y = -1; 49 private int m_cursorYPosition = -1;
50 private int cp = 0; 50 private int m_cursorXPosition = 0;
51 private int h = 1; 51 private StringBuilder m_commandLine = new StringBuilder();
52 private StringBuilder cmdline = new StringBuilder(); 52 private bool m_echo = true;
53 private bool echo = true; 53 private List<string> m_history = new List<string>();
54 private List<string> history = new List<string>();
55 54
56 private static readonly ConsoleColor[] Colors = { 55 private static readonly ConsoleColor[] Colors = {
57 // the dark colors don't seem to be visible on some black background terminals like putty :( 56 // the dark colors don't seem to be visible on some black background terminals like putty :(
@@ -81,10 +80,10 @@ namespace OpenSim.Framework.Console
81 80
82 private void AddToHistory(string text) 81 private void AddToHistory(string text)
83 { 82 {
84 while (history.Count >= 100) 83 while (m_history.Count >= 100)
85 history.RemoveAt(0); 84 m_history.RemoveAt(0);
86 85
87 history.Add(text); 86 m_history.Add(text);
88 } 87 }
89 88
90 /// <summary> 89 /// <summary>
@@ -111,11 +110,11 @@ namespace OpenSim.Framework.Console
111 } 110 }
112 else 111 else
113 { 112 {
114 int bw = System.Console.BufferWidth; 113 int bufferWidth = System.Console.BufferWidth;
115 114
116 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) 115 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657)
117 if (bw > 0 && left >= bw) 116 if (bufferWidth > 0 && left >= bufferWidth)
118 System.Console.CursorLeft = bw - 1; 117 System.Console.CursorLeft = bufferWidth - 1;
119 } 118 }
120 119
121 if (top < 0) 120 if (top < 0)
@@ -124,11 +123,11 @@ namespace OpenSim.Framework.Console
124 } 123 }
125 else 124 else
126 { 125 {
127 int bh = System.Console.BufferHeight; 126 int bufferHeight = System.Console.BufferHeight;
128 127
129 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) 128 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657)
130 if (bh > 0 && top >= bh) 129 if (bufferHeight > 0 && top >= bufferHeight)
131 top = bh - 1; 130 top = bufferHeight - 1;
132 } 131 }
133 132
134 System.Console.CursorTop = top; 133 System.Console.CursorTop = top;
@@ -160,10 +159,10 @@ namespace OpenSim.Framework.Console
160 } 159 }
161 else 160 else
162 { 161 {
163 int bh = System.Console.BufferHeight; 162 int bufferHeight = System.Console.BufferHeight;
164 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) 163 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657)
165 if (bh > 0 && top >= bh) 164 if (bufferHeight > 0 && top >= bufferHeight)
166 System.Console.CursorTop = bh - 1; 165 System.Console.CursorTop = bufferHeight - 1;
167 } 166 }
168 167
169 if (left < 0) 168 if (left < 0)
@@ -172,11 +171,11 @@ namespace OpenSim.Framework.Console
172 } 171 }
173 else 172 else
174 { 173 {
175 int bw = System.Console.BufferWidth; 174 int bufferWidth = System.Console.BufferWidth;
176 175
177 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) 176 // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657)
178 if (bw > 0 && left >= bw) 177 if (bufferWidth > 0 && left >= bufferWidth)
179 left = bw - 1; 178 left = bufferWidth - 1;
180 } 179 }
181 180
182 System.Console.CursorLeft = left; 181 System.Console.CursorLeft = left;
@@ -186,31 +185,30 @@ namespace OpenSim.Framework.Console
186 185
187 private void Show() 186 private void Show()
188 { 187 {
189 lock (cmdline) 188 lock (m_commandLine)
190 { 189 {
191 if (y == -1 || System.Console.BufferWidth == 0) 190 if (m_cursorYPosition == -1 || System.Console.BufferWidth == 0)
192 return; 191 return;
193 192
194 int xc = prompt.Length + cp; 193 int xc = prompt.Length + m_cursorXPosition;
195 int new_x = xc % System.Console.BufferWidth; 194 int new_x = xc % System.Console.BufferWidth;
196 int new_y = y + xc / System.Console.BufferWidth; 195 int new_y = m_cursorYPosition + xc / System.Console.BufferWidth;
197 int end_y = y + (cmdline.Length + prompt.Length) / System.Console.BufferWidth; 196 int end_y = m_cursorYPosition + (m_commandLine.Length + prompt.Length) / System.Console.BufferWidth;
198 if (end_y / System.Console.BufferWidth >= h) 197
199 h++;
200 if (end_y >= System.Console.BufferHeight) // wrap 198 if (end_y >= System.Console.BufferHeight) // wrap
201 { 199 {
202 y--; 200 m_cursorYPosition--;
203 new_y--; 201 new_y--;
204 SetCursorLeft(0); 202 SetCursorLeft(0);
205 SetCursorTop(System.Console.BufferHeight - 1); 203 SetCursorTop(System.Console.BufferHeight - 1);
206 System.Console.WriteLine(" "); 204 System.Console.WriteLine(" ");
207 } 205 }
208 206
209 y = SetCursorTop(y); 207 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
210 SetCursorLeft(0); 208 SetCursorLeft(0);
211 209
212 if (echo) 210 if (m_echo)
213 System.Console.Write("{0}{1}", prompt, cmdline); 211 System.Console.Write("{0}{1}", prompt, m_commandLine);
214 else 212 else
215 System.Console.Write("{0}", prompt); 213 System.Console.Write("{0}", prompt);
216 214
@@ -221,20 +219,20 @@ namespace OpenSim.Framework.Console
221 219
222 public override void LockOutput() 220 public override void LockOutput()
223 { 221 {
224 Monitor.Enter(cmdline); 222 Monitor.Enter(m_commandLine);
225 try 223 try
226 { 224 {
227 if (y != -1) 225 if (m_cursorYPosition != -1)
228 { 226 {
229 y = SetCursorTop(y); 227 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
230 System.Console.CursorLeft = 0; 228 System.Console.CursorLeft = 0;
231 229
232 int count = cmdline.Length + prompt.Length; 230 int count = m_commandLine.Length + prompt.Length;
233 231
234 while (count-- > 0) 232 while (count-- > 0)
235 System.Console.Write(" "); 233 System.Console.Write(" ");
236 234
237 y = SetCursorTop(y); 235 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
238 SetCursorLeft(0); 236 SetCursorLeft(0);
239 } 237 }
240 } 238 }
@@ -245,12 +243,12 @@ namespace OpenSim.Framework.Console
245 243
246 public override void UnlockOutput() 244 public override void UnlockOutput()
247 { 245 {
248 if (y != -1) 246 if (m_cursorYPosition != -1)
249 { 247 {
250 y = System.Console.CursorTop; 248 m_cursorYPosition = System.Console.CursorTop;
251 Show(); 249 Show();
252 } 250 }
253 Monitor.Exit(cmdline); 251 Monitor.Exit(m_commandLine);
254 } 252 }
255 253
256 private void WriteColorText(ConsoleColor color, string sender) 254 private void WriteColorText(ConsoleColor color, string sender)
@@ -317,29 +315,29 @@ namespace OpenSim.Framework.Console
317 315
318 public override void Output(string text, string level) 316 public override void Output(string text, string level)
319 { 317 {
320 lock (cmdline) 318 lock (m_commandLine)
321 { 319 {
322 if (y == -1) 320 if (m_cursorYPosition == -1)
323 { 321 {
324 WriteLocalText(text, level); 322 WriteLocalText(text, level);
325 323
326 return; 324 return;
327 } 325 }
328 326
329 y = SetCursorTop(y); 327 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
330 SetCursorLeft(0); 328 SetCursorLeft(0);
331 329
332 int count = cmdline.Length + prompt.Length; 330 int count = m_commandLine.Length + prompt.Length;
333 331
334 while (count-- > 0) 332 while (count-- > 0)
335 System.Console.Write(" "); 333 System.Console.Write(" ");
336 334
337 y = SetCursorTop(y); 335 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
338 SetCursorLeft(0); 336 SetCursorLeft(0);
339 337
340 WriteLocalText(text, level); 338 WriteLocalText(text, level);
341 339
342 y = System.Console.CursorTop; 340 m_cursorYPosition = System.Console.CursorTop;
343 341
344 Show(); 342 Show();
345 } 343 }
@@ -347,9 +345,9 @@ namespace OpenSim.Framework.Console
347 345
348 private bool ContextHelp() 346 private bool ContextHelp()
349 { 347 {
350 string[] words = Parser.Parse(cmdline.ToString()); 348 string[] words = Parser.Parse(m_commandLine.ToString());
351 349
352 bool trailingSpace = cmdline.ToString().EndsWith(" "); 350 bool trailingSpace = m_commandLine.ToString().EndsWith(" ");
353 351
354 // Allow ? through while typing a URI 352 // Allow ? through while typing a URI
355 // 353 //
@@ -368,19 +366,18 @@ namespace OpenSim.Framework.Console
368 366
369 public override string ReadLine(string p, bool isCommand, bool e) 367 public override string ReadLine(string p, bool isCommand, bool e)
370 { 368 {
371 h = 1; 369 m_cursorXPosition = 0;
372 cp = 0;
373 prompt = p; 370 prompt = p;
374 echo = e; 371 m_echo = e;
375 int historyLine = history.Count; 372 int historyLine = m_history.Count;
376 373
377 SetCursorLeft(0); // Needed for mono 374 SetCursorLeft(0); // Needed for mono
378 System.Console.Write(" "); // Needed for mono 375 System.Console.Write(" "); // Needed for mono
379 376
380 lock (cmdline) 377 lock (m_commandLine)
381 { 378 {
382 y = System.Console.CursorTop; 379 m_cursorYPosition = System.Console.CursorTop;
383 cmdline.Remove(0, cmdline.Length); 380 m_commandLine.Remove(0, m_commandLine.Length);
384 } 381 }
385 382
386 while (true) 383 while (true)
@@ -388,92 +385,95 @@ namespace OpenSim.Framework.Console
388 Show(); 385 Show();
389 386
390 ConsoleKeyInfo key = System.Console.ReadKey(true); 387 ConsoleKeyInfo key = System.Console.ReadKey(true);
391 char c = key.KeyChar; 388 char enteredChar = key.KeyChar;
392 389
393 if (!Char.IsControl(c)) 390 if (!Char.IsControl(enteredChar))
394 { 391 {
395 if (cp >= 318) 392 if (m_cursorXPosition >= 318)
396 continue; 393 continue;
397 394
398 if (c == '?' && isCommand) 395 if (enteredChar == '?' && isCommand)
399 { 396 {
400 if (ContextHelp()) 397 if (ContextHelp())
401 continue; 398 continue;
402 } 399 }
403 400
404 cmdline.Insert(cp, c); 401 m_commandLine.Insert(m_cursorXPosition, enteredChar);
405 cp++; 402 m_cursorXPosition++;
406 } 403 }
407 else 404 else
408 { 405 {
409 switch (key.Key) 406 switch (key.Key)
410 { 407 {
411 case ConsoleKey.Backspace: 408 case ConsoleKey.Backspace:
412 if (cp == 0) 409 if (m_cursorXPosition == 0)
413 break; 410 break;
414 cmdline.Remove(cp-1, 1); 411 m_commandLine.Remove(m_cursorXPosition-1, 1);
415 cp--; 412 m_cursorXPosition--;
416 413
417 SetCursorLeft(0); 414 SetCursorLeft(0);
418 y = SetCursorTop(y); 415 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
419 416
420 System.Console.Write("{0}{1} ", prompt, cmdline); 417 if (m_echo)
418 System.Console.Write("{0}{1} ", prompt, m_commandLine);
419 else
420 System.Console.Write("{0}", prompt);
421 421
422 break; 422 break;
423 case ConsoleKey.End: 423 case ConsoleKey.End:
424 cp = cmdline.Length; 424 m_cursorXPosition = m_commandLine.Length;
425 break; 425 break;
426 case ConsoleKey.Home: 426 case ConsoleKey.Home:
427 cp = 0; 427 m_cursorXPosition = 0;
428 break; 428 break;
429 case ConsoleKey.UpArrow: 429 case ConsoleKey.UpArrow:
430 if (historyLine < 1) 430 if (historyLine < 1)
431 break; 431 break;
432 historyLine--; 432 historyLine--;
433 LockOutput(); 433 LockOutput();
434 cmdline.Remove(0, cmdline.Length); 434 m_commandLine.Remove(0, m_commandLine.Length);
435 cmdline.Append(history[historyLine]); 435 m_commandLine.Append(m_history[historyLine]);
436 cp = cmdline.Length; 436 m_cursorXPosition = m_commandLine.Length;
437 UnlockOutput(); 437 UnlockOutput();
438 break; 438 break;
439 case ConsoleKey.DownArrow: 439 case ConsoleKey.DownArrow:
440 if (historyLine >= history.Count) 440 if (historyLine >= m_history.Count)
441 break; 441 break;
442 historyLine++; 442 historyLine++;
443 LockOutput(); 443 LockOutput();
444 if (historyLine == history.Count) 444 if (historyLine == m_history.Count)
445 { 445 {
446 cmdline.Remove(0, cmdline.Length); 446 m_commandLine.Remove(0, m_commandLine.Length);
447 } 447 }
448 else 448 else
449 { 449 {
450 cmdline.Remove(0, cmdline.Length); 450 m_commandLine.Remove(0, m_commandLine.Length);
451 cmdline.Append(history[historyLine]); 451 m_commandLine.Append(m_history[historyLine]);
452 } 452 }
453 cp = cmdline.Length; 453 m_cursorXPosition = m_commandLine.Length;
454 UnlockOutput(); 454 UnlockOutput();
455 break; 455 break;
456 case ConsoleKey.LeftArrow: 456 case ConsoleKey.LeftArrow:
457 if (cp > 0) 457 if (m_cursorXPosition > 0)
458 cp--; 458 m_cursorXPosition--;
459 break; 459 break;
460 case ConsoleKey.RightArrow: 460 case ConsoleKey.RightArrow:
461 if (cp < cmdline.Length) 461 if (m_cursorXPosition < m_commandLine.Length)
462 cp++; 462 m_cursorXPosition++;
463 break; 463 break;
464 case ConsoleKey.Enter: 464 case ConsoleKey.Enter:
465 SetCursorLeft(0); 465 SetCursorLeft(0);
466 y = SetCursorTop(y); 466 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
467 467
468 System.Console.WriteLine(); 468 System.Console.WriteLine();
469 //Show(); 469 //Show();
470 470
471 lock (cmdline) 471 lock (m_commandLine)
472 { 472 {
473 y = -1; 473 m_cursorYPosition = -1;
474 } 474 }
475 475
476 string commandLine = cmdline.ToString(); 476 string commandLine = m_commandLine.ToString();
477 477
478 if (isCommand) 478 if (isCommand)
479 { 479 {
@@ -481,12 +481,12 @@ namespace OpenSim.Framework.Console
481 481
482 if (cmd.Length != 0) 482 if (cmd.Length != 0)
483 { 483 {
484 int i; 484 int index;
485 485
486 for (i=0 ; i < cmd.Length ; i++) 486 for (index=0 ; index < cmd.Length ; index++)
487 { 487 {
488 if (cmd[i].Contains(" ")) 488 if (cmd[index].Contains(" "))
489 cmd[i] = "\"" + cmd[i] + "\""; 489 cmd[index] = "\"" + cmd[index] + "\"";
490 } 490 }
491 AddToHistory(String.Join(" ", cmd)); 491 AddToHistory(String.Join(" ", cmd));
492 return String.Empty; 492 return String.Empty;
@@ -494,7 +494,7 @@ namespace OpenSim.Framework.Console
494 } 494 }
495 495
496 // If we're not echoing to screen (e.g. a password) then we probably don't want it in history 496 // If we're not echoing to screen (e.g. a password) then we probably don't want it in history
497 if (echo && commandLine != "") 497 if (m_echo && commandLine != "")
498 AddToHistory(commandLine); 498 AddToHistory(commandLine);
499 499
500 return commandLine; 500 return commandLine;
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 150ff1b..47e79d1 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -935,7 +935,7 @@ namespace OpenSim.Framework
935 event ScriptReset OnScriptReset; 935 event ScriptReset OnScriptReset;
936 event GetScriptRunning OnGetScriptRunning; 936 event GetScriptRunning OnGetScriptRunning;
937 event SetScriptRunning OnSetScriptRunning; 937 event SetScriptRunning OnSetScriptRunning;
938 event Action<Vector3, bool> OnAutoPilotGo; 938 event Action<Vector3, bool, bool> OnAutoPilotGo;
939 939
940 event TerrainUnacked OnUnackedTerrain; 940 event TerrainUnacked OnUnackedTerrain;
941 event ActivateGesture OnActivateGesture; 941 event ActivateGesture OnActivateGesture;
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 745da17..c4fc643 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1372,11 +1372,30 @@ namespace OpenSim.Framework
1372 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; 1372 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri;
1373 } 1373 }
1374 1374
1375 /// <summary>
1376 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
1377 /// </summary>
1378 /// <param name="str">
1379 /// If null or empty, then an bytes[0] is returned.
1380 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1381 /// </param>
1382 /// <param name="args">
1383 /// Arguments to substitute into the string via the {} mechanism.
1384 /// </param>
1385 /// <returns></returns>
1375 public static byte[] StringToBytes256(string str, params object[] args) 1386 public static byte[] StringToBytes256(string str, params object[] args)
1376 { 1387 {
1377 return StringToBytes256(string.Format(str, args)); 1388 return StringToBytes256(string.Format(str, args));
1378 } 1389 }
1379 1390
1391 /// <summary>
1392 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
1393 /// </summary>
1394 /// <param name="str">
1395 /// If null or empty, then an bytes[0] is returned.
1396 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1397 /// </param>
1398 /// <returns></returns>
1380 public static byte[] StringToBytes256(string str) 1399 public static byte[] StringToBytes256(string str)
1381 { 1400 {
1382 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } 1401 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
@@ -1395,11 +1414,30 @@ namespace OpenSim.Framework
1395 return data; 1414 return data;
1396 } 1415 }
1397 1416
1417 /// <summary>
1418 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary.
1419 /// </summary>
1420 /// <param name="str">
1421 /// If null or empty, then an bytes[0] is returned.
1422 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1423 /// </param>
1424 /// <param name="args">
1425 /// Arguments to substitute into the string via the {} mechanism.
1426 /// </param>
1427 /// <returns></returns>
1398 public static byte[] StringToBytes1024(string str, params object[] args) 1428 public static byte[] StringToBytes1024(string str, params object[] args)
1399 { 1429 {
1400 return StringToBytes1024(string.Format(str, args)); 1430 return StringToBytes1024(string.Format(str, args));
1401 } 1431 }
1402 1432
1433 /// <summary>
1434 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary.
1435 /// </summary>
1436 /// <param name="str">
1437 /// If null or empty, then an bytes[0] is returned.
1438 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
1439 /// </param>
1440 /// <returns></returns>
1403 public static byte[] StringToBytes1024(string str) 1441 public static byte[] StringToBytes1024(string str)
1404 { 1442 {
1405 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } 1443 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index fe1525b..e5b9dcb 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -269,13 +269,15 @@ namespace OpenSim
269 269
270 m_console.Commands.AddCommand("region", false, "save oar", 270 m_console.Commands.AddCommand("region", false, "save oar",
271 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", 271 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
272 "save oar [-p|--profile=<url>] [--noassets] [<OAR path>]", 272 "save oar [-p|--profile=<url>] [--noassets] [--perm=<permissions>] [<OAR path>]",
273 "Save a region's data to an OAR archive.", 273 "Save a region's data to an OAR archive.",
274// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 274// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
275 "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine 275 "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine
276 + " The OAR path must be a filesystem path." 276 + "--noassets stops assets being saved to the OAR." + Environment.NewLine
277 + " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine 277 + "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine
278 + "--noassets stops assets being saved to the OAR.", 278 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
279 + "The OAR path must be a filesystem path."
280 + " If this is not given then the oar is saved to region.oar in the current directory.",
279 SaveOar); 281 SaveOar);
280 282
281 m_console.Commands.AddCommand("region", false, "edit scale", 283 m_console.Commands.AddCommand("region", false, "edit scale",
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 00b080c..866ba9a 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -41,11 +41,15 @@ using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Framework.Statistics; 42using OpenSim.Framework.Statistics;
43using OpenSim.Region.ClientStack; 43using OpenSim.Region.ClientStack;
44using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts;
44using OpenSim.Region.Framework; 45using OpenSim.Region.Framework;
45using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 47using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Physics.Manager; 48using OpenSim.Region.Physics.Manager;
48using OpenSim.Server.Base; 49using OpenSim.Server.Base;
50using OpenSim.Services.Base;
51using OpenSim.Services.Interfaces;
52using OpenSim.Services.UserAccountService;
49 53
50namespace OpenSim 54namespace OpenSim
51{ 55{
@@ -362,6 +366,9 @@ namespace OpenSim
362 366
363 scene.SetModuleInterfaces(); 367 scene.SetModuleInterfaces();
364 368
369 while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
370 SetUpEstateOwner(scene);
371
365 // Prims have to be loaded after module configuration since some modules may be invoked during the load 372 // Prims have to be loaded after module configuration since some modules may be invoked during the load
366 scene.LoadPrimsFromStorage(regionInfo.originRegionID); 373 scene.LoadPrimsFromStorage(regionInfo.originRegionID);
367 374
@@ -411,9 +418,69 @@ namespace OpenSim
411 418
412 scene.StartTimer(); 419 scene.StartTimer();
413 420
421 scene.StartScripts();
422
414 return clientServer; 423 return clientServer;
415 } 424 }
416 425
426 /// <summary>
427 /// Try to set up the estate owner for the given scene.
428 /// </summary>
429 /// <remarks>
430 /// The involves asking the user for information about the user on the console. If the user does not already
431 /// exist then it is created.
432 /// </remarks>
433 /// <param name="scene"></param>
434 private void SetUpEstateOwner(Scene scene)
435 {
436 RegionInfo regionInfo = scene.RegionInfo;
437
438 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName);
439 List<char> excluded = new List<char>(new char[1]{' '});
440 string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded);
441 string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded);
442
443 UserAccount account = scene.UserAccountService.GetUserAccount(regionInfo.ScopeID, first, last);
444
445 if (account == null)
446 {
447
448 // XXX: The LocalUserAccountServicesConnector is currently registering its inner service rather than
449 // itself!
450// if (scene.UserAccountService is LocalUserAccountServicesConnector)
451// {
452// IUserAccountService innerUas
453// = ((LocalUserAccountServicesConnector)scene.UserAccountService).UserAccountService;
454//
455// m_log.DebugFormat("B {0}", innerUas.GetType());
456//
457// if (innerUas is UserAccountService)
458// {
459
460 if (scene.UserAccountService is UserAccountService)
461 {
462 string password = MainConsole.Instance.PasswdPrompt("Password");
463 string email = MainConsole.Instance.CmdPrompt("Email", "");
464
465 account
466 = ((UserAccountService)scene.UserAccountService).CreateUser(
467 regionInfo.ScopeID, first, last, password, email);
468 }
469// }
470 }
471
472 if (account == null)
473 {
474 m_log.ErrorFormat(
475 "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first.");
476 }
477 else
478 {
479 regionInfo.EstateSettings.EstateOwner = account.PrincipalID;
480 regionInfo.EstateSettings.Save();
481 }
482 }
483
417 private void ShutdownRegion(Scene scene) 484 private void ShutdownRegion(Scene scene)
418 { 485 {
419 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName); 486 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index e9ee7be..ce2ff86 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -231,7 +231,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
231 public event ScriptReset OnScriptReset; 231 public event ScriptReset OnScriptReset;
232 public event GetScriptRunning OnGetScriptRunning; 232 public event GetScriptRunning OnGetScriptRunning;
233 public event SetScriptRunning OnSetScriptRunning; 233 public event SetScriptRunning OnSetScriptRunning;
234 public event Action<Vector3, bool> OnAutoPilotGo; 234 public event Action<Vector3, bool, bool> OnAutoPilotGo;
235 public event TerrainUnacked OnUnackedTerrain; 235 public event TerrainUnacked OnUnackedTerrain;
236 public event ActivateGesture OnActivateGesture; 236 public event ActivateGesture OnActivateGesture;
237 public event DeactivateGesture OnDeactivateGesture; 237 public event DeactivateGesture OnDeactivateGesture;
@@ -4119,8 +4119,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4119 while (updatesThisCall < m_maxUpdates) 4119 while (updatesThisCall < m_maxUpdates)
4120 { 4120 {
4121 lock (m_entityProps.SyncRoot) 4121 lock (m_entityProps.SyncRoot)
4122 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) 4122 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
4123 break; 4123 break;
4124 4124
4125 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; 4125 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
4126 if (update.SendFamilyProps) 4126 if (update.SendFamilyProps)
@@ -11640,9 +11640,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11640 locy = Convert.ToSingle(args[1]) - (float)regionY; 11640 locy = Convert.ToSingle(args[1]) - (float)regionY;
11641 locz = Convert.ToSingle(args[2]); 11641 locz = Convert.ToSingle(args[2]);
11642 11642
11643 Action<Vector3, bool> handlerAutoPilotGo = OnAutoPilotGo; 11643 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo;
11644 if (handlerAutoPilotGo != null) 11644 if (handlerAutoPilotGo != null)
11645 handlerAutoPilotGo(new Vector3(locx, locy, locz), false); 11645 handlerAutoPilotGo(new Vector3(locx, locy, locz), false, false);
11646 } 11646 }
11647 11647
11648 /// <summary> 11648 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 9d8082b..eed7cd5 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -41,14 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
41 /// </summary> 41 /// </summary>
42 public class AgentAssetTransactions 42 public class AgentAssetTransactions
43 { 43 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 // Fields 46 // Fields
47 private bool m_dumpAssetsToFile; 47 private bool m_dumpAssetsToFile;
48 private Scene m_Scene; 48 private Scene m_Scene;
49 public UUID UserID; 49 private UUID UserID;
50 public Dictionary<UUID, AssetXferUploader> XferUploaders = 50 private Dictionary<UUID, AssetXferUploader> XferUploaders = new Dictionary<UUID, AssetXferUploader>();
51 new Dictionary<UUID, AssetXferUploader>();
52 51
53 // Methods 52 // Methods
54 public AgentAssetTransactions(UUID agentID, Scene scene, 53 public AgentAssetTransactions(UUID agentID, Scene scene,
@@ -59,36 +58,94 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
59 m_dumpAssetsToFile = dumpAssetsToFile; 58 m_dumpAssetsToFile = dumpAssetsToFile;
60 } 59 }
61 60
62 public AssetXferUploader RequestXferUploader(UUID transactionID) 61 /// <summary>
62 /// Return a xfer uploader if one does not already exist.
63 /// </summary>
64 /// <param name="transactionID"></param>
65 /// <param name="assetID">
66 /// We must transfer the new asset ID into the uploader on creation, otherwise
67 /// we can see race conditions with other threads which can retrieve an item before it is updated with the new
68 /// asset id.
69 /// </param>
70 /// <returns>
71 /// The xfer uploader requested. Null if one is already in existence.
72 /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
73 /// transfers are made. Needs to be corrected.
74 /// </returns>
75 public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
63 { 76 {
64 if (!XferUploaders.ContainsKey(transactionID)) 77 lock (XferUploaders)
65 { 78 {
66 AssetXferUploader uploader = new AssetXferUploader(m_Scene, 79 if (!XferUploaders.ContainsKey(transactionID))
67 m_dumpAssetsToFile);
68
69 lock (XferUploaders)
70 { 80 {
81 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile);
82
83// m_log.DebugFormat(
84// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
85
71 XferUploaders.Add(transactionID, uploader); 86 XferUploaders.Add(transactionID, uploader);
72 }
73 87
74 return uploader; 88 return uploader;
89 }
75 } 90 }
91
92 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID);
93
76 return null; 94 return null;
77 } 95 }
78 96
79 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 97 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
80 { 98 {
99 AssetXferUploader foundUploader = null;
100
81 lock (XferUploaders) 101 lock (XferUploaders)
82 { 102 {
83 foreach (AssetXferUploader uploader in XferUploaders.Values) 103 foreach (AssetXferUploader uploader in XferUploaders.Values)
84 { 104 {
105// m_log.DebugFormat(
106// "[AGENT ASSETS TRANSACTIONS]: In HandleXfer, inspect xfer upload with xfer id {0}",
107// uploader.XferID);
108
85 if (uploader.XferID == xferID) 109 if (uploader.XferID == xferID)
86 { 110 {
87 uploader.HandleXferPacket(xferID, packetID, data); 111 foundUploader = uploader;
88 break; 112 break;
89 } 113 }
90 } 114 }
91 } 115 }
116
117 if (foundUploader != null)
118 {
119// m_log.DebugFormat(
120// "[AGENT ASSETS TRANSACTIONS]: Found xfer uploader for xfer id {0}, packet id {1}, data length {2}",
121// xferID, packetID, data.Length);
122
123 foundUploader.HandleXferPacket(xferID, packetID, data);
124 }
125 else
126 {
127 m_log.ErrorFormat(
128 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
129 xferID, packetID, data.Length);
130 }
131 }
132
133 public bool RemoveXferUploader(UUID transactionID)
134 {
135 lock (XferUploaders)
136 {
137 bool removed = XferUploaders.Remove(transactionID);
138
139 if (!removed)
140 m_log.WarnFormat(
141 "[AGENT ASSET TRANSACTIONS]: Received request to remove xfer uploader with transaction ID {0} but none found",
142 transactionID);
143// else
144// m_log.DebugFormat(
145// "[AGENT ASSET TRANSACTIONS]: Removed xfer uploader with transaction ID {0}", transactionID);
146
147 return removed;
148 }
92 } 149 }
93 150
94 public void RequestCreateInventoryItem(IClientAPI remoteClient, 151 public void RequestCreateInventoryItem(IClientAPI remoteClient,
@@ -96,16 +153,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
96 string description, string name, sbyte invType, 153 string description, string name, sbyte invType,
97 sbyte type, byte wearableType, uint nextOwnerMask) 154 sbyte type, byte wearableType, uint nextOwnerMask)
98 { 155 {
99 if (XferUploaders.ContainsKey(transactionID)) 156 AssetXferUploader uploader = null;
157
158 lock (XferUploaders)
100 { 159 {
101 XferUploaders[transactionID].RequestCreateInventoryItem( 160 if (XferUploaders.ContainsKey(transactionID))
102 remoteClient, transactionID, folderID, 161 uploader = XferUploaders[transactionID];
103 callbackID, description, name, invType, type,
104 wearableType, nextOwnerMask);
105 } 162 }
106 }
107
108 163
164 if (uploader != null)
165 uploader.RequestCreateInventoryItem(
166 remoteClient, transactionID, folderID,
167 callbackID, description, name, invType, type,
168 wearableType, nextOwnerMask);
169 else
170 m_log.ErrorFormat(
171 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}",
172 transactionID, name, remoteClient.Name);
173 }
109 174
110 /// <summary> 175 /// <summary>
111 /// Get an uploaded asset. If the data is successfully retrieved, 176 /// Get an uploaded asset. If the data is successfully retrieved,
@@ -113,19 +178,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
113 /// </summary> 178 /// </summary>
114 /// <param name="transactionID"></param> 179 /// <param name="transactionID"></param>
115 /// <returns>The asset if the upload has completed, null if it has not.</returns> 180 /// <returns>The asset if the upload has completed, null if it has not.</returns>
116 public AssetBase GetTransactionAsset(UUID transactionID) 181 private AssetBase GetTransactionAsset(UUID transactionID)
117 { 182 {
118 if (XferUploaders.ContainsKey(transactionID)) 183 lock (XferUploaders)
119 { 184 {
120 AssetXferUploader uploader = XferUploaders[transactionID]; 185 if (XferUploaders.ContainsKey(transactionID))
121 AssetBase asset = uploader.GetAssetData();
122
123 lock (XferUploaders)
124 { 186 {
125 XferUploaders.Remove(transactionID); 187 AssetXferUploader uploader = XferUploaders[transactionID];
126 } 188 AssetBase asset = uploader.GetAssetData();
189 RemoveXferUploader(transactionID);
127 190
128 return asset; 191 return asset;
192 }
129 } 193 }
130 194
131 return null; 195 return null;
@@ -135,7 +199,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
135 SceneObjectPart part, UUID transactionID, 199 SceneObjectPart part, UUID transactionID,
136 TaskInventoryItem item) 200 TaskInventoryItem item)
137 { 201 {
138 if (XferUploaders.ContainsKey(transactionID)) 202 AssetXferUploader uploader = null;
203
204 lock (XferUploaders)
205 {
206 if (XferUploaders.ContainsKey(transactionID))
207 uploader = XferUploaders[transactionID];
208 }
209
210 if (uploader != null)
139 { 211 {
140 AssetBase asset = GetTransactionAsset(transactionID); 212 AssetBase asset = GetTransactionAsset(transactionID);
141 213
@@ -161,28 +233,34 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
161 m_Scene.AssetService.Store(asset); 233 m_Scene.AssetService.Store(asset);
162 } 234 }
163 } 235 }
236 else
237 {
238 m_log.ErrorFormat(
239 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
240 transactionID, item.Name, part.Name);
241 }
164 } 242 }
165 243
166 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 244 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
167 UUID transactionID, InventoryItemBase item) 245 UUID transactionID, InventoryItemBase item)
168 { 246 {
169 if (XferUploaders.ContainsKey(transactionID)) 247 AssetXferUploader uploader = null;
170 {
171 AssetBase asset = GetTransactionAsset(transactionID);
172 248
173 if (asset != null) 249 lock (XferUploaders)
174 { 250 {
175 asset.FullID = UUID.Random(); 251 if (XferUploaders.ContainsKey(transactionID))
176 asset.Name = item.Name; 252 uploader = XferUploaders[transactionID];
177 asset.Description = item.Description; 253 }
178 asset.Type = (sbyte)item.AssetType;
179 item.AssetID = asset.FullID;
180
181 m_Scene.AssetService.Store(asset);
182 254
183 IInventoryService invService = m_Scene.InventoryService; 255 if (uploader != null)
184 invService.UpdateItem(item); 256 {
185 } 257 uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
258 }
259 else
260 {
261 m_log.ErrorFormat(
262 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
263 transactionID, item.Name, remoteClient.Name);
186 } 264 }
187 } 265 }
188 } 266 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 82558de..a28d5d7 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -172,11 +172,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
172 /// <summary> 172 /// <summary>
173 /// Update an inventory item with data that has been received through a 173 /// Update an inventory item with data that has been received through a
174 /// transaction. 174 /// transaction.
175 /// 175 /// </summary>
176 /// <remarks>
176 /// This is called when clothing or body parts are updated (for 177 /// This is called when clothing or body parts are updated (for
177 /// instance, with new textures or colours). It may also be called in 178 /// instance, with new textures or colours). It may also be called in
178 /// other situations. 179 /// other situations.
179 /// </summary> 180 /// </remarks>
180 /// <param name="remoteClient"></param> 181 /// <param name="remoteClient"></param>
181 /// <param name="transactionID"></param> 182 /// <param name="transactionID"></param>
182 /// <param name="item"></param> 183 /// <param name="item"></param>
@@ -184,14 +185,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
184 UUID transactionID, InventoryItemBase item) 185 UUID transactionID, InventoryItemBase item)
185 { 186 {
186// m_log.DebugFormat( 187// m_log.DebugFormat(
187// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", 188// "[ASSET TRANSACTION MODULE]: Called HandleItemUpdateFromTransaction with item {0}",
188// item.Name); 189// item.Name);
189 190
190 AgentAssetTransactions transactions = 191 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
191 GetUserTransactions(remoteClient.AgentId);
192 192
193 transactions.RequestUpdateInventoryItem(remoteClient, 193 transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
194 transactionID, item);
195 } 194 }
196 195
197 /// <summary> 196 /// <summary>
@@ -255,11 +254,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
255 } 254 }
256 } 255 }
257 256
258 AgentAssetTransactions transactions = 257 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
259 GetUserTransactions(remoteClient.AgentId); 258 AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID);
260
261 AssetXferUploader uploader =
262 transactions.RequestXferUploader(transaction);
263 259
264 if (uploader != null) 260 if (uploader != null)
265 { 261 {
@@ -279,9 +275,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
279 public void HandleXfer(IClientAPI remoteClient, ulong xferID, 275 public void HandleXfer(IClientAPI remoteClient, ulong xferID,
280 uint packetID, byte[] data) 276 uint packetID, byte[] data)
281 { 277 {
282 //m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data!"); 278// m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data length " + data.Length);
283 AgentAssetTransactions transactions = 279 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
284 GetUserTransactions(remoteClient.AgentId);
285 280
286 transactions.HandleXfer(xferID, packetID, data); 281 transactions.HandleXfer(xferID, packetID, data);
287 } 282 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index a7929ba..ec4dfd0 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -40,11 +40,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40 { 40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 42
43 /// <summary>
44 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
45 /// are performing a delayed update.
46 /// </summary>
47 AgentAssetTransactions m_transactions;
48
43 private AssetBase m_asset; 49 private AssetBase m_asset;
44 private UUID InventFolder = UUID.Zero; 50 private UUID InventFolder = UUID.Zero;
45 private sbyte invType = 0; 51 private sbyte invType = 0;
52
46 private bool m_createItem = false; 53 private bool m_createItem = false;
47 private uint m_createItemCallback = 0; 54 private uint m_createItemCallback = 0;
55 private bool m_updateItem = false;
56 private InventoryItemBase m_updateItemData;
57
48 private string m_description = String.Empty; 58 private string m_description = String.Empty;
49 private bool m_dumpAssetToFile; 59 private bool m_dumpAssetToFile;
50 private bool m_finished = false; 60 private bool m_finished = false;
@@ -58,9 +68,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
58 public ulong XferID; 68 public ulong XferID;
59 private Scene m_Scene; 69 private Scene m_Scene;
60 70
61 public AssetXferUploader(Scene scene, bool dumpAssetToFile) 71 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile)
62 { 72 {
73 m_transactions = transactions;
63 m_Scene = scene; 74 m_Scene = scene;
75 m_asset = new AssetBase() { FullID = assetID };
64 m_dumpAssetToFile = dumpAssetToFile; 76 m_dumpAssetToFile = dumpAssetToFile;
65 } 77 }
66 78
@@ -73,6 +85,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
73 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> 85 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns>
74 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) 86 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
75 { 87 {
88// m_log.DebugFormat(
89// "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})",
90// packetID, xferID, data.Length);
91
76 if (XferID == xferID) 92 if (XferID == xferID)
77 { 93 {
78 if (m_asset.Data.Length > 1) 94 if (m_asset.Data.Length > 1)
@@ -107,16 +123,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
107 /// <param name="xferID"></param> 123 /// <param name="xferID"></param>
108 /// <param name="packetID"></param> 124 /// <param name="packetID"></param>
109 /// <param name="data"></param> 125 /// <param name="data"></param>
110 /// <returns>True if the transfer is complete, false otherwise</returns> 126 public void Initialise(IClientAPI remoteClient, UUID assetID,
111 public bool Initialise(IClientAPI remoteClient, UUID assetID,
112 UUID transaction, sbyte type, byte[] data, bool storeLocal, 127 UUID transaction, sbyte type, byte[] data, bool storeLocal,
113 bool tempFile) 128 bool tempFile)
114 { 129 {
130// m_log.DebugFormat(
131// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
132// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
133
115 ourClient = remoteClient; 134 ourClient = remoteClient;
116 m_asset = new AssetBase(assetID, "blank", type, 135 m_asset.Name = "blank";
117 remoteClient.AgentId.ToString());
118 m_asset.Data = data;
119 m_asset.Description = "empty"; 136 m_asset.Description = "empty";
137 m_asset.Type = type;
138 m_asset.CreatorID = remoteClient.AgentId.ToString();
139 m_asset.Data = data;
120 m_asset.Local = storeLocal; 140 m_asset.Local = storeLocal;
121 m_asset.Temporary = tempFile; 141 m_asset.Temporary = tempFile;
122 142
@@ -126,21 +146,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
126 if (m_asset.Data.Length > 2) 146 if (m_asset.Data.Length > 2)
127 { 147 {
128 SendCompleteMessage(); 148 SendCompleteMessage();
129 return true;
130 } 149 }
131 else 150 else
132 { 151 {
133 RequestStartXfer(); 152 RequestStartXfer();
134 } 153 }
135
136 return false;
137 } 154 }
138 155
139 protected void RequestStartXfer() 156 protected void RequestStartXfer()
140 { 157 {
141 XferID = Util.GetNextXferID(); 158 XferID = Util.GetNextXferID();
142 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 159
143 0, new byte[0]); 160// m_log.DebugFormat(
161// "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}",
162// m_asset.FullID, m_asset.Type, XferID, ourClient.Name);
163
164 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]);
144 } 165 }
145 166
146 protected void SendCompleteMessage() 167 protected void SendCompleteMessage()
@@ -148,18 +169,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
148 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, 169 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
149 m_asset.FullID); 170 m_asset.FullID);
150 171
151 m_finished = true; 172 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
152 if (m_createItem) 173 // message from other client UDP.
153 { 174 lock (this)
154 DoCreateItem(m_createItemCallback);
155 }
156 else if (m_storeLocal)
157 { 175 {
158 m_Scene.AssetService.Store(m_asset); 176 m_finished = true;
177 if (m_createItem)
178 {
179 DoCreateItem(m_createItemCallback);
180 }
181 else if (m_updateItem)
182 {
183 StoreAssetForItemUpdate(m_updateItemData);
184
185 // Remove ourselves from the list of transactions if completion was delayed until the transaction
186 // was complete.
187 // TODO: Should probably do the same for create item.
188 m_transactions.RemoveXferUploader(TransactionID);
189 }
190 else if (m_storeLocal)
191 {
192 m_Scene.AssetService.Store(m_asset);
193 }
159 } 194 }
160 195
161 m_log.DebugFormat( 196 m_log.DebugFormat(
162 "[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", 197 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
163 m_asset.FullID, TransactionID); 198 m_asset.FullID, TransactionID);
164 199
165 if (m_dumpAssetToFile) 200 if (m_dumpAssetToFile)
@@ -205,18 +240,66 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
205 m_asset.Description = description; 240 m_asset.Description = description;
206 m_asset.Type = type; 241 m_asset.Type = type;
207 242
243 // We must lock to avoid a race with a separate thread uploading the asset.
244 lock (this)
245 {
246 if (m_finished)
247 {
248 DoCreateItem(callbackID);
249 }
250 else
251 {
252 m_createItem = true; //set flag so the inventory item is created when upload is complete
253 m_createItemCallback = callbackID;
254 }
255 }
256 }
257 }
258
259 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item)
260 {
261 // We must lock to avoid a race with a separate thread uploading the asset.
262 lock (this)
263 {
264 m_asset.Name = item.Name;
265 m_asset.Description = item.Description;
266 m_asset.Type = (sbyte)item.AssetType;
267
268 // We must always store the item at this point even if the asset hasn't finished uploading, in order
269 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
270 // the AvatarAppearance structure.
271 item.AssetID = m_asset.FullID;
272 m_Scene.InventoryService.UpdateItem(item);
273
208 if (m_finished) 274 if (m_finished)
209 { 275 {
210 DoCreateItem(callbackID); 276 StoreAssetForItemUpdate(item);
211 } 277 }
212 else 278 else
213 { 279 {
214 m_createItem = true; //set flag so the inventory item is created when upload is complete 280// m_log.DebugFormat(
215 m_createItemCallback = callbackID; 281// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
282// item.Name, remoteClient.Name, transactionID);
283
284 m_updateItem = true;
285 m_updateItemData = item;
216 } 286 }
217 } 287 }
218 } 288 }
219 289
290 /// <summary>
291 /// Store the asset for the given item.
292 /// </summary>
293 /// <param name="item"></param>
294 private void StoreAssetForItemUpdate(InventoryItemBase item)
295 {
296// m_log.DebugFormat(
297// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
298// m_asset.FullID, item.Name, ourClient.Name);
299
300 m_Scene.AssetService.Store(m_asset);
301 }
302
220 private void DoCreateItem(uint callbackID) 303 private void DoCreateItem(uint callbackID)
221 { 304 {
222 m_Scene.AssetService.Store(m_asset); 305 m_Scene.AssetService.Store(m_asset);
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 996e2ab..b965d75 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -143,20 +143,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
143 143
144 public void SaveChangedAttachments(IScenePresence sp) 144 public void SaveChangedAttachments(IScenePresence sp)
145 { 145 {
146// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
147
146 foreach (SceneObjectGroup grp in sp.GetAttachments()) 148 foreach (SceneObjectGroup grp in sp.GetAttachments())
147 { 149 {
148 if (grp.HasGroupChanged) // Resizer scripts? 150// if (grp.HasGroupChanged) // Resizer scripts?
149 { 151// {
150 grp.IsAttachment = false; 152 grp.IsAttachment = false;
151 grp.AbsolutePosition = grp.RootPart.AttachedPos; 153 grp.AbsolutePosition = grp.RootPart.AttachedPos;
152 UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); 154 UpdateKnownItem(sp.ControllingClient, grp);
153 grp.IsAttachment = true; 155 grp.IsAttachment = true;
154 } 156// }
155 } 157 }
156 } 158 }
157 159
158 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 160 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
159 { 161 {
162// m_log.DebugFormat(
163// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
164// m_scene.RegionInfo.RegionName, sp.Name, silent);
165
160 foreach (SceneObjectGroup sop in sp.GetAttachments()) 166 foreach (SceneObjectGroup sop in sp.GetAttachments())
161 { 167 {
162 sop.Scene.DeleteSceneObject(sop, silent); 168 sop.Scene.DeleteSceneObject(sop, silent);
@@ -212,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
212 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); 218 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
213 219
214 // Save avatar attachment information 220 // Save avatar attachment information
215 m_log.Info( 221 m_log.Debug(
216 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 222 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
217 + ", AttachmentPoint: " + AttachmentPt); 223 + ", AttachmentPoint: " + AttachmentPt);
218 224
@@ -240,80 +246,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
240 246
241 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) 247 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
242 { 248 {
243// m_log.DebugFormat( 249 lock (sp.AttachmentsSyncLock)
244// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
245// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
246
247 if (sp.GetAttachments(attachmentPt).Contains(group))
248 {
249// m_log.WarnFormat(
250// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
251// group.Name, group.LocalId, sp.Name, AttachmentPt);
252
253 return false;
254 }
255
256 Vector3 attachPos = group.AbsolutePosition;
257
258 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
259 // be removed when that functionality is implemented in opensim
260 attachmentPt &= 0x7f;
261
262 // If the attachment point isn't the same as the one previously used
263 // set it's offset position = 0 so that it appears on the attachment point
264 // and not in a weird location somewhere unknown.
265 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
266 {
267 attachPos = Vector3.Zero;
268 }
269
270 // AttachmentPt 0 means the client chose to 'wear' the attachment.
271 if (attachmentPt == 0)
272 {
273 // Check object for stored attachment point
274 attachmentPt = group.AttachmentPoint;
275 }
276
277 // if we still didn't find a suitable attachment point.......
278 if (attachmentPt == 0)
279 {
280 // Stick it on left hand with Zero Offset from the attachment point.
281 attachmentPt = (uint)AttachmentPoint.LeftHand;
282 attachPos = Vector3.Zero;
283 }
284
285 group.AttachmentPoint = attachmentPt;
286 group.AbsolutePosition = attachPos;
287
288 // We also don't want to do any of the inventory operations for an NPC.
289 if (sp.PresenceType != PresenceType.Npc)
290 { 250 {
291 // Remove any previous attachments 251// m_log.DebugFormat(
292 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 252// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
293 253// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
294 // At the moment we can only deal with a single attachment 254
295 if (attachments.Count != 0) 255 if (sp.GetAttachments(attachmentPt).Contains(group))
296 { 256 {
297 UUID oldAttachmentItemID = attachments[0].GetFromItemID(); 257 // m_log.WarnFormat(
258 // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
259 // group.Name, group.LocalId, sp.Name, AttachmentPt);
298 260
299 if (oldAttachmentItemID != UUID.Zero) 261 return false;
300 DetachSingleAttachmentToInv(oldAttachmentItemID, sp);
301 else
302 m_log.WarnFormat(
303 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
304 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
305 } 262 }
306
307 // Add the new attachment to inventory if we don't already have it.
308 UUID newAttachmentItemID = group.GetFromItemID();
309 if (newAttachmentItemID == UUID.Zero)
310 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID;
311 263
312 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 264 Vector3 attachPos = group.AbsolutePosition;
265
266 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
267 // be removed when that functionality is implemented in opensim
268 attachmentPt &= 0x7f;
269
270 // If the attachment point isn't the same as the one previously used
271 // set it's offset position = 0 so that it appears on the attachment point
272 // and not in a weird location somewhere unknown.
273 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
274 {
275 attachPos = Vector3.Zero;
276 }
277
278 // AttachmentPt 0 means the client chose to 'wear' the attachment.
279 if (attachmentPt == 0)
280 {
281 // Check object for stored attachment point
282 attachmentPt = group.AttachmentPoint;
283 }
284
285 // if we still didn't find a suitable attachment point.......
286 if (attachmentPt == 0)
287 {
288 // Stick it on left hand with Zero Offset from the attachment point.
289 attachmentPt = (uint)AttachmentPoint.LeftHand;
290 attachPos = Vector3.Zero;
291 }
292
293 group.AttachmentPoint = attachmentPt;
294 group.AbsolutePosition = attachPos;
295
296 // We also don't want to do any of the inventory operations for an NPC.
297 if (sp.PresenceType != PresenceType.Npc)
298 {
299 // Remove any previous attachments
300 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
301
302 // At the moment we can only deal with a single attachment
303 if (attachments.Count != 0)
304 {
305 UUID oldAttachmentItemID = attachments[0].GetFromItemID();
306
307 if (oldAttachmentItemID != UUID.Zero)
308 DetachSingleAttachmentToInv(oldAttachmentItemID, sp);
309 else
310 m_log.WarnFormat(
311 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
312 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
313 }
314
315 // Add the new attachment to inventory if we don't already have it.
316 UUID newAttachmentItemID = group.GetFromItemID();
317 if (newAttachmentItemID == UUID.Zero)
318 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID;
319
320 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
321 }
322
323 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
313 } 324 }
314 325
315 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
316
317 return true; 326 return true;
318 } 327 }
319 328
@@ -322,17 +331,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
322 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, 331 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header,
323 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) 332 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects)
324 { 333 {
325 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) 334 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
335
336 if (sp == null)
326 { 337 {
327 RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); 338 m_log.ErrorFormat(
339 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
340 remoteClient.Name, remoteClient.AgentId);
341 return;
342 }
343
344 lock (sp.AttachmentsSyncLock)
345 {
346// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
347
348 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects)
349 {
350 RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt);
351 }
328 } 352 }
329 } 353 }
330 354
331 public ISceneEntity RezSingleAttachmentFromInventory( 355 public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
332 IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
333 { 356 {
334// m_log.DebugFormat( 357// m_log.DebugFormat(
335// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", 358// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
336// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); 359// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
337 360
338 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 361 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
@@ -344,11 +367,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
344 remoteClient.Name, remoteClient.AgentId); 367 remoteClient.Name, remoteClient.AgentId);
345 return null; 368 return null;
346 } 369 }
347 370
371 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
372 }
373
374 public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt)
375 {
376// m_log.DebugFormat(
377// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
378// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
379
348 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 380 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
349 // be removed when that functionality is implemented in opensim 381 // be removed when that functionality is implemented in opensim
350 AttachmentPt &= 0x7f; 382 AttachmentPt &= 0x7f;
351 383
384 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
385 // This often happens during login - not sure the exact reason.
386 // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the
387 // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login
388 // before anything has actually been attached.
389 bool alreadyOn = false;
390 List<SceneObjectGroup> existingAttachments = sp.GetAttachments();
391 foreach (SceneObjectGroup so in existingAttachments)
392 {
393 if (so.GetFromItemID() == itemID)
394 {
395 alreadyOn = true;
396 break;
397 }
398 }
399
400// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
401 if (alreadyOn)
402 {
403// m_log.WarnFormat(
404// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
405// sp.Name, itemID, AttachmentPt);
406
407 return null;
408 }
409
352 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); 410 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt);
353 411
354 if (att == null) 412 if (att == null)
@@ -363,65 +421,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
363 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 421 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
364 if (invAccess != null) 422 if (invAccess != null)
365 { 423 {
366 SceneObjectGroup objatt; 424 lock (sp.AttachmentsSyncLock)
367
368 if (itemID != UUID.Zero)
369 objatt = invAccess.RezObject(sp.ControllingClient,
370 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
371 false, false, sp.UUID, true);
372 else
373 objatt = invAccess.RezObject(sp.ControllingClient,
374 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
375 false, false, sp.UUID, true);
376
377// m_log.DebugFormat(
378// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
379// objatt.Name, remoteClient.Name, AttachmentPt);
380
381 if (objatt != null)
382 { 425 {
383 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 426 SceneObjectGroup objatt;
384 objatt.HasGroupChanged = false; 427
385 bool tainted = false; 428 if (itemID != UUID.Zero)
386 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) 429 objatt = invAccess.RezObject(sp.ControllingClient,
387 tainted = true; 430 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
388 431 false, false, sp.UUID, true);
389 // This will throw if the attachment fails 432 else
390 try 433 objatt = invAccess.RezObject(sp.ControllingClient,
434 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
435 false, false, sp.UUID, true);
436
437 // m_log.DebugFormat(
438 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
439 // objatt.Name, remoteClient.Name, AttachmentPt);
440
441 if (objatt != null)
391 { 442 {
392 AttachObject(sp, objatt, attachmentPt, false); 443 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
444 objatt.HasGroupChanged = false;
445 bool tainted = false;
446 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
447 tainted = true;
448
449 // This will throw if the attachment fails
450 try
451 {
452 AttachObject(sp, objatt, attachmentPt, false);
453 }
454 catch (Exception e)
455 {
456 m_log.ErrorFormat(
457 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
458 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
459
460 // Make sure the object doesn't stick around and bail
461 sp.RemoveAttachment(objatt);
462 m_scene.DeleteSceneObject(objatt, false);
463 return null;
464 }
465
466 if (tainted)
467 objatt.HasGroupChanged = true;
468
469 // Fire after attach, so we don't get messy perms dialogs
470 // 4 == AttachedRez
471 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
472 objatt.ResumeScripts();
473
474 // Do this last so that event listeners have access to all the effects of the attachment
475 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
476
477 return objatt;
393 } 478 }
394 catch (Exception e) 479 else
395 { 480 {
396 m_log.ErrorFormat( 481 m_log.WarnFormat(
397 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", 482 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
398 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); 483 itemID, sp.Name, attachmentPt);
399
400 // Make sure the object doesn't stick around and bail
401 sp.RemoveAttachment(objatt);
402 m_scene.DeleteSceneObject(objatt, false);
403 return null;
404 } 484 }
405
406 if (tainted)
407 objatt.HasGroupChanged = true;
408
409 // Fire after attach, so we don't get messy perms dialogs
410 // 4 == AttachedRez
411 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
412 objatt.ResumeScripts();
413
414 // Do this last so that event listeners have access to all the effects of the attachment
415 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
416 }
417 else
418 {
419 m_log.WarnFormat(
420 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
421 itemID, sp.Name, attachmentPt);
422 } 485 }
423
424 return objatt;
425 } 486 }
426 487
427 return null; 488 return null;
@@ -438,8 +499,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
438 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 499 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
439 { 500 {
440// m_log.DebugFormat( 501// m_log.DebugFormat(
441// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 502// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
442// att.Name, remoteClient.Name, AttachmentPt, itemID); 503// att.Name, sp.Name, AttachmentPt, itemID);
443 504
444 if (UUID.Zero == itemID) 505 if (UUID.Zero == itemID)
445 { 506 {
@@ -462,6 +523,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
462 523
463 public void DetachObject(uint objectLocalID, IClientAPI remoteClient) 524 public void DetachObject(uint objectLocalID, IClientAPI remoteClient)
464 { 525 {
526// m_log.DebugFormat(
527// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name);
528
465 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 529 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
466 if (group != null) 530 if (group != null)
467 { 531 {
@@ -474,14 +538,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
474 ScenePresence presence; 538 ScenePresence presence;
475 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 539 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
476 { 540 {
477 // Save avatar attachment information 541 lock (presence.AttachmentsSyncLock)
478 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); 542 {
479 543 // Save avatar attachment information
480 bool changed = presence.Appearance.DetachAttachment(itemID); 544 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
481 if (changed && m_scene.AvatarFactory != null)
482 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
483 545
484 DetachSingleAttachmentToInv(itemID, presence); 546 bool changed = presence.Appearance.DetachAttachment(itemID);
547 if (changed && m_scene.AvatarFactory != null)
548 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
549
550 DetachSingleAttachmentToInv(itemID, presence);
551 }
485 } 552 }
486 } 553 }
487 554
@@ -489,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
489 { 556 {
490// m_log.DebugFormat( 557// m_log.DebugFormat(
491// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", 558// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
492// remoteClient.Name, sceneObjectID); 559// remoteClient.Name, soLocalId);
493 560
494 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); 561 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
495 562
@@ -508,24 +575,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
508 ScenePresence presence; 575 ScenePresence presence;
509 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 576 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
510 { 577 {
511 if (!m_scene.Permissions.CanRezObject( 578 lock (presence.AttachmentsSyncLock)
512 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) 579 {
513 return; 580 if (!m_scene.Permissions.CanRezObject(
581 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
582 return;
514 583
515 bool changed = presence.Appearance.DetachAttachment(inventoryID); 584 bool changed = presence.Appearance.DetachAttachment(inventoryID);
516 if (changed && m_scene.AvatarFactory != null) 585 if (changed && m_scene.AvatarFactory != null)
517 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); 586 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
518 587
519 presence.RemoveAttachment(so); 588 presence.RemoveAttachment(so);
520 DetachSceneObjectToGround(so, presence); 589 DetachSceneObjectToGround(so, presence);
521 590
522 List<UUID> uuids = new List<UUID>(); 591 List<UUID> uuids = new List<UUID>();
523 uuids.Add(inventoryID); 592 uuids.Add(inventoryID);
524 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); 593 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
525 remoteClient.SendRemoveInventoryItem(inventoryID); 594 remoteClient.SendRemoveInventoryItem(inventoryID);
526 } 595 }
527 596
528 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 597 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
598 }
529 } 599 }
530 600
531 /// <summary> 601 /// <summary>
@@ -559,6 +629,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
559 // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? 629 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
560 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) 630 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp)
561 { 631 {
632// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
633
562 if (itemID == UUID.Zero) // If this happened, someone made a mistake.... 634 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
563 return; 635 return;
564 636
@@ -567,37 +639,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
567 EntityBase[] detachEntities = m_scene.GetEntities(); 639 EntityBase[] detachEntities = m_scene.GetEntities();
568 SceneObjectGroup group; 640 SceneObjectGroup group;
569 641
570 foreach (EntityBase entity in detachEntities) 642 lock (sp.AttachmentsSyncLock)
571 { 643 {
572 if (entity is SceneObjectGroup) 644 foreach (EntityBase entity in detachEntities)
573 { 645 {
574 group = (SceneObjectGroup)entity; 646 if (entity is SceneObjectGroup)
575 if (group.GetFromItemID() == itemID)
576 { 647 {
577 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); 648 group = (SceneObjectGroup)entity;
578 sp.RemoveAttachment(group); 649 if (group.GetFromItemID() == itemID)
579 650 {
580 // Prepare sog for storage 651 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
581 group.AttachedAvatar = UUID.Zero; 652 sp.RemoveAttachment(group);
582 653
583 group.ForEachPart( 654 // Prepare sog for storage
584 delegate(SceneObjectPart part) 655 group.AttachedAvatar = UUID.Zero;
585 { 656 group.RootPart.SetParentLocalId(0);
586 // If there are any scripts, 657 group.IsAttachment = false;
587 // then always trigger a new object and state persistence in UpdateKnownItem() 658 group.AbsolutePosition = group.RootPart.AttachedPos;
588 if (part.Inventory.ContainsScripts()) 659
589 group.HasGroupChanged = true; 660 UpdateKnownItem(sp.ControllingClient, group);
590 } 661 m_scene.DeleteSceneObject(group, false);
591 ); 662
592 663 return;
593 group.RootPart.SetParentLocalId(0); 664 }
594 group.IsAttachment = false;
595 group.AbsolutePosition = group.RootPart.AttachedPos;
596
597 UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID);
598 m_scene.DeleteSceneObject(group, false);
599
600 return;
601 } 665 }
602 } 666 }
603 } 667 }
@@ -628,28 +692,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
628 /// </remarks> 692 /// </remarks>
629 /// <param name="remoteClient"></param> 693 /// <param name="remoteClient"></param>
630 /// <param name="grp"></param> 694 /// <param name="grp"></param>
631 /// <param name="itemID"></param> 695 private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp)
632 /// <param name="agentID"></param>
633 public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
634 { 696 {
635 if (grp != null) 697 if (grp.HasGroupChanged || grp.ContainsScripts())
636 { 698 {
637 if (!grp.HasGroupChanged)
638 {
639 m_log.DebugFormat(
640 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
641 grp.UUID, grp.AttachmentPoint);
642
643 return;
644 }
645
646 m_log.DebugFormat( 699 m_log.DebugFormat(
647 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 700 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
648 grp.UUID, grp.AttachmentPoint); 701 grp.UUID, grp.AttachmentPoint);
649 702
650 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 703 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
651 704
652 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 705 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId);
653 item = m_scene.InventoryService.GetItem(item); 706 item = m_scene.InventoryService.GetItem(item);
654 707
655 if (item != null) 708 if (item != null)
@@ -675,6 +728,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
675 remoteClient.SendInventoryItemCreateUpdate(item, 0); 728 remoteClient.SendInventoryItemCreateUpdate(item, 0);
676 } 729 }
677 } 730 }
731 else
732 {
733 m_log.DebugFormat(
734 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
735 grp.UUID, grp.AttachmentPoint);
736 }
678 } 737 }
679 738
680 /// <summary> 739 /// <summary>
@@ -692,7 +751,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
692 private void AttachToAgent( 751 private void AttachToAgent(
693 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 752 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
694 { 753 {
695// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 754// m_log.DebugFormat(
755// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
696// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 756// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
697 757
698 so.DetachFromBackup(); 758 so.DetachFromBackup();
@@ -745,7 +805,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 /// <returns>The user inventory item created that holds the attachment.</returns> 805 /// <returns>The user inventory item created that holds the attachment.</returns>
746 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) 806 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp)
747 { 807 {
748// m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); 808// m_log.DebugFormat(
809// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
810// grp.Name, grp.LocalId, remoteClient.Name);
749 811
750 Vector3 inventoryStoredPosition = new Vector3 812 Vector3 inventoryStoredPosition = new Vector3
751 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 813 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
@@ -829,4 +891,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
829 return item; 891 return item;
830 } 892 }
831 } 893 }
832} 894} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 35183b3..ff3358f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -220,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
220 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); 220 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0));
221 } 221 }
222 222
223 /// <summary>
224 /// Test that attachments don't hang about in the scene when the agent is closed
225 /// </summary>
226 [Test]
227 public void TestRemoveAttachmentsOnAvatarExit()
228 {
229 TestHelpers.InMethod();
230// log4net.Config.XmlConfigurator.Configure();
231
232 UUID userId = TestHelpers.ParseTail(0x1);
233 UUID attItemId = TestHelpers.ParseTail(0x2);
234 UUID attAssetId = TestHelpers.ParseTail(0x3);
235 string attName = "att";
236
237 UserAccountHelpers.CreateUserWithInventory(scene, userId);
238 InventoryItemBase attItem
239 = UserInventoryHelpers.CreateInventoryItem(
240 scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
241
242 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
243 acd.Appearance = new AvatarAppearance();
244 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
245 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
246
247 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
248
249 scene.IncomingCloseAgent(presence.UUID);
250
251 // Check that we can't retrieve this attachment from the scene.
252 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
253 }
254
223 [Test] 255 [Test]
224 public void TestRezAttachmentsOnAvatarEntrance() 256 public void TestRezAttachmentsOnAvatarEntrance()
225 { 257 {
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index b6a1564..0cadd83 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -211,8 +211,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
211 // Process the visual params, this may change height as well 211 // Process the visual params, this may change height as well
212 if (visualParams != null) 212 if (visualParams != null)
213 { 213 {
214// string[] visualParamsStrings = new string[visualParams.Length];
215// for (int i = 0; i < visualParams.Length; i++)
216// visualParamsStrings[i] = visualParams[i].ToString();
217// m_log.DebugFormat(
218// "[AVFACTORY]: Setting visual params for {0} to {1}",
219// client.Name, string.Join(", ", visualParamsStrings));
220
221 float oldHeight = sp.Appearance.AvatarHeight;
214 changed = sp.Appearance.SetVisualParams(visualParams); 222 changed = sp.Appearance.SetVisualParams(visualParams);
215 if (sp.Appearance.AvatarHeight > 0) 223
224 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
216 sp.SetHeight(sp.Appearance.AvatarHeight); 225 sp.SetHeight(sp.Appearance.AvatarHeight);
217 } 226 }
218 227
@@ -416,6 +425,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
416 425
417 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); 426 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
418 427
428 // This could take awhile since it needs to pull inventory
429 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
430 // assets and item asset id changes to complete.
431 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
432 // multiple save requests.
433 SetAppearanceAssets(sp.UUID, sp.Appearance);
434
419 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 435 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
420 } 436 }
421 437
@@ -467,7 +483,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
467 return; 483 return;
468 } 484 }
469 485
470 // m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId); 486// m_log.DebugFormat("[AVFACTORY]: Received request for wearables of {0}", client.Name);
471 487
472 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); 488 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
473 } 489 }
@@ -502,9 +518,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
502 518
503 avatAppearance.GetAssetsFrom(sp.Appearance); 519 avatAppearance.GetAssetsFrom(sp.Appearance);
504 520
505 // This could take awhile since it needs to pull inventory
506 SetAppearanceAssets(sp.UUID, ref avatAppearance);
507
508 lock (m_setAppearanceLock) 521 lock (m_setAppearanceLock)
509 { 522 {
510 // Update only those fields that we have changed. This is important because the viewer 523 // Update only those fields that we have changed. This is important because the viewer
@@ -538,7 +551,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
538 return true; 551 return true;
539 } 552 }
540 553
541 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) 554 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
542 { 555 {
543 IInventoryService invService = m_scene.InventoryService; 556 IInventoryService invService = m_scene.InventoryService;
544 557
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index 7753c25..d294692 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -24,6 +24,7 @@
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; 29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
@@ -145,14 +146,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
145 scene.Entities[toAgentID] is ScenePresence) 146 scene.Entities[toAgentID] is ScenePresence)
146 { 147 {
147// m_log.DebugFormat( 148// m_log.DebugFormat(
148// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", 149// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
149// toAgentID.ToString(), scene.RegionInfo.RegionName); 150// toAgentID.ToString(), scene.RegionInfo.RegionName);
150 151
151 ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; 152 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
152 if (!user.IsChildAgent) 153 if (!user.IsChildAgent)
153 { 154 {
154 // Local message 155 // Local message
155// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); 156// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
156 user.ControllingClient.SendInstantMessage(im); 157 user.ControllingClient.SendInstantMessage(im);
157 158
158 // Message sent 159 // Message sent
@@ -166,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
166 foreach (Scene scene in m_Scenes) 167 foreach (Scene scene in m_Scenes)
167 { 168 {
168// m_log.DebugFormat( 169// m_log.DebugFormat(
169// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 170// "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
170 171
171 if (scene.Entities.ContainsKey(toAgentID) && 172 if (scene.Entities.ContainsKey(toAgentID) &&
172 scene.Entities[toAgentID] is ScenePresence) 173 scene.Entities[toAgentID] is ScenePresence)
@@ -174,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
174 // Local message 175 // Local message
175 ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; 176 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
176 177
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); 178// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
178 user.ControllingClient.SendInstantMessage(im); 179 user.ControllingClient.SendInstantMessage(im);
179 180
180 // Message sent 181 // Message sent
@@ -183,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
183 } 184 }
184 } 185 }
185 186
186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 187// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 // Is the user a local user? 188 // Is the user a local user?
188 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); 189 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID);
189 string url = string.Empty; 190 string url = string.Empty;
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index d687e6a..bc5c1ff 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -154,14 +154,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
154 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) 154 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport)
155 { 155 {
156 UUID sessionID = new UUID(im.imSessionID); 156 UUID sessionID = new UUID(im.imSessionID);
157 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); 157
158 m_PendingLures.Add(sessionID, im, 7200); // 2 hours 158 if (!m_PendingLures.Contains(sessionID))
159 {
160 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message);
161 m_PendingLures.Add(sessionID, im, 7200); // 2 hours
162 }
159 163
160 // Forward. We do this, because the IM module explicitly rejects 164 // Forward. We do this, because the IM module explicitly rejects
161 // IMs of this type 165 // IMs of this type
162 if (m_TransferModule != null) 166 if (m_TransferModule != null)
163 m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); 167 m_TransferModule.SendInstantMessage(im, delegate(bool success) { });
164
165 } 168 }
166 } 169 }
167 170
@@ -177,12 +180,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
177 180
178 m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); 181 m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message);
179 182
183 UUID sessionID = UUID.Random();
184
180 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, 185 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
181 client.FirstName+" "+client.LastName, targetid, 186 client.FirstName+" "+client.LastName, targetid,
182 (byte)InstantMessageDialog.RequestTeleport, false, 187 (byte)InstantMessageDialog.RequestTeleport, false,
183 message, UUID.Random(), false, presence.AbsolutePosition, 188 message, sessionID, false, presence.AbsolutePosition,
184 new Byte[0]); 189 new Byte[0]);
185 m.RegionID = client.Scene.RegionInfo.RegionID.Guid; 190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
191
192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
193 m_PendingLures.Add(sessionID, m, 7200); // 2 hours
186 194
187 if (m_TransferModule != null) 195 if (m_TransferModule != null)
188 { 196 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ac13d5e..8924c0a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -59,7 +59,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
59 get { return m_MaxTransferDistance; } 59 get { return m_MaxTransferDistance; }
60 set { m_MaxTransferDistance = value; } 60 set { m_MaxTransferDistance = value; }
61 } 61 }
62
63 62
64 protected bool m_Enabled = false; 63 protected bool m_Enabled = false;
65 protected Scene m_aScene; 64 protected Scene m_aScene;
@@ -68,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
68 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = 67 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
69 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 68 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
70 69
71
72 #region ISharedRegionModule 70 #region ISharedRegionModule
73 71
74 public Type ReplaceableInterface 72 public Type ReplaceableInterface
@@ -329,6 +327,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
329 if (sp.ParentID != (uint)0) 327 if (sp.ParentID != (uint)0)
330 sp.StandUp(); 328 sp.StandUp();
331 329
330 if (!sp.ValidateAttachments())
331 m_log.DebugFormat(
332 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
333 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
334
332// if (!sp.ValidateAttachments()) 335// if (!sp.ValidateAttachments())
333// { 336// {
334// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); 337// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
@@ -939,7 +942,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
939 /// This Closes child agents on neighbouring regions 942 /// This Closes child agents on neighbouring regions
940 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 943 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
941 /// </summary> 944 /// </summary>
942 protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) 945 protected ScenePresence CrossAgentToNewRegionAsync(
946 ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion,
947 bool isFlying, string version)
943 { 948 {
944 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); 949 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
945 950
@@ -949,7 +954,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
949 954
950 if (neighbourRegion != null) 955 if (neighbourRegion != null)
951 { 956 {
952 agent.ValidateAttachments(); 957 if (!agent.ValidateAttachments())
958 m_log.DebugFormat(
959 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
960 agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
953 961
954 pos = pos + (agent.Velocity); 962 pos = pos + (agent.Velocity);
955 963
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index f7003db..bef0d69 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -363,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
363 lock (m_UserCache) 363 lock (m_UserCache)
364 m_UserCache[user.Id] = user; 364 m_UserCache[user.Id] = user;
365 365
366 m_log.DebugFormat( 366// m_log.DebugFormat(
367 "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", 367// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
368 user.Id, user.FirstName, user.LastName, user.HomeURL); 368// user.Id, user.FirstName, user.LastName, user.HomeURL);
369 } 369 }
370 370
371 //public void AddUser(UUID uuid, string userData) 371 //public void AddUser(UUID uuid, string userData)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index 1c83f8e..097ff1a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -185,15 +185,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
185 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 185 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
186 { 186 {
187 InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); 187 InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID);
188 Util.FireAndForget(delegate 188
189 if (UserManager != null)
189 { 190 {
190 if (UserManager != null) 191 // Protect ourselves against the caller subsequently modifying the items list
192 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
193
194 Util.FireAndForget(delegate
191 { 195 {
192 // Protect ourselves against the caller subsequently modifying the items list 196 foreach (InventoryItemBase item in items)
193 foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
194 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 197 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
195 } 198 });
196 }); 199 }
197 200
198 return invCol; 201 return invCol;
199 } 202 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index c9c716c..73ab4e3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -193,15 +193,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
193 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 193 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
194 { 194 {
195 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); 195 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
196 Util.FireAndForget(delegate 196
197 if (UserManager != null)
197 { 198 {
198 if (UserManager != null) 199 // Protect ourselves against the caller subsequently modifying the items list
200 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
201
202 Util.FireAndForget(delegate
199 { 203 {
200 // Protect ourselves against the caller subsequently modifying the items list 204 foreach (InventoryItemBase item in items)
201 foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
202 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 205 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
203 } 206 });
204 }); 207 }
205 208
206 return invCol; 209 return invCol;
207 } 210 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 30ebb21..0a0ce3c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -45,7 +45,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
45 LogManager.GetLogger( 45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private IUserAccountService m_UserService; 48 /// <summary>
49 /// This is not on the IUserAccountService. It's only being used so that standalone scenes can punch through
50 /// to a local UserAccountService when setting up an estate manager.
51 /// </summary>
52 public IUserAccountService UserAccountService { get; private set; }
53
49 private UserAccountCache m_Cache; 54 private UserAccountCache m_Cache;
50 55
51 private bool m_Enabled = false; 56 private bool m_Enabled = false;
@@ -86,9 +91,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
86 } 91 }
87 92
88 Object[] args = new Object[] { source }; 93 Object[] args = new Object[] { source };
89 m_UserService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args); 94 UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args);
90 95
91 if (m_UserService == null) 96 if (UserAccountService == null)
92 { 97 {
93 m_log.ErrorFormat( 98 m_log.ErrorFormat(
94 "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll); 99 "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll);
@@ -119,7 +124,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
119 if (!m_Enabled) 124 if (!m_Enabled)
120 return; 125 return;
121 126
122 scene.RegisterModuleInterface<IUserAccountService>(m_UserService); 127 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner
128 // user account service?!
129 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService);
123 } 130 }
124 131
125 public void RemoveRegion(Scene scene) 132 public void RemoveRegion(Scene scene)
@@ -147,7 +154,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
147 if (inCache) 154 if (inCache)
148 return account; 155 return account;
149 156
150 account = m_UserService.GetUserAccount(scopeID, userID); 157 account = UserAccountService.GetUserAccount(scopeID, userID);
151 m_Cache.Cache(userID, account); 158 m_Cache.Cache(userID, account);
152 159
153 return account; 160 return account;
@@ -160,7 +167,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
160 if (inCache) 167 if (inCache)
161 return account; 168 return account;
162 169
163 account = m_UserService.GetUserAccount(scopeID, firstName, lastName); 170 account = UserAccountService.GetUserAccount(scopeID, firstName, lastName);
164 if (account != null) 171 if (account != null)
165 m_Cache.Cache(account.PrincipalID, account); 172 m_Cache.Cache(account.PrincipalID, account);
166 173
@@ -169,22 +176,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
169 176
170 public UserAccount GetUserAccount(UUID scopeID, string Email) 177 public UserAccount GetUserAccount(UUID scopeID, string Email)
171 { 178 {
172 return m_UserService.GetUserAccount(scopeID, Email); 179 return UserAccountService.GetUserAccount(scopeID, Email);
173 } 180 }
174 181
175 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 182 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
176 { 183 {
177 return m_UserService.GetUserAccounts(scopeID, query); 184 return UserAccountService.GetUserAccounts(scopeID, query);
178 } 185 }
179 186
180 // Update all updatable fields 187 // Update all updatable fields
181 // 188 //
182 public bool StoreUserAccount(UserAccount data) 189 public bool StoreUserAccount(UserAccount data)
183 { 190 {
184 return m_UserService.StoreUserAccount(data); 191 return UserAccountService.StoreUserAccount(data);
185 } 192 }
186 193
187 #endregion 194 #endregion
188
189 } 195 }
190} 196} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 48130e7..587d260 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -284,8 +284,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
284 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 284 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
285 285
286 // And zap any troublesome sit target information 286 // And zap any troublesome sit target information
287 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 287// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
288 part.SitTargetPosition = new Vector3(0, 0, 0); 288// part.SitTargetPosition = new Vector3(0, 0, 0);
289 289
290 // Fix ownership/creator of inventory items 290 // Fix ownership/creator of inventory items
291 // Not doing so results in inventory items 291 // Not doing so results in inventory items
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
index 10a83ee..b895afe 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -127,6 +127,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
127 127
128 EntityBase[] entities = m_scene.GetEntities(); 128 EntityBase[] entities = m_scene.GetEntities();
129 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 129 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
130
131 string checkPermissions = null;
132 int numObjectsSkippedPermissions = 0;
133 Object temp;
134 if (options.TryGetValue("checkPermissions", out temp))
135 checkPermissions = (string)temp;
130 136
131 // Filter entities so that we only have scene objects. 137 // Filter entities so that we only have scene objects.
132 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods 138 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
@@ -136,9 +142,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
136 if (entity is SceneObjectGroup) 142 if (entity is SceneObjectGroup)
137 { 143 {
138 SceneObjectGroup sceneObject = (SceneObjectGroup)entity; 144 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
139 145
140 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) 146 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
141 sceneObjects.Add((SceneObjectGroup)entity); 147 {
148 if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
149 {
150 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
151 ++numObjectsSkippedPermissions;
152 }
153 else
154 {
155 sceneObjects.Add(sceneObject);
156 }
157 }
142 } 158 }
143 } 159 }
144 160
@@ -159,7 +175,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
159 { 175 {
160 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); 176 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
161 } 177 }
162 178
179 if (numObjectsSkippedPermissions > 0)
180 {
181 m_log.DebugFormat(
182 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
183 numObjectsSkippedPermissions);
184 }
185
163 // Make sure that we also request terrain texture assets 186 // Make sure that we also request terrain texture assets
164 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; 187 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
165 188
@@ -211,6 +234,83 @@ namespace OpenSim.Region.CoreModules.World.Archiver
211 } 234 }
212 235
213 /// <summary> 236 /// <summary>
237 /// Checks whether the user has permission to export an object group to an OAR.
238 /// </summary>
239 /// <param name="user">The user</param>
240 /// <param name="objGroup">The object group</param>
241 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
242 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
243 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
244 {
245 if (checkPermissions == null)
246 return true;
247
248 IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
249 if (module == null)
250 return true; // this shouldn't happen
251
252 // Check whether the user is permitted to export all of the parts in the SOG. If any
253 // part can't be exported then the entire SOG can't be exported.
254
255 bool permitted = true;
256 //int primNumber = 1;
257
258 foreach (SceneObjectPart obj in objGroup.Parts)
259 {
260 uint perm;
261 PermissionClass permissionClass = module.GetPermissionClass(user, obj);
262 switch (permissionClass)
263 {
264 case PermissionClass.Owner:
265 perm = obj.BaseMask;
266 break;
267 case PermissionClass.Group:
268 perm = obj.GroupMask | obj.EveryoneMask;
269 break;
270 case PermissionClass.Everyone:
271 default:
272 perm = obj.EveryoneMask;
273 break;
274 }
275
276 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
277 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
278
279 // Special case: if Everyone can copy the object then this implies it can also be
280 // Transferred.
281 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
282 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
283 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
284 if (permissionClass != PermissionClass.Owner)
285 {
286 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
287 }
288
289
290 bool partPermitted = true;
291 if (checkPermissions.Contains("C") && !canCopy)
292 partPermitted = false;
293 if (checkPermissions.Contains("T") && !canTransfer)
294 partPermitted = false;
295
296 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
297 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, permitted={8}",
298 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
299 // permissionClass, checkPermissions, canCopy, canTransfer, permitted);
300
301 if (!partPermitted)
302 {
303 permitted = false;
304 break;
305 }
306
307 //++primNumber;
308 }
309
310 return permitted;
311 }
312
313 /// <summary>
214 /// Create the control file for the most up to date archive 314 /// Create the control file for the most up to date archive
215 /// </summary> 315 /// </summary>
216 /// <returns></returns> 316 /// <returns></returns>
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 08eb80c..f44a3ba 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -128,6 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
128// ops.Add("v|version=", delegate(string v) { options["version"] = v; }); 128// ops.Add("v|version=", delegate(string v) { options["version"] = v; });
129 ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); 129 ops.Add("p|profile=", delegate(string v) { options["profile"] = v; });
130 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 130 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
131 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
131 132
132 List<string> mainParams = ops.Parse(cmdparams); 133 List<string> mainParams = ops.Parse(cmdparams);
133 134
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index b185d9b..e798e5e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -318,6 +318,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
318 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 318 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
319 319
320 SceneObjectPart part1 = CreateSceneObjectPart1(); 320 SceneObjectPart part1 = CreateSceneObjectPart1();
321
322 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
323 part1.SitTargetPosition = new Vector3(1, 2, 3);
324
321 SceneObjectGroup object1 = new SceneObjectGroup(part1); 325 SceneObjectGroup object1 = new SceneObjectGroup(part1);
322 326
323 // Let's put some inventory items into our object 327 // Let's put some inventory items into our object
@@ -390,6 +394,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
390 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); 394 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
391 Assert.That( 395 Assert.That(
392 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); 396 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
397 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
398 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
393 399
394 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; 400 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
395 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); 401 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 94c1417..c199a77 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -968,10 +968,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
968 args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; 968 args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3;
969 args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; 969 args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4;
970 970
971 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); 971// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName);
972 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); 972// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName);
973 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); 973// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName);
974 m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); 974// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName);
975 975
976 remoteClient.SendRegionHandshake(Scene.RegionInfo,args); 976 remoteClient.SendRegionHandshake(Scene.RegionInfo,args);
977 } 977 }
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 8b78701..1e4f0a4 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
101 101
102 part.ParentGroup.HasGroupChanged = true; 102 part.ParentGroup.HasGroupChanged = true;
103 103
104 part.GetProperties(client); 104 part.SendPropertiesToClient(client);
105 } 105 }
106 106
107 public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice) 107 public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice)
@@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
142 part.SalePrice = 10; 142 part.SalePrice = 10;
143 143
144 group.HasGroupChanged = true; 144 group.HasGroupChanged = true;
145 part.GetProperties(remoteClient); 145 part.SendPropertiesToClient(remoteClient);
146 part.TriggerScriptChangedEvent(Changed.OWNER); 146 part.TriggerScriptChangedEvent(Changed.OWNER);
147 group.ResumeScripts(); 147 group.ResumeScripts();
148 part.ScheduleFullUpdate(); 148 part.ScheduleFullUpdate();
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index b9bd9a4..3b661ed 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces;
39 39
40namespace OpenSim.Region.CoreModules.World.Permissions 40namespace OpenSim.Region.CoreModules.World.Permissions
41{ 41{
42 public class PermissionsModule : IRegionModule 42 public class PermissionsModule : IRegionModule, IPermissionsModule
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
@@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
150 else 150 else
151 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); 151 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
152 152
153 scene.RegisterModuleInterface<IPermissionsModule>(this);
154
153 //Register functions with Scene External Checks! 155 //Register functions with Scene External Checks!
154 m_scene.Permissions.OnBypassPermissions += BypassPermissions; 156 m_scene.Permissions.OnBypassPermissions += BypassPermissions;
155 m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; 157 m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions;
@@ -574,46 +576,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
574 if (objectOwner != UUID.Zero) 576 if (objectOwner != UUID.Zero)
575 objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; 577 objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner;
576 578
577 if (m_bypassPermissions) 579 PermissionClass permissionClass = GetPermissionClass(user, task);
578 return objectOwnerMask;
579
580 // Object owners should be able to edit their own content
581 if (user == objectOwner)
582 return objectOwnerMask;
583
584 if (IsFriendWithPerms(user, objectOwner))
585 {
586 return objectOwnerMask;
587 }
588 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
589 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
590 {
591 return objectOwnerMask;
592 }
593
594 // Admin should be able to edit anything in the sim (including admin objects)
595 if (IsAdministrator(user))
596 {
597 return objectOwnerMask;
598 }
599 580
600 // Users should be able to edit what is over their land. 581 switch (permissionClass)
601 Vector3 taskPos = task.AbsolutePosition;
602 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
603 if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
604 { 582 {
605 // Admin objects should not be editable by the above 583 case PermissionClass.Owner:
606 if (!IsAdministrator(objectOwner))
607 {
608 return objectOwnerMask; 584 return objectOwnerMask;
609 } 585 case PermissionClass.Group:
586 return objectGroupMask | objectEveryoneMask;
587 case PermissionClass.Everyone:
588 default:
589 return objectEveryoneMask;
610 } 590 }
611
612 // Group permissions
613 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
614 return objectGroupMask | objectEveryoneMask;
615
616 return objectEveryoneMask;
617 } 591 }
618 592
619 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) 593 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask)
@@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions
644 return objectFlagsMask; 618 return objectFlagsMask;
645 } 619 }
646 620
621 public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj)
622 {
623 if (obj == null)
624 return PermissionClass.Everyone;
625
626 if (m_bypassPermissions)
627 return PermissionClass.Owner;
628
629 // Object owners should be able to edit their own content
630 UUID objectOwner = obj.OwnerID;
631 if (user == objectOwner)
632 return PermissionClass.Owner;
633
634 if (IsFriendWithPerms(user, objectOwner))
635 return PermissionClass.Owner;
636
637 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
638 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
639 return PermissionClass.Owner;
640
641 // Admin should be able to edit anything in the sim (including admin objects)
642 if (IsAdministrator(user))
643 return PermissionClass.Owner;
644
645 // Users should be able to edit what is over their land.
646 Vector3 taskPos = obj.AbsolutePosition;
647 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
648 if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
649 {
650 // Admin objects should not be editable by the above
651 if (!IsAdministrator(objectOwner))
652 return PermissionClass.Owner;
653 }
654
655 // Group permissions
656 if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0))
657 return PermissionClass.Group;
658
659 return PermissionClass.Everyone;
660 }
661
647 /// <summary> 662 /// <summary>
648 /// General permissions checks for any operation involving an object. These supplement more specific checks 663 /// General permissions checks for any operation involving an object. These supplement more specific checks
649 /// implemented by callers. 664 /// implemented by callers.
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index c87790f..b0266c5 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -222,7 +222,7 @@ namespace OpenSim.Region.Examples.SimpleModule
222 public event ScriptReset OnScriptReset; 222 public event ScriptReset OnScriptReset;
223 public event GetScriptRunning OnGetScriptRunning; 223 public event GetScriptRunning OnGetScriptRunning;
224 public event SetScriptRunning OnSetScriptRunning; 224 public event SetScriptRunning OnSetScriptRunning;
225 public event Action<Vector3, bool> OnAutoPilotGo; 225 public event Action<Vector3, bool, bool> OnAutoPilotGo;
226 226
227 public event TerrainUnacked OnUnackedTerrain; 227 public event TerrainUnacked OnUnackedTerrain;
228 228
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 73d15a5..5ffbec8 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -88,6 +88,15 @@ namespace OpenSim.Region.Framework.Interfaces
88 ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); 88 ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt);
89 89
90 /// <summary> 90 /// <summary>
91 /// Rez an attachment from user inventory and change inventory status to match.
92 /// </summary>
93 /// <param name="sp"></param>
94 /// <param name="itemID"></param>
95 /// <param name="AttachmentPt"></param>
96 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
97 ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt);
98
99 /// <summary>
91 /// Rez multiple attachments from a user's inventory 100 /// Rez multiple attachments from a user's inventory
92 /// </summary> 101 /// </summary>
93 /// <param name="remoteClient"></param> 102 /// <param name="remoteClient"></param>
@@ -129,14 +138,5 @@ namespace OpenSim.Region.Framework.Interfaces
129 /// <param name="sog"></param> 138 /// <param name="sog"></param>
130 /// <param name="pos"></param> 139 /// <param name="pos"></param>
131 void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos); 140 void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos);
132
133 /// <summary>
134 /// Update the user inventory with a changed attachment
135 /// </summary>
136 /// <param name="remoteClient"></param>
137 /// <param name="grp"></param>
138 /// <param name="itemID"></param>
139 /// <param name="agentID"></param>
140 void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID);
141 } 141 }
142} 142}
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs b/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs
index 7066cf2..35cc220 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs
@@ -1,4 +1,4 @@
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 *
@@ -48,6 +48,14 @@ namespace OpenSim.Region.Framework.Interfaces
48 /// <param name="estateID"></param> 48 /// <param name="estateID"></param>
49 /// <returns></returns> 49 /// <returns></returns>
50 EstateSettings LoadEstateSettings(int estateID); 50 EstateSettings LoadEstateSettings(int estateID);
51
52 /// <summary>
53 /// Create a new estate.
54 /// </summary>
55 /// <returns>
56 /// A <see cref="EstateSettings"/>
57 /// </returns>
58 EstateSettings CreateNewEstate();
51 59
52 /// <summary> 60 /// <summary>
53 /// Load/Get all estate settings. 61 /// Load/Get all estate settings.
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs b/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs
index d790a30..8febb13 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs
@@ -55,6 +55,14 @@ namespace OpenSim.Region.Framework.Interfaces
55 EstateSettings LoadEstateSettings(int estateID); 55 EstateSettings LoadEstateSettings(int estateID);
56 56
57 /// <summary> 57 /// <summary>
58 /// Create a new estate.
59 /// </summary>
60 /// <returns>
61 /// A <see cref="EstateSettings"/>
62 /// </returns>
63 EstateSettings CreateNewEstate();
64
65 /// <summary>
58 /// Load/Get all estate settings. 66 /// Load/Get all estate settings.
59 /// </summary> 67 /// </summary>
60 /// <returns>An empty list if no estates were found.</returns> 68 /// <returns>An empty list if no estates were found.</returns>
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
index 578c22a..1ed978b 100644
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs
+++ b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
@@ -1,4 +1,4 @@
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 *
@@ -25,36 +25,30 @@
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 OpenMetaverse;
29using OpenSim.Region.Framework.Scenes;
29 30
30public enum StatusIndicators : int 31namespace OpenSim.Region.Framework.Interfaces
31{ 32{
32 Generic = 0, 33 /// <value>
33 Start = 1, 34 /// Which set of permissions a user has.
34 End = 2 35 /// </value>
35} 36 public enum PermissionClass
37 {
38 Owner,
39 Group,
40 Everyone
41 };
36 42
37public struct sCollisionData 43 public interface IPermissionsModule
38{ 44 {
39 public uint ColliderLocalId; 45
40 public uint CollidedWithLocalId; 46 /// <summary>
41 public int NumberOfCollisions; 47 /// Returns the type of permissions that the user has over an object.
42 public int CollisionType; 48 /// </summary>
43 public int StatusIndicator; 49 /// <param name="user">The user</param>
44 public int lastframe; 50 /// <param name="obj">The object</param>
51 /// <returns>The type of permissions the user has over the object</returns>
52 PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj);
53 }
45} 54}
46
47[Flags]
48public enum CollisionCategories : int
49{
50 Disabled = 0,
51 Geom = 0x00000001,
52 Body = 0x00000002,
53 Space = 0x00000004,
54 Character = 0x00000008,
55 Land = 0x00000010,
56 Water = 0x00000020,
57 Wind = 0x00000040,
58 Sensor = 0x00000080,
59 Selected = 0x00000100
60} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
index 8913133..ff39283 100644
--- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
@@ -61,6 +61,14 @@ namespace OpenSim.Region.Framework.Interfaces
61 AvatarAppearance Appearance { get; set; } 61 AvatarAppearance Appearance { get; set; }
62 62
63 /// <summary> 63 /// <summary>
64 /// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments.
65 /// </summary>
66 /// <remarks>
67 /// All add and remove attachment operations must synchronize on this for the lifetime of their operations.
68 /// </remarks>
69 Object AttachmentsSyncLock { get; }
70
71 /// <summary>
64 /// The scene objects attached to this avatar. 72 /// The scene objects attached to this avatar.
65 /// </summary> 73 /// </summary>
66 /// <returns> 74 /// <returns>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index d9752e6..b27b7da 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -52,5 +52,10 @@ namespace OpenSim.Region.Framework.Interfaces
52 ArrayList GetScriptErrors(UUID itemID); 52 ArrayList GetScriptErrors(UUID itemID);
53 53
54 void SaveAllState(); 54 void SaveAllState();
55
56 /// <summary>
57 /// Starts the processing threads.
58 /// </summary>
59 void StartProcessing();
55 } 60 }
56} 61}
diff --git a/OpenSim/Region/Framework/Scenes/EntityBase.cs b/OpenSim/Region/Framework/Scenes/EntityBase.cs
index 213431a..320b904 100644
--- a/OpenSim/Region/Framework/Scenes/EntityBase.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityBase.cs
@@ -26,8 +26,10 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Reflection;
29using System.Runtime.Serialization; 30using System.Runtime.Serialization;
30using System.Security.Permissions; 31using System.Security.Permissions;
32using log4net;
31using OpenSim.Framework; 33using OpenSim.Framework;
32using OpenMetaverse; 34using OpenMetaverse;
33 35
@@ -35,6 +37,8 @@ namespace OpenSim.Region.Framework.Scenes
35{ 37{
36 public abstract class EntityBase : ISceneEntity 38 public abstract class EntityBase : ISceneEntity
37 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
38 /// <summary> 42 /// <summary>
39 /// The scene to which this entity belongs 43 /// The scene to which this entity belongs
40 /// </summary> 44 /// </summary>
@@ -71,12 +75,15 @@ namespace OpenSim.Region.Framework.Scenes
71 protected Vector3 m_pos; 75 protected Vector3 m_pos;
72 76
73 /// <summary> 77 /// <summary>
74 /// 78 /// Absolute position of this entity in a scene.
75 /// </summary> 79 /// </summary>
76 public virtual Vector3 AbsolutePosition 80 public virtual Vector3 AbsolutePosition
77 { 81 {
78 get { return m_pos; } 82 get { return m_pos; }
79 set { m_pos = value; } 83 set
84 {
85 m_pos = value;
86 }
80 } 87 }
81 88
82 protected Vector3 m_velocity; 89 protected Vector3 m_velocity;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 4700c3b..663aa22 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -57,11 +57,11 @@ namespace OpenSim.Region.Framework.Scenes
57 protected AsyncInventorySender m_asyncInventorySender; 57 protected AsyncInventorySender m_asyncInventorySender;
58 58
59 /// <summary> 59 /// <summary>
60 /// Start all the scripts in the scene which should be started. 60 /// Creates all the scripts in the scene which should be started.
61 /// </summary> 61 /// </summary>
62 public void CreateScriptInstances() 62 public void CreateScriptInstances()
63 { 63 {
64 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); 64 m_log.Info("[PRIM INVENTORY]: Creating scripts in scene");
65 65
66 EntityBase[] entities = Entities.GetEntities(); 66 EntityBase[] entities = Entities.GetEntities();
67 foreach (EntityBase group in entities) 67 foreach (EntityBase group in entities)
@@ -74,6 +74,26 @@ namespace OpenSim.Region.Framework.Scenes
74 } 74 }
75 } 75 }
76 76
77 /// <summary>
78 /// Lets the script engines start processing scripts.
79 /// </summary>
80 public void StartScripts()
81 {
82 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene");
83
84 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
85 if (engines != null)
86 {
87 foreach (IScriptModule engine in engines)
88 {
89 if (engine != null)
90 {
91 engine.StartProcessing();
92 }
93 }
94 }
95 }
96
77 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) 97 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)
78 { 98 {
79 IMoneyModule money = RequestModuleInterface<IMoneyModule>(); 99 IMoneyModule money = RequestModuleInterface<IMoneyModule>();
@@ -254,7 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
254 if (group.UpdateInventoryItem(item)) 274 if (group.UpdateInventoryItem(item))
255 remoteClient.SendAgentAlertMessage("Script saved", false); 275 remoteClient.SendAgentAlertMessage("Script saved", false);
256 276
257 part.GetProperties(remoteClient); 277 part.SendPropertiesToClient(remoteClient);
258 278
259 // Trigger rerunning of script (use TriggerRezScript event, see RezScript) 279 // Trigger rerunning of script (use TriggerRezScript event, see RezScript)
260 ArrayList errors = new ArrayList(); 280 ArrayList errors = new ArrayList();
@@ -314,6 +334,10 @@ namespace OpenSim.Region.Framework.Scenes
314 public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, 334 public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID,
315 UUID itemID, InventoryItemBase itemUpd) 335 UUID itemID, InventoryItemBase itemUpd)
316 { 336 {
337// m_log.DebugFormat(
338// "[USER INVENTORY]: Updating asset for item {0} {1}, transaction ID {2} for {3}",
339// itemID, itemUpd.Name, transactionID, remoteClient.Name);
340
317 // This one will let people set next perms on items in agent 341 // This one will let people set next perms on items in agent
318 // inventory. Rut-Roh. Whatever. Make this secure. Yeah. 342 // inventory. Rut-Roh. Whatever. Make this secure. Yeah.
319 // 343 //
@@ -365,8 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
365 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); 389 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
366 if (agentTransactions != null) 390 if (agentTransactions != null)
367 { 391 {
368 agentTransactions.HandleItemUpdateFromTransaction( 392 agentTransactions.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
369 remoteClient, transactionID, item);
370 } 393 }
371 } 394 }
372 } 395 }
@@ -979,7 +1002,7 @@ namespace OpenSim.Region.Framework.Scenes
979 } 1002 }
980 1003
981 group.RemoveInventoryItem(localID, itemID); 1004 group.RemoveInventoryItem(localID, itemID);
982 part.GetProperties(remoteClient); 1005 part.SendPropertiesToClient(remoteClient);
983 } 1006 }
984 1007
985 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) 1008 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
@@ -1252,7 +1275,7 @@ namespace OpenSim.Region.Framework.Scenes
1252 1275
1253 if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar)) 1276 if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar))
1254 { 1277 {
1255 destPart.GetProperties(avatar.ControllingClient); 1278 destPart.SendPropertiesToClient(avatar.ControllingClient);
1256 } 1279 }
1257 } 1280 }
1258 1281
@@ -1407,7 +1430,7 @@ namespace OpenSim.Region.Framework.Scenes
1407 m_log.InfoFormat( 1430 m_log.InfoFormat(
1408 "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", 1431 "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}",
1409 item.Name, primLocalID, remoteClient.Name); 1432 item.Name, primLocalID, remoteClient.Name);
1410 part.GetProperties(remoteClient); 1433 part.SendPropertiesToClient(remoteClient);
1411 if (!Permissions.BypassPermissions()) 1434 if (!Permissions.BypassPermissions())
1412 { 1435 {
1413 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 1436 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
@@ -1502,7 +1525,7 @@ namespace OpenSim.Region.Framework.Scenes
1502 1525
1503 if (part.Inventory.UpdateInventoryItem(itemInfo)) 1526 if (part.Inventory.UpdateInventoryItem(itemInfo))
1504 { 1527 {
1505 part.GetProperties(remoteClient); 1528 part.SendPropertiesToClient(remoteClient);
1506 } 1529 }
1507 } 1530 }
1508 } 1531 }
@@ -1554,7 +1577,7 @@ namespace OpenSim.Region.Framework.Scenes
1554 // m_log.InfoFormat("[PRIMINVENTORY]: " + 1577 // m_log.InfoFormat("[PRIMINVENTORY]: " +
1555 // "Rezzed script {0} into prim local ID {1} for user {2}", 1578 // "Rezzed script {0} into prim local ID {1} for user {2}",
1556 // item.inventoryName, localID, remoteClient.Name); 1579 // item.inventoryName, localID, remoteClient.Name);
1557 part.GetProperties(remoteClient); 1580 part.SendPropertiesToClient(remoteClient);
1558 part.ParentGroup.ResumeScripts(); 1581 part.ParentGroup.ResumeScripts();
1559 } 1582 }
1560 else 1583 else
@@ -1612,7 +1635,7 @@ namespace OpenSim.Region.Framework.Scenes
1612 taskItem.AssetID = asset.FullID; 1635 taskItem.AssetID = asset.FullID;
1613 1636
1614 part.Inventory.AddInventoryItem(taskItem, false); 1637 part.Inventory.AddInventoryItem(taskItem, false);
1615 part.GetProperties(remoteClient); 1638 part.SendPropertiesToClient(remoteClient);
1616 1639
1617 part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); 1640 part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
1618 part.ParentGroup.ResumeScripts(); 1641 part.ParentGroup.ResumeScripts();
@@ -1726,7 +1749,7 @@ namespace OpenSim.Region.Framework.Scenes
1726 1749
1727 if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar)) 1750 if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar))
1728 { 1751 {
1729 destPart.GetProperties(avatar.ControllingClient); 1752 destPart.SendPropertiesToClient(avatar.ControllingClient);
1730 } 1753 }
1731 } 1754 }
1732 1755
@@ -2064,7 +2087,7 @@ namespace OpenSim.Region.Framework.Scenes
2064 SceneObjectPart part = GetSceneObjectPart(localID); 2087 SceneObjectPart part = GetSceneObjectPart(localID);
2065 if (part == null) 2088 if (part == null)
2066 continue; 2089 continue;
2067 part.GetProperties(remoteClient); 2090 part.SendPropertiesToClient(remoteClient);
2068 } 2091 }
2069 } 2092 }
2070 2093
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 29d01d6..270e582 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -144,7 +144,7 @@ namespace OpenSim.Region.Framework.Scenes
144 { 144 {
145 if (((SceneObjectGroup) ent).LocalId == primLocalID) 145 if (((SceneObjectGroup) ent).LocalId == primLocalID)
146 { 146 {
147 ((SceneObjectGroup) ent).GetProperties(remoteClient); 147 ((SceneObjectGroup) ent).SendPropertiesToClient(remoteClient);
148 ((SceneObjectGroup) ent).IsSelected = true; 148 ((SceneObjectGroup) ent).IsSelected = true;
149 // A prim is only tainted if it's allowed to be edited by the person clicking it. 149 // A prim is only tainted if it's allowed to be edited by the person clicking it.
150 if (Permissions.CanEditObject(((SceneObjectGroup)ent).UUID, remoteClient.AgentId) 150 if (Permissions.CanEditObject(((SceneObjectGroup)ent).UUID, remoteClient.AgentId)
@@ -167,7 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
167 { 167 {
168 if (part.LocalId == primLocalID) 168 if (part.LocalId == primLocalID)
169 { 169 {
170 part.GetProperties(remoteClient); 170 part.SendPropertiesToClient(remoteClient);
171 foundPrim = true; 171 foundPrim = true;
172 break; 172 break;
173 } 173 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f86b3b6..eadec09 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -656,7 +656,7 @@ namespace OpenSim.Region.Framework.Scenes
656 EventManager.OnLandObjectRemoved += 656 EventManager.OnLandObjectRemoved +=
657 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 657 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
658 658
659 m_sceneGraph = new SceneGraph(this, m_regInfo); 659 m_sceneGraph = new SceneGraph(this);
660 660
661 // If the scene graph has an Unrecoverable error, restart this sim. 661 // If the scene graph has an Unrecoverable error, restart this sim.
662 // Currently the only thing that causes it to happen is two kinds of specific 662 // Currently the only thing that causes it to happen is two kinds of specific
@@ -870,6 +870,8 @@ namespace OpenSim.Region.Framework.Scenes
870 870
871 if (dm != null) 871 if (dm != null)
872 m_eventManager.OnPermissionError += dm.SendAlertToUser; 872 m_eventManager.OnPermissionError += dm.SendAlertToUser;
873
874 m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
873 } 875 }
874 876
875 public override string GetSimulatorVersion() 877 public override string GetSimulatorVersion()
@@ -1170,87 +1172,6 @@ namespace OpenSim.Region.Framework.Scenes
1170 m_dialogModule = RequestModuleInterface<IDialogModule>(); 1172 m_dialogModule = RequestModuleInterface<IDialogModule>();
1171 m_capsModule = RequestModuleInterface<ICapabilitiesModule>(); 1173 m_capsModule = RequestModuleInterface<ICapabilitiesModule>();
1172 m_teleportModule = RequestModuleInterface<IEntityTransferModule>(); 1174 m_teleportModule = RequestModuleInterface<IEntityTransferModule>();
1173
1174 // Shoving this in here for now, because we have the needed
1175 // interfaces at this point
1176 //
1177 // TODO: Find a better place for this
1178 //
1179 while (m_regInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
1180 {
1181 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", m_regInfo.EstateSettings.EstateName);
1182 List<char> excluded = new List<char>(new char[1]{' '});
1183 string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded);
1184 string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded);
1185
1186 UserAccount account = UserAccountService.GetUserAccount(m_regInfo.ScopeID, first, last);
1187
1188 if (account == null)
1189 {
1190 // Create a new account
1191 account = new UserAccount(m_regInfo.ScopeID, first, last, String.Empty);
1192 if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0))
1193 {
1194 account.ServiceURLs = new Dictionary<string, object>();
1195 account.ServiceURLs["HomeURI"] = string.Empty;
1196 account.ServiceURLs["GatekeeperURI"] = string.Empty;
1197 account.ServiceURLs["InventoryServerURI"] = string.Empty;
1198 account.ServiceURLs["AssetServerURI"] = string.Empty;
1199 }
1200
1201 if (UserAccountService.StoreUserAccount(account))
1202 {
1203 string password = MainConsole.Instance.PasswdPrompt("Password");
1204 string email = MainConsole.Instance.CmdPrompt("Email", "");
1205
1206 account.Email = email;
1207 UserAccountService.StoreUserAccount(account);
1208
1209 bool success = false;
1210 success = AuthenticationService.SetPassword(account.PrincipalID, password);
1211 if (!success)
1212 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set password for account {0} {1}.",
1213 first, last);
1214
1215 GridRegion home = null;
1216 if (GridService != null)
1217 {
1218 List<GridRegion> defaultRegions = GridService.GetDefaultRegions(UUID.Zero);
1219 if (defaultRegions != null && defaultRegions.Count >= 1)
1220 home = defaultRegions[0];
1221
1222 if (GridUserService != null && home != null)
1223 GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0));
1224 else
1225 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.",
1226 first, last);
1227
1228 }
1229 else
1230 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to retrieve home region for account {0} {1}.",
1231 first, last);
1232
1233 if (InventoryService != null)
1234 success = InventoryService.CreateUserInventory(account.PrincipalID);
1235 if (!success)
1236 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.",
1237 first, last);
1238
1239
1240 m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", first, last);
1241
1242 m_regInfo.EstateSettings.EstateOwner = account.PrincipalID;
1243 m_regInfo.EstateSettings.Save();
1244 }
1245 else
1246 m_log.ErrorFormat("[SCENE]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first.");
1247 }
1248 else
1249 {
1250 m_regInfo.EstateSettings.EstateOwner = account.PrincipalID;
1251 m_regInfo.EstateSettings.Save();
1252 }
1253 }
1254 } 1175 }
1255 1176
1256 #endregion 1177 #endregion
@@ -1579,7 +1500,9 @@ namespace OpenSim.Region.Framework.Scenes
1579 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1500 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1580 msg.Position = Vector3.Zero; 1501 msg.Position = Vector3.Zero;
1581 msg.RegionID = RegionInfo.RegionID.Guid; 1502 msg.RegionID = RegionInfo.RegionID.Guid;
1582 msg.binaryBucket = new byte[0]; 1503
1504 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
1505 msg.binaryBucket = Util.StringToBytes256("\0");
1583 if (ret.Value.count > 1) 1506 if (ret.Value.count > 1)
1584 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); 1507 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
1585 else 1508 else
@@ -2459,14 +2382,16 @@ namespace OpenSim.Region.Framework.Scenes
2459 /// <returns>False</returns> 2382 /// <returns>False</returns>
2460 public virtual bool IncomingCreateObject(UUID userID, UUID itemID) 2383 public virtual bool IncomingCreateObject(UUID userID, UUID itemID)
2461 { 2384 {
2462 //m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID); 2385 m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
2463 2386
2464 ScenePresence sp = GetScenePresence(userID); 2387 // Commented out since this is as yet unused and is arguably not the appropriate place to do this, as
2465 if (sp != null && AttachmentsModule != null) 2388 // attachments are being rezzed elsewhere in AddNewClient()
2466 { 2389// ScenePresence sp = GetScenePresence(userID);
2467 uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); 2390// if (sp != null && AttachmentsModule != null)
2468 AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt); 2391// {
2469 } 2392// uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID);
2393// AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt);
2394// }
2470 2395
2471 return false; 2396 return false;
2472 } 2397 }
@@ -5215,5 +5140,70 @@ namespace OpenSim.Region.Framework.Scenes
5215 reason = String.Empty; 5140 reason = String.Empty;
5216 return true; 5141 return true;
5217 } 5142 }
5143
5144 /// <summary>
5145 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5146 /// autopilot that moves an avatar to a sit target!.
5147 /// </summary>
5148 /// <remarks>
5149 /// This is not intended as a permament location for this method.
5150 /// </remarks>
5151 /// <param name="presence"></param>
5152 private void HandleOnSignificantClientMovement(ScenePresence presence)
5153 {
5154 if (presence.MovingToTarget)
5155 {
5156 double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget);
5157// m_log.DebugFormat(
5158// "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}",
5159// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget);
5160
5161 // Check the error term of the current position in relation to the target position
5162 if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT)
5163 {
5164 // We are close enough to the target
5165// m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name);
5166
5167 presence.Velocity = Vector3.Zero;
5168 presence.AbsolutePosition = presence.MoveToPositionTarget;
5169 presence.ResetMoveToTarget();
5170
5171 if (presence.PhysicsActor.Flying)
5172 {
5173 // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot
5174 // the target if flying.
5175 // We really need to be more subtle (slow the avatar as it approaches the target) or at
5176 // least be able to set collision status once, rather than 5 times to give it enough
5177 // weighting so that that PhysicsActor thinks it really is colliding.
5178 for (int i = 0; i < 5; i++)
5179 presence.PhysicsActor.IsColliding = true;
5180
5181 if (presence.LandAtTarget)
5182 presence.PhysicsActor.Flying = false;
5183
5184// Vector3 targetPos = presence.MoveToPositionTarget;
5185// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y];
5186// if (targetPos.Z - terrainHeight < 0.2)
5187// {
5188// presence.PhysicsActor.Flying = false;
5189// }
5190 }
5191
5192// m_log.DebugFormat(
5193// "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}",
5194// presence.AgentControlFlags, presence.MovementFlag, presence.Name);
5195 }
5196 else
5197 {
5198// m_log.DebugFormat(
5199// "[SCENE]: Updating npc {0} at {1} for next movement to {2}",
5200// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget);
5201
5202 Vector3 agent_control_v3 = new Vector3();
5203 presence.HandleMoveToTargetUpdate(ref agent_control_v3);
5204 presence.AddNewMovement(agent_control_v3);
5205 }
5206 }
5207 }
5218 } 5208 }
5219} 5209}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 6f963ac..36c5c52 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -74,7 +74,6 @@ namespace OpenSim.Region.Framework.Scenes
74 74
75 protected internal EntityManager Entities = new EntityManager(); 75 protected internal EntityManager Entities = new EntityManager();
76 76
77 protected RegionInfo m_regInfo;
78 protected Scene m_parentScene; 77 protected Scene m_parentScene;
79 protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>(); 78 protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
80 protected int m_numRootAgents = 0; 79 protected int m_numRootAgents = 0;
@@ -108,10 +107,9 @@ namespace OpenSim.Region.Framework.Scenes
108 107
109 #endregion 108 #endregion
110 109
111 protected internal SceneGraph(Scene parent, RegionInfo regInfo) 110 protected internal SceneGraph(Scene parent)
112 { 111 {
113 m_parentScene = parent; 112 m_parentScene = parent;
114 m_regInfo = regInfo;
115 } 113 }
116 114
117 public PhysicsScene PhysicsScene 115 public PhysicsScene PhysicsScene
@@ -122,7 +120,6 @@ namespace OpenSim.Region.Framework.Scenes
122 // If we're not doing the initial set 120 // If we're not doing the initial set
123 // Then we've got to remove the previous 121 // Then we've got to remove the previous
124 // event handler 122 // event handler
125
126 if (_PhyScene != null) 123 if (_PhyScene != null)
127 _PhyScene.OnPhysicsCrash -= physicsBasedCrash; 124 _PhyScene.OnPhysicsCrash -= physicsBasedCrash;
128 125
@@ -372,12 +369,12 @@ namespace OpenSim.Region.Framework.Scenes
372// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", 369// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
373// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); 370// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
374 371
375 SceneObjectPart[] children = sceneObject.Parts; 372 SceneObjectPart[] parts = sceneObject.Parts;
376 373
377 // Clamp child prim sizes and add child prims to the m_numPrim count 374 // Clamp child prim sizes and add child prims to the m_numPrim count
378 if (m_parentScene.m_clampPrimSize) 375 if (m_parentScene.m_clampPrimSize)
379 { 376 {
380 foreach (SceneObjectPart part in children) 377 foreach (SceneObjectPart part in parts)
381 { 378 {
382 Vector3 scale = part.Shape.Scale; 379 Vector3 scale = part.Shape.Scale;
383 380
@@ -391,7 +388,7 @@ namespace OpenSim.Region.Framework.Scenes
391 part.Shape.Scale = scale; 388 part.Shape.Scale = scale;
392 } 389 }
393 } 390 }
394 m_numPrim += children.Length; 391 m_numPrim += parts.Length;
395 392
396 sceneObject.AttachToScene(m_parentScene); 393 sceneObject.AttachToScene(m_parentScene);
397 394
@@ -411,15 +408,17 @@ namespace OpenSim.Region.Framework.Scenes
411 408
412 lock (SceneObjectGroupsByFullPartID) 409 lock (SceneObjectGroupsByFullPartID)
413 { 410 {
414 SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject; 411 foreach (SceneObjectPart part in parts)
415 foreach (SceneObjectPart part in children)
416 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 412 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
417 } 413 }
418 414
419 lock (SceneObjectGroupsByLocalPartID) 415 lock (SceneObjectGroupsByLocalPartID)
420 { 416 {
421 SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject; 417// m_log.DebugFormat(
422 foreach (SceneObjectPart part in children) 418// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
419// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
420
421 foreach (SceneObjectPart part in parts)
423 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 422 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
424 } 423 }
425 424
@@ -432,6 +431,10 @@ namespace OpenSim.Region.Framework.Scenes
432 /// <returns>true if the object was deleted, false if there was no object to delete</returns> 431 /// <returns>true if the object was deleted, false if there was no object to delete</returns>
433 public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) 432 public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
434 { 433 {
434// m_log.DebugFormat(
435// "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}",
436// uuid, resultOfObjectLinked);
437
435 EntityBase entity; 438 EntityBase entity;
436 if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup))) 439 if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup)))
437 return false; 440 return false;
@@ -460,7 +463,6 @@ namespace OpenSim.Region.Framework.Scenes
460 SceneObjectPart[] parts = grp.Parts; 463 SceneObjectPart[] parts = grp.Parts;
461 for (int i = 0; i < parts.Length; i++) 464 for (int i = 0; i < parts.Length; i++)
462 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 465 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
463 SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID);
464 } 466 }
465 467
466 lock (SceneObjectGroupsByLocalPartID) 468 lock (SceneObjectGroupsByLocalPartID)
@@ -468,7 +470,6 @@ namespace OpenSim.Region.Framework.Scenes
468 SceneObjectPart[] parts = grp.Parts; 470 SceneObjectPart[] parts = grp.Parts;
469 for (int i = 0; i < parts.Length; i++) 471 for (int i = 0; i < parts.Length; i++)
470 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 472 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
471 SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId);
472 } 473 }
473 474
474 return Entities.Remove(uuid); 475 return Entities.Remove(uuid);
@@ -589,7 +590,7 @@ namespace OpenSim.Region.Framework.Scenes
589 ScenePresence newAvatar = null; 590 ScenePresence newAvatar = null;
590 591
591 // ScenePresence always defaults to child agent 592 // ScenePresence always defaults to child agent
592 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance, type); 593 newAvatar = new ScenePresence(client, m_parentScene, appearance, type);
593 594
594 AddScenePresence(newAvatar); 595 AddScenePresence(newAvatar);
595 596
@@ -651,7 +652,7 @@ namespace OpenSim.Region.Framework.Scenes
651 if (!Entities.Remove(agentID)) 652 if (!Entities.Remove(agentID))
652 { 653 {
653 m_log.WarnFormat( 654 m_log.WarnFormat(
654 "[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", 655 "[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
655 agentID); 656 agentID);
656 } 657 }
657 658
@@ -674,7 +675,7 @@ namespace OpenSim.Region.Framework.Scenes
674 } 675 }
675 else 676 else
676 { 677 {
677 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 678 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
678 } 679 }
679 } 680 }
680 } 681 }
@@ -881,7 +882,8 @@ namespace OpenSim.Region.Framework.Scenes
881 if (Entities.TryGetValue(localID, out entity)) 882 if (Entities.TryGetValue(localID, out entity))
882 return entity as SceneObjectGroup; 883 return entity as SceneObjectGroup;
883 884
884 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); 885// m_log.DebugFormat("[SCENE GRAPH]: Entered GetGroupByPrim with localID {0}", localID);
886
885 SceneObjectGroup sog; 887 SceneObjectGroup sog;
886 lock (SceneObjectGroupsByLocalPartID) 888 lock (SceneObjectGroupsByLocalPartID)
887 SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog); 889 SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
@@ -889,8 +891,24 @@ namespace OpenSim.Region.Framework.Scenes
889 if (sog != null) 891 if (sog != null)
890 { 892 {
891 if (sog.HasChildPrim(localID)) 893 if (sog.HasChildPrim(localID))
894 {
895// m_log.DebugFormat(
896// "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.",
897// sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
898
892 return sog; 899 return sog;
893 SceneObjectGroupsByLocalPartID.Remove(localID); 900 }
901 else
902 {
903 lock (SceneObjectGroupsByLocalPartID)
904 {
905 m_log.WarnFormat(
906 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
907 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
908
909 SceneObjectGroupsByLocalPartID.Remove(localID);
910 }
911 }
894 } 912 }
895 913
896 EntityBase[] entityList = GetEntities(); 914 EntityBase[] entityList = GetEntities();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 4bca3d0..905ecc9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -389,5 +389,18 @@ namespace OpenSim.Region.Framework.Scenes
389 for (int i = 0; i < parts.Length; i++) 389 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 390 parts[i].Inventory.ResumeScripts();
391 } 391 }
392
393 /// <summary>
394 /// Returns true if any part in the scene object contains scripts, false otherwise.
395 /// </summary>
396 /// <returns></returns>
397 public bool ContainsScripts()
398 {
399 foreach (SceneObjectPart part in Parts)
400 if (part.Inventory.ContainsScripts())
401 return true;
402
403 return false;
404 }
392 } 405 }
393} 406}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 2819545..980b01f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1599,7 +1599,7 @@ namespace OpenSim.Region.Framework.Scenes
1599 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1599 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1600 if (avatar != null) 1600 if (avatar != null)
1601 { 1601 {
1602 avatar.MoveToTarget(target, false); 1602 avatar.MoveToTarget(target, false, false);
1603 } 1603 }
1604 } 1604 }
1605 else 1605 else
@@ -1728,8 +1728,6 @@ namespace OpenSim.Region.Framework.Scenes
1728 1728
1729 #endregion 1729 #endregion
1730 1730
1731 #region Scheduling
1732
1733 public override void Update() 1731 public override void Update()
1734 { 1732 {
1735 // Check that the group was not deleted before the scheduled update 1733 // Check that the group was not deleted before the scheduled update
@@ -1880,7 +1878,14 @@ namespace OpenSim.Region.Framework.Scenes
1880 parts[i].SendTerseUpdateToAllClients(); 1878 parts[i].SendTerseUpdateToAllClients();
1881 } 1879 }
1882 1880
1883 #endregion 1881 /// <summary>
1882 /// Send metadata about the root prim (name, description, sale price, etc.) to a client.
1883 /// </summary>
1884 /// <param name="client"></param>
1885 public void SendPropertiesToClient(IClientAPI client)
1886 {
1887 m_rootPart.SendPropertiesToClient(client);
1888 }
1884 1889
1885 #region SceneGroupPart Methods 1890 #region SceneGroupPart Methods
1886 1891
@@ -2370,15 +2375,6 @@ namespace OpenSim.Region.Framework.Scenes
2370 } 2375 }
2371 2376
2372 /// <summary> 2377 /// <summary>
2373 /// Return metadata about a prim (name, description, sale price, etc.)
2374 /// </summary>
2375 /// <param name="client"></param>
2376 public void GetProperties(IClientAPI client)
2377 {
2378 m_rootPart.GetProperties(client);
2379 }
2380
2381 /// <summary>
2382 /// Set the name of a prim 2378 /// Set the name of a prim
2383 /// </summary> 2379 /// </summary>
2384 /// <param name="name"></param> 2380 /// <param name="name"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 04fef83..632ac8f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1305,8 +1305,6 @@ namespace OpenSim.Region.Framework.Scenes
1305 1305
1306 #endregion Public Properties with only Get 1306 #endregion Public Properties with only Get
1307 1307
1308 #region Private Methods
1309
1310 private uint ApplyMask(uint val, bool set, uint mask) 1308 private uint ApplyMask(uint val, bool set, uint mask)
1311 { 1309 {
1312 if (set) 1310 if (set)
@@ -1327,14 +1325,27 @@ namespace OpenSim.Region.Framework.Scenes
1327 m_updateFlag = 0; 1325 m_updateFlag = 0;
1328 } 1326 }
1329 1327
1330 private void SendObjectPropertiesToClient(UUID AgentID) 1328 /// <summary>
1329 /// Send this part's properties (name, description, inventory serial, base mask, etc.) to a client
1330 /// </summary>
1331 /// <param name="client"></param>
1332 public void SendPropertiesToClient(IClientAPI client)
1333 {
1334 client.SendObjectPropertiesReply(this);
1335 }
1336
1337 /// <summary>
1338 /// For the scene object group to which this part belongs, send that scene object's root part properties to a client.
1339 /// </summary>
1340 /// <param name="AgentID"></param>
1341 private void SendRootPartPropertiesToClient(UUID AgentID)
1331 { 1342 {
1332 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1343 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
1333 { 1344 {
1334 // Ugly reference :( 1345 // Ugly reference :(
1335 if (avatar.UUID == AgentID) 1346 if (avatar.UUID == AgentID)
1336 { 1347 {
1337 m_parentGroup.GetProperties(avatar.ControllingClient); 1348 m_parentGroup.SendPropertiesToClient(avatar.ControllingClient);
1338 } 1349 }
1339 }); 1350 });
1340 } 1351 }
@@ -1363,8 +1374,6 @@ namespace OpenSim.Region.Framework.Scenes
1363 // } 1374 // }
1364 // } 1375 // }
1365 1376
1366 #endregion Private Methods
1367
1368 #region Public Methods 1377 #region Public Methods
1369 1378
1370 public void ResetExpire() 1379 public void ResetExpire()
@@ -1705,20 +1714,6 @@ namespace OpenSim.Region.Framework.Scenes
1705 Name, LocalId, id); 1714 Name, LocalId, id);
1706 } 1715 }
1707 1716
1708 public static SceneObjectPart Create()
1709 {
1710 SceneObjectPart part = new SceneObjectPart();
1711 part.UUID = UUID.Random();
1712
1713 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1714 part.Shape = shape;
1715
1716 part.Name = "Primitive";
1717 part._ownerID = UUID.Random();
1718
1719 return part;
1720 }
1721
1722 /// <summary> 1717 /// <summary>
1723 /// Do a physics property update for a NINJA joint. 1718 /// Do a physics property update for a NINJA joint.
1724 /// </summary> 1719 /// </summary>
@@ -2030,11 +2025,6 @@ namespace OpenSim.Region.Framework.Scenes
2030 return Vector3.Zero; 2025 return Vector3.Zero;
2031 } 2026 }
2032 2027
2033 public void GetProperties(IClientAPI client)
2034 {
2035 client.SendObjectPropertiesReply(this);
2036 }
2037
2038 /// <summary> 2028 /// <summary>
2039 /// Method for a prim to get it's world position from the group. 2029 /// Method for a prim to get it's world position from the group.
2040 /// </summary> 2030 /// </summary>
@@ -3453,7 +3443,7 @@ namespace OpenSim.Region.Framework.Scenes
3453 { 3443 {
3454 _groupID = groupID; 3444 _groupID = groupID;
3455 if (client != null) 3445 if (client != null)
3456 GetProperties(client); 3446 SendPropertiesToClient(client);
3457 m_updateFlag = 2; 3447 m_updateFlag = 2;
3458 } 3448 }
3459 3449
@@ -4273,10 +4263,10 @@ namespace OpenSim.Region.Framework.Scenes
4273 4263
4274 break; 4264 break;
4275 } 4265 }
4276 SendFullUpdateToAllClients();
4277 4266
4278 SendObjectPropertiesToClient(AgentID); 4267 SendFullUpdateToAllClients();
4279 4268
4269 SendRootPartPropertiesToClient(AgentID);
4280 } 4270 }
4281 } 4271 }
4282 4272
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index e40e57d..9446741 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -784,6 +784,10 @@ namespace OpenSim.Region.Framework.Scenes
784 784
785 private bool CreateInventoryFile() 785 private bool CreateInventoryFile()
786 { 786 {
787// m_log.DebugFormat(
788// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
789// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial);
790
787 if (m_inventoryFileName == String.Empty || 791 if (m_inventoryFileName == String.Empty ||
788 m_inventoryFileNameSerial < m_inventorySerial) 792 m_inventoryFileNameSerial < m_inventorySerial)
789 { 793 {
@@ -797,6 +801,10 @@ namespace OpenSim.Region.Framework.Scenes
797 { 801 {
798 foreach (TaskInventoryItem item in m_items.Values) 802 foreach (TaskInventoryItem item in m_items.Values)
799 { 803 {
804// m_log.DebugFormat(
805// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}",
806// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
807
800 UUID ownerID = item.OwnerID; 808 UUID ownerID = item.OwnerID;
801 uint everyoneMask = 0; 809 uint everyoneMask = 0;
802 uint baseMask = item.BasePermissions; 810 uint baseMask = item.BasePermissions;
@@ -856,28 +864,43 @@ namespace OpenSim.Region.Framework.Scenes
856 /// <param name="xferManager"></param> 864 /// <param name="xferManager"></param>
857 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 865 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
858 { 866 {
859 CreateInventoryFile(); 867 lock (m_items)
860
861 if (m_inventorySerial == 0) // No inventory
862 { 868 {
863 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 869 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
864 return; 870 // a new script if any previous deletion has left the prim inventory empty.
865 } 871 if (m_items.Count == 0) // No inventory
866 872 {
867 // In principle, we should only do the rest if the inventory changed; 873// m_log.DebugFormat(
868 // by sending m_inventorySerial to the client, it ought to know 874// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
869 // that nothing changed and that it doesn't need to request the file. 875// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
870 // Unfortunately, it doesn't look like the client optimizes this;
871 // the client seems to always come back and request the Xfer,
872 // no matter what value m_inventorySerial has.
873 876
874 if (m_inventoryFileData.Length > 2) 877 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
875 // Add the file for Xfer 878 return;
876 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 879 }
877 880
878 // Tell the client we're ready to Xfer the file 881 CreateInventoryFile();
879 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 882
880 Util.StringToBytes256(m_inventoryFileName)); 883 // In principle, we should only do the rest if the inventory changed;
884 // by sending m_inventorySerial to the client, it ought to know
885 // that nothing changed and that it doesn't need to request the file.
886 // Unfortunately, it doesn't look like the client optimizes this;
887 // the client seems to always come back and request the Xfer,
888 // no matter what value m_inventorySerial has.
889 // FIXME: Could probably be > 0 here rather than > 2
890 if (m_inventoryFileData.Length > 2)
891 {
892 // Add the file for Xfer
893 // m_log.DebugFormat(
894 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
895 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
896
897 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
898 }
899
900 // Tell the client we're ready to Xfer the file
901 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
902 Util.StringToBytes256(m_inventoryFileName));
903 }
881 } 904 }
882 905
883 /// <summary> 906 /// <summary>
@@ -1035,10 +1058,15 @@ namespace OpenSim.Region.Framework.Scenes
1035 item.BasePermissions = perms; 1058 item.BasePermissions = perms;
1036 } 1059 }
1037 } 1060 }
1061
1038 m_inventorySerial++; 1062 m_inventorySerial++;
1039 HasInventoryChanged = true; 1063 HasInventoryChanged = true;
1040 } 1064 }
1041 1065
1066 /// <summary>
1067 /// Returns true if this part inventory contains any scripts. False otherwise.
1068 /// </summary>
1069 /// <returns></returns>
1042 public bool ContainsScripts() 1070 public bool ContainsScripts()
1043 { 1071 {
1044 lock (m_items) 1072 lock (m_items)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index f231a39..5b02c3b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
70 { 70 {
71// ~ScenePresence() 71// ~ScenePresence()
72// { 72// {
73// m_log.Debug("[ScenePresence] Destructor called"); 73// m_log.Debug("[SCENE PRESENCE] Destructor called");
74// } 74// }
75 75
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -120,6 +120,8 @@ namespace OpenSim.Region.Framework.Scenes
120 /// </remarks> 120 /// </remarks>
121 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 121 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
122 122
123 public Object AttachmentsSyncLock { get; private set; }
124
123 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); 125 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
124 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; 126 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
125 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; 127 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
@@ -176,8 +178,6 @@ namespace OpenSim.Region.Framework.Scenes
176 178
177 private Quaternion m_bodyRot = Quaternion.Identity; 179 private Quaternion m_bodyRot = Quaternion.Identity;
178 180
179 private Quaternion m_bodyRotPrevious = Quaternion.Identity;
180
181 private const int LAND_VELOCITYMAG_MAX = 12; 181 private const int LAND_VELOCITYMAG_MAX = 12;
182 182
183 public bool IsRestrictedToRegion; 183 public bool IsRestrictedToRegion;
@@ -186,7 +186,6 @@ namespace OpenSim.Region.Framework.Scenes
186 186
187 private float m_health = 100f; 187 private float m_health = 100f;
188 188
189 protected RegionInfo m_regionInfo;
190 protected ulong crossingFromRegion; 189 protected ulong crossingFromRegion;
191 190
192 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 191 private readonly Vector3[] Dir_Vectors = new Vector3[9];
@@ -221,6 +220,11 @@ namespace OpenSim.Region.Framework.Scenes
221 public bool MovingToTarget { get; private set; } 220 public bool MovingToTarget { get; private set; }
222 public Vector3 MoveToPositionTarget { get; private set; } 221 public Vector3 MoveToPositionTarget { get; private set; }
223 222
223 /// <summary>
224 /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying).
225 /// </summary>
226 public bool LandAtTarget { get; private set; }
227
224 private bool m_followCamAuto; 228 private bool m_followCamAuto;
225 229
226 private int m_movementUpdateCount; 230 private int m_movementUpdateCount;
@@ -466,7 +470,13 @@ namespace OpenSim.Region.Framework.Scenes
466 { 470 {
467 PhysicsActor actor = m_physicsActor; 471 PhysicsActor actor = m_physicsActor;
468 if (actor != null) 472 if (actor != null)
473 {
469 m_pos = actor.Position; 474 m_pos = actor.Position;
475
476// m_log.DebugFormat(
477// "[SCENE PRESENCE]: Set position {0} for {1} in {2} via getting AbsolutePosition!",
478// m_pos, Name, Scene.RegionInfo.RegionName);
479 }
470 else 480 else
471 { 481 {
472 // Obtain the correct position of a seated avatar. 482 // Obtain the correct position of a seated avatar.
@@ -510,19 +520,26 @@ namespace OpenSim.Region.Framework.Scenes
510 } 520 }
511 catch (Exception e) 521 catch (Exception e)
512 { 522 {
513 m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message); 523 m_log.Error("[SCENE PRESENCE]: ABSOLUTE POSITION " + e.Message);
514 } 524 }
515 } 525 }
516 526
517 m_pos = value; 527 m_pos = value;
518 m_parentPosition = Vector3.Zero; 528 m_parentPosition = Vector3.Zero;
529
530// m_log.DebugFormat(
531// "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
532// Scene.RegionInfo.RegionName, Name, m_pos);
519 } 533 }
520 } 534 }
521 535
536 /// <summary>
537 /// If sitting, returns the offset position from the prim the avatar is sitting on.
538 /// Otherwise, returns absolute position in the scene.
539 /// </summary>
522 public Vector3 OffsetPosition 540 public Vector3 OffsetPosition
523 { 541 {
524 get { return m_pos; } 542 get { return m_pos; }
525 set { m_pos = value; }
526 } 543 }
527 544
528 /// <summary> 545 /// <summary>
@@ -534,8 +551,14 @@ namespace OpenSim.Region.Framework.Scenes
534 { 551 {
535 PhysicsActor actor = m_physicsActor; 552 PhysicsActor actor = m_physicsActor;
536 if (actor != null) 553 if (actor != null)
554 {
537 m_velocity = actor.Velocity; 555 m_velocity = actor.Velocity;
538 556
557// m_log.DebugFormat(
558// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
559// m_velocity, Name, Scene.RegionInfo.RegionName);
560 }
561
539 return m_velocity; 562 return m_velocity;
540 } 563 }
541 set 564 set
@@ -550,24 +573,26 @@ namespace OpenSim.Region.Framework.Scenes
550 } 573 }
551 catch (Exception e) 574 catch (Exception e)
552 { 575 {
553 m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message); 576 m_log.Error("[SCENE PRESENCE]: VELOCITY " + e.Message);
554 } 577 }
555 } 578 }
556 579
557 m_velocity = value; 580 m_velocity = value;
581
582// m_log.DebugFormat(
583// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
584// Scene.RegionInfo.RegionName, Name, m_velocity);
558 } 585 }
559 } 586 }
560 587
561 public Quaternion Rotation 588 public Quaternion Rotation
562 { 589 {
563 get { return m_bodyRot; } 590 get { return m_bodyRot; }
564 set { m_bodyRot = value; } 591 set
565 } 592 {
566 593 m_bodyRot = value;
567 public Quaternion PreviousRotation 594// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
568 { 595 }
569 get { return m_bodyRotPrevious; }
570 set { m_bodyRotPrevious = value; }
571 } 596 }
572 597
573 /// <summary> 598 /// <summary>
@@ -705,23 +730,24 @@ namespace OpenSim.Region.Framework.Scenes
705 #endregion 730 #endregion
706 731
707 #region Constructor(s) 732 #region Constructor(s)
708 733
709 public ScenePresence( 734 public ScenePresence(
710 IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance, PresenceType type) 735 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
711 { 736 {
737 AttachmentsSyncLock = new Object();
738
712 m_sendCourseLocationsMethod = SendCoarseLocationsDefault; 739 m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
713 m_sceneViewer = new SceneViewer(this); 740 m_sceneViewer = new SceneViewer(this);
714 m_animator = new ScenePresenceAnimator(this); 741 m_animator = new ScenePresenceAnimator(this);
715 PresenceType = type; 742 PresenceType = type;
716 m_DrawDistance = world.DefaultDrawDistance; 743 m_DrawDistance = world.DefaultDrawDistance;
717 m_rootRegionHandle = reginfo.RegionHandle; 744 m_rootRegionHandle = world.RegionInfo.RegionHandle;
718 m_controllingClient = client; 745 m_controllingClient = client;
719 m_firstname = m_controllingClient.FirstName; 746 m_firstname = m_controllingClient.FirstName;
720 m_lastname = m_controllingClient.LastName; 747 m_lastname = m_controllingClient.LastName;
721 m_name = String.Format("{0} {1}", m_firstname, m_lastname); 748 m_name = String.Format("{0} {1}", m_firstname, m_lastname);
722 m_scene = world; 749 m_scene = world;
723 m_uuid = client.AgentId; 750 m_uuid = client.AgentId;
724 m_regionInfo = reginfo;
725 m_localId = m_scene.AllocateLocalId(); 751 m_localId = m_scene.AllocateLocalId();
726 752
727 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 753 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
@@ -983,7 +1009,7 @@ namespace OpenSim.Region.Framework.Scenes
983 Animator.ResetAnimations(); 1009 Animator.ResetAnimations();
984 1010
985// m_log.DebugFormat( 1011// m_log.DebugFormat(
986// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1012// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
987// Name, UUID, m_scene.RegionInfo.RegionName); 1013// Name, UUID, m_scene.RegionInfo.RegionName);
988 1014
989 // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, 1015 // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
@@ -1150,9 +1176,9 @@ namespace OpenSim.Region.Framework.Scenes
1150 m_callbackURI = null; 1176 m_callbackURI = null;
1151 } 1177 }
1152 1178
1153 //m_log.DebugFormat("Completed movement"); 1179 //m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1154 1180
1155 m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); 1181 m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1156 SendInitialData(); 1182 SendInitialData();
1157 1183
1158 // Create child agents in neighbouring regions 1184 // Create child agents in neighbouring regions
@@ -1217,7 +1243,9 @@ namespace OpenSim.Region.Framework.Scenes
1217 /// </summary> 1243 /// </summary>
1218 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1244 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1219 { 1245 {
1220// m_log.DebugFormat("[SCENE PRESENCE]: Received agent update from {0}", remoteClient.Name); 1246// m_log.DebugFormat(
1247// "[SCENE PRESENCE]: In {0} received agent update from {1}",
1248// Scene.RegionInfo.RegionName, remoteClient.Name);
1221 1249
1222 //if (m_isChildAgent) 1250 //if (m_isChildAgent)
1223 //{ 1251 //{
@@ -1658,7 +1686,10 @@ namespace OpenSim.Region.Framework.Scenes
1658 /// This is to allow movement to targets that are known to be on an elevated platform with a continuous path 1686 /// This is to allow movement to targets that are known to be on an elevated platform with a continuous path
1659 /// from start to finish. 1687 /// from start to finish.
1660 /// </param> 1688 /// </param>
1661 public void MoveToTarget(Vector3 pos, bool noFly) 1689 /// <param name="landAtTarget">
1690 /// If true and the avatar starts flying during the move then land at the target.
1691 /// </param>
1692 public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget)
1662 { 1693 {
1663 m_log.DebugFormat( 1694 m_log.DebugFormat(
1664 "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}", 1695 "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
@@ -1684,7 +1715,7 @@ namespace OpenSim.Region.Framework.Scenes
1684 1715
1685 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 1716 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
1686 // always slightly higher than the actual terrain height. 1717 // always slightly higher than the actual terrain height.
1687 // FIXME: This constrains NOC movements as well, so should be somewhere else. 1718 // FIXME: This constrains NPC movements as well, so should be somewhere else.
1688 if (pos.Z - terrainHeight < 0.2) 1719 if (pos.Z - terrainHeight < 0.2)
1689 pos.Z = terrainHeight; 1720 pos.Z = terrainHeight;
1690 1721
@@ -1697,9 +1728,25 @@ namespace OpenSim.Region.Framework.Scenes
1697 else if (pos.Z > terrainHeight) 1728 else if (pos.Z > terrainHeight)
1698 PhysicsActor.Flying = true; 1729 PhysicsActor.Flying = true;
1699 1730
1731 LandAtTarget = landAtTarget;
1700 MovingToTarget = true; 1732 MovingToTarget = true;
1701 MoveToPositionTarget = pos; 1733 MoveToPositionTarget = pos;
1702 1734
1735 // Rotate presence around the z-axis to point in same direction as movement.
1736 // Ignore z component of vector
1737 Vector3 localVectorToTarget3D = pos - AbsolutePosition;
1738 Vector3 localVectorToTarget2D = new Vector3((float)(localVectorToTarget3D.X), (float)(localVectorToTarget3D.Y), 0f);
1739
1740// m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0}", localVectorToTarget2D);
1741
1742 // Calculate the yaw.
1743 Vector3 angle = new Vector3(0, 0, (float)(Math.Atan2(localVectorToTarget2D.Y, localVectorToTarget2D.X)));
1744
1745// m_log.DebugFormat("[SCENE PRESENCE]: Angle is {0}", angle);
1746
1747 Rotation = Quaternion.CreateFromEulers(angle);
1748// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation);
1749
1703 Vector3 agent_control_v3 = new Vector3(); 1750 Vector3 agent_control_v3 = new Vector3();
1704 HandleMoveToTargetUpdate(ref agent_control_v3); 1751 HandleMoveToTargetUpdate(ref agent_control_v3);
1705 AddNewMovement(agent_control_v3); 1752 AddNewMovement(agent_control_v3);
@@ -2389,7 +2436,7 @@ namespace OpenSim.Region.Framework.Scenes
2389 Vector3 pos = m_pos; 2436 Vector3 pos = m_pos;
2390 pos.Z += m_appearance.HipOffset; 2437 pos.Z += m_appearance.HipOffset;
2391 2438
2392 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); 2439 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
2393 2440
2394 remoteClient.SendPrimUpdate( 2441 remoteClient.SendPrimUpdate(
2395 this, 2442 this,
@@ -2476,6 +2523,7 @@ namespace OpenSim.Region.Framework.Scenes
2476 /// </summary> 2523 /// </summary>
2477 private void SendInitialData() 2524 private void SendInitialData()
2478 { 2525 {
2526 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
2479 // Moved this into CompleteMovement to ensure that m_appearance is initialized before 2527 // Moved this into CompleteMovement to ensure that m_appearance is initialized before
2480 // the inventory arrives 2528 // the inventory arrives
2481 // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); 2529 // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
@@ -2520,10 +2568,11 @@ namespace OpenSim.Region.Framework.Scenes
2520 /// </summary> 2568 /// </summary>
2521 public void SendAvatarDataToAllAgents() 2569 public void SendAvatarDataToAllAgents()
2522 { 2570 {
2571 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
2523 // only send update from root agents to other clients; children are only "listening posts" 2572 // only send update from root agents to other clients; children are only "listening posts"
2524 if (IsChildAgent) 2573 if (IsChildAgent)
2525 { 2574 {
2526 m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); 2575 m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent");
2527 return; 2576 return;
2528 } 2577 }
2529 2578
@@ -2573,7 +2622,7 @@ namespace OpenSim.Region.Framework.Scenes
2573 /// <param name="avatar"></param> 2622 /// <param name="avatar"></param>
2574 public void SendAvatarDataToAgent(ScenePresence avatar) 2623 public void SendAvatarDataToAgent(ScenePresence avatar)
2575 { 2624 {
2576// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); 2625 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2577 2626
2578 avatar.ControllingClient.SendAvatarDataImmediate(this); 2627 avatar.ControllingClient.SendAvatarDataImmediate(this);
2579 if (Animator != null) 2628 if (Animator != null)
@@ -2586,10 +2635,11 @@ namespace OpenSim.Region.Framework.Scenes
2586 /// </summary> 2635 /// </summary>
2587 public void SendAppearanceToAllOtherAgents() 2636 public void SendAppearanceToAllOtherAgents()
2588 { 2637 {
2638 m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} ({1})", Name, UUID);
2589 // only send update from root agents to other clients; children are only "listening posts" 2639 // only send update from root agents to other clients; children are only "listening posts"
2590 if (IsChildAgent) 2640 if (IsChildAgent)
2591 { 2641 {
2592 m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); 2642 m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent");
2593 return; 2643 return;
2594 } 2644 }
2595 2645
@@ -2615,6 +2665,7 @@ namespace OpenSim.Region.Framework.Scenes
2615 /// </summary> 2665 /// </summary>
2616 public void SendOtherAgentsAppearanceToMe() 2666 public void SendOtherAgentsAppearanceToMe()
2617 { 2667 {
2668 //m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID);
2618 m_perfMonMS = Util.EnvironmentTickCount(); 2669 m_perfMonMS = Util.EnvironmentTickCount();
2619 2670
2620 int count = 0; 2671 int count = 0;
@@ -2873,8 +2924,8 @@ namespace OpenSim.Region.Framework.Scenes
2873 /// </returns> 2924 /// </returns>
2874 protected int HaveNeighbor(Cardinals car, ref int[] fix) 2925 protected int HaveNeighbor(Cardinals car, ref int[] fix)
2875 { 2926 {
2876 uint neighbourx = m_regionInfo.RegionLocX; 2927 uint neighbourx = m_scene.RegionInfo.RegionLocX;
2877 uint neighboury = m_regionInfo.RegionLocY; 2928 uint neighboury = m_scene.RegionInfo.RegionLocY;
2878 2929
2879 int dir = (int)car; 2930 int dir = (int)car;
2880 2931
@@ -2894,8 +2945,8 @@ namespace OpenSim.Region.Framework.Scenes
2894 2945
2895 if (neighbourRegion == null) 2946 if (neighbourRegion == null)
2896 { 2947 {
2897 fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); 2948 fix[0] = (int)(m_scene.RegionInfo.RegionLocX - neighbourx);
2898 fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); 2949 fix[1] = (int)(m_scene.RegionInfo.RegionLocY - neighboury);
2899 return dir * (-1); 2950 return dir * (-1);
2900 } 2951 }
2901 else 2952 else
@@ -3141,26 +3192,30 @@ namespace OpenSim.Region.Framework.Scenes
3141 catch { } 3192 catch { }
3142 3193
3143 // Attachment objects 3194 // Attachment objects
3144 if (m_attachments != null && m_attachments.Count > 0) 3195 lock (m_attachments)
3145 { 3196 {
3146 cAgent.AttachmentObjects = new List<ISceneObject>(); 3197 if (m_attachments.Count > 0)
3147 cAgent.AttachmentObjectStates = new List<string>();
3148// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3149 m_InTransitScriptStates.Clear();
3150 foreach (SceneObjectGroup sog in m_attachments)
3151 { 3198 {
3152 // We need to make a copy and pass that copy 3199 cAgent.AttachmentObjects = new List<ISceneObject>();
3153 // because of transfers withn the same sim 3200 cAgent.AttachmentObjectStates = new List<string>();
3154 ISceneObject clone = sog.CloneForNewScene(); 3201 // IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3155 // Attachment module assumes that GroupPosition holds the offsets...! 3202 m_InTransitScriptStates.Clear();
3156 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos; 3203
3157 ((SceneObjectGroup)clone).IsAttachment = false; 3204 foreach (SceneObjectGroup sog in m_attachments)
3158 cAgent.AttachmentObjects.Add(clone); 3205 {
3159 string state = sog.GetStateSnapshot(); 3206 // We need to make a copy and pass that copy
3160 cAgent.AttachmentObjectStates.Add(state); 3207 // because of transfers withn the same sim
3161 m_InTransitScriptStates.Add(state); 3208 ISceneObject clone = sog.CloneForNewScene();
3162 // Let's remove the scripts of the original object here 3209 // Attachment module assumes that GroupPosition holds the offsets...!
3163 sog.RemoveScriptInstances(true); 3210 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
3211 ((SceneObjectGroup)clone).IsAttachment = false;
3212 cAgent.AttachmentObjects.Add(clone);
3213 string state = sog.GetStateSnapshot();
3214 cAgent.AttachmentObjectStates.Add(state);
3215 m_InTransitScriptStates.Add(state);
3216 // Let's remove the scripts of the original object here
3217 sog.RemoveScriptInstances(true);
3218 }
3164 } 3219 }
3165 } 3220 }
3166 } 3221 }
@@ -3277,6 +3332,10 @@ namespace OpenSim.Region.Framework.Scenes
3277 /// </summary> 3332 /// </summary>
3278 public void AddToPhysicalScene(bool isFlying) 3333 public void AddToPhysicalScene(bool isFlying)
3279 { 3334 {
3335// m_log.DebugFormat(
3336// "[SCENE PRESENCE]: Adding physics actor for {0}, ifFlying = {1} in {2}",
3337// Name, isFlying, Scene.RegionInfo.RegionName);
3338
3280 if (m_appearance.AvatarHeight == 0) 3339 if (m_appearance.AvatarHeight == 0)
3281 m_appearance.SetHeight(); 3340 m_appearance.SetHeight();
3282 3341
@@ -3317,7 +3376,7 @@ namespace OpenSim.Region.Framework.Scenes
3317 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3376 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3318 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents( 3377 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3319 // as of this comment the interval is set in AddToPhysicalScene 3378 // as of this comment the interval is set in AddToPhysicalScene
3320 if (Animator!=null) 3379 if (Animator != null)
3321 Animator.UpdateMovementAnimations(); 3380 Animator.UpdateMovementAnimations();
3322 3381
3323 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3382 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
@@ -3398,7 +3457,8 @@ namespace OpenSim.Region.Framework.Scenes
3398 3457
3399 public void Close() 3458 public void Close()
3400 { 3459 {
3401 m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false); 3460 if (!IsChildAgent)
3461 m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
3402 3462
3403 lock (m_knownChildRegions) 3463 lock (m_knownChildRegions)
3404 { 3464 {
@@ -3501,8 +3561,10 @@ namespace OpenSim.Region.Framework.Scenes
3501 /// <summary> 3561 /// <summary>
3502 /// This is currently just being done for information. 3562 /// This is currently just being done for information.
3503 /// </summary> 3563 /// </summary>
3504 public void ValidateAttachments() 3564 public bool ValidateAttachments()
3505 { 3565 {
3566 bool validated = true;
3567
3506 lock (m_attachments) 3568 lock (m_attachments)
3507 { 3569 {
3508 // Validate 3570 // Validate
@@ -3512,15 +3574,21 @@ namespace OpenSim.Region.Framework.Scenes
3512 { 3574 {
3513 m_log.WarnFormat( 3575 m_log.WarnFormat(
3514 "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name); 3576 "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name);
3577
3578 validated = false;
3515 } 3579 }
3516 else if (gobj.IsDeleted) 3580 else if (gobj.IsDeleted)
3517 { 3581 {
3518 m_log.WarnFormat( 3582 m_log.WarnFormat(
3519 "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted. Continuing", 3583 "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted. Continuing",
3520 gobj.Name, gobj.UUID, Name); 3584 gobj.Name, gobj.UUID, Name);
3585
3586 validated = false;
3521 } 3587 }
3522 } 3588 }
3523 } 3589 }
3590
3591 return validated;
3524 } 3592 }
3525 3593
3526 /// <summary> 3594 /// <summary>
@@ -3552,29 +3620,6 @@ namespace OpenSim.Region.Framework.Scenes
3552 } 3620 }
3553 } 3621 }
3554 3622
3555
3556 public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
3557 {
3558 m_controllingClient = client;
3559 m_regionInfo = region;
3560 m_scene = scene;
3561
3562 RegisterToEvents();
3563
3564 /*
3565 AbsolutePosition = client.StartPos;
3566
3567 Animations = new AvatarAnimations();
3568 Animations.LoadAnims();
3569
3570 m_animations = new List<UUID>();
3571 m_animations.Add(Animations.AnimsUUID["STAND"]);
3572 m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
3573
3574 SetDirectionVectors();
3575 */
3576 }
3577
3578 internal void PushForce(Vector3 impulse) 3623 internal void PushForce(Vector3 impulse)
3579 { 3624 {
3580 if (PhysicsActor != null) 3625 if (PhysicsActor != null)
@@ -3602,6 +3647,7 @@ namespace OpenSim.Region.Framework.Scenes
3602 obj.ignoreControls = (ScriptControlled)controls; 3647 obj.ignoreControls = (ScriptControlled)controls;
3603 obj.eventControls = (ScriptControlled)controls; 3648 obj.eventControls = (ScriptControlled)controls;
3604 } 3649 }
3650
3605 if (pass_on == 1 && accept == 1) 3651 if (pass_on == 1 && accept == 1)
3606 { 3652 {
3607 IgnoredControls = ScriptControlled.CONTROL_ZERO; 3653 IgnoredControls = ScriptControlled.CONTROL_ZERO;
@@ -3622,6 +3668,7 @@ namespace OpenSim.Region.Framework.Scenes
3622 scriptedcontrols[Script_item_UUID] = obj; 3668 scriptedcontrols[Script_item_UUID] = obj;
3623 } 3669 }
3624 } 3670 }
3671
3625 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); 3672 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
3626 } 3673 }
3627 3674
@@ -3803,4 +3850,4 @@ namespace OpenSim.Region.Framework.Scenes
3803 } 3850 }
3804 } 3851 }
3805 } 3852 }
3806} \ No newline at end of file 3853}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 1ea2329..80f198d 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -52,22 +52,25 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 TestHelpers.InMethod(); 52 TestHelpers.InMethod();
53 53
54 Scene scene = SceneHelpers.SetupScene(); 54 Scene scene = SceneHelpers.SetupScene();
55 int partsToTestCount = 3;
55 56
56 string objName = "obj1"; 57 SceneObjectGroup so
57 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); 58 = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
58 59 SceneObjectPart[] parts = so.Parts;
59 SceneObjectPart part
60 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
61 { Name = objName, UUID = objUuid };
62 60
63 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part), false), Is.True); 61 Assert.That(scene.AddNewSceneObject(so, false), Is.True);
64 62 SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID);
65 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid); 63 SceneObjectPart[] retrievedParts = retrievedSo.Parts;
66 64
67 //m_log.Debug("retrievedPart : {0}", retrievedPart); 65 //m_log.Debug("retrievedPart : {0}", retrievedPart);
68 // If the parts have the same UUID then we will consider them as one and the same 66 // If the parts have the same UUID then we will consider them as one and the same
69 Assert.That(retrievedPart.Name, Is.EqualTo(objName)); 67 Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount));
70 Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); 68
69 for (int i = 0; i < partsToTestCount; i++)
70 {
71 Assert.That(retrievedParts[i].Name, Is.EqualTo(parts[i].Name));
72 Assert.That(retrievedParts[i].UUID, Is.EqualTo(parts[i].UUID));
73 }
71 } 74 }
72 75
73 [Test] 76 [Test]
@@ -103,6 +106,39 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name)); 106 Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name));
104 Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); 107 Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid));
105 } 108 }
109
110 /// <summary>
111 /// Test retrieving a scene object via the local id of one of its parts.
112 /// </summary>
113 [Test]
114 public void TestGetSceneObjectByPartLocalId()
115 {
116 TestHelpers.InMethod();
117
118 Scene scene = SceneHelpers.SetupScene();
119 int partsToTestCount = 3;
120
121 SceneObjectGroup so
122 = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
123 SceneObjectPart[] parts = so.Parts;
124
125 scene.AddNewSceneObject(so, false);
126
127 // Test getting via the root part's local id
128 Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Not.Null);
129
130 // Test getting via a non root part's local id
131 Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Not.Null);
132
133 // Test that we don't get back an object for a local id that doesn't exist
134 Assert.That(scene.GetGroupByPrim(999), Is.Null);
135
136 // Now delete the scene object and check again
137 scene.DeleteSceneObject(so, false);
138
139 Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Null);
140 Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Null);
141 }
106 142
107 /// <summary> 143 /// <summary>
108 /// Test deleting an object from a scene. 144 /// Test deleting an object from a scene.
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
new file mode 100644
index 0000000..64c36ff
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
@@ -0,0 +1,135 @@
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 Nini.Config;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Tests.Common;
40using OpenSim.Tests.Common.Mock;
41
42namespace OpenSim.Region.Framework.Scenes.Tests
43{
44 [TestFixture]
45 public class ScenePresenceAutopilotTests
46 {
47 private TestScene m_scene;
48
49 [TestFixtureSetUp]
50 public void FixtureInit()
51 {
52 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
53 Util.FireAndForgetMethod = FireAndForgetMethod.None;
54 }
55
56 [TestFixtureTearDown]
57 public void TearDown()
58 {
59 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
60 // threads. Possibly, later tests should be rewritten not to worry about such things.
61 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
62 }
63
64 [SetUp]
65 public void Init()
66 {
67 m_scene = SceneHelpers.SetupScene();
68 }
69
70 [Test]
71 public void TestMove()
72 {
73 TestHelpers.InMethod();
74// log4net.Config.XmlConfigurator.Configure();
75
76 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
77
78 Vector3 startPos = sp.AbsolutePosition;
79// Vector3 startPos = new Vector3(128, 128, 30);
80
81 // For now, we'll make the scene presence fly to simplify this test, but this needs to change.
82 sp.PhysicsActor.Flying = true;
83
84 m_scene.Update();
85 Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos));
86
87 Vector3 targetPos = startPos + new Vector3(0, 10, 0);
88 sp.MoveToTarget(targetPos, false, false);
89
90 Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos));
91 Assert.That(
92 sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
93
94 m_scene.Update();
95
96 // We should really check the exact figure.
97 Assert.That(sp.AbsolutePosition.X, Is.EqualTo(startPos.X));
98 Assert.That(sp.AbsolutePosition.Y, Is.GreaterThan(startPos.Y));
99 Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
100 Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X));
101
102 for (int i = 0; i < 10; i++)
103 m_scene.Update();
104
105 double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
106 Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move");
107 Assert.That(sp.AbsolutePosition, Is.EqualTo(targetPos));
108 Assert.That(sp.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE));
109
110 // Try a second movement
111 startPos = sp.AbsolutePosition;
112 targetPos = startPos + new Vector3(10, 0, 0);
113 sp.MoveToTarget(targetPos, false, false);
114
115 Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos));
116 Assert.That(
117 sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001));
118
119 m_scene.Update();
120
121 // We should really check the exact figure.
122 Assert.That(sp.AbsolutePosition.X, Is.GreaterThan(startPos.X));
123 Assert.That(sp.AbsolutePosition.X, Is.LessThan(targetPos.X));
124 Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
125 Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
126
127 for (int i = 0; i < 10; i++)
128 m_scene.Update();
129
130 distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
131 Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move");
132 Assert.That(sp.AbsolutePosition, Is.EqualTo(targetPos));
133 }
134 }
135} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 77b1535..3acdaf8 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -43,11 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 /// <summary> 43 /// <summary>
44 /// Gather uuids for a given entity. 44 /// Gather uuids for a given entity.
45 /// </summary> 45 /// </summary>
46 /// 46 /// <remarks>
47 /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts 47 /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts
48 /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets 48 /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets
49 /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be 49 /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be
50 /// retrieved to work out which assets it references). 50 /// retrieved to work out which assets it references).
51 /// </remarks>
51 public class UuidGatherer 52 public class UuidGatherer
52 { 53 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -76,11 +77,11 @@ namespace OpenSim.Region.Framework.Scenes
76 /// <summary> 77 /// <summary>
77 /// Gather all the asset uuids associated with the asset referenced by a given uuid 78 /// Gather all the asset uuids associated with the asset referenced by a given uuid
78 /// </summary> 79 /// </summary>
79 /// 80 /// <remarks>
80 /// This includes both those directly associated with 81 /// This includes both those directly associated with
81 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained 82 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
82 /// within this object). 83 /// within this object).
83 /// 84 /// </remarks>
84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 85 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
85 /// <param name="assetType">The type of the asset for the uuid given</param> 86 /// <param name="assetType">The type of the asset for the uuid given</param>
86 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
@@ -123,11 +124,11 @@ namespace OpenSim.Region.Framework.Scenes
123 /// <summary> 124 /// <summary>
124 /// Gather all the asset uuids associated with a given object. 125 /// Gather all the asset uuids associated with a given object.
125 /// </summary> 126 /// </summary>
126 /// 127 /// <remarks>
127 /// This includes both those directly associated with 128 /// This includes both those directly associated with
128 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained 129 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
129 /// within this object). 130 /// within this object).
130 /// 131 /// </remarks>
131 /// <param name="sceneObject">The scene object for which to gather assets</param> 132 /// <param name="sceneObject">The scene object for which to gather assets</param>
132 /// <param name="assetUuids">The assets gathered</param> 133 /// <param name="assetUuids">The assets gathered</param>
133 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 134 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids)
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index c413634..f6656c2 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -806,7 +806,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
806 public event ScriptReset OnScriptReset; 806 public event ScriptReset OnScriptReset;
807 public event GetScriptRunning OnGetScriptRunning; 807 public event GetScriptRunning OnGetScriptRunning;
808 public event SetScriptRunning OnSetScriptRunning; 808 public event SetScriptRunning OnSetScriptRunning;
809 public event Action<Vector3, bool> OnAutoPilotGo; 809 public event Action<Vector3, bool, bool> OnAutoPilotGo;
810 public event TerrainUnacked OnUnackedTerrain; 810 public event TerrainUnacked OnUnackedTerrain;
811 public event ActivateGesture OnActivateGesture; 811 public event ActivateGesture OnActivateGesture;
812 public event DeactivateGesture OnDeactivateGesture; 812 public event DeactivateGesture OnDeactivateGesture;
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 31e79fa..edb618e 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -37,11 +37,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
37{ 37{
38 public class NPCAvatar : IClientAPI 38 public class NPCAvatar : IClientAPI
39 { 39 {
40 /// <summary>
41 /// Signal whether the avatar should land when it reaches a move target
42 /// </summary>
43 public bool LandAtTarget { get; set; }
44
45 private readonly string m_firstname; 40 private readonly string m_firstname;
46 private readonly string m_lastname; 41 private readonly string m_lastname;
47 private readonly Vector3 m_startPos; 42 private readonly Vector3 m_startPos;
@@ -333,7 +328,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
333 public event ScriptReset OnScriptReset; 328 public event ScriptReset OnScriptReset;
334 public event GetScriptRunning OnGetScriptRunning; 329 public event GetScriptRunning OnGetScriptRunning;
335 public event SetScriptRunning OnSetScriptRunning; 330 public event SetScriptRunning OnSetScriptRunning;
336 public event Action<Vector3, bool> OnAutoPilotGo; 331 public event Action<Vector3, bool, bool> OnAutoPilotGo;
337 332
338 public event TerrainUnacked OnUnackedTerrain; 333 public event TerrainUnacked OnUnackedTerrain;
339 334
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 2fdeeab..bcd9e94 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -53,78 +53,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
53 if (config != null && config.GetBoolean("Enabled", false)) 53 if (config != null && config.GetBoolean("Enabled", false))
54 { 54 {
55 scene.RegisterModuleInterface<INPCModule>(this); 55 scene.RegisterModuleInterface<INPCModule>(this);
56 scene.EventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
57 }
58 }
59
60 public void HandleOnSignificantClientMovement(ScenePresence presence)
61 {
62 lock (m_avatars)
63 {
64 if (m_avatars.ContainsKey(presence.UUID) && presence.MovingToTarget)
65 {
66 double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget);
67// m_log.DebugFormat(
68// "[NPC MODULE]: Abs pos of {0} is {1}, target {2}, distance {3}",
69// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget);
70
71 // Check the error term of the current position in relation to the target position
72 if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT)
73 {
74 // We are close enough to the target
75 m_log.DebugFormat("[NPC MODULE]: Stopping movement of npc {0}", presence.Name);
76
77 presence.Velocity = Vector3.Zero;
78 presence.AbsolutePosition = presence.MoveToPositionTarget;
79 presence.ResetMoveToTarget();
80
81 if (presence.PhysicsActor.Flying)
82 {
83 // A horrible hack to stop the NPC dead in its tracks rather than having them overshoot
84 // the target if flying.
85 // We really need to be more subtle (slow the avatar as it approaches the target) or at
86 // least be able to set collision status once, rather than 5 times to give it enough
87 // weighting so that that PhysicsActor thinks it really is colliding.
88 for (int i = 0; i < 5; i++)
89 presence.PhysicsActor.IsColliding = true;
90
91// Vector3 targetPos = presence.MoveToPositionTarget;
92 if (m_avatars[presence.UUID].LandAtTarget)
93 presence.PhysicsActor.Flying = false;
94
95// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y];
96// if (targetPos.Z - terrainHeight < 0.2)
97// {
98// presence.PhysicsActor.Flying = false;
99// }
100 }
101
102// m_log.DebugFormat(
103// "[NPC MODULE]: AgentControlFlags {0}, MovementFlag {1} for {2}",
104// presence.AgentControlFlags, presence.MovementFlag, presence.Name);
105 }
106 else
107 {
108// m_log.DebugFormat(
109// "[NPC MODULE]: Updating npc {0} at {1} for next movement to {2}",
110// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget);
111
112 Vector3 agent_control_v3 = new Vector3();
113 presence.HandleMoveToTargetUpdate(ref agent_control_v3);
114 presence.AddNewMovement(agent_control_v3);
115 }
116//
117//// presence.DoMoveToPositionUpdate((0, presence.MoveToPositionTarget, null);
118
119//
120//
121
122 }
123 } 56 }
124 } 57 }
125 58
126 public bool IsNPC(UUID agentId, Scene scene) 59 public bool IsNPC(UUID agentId, Scene scene)
127 { 60 {
61 // FIXME: This implementation could not just use the ScenePresence.PresenceType (and callers could inspect
62 // that directly).
128 ScenePresence sp = scene.GetScenePresence(agentId); 63 ScenePresence sp = scene.GetScenePresence(agentId);
129 if (sp == null || sp.IsChildAgent) 64 if (sp == null || sp.IsChildAgent)
130 return false; 65 return false;
@@ -218,8 +153,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
218 "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", 153 "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
219 sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); 154 sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
220 155
221 m_avatars[agentID].LandAtTarget = landAtTarget; 156 sp.MoveToTarget(pos, noFly, landAtTarget);
222 sp.MoveToTarget(pos, noFly);
223 157
224 return true; 158 return true;
225 } 159 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 246bc34..1a0d0c7 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -182,18 +182,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
182 scene.Update(); 182 scene.Update();
183 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); 183 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
184 184
185 Vector3 targetPos = startPos + new Vector3(0, 0, 10); 185 Vector3 targetPos = startPos + new Vector3(0, 10, 0);
186 npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false); 186 npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false);
187 187
188 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); 188 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
189 //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f)));
190 Assert.That(
191 npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001));
189 192
190 scene.Update(); 193 scene.Update();
191 194
192 // We should really check the exact figure. 195 // We should really check the exact figure.
193 Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X)); 196 Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X));
194 Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y)); 197 Assert.That(npc.AbsolutePosition.Y, Is.GreaterThan(startPos.Y));
195 Assert.That(npc.AbsolutePosition.Z, Is.GreaterThan(startPos.Z)); 198 Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
196 Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.Z)); 199 Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X));
197 200
198 for (int i = 0; i < 10; i++) 201 for (int i = 0; i < 10; i++)
199 scene.Update(); 202 scene.Update();
@@ -208,6 +211,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
208 targetPos = startPos + new Vector3(10, 0, 0); 211 targetPos = startPos + new Vector3(10, 0, 0);
209 npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false); 212 npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false);
210 213
214 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
215// Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0, 1)));
216 Assert.That(
217 npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001));
218
211 scene.Update(); 219 scene.Update();
212 220
213 // We should really check the exact figure. 221 // We should really check the exact figure.
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs
deleted file mode 100644
index 2830325..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
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.Reflection;
29using System.Runtime.InteropServices;
30
31// Information about this assembly is defined by the following
32// attributes.
33//
34// change them to the information which is associated with the assembly
35// you compile.
36
37[assembly : AssemblyTitle("BulletDotNETPlugin")]
38[assembly : AssemblyDescription("")]
39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("OdePlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")]
45
46// This sets the default COM visibility of types in the assembly to invisible.
47// If you need to expose a type to COM, use [ComVisible(true)] on that type.
48
49[assembly : ComVisible(false)]
50
51// The assembly version has following format :
52//
53// Major.Minor.Build.Revision
54//
55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default):
57
58[assembly : AssemblyVersion("0.6.3.*")]
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
deleted file mode 100644
index ac4e2b9..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
+++ /dev/null
@@ -1,1191 +0,0 @@
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.Reflection;
30using BulletDotNET;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34using log4net;
35
36namespace OpenSim.Region.Physics.BulletDotNETPlugin
37{
38 public class BulletDotNETCharacter : PhysicsActor
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 public btRigidBody Body;
43 public btCollisionShape Shell;
44 public btVector3 tempVector1;
45 public btVector3 tempVector2;
46 public btVector3 tempVector3;
47 public btVector3 tempVector4;
48
49 public btVector3 tempVector5RayCast;
50 public btVector3 tempVector6RayCast;
51 public btVector3 tempVector7RayCast;
52
53 public btQuaternion tempQuat1;
54 public btTransform tempTrans1;
55
56 public ClosestNotMeRayResultCallback ClosestCastResult;
57 private btTransform m_bodyTransform;
58 private btVector3 m_bodyPosition;
59 private btVector3 m_CapsuleOrientationAxis;
60 private btQuaternion m_bodyOrientation;
61 private btDefaultMotionState m_bodyMotionState;
62 private btGeneric6DofConstraint m_aMotor;
63 // private Vector3 m_movementComparision;
64 private Vector3 m_position;
65 private Vector3 m_zeroPosition;
66 private bool m_zeroFlag = false;
67 private bool m_lastUpdateSent = false;
68 private Vector3 m_velocity;
69 private Vector3 m_target_velocity;
70 private Vector3 m_acceleration;
71 private Vector3 m_rotationalVelocity;
72 private bool m_pidControllerActive = true;
73 public float PID_D = 80.0f;
74 public float PID_P = 90.0f;
75 public float CAPSULE_RADIUS = 0.37f;
76 public float CAPSULE_LENGTH = 2.140599f;
77 public float heightFudgeFactor = 0.52f;
78 public float walkDivisor = 1.3f;
79 public float runDivisor = 0.8f;
80 private float m_mass = 80f;
81 public float m_density = 60f;
82 private bool m_flying = false;
83 private bool m_iscolliding = false;
84 private bool m_iscollidingGround = false;
85 private bool m_wascolliding = false;
86 private bool m_wascollidingGround = false;
87 private bool m_iscollidingObj = false;
88 private bool m_alwaysRun = false;
89 private bool m_hackSentFall = false;
90 private bool m_hackSentFly = false;
91 public uint m_localID = 0;
92 public bool m_returnCollisions = false;
93 // taints and their non-tainted counterparts
94 public bool m_isPhysical = false; // the current physical status
95 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
96 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
97 private bool m_taintRemove = false;
98 // private bool m_taintedPosition = false;
99 // private Vector3 m_taintedPosition_value;
100 private Vector3 m_taintedForce;
101
102 private float m_buoyancy = 0f;
103
104 // private CollisionLocker ode;
105
106 // private string m_name = String.Empty;
107
108 private bool[] m_colliderarr = new bool[11];
109 private bool[] m_colliderGroundarr = new bool[11];
110
111 private BulletDotNETScene m_parent_scene;
112
113 public int m_eventsubscription = 0;
114 private CollisionEventUpdate CollisionEventsThisFrame = null;
115 private int m_requestedUpdateFrequency = 0;
116
117 public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
118 {
119 m_position = pos;
120 m_zeroPosition = pos;
121 m_parent_scene = parent_scene;
122 PID_D = pid_d;
123 PID_P = pid_p;
124 CAPSULE_RADIUS = capsule_radius;
125 m_density = density;
126 heightFudgeFactor = height_fudge_factor;
127 walkDivisor = walk_divisor;
128 runDivisor = rundivisor;
129
130 for (int i = 0; i < 11; i++)
131 {
132 m_colliderarr[i] = false;
133 }
134 for (int i = 0; i < 11; i++)
135 {
136 m_colliderGroundarr[i] = false;
137 }
138 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
139 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
140 m_isPhysical = false; // current status: no ODE information exists
141 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
142
143 m_parent_scene.AddPhysicsActorTaint(this);
144
145 // m_name = avName;
146 tempVector1 = new btVector3(0, 0, 0);
147 tempVector2 = new btVector3(0, 0, 0);
148 tempVector3 = new btVector3(0, 0, 0);
149 tempVector4 = new btVector3(0, 0, 0);
150
151 tempVector5RayCast = new btVector3(0, 0, 0);
152 tempVector6RayCast = new btVector3(0, 0, 0);
153 tempVector7RayCast = new btVector3(0, 0, 0);
154
155 tempQuat1 = new btQuaternion(0, 0, 0, 1);
156 tempTrans1 = new btTransform(tempQuat1, tempVector1);
157 // m_movementComparision = new PhysicsVector(0, 0, 0);
158 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
159 }
160
161 /// <summary>
162 /// This creates the Avatar's physical Surrogate at the position supplied
163 /// </summary>
164 /// <param name="npositionX"></param>
165 /// <param name="npositionY"></param>
166 /// <param name="npositionZ"></param>
167
168 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
169 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
170 // place that is safe to call this routine AvatarGeomAndBodyCreation.
171 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
172 {
173
174 if (CAPSULE_LENGTH <= 0)
175 {
176 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
177 CAPSULE_LENGTH = 0.01f;
178
179 }
180
181 if (CAPSULE_RADIUS <= 0)
182 {
183 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
184 CAPSULE_RADIUS = 0.01f;
185
186 }
187
188 Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
189
190 if (m_bodyPosition == null)
191 m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
192
193 m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
194
195 if (m_bodyOrientation == null)
196 m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
197
198 if (m_bodyTransform == null)
199 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
200 else
201 {
202 m_bodyTransform.Dispose();
203 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
204 }
205
206 if (m_bodyMotionState == null)
207 m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
208 else
209 m_bodyMotionState.setWorldTransform(m_bodyTransform);
210
211 m_mass = Mass;
212
213 Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
214 // this is used for self identification. User localID instead of body handle
215 Body.setUserPointer(new IntPtr((int)m_localID));
216
217 if (ClosestCastResult != null)
218 ClosestCastResult.Dispose();
219 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
220
221 m_parent_scene.AddRigidBody(Body);
222 Body.setActivationState(4);
223 if (m_aMotor != null)
224 {
225 if (m_aMotor.Handle != IntPtr.Zero)
226 {
227 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
228 m_aMotor.Dispose();
229 }
230 m_aMotor = null;
231 }
232
233 m_aMotor = new btGeneric6DofConstraint(Body, m_parent_scene.TerrainBody,
234 m_parent_scene.TransZero,
235 m_parent_scene.TransZero, false);
236 m_aMotor.setAngularLowerLimit(m_parent_scene.VectorZero);
237 m_aMotor.setAngularUpperLimit(m_parent_scene.VectorZero);
238
239
240 }
241 public void Remove()
242 {
243 m_taintRemove = true;
244 }
245 public override bool Stopped
246 {
247 get { return m_zeroFlag; }
248 }
249
250 public override Vector3 Size
251 {
252 get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
253 set
254 {
255 m_pidControllerActive = true;
256
257 Vector3 SetSize = value;
258 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
259 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
260
261 Velocity = Vector3.Zero;
262
263 m_parent_scene.AddPhysicsActorTaint(this);
264 }
265 }
266
267 /// <summary>
268 /// turn the PID controller on or off.
269 /// The PID Controller will turn on all by itself in many situations
270 /// </summary>
271 /// <param name="status"></param>
272 public void SetPidStatus(bool status)
273 {
274 m_pidControllerActive = status;
275 }
276
277 public override PrimitiveBaseShape Shape
278 {
279 set { return; }
280 }
281
282 public override uint LocalID
283 {
284 set { m_localID = value; }
285 }
286
287 public override bool Grabbed
288 {
289 set { return; }
290 }
291
292 public override bool Selected
293 {
294 set { return; }
295 }
296
297
298 public override void CrossingFailure()
299 {
300
301 }
302
303 public override void link(PhysicsActor obj)
304 {
305
306 }
307
308 public override void delink()
309 {
310
311 }
312
313 public override void LockAngularMotion(Vector3 axis)
314 {
315
316 }
317
318 public override Vector3 Position
319 {
320 get { return m_position; }
321 set
322 {
323 // m_taintedPosition_value = value;
324 m_position = value;
325 // m_taintedPosition = true;
326 }
327 }
328
329 public override float Mass
330 {
331 get
332 {
333 float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
334 return m_density * AVvolume;
335 }
336 }
337
338 public override Vector3 Force
339 {
340 get { return m_target_velocity; }
341 set { return; }
342 }
343
344 public override int VehicleType
345 {
346 get { return 0; }
347 set { return; }
348 }
349
350 public override void VehicleFloatParam(int param, float value)
351 {
352
353 }
354
355 public override void VehicleVectorParam(int param, Vector3 value)
356 {
357
358 }
359
360 public override void VehicleRotationParam(int param, Quaternion rotation)
361 {
362
363 }
364
365 public override void VehicleFlags(int param, bool remove)
366 {
367
368 }
369
370 public override void SetVolumeDetect(int param)
371 {
372
373 }
374
375 public override Vector3 GeometricCenter
376 {
377 get { return Vector3.Zero; }
378 }
379
380 public override Vector3 CenterOfMass
381 {
382 get { return Vector3.Zero; }
383 }
384
385 public override Vector3 Velocity
386 {
387 get
388 {
389 if (m_zeroFlag)
390 return Vector3.Zero;
391 m_lastUpdateSent = false;
392 return m_velocity;
393 }
394 set
395 {
396 m_pidControllerActive = true;
397 m_target_velocity = value;
398 }
399 }
400
401 public override Vector3 Torque
402 {
403 get { return Vector3.Zero; }
404 set { return; }
405 }
406
407 public override float CollisionScore
408 {
409 get { return 0f; }
410 set { }
411 }
412
413 public override Vector3 Acceleration
414 {
415 get { return m_acceleration; }
416 }
417
418 public override Quaternion Orientation
419 {
420 get { return Quaternion.Identity; }
421 set
422 {
423
424 }
425 }
426
427 public override int PhysicsActorType
428 {
429 get { return (int)ActorTypes.Agent; }
430 set { return; }
431 }
432
433 public override bool IsPhysical
434 {
435 get { return false; }
436 set { return; }
437 }
438
439 public override bool Flying
440 {
441 get { return m_flying; }
442 set { m_flying = value; }
443 }
444
445 public override bool SetAlwaysRun
446 {
447 get { return m_alwaysRun; }
448 set { m_alwaysRun = value; }
449 }
450
451
452 public override bool ThrottleUpdates
453 {
454 get { return false; }
455 set { return; }
456 }
457
458 /// <summary>
459 /// Returns if the avatar is colliding in general.
460 /// This includes the ground and objects and avatar.
461 /// </summary>
462 public override bool IsColliding
463 {
464 get { return m_iscolliding; }
465 set
466 {
467 int i;
468 int truecount = 0;
469 int falsecount = 0;
470
471 if (m_colliderarr.Length >= 10)
472 {
473 for (i = 0; i < 10; i++)
474 {
475 m_colliderarr[i] = m_colliderarr[i + 1];
476 }
477 }
478 m_colliderarr[10] = value;
479
480 for (i = 0; i < 11; i++)
481 {
482 if (m_colliderarr[i])
483 {
484 truecount++;
485 }
486 else
487 {
488 falsecount++;
489 }
490 }
491
492 // Equal truecounts and false counts means we're colliding with something.
493 m_log.DebugFormat("[PHYSICS]: TrueCount:{0}, FalseCount:{1}",truecount,falsecount);
494 if (falsecount > 1.2 * truecount)
495 {
496 m_iscolliding = false;
497 }
498 else
499 {
500 m_iscolliding = true;
501 }
502 if (m_wascolliding != m_iscolliding)
503 {
504 //base.SendCollisionUpdate(new CollisionEventUpdate());
505 }
506 m_wascolliding = m_iscolliding;
507 }
508 }
509
510 /// <summary>
511 /// Returns if an avatar is colliding with the ground
512 /// </summary>
513 public override bool CollidingGround
514 {
515 get { return m_iscollidingGround; }
516 set
517 {
518 // Collisions against the ground are not really reliable
519 // So, to get a consistant value we have to average the current result over time
520 // Currently we use 1 second = 10 calls to this.
521 int i;
522 int truecount = 0;
523 int falsecount = 0;
524
525 if (m_colliderGroundarr.Length >= 10)
526 {
527 for (i = 0; i < 10; i++)
528 {
529 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
530 }
531 }
532 m_colliderGroundarr[10] = value;
533
534 for (i = 0; i < 11; i++)
535 {
536 if (m_colliderGroundarr[i])
537 {
538 truecount++;
539 }
540 else
541 {
542 falsecount++;
543 }
544 }
545
546 // Equal truecounts and false counts means we're colliding with something.
547
548 if (falsecount > 1.2 * truecount)
549 {
550 m_iscollidingGround = false;
551 }
552 else
553 {
554 m_iscollidingGround = true;
555 }
556 if (m_wascollidingGround != m_iscollidingGround)
557 {
558 //base.SendCollisionUpdate(new CollisionEventUpdate());
559 }
560 m_wascollidingGround = m_iscollidingGround;
561 }
562 }
563
564 /// <summary>
565 /// Returns if the avatar is colliding with an object
566 /// </summary>
567 public override bool CollidingObj
568 {
569 get { return m_iscollidingObj; }
570 set
571 {
572 m_iscollidingObj = value;
573 if (value)
574 m_pidControllerActive = false;
575 else
576 m_pidControllerActive = true;
577 }
578 }
579
580
581 public override bool FloatOnWater
582 {
583 set { return; }
584 }
585
586 public override Vector3 RotationalVelocity
587 {
588 get { return m_rotationalVelocity; }
589 set { m_rotationalVelocity = value; }
590 }
591
592 public override bool Kinematic
593 {
594 get { return false; }
595 set { }
596 }
597
598 public override float Buoyancy
599 {
600 get { return m_buoyancy; }
601 set { m_buoyancy = value; }
602 }
603
604 public override Vector3 PIDTarget { set { return; } }
605 public override bool PIDActive { set { return; } }
606 public override float PIDTau { set { return; } }
607
608 public override bool PIDHoverActive
609 {
610 set { return; }
611 }
612
613 public override float PIDHoverHeight
614 {
615 set { return; }
616 }
617
618 public override PIDHoverType PIDHoverType
619 {
620 set { return; }
621 }
622
623 public override float PIDHoverTau
624 {
625 set { return; }
626 }
627
628
629 public override Quaternion APIDTarget
630 {
631 set { return; }
632 }
633
634 public override bool APIDActive
635 {
636 set { return; }
637 }
638
639 public override float APIDStrength
640 {
641 set { return; }
642 }
643
644 public override float APIDDamping
645 {
646 set { return; }
647 }
648
649 /// <summary>
650 /// Adds the force supplied to the Target Velocity
651 /// The PID controller takes this target velocity and tries to make it a reality
652 /// </summary>
653 /// <param name="force"></param>
654 /// <param name="pushforce">Is this a push by a script?</param>
655 public override void AddForce(Vector3 force, bool pushforce)
656 {
657 if (pushforce)
658 {
659 m_pidControllerActive = false;
660 force *= 100f;
661 doForce(force, false);
662 //System.Console.WriteLine("Push!");
663 //_target_velocity.X += force.X;
664 // _target_velocity.Y += force.Y;
665 //_target_velocity.Z += force.Z;
666 }
667 else
668 {
669 m_pidControllerActive = true;
670 m_target_velocity.X += force.X;
671 m_target_velocity.Y += force.Y;
672 m_target_velocity.Z += force.Z;
673 }
674 //m_lastUpdateSent = false;
675 }
676
677 public void doForce(Vector3 force, bool now)
678 {
679
680 tempVector3.setValue(force.X, force.Y, force.Z);
681 if (now)
682 {
683 Body.applyCentralForce(tempVector3);
684 }
685 else
686 {
687 m_taintedForce += force;
688 m_parent_scene.AddPhysicsActorTaint(this);
689 }
690 }
691
692 public void doImpulse(Vector3 force, bool now)
693 {
694
695 tempVector3.setValue(force.X, force.Y, force.Z);
696 if (now)
697 {
698 Body.applyCentralImpulse(tempVector3);
699 }
700 else
701 {
702 m_taintedForce += force;
703 m_parent_scene.AddPhysicsActorTaint(this);
704 }
705 }
706
707 public override void AddAngularForce(Vector3 force, bool pushforce)
708 {
709
710 }
711
712 public override void SetMomentum(Vector3 momentum)
713 {
714
715 }
716
717 public override void SubscribeEvents(int ms)
718 {
719 m_eventsubscription = ms;
720 m_requestedUpdateFrequency = ms;
721 m_parent_scene.addCollisionEventReporting(this);
722 }
723
724 public override void UnSubscribeEvents()
725 {
726 m_parent_scene.remCollisionEventReporting(this);
727 m_eventsubscription = 0;
728 m_requestedUpdateFrequency = 0;
729 }
730
731 public override bool SubscribedEvents()
732 {
733 if (m_eventsubscription > 0)
734 return true;
735 return false;
736 }
737
738 public void AddCollision(uint collideWith, ContactPoint contact)
739 {
740 if (CollisionEventsThisFrame == null)
741 {
742 CollisionEventsThisFrame = new CollisionEventUpdate();
743 }
744 CollisionEventsThisFrame.addCollider(collideWith, contact);
745 }
746
747 public void SendCollisions()
748 {
749 if (m_eventsubscription >= m_requestedUpdateFrequency)
750 {
751 if (CollisionEventsThisFrame != null)
752 {
753 base.SendCollisionUpdate(CollisionEventsThisFrame);
754 }
755 CollisionEventsThisFrame = new CollisionEventUpdate();
756 m_eventsubscription = 0;
757 }
758 return;
759 }
760
761 internal void Dispose()
762 {
763 if (Body.isInWorld())
764 m_parent_scene.removeFromWorld(Body);
765
766 if (m_aMotor.Handle != IntPtr.Zero)
767 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
768
769 m_aMotor.Dispose(); m_aMotor = null;
770 ClosestCastResult.Dispose(); ClosestCastResult = null;
771 Body.Dispose(); Body = null;
772 Shell.Dispose(); Shell = null;
773 tempQuat1.Dispose();
774 tempTrans1.Dispose();
775 tempVector1.Dispose();
776 tempVector2.Dispose();
777 tempVector3.Dispose();
778 tempVector4.Dispose();
779 tempVector5RayCast.Dispose();
780 tempVector6RayCast.Dispose();
781
782 }
783
784 public void ProcessTaints(float timestep)
785 {
786
787 if (m_tainted_isPhysical != m_isPhysical)
788 {
789 if (m_tainted_isPhysical)
790 {
791 // Create avatar capsule and related ODE data
792 if (!(Shell == null && Body == null))
793 {
794 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
795 + (Shell != null ? "Shell " : "")
796 + (Body != null ? "Body " : ""));
797 }
798 AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
799
800
801 }
802 else
803 {
804 // destroy avatar capsule and related ODE data
805
806 Dispose();
807 tempVector1 = new btVector3(0, 0, 0);
808 tempVector2 = new btVector3(0, 0, 0);
809 tempVector3 = new btVector3(0, 0, 0);
810 tempVector4 = new btVector3(0, 0, 0);
811
812 tempVector5RayCast = new btVector3(0, 0, 0);
813 tempVector6RayCast = new btVector3(0, 0, 0);
814 tempVector7RayCast = new btVector3(0, 0, 0);
815
816 tempQuat1 = new btQuaternion(0, 0, 0, 1);
817 tempTrans1 = new btTransform(tempQuat1, tempVector1);
818 // m_movementComparision = new PhysicsVector(0, 0, 0);
819 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
820 }
821
822 m_isPhysical = m_tainted_isPhysical;
823 }
824
825 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
826 {
827 if (Body != null)
828 {
829
830 m_pidControllerActive = true;
831 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
832 //d.JointDestroy(Amotor);
833 float prevCapsule = CAPSULE_LENGTH;
834 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
835 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
836 Dispose();
837
838 tempVector1 = new btVector3(0, 0, 0);
839 tempVector2 = new btVector3(0, 0, 0);
840 tempVector3 = new btVector3(0, 0, 0);
841 tempVector4 = new btVector3(0, 0, 0);
842
843 tempVector5RayCast = new btVector3(0, 0, 0);
844 tempVector6RayCast = new btVector3(0, 0, 0);
845 tempVector7RayCast = new btVector3(0, 0, 0);
846
847 tempQuat1 = new btQuaternion(0, 0, 0, 1);
848 tempTrans1 = new btTransform(tempQuat1, tempVector1);
849 // m_movementComparision = new PhysicsVector(0, 0, 0);
850 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
851
852 AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
853 m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
854 Velocity = Vector3.Zero;
855
856 }
857 else
858 {
859 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
860 + (Shell == null ? "Shell " : "")
861 + (Body == null ? "Body " : ""));
862 }
863 }
864 if (m_taintRemove)
865 {
866 Dispose();
867 }
868 }
869
870 /// <summary>
871 /// Called from Simulate
872 /// This is the avatar's movement control + PID Controller
873 /// </summary>
874 /// <param name="timeStep"></param>
875 public void Move(float timeStep)
876 {
877 // no lock; for now it's only called from within Simulate()
878
879 // If the PID Controller isn't active then we set our force
880 // calculating base velocity to the current position
881 if (Body == null)
882 return;
883 tempTrans1.Dispose();
884 tempTrans1 = Body.getInterpolationWorldTransform();
885 tempVector1.Dispose();
886 tempVector1 = tempTrans1.getOrigin();
887 tempVector2.Dispose();
888 tempVector2 = Body.getInterpolationLinearVelocity();
889
890 if (m_pidControllerActive == false)
891 {
892 m_zeroPosition.X = tempVector1.getX();
893 m_zeroPosition.Y = tempVector1.getY();
894 m_zeroPosition.Z = tempVector1.getZ();
895 }
896 //PidStatus = true;
897
898 Vector3 vec = Vector3.Zero;
899
900 Vector3 vel = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
901
902 float movementdivisor = 1f;
903
904 if (!m_alwaysRun)
905 {
906 movementdivisor = walkDivisor;
907 }
908 else
909 {
910 movementdivisor = runDivisor;
911 }
912
913 // if velocity is zero, use position control; otherwise, velocity control
914 if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
915 {
916 // keep track of where we stopped. No more slippin' & slidin'
917 if (!m_zeroFlag)
918 {
919 m_zeroFlag = true;
920 m_zeroPosition.X = tempVector1.getX();
921 m_zeroPosition.Y = tempVector1.getY();
922 m_zeroPosition.Z = tempVector1.getZ();
923 }
924 if (m_pidControllerActive)
925 {
926 // We only want to deactivate the PID Controller if we think we want to have our surrogate
927 // react to the physics scene by moving it's position.
928 // Avatar to Avatar collisions
929 // Prim to avatar collisions
930
931 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
932 vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
933 vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
934 if (m_flying)
935 {
936 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
937 }
938 }
939 //PidStatus = true;
940 }
941 else
942 {
943 m_pidControllerActive = true;
944 m_zeroFlag = false;
945 if (m_iscolliding && !m_flying)
946 {
947 // We're standing on something
948 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
949 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
950 }
951 else if (m_iscolliding && m_flying)
952 {
953 // We're flying and colliding with something
954 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
955 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
956 }
957 else if (!m_iscolliding && m_flying)
958 {
959 // we're in mid air suspended
960 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
961 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
962
963 // We don't want linear velocity to cause our avatar to bounce, so we check target Z and actual velocity X, Y
964 // rebound preventing
965 if (m_target_velocity.Z < 0.025f && m_velocity.X < 0.25f && m_velocity.Y < 0.25f)
966 m_zeroFlag = true;
967 }
968
969 if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
970 {
971 // We're colliding with something and we're not flying but we're moving
972 // This means we're walking or running.
973 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
974 vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
975 if (m_target_velocity.X > 0)
976 {
977 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
978 }
979 if (m_target_velocity.Y > 0)
980 {
981 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
982 }
983 }
984 else if (!m_iscolliding && !m_flying)
985 {
986 // we're not colliding and we're not flying so that means we're falling!
987 // m_iscolliding includes collisions with the ground.
988
989 // d.Vector3 pos = d.BodyGetPosition(Body);
990 if (m_target_velocity.X > 0)
991 {
992 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
993 }
994 if (m_target_velocity.Y > 0)
995 {
996 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
997 }
998 }
999
1000
1001 if (m_flying)
1002 {
1003 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
1004 }
1005 }
1006 if (m_flying)
1007 {
1008 // Slight PID correction
1009 vec.Z += (((-1 * m_parent_scene.gravityz) * m_mass) * 0.06f);
1010
1011
1012 //auto fly height. Kitto Flora
1013 //d.Vector3 pos = d.BodyGetPosition(Body);
1014 float target_altitude = m_parent_scene.GetTerrainHeightAtXY(m_position.X, m_position.Y) + 5.0f;
1015
1016 if (m_position.Z < target_altitude)
1017 {
1018 vec.Z += (target_altitude - m_position.Z) * PID_P * 5.0f;
1019 }
1020
1021 }
1022 if (Body != null && (((m_target_velocity.X > 0.2f || m_target_velocity.X < -0.2f) || (m_target_velocity.Y > 0.2f || m_target_velocity.Y < -0.2f))))
1023 {
1024 Body.setFriction(0.001f);
1025 //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
1026 }
1027
1028 if (Body != null)
1029 {
1030 int activationstate = Body.getActivationState();
1031 if (activationstate == 0)
1032 {
1033 Body.forceActivationState(1);
1034 }
1035
1036
1037 }
1038 doImpulse(vec, true);
1039 }
1040
1041 /// <summary>
1042 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1043 /// </summary>
1044 public void UpdatePositionAndVelocity()
1045 {
1046 if (Body == null)
1047 return;
1048 //int val = Environment.TickCount;
1049 CheckIfStandingOnObject();
1050 //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
1051
1052 //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
1053
1054 tempTrans1.Dispose();
1055 tempTrans1 = Body.getInterpolationWorldTransform();
1056 tempVector1.Dispose();
1057 tempVector1 = tempTrans1.getOrigin();
1058 tempVector2.Dispose();
1059 tempVector2 = Body.getInterpolationLinearVelocity();
1060
1061 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1062 Vector3 vec = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
1063
1064 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1065 if (vec.X < -10.0f) vec.X = 0.0f;
1066 if (vec.Y < -10.0f) vec.Y = 0.0f;
1067 if (vec.X > (int)Constants.RegionSize + 10.2f) vec.X = (int)Constants.RegionSize + 10.2f;
1068 if (vec.Y > (int)Constants.RegionSize + 10.2f) vec.Y = (int)Constants.RegionSize + 10.2f;
1069
1070 m_position.X = vec.X;
1071 m_position.Y = vec.Y;
1072 m_position.Z = vec.Z;
1073
1074 // Did we move last? = zeroflag
1075 // This helps keep us from sliding all over
1076
1077 if (m_zeroFlag)
1078 {
1079 m_velocity.X = 0.0f;
1080 m_velocity.Y = 0.0f;
1081 m_velocity.Z = 0.0f;
1082
1083 // Did we send out the 'stopped' message?
1084 if (!m_lastUpdateSent)
1085 {
1086 m_lastUpdateSent = true;
1087 //base.RequestPhysicsterseUpdate();
1088
1089 }
1090 }
1091 else
1092 {
1093 m_lastUpdateSent = false;
1094 vec = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
1095 m_velocity.X = (vec.X);
1096 m_velocity.Y = (vec.Y);
1097
1098 m_velocity.Z = (vec.Z);
1099 //m_log.Debug(m_target_velocity);
1100 if (m_velocity.Z < -6 && !m_hackSentFall)
1101 {
1102 m_hackSentFall = true;
1103 m_pidControllerActive = false;
1104 }
1105 else if (m_flying && !m_hackSentFly)
1106 {
1107 //m_hackSentFly = true;
1108 //base.SendCollisionUpdate(new CollisionEventUpdate());
1109 }
1110 else
1111 {
1112 m_hackSentFly = false;
1113 m_hackSentFall = false;
1114 }
1115 }
1116 if (Body != null)
1117 {
1118 if (Body.getFriction() < 0.9f)
1119 Body.setFriction(0.9f);
1120 }
1121 //if (Body != null)
1122 // Body.clearForces();
1123 }
1124
1125 public void CheckIfStandingOnObject()
1126 {
1127
1128 float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
1129
1130 tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
1131 tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
1132
1133
1134 ClosestCastResult.Dispose();
1135 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
1136
1137 try
1138 {
1139 m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
1140 }
1141 catch (AccessViolationException)
1142 {
1143 m_log.Debug("BAD!");
1144 }
1145 if (ClosestCastResult.hasHit())
1146 {
1147
1148 if (tempVector7RayCast != null)
1149 tempVector7RayCast.Dispose();
1150
1151 //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
1152
1153 /*if (tempVector7RayCast == null) // null == no result also
1154 {
1155 CollidingObj = false;
1156 IsColliding = false;
1157 CollidingGround = false;
1158
1159 return;
1160 }
1161 float zVal = tempVector7RayCast.getZ();
1162 if (zVal != 0)
1163 m_log.Debug("[PHYSICS]: HAAAA");
1164 if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
1165 {
1166 CollidingObj = true;
1167 IsColliding = true;
1168 }
1169 else
1170 {
1171 CollidingObj = false;
1172 IsColliding = false;
1173 CollidingGround = false;
1174 }*/
1175
1176 //height+2*radius = capsule full length
1177 //CollidingObj = true;
1178 //IsColliding = true;
1179 m_iscolliding = true;
1180 }
1181 else
1182 {
1183 //CollidingObj = false;
1184 //IsColliding = false;
1185 //CollidingGround = false;
1186 m_iscolliding = false;
1187 }
1188 }
1189 }
1190
1191}
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs
deleted file mode 100644
index cf75c48..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs
+++ /dev/null
@@ -1,65 +0,0 @@
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 OpenSim.Region.Physics.Manager;
29
30namespace OpenSim.Region.Physics.BulletDotNETPlugin
31{
32 public class BulletDotNetPlugin : IPhysicsPlugin
33 {
34 private BulletDotNETScene m_scene;
35 private const string m_pluginName = "BulletDotNETPlugin";
36
37 #region IPhysicsPlugin Members
38
39 public bool Init()
40 {
41 return true;
42 }
43
44 public PhysicsScene GetScene(string sceneIdentifier)
45 {
46 if (m_scene == null)
47 {
48 m_scene = new BulletDotNETScene(sceneIdentifier);
49 }
50 return m_scene;
51 }
52
53 public string GetName()
54 {
55 return m_pluginName;
56 }
57
58 public void Dispose()
59 {
60
61 }
62
63 #endregion
64 }
65} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
deleted file mode 100644
index dc3229a..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
+++ /dev/null
@@ -1,2767 +0,0 @@
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.Runtime.InteropServices;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using BulletDotNET;
36using OpenSim.Framework;
37using OpenSim.Region.Physics.Manager;
38
39
40namespace OpenSim.Region.Physics.BulletDotNETPlugin
41{
42 public class BulletDotNETPrim : PhysicsActor
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 private Vector3 _position;
47 private Vector3 m_zeroPosition;
48 private Vector3 _velocity;
49 private Vector3 _torque;
50 private Vector3 m_lastVelocity;
51 private Vector3 m_lastposition;
52 private Quaternion m_lastorientation = Quaternion.Identity;
53 private Vector3 m_rotationalVelocity;
54 private Vector3 _size;
55 private Vector3 _acceleration;
56 // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
57 private Quaternion _orientation;
58 private Vector3 m_taintposition;
59 private Vector3 m_taintsize;
60 private Vector3 m_taintVelocity;
61 private Vector3 m_taintTorque;
62 private Quaternion m_taintrot;
63 private Vector3 m_angularlock = Vector3.One;
64 private Vector3 m_taintAngularLock = Vector3.One;
65 // private btGeneric6DofConstraint Amotor;
66
67 private Vector3 m_PIDTarget;
68 private float m_PIDTau;
69 private float m_PIDHoverHeight;
70 private float m_PIDHoverTau;
71 private bool m_useHoverPID;
72 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
73 private float m_targetHoverHeight;
74 private float m_groundHeight;
75 private float m_waterHeight;
76 private float PID_D = 35f;
77 private float PID_G = 25f;
78 // private float m_tensor = 5f;
79 // private int body_autodisable_frames = 20;
80 private IMesh primMesh;
81
82 private bool m_usePID;
83
84 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
85 | CollisionCategories.Space
86 | CollisionCategories.Body
87 | CollisionCategories.Character
88 );
89
90 private bool m_taintshape;
91 private bool m_taintPhysics;
92 // private bool m_collidesLand = true;
93 private bool m_collidesWater;
94 public bool m_returnCollisions;
95
96 // Default we're a Geometry
97 // private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
98
99 // Default, Collide with Other Geometries, spaces and Bodies
100 // private CollisionCategories m_collisionFlags = m_default_collisionFlags;
101
102 public bool m_taintremove;
103 public bool m_taintdisable;
104 public bool m_disabled;
105 public bool m_taintadd;
106 public bool m_taintselected;
107 public bool m_taintCollidesWater;
108
109 public uint m_localID;
110
111 //public GCHandle gc;
112 // private CollisionLocker ode;
113
114 private bool m_taintforce;
115 private bool m_taintaddangularforce;
116 private Vector3 m_force;
117 private List<Vector3> m_forcelist = new List<Vector3>();
118 private List<Vector3> m_angularforcelist = new List<Vector3>();
119
120 private IMesh _mesh;
121 private PrimitiveBaseShape _pbs;
122 private BulletDotNETScene _parent_scene;
123 public btCollisionShape prim_geom;
124 public IntPtr _triMeshData;
125
126 private PhysicsActor _parent;
127 private PhysicsActor m_taintparent;
128
129 private List<BulletDotNETPrim> childrenPrim = new List<BulletDotNETPrim>();
130
131 private bool iscolliding;
132 private bool m_isphysical;
133 private bool m_isSelected;
134
135 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
136
137 private bool m_throttleUpdates;
138 // private int throttleCounter;
139 public int m_interpenetrationcount;
140 public float m_collisionscore;
141 public int m_roundsUnderMotionThreshold;
142 private int m_crossingfailures;
143
144 public float m_buoyancy;
145
146 public bool outofBounds;
147 private float m_density = 10.000006836f; // Aluminum g/cm3;
148
149 public bool _zeroFlag;
150 private bool m_lastUpdateSent;
151
152
153 private String m_primName;
154 private Vector3 _target_velocity;
155
156 public int m_eventsubscription;
157 private int m_requestedUpdateFrequency = 0;
158 private CollisionEventUpdate CollisionEventsThisFrame = null;
159
160 public volatile bool childPrim;
161
162 private btVector3 tempPosition1;
163 private btVector3 tempPosition2;
164 private btVector3 tempPosition3;
165 private btVector3 tempSize1;
166 private btVector3 tempSize2;
167 private btVector3 tempLinearVelocity1;
168 private btVector3 tempLinearVelocity2;
169 private btVector3 tempAngularVelocity1;
170 private btVector3 tempAngularVelocity2;
171 private btVector3 tempInertia1;
172 private btVector3 tempInertia2;
173 private btVector3 tempAddForce;
174 private btQuaternion tempOrientation1;
175 private btQuaternion tempOrientation2;
176 private btMotionState tempMotionState1;
177 private btMotionState tempMotionState2;
178 private btMotionState tempMotionState3;
179 private btTransform tempTransform1;
180 private btTransform tempTransform2;
181 private btTransform tempTransform3;
182 private btTransform tempTransform4;
183 private btTriangleIndexVertexArray btshapeArray;
184 private btVector3 AxisLockAngleHigh;
185 private btVector3 AxisLockLinearLow;
186 private btVector3 AxisLockLinearHigh;
187 private bool forceenable = false;
188
189 private btGeneric6DofConstraint m_aMotor;
190
191 public btRigidBody Body;
192
193 public BulletDotNETPrim(String primName, BulletDotNETScene parent_scene, Vector3 pos, Vector3 size,
194 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
195 {
196 tempPosition1 = new btVector3(0, 0, 0);
197 tempPosition2 = new btVector3(0, 0, 0);
198 tempPosition3 = new btVector3(0, 0, 0);
199 tempSize1 = new btVector3(0, 0, 0);
200 tempSize2 = new btVector3(0, 0, 0);
201 tempLinearVelocity1 = new btVector3(0, 0, 0);
202 tempLinearVelocity2 = new btVector3(0, 0, 0);
203 tempAngularVelocity1 = new btVector3(0, 0, 0);
204 tempAngularVelocity2 = new btVector3(0, 0, 0);
205 tempInertia1 = new btVector3(0, 0, 0);
206 tempInertia2 = new btVector3(0, 0, 0);
207 tempOrientation1 = new btQuaternion(0, 0, 0, 1);
208 tempOrientation2 = new btQuaternion(0, 0, 0, 1);
209 _parent_scene = parent_scene;
210 tempTransform1 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero);
211 tempTransform2 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
212 tempTransform3 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
213 tempTransform4 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
214
215 tempMotionState1 = new btDefaultMotionState(_parent_scene.TransZero);
216 tempMotionState2 = new btDefaultMotionState(_parent_scene.TransZero);
217 tempMotionState3 = new btDefaultMotionState(_parent_scene.TransZero);
218
219
220 AxisLockLinearLow = new btVector3(-1 * (int)Constants.RegionSize, -1 * (int)Constants.RegionSize, -1 * (int)Constants.RegionSize);
221 int regionsize = (int)Constants.RegionSize;
222
223 if (regionsize == 256)
224 regionsize = 512;
225
226 AxisLockLinearHigh = new btVector3((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionSize);
227
228 _target_velocity = Vector3.Zero;
229 _velocity = Vector3.Zero;
230 _position = pos;
231 m_taintposition = pos;
232 PID_D = parent_scene.bodyPIDD;
233 PID_G = parent_scene.bodyPIDG;
234 m_density = parent_scene.geomDefaultDensity;
235 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
236 // body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
237
238 prim_geom = null;
239 Body = null;
240
241 if (size.X <= 0) size.X = 0.01f;
242 if (size.Y <= 0) size.Y = 0.01f;
243 if (size.Z <= 0) size.Z = 0.01f;
244
245 _size = size;
246 m_taintsize = _size;
247 _acceleration = Vector3.Zero;
248 m_rotationalVelocity = Vector3.Zero;
249 _orientation = rotation;
250 m_taintrot = _orientation;
251 _mesh = mesh;
252 _pbs = pbs;
253
254 _parent_scene = parent_scene;
255
256 if (pos.Z < 0)
257 m_isphysical = false;
258 else
259 {
260 m_isphysical = pisPhysical;
261 // If we're physical, we need to be in the master space for now.
262 // linksets *should* be in a space together.. but are not currently
263 }
264 m_primName = primName;
265 m_taintadd = true;
266 _parent_scene.AddPhysicsActorTaint(this);
267
268 }
269
270 #region PhysicsActor overrides
271
272 public override bool Stopped
273 {
274 get { return _zeroFlag; }
275 }
276
277 public override Vector3 Size
278 {
279 get { return _size; }
280 set { _size = value; }
281 }
282
283 public override PrimitiveBaseShape Shape
284 {
285 set
286 {
287 _pbs = value;
288 m_taintshape = true;
289 }
290 }
291
292 public override uint LocalID
293 {
294 set
295 {
296 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
297 m_localID = value;
298 }
299 }
300
301 public override bool Grabbed
302 {
303 set { return; }
304 }
305
306 public override bool Selected
307 {
308 set
309 {
310 // This only makes the object not collidable if the object
311 // is physical or the object is modified somehow *IN THE FUTURE*
312 // without this, if an avatar selects prim, they can walk right
313 // through it while it's selected
314 m_collisionscore = 0;
315 if ((m_isphysical && !_zeroFlag) || !value)
316 {
317 m_taintselected = value;
318 _parent_scene.AddPhysicsActorTaint(this);
319 }
320 else
321 {
322 m_taintselected = value;
323 m_isSelected = value;
324 }
325 }
326 }
327
328 public override void CrossingFailure()
329 {
330 m_crossingfailures++;
331 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
332 {
333 base.RaiseOutOfBounds(_position);
334 return;
335 }
336 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
337 {
338 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
339 }
340 }
341 public override void link(PhysicsActor obj)
342 {
343 m_taintparent = obj;
344 }
345
346 public override void delink()
347 {
348 m_taintparent = null;
349 }
350
351 public override void LockAngularMotion(Vector3 axis)
352 {
353 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
354 m_taintAngularLock = axis;
355 }
356
357 public override Vector3 Position
358 {
359 get { return _position; }
360
361 set
362 {
363 _position = value;
364 //m_log.Info("[PHYSICS]: " + _position.ToString());
365 }
366 }
367
368 public override float Mass
369 {
370 get { return CalculateMass(); }
371 }
372
373 public override Vector3 Force
374 {
375 //get { return Vector3.Zero; }
376 get { return m_force; }
377 set { m_force = value; }
378 }
379
380 public override int VehicleType
381 {
382 get { return 0; }
383 set { return; }
384 }
385
386 public override void VehicleFloatParam(int param, float value)
387 {
388 //TODO:
389 }
390
391 public override void VehicleVectorParam(int param, Vector3 value)
392 {
393 //TODO:
394 }
395
396 public override void VehicleRotationParam(int param, Quaternion rotation)
397 {
398 //TODO:
399 }
400
401 public override void VehicleFlags(int param, bool remove)
402 {
403
404 }
405
406 public override void SetVolumeDetect(int param)
407 {
408 //TODO: GhostObject
409 m_isVolumeDetect = (param != 0);
410
411 }
412
413 public override Vector3 GeometricCenter
414 {
415 get { return Vector3.Zero; }
416 }
417
418 public override Vector3 CenterOfMass
419 {
420 get { return Vector3.Zero; }
421 }
422
423 public override Vector3 Velocity
424 {
425 get
426 {
427 // Averate previous velocity with the new one so
428 // client object interpolation works a 'little' better
429 Vector3 returnVelocity;
430 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
431 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
432 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
433 return returnVelocity;
434 }
435 set
436 {
437 _velocity = value;
438
439 m_taintVelocity = value;
440 _parent_scene.AddPhysicsActorTaint(this);
441 }
442 }
443
444 public override Vector3 Torque
445 {
446 get
447 {
448 if (!m_isphysical || Body.Handle == IntPtr.Zero)
449 return Vector3.Zero;
450
451 return _torque;
452 }
453
454 set
455 {
456 m_taintTorque = value;
457 _parent_scene.AddPhysicsActorTaint(this);
458 }
459 }
460
461 public override float CollisionScore
462 {
463 get { return m_collisionscore; }
464 set { m_collisionscore = value; }
465 }
466
467 public override Vector3 Acceleration
468 {
469 get { return _acceleration; }
470 }
471
472 public override Quaternion Orientation
473 {
474 get { return _orientation; }
475 set { _orientation = value; }
476 }
477
478 public override int PhysicsActorType
479 {
480 get { return (int)ActorTypes.Prim; }
481 set { return; }
482 }
483
484 public override bool IsPhysical
485 {
486 get { return m_isphysical; }
487 set { m_isphysical = value; }
488 }
489
490 public override bool Flying
491 {
492 // no flying prims for you
493 get { return false; }
494 set { }
495 }
496
497 public override bool SetAlwaysRun
498 {
499 get { return false; }
500 set { return; }
501 }
502
503 public override bool ThrottleUpdates
504 {
505 get { return m_throttleUpdates; }
506 set { m_throttleUpdates = value; }
507 }
508
509 public override bool IsColliding
510 {
511 get { return iscolliding; }
512 set { iscolliding = value; }
513 }
514
515 public override bool CollidingGround
516 {
517 get { return false; }
518 set { return; }
519 }
520
521 public override bool CollidingObj
522 {
523 get { return false; }
524 set { return; }
525 }
526
527 public override bool FloatOnWater
528 {
529 set
530 {
531 m_taintCollidesWater = value;
532 _parent_scene.AddPhysicsActorTaint(this);
533 }
534 }
535
536 public override Vector3 RotationalVelocity
537 {
538 get
539 {
540 Vector3 pv = Vector3.Zero;
541 if (_zeroFlag)
542 return pv;
543 m_lastUpdateSent = false;
544
545 if (m_rotationalVelocity.ApproxEquals(pv, 0.2f))
546 return pv;
547
548 return m_rotationalVelocity;
549 }
550 set { m_rotationalVelocity = value; }
551 }
552
553 public override bool Kinematic
554 {
555 get { return false; }
556 set { }
557 }
558
559 public override float Buoyancy
560 {
561 get { return m_buoyancy; }
562 set { m_buoyancy = value; }
563 }
564
565 public override Vector3 PIDTarget { set { m_PIDTarget = value; ; } }
566 public override bool PIDActive { set { m_usePID = value; } }
567 public override float PIDTau { set { m_PIDTau = value; } }
568
569 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
570 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
571 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
572 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
573
574 public override Quaternion APIDTarget { set { return; } }
575 public override bool APIDActive { set { return; } }
576 public override float APIDStrength { set { return; } }
577 public override float APIDDamping { set { return; } }
578
579 public override void AddForce(Vector3 force, bool pushforce)
580 {
581 m_forcelist.Add(force);
582 m_taintforce = true;
583 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
584 }
585
586 public override void AddAngularForce(Vector3 force, bool pushforce)
587 {
588 m_angularforcelist.Add(force);
589 m_taintaddangularforce = true;
590 }
591
592 public override void SetMomentum(Vector3 momentum)
593 {
594 }
595
596 public override void SubscribeEvents(int ms)
597 {
598 m_eventsubscription = ms;
599 m_requestedUpdateFrequency = ms;
600 _parent_scene.addCollisionEventReporting(this);
601 }
602
603 public override void UnSubscribeEvents()
604 {
605 _parent_scene.remCollisionEventReporting(this);
606 m_eventsubscription = 0;
607 m_requestedUpdateFrequency = 0;
608 }
609
610 public override bool SubscribedEvents()
611 {
612 return (m_eventsubscription > 0);
613 }
614
615 #endregion
616
617 public void AddCollision(uint collideWith, ContactPoint contact)
618 {
619 if (CollisionEventsThisFrame == null)
620 {
621 CollisionEventsThisFrame = new CollisionEventUpdate();
622 }
623 CollisionEventsThisFrame.addCollider(collideWith, contact);
624 }
625
626 public void SendCollisions()
627 {
628 if (m_eventsubscription >= m_requestedUpdateFrequency)
629 {
630 if (CollisionEventsThisFrame != null)
631 {
632 base.SendCollisionUpdate(CollisionEventsThisFrame);
633 }
634 CollisionEventsThisFrame = null;
635 // m_eventsubscription = 0;
636 }
637 return;
638 }
639
640 internal void Dispose()
641 {
642 //TODO:
643 DisableAxisMotor();
644 DisposeOfBody();
645 SetCollisionShape(null);
646
647 if (tempMotionState3 != null && tempMotionState3.Handle != IntPtr.Zero)
648 {
649 tempMotionState3.Dispose();
650 tempMotionState3 = null;
651 }
652
653 if (tempMotionState2 != null && tempMotionState2.Handle != IntPtr.Zero)
654 {
655 tempMotionState2.Dispose();
656 tempMotionState2 = null;
657 }
658
659 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
660 {
661 tempMotionState1.Dispose();
662 tempMotionState1 = null;
663 }
664
665 if (tempTransform4 != null && tempTransform4.Handle != IntPtr.Zero)
666 {
667 tempTransform4.Dispose();
668 tempTransform4 = null;
669 }
670
671 if (tempTransform3 != null && tempTransform3.Handle != IntPtr.Zero)
672 {
673 tempTransform3.Dispose();
674 tempTransform3 = null;
675 }
676
677 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
678 {
679 tempTransform2.Dispose();
680 tempTransform2 = null;
681 }
682
683 if (tempTransform1 != null && tempTransform1.Handle != IntPtr.Zero)
684 {
685 tempTransform1.Dispose();
686 tempTransform1 = null;
687 }
688
689 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
690 {
691 tempOrientation2.Dispose();
692 tempOrientation2 = null;
693 }
694
695 if (tempOrientation1 != null && tempOrientation1.Handle != IntPtr.Zero)
696 {
697 tempOrientation1.Dispose();
698 tempOrientation1 = null;
699 }
700
701 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
702 {
703 tempInertia1.Dispose();
704 tempInertia1 = null;
705 }
706
707 if (tempInertia2 != null && tempInertia2.Handle != IntPtr.Zero)
708 {
709 tempInertia2.Dispose();
710 tempInertia1 = null;
711 }
712
713
714 if (tempAngularVelocity2 != null && tempAngularVelocity2.Handle != IntPtr.Zero)
715 {
716 tempAngularVelocity2.Dispose();
717 tempAngularVelocity2 = null;
718 }
719
720 if (tempAngularVelocity1 != null && tempAngularVelocity1.Handle != IntPtr.Zero)
721 {
722 tempAngularVelocity1.Dispose();
723 tempAngularVelocity1 = null;
724 }
725
726 if (tempLinearVelocity2 != null && tempLinearVelocity2.Handle != IntPtr.Zero)
727 {
728 tempLinearVelocity2.Dispose();
729 tempLinearVelocity2 = null;
730 }
731
732 if (tempLinearVelocity1 != null && tempLinearVelocity1.Handle != IntPtr.Zero)
733 {
734 tempLinearVelocity1.Dispose();
735 tempLinearVelocity1 = null;
736 }
737
738 if (tempSize2 != null && tempSize2.Handle != IntPtr.Zero)
739 {
740 tempSize2.Dispose();
741 tempSize2 = null;
742 }
743
744 if (tempSize1 != null && tempSize1.Handle != IntPtr.Zero)
745 {
746 tempSize1.Dispose();
747 tempSize1 = null;
748 }
749
750 if (tempPosition3 != null && tempPosition3.Handle != IntPtr.Zero)
751 {
752 tempPosition3.Dispose();
753 tempPosition3 = null;
754 }
755
756 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
757 {
758 tempPosition2.Dispose();
759 tempPosition2 = null;
760 }
761
762 if (tempPosition1 != null && tempPosition1.Handle != IntPtr.Zero)
763 {
764 tempPosition1.Dispose();
765 tempPosition1 = null;
766 }
767 if (AxisLockLinearLow != null && AxisLockLinearLow.Handle != IntPtr.Zero)
768 {
769 AxisLockLinearLow.Dispose();
770 AxisLockLinearLow = null;
771 }
772 if (AxisLockLinearHigh != null && AxisLockLinearHigh.Handle != IntPtr.Zero)
773 {
774 AxisLockLinearHigh.Dispose();
775 AxisLockLinearHigh = null;
776 }
777
778 }
779
780
781
782 public void ProcessTaints(float timestep)
783 {
784 if (m_taintadd)
785 {
786 // m_log.Debug("[PHYSICS]: TaintAdd");
787 changeadd(timestep);
788 }
789
790 if (prim_geom == null)
791 {
792 CreateGeom(IntPtr.Zero, primMesh);
793
794 if (IsPhysical)
795 SetBody(Mass);
796 else
797 SetBody(0);
798 // m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT");
799 }
800
801 if (prim_geom.Handle == IntPtr.Zero)
802 {
803 CreateGeom(IntPtr.Zero, primMesh);
804
805 if (IsPhysical)
806 SetBody(Mass);
807 else
808 SetBody(0);
809 // m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT");
810
811 }
812
813 if (!_position.ApproxEquals(m_taintposition, 0f))
814 {
815 // m_log.Debug("[PHYSICS]: TaintMove");
816 changemove(timestep);
817 }
818 if (m_taintrot != _orientation)
819 {
820 // m_log.Debug("[PHYSICS]: TaintRotate");
821 rotate(timestep);
822 } //
823
824 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
825 {
826 // m_log.Debug("[PHYSICS]: TaintPhysics");
827 changePhysicsStatus(timestep);
828 }
829 //
830
831 if (!_size.ApproxEquals(m_taintsize, 0f))
832 {
833 // m_log.Debug("[PHYSICS]: TaintSize");
834 changesize(timestep);
835 }
836
837 //
838
839 if (m_taintshape)
840 {
841 // m_log.Debug("[PHYSICS]: TaintShape");
842 changeshape(timestep);
843 } //
844
845 if (m_taintforce)
846 {
847 // m_log.Debug("[PHYSICS]: TaintForce");
848 changeAddForce(timestep);
849 }
850 if (m_taintaddangularforce)
851 {
852 // m_log.Debug("[PHYSICS]: TaintAngularForce");
853 changeAddAngularForce(timestep);
854 }
855 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
856 {
857 // m_log.Debug("[PHYSICS]: TaintTorque");
858 changeSetTorque(timestep);
859 }
860 if (m_taintdisable)
861 {
862 // m_log.Debug("[PHYSICS]: TaintDisable");
863 changedisable(timestep);
864 }
865 if (m_taintselected != m_isSelected)
866 {
867 // m_log.Debug("[PHYSICS]: TaintSelected");
868 changeSelectedStatus(timestep);
869 }
870 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
871 {
872 // m_log.Debug("[PHYSICS]: TaintVelocity");
873 changevelocity(timestep);
874 }
875 if (m_taintparent != _parent)
876 {
877 // m_log.Debug("[PHYSICS]: TaintLink");
878 changelink(timestep);
879 }
880 if (m_taintCollidesWater != m_collidesWater)
881 {
882 changefloatonwater(timestep);
883 }
884 if (!m_angularlock.ApproxEquals(m_taintAngularLock, 0))
885 {
886 // m_log.Debug("[PHYSICS]: TaintAngularLock");
887 changeAngularLock(timestep);
888 }
889 if (m_taintremove)
890 {
891 DisposeOfBody();
892 Dispose();
893 }
894
895 }
896
897 #region Physics Scene Change Action routines
898
899 private void changeadd(float timestep)
900 {
901 //SetCollisionShape(null);
902 // Construction of new prim
903 if (Body != null)
904 {
905 if (Body.Handle != IntPtr.Zero)
906 {
907 DisableAxisMotor();
908 _parent_scene.removeFromWorld(this, Body);
909 //Body.Dispose();
910 }
911 //Body = null;
912 // TODO: dispose parts that make up body
913 }
914 if (_parent_scene.needsMeshing(_pbs))
915 {
916 // Don't need to re-enable body.. it's done in SetMesh
917 float meshlod = _parent_scene.meshSculptLOD;
918
919 if (IsPhysical)
920 meshlod = _parent_scene.MeshSculptphysicalLOD;
921
922 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
923 // createmesh returns null when it doesn't mesh.
924 CreateGeom(IntPtr.Zero, mesh);
925 }
926 else
927 {
928 _mesh = null;
929 CreateGeom(IntPtr.Zero, null);
930 }
931
932 if (IsPhysical)
933 SetBody(Mass);
934 else
935 SetBody(0);
936 //changeSelectedStatus(timestep);
937 m_taintadd = false;
938
939 }
940
941 private void changemove(float timestep)
942 {
943
944 // m_log.Debug("[PHYSICS]: _________ChangeMove");
945 if (!m_isphysical)
946 {
947 tempTransform2 = Body.getWorldTransform();
948 btQuaternion quat = tempTransform2.getRotation();
949 tempPosition2.setValue(_position.X, _position.Y, _position.Z);
950 tempTransform2.Dispose();
951 tempTransform2 = new btTransform(quat, tempPosition2);
952 Body.setWorldTransform(tempTransform2);
953
954 changeSelectedStatus(timestep);
955
956 resetCollisionAccounting();
957 }
958 else
959 {
960 if (Body != null)
961 {
962 if (Body.Handle != IntPtr.Zero)
963 {
964 DisableAxisMotor();
965 _parent_scene.removeFromWorld(this, Body);
966 //Body.Dispose();
967 }
968 //Body = null;
969 // TODO: dispose parts that make up body
970 }
971 /*
972 if (_parent_scene.needsMeshing(_pbs))
973 {
974 // Don't need to re-enable body.. it's done in SetMesh
975 float meshlod = _parent_scene.meshSculptLOD;
976
977 if (IsPhysical)
978 meshlod = _parent_scene.MeshSculptphysicalLOD;
979
980 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
981 // createmesh returns null when it doesn't mesh.
982 CreateGeom(IntPtr.Zero, mesh);
983 }
984 else
985 {
986 _mesh = null;
987 CreateGeom(IntPtr.Zero, null);
988 }
989 SetCollisionShape(prim_geom);
990 */
991 if (m_isphysical)
992 SetBody(Mass);
993 else
994 SetBody(0);
995 changeSelectedStatus(timestep);
996
997 resetCollisionAccounting();
998 }
999 m_taintposition = _position;
1000 }
1001
1002 private void rotate(float timestep)
1003 {
1004 // m_log.Debug("[PHYSICS]: _________ChangeRotate");
1005 tempTransform2 = Body.getWorldTransform();
1006 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
1007 tempTransform2.setRotation(tempOrientation2);
1008 Body.setWorldTransform(tempTransform2);
1009
1010 resetCollisionAccounting();
1011 m_taintrot = _orientation;
1012 }
1013
1014 private void changePhysicsStatus(float timestep)
1015 {
1016 if (Body != null)
1017 {
1018 if (Body.Handle != IntPtr.Zero)
1019 {
1020 DisableAxisMotor();
1021 _parent_scene.removeFromWorld(this, Body);
1022 //Body.Dispose();
1023 }
1024 //Body = null;
1025 // TODO: dispose parts that make up body
1026 }
1027 // m_log.Debug("[PHYSICS]: _________ChangePhysics");
1028
1029 ProcessGeomCreation();
1030
1031 if (m_isphysical)
1032 SetBody(Mass);
1033 else
1034 SetBody(0);
1035 changeSelectedStatus(timestep);
1036
1037 resetCollisionAccounting();
1038 m_taintPhysics = m_isphysical;
1039 }
1040
1041
1042
1043 internal void ProcessGeomCreation()
1044 {
1045 if (_parent_scene.needsMeshing(_pbs))
1046 {
1047 ProcessGeomCreationAsTriMesh(Vector3.Zero, Quaternion.Identity);
1048 // createmesh returns null when it doesn't mesh.
1049 CreateGeom(IntPtr.Zero, _mesh);
1050 }
1051 else
1052 {
1053 _mesh = null;
1054 CreateGeom(IntPtr.Zero, null);
1055 }
1056 SetCollisionShape(prim_geom);
1057 }
1058
1059 internal bool NeedsMeshing()
1060 {
1061 return _parent_scene.needsMeshing(_pbs);
1062 }
1063
1064 internal void ProcessGeomCreationAsTriMesh(Vector3 positionOffset, Quaternion orientation)
1065 {
1066 // Don't need to re-enable body.. it's done in SetMesh
1067 float meshlod = _parent_scene.meshSculptLOD;
1068
1069 if (IsPhysical)
1070 meshlod = _parent_scene.MeshSculptphysicalLOD;
1071
1072 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
1073 if (!positionOffset.ApproxEquals(Vector3.Zero, 0.001f) || orientation != Quaternion.Identity)
1074 {
1075
1076 float[] xyz = new float[3];
1077 xyz[0] = positionOffset.X;
1078 xyz[1] = positionOffset.Y;
1079 xyz[2] = positionOffset.Z;
1080
1081 Matrix4 m4 = Matrix4.CreateFromQuaternion(orientation);
1082
1083 float[,] matrix = new float[3, 3];
1084
1085 matrix[0, 0] = m4.M11;
1086 matrix[0, 1] = m4.M12;
1087 matrix[0, 2] = m4.M13;
1088 matrix[1, 0] = m4.M21;
1089 matrix[1, 1] = m4.M22;
1090 matrix[1, 2] = m4.M23;
1091 matrix[2, 0] = m4.M31;
1092 matrix[2, 1] = m4.M32;
1093 matrix[2, 2] = m4.M33;
1094
1095
1096 mesh.TransformLinear(matrix, xyz);
1097
1098
1099
1100 }
1101
1102 _mesh = mesh;
1103 }
1104
1105 private void changesize(float timestep)
1106 {
1107 if (Body != null)
1108 {
1109 if (Body.Handle != IntPtr.Zero)
1110 {
1111 DisableAxisMotor();
1112 _parent_scene.removeFromWorld(this, Body);
1113 //Body.Dispose();
1114 }
1115 //Body = null;
1116 // TODO: dispose parts that make up body
1117 }
1118
1119 // m_log.Debug("[PHYSICS]: _________ChangeSize");
1120 SetCollisionShape(null);
1121 // Construction of new prim
1122 ProcessGeomCreation();
1123
1124 if (IsPhysical)
1125 SetBody(Mass);
1126 else
1127 SetBody(0);
1128
1129 m_taintsize = _size;
1130
1131 }
1132
1133 private void changeshape(float timestep)
1134 {
1135 if (Body != null)
1136 {
1137 if (Body.Handle != IntPtr.Zero)
1138 {
1139 DisableAxisMotor();
1140 _parent_scene.removeFromWorld(this, Body);
1141 //Body.Dispose();
1142 }
1143 //Body = null;
1144 // TODO: dispose parts that make up body
1145 }
1146 // Cleanup of old prim geometry and Bodies
1147 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
1148 {
1149 if (childPrim)
1150 {
1151 if (_parent != null)
1152 {
1153 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
1154 parent.ChildDelink(this);
1155 }
1156 }
1157 else
1158 {
1159 //disableBody();
1160 }
1161 }
1162 try
1163 {
1164 //SetCollisionShape(null);
1165 }
1166 catch (System.AccessViolationException)
1167 {
1168 //prim_geom = IntPtr.Zero;
1169 m_log.Error("[PHYSICS]: PrimGeom dead");
1170 }
1171
1172 // we don't need to do space calculation because the client sends a position update also.
1173 if (_size.X <= 0) _size.X = 0.01f;
1174 if (_size.Y <= 0) _size.Y = 0.01f;
1175 if (_size.Z <= 0) _size.Z = 0.01f;
1176 // Construction of new prim
1177
1178 ProcessGeomCreation();
1179
1180 tempPosition1.setValue(_position.X, _position.Y, _position.Z);
1181 if (tempOrientation1.Handle != IntPtr.Zero)
1182 tempOrientation1.Dispose();
1183 tempOrientation1 = new btQuaternion(_orientation.X, Orientation.Y, _orientation.Z, _orientation.W);
1184 if (tempTransform1 != null && tempTransform1.Handle != IntPtr.Zero)
1185 tempTransform1.Dispose();
1186 tempTransform1 = new btTransform(tempOrientation1, tempPosition1);
1187
1188
1189
1190
1191 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
1192 if (IsPhysical)
1193 {
1194 SetBody(Mass);
1195 // Re creates body on size.
1196 // EnableBody also does setMass()
1197
1198 }
1199 else
1200 {
1201 SetBody(0);
1202 }
1203
1204 changeSelectedStatus(timestep);
1205 if (childPrim)
1206 {
1207 if (_parent is BulletDotNETPrim)
1208 {
1209 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
1210 parent.ChildSetGeom(this);
1211 }
1212 }
1213 resetCollisionAccounting();
1214
1215 m_taintshape = false;
1216 }
1217
1218 private void resetCollisionAccounting()
1219 {
1220 m_collisionscore = 0;
1221 }
1222
1223 private void ChildSetGeom(BulletDotNETPrim bulletDotNETPrim)
1224 {
1225 // TODO: throw new NotImplementedException();
1226 }
1227
1228 private void changeAddForce(float timestep)
1229 {
1230 if (!m_isSelected)
1231 {
1232 lock (m_forcelist)
1233 {
1234 //m_log.Info("[PHYSICS]: dequeing forcelist");
1235 if (IsPhysical)
1236 {
1237 Vector3 iforce = Vector3.Zero;
1238 for (int i = 0; i < m_forcelist.Count; i++)
1239 {
1240 iforce = iforce + m_forcelist[i];
1241 }
1242
1243 if (Body != null && Body.Handle != IntPtr.Zero)
1244 {
1245 if (tempAddForce != null && tempAddForce.Handle != IntPtr.Zero)
1246 tempAddForce.Dispose();
1247 enableBodySoft();
1248 tempAddForce = new btVector3(iforce.X, iforce.Y, iforce.Z);
1249 Body.applyCentralImpulse(tempAddForce);
1250 }
1251 }
1252 m_forcelist.Clear();
1253 }
1254
1255 m_collisionscore = 0;
1256 m_interpenetrationcount = 0;
1257 }
1258
1259 m_taintforce = false;
1260
1261 }
1262
1263 private void changeAddAngularForce(float timestep)
1264 {
1265 if (!m_isSelected)
1266 {
1267 lock (m_angularforcelist)
1268 {
1269 //m_log.Info("[PHYSICS]: dequeing forcelist");
1270 if (IsPhysical)
1271 {
1272 Vector3 iforce = Vector3.Zero;
1273 for (int i = 0; i < m_angularforcelist.Count; i++)
1274 {
1275 iforce = iforce + m_angularforcelist[i];
1276 }
1277
1278 if (Body != null && Body.Handle != IntPtr.Zero)
1279 {
1280 if (tempAddForce != null && tempAddForce.Handle != IntPtr.Zero)
1281 tempAddForce.Dispose();
1282 enableBodySoft();
1283 tempAddForce = new btVector3(iforce.X, iforce.Y, iforce.Z);
1284 Body.applyTorqueImpulse(tempAddForce);
1285 }
1286
1287 }
1288 m_angularforcelist.Clear();
1289 }
1290
1291 m_collisionscore = 0;
1292 m_interpenetrationcount = 0;
1293 }
1294
1295 m_taintaddangularforce = false;
1296 }
1297
1298 private void changeSetTorque(float timestep)
1299 {
1300 if (!m_isSelected)
1301 {
1302 if (IsPhysical)
1303 {
1304 if (Body != null && Body.Handle != IntPtr.Zero)
1305 {
1306 tempAngularVelocity2.setValue(m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
1307 Body.applyTorque(tempAngularVelocity2);
1308 }
1309 }
1310 }
1311 m_taintTorque = Vector3.Zero;
1312 }
1313
1314 private void changedisable(float timestep)
1315 {
1316 // TODO: throw new NotImplementedException();
1317 }
1318
1319 private void changeSelectedStatus(float timestep)
1320 {
1321 // TODO: throw new NotImplementedException();
1322 if (m_taintselected)
1323 {
1324 // Body.setCollisionFlags((int)ContactFlags.CF_NO_CONTACT_RESPONSE);
1325 disableBodySoft();
1326
1327 }
1328 else
1329 {
1330 // Body.setCollisionFlags(0 | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK);
1331 enableBodySoft();
1332 }
1333 m_isSelected = m_taintselected;
1334
1335 }
1336
1337 private void changevelocity(float timestep)
1338 {
1339 if (!m_isSelected)
1340 {
1341 if (IsPhysical)
1342 {
1343 if (Body != null && Body.Handle != IntPtr.Zero)
1344 {
1345 tempLinearVelocity2.setValue(m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
1346 Body.setLinearVelocity(tempLinearVelocity2);
1347 }
1348 }
1349
1350 //resetCollisionAccounting();
1351 }
1352 m_taintVelocity = Vector3.Zero;
1353 }
1354
1355 private void changelink(float timestep)
1356 {
1357 if (IsPhysical)
1358 {
1359 // Construction of new prim
1360 if (Body != null)
1361 {
1362 if (Body.Handle != IntPtr.Zero)
1363 {
1364 DisableAxisMotor();
1365 _parent_scene.removeFromWorld(this, Body);
1366 //Body.Dispose();
1367 }
1368 //Body = null;
1369 // TODO: dispose parts that make up body
1370 }
1371
1372 if (_parent == null && m_taintparent != null)
1373 {
1374
1375 if (m_taintparent is BulletDotNETPrim)
1376 {
1377 BulletDotNETPrim obj = (BulletDotNETPrim)m_taintparent;
1378 obj.ParentPrim(this);
1379 childPrim = true;
1380
1381 }
1382 }
1383 else if (_parent != null && m_taintparent == null)
1384 {
1385 if (_parent is BulletDotNETPrim)
1386 {
1387 BulletDotNETPrim obj = (BulletDotNETPrim)_parent;
1388 obj.ChildDelink(obj);
1389
1390 childPrim = false;
1391 }
1392 }
1393
1394 if (m_taintparent != null)
1395 {
1396 Vector3 taintparentPosition = m_taintparent.Position;
1397 taintparentPosition.Z = m_taintparent.Position.Z + 0.02f;
1398 m_taintparent.Position = taintparentPosition;
1399 _parent_scene.AddPhysicsActorTaint(m_taintparent);
1400 }
1401 }
1402 _parent = m_taintparent;
1403
1404 m_taintPhysics = m_isphysical;
1405
1406 }
1407
1408 private void changefloatonwater(float timestep)
1409 {
1410 // TODO: throw new NotImplementedException();
1411 }
1412
1413 private void changeAngularLock(float timestep)
1414 {
1415 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
1416 {
1417 if (_parent == null)
1418 {
1419 if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f))
1420 {
1421 //d.BodySetFiniteRotationMode(Body, 0);
1422 //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z);
1423 EnableAxisMotor(m_taintAngularLock);
1424 }
1425 else
1426 {
1427 DisableAxisMotor();
1428 }
1429 }
1430
1431 }
1432 m_angularlock = m_taintAngularLock;
1433
1434 }
1435 #endregion
1436
1437
1438
1439
1440 internal void Move(float timestep)
1441 {
1442 //TODO:
1443 float fx = 0;
1444 float fy = 0;
1445 float fz = 0;
1446
1447 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero && !m_isSelected)
1448 {
1449 float m_mass = CalculateMass();
1450
1451 fz = 0f;
1452 //m_log.Info(m_collisionFlags.ToString());
1453
1454 if (m_buoyancy != 0)
1455 {
1456 if (m_buoyancy > 0)
1457 {
1458 fz = (((-1 * _parent_scene.gravityz) * m_buoyancy) * m_mass) * 0.035f;
1459
1460 //d.Vector3 l_velocity = d.BodyGetLinearVel(Body);
1461 //m_log.Info("Using Buoyancy: " + buoyancy + " G: " + (_parent_scene.gravityz * m_buoyancy) + "mass:" + m_mass + " Pos: " + Position.ToString());
1462 }
1463 else
1464 {
1465 fz = (-1 * (((-1 * _parent_scene.gravityz) * (-1 * m_buoyancy)) * m_mass) * 0.035f);
1466 }
1467 }
1468
1469 if (m_usePID)
1470 {
1471 PID_D = 61f;
1472 PID_G = 65f;
1473 //if (!d.BodyIsEnabled(Body))
1474 //d.BodySetForce(Body, 0f, 0f, 0f);
1475 // If we're using the PID controller, then we have no gravity
1476 fz = ((-1 * _parent_scene.gravityz) * m_mass) * 1.025f;
1477
1478 // no lock; for now it's only called from within Simulate()
1479
1480 // If the PID Controller isn't active then we set our force
1481 // calculating base velocity to the current position
1482
1483 if ((m_PIDTau < 1) && (m_PIDTau != 0))
1484 {
1485 //PID_G = PID_G / m_PIDTau;
1486 m_PIDTau = 1;
1487 }
1488
1489 if ((PID_G - m_PIDTau) <= 0)
1490 {
1491 PID_G = m_PIDTau + 1;
1492 }
1493
1494 // TODO: NEED btVector3 for Linear Velocity
1495 // NEED btVector3 for Position
1496
1497 Vector3 pos = _position; //TODO: Insert values gotten from bullet
1498 Vector3 vel = _velocity;
1499
1500 _target_velocity =
1501 new Vector3(
1502 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1503 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1504 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1505 );
1506
1507 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
1508 {
1509
1510 /* TODO: Do Bullet equiv
1511 *
1512 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1513 d.BodySetLinearVel(Body, 0, 0, 0);
1514 d.BodyAddForce(Body, 0, 0, fz);
1515 return;
1516 */
1517 }
1518 else
1519 {
1520 _zeroFlag = false;
1521
1522 fx = ((_target_velocity.X) - vel.X) * (PID_D);
1523 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1524 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1525
1526 }
1527
1528 }
1529
1530 if (m_useHoverPID && !m_usePID)
1531 {
1532 // If we're using the PID controller, then we have no gravity
1533 fz = (-1 * _parent_scene.gravityz) * m_mass;
1534
1535 // no lock; for now it's only called from within Simulate()
1536
1537 // If the PID Controller isn't active then we set our force
1538 // calculating base velocity to the current position
1539
1540 if ((m_PIDTau < 1))
1541 {
1542 PID_G = PID_G / m_PIDTau;
1543 }
1544
1545 if ((PID_G - m_PIDTau) <= 0)
1546 {
1547 PID_G = m_PIDTau + 1;
1548 }
1549 Vector3 pos = Vector3.Zero; //TODO: Insert values gotten from bullet
1550 Vector3 vel = Vector3.Zero;
1551
1552 // determine what our target height really is based on HoverType
1553 switch (m_PIDHoverType)
1554 {
1555 case PIDHoverType.Absolute:
1556 m_targetHoverHeight = m_PIDHoverHeight;
1557 break;
1558 case PIDHoverType.Ground:
1559 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1560 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1561 break;
1562 case PIDHoverType.GroundAndWater:
1563 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1564 m_waterHeight = _parent_scene.GetWaterLevel();
1565 if (m_groundHeight > m_waterHeight)
1566 {
1567 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1568 }
1569 else
1570 {
1571 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1572 }
1573 break;
1574 case PIDHoverType.Water:
1575 m_waterHeight = _parent_scene.GetWaterLevel();
1576 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1577 break;
1578 }
1579
1580
1581 _target_velocity =
1582 new Vector3(0.0f, 0.0f,
1583 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1584 );
1585
1586 // if velocity is zero, use position control; otherwise, velocity control
1587
1588 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
1589 {
1590
1591 /* TODO: Do Bullet Equiv
1592 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1593 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1594 d.BodyAddForce(Body, 0, 0, fz);
1595 */
1596 if (Body != null && Body.Handle != IntPtr.Zero)
1597 {
1598 Body.setLinearVelocity(_parent_scene.VectorZero);
1599 Body.clearForces();
1600 }
1601 return;
1602 }
1603 else
1604 {
1605 _zeroFlag = false;
1606
1607 // We're flying and colliding with something
1608 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1609 }
1610 }
1611
1612 fx *= m_mass;
1613 fy *= m_mass;
1614 //fz *= m_mass;
1615
1616 fx += m_force.X;
1617 fy += m_force.Y;
1618 fz += m_force.Z;
1619
1620 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1621 if (fx != 0 || fy != 0 || fz != 0)
1622 {
1623 /*
1624 * TODO: Do Bullet Equiv
1625 if (!d.BodyIsEnabled(Body))
1626 {
1627 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1628 d.BodySetForce(Body, 0, 0, 0);
1629 enableBodySoft();
1630 }
1631 */
1632 if (!Body.isActive())
1633 {
1634 Body.clearForces();
1635 enableBodySoft();
1636 }
1637 // 35x10 = 350n times the mass per second applied maximum.
1638
1639 float nmax = 35f * m_mass;
1640 float nmin = -35f * m_mass;
1641
1642
1643 if (fx > nmax)
1644 fx = nmax;
1645 if (fx < nmin)
1646 fx = nmin;
1647 if (fy > nmax)
1648 fy = nmax;
1649 if (fy < nmin)
1650 fy = nmin;
1651
1652 // TODO: Do Bullet Equiv
1653 // d.BodyAddForce(Body, fx, fy, fz);
1654 if (Body != null && Body.Handle != IntPtr.Zero)
1655 {
1656 Body.activate(true);
1657 if (tempAddForce != null && tempAddForce.Handle != IntPtr.Zero)
1658 tempAddForce.Dispose();
1659
1660 tempAddForce = new btVector3(fx * 0.01f, fy * 0.01f, fz * 0.01f);
1661 Body.applyCentralImpulse(tempAddForce);
1662 }
1663 }
1664 else
1665 {
1666 // if no forces on the prim, make sure everything is zero
1667 Body.clearForces();
1668 enableBodySoft();
1669 }
1670 }
1671 else
1672 {
1673 if (m_zeroPosition == null)
1674 m_zeroPosition = Vector3.Zero;
1675 m_zeroPosition = _position;
1676 return;
1677 }
1678 }
1679
1680
1681
1682
1683 #region Mass Calculation
1684
1685 private float CalculateMass()
1686 {
1687 float volume = 0;
1688
1689 // No material is passed to the physics engines yet.. soo..
1690 // we're using the m_density constant in the class definition
1691
1692 float returnMass = 0;
1693
1694 switch (_pbs.ProfileShape)
1695 {
1696 case ProfileShape.Square:
1697 // Profile Volume
1698
1699 volume = _size.X * _size.Y * _size.Z;
1700
1701 // If the user has 'hollowed out'
1702 // ProfileHollow is one of those 0 to 50000 values :P
1703 // we like percentages better.. so turning into a percentage
1704
1705 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
1706 {
1707 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
1708
1709 // calculate the hollow volume by it's shape compared to the prim shape
1710 float hollowVolume = 0;
1711 switch (_pbs.HollowShape)
1712 {
1713 case HollowShape.Square:
1714 case HollowShape.Same:
1715 // Cube Hollow volume calculation
1716 float hollowsizex = _size.X * hollowAmount;
1717 float hollowsizey = _size.Y * hollowAmount;
1718 float hollowsizez = _size.Z * hollowAmount;
1719 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1720 break;
1721
1722 case HollowShape.Circle:
1723 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1724 // Cyllinder hollow volume calculation
1725 float hRadius = _size.X / 2;
1726 float hLength = _size.Z;
1727
1728 // pi * r2 * h
1729 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
1730 break;
1731
1732 case HollowShape.Triangle:
1733 // Equilateral Triangular Prism volume hollow calculation
1734 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1735
1736 float aLength = _size.Y;
1737 // 1/2 abh
1738 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1739 break;
1740
1741 default:
1742 hollowVolume = 0;
1743 break;
1744 }
1745 volume = volume - hollowVolume;
1746 }
1747
1748 break;
1749 case ProfileShape.Circle:
1750 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1751 {
1752 // Cylinder
1753 float volume1 = (float)(Math.PI * Math.Pow(_size.X / 2, 2) * _size.Z);
1754 float volume2 = (float)(Math.PI * Math.Pow(_size.Y / 2, 2) * _size.Z);
1755
1756 // Approximating the cylinder's irregularity.
1757 if (volume1 > volume2)
1758 {
1759 volume = (float)volume1 - (volume1 - volume2);
1760 }
1761 else if (volume2 > volume1)
1762 {
1763 volume = (float)volume2 - (volume2 - volume1);
1764 }
1765 else
1766 {
1767 // Regular cylinder
1768 volume = volume1;
1769 }
1770 }
1771 else
1772 {
1773 // We don't know what the shape is yet, so use default
1774 volume = _size.X * _size.Y * _size.Z;
1775 }
1776 // If the user has 'hollowed out'
1777 // ProfileHollow is one of those 0 to 50000 values :P
1778 // we like percentages better.. so turning into a percentage
1779
1780 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
1781 {
1782 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
1783
1784 // calculate the hollow volume by it's shape compared to the prim shape
1785 float hollowVolume = 0;
1786 switch (_pbs.HollowShape)
1787 {
1788 case HollowShape.Same:
1789 case HollowShape.Circle:
1790 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1791 // Cyllinder hollow volume calculation
1792 float hRadius = _size.X / 2;
1793 float hLength = _size.Z;
1794
1795 // pi * r2 * h
1796 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
1797 break;
1798
1799 case HollowShape.Square:
1800 // Cube Hollow volume calculation
1801 float hollowsizex = _size.X * hollowAmount;
1802 float hollowsizey = _size.Y * hollowAmount;
1803 float hollowsizez = _size.Z * hollowAmount;
1804 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1805 break;
1806
1807 case HollowShape.Triangle:
1808 // Equilateral Triangular Prism volume hollow calculation
1809 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1810
1811 float aLength = _size.Y;
1812 // 1/2 abh
1813 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1814 break;
1815
1816 default:
1817 hollowVolume = 0;
1818 break;
1819 }
1820 volume = volume - hollowVolume;
1821 }
1822 break;
1823
1824 case ProfileShape.HalfCircle:
1825 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1826 {
1827 if (_size.X == _size.Y && _size.Z == _size.X)
1828 {
1829 // regular sphere
1830 // v = 4/3 * pi * r^3
1831 float sradius3 = (float)Math.Pow((_size.X / 2), 3);
1832 volume = (float)((4 / 3f) * Math.PI * sradius3);
1833 }
1834 else
1835 {
1836 // we treat this as a box currently
1837 volume = _size.X * _size.Y * _size.Z;
1838 }
1839 }
1840 else
1841 {
1842 // We don't know what the shape is yet, so use default
1843 volume = _size.X * _size.Y * _size.Z;
1844 }
1845 break;
1846
1847 case ProfileShape.EquilateralTriangle:
1848 /*
1849 v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h
1850
1851 // seed mesh
1852 Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
1853 Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
1854 Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
1855 */
1856 float xA = -0.25f * _size.X;
1857 float yA = -0.45f * _size.Y;
1858
1859 float xB = 0.5f * _size.X;
1860 float yB = 0;
1861
1862 float xC = -0.25f * _size.X;
1863 float yC = 0.45f * _size.Y;
1864
1865 volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z);
1866
1867 // If the user has 'hollowed out'
1868 // ProfileHollow is one of those 0 to 50000 values :P
1869 // we like percentages better.. so turning into a percentage
1870 float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f);
1871 if (((float)fhollowFactor / 50000f) > 0.0)
1872 {
1873 float hollowAmount = (float)fhollowFactor / 50000f;
1874
1875 // calculate the hollow volume by it's shape compared to the prim shape
1876 float hollowVolume = 0;
1877 switch (_pbs.HollowShape)
1878 {
1879 case HollowShape.Same:
1880 case HollowShape.Triangle:
1881 // Equilateral Triangular Prism volume hollow calculation
1882 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1883
1884 float aLength = _size.Y;
1885 // 1/2 abh
1886 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1887 break;
1888
1889 case HollowShape.Square:
1890 // Cube Hollow volume calculation
1891 float hollowsizex = _size.X * hollowAmount;
1892 float hollowsizey = _size.Y * hollowAmount;
1893 float hollowsizez = _size.Z * hollowAmount;
1894 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1895 break;
1896
1897 case HollowShape.Circle:
1898 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1899 // Cyllinder hollow volume calculation
1900 float hRadius = _size.X / 2;
1901 float hLength = _size.Z;
1902
1903 // pi * r2 * h
1904 hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength) / 2) * hollowAmount);
1905 break;
1906
1907 default:
1908 hollowVolume = 0;
1909 break;
1910 }
1911 volume = volume - hollowVolume;
1912 }
1913 break;
1914
1915 default:
1916 // we don't have all of the volume formulas yet so
1917 // use the common volume formula for all
1918 volume = _size.X * _size.Y * _size.Z;
1919 break;
1920 }
1921
1922 // Calculate Path cut effect on volume
1923 // Not exact, in the triangle hollow example
1924 // They should never be zero or less then zero..
1925 // we'll ignore it if it's less then zero
1926
1927 // ProfileEnd and ProfileBegin are values
1928 // from 0 to 50000
1929
1930 // Turning them back into percentages so that I can cut that percentage off the volume
1931
1932 float PathCutEndAmount = _pbs.ProfileEnd;
1933 float PathCutStartAmount = _pbs.ProfileBegin;
1934 if (((PathCutStartAmount + PathCutEndAmount) / 50000f) > 0.0f)
1935 {
1936 float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount) / 50000f);
1937
1938 // Check the return amount for sanity
1939 if (pathCutAmount >= 0.99f)
1940 pathCutAmount = 0.99f;
1941
1942 volume = volume - (volume * pathCutAmount);
1943 }
1944 UInt16 taperX = _pbs.PathScaleX;
1945 UInt16 taperY = _pbs.PathScaleY;
1946 float taperFactorX = 0;
1947 float taperFactorY = 0;
1948
1949 // Mass = density * volume
1950 if (taperX != 100)
1951 {
1952 if (taperX > 100)
1953 {
1954 taperFactorX = 1.0f - ((float)taperX / 200);
1955 //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
1956 }
1957 else
1958 {
1959 taperFactorX = 1.0f - ((100 - (float)taperX) / 100);
1960 //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
1961 }
1962 volume = (float)volume * ((taperFactorX / 3f) + 0.001f);
1963 }
1964
1965 if (taperY != 100)
1966 {
1967 if (taperY > 100)
1968 {
1969 taperFactorY = 1.0f - ((float)taperY / 200);
1970 //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
1971 }
1972 else
1973 {
1974 taperFactorY = 1.0f - ((100 - (float)taperY) / 100);
1975 //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
1976 }
1977 volume = (float)volume * ((taperFactorY / 3f) + 0.001f);
1978 }
1979 returnMass = m_density * volume;
1980 if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1981
1982
1983
1984 // Recursively calculate mass
1985 bool HasChildPrim = false;
1986 lock (childrenPrim)
1987 {
1988 if (childrenPrim.Count > 0)
1989 {
1990 HasChildPrim = true;
1991 }
1992
1993 }
1994 if (HasChildPrim)
1995 {
1996 BulletDotNETPrim[] childPrimArr = new BulletDotNETPrim[0];
1997
1998 lock (childrenPrim)
1999 childPrimArr = childrenPrim.ToArray();
2000
2001 for (int i = 0; i < childPrimArr.Length; i++)
2002 {
2003 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
2004 returnMass += childPrimArr[i].CalculateMass();
2005 // failsafe, this shouldn't happen but with OpenSim, you never know :)
2006 if (i > 256)
2007 break;
2008 }
2009 }
2010
2011
2012
2013
2014
2015 return returnMass;
2016 }
2017
2018 #endregion
2019
2020
2021 public void CreateGeom(IntPtr m_targetSpace, IMesh p_mesh)
2022 {
2023 // m_log.Debug("[PHYSICS]: _________CreateGeom");
2024 if (p_mesh != null)
2025 {
2026 //_mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
2027 _mesh = p_mesh;
2028 setMesh(_parent_scene, _mesh);
2029
2030 }
2031 else
2032 {
2033 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
2034 {
2035 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
2036 {
2037 if (((_size.X / 2f) > 0f))
2038 {
2039 //SetGeom to a Regular Sphere
2040 if (tempSize1 == null)
2041 tempSize1 = new btVector3(0, 0, 0);
2042 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2043 SetCollisionShape(new btSphereShape(_size.X * 0.5f));
2044 }
2045 else
2046 {
2047 // uses halfextents
2048 if (tempSize1 == null)
2049 tempSize1 = new btVector3(0, 0, 0);
2050 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2051 SetCollisionShape(new btBoxShape(tempSize1));
2052 }
2053 }
2054 else
2055 {
2056 // uses halfextents
2057 if (tempSize1 == null)
2058 tempSize1 = new btVector3(0, 0, 0);
2059 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2060 SetCollisionShape(new btBoxShape(tempSize1));
2061 }
2062
2063 }
2064 else
2065 {
2066 if (tempSize1 == null)
2067 tempSize1 = new btVector3(0, 0, 0);
2068 // uses halfextents
2069 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2070 SetCollisionShape(new btBoxShape(tempSize1));
2071 }
2072 }
2073 }
2074
2075 private void setMesh(BulletDotNETScene _parent_scene, IMesh mesh)
2076 {
2077 // TODO: Set Collision Body Mesh
2078 // This sleeper is there to moderate how long it takes between
2079 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
2080 // m_log.Debug("_________SetMesh");
2081 Thread.Sleep(10);
2082
2083 //Kill Body so that mesh can re-make the geom
2084 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
2085 {
2086 if (childPrim)
2087 {
2088 if (_parent != null)
2089 {
2090 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
2091 parent.ChildDelink(this);
2092 }
2093 }
2094 else
2095 {
2096 //disableBody();
2097 }
2098 }
2099
2100 //IMesh oldMesh = primMesh;
2101
2102 //primMesh = mesh;
2103
2104 //float[] vertexList = primMesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
2105 //int[] indexList = primMesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
2106 ////Array.Reverse(indexList);
2107 //primMesh.releaseSourceMeshData(); // free up the original mesh data to save memory
2108
2109 IMesh oldMesh = primMesh;
2110
2111 primMesh = mesh;
2112
2113 float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
2114 int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
2115 //Array.Reverse(indexList);
2116 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
2117
2118
2119 int VertexCount = vertexList.GetLength(0) / 3;
2120 int IndexCount = indexList.GetLength(0);
2121
2122 if (btshapeArray != null && btshapeArray.Handle != IntPtr.Zero)
2123 btshapeArray.Dispose();
2124 //Array.Reverse(indexList);
2125 btshapeArray = new btTriangleIndexVertexArray(IndexCount / 3, indexList, (3 * sizeof(int)),
2126 VertexCount, vertexList, 3 * sizeof(float));
2127 SetCollisionShape(new btGImpactMeshShape(btshapeArray));
2128 //((btGImpactMeshShape) prim_geom).updateBound();
2129 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1));
2130 ((btGImpactMeshShape)prim_geom).updateBound();
2131 _parent_scene.SetUsingGImpact();
2132 //if (oldMesh != null)
2133 //{
2134 // oldMesh.releasePinned();
2135 // oldMesh = null;
2136 //}
2137
2138 }
2139
2140 private void SetCollisionShape(btCollisionShape shape)
2141 {
2142 /*
2143 if (shape == null)
2144 m_log.Debug("[PHYSICS]:SetShape!Null");
2145 else
2146 m_log.Debug("[PHYSICS]:SetShape!");
2147
2148 if (Body != null)
2149 {
2150 DisposeOfBody();
2151 }
2152
2153 if (prim_geom != null)
2154 {
2155 prim_geom.Dispose();
2156 prim_geom = null;
2157 }
2158 */
2159 prim_geom = shape;
2160
2161 //Body.set
2162 }
2163
2164 public void SetBody(float mass)
2165 {
2166
2167 if (!IsPhysical || childrenPrim.Count == 0)
2168 {
2169 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
2170 tempMotionState1.Dispose();
2171 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
2172 tempTransform2.Dispose();
2173 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
2174 tempOrientation2.Dispose();
2175
2176 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
2177 tempPosition2.Dispose();
2178
2179 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
2180 tempPosition2 = new btVector3(_position.X, _position.Y, _position.Z);
2181 tempTransform2 = new btTransform(tempOrientation2, tempPosition2);
2182 tempMotionState1 = new btDefaultMotionState(tempTransform2, _parent_scene.TransZero);
2183 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
2184 tempInertia1.Dispose();
2185 tempInertia1 = new btVector3(0, 0, 0);
2186
2187
2188 prim_geom.calculateLocalInertia(mass, tempInertia1);
2189
2190 if (mass != 0)
2191 _parent_scene.addActivePrim(this);
2192 else
2193 _parent_scene.remActivePrim(this);
2194
2195 // Body = new btRigidBody(mass, tempMotionState1, prim_geom);
2196 //else
2197 // Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2198 if (Body == null)
2199 {
2200 Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2201 // add localID so we can later map bullet object back to OpenSim object
2202 Body.setUserPointer(new IntPtr((int)m_localID));
2203 }
2204
2205
2206 if (prim_geom is btGImpactMeshShape)
2207 {
2208 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1));
2209 ((btGImpactMeshShape)prim_geom).updateBound();
2210 }
2211 //Body.setCollisionFlags(Body.getCollisionFlags() | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK);
2212 //Body.setUserPointer((IntPtr) (int)m_localID);
2213 _parent_scene.AddPrimToScene(this);
2214 }
2215 else
2216 {
2217 // bool hasTrimesh = false;
2218 lock (childrenPrim)
2219 {
2220 foreach (BulletDotNETPrim chld in childrenPrim)
2221 {
2222 if (chld == null)
2223 continue;
2224
2225 // if (chld.NeedsMeshing())
2226 // hasTrimesh = true;
2227 }
2228 }
2229
2230 //if (hasTrimesh)
2231 //{
2232 ProcessGeomCreationAsTriMesh(Vector3.Zero, Quaternion.Identity);
2233 // createmesh returns null when it doesn't mesh.
2234
2235 /*
2236 if (_mesh is Mesh)
2237 {
2238 }
2239 else
2240 {
2241 m_log.Warn("[PHYSICS]: Can't link a OpenSim.Region.Physics.Meshing.Mesh object");
2242 return;
2243 }
2244 */
2245
2246
2247
2248 foreach (BulletDotNETPrim chld in childrenPrim)
2249 {
2250 if (chld == null)
2251 continue;
2252 Vector3 offset = chld.Position - Position;
2253 Vector3 pos = new Vector3(offset.X, offset.Y, offset.Z);
2254 pos *= Quaternion.Inverse(Orientation);
2255 //pos *= Orientation;
2256 offset = pos;
2257 chld.ProcessGeomCreationAsTriMesh(offset, chld.Orientation);
2258
2259 _mesh.Append(chld._mesh);
2260
2261
2262 }
2263 setMesh(_parent_scene, _mesh);
2264
2265 //}
2266
2267 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
2268 tempMotionState1.Dispose();
2269 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
2270 tempTransform2.Dispose();
2271 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
2272 tempOrientation2.Dispose();
2273
2274 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
2275 tempPosition2.Dispose();
2276
2277 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
2278 tempPosition2 = new btVector3(_position.X, _position.Y, _position.Z);
2279 tempTransform2 = new btTransform(tempOrientation2, tempPosition2);
2280 tempMotionState1 = new btDefaultMotionState(tempTransform2, _parent_scene.TransZero);
2281 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
2282 tempInertia1.Dispose();
2283 tempInertia1 = new btVector3(0, 0, 0);
2284
2285
2286 prim_geom.calculateLocalInertia(mass, tempInertia1);
2287
2288 if (mass != 0)
2289 _parent_scene.addActivePrim(this);
2290 else
2291 _parent_scene.remActivePrim(this);
2292
2293 // Body = new btRigidBody(mass, tempMotionState1, prim_geom);
2294 //else
2295 // Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2296 if (Body == null)
2297 {
2298 Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2299 // each body has the localID stored into it so we can identify collision objects
2300 Body.setUserPointer(new IntPtr((int)m_localID));
2301 }
2302
2303 if (prim_geom is btGImpactMeshShape)
2304 {
2305 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1));
2306 ((btGImpactMeshShape)prim_geom).updateBound();
2307 }
2308 _parent_scene.AddPrimToScene(this);
2309
2310 }
2311
2312 if (IsPhysical)
2313 changeAngularLock(0);
2314 }
2315
2316 private void DisposeOfBody()
2317 {
2318 if (Body != null)
2319 {
2320 if (Body.Handle != IntPtr.Zero)
2321 {
2322 DisableAxisMotor();
2323 _parent_scene.removeFromWorld(this, Body);
2324 Body.Dispose();
2325 }
2326 Body = null;
2327 // TODO: dispose parts that make up body
2328 }
2329 }
2330
2331 private void ChildDelink(BulletDotNETPrim pPrim)
2332 {
2333 // Okay, we have a delinked child.. need to rebuild the body.
2334 lock (childrenPrim)
2335 {
2336 foreach (BulletDotNETPrim prm in childrenPrim)
2337 {
2338 prm.childPrim = true;
2339 prm.disableBody();
2340
2341 }
2342 }
2343 disableBody();
2344
2345 lock (childrenPrim)
2346 {
2347 childrenPrim.Remove(pPrim);
2348 }
2349
2350
2351
2352
2353 if (Body != null && Body.Handle != IntPtr.Zero)
2354 {
2355 _parent_scene.remActivePrim(this);
2356 }
2357
2358
2359
2360 lock (childrenPrim)
2361 {
2362 foreach (BulletDotNETPrim prm in childrenPrim)
2363 {
2364 ParentPrim(prm);
2365 }
2366 }
2367
2368 }
2369
2370 internal void ParentPrim(BulletDotNETPrim prm)
2371 {
2372 if (prm == null)
2373 return;
2374
2375
2376
2377 lock (childrenPrim)
2378 {
2379 if (!childrenPrim.Contains(prm))
2380 {
2381 childrenPrim.Add(prm);
2382 }
2383 }
2384
2385
2386 }
2387
2388 public void disableBody()
2389 {
2390 //this kills the body so things like 'mesh' can re-create it.
2391 /*
2392 lock (this)
2393 {
2394 if (!childPrim)
2395 {
2396 if (Body != null && Body.Handle != IntPtr.Zero)
2397 {
2398 _parent_scene.remActivePrim(this);
2399
2400 m_collisionCategories &= ~CollisionCategories.Body;
2401 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
2402
2403 if (prim_geom != null && prim_geom.Handle != IntPtr.Zero)
2404 {
2405 // TODO: Set Category bits and Flags
2406 }
2407
2408 // TODO: destroy body
2409 DisposeOfBody();
2410
2411 lock (childrenPrim)
2412 {
2413 if (childrenPrim.Count > 0)
2414 {
2415 foreach (BulletDotNETPrim prm in childrenPrim)
2416 {
2417 _parent_scene.remActivePrim(prm);
2418 prm.DisposeOfBody();
2419 prm.SetCollisionShape(null);
2420 }
2421 }
2422
2423 }
2424
2425 DisposeOfBody();
2426 }
2427 }
2428 else
2429 {
2430 _parent_scene.remActivePrim(this);
2431 m_collisionCategories &= ~CollisionCategories.Body;
2432 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
2433
2434 if (prim_geom != null && prim_geom.Handle != IntPtr.Zero)
2435 {
2436 // TODO: Set Category bits and Flags
2437 }
2438
2439 DisposeOfBody();
2440 }
2441
2442 }
2443 */
2444 DisableAxisMotor();
2445 m_disabled = true;
2446 m_collisionscore = 0;
2447 }
2448
2449 public void disableBodySoft()
2450 {
2451 m_disabled = true;
2452
2453 if (m_isphysical && Body.Handle != IntPtr.Zero)
2454 {
2455 Body.clearForces();
2456 Body.forceActivationState(0);
2457
2458 }
2459
2460 }
2461
2462 public void enableBodySoft()
2463 {
2464 if (!childPrim)
2465 {
2466 if (m_isphysical && Body.Handle != IntPtr.Zero)
2467 {
2468 Body.clearForces();
2469 Body.forceActivationState(4);
2470 forceenable = true;
2471
2472 }
2473 m_disabled = false;
2474 }
2475 }
2476
2477 public void enableBody()
2478 {
2479 if (!childPrim)
2480 {
2481 //SetCollisionShape(prim_geom);
2482 if (IsPhysical)
2483 SetBody(Mass);
2484 else
2485 SetBody(0);
2486
2487 // TODO: Set Collision Category Bits and Flags
2488 // TODO: Set Auto Disable data
2489
2490 m_interpenetrationcount = 0;
2491 m_collisionscore = 0;
2492 m_disabled = false;
2493 // The body doesn't already have a finite rotation mode set here
2494 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
2495 {
2496 // TODO: Create Angular Motor on Axis Lock!
2497 }
2498 _parent_scene.addActivePrim(this);
2499 }
2500 }
2501
2502 public void UpdatePositionAndVelocity()
2503 {
2504 if (!m_isSelected)
2505 {
2506 if (_parent == null)
2507 {
2508 Vector3 pv = Vector3.Zero;
2509 bool lastZeroFlag = _zeroFlag;
2510 if (tempPosition3 != null && tempPosition3.Handle != IntPtr.Zero)
2511 tempPosition3.Dispose();
2512 if (tempTransform3 != null && tempTransform3.Handle != IntPtr.Zero)
2513 tempTransform3.Dispose();
2514
2515 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
2516 tempOrientation2.Dispose();
2517
2518 if (tempAngularVelocity1 != null && tempAngularVelocity1.Handle != IntPtr.Zero)
2519 tempAngularVelocity1.Dispose();
2520
2521 if (tempLinearVelocity1 != null && tempLinearVelocity1.Handle != IntPtr.Zero)
2522 tempLinearVelocity1.Dispose();
2523
2524
2525
2526 tempTransform3 = Body.getInterpolationWorldTransform();
2527 tempPosition3 = tempTransform3.getOrigin(); // vec
2528 tempOrientation2 = tempTransform3.getRotation(); // ori
2529 tempAngularVelocity1 = Body.getInterpolationAngularVelocity(); //rotvel
2530 tempLinearVelocity1 = Body.getInterpolationLinearVelocity(); // vel
2531
2532 _torque = new Vector3(tempAngularVelocity1.getX(), tempAngularVelocity1.getX(),
2533 tempAngularVelocity1.getZ());
2534 Vector3 l_position = Vector3.Zero;
2535 Quaternion l_orientation = Quaternion.Identity;
2536 m_lastposition = _position;
2537 m_lastorientation = _orientation;
2538
2539 l_position.X = tempPosition3.getX();
2540 l_position.Y = tempPosition3.getY();
2541 l_position.Z = tempPosition3.getZ();
2542 l_orientation.X = tempOrientation2.getX();
2543 l_orientation.Y = tempOrientation2.getY();
2544 l_orientation.Z = tempOrientation2.getZ();
2545 l_orientation.W = tempOrientation2.getW();
2546
2547 if (l_position.X > ((int)Constants.RegionSize - 0.05f) || l_position.X < 0f || l_position.Y > ((int)Constants.RegionSize - 0.05f) || l_position.Y < 0f)
2548 {
2549 //base.RaiseOutOfBounds(l_position);
2550
2551 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2552 {
2553 _position = l_position;
2554 //_parent_scene.remActivePrim(this);
2555 if (_parent == null)
2556 base.RequestPhysicsterseUpdate();
2557 return;
2558 }
2559 else
2560 {
2561 if (_parent == null)
2562 base.RaiseOutOfBounds(l_position);
2563 return;
2564 }
2565 }
2566
2567 if (l_position.Z < -200000f)
2568 {
2569 // This is so prim that get lost underground don't fall forever and suck up
2570 //
2571 // Sim resources and memory.
2572 // Disables the prim's movement physics....
2573 // It's a hack and will generate a console message if it fails.
2574
2575 //IsPhysical = false;
2576 //if (_parent == null)
2577 //base.RaiseOutOfBounds(_position);
2578
2579 _acceleration.X = 0;
2580 _acceleration.Y = 0;
2581 _acceleration.Z = 0;
2582
2583 _velocity.X = 0;
2584 _velocity.Y = 0;
2585 _velocity.Z = 0;
2586 m_rotationalVelocity.X = 0;
2587 m_rotationalVelocity.Y = 0;
2588 m_rotationalVelocity.Z = 0;
2589
2590 if (_parent == null)
2591 base.RequestPhysicsterseUpdate();
2592
2593 m_throttleUpdates = false;
2594 // throttleCounter = 0;
2595 _zeroFlag = true;
2596 //outofBounds = true;
2597 }
2598
2599 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2600 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2601 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
2602 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01))
2603 {
2604 _zeroFlag = true;
2605 m_throttleUpdates = false;
2606 }
2607 else
2608 {
2609 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
2610 _zeroFlag = false;
2611 }
2612
2613 if (_zeroFlag)
2614 {
2615 _velocity.X = 0.0f;
2616 _velocity.Y = 0.0f;
2617 _velocity.Z = 0.0f;
2618
2619 _acceleration.X = 0;
2620 _acceleration.Y = 0;
2621 _acceleration.Z = 0;
2622
2623 //_orientation.w = 0f;
2624 //_orientation.X = 0f;
2625 //_orientation.Y = 0f;
2626 //_orientation.Z = 0f;
2627 m_rotationalVelocity.X = 0;
2628 m_rotationalVelocity.Y = 0;
2629 m_rotationalVelocity.Z = 0;
2630 if (!m_lastUpdateSent)
2631 {
2632 m_throttleUpdates = false;
2633 // throttleCounter = 0;
2634 m_rotationalVelocity = pv;
2635
2636 if (_parent == null)
2637 base.RequestPhysicsterseUpdate();
2638
2639 m_lastUpdateSent = true;
2640 }
2641 }
2642 else
2643 {
2644 if (lastZeroFlag != _zeroFlag)
2645 {
2646 if (_parent == null)
2647 base.RequestPhysicsterseUpdate();
2648 }
2649
2650 m_lastVelocity = _velocity;
2651
2652 _position = l_position;
2653
2654 _velocity.X = tempLinearVelocity1.getX();
2655 _velocity.Y = tempLinearVelocity1.getY();
2656 _velocity.Z = tempLinearVelocity1.getZ();
2657
2658 _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
2659 _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f,
2660 _velocity.Y - m_lastVelocity.Y / 0.1f,
2661 _velocity.Z - m_lastVelocity.Z / 0.1f);
2662 //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
2663
2664 if (_velocity.ApproxEquals(pv, 0.5f))
2665 {
2666 m_rotationalVelocity = pv;
2667 }
2668 else
2669 {
2670 m_rotationalVelocity = new Vector3(tempAngularVelocity1.getX(), tempAngularVelocity1.getY(), tempAngularVelocity1.getZ());
2671 }
2672
2673 //m_log.Debug("ODE: " + m_rotationalVelocity.ToString());
2674
2675 _orientation.X = l_orientation.X;
2676 _orientation.Y = l_orientation.Y;
2677 _orientation.Z = l_orientation.Z;
2678 _orientation.W = l_orientation.W;
2679 m_lastUpdateSent = false;
2680
2681 //if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
2682 //{
2683 if (_parent == null)
2684 base.RequestPhysicsterseUpdate();
2685 // }
2686 // else
2687 // {
2688 // throttleCounter++;
2689 //}
2690
2691 }
2692 m_lastposition = l_position;
2693 if (forceenable)
2694 {
2695 Body.forceActivationState(1);
2696 forceenable = false;
2697 }
2698 }
2699 else
2700 {
2701 // Not a body.. so Make sure the client isn't interpolating
2702 _velocity.X = 0;
2703 _velocity.Y = 0;
2704 _velocity.Z = 0;
2705
2706 _acceleration.X = 0;
2707 _acceleration.Y = 0;
2708 _acceleration.Z = 0;
2709
2710 m_rotationalVelocity.X = 0;
2711 m_rotationalVelocity.Y = 0;
2712 m_rotationalVelocity.Z = 0;
2713 _zeroFlag = true;
2714 }
2715 }
2716 }
2717
2718
2719 internal void setPrimForRemoval()
2720 {
2721 m_taintremove = true;
2722 }
2723
2724 internal void EnableAxisMotor(Vector3 axislock)
2725 {
2726 if (m_aMotor != null)
2727 DisableAxisMotor();
2728
2729 if (Body == null)
2730 return;
2731
2732 if (Body.Handle == IntPtr.Zero)
2733 return;
2734
2735 if (AxisLockAngleHigh != null && AxisLockAngleHigh.Handle != IntPtr.Zero)
2736 AxisLockAngleHigh.Dispose();
2737
2738
2739
2740 m_aMotor = new btGeneric6DofConstraint(Body, _parent_scene.TerrainBody, _parent_scene.TransZero,
2741 _parent_scene.TransZero, false);
2742
2743 float endNoLock = (360 * Utils.DEG_TO_RAD);
2744 AxisLockAngleHigh = new btVector3((axislock.X == 0) ? 0 : endNoLock, (axislock.Y == 0) ? 0 : endNoLock, (axislock.Z == 0) ? 0 : endNoLock);
2745
2746 m_aMotor.setAngularLowerLimit(_parent_scene.VectorZero);
2747 m_aMotor.setAngularUpperLimit(AxisLockAngleHigh);
2748 m_aMotor.setLinearLowerLimit(AxisLockLinearLow);
2749 m_aMotor.setLinearUpperLimit(AxisLockLinearHigh);
2750 _parent_scene.getBulletWorld().addConstraint((btTypedConstraint)m_aMotor);
2751 //m_aMotor.
2752
2753
2754 }
2755 internal void DisableAxisMotor()
2756 {
2757 if (m_aMotor != null && m_aMotor.Handle != IntPtr.Zero)
2758 {
2759 _parent_scene.getBulletWorld().removeConstraint(m_aMotor);
2760 m_aMotor.Dispose();
2761 m_aMotor = null;
2762 }
2763 }
2764
2765 }
2766}
2767
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
deleted file mode 100644
index 0d1bd82..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
+++ /dev/null
@@ -1,776 +0,0 @@
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.IO;
32using System.Diagnostics;
33using System.Threading;
34using log4net;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Region.Physics.Manager;
38using OpenMetaverse;
39using BulletDotNET;
40
41namespace OpenSim.Region.Physics.BulletDotNETPlugin
42{
43 public class BulletDotNETScene : PhysicsScene
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 // private string m_sceneIdentifier = string.Empty;
48
49 private List<BulletDotNETCharacter> m_characters = new List<BulletDotNETCharacter>();
50 private Dictionary<uint, BulletDotNETCharacter> m_charactersLocalID = new Dictionary<uint, BulletDotNETCharacter>();
51 private List<BulletDotNETPrim> m_prims = new List<BulletDotNETPrim>();
52 private Dictionary<uint, BulletDotNETPrim> m_primsLocalID = new Dictionary<uint, BulletDotNETPrim>();
53 private List<BulletDotNETPrim> m_activePrims = new List<BulletDotNETPrim>();
54 private List<PhysicsActor> m_taintedActors = new List<PhysicsActor>();
55 private btDiscreteDynamicsWorld m_world;
56 private btAxisSweep3 m_broadphase;
57 private btCollisionConfiguration m_collisionConfiguration;
58 private btConstraintSolver m_solver;
59 private btCollisionDispatcher m_dispatcher;
60 private btHeightfieldTerrainShape m_terrainShape;
61 public btRigidBody TerrainBody;
62 private btVector3 m_terrainPosition;
63 private btVector3 m_gravity;
64 public btMotionState m_terrainMotionState;
65 public btTransform m_terrainTransform;
66 public btVector3 VectorZero;
67 public btQuaternion QuatIdentity;
68 public btTransform TransZero;
69
70 public float geomDefaultDensity = 10.000006836f;
71
72 private float avPIDD = 65f;
73 private float avPIDP = 21f;
74 private float avCapRadius = 0.37f;
75 private float avStandupTensor = 2000000f;
76 private float avDensity = 80f;
77 private float avHeightFudgeFactor = 0.52f;
78 private float avMovementDivisorWalk = 1.8f;
79 private float avMovementDivisorRun = 0.8f;
80
81 // private float minimumGroundFlightOffset = 3f;
82
83 public bool meshSculptedPrim = true;
84
85 public float meshSculptLOD = 32;
86 public float MeshSculptphysicalLOD = 16;
87
88 public float bodyPIDD = 35f;
89 public float bodyPIDG = 25;
90 internal int geomCrossingFailuresBeforeOutofbounds = 4;
91
92 public float bodyMotorJointMaxforceTensor = 2;
93
94 public int bodyFramesAutoDisable = 20;
95
96 public float WorldTimeStep = 10f/60f;
97 public const float WorldTimeComp = 1/60f;
98 public float gravityz = -9.8f;
99
100 private float[] _origheightmap; // Used for Fly height. Kitto Flora
101 private bool usingGImpactAlgorithm = false;
102
103 // private IConfigSource m_config;
104 private readonly btVector3 worldAabbMin = new btVector3(-10f, -10f, 0);
105 private readonly btVector3 worldAabbMax = new btVector3((int)Constants.RegionSize + 10f, (int)Constants.RegionSize + 10f, 9000);
106
107 public IMesher mesher;
108 private ContactAddedCallbackHandler m_CollisionInterface;
109
110 public BulletDotNETScene(string sceneIdentifier)
111 {
112 // m_sceneIdentifier = sceneIdentifier;
113 VectorZero = new btVector3(0, 0, 0);
114 QuatIdentity = new btQuaternion(0, 0, 0, 1);
115 TransZero = new btTransform(QuatIdentity, VectorZero);
116 m_gravity = new btVector3(0, 0, gravityz);
117 _origheightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
118
119 }
120
121 public override void Initialise(IMesher meshmerizer, IConfigSource config)
122 {
123 mesher = meshmerizer;
124 // m_config = config;
125 /*
126 if (Environment.OSVersion.Platform == PlatformID.Unix)
127 {
128 m_log.Fatal("[BulletDotNET]: This configuration is not supported on *nix currently");
129 Thread.Sleep(5000);
130 Environment.Exit(0);
131 }
132 */
133 m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, 16000);
134 m_collisionConfiguration = new btDefaultCollisionConfiguration();
135 m_solver = new btSequentialImpulseConstraintSolver();
136 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
137 m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
138 m_world.setGravity(m_gravity);
139 EnableCollisionInterface();
140
141
142 }
143
144 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
145 {
146 BulletDotNETCharacter chr = new BulletDotNETCharacter(avName, this, position, size, avPIDD, avPIDP,
147 avCapRadius, avStandupTensor, avDensity,
148 avHeightFudgeFactor, avMovementDivisorWalk,
149 avMovementDivisorRun);
150 try
151 {
152 m_characters.Add(chr);
153 m_charactersLocalID.Add(chr.m_localID, chr);
154 }
155 catch
156 {
157 // noop if it's already there
158 m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate avatar localID");
159 }
160 AddPhysicsActorTaint(chr);
161 return chr;
162 }
163
164 public override void RemoveAvatar(PhysicsActor actor)
165 {
166 BulletDotNETCharacter chr = (BulletDotNETCharacter) actor;
167
168 m_charactersLocalID.Remove(chr.m_localID);
169 m_characters.Remove(chr);
170 m_world.removeRigidBody(chr.Body);
171 m_world.removeCollisionObject(chr.Body);
172
173 chr.Remove();
174 AddPhysicsActorTaint(chr);
175 //chr = null;
176 }
177
178 public override void RemovePrim(PhysicsActor prim)
179 {
180 if (prim is BulletDotNETPrim)
181 {
182
183 BulletDotNETPrim p = (BulletDotNETPrim)prim;
184
185 p.setPrimForRemoval();
186 AddPhysicsActorTaint(prim);
187 //RemovePrimThreadLocked(p);
188
189 }
190 }
191
192 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
193 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
194 {
195 Vector3 pos = position;
196 //pos.X = position.X;
197 //pos.Y = position.Y;
198 //pos.Z = position.Z;
199 Vector3 siz = Vector3.Zero;
200 siz.X = size.X;
201 siz.Y = size.Y;
202 siz.Z = size.Z;
203 Quaternion rot = rotation;
204
205 BulletDotNETPrim newPrim;
206
207 newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
208
209 //lock (m_prims)
210 // m_prims.Add(newPrim);
211
212
213 return newPrim;
214 }
215
216 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
217 {
218 PhysicsActor result;
219 IMesh mesh = null;
220
221 //switch (pbs.ProfileShape)
222 //{
223 // case ProfileShape.Square:
224 // //support simple box & hollow box now; later, more shapes
225 // if (needsMeshing(pbs))
226 // {
227 // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
228 // }
229
230 // break;
231 //}
232
233 if (needsMeshing(pbs))
234 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
235
236 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
237
238 return result;
239 }
240
241 public override void AddPhysicsActorTaint(PhysicsActor prim)
242 {
243 lock (m_taintedActors)
244 {
245 if (!m_taintedActors.Contains(prim))
246 {
247 m_taintedActors.Add(prim);
248 }
249 }
250 }
251 internal void SetUsingGImpact()
252 {
253 if (!usingGImpactAlgorithm)
254 btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
255 usingGImpactAlgorithm = true;
256 }
257
258 public override float Simulate(float timeStep)
259 {
260
261 lock (m_taintedActors)
262 {
263 foreach (PhysicsActor act in m_taintedActors)
264 {
265 if (act is BulletDotNETCharacter)
266 ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
267 if (act is BulletDotNETPrim)
268 ((BulletDotNETPrim)act).ProcessTaints(timeStep);
269 }
270 m_taintedActors.Clear();
271 }
272
273 lock (m_characters)
274 {
275 foreach (BulletDotNETCharacter chr in m_characters)
276 {
277 chr.Move(timeStep);
278 }
279 }
280
281 lock (m_prims)
282 {
283 foreach (BulletDotNETPrim prim in m_prims)
284 {
285 if (prim != null)
286 prim.Move(timeStep);
287 }
288 }
289 float steps = m_world.stepSimulation(timeStep, 10, WorldTimeComp);
290
291 foreach (BulletDotNETCharacter chr in m_characters)
292 {
293 chr.UpdatePositionAndVelocity();
294 }
295
296 foreach (BulletDotNETPrim prm in m_activePrims)
297 {
298 /*
299 if (prm != null)
300 if (prm.Body != null)
301 */
302 prm.UpdatePositionAndVelocity();
303 }
304 if (m_CollisionInterface != null)
305 {
306 List<BulletDotNETPrim> primsWithCollisions = new List<BulletDotNETPrim>();
307 List<BulletDotNETCharacter> charactersWithCollisions = new List<BulletDotNETCharacter>();
308
309 // get the collisions that happened this tick
310 List<BulletDotNET.ContactAddedCallbackHandler.ContactInfo> collisions = m_CollisionInterface.GetContactList();
311 // passed back the localID of the prim so we can associate the prim
312 foreach (BulletDotNET.ContactAddedCallbackHandler.ContactInfo ci in collisions)
313 {
314 // ContactPoint = { contactPoint, contactNormal, penetrationDepth }
315 ContactPoint contact = new ContactPoint(new Vector3(ci.pX, ci.pY, ci.pZ),
316 new Vector3(ci.nX, ci.nY, ci.nZ), ci.depth);
317
318 ProcessContact(ci.contact, ci.contactWith, contact, ref primsWithCollisions, ref charactersWithCollisions);
319 ProcessContact(ci.contactWith, ci.contact, contact, ref primsWithCollisions, ref charactersWithCollisions);
320
321 }
322 m_CollisionInterface.Clear();
323 // for those prims and characters that had collisions cause collision events
324 foreach (BulletDotNETPrim bdnp in primsWithCollisions)
325 {
326 bdnp.SendCollisions();
327 }
328 foreach (BulletDotNETCharacter bdnc in charactersWithCollisions)
329 {
330 bdnc.SendCollisions();
331 }
332 }
333 return steps;
334 }
335
336 private void ProcessContact(uint cont, uint contWith, ContactPoint contact,
337 ref List<BulletDotNETPrim> primsWithCollisions,
338 ref List<BulletDotNETCharacter> charactersWithCollisions)
339 {
340 BulletDotNETPrim bdnp;
341 // collisions with a normal prim?
342 if (m_primsLocalID.TryGetValue(cont, out bdnp))
343 {
344 // Added collision event to the prim. This creates a pile of events
345 // that will be sent to any subscribed listeners.
346 bdnp.AddCollision(contWith, contact);
347 if (!primsWithCollisions.Contains(bdnp))
348 {
349 primsWithCollisions.Add(bdnp);
350 }
351 }
352 else
353 {
354 BulletDotNETCharacter bdnc;
355 // if not a prim, maybe it's one of the characters
356 if (m_charactersLocalID.TryGetValue(cont, out bdnc))
357 {
358 bdnc.AddCollision(contWith, contact);
359 if (!charactersWithCollisions.Contains(bdnc))
360 {
361 charactersWithCollisions.Add(bdnc);
362 }
363 }
364 }
365 }
366
367 public override void GetResults()
368 {
369
370 }
371
372 public override void SetTerrain(float[] heightMap)
373 {
374 if (m_terrainShape != null)
375 DeleteTerrain();
376
377 float hfmax = -9000;
378 float hfmin = 90000;
379
380 for (int i = 0; i <heightMap.Length;i++)
381 {
382 if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
383 {
384 heightMap[i] = 0f;
385 }
386
387 hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
388 hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
389 }
390 // store this for later reference.
391 // Note, we're storing it after we check it for anomolies above
392 _origheightmap = heightMap;
393
394 hfmin = 0;
395 hfmax = 256;
396
397 m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
398 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
399 (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
400 float AabbCenterX = Constants.RegionSize/2f;
401 float AabbCenterY = Constants.RegionSize/2f;
402
403 float AabbCenterZ = 0;
404 float temphfmin, temphfmax;
405
406 temphfmin = hfmin;
407 temphfmax = hfmax;
408
409 if (temphfmin < 0)
410 {
411 temphfmax = 0 - temphfmin;
412 temphfmin = 0 - temphfmin;
413 }
414 else if (temphfmin > 0)
415 {
416 temphfmax = temphfmax + (0 - temphfmin);
417 //temphfmin = temphfmin + (0 - temphfmin);
418 }
419 AabbCenterZ = temphfmax/2f;
420
421 if (m_terrainPosition == null)
422 {
423 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
424 }
425 else
426 {
427 try
428 {
429 m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
430 }
431 catch (ObjectDisposedException)
432 {
433 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
434 }
435 }
436 if (m_terrainMotionState != null)
437 {
438 m_terrainMotionState.Dispose();
439 m_terrainMotionState = null;
440 }
441 m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
442 m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
443 TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
444 TerrainBody.setUserPointer((IntPtr)0);
445 m_world.addRigidBody(TerrainBody);
446
447
448 }
449
450 public override void SetWaterLevel(float baseheight)
451 {
452
453 }
454
455 public override void DeleteTerrain()
456 {
457 if (TerrainBody != null)
458 {
459 m_world.removeRigidBody(TerrainBody);
460 }
461
462 if (m_terrainShape != null)
463 {
464 m_terrainShape.Dispose();
465 m_terrainShape = null;
466 }
467
468 if (m_terrainMotionState != null)
469 {
470 m_terrainMotionState.Dispose();
471 m_terrainMotionState = null;
472 }
473
474 if (m_terrainTransform != null)
475 {
476 m_terrainTransform.Dispose();
477 m_terrainTransform = null;
478 }
479
480 if (m_terrainPosition != null)
481 {
482 m_terrainPosition.Dispose();
483 m_terrainPosition = null;
484 }
485 }
486
487 public override void Dispose()
488 {
489 disposeAllBodies();
490 m_world.Dispose();
491 m_broadphase.Dispose();
492 ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
493 ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
494 worldAabbMax.Dispose();
495 worldAabbMin.Dispose();
496 VectorZero.Dispose();
497 QuatIdentity.Dispose();
498 m_gravity.Dispose();
499 VectorZero = null;
500 QuatIdentity = null;
501 }
502
503 public override Dictionary<uint, float> GetTopColliders()
504 {
505 return new Dictionary<uint, float>();
506 }
507
508 public btDiscreteDynamicsWorld getBulletWorld()
509 {
510 return m_world;
511 }
512
513 private void disposeAllBodies()
514 {
515 lock (m_prims)
516 {
517 m_primsLocalID.Clear();
518 foreach (BulletDotNETPrim prim in m_prims)
519 {
520 if (prim.Body != null)
521 m_world.removeRigidBody(prim.Body);
522
523 prim.Dispose();
524 }
525 m_prims.Clear();
526
527 foreach (BulletDotNETCharacter chr in m_characters)
528 {
529 if (chr.Body != null)
530 m_world.removeRigidBody(chr.Body);
531 chr.Dispose();
532 }
533 m_characters.Clear();
534 }
535 }
536
537 public override bool IsThreaded
538 {
539 get { return false; }
540 }
541
542 internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
543 {
544 //TODO: FIXME:
545 }
546
547 internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
548 {
549 //TODO: FIXME:
550 }
551
552 internal void AddRigidBody(btRigidBody Body)
553 {
554 m_world.addRigidBody(Body);
555 }
556 [Obsolete("bad!")]
557 internal void removeFromWorld(btRigidBody body)
558 {
559
560 m_world.removeRigidBody(body);
561 }
562
563 internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
564 {
565 lock (m_prims)
566 {
567 if (m_prims.Contains(prm))
568 {
569 m_world.removeRigidBody(body);
570 }
571 remActivePrim(prm);
572 m_primsLocalID.Remove(prm.m_localID);
573 m_prims.Remove(prm);
574 }
575
576 }
577
578 internal float GetWaterLevel()
579 {
580 throw new NotImplementedException();
581 }
582
583 // Recovered for use by fly height. Kitto Flora
584 public float GetTerrainHeightAtXY(float x, float y)
585 {
586 // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
587 // the values are checked, so checking below.
588 // Is there any reason that we don't do this in ScenePresence?
589 // The only physics engine that benefits from it in the physics plugin is this one
590
591 if (x > (int)Constants.RegionSize || y > (int)Constants.RegionSize ||
592 x < 0.001f || y < 0.001f)
593 return 0;
594
595 return _origheightmap[(int)y * Constants.RegionSize + (int)x];
596 }
597 // End recovered. Kitto Flora
598
599 /// <summary>
600 /// Routine to figure out if we need to mesh this prim with our mesher
601 /// </summary>
602 /// <param name="pbs"></param>
603 /// <returns></returns>
604 public bool needsMeshing(PrimitiveBaseShape pbs)
605 {
606 // most of this is redundant now as the mesher will return null if it cant mesh a prim
607 // but we still need to check for sculptie meshing being enabled so this is the most
608 // convenient place to do it for now...
609
610 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
611 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
612 int iPropertiesNotSupportedDefault = 0;
613
614 if (pbs.SculptEntry && !meshSculptedPrim)
615 {
616#if SPAM
617 m_log.Warn("NonMesh");
618#endif
619 return false;
620 }
621
622 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
623 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
624 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
625 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
626 {
627
628 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
629 && pbs.ProfileHollow == 0
630 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
631 && pbs.PathBegin == 0 && pbs.PathEnd == 0
632 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
633 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
634 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
635 {
636#if SPAM
637 m_log.Warn("NonMesh");
638#endif
639 return false;
640 }
641 }
642
643 if (pbs.ProfileHollow != 0)
644 iPropertiesNotSupportedDefault++;
645
646 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
647 iPropertiesNotSupportedDefault++;
648
649 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
650 iPropertiesNotSupportedDefault++;
651
652 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
653 iPropertiesNotSupportedDefault++;
654
655 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
656 iPropertiesNotSupportedDefault++;
657
658 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
659 iPropertiesNotSupportedDefault++;
660
661 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
662 iPropertiesNotSupportedDefault++;
663
664 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
665 iPropertiesNotSupportedDefault++;
666
667 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
668 iPropertiesNotSupportedDefault++;
669
670 // test for torus
671 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
672 {
673 if (pbs.PathCurve == (byte)Extrusion.Curve1)
674 {
675 iPropertiesNotSupportedDefault++;
676 }
677 }
678 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
679 {
680 if (pbs.PathCurve == (byte)Extrusion.Straight)
681 {
682 iPropertiesNotSupportedDefault++;
683 }
684
685 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
686 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
687 {
688 iPropertiesNotSupportedDefault++;
689 }
690 }
691 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
692 {
693 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
694 {
695 iPropertiesNotSupportedDefault++;
696 }
697 }
698 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
699 {
700 if (pbs.PathCurve == (byte)Extrusion.Straight)
701 {
702 iPropertiesNotSupportedDefault++;
703 }
704 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
705 {
706 iPropertiesNotSupportedDefault++;
707 }
708 }
709
710
711 if (iPropertiesNotSupportedDefault == 0)
712 {
713#if SPAM
714 m_log.Warn("NonMesh");
715#endif
716 return false;
717 }
718#if SPAM
719 m_log.Debug("Mesh");
720#endif
721 return true;
722 }
723
724 internal void addActivePrim(BulletDotNETPrim pPrim)
725 {
726 lock (m_activePrims)
727 {
728 if (!m_activePrims.Contains(pPrim))
729 {
730 m_activePrims.Add(pPrim);
731 }
732 }
733 }
734
735 public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
736 {
737 lock (m_activePrims)
738 {
739 m_activePrims.Remove(pDeactivatePrim);
740 }
741 }
742
743 internal void AddPrimToScene(BulletDotNETPrim pPrim)
744 {
745 lock (m_prims)
746 {
747 if (!m_prims.Contains(pPrim))
748 {
749 try
750 {
751 m_prims.Add(pPrim);
752 m_primsLocalID.Add(pPrim.m_localID, pPrim);
753 }
754 catch
755 {
756 // noop if it's already there
757 m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate prim localID");
758 }
759 m_world.addRigidBody(pPrim.Body);
760 // m_log.Debug("[PHYSICS] added prim to scene");
761 }
762 }
763 }
764 internal void EnableCollisionInterface()
765 {
766 if (m_CollisionInterface == null)
767 {
768 m_CollisionInterface = new ContactAddedCallbackHandler(m_world);
769 // m_world.SetCollisionAddedCallback(m_CollisionInterface);
770 }
771 }
772
773
774
775 }
776}
diff --git a/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs
deleted file mode 100644
index 6383f26..0000000
--- a/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
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.Reflection;
29using System.Runtime.InteropServices;
30
31// Information about this assembly is defined by the following
32// attributes.
33//
34// change them to the information which is associated with the assembly
35// you compile.
36
37[assembly : AssemblyTitle("BulletXPlugin")]
38[assembly : AssemblyDescription("")]
39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("BulletXPlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")]
45
46// This sets the default COM visibility of types in the assembly to invisible.
47// If you need to expose a type to COM, use [ComVisible(true)] on that type.
48
49[assembly : ComVisible(false)]
50
51// The assembly version has following format :
52//
53// Major.Minor.Build.Revision
54//
55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default):
57
58[assembly : AssemblyVersion("0.6.5.*")]
diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
deleted file mode 100644
index df62dbc..0000000
--- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
+++ /dev/null
@@ -1,1855 +0,0 @@
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
28#region References
29
30using System;
31using System.Collections.Generic;
32using OpenMetaverse;
33using MonoXnaCompactMaths;
34using OpenSim.Framework;
35using OpenSim.Region.Physics.Manager;
36using XnaDevRu.BulletX;
37using XnaDevRu.BulletX.Dynamics;
38using Nini.Config;
39using Vector3 = MonoXnaCompactMaths.Vector3;
40using Quaternion = MonoXnaCompactMaths.Quaternion;
41
42#endregion
43
44namespace OpenSim.Region.Physics.BulletXPlugin
45{
46 /// <summary>
47 /// BulletXConversions are called now BulletXMaths
48 /// This Class converts objects and types for BulletX and give some operations
49 /// </summary>
50 public class BulletXMaths
51 {
52 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
53
54 //Vector3
55 public static Vector3 PhysicsVectorToXnaVector3(OpenMetaverse.Vector3 physicsVector)
56 {
57 return new Vector3(physicsVector.X, physicsVector.Y, physicsVector.Z);
58 }
59
60 public static OpenMetaverse.Vector3 XnaVector3ToPhysicsVector(Vector3 xnaVector3)
61 {
62 return new OpenMetaverse.Vector3(xnaVector3.X, xnaVector3.Y, xnaVector3.Z);
63 }
64
65 //Quaternion
66 public static Quaternion QuaternionToXnaQuaternion(OpenMetaverse.Quaternion quaternion)
67 {
68 return new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
69 }
70
71 public static OpenMetaverse.Quaternion XnaQuaternionToQuaternion(Quaternion xnaQuaternion)
72 {
73 return new OpenMetaverse.Quaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z);
74 }
75
76 //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license):
77 //- SetRotation (class MatrixOperations)
78 //- GetRotation (class MatrixOperations)
79 //- GetElement (class MathHelper)
80 //- SetElement (class MathHelper)
81 internal static void SetRotation(ref Matrix m, Quaternion q)
82 {
83 float d = q.LengthSquared();
84 float s = 2f/d;
85 float xs = q.X*s, ys = q.Y*s, zs = q.Z*s;
86 float wx = q.W*xs, wy = q.W*ys, wz = q.W*zs;
87 float xx = q.X*xs, xy = q.X*ys, xz = q.X*zs;
88 float yy = q.Y*ys, yz = q.Y*zs, zz = q.Z*zs;
89 m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0,
90 xy + wz, 1 - (xx + zz), yz - wx, 0,
91 xz - wy, yz + wx, 1 - (xx + yy), 0,
92 m.M41, m.M42, m.M43, 1);
93 }
94
95 internal static Quaternion GetRotation(Matrix m)
96 {
97 Quaternion q;
98
99 float trace = m.M11 + m.M22 + m.M33;
100
101 if (trace > 0)
102 {
103 float s = (float) Math.Sqrt(trace + 1);
104 q.W = s*0.5f;
105 s = 0.5f/s;
106
107 q.X = (m.M32 - m.M23)*s;
108 q.Y = (m.M13 - m.M31)*s;
109 q.Z = (m.M21 - m.M12)*s;
110 }
111 else
112 {
113 q.X = q.Y = q.Z = q.W = 0f;
114
115 int i = m.M11 < m.M22
116 ?
117 (m.M22 < m.M33 ? 2 : 1)
118 :
119 (m.M11 < m.M33 ? 2 : 0);
120 int j = (i + 1)%3;
121 int k = (i + 2)%3;
122
123 float s = (float) Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1);
124 SetElement(ref q, i, s*0.5f);
125 s = 0.5f/s;
126
127 q.W = (GetElement(m, k, j) - GetElement(m, j, k))*s;
128 SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j))*s);
129 SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k))*s);
130 }
131
132 return q;
133 }
134
135 internal static float SetElement(ref Quaternion q, int index, float value)
136 {
137 switch (index)
138 {
139 case 0:
140 q.X = value;
141 break;
142 case 1:
143 q.Y = value;
144 break;
145 case 2:
146 q.Z = value;
147 break;
148 case 3:
149 q.W = value;
150 break;
151 }
152
153 return 0;
154 }
155
156 internal static float GetElement(Matrix mat, int row, int col)
157 {
158 switch (row)
159 {
160 case 0:
161 switch (col)
162 {
163 case 0:
164 return mat.M11;
165 case 1:
166 return mat.M12;
167 case 2:
168 return mat.M13;
169 }
170 break;
171 case 1:
172 switch (col)
173 {
174 case 0:
175 return mat.M21;
176 case 1:
177 return mat.M22;
178 case 2:
179 return mat.M23;
180 }
181 break;
182 case 2:
183 switch (col)
184 {
185 case 0:
186 return mat.M31;
187 case 1:
188 return mat.M32;
189 case 2:
190 return mat.M33;
191 }
192 break;
193 }
194
195 return 0;
196 }
197 }
198
199 /// <summary>
200 /// PhysicsPlugin Class for BulletX
201 /// </summary>
202 public class BulletXPlugin : IPhysicsPlugin
203 {
204 private BulletXScene _mScene;
205
206 public BulletXPlugin()
207 {
208 }
209
210 public bool Init()
211 {
212 return true;
213 }
214
215 public PhysicsScene GetScene(string sceneIdentifier)
216 {
217 if (_mScene == null)
218 {
219 _mScene = new BulletXScene(sceneIdentifier);
220 }
221 return (_mScene);
222 }
223
224 public string GetName()
225 {
226 return ("modified_BulletX"); //Changed!! "BulletXEngine" To "modified_BulletX"
227 }
228
229 public void Dispose()
230 {
231 }
232 }
233
234
235 // Class to detect and debug collisions
236 // Mainly used for debugging purposes
237 internal class CollisionDispatcherLocal : CollisionDispatcher
238 {
239 private BulletXScene relatedScene;
240
241 public CollisionDispatcherLocal(BulletXScene s)
242 : base()
243 {
244 relatedScene = s;
245 }
246
247 public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB)
248 {
249 RigidBody rb;
250 BulletXCharacter bxcA = null;
251 BulletXPrim bxpA = null;
252 Type t = bodyA.GetType();
253 if (t == typeof (RigidBody))
254 {
255 rb = (RigidBody) bodyA;
256 relatedScene._characters.TryGetValue(rb, out bxcA);
257 relatedScene._prims.TryGetValue(rb, out bxpA);
258 }
259// String nameA;
260// if (bxcA != null)
261// nameA = bxcA._name;
262// else if (bxpA != null)
263// nameA = bxpA._name;
264// else
265// nameA = "null";
266
267
268
269 BulletXCharacter bxcB = null;
270 BulletXPrim bxpB = null;
271 t = bodyB.GetType();
272 if (t == typeof (RigidBody))
273 {
274 rb = (RigidBody) bodyB;
275 relatedScene._characters.TryGetValue(rb, out bxcB);
276 relatedScene._prims.TryGetValue(rb, out bxpB);
277 }
278
279// String nameB;
280// if (bxcB != null)
281// nameB = bxcB._name;
282// else if (bxpB != null)
283// nameB = bxpB._name;
284// else
285 // nameB = "null";
286 bool needsCollision;// = base.NeedsCollision(bodyA, bodyB);
287 int c1 = 3;
288 int c2 = 3;
289
290 ////////////////////////////////////////////////////////
291 //BulletX Mesh Collisions
292 //added by Jed zhu
293 //data: May 07,2005
294 ////////////////////////////////////////////////////////
295 #region BulletXMeshCollisions Fields
296
297
298 if (bxcA != null && bxpB != null)
299 c1 = Collision(bxcA, bxpB);
300 if (bxpA != null && bxcB != null)
301 c2 = Collision(bxcB, bxpA);
302 if (c1 < 2)
303 needsCollision = (c1 > 0) ? true : false;
304 else if (c2 < 2)
305 needsCollision = (c2 > 0) ? true : false;
306 else
307 needsCollision = base.NeedsCollision(bodyA, bodyB);
308
309
310 #endregion
311
312
313 //m_log.DebugFormat("[BulletX]: A collision was detected between {0} and {1} --> {2}", nameA, nameB,
314 //needsCollision);
315
316
317 return needsCollision;
318 }
319 //added by jed zhu
320 //calculas the collision between the Prim and Actor
321 //
322 private int Collision(BulletXCharacter actorA, BulletXPrim primB)
323 {
324 int[] indexBase;
325 Vector3[] vertexBase;
326 Vector3 vNormal;
327 // Vector3 vP1;
328 // Vector3 vP2;
329 // Vector3 vP3;
330 IMesh mesh = primB.GetMesh();
331
332 float fdistance;
333 if (primB == null)
334 return 3;
335 if (mesh == null)
336 return 2;
337 if (actorA == null)
338 return 3;
339
340 int iVertexCount = mesh.getVertexList().Count;
341 int iIndexCount = mesh.getIndexListAsInt().Length;
342 if (iVertexCount == 0)
343 return 3;
344 if (iIndexCount == 0)
345 return 3;
346 lock (BulletXScene.BulletXLock)
347 {
348 indexBase = mesh.getIndexListAsInt();
349 vertexBase = new Vector3[iVertexCount];
350
351 for (int i = 0; i < iVertexCount; i++)
352 {
353 OpenMetaverse.Vector3 v = mesh.getVertexList()[i];
354 if (v != null) // Note, null has special meaning. See meshing code for details
355 vertexBase[i] = BulletXMaths.PhysicsVectorToXnaVector3(v);
356 else
357 vertexBase[i] = Vector3.Zero;
358 }
359
360 for (int ix = 0; ix < iIndexCount; ix += 3)
361 {
362 int ia = indexBase[ix + 0];
363 int ib = indexBase[ix + 1];
364 int ic = indexBase[ix + 2];
365 //
366 Vector3 v1 = vertexBase[ib] - vertexBase[ia];
367 Vector3 v2 = vertexBase[ic] - vertexBase[ia];
368
369 Vector3.Cross(ref v1, ref v2, out vNormal);
370 Vector3.Normalize(ref vNormal, out vNormal);
371
372 fdistance = Vector3.Dot(vNormal, vertexBase[ia]) + 0.50f;
373 if (preCheckCollision(actorA, vNormal, fdistance) == 1)
374 {
375 if (CheckCollision(actorA, ia, ib, ic, vNormal, vertexBase) == 1)
376 {
377 //PhysicsVector v = actorA.Position;
378 //Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v);
379 //Vector3 vp = vNormal * (fdistance - Vector3.Dot(vNormal, v3) + 0.2f);
380 //actorA.Position += BulletXMaths.XnaVector3ToPhysicsVector(vp);
381 return 1;
382 }
383 }
384 }
385 }
386
387
388 return 0;
389 }
390 //added by jed zhu
391 //return value 1: need second check
392 //return value 0: no need check
393
394 private int preCheckCollision(BulletXActor actA, Vector3 vNormal, float fDist)
395 {
396 float fstartSide;
397 OpenMetaverse.Vector3 v = actA.Position;
398 Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v);
399
400 fstartSide = Vector3.Dot(vNormal, v3) - fDist;
401 if (fstartSide > 0) return 0;
402 else return 1;
403 }
404 //added by jed zhu
405 private int CheckCollision(BulletXActor actA, int ia, int ib, int ic, Vector3 vNormal, Vector3[] vertBase)
406 {
407 Vector3 perPlaneNormal;
408 float fPerPlaneDist;
409 OpenMetaverse.Vector3 v = actA.Position;
410 Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v);
411 //check AB
412 Vector3 v1;
413 v1 = vertBase[ib] - vertBase[ia];
414 Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal);
415 Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal);
416
417 if (Vector3.Dot((vertBase[ic] - vertBase[ia]), perPlaneNormal) < 0)
418 perPlaneNormal = -perPlaneNormal;
419 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ia]) - 0.50f;
420
421
422
423 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0)
424 return 0;
425 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ic]) + 0.50f;
426 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0)
427 return 0;
428
429 //check BC
430
431 v1 = vertBase[ic] - vertBase[ib];
432 Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal);
433 Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal);
434
435 if (Vector3.Dot((vertBase[ia] - vertBase[ib]), perPlaneNormal) < 0)
436 perPlaneNormal = -perPlaneNormal;
437 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ib]) - 0.50f;
438
439
440 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0)
441 return 0;
442 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ia]) + 0.50f;
443 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0)
444 return 0;
445 //check CA
446 v1 = vertBase[ia] - vertBase[ic];
447 Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal);
448 Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal);
449
450 if (Vector3.Dot((vertBase[ib] - vertBase[ic]), perPlaneNormal) < 0)
451 perPlaneNormal = -perPlaneNormal;
452 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ic]) - 0.50f;
453
454
455 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0)
456 return 0;
457 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ib]) + 0.50f;
458 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0)
459 return 0;
460
461 return 1;
462
463 }
464 }
465
466 /// <summary>
467 /// PhysicsScene Class for BulletX
468 /// </summary>
469 public class BulletXScene : PhysicsScene
470 {
471 #region BulletXScene Fields
472
473 public DiscreteDynamicsWorld ddWorld;
474 private CollisionDispatcher cDispatcher;
475 private OverlappingPairCache opCache;
476 private SequentialImpulseConstraintSolver sicSolver;
477 public static Object BulletXLock = new Object();
478
479 private const int minXY = 0;
480 private const int minZ = 0;
481 private const int maxXY = (int)Constants.RegionSize;
482 private const int maxZ = 4096;
483 private const int maxHandles = 32766; //Why? I don't know
484 private const float gravity = 9.8f;
485 private const float heightLevel0 = 77.0f;
486 private const float heightLevel1 = 200.0f;
487 private const float lowGravityFactor = 0.2f;
488 //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS
489 private const int simulationSubSteps = 10;
490 //private float[] _heightmap;
491 private BulletXPlanet _simFlatPlanet;
492 internal Dictionary<RigidBody, BulletXCharacter> _characters = new Dictionary<RigidBody, BulletXCharacter>();
493 internal Dictionary<RigidBody, BulletXPrim> _prims = new Dictionary<RigidBody, BulletXPrim>();
494
495 public IMesher mesher;
496 // private IConfigSource m_config;
497
498 // protected internal String identifier;
499
500 public BulletXScene(String sceneIdentifier)
501 {
502 //identifier = sceneIdentifier;
503 cDispatcher = new CollisionDispatcherLocal(this);
504 Vector3 worldMinDim = new Vector3((float)minXY, (float)minXY, (float)minZ);
505 Vector3 worldMaxDim = new Vector3((float)maxXY, (float)maxXY, (float)maxZ);
506 opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles);
507 sicSolver = new SequentialImpulseConstraintSolver();
508
509 lock (BulletXLock)
510 {
511 ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver);
512 ddWorld.Gravity = new Vector3(0, 0, -gravity);
513 }
514 //this._heightmap = new float[65536];
515 }
516
517 public static float Gravity
518 {
519 get { return gravity; }
520 }
521
522 public static float HeightLevel0
523 {
524 get { return heightLevel0; }
525 }
526
527 public static float HeightLevel1
528 {
529 get { return heightLevel1; }
530 }
531
532 public static float LowGravityFactor
533 {
534 get { return lowGravityFactor; }
535 }
536
537 public static int MaxXY
538 {
539 get { return maxXY; }
540 }
541
542 public static int MaxZ
543 {
544 get { return maxZ; }
545 }
546
547 private List<RigidBody> _forgottenRigidBodies = new List<RigidBody>();
548 internal string is_ex_message = "Can't remove rigidBody!: ";
549
550 #endregion
551
552 public BulletXScene()
553 {
554 cDispatcher = new CollisionDispatcherLocal(this);
555 Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ);
556 Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ);
557 opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles);
558 sicSolver = new SequentialImpulseConstraintSolver();
559
560 lock (BulletXLock)
561 {
562 ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver);
563 ddWorld.Gravity = new Vector3(0, 0, -gravity);
564 }
565 //this._heightmap = new float[65536];
566 }
567
568 public override void Initialise(IMesher meshmerizer, IConfigSource config)
569 {
570 mesher = meshmerizer;
571 // m_config = config;
572 }
573
574 public override void Dispose()
575 {
576
577 }
578
579 public override Dictionary<uint, float> GetTopColliders()
580 {
581 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
582 return returncolliders;
583 }
584
585 public override void SetWaterLevel(float baseheight)
586 {
587
588 }
589
590 public override PhysicsActor AddAvatar(string avName, OpenMetaverse.Vector3 position, OpenMetaverse.Vector3 size, bool isFlying)
591 {
592 OpenMetaverse.Vector3 pos = OpenMetaverse.Vector3.Zero;
593 pos.X = position.X;
594 pos.Y = position.Y;
595 pos.Z = position.Z + 20;
596 BulletXCharacter newAv = null;
597 lock (BulletXLock)
598 {
599 newAv = new BulletXCharacter(avName, this, pos);
600 _characters.Add(newAv.RigidBody, newAv);
601 }
602 newAv.Flying = isFlying;
603 return newAv;
604 }
605
606 public override void RemoveAvatar(PhysicsActor actor)
607 {
608 if (actor is BulletXCharacter)
609 {
610 lock (BulletXLock)
611 {
612 try
613 {
614 ddWorld.RemoveRigidBody(((BulletXCharacter) actor).RigidBody);
615 }
616 catch (Exception ex)
617 {
618 BulletXMessage(is_ex_message + ex.Message, true);
619 ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation;
620 AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody);
621 }
622 _characters.Remove(((BulletXCharacter) actor).RigidBody);
623 }
624 GC.Collect();
625 }
626 }
627
628 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, OpenMetaverse.Vector3 position,
629 OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation, bool isPhysical, uint localid)
630 {
631 PhysicsActor result;
632
633 switch (pbs.ProfileShape)
634 {
635 case ProfileShape.Square:
636 /// support simple box & hollow box now; later, more shapes
637 if (pbs.ProfileHollow == 0)
638 {
639 result = AddPrim(primName, position, size, rotation, null, null, isPhysical);
640 }
641 else
642 {
643 IMesh mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
644 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
645 }
646 break;
647
648 default:
649 result = AddPrim(primName, position, size, rotation, null, null, isPhysical);
650 break;
651 }
652
653 return result;
654 }
655
656 public PhysicsActor AddPrim(String name, OpenMetaverse.Vector3 position, OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation,
657 IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
658 {
659 BulletXPrim newPrim = null;
660 lock (BulletXLock)
661 {
662 newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical);
663 _prims.Add(newPrim.RigidBody, newPrim);
664 }
665 return newPrim;
666 }
667
668 public override void RemovePrim(PhysicsActor prim)
669 {
670 if (prim is BulletXPrim)
671 {
672 lock (BulletXLock)
673 {
674 try
675 {
676 ddWorld.RemoveRigidBody(((BulletXPrim) prim).RigidBody);
677 }
678 catch (Exception ex)
679 {
680 BulletXMessage(is_ex_message + ex.Message, true);
681 ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation;
682 AddForgottenRigidBody(((BulletXPrim) prim).RigidBody);
683 }
684 _prims.Remove(((BulletXPrim) prim).RigidBody);
685 }
686 GC.Collect();
687 }
688 }
689
690 public override void AddPhysicsActorTaint(PhysicsActor prim)
691 {
692 }
693
694 public override float Simulate(float timeStep)
695 {
696 float fps = 0;
697 lock (BulletXLock)
698 {
699 //Try to remove garbage
700 RemoveForgottenRigidBodies();
701 //End of remove
702 MoveAPrimitives(timeStep);
703
704
705 fps = (timeStep*simulationSubSteps);
706
707 ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep);
708 //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine.
709 ValidateHeightForAll();
710 //End heightmap validation.
711 UpdateKineticsForAll();
712 }
713 return fps;
714 }
715
716 private void MoveAPrimitives(float timeStep)
717 {
718 foreach (BulletXCharacter actor in _characters.Values)
719 {
720 actor.Move(timeStep);
721 }
722 }
723
724 private void ValidateHeightForAll()
725 {
726 float _height;
727 foreach (BulletXCharacter actor in _characters.Values)
728 {
729 //_height = HeightValue(actor.RigidBodyPosition);
730 _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition);
731 actor.ValidateHeight(_height);
732 //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height);
733 }
734 foreach (BulletXPrim prim in _prims.Values)
735 {
736 //_height = HeightValue(prim.RigidBodyPosition);
737 _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition);
738 prim.ValidateHeight(_height);
739 //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height);
740 }
741 //foreach (BulletXCharacter actor in _characters)
742 //{
743 // actor.ValidateHeight(0);
744 //}
745 //foreach (BulletXPrim prim in _prims)
746 //{
747 // prim.ValidateHeight(0);
748 //}
749 }
750
751 private void UpdateKineticsForAll()
752 {
753 //UpdatePosition > UpdateKinetics.
754 //Not only position will be updated, also velocity cause acceleration.
755 foreach (BulletXCharacter actor in _characters.Values)
756 {
757 actor.UpdateKinetics();
758 }
759 foreach (BulletXPrim prim in _prims.Values)
760 {
761 prim.UpdateKinetics();
762 }
763 //if (this._simFlatPlanet!=null) this._simFlatPlanet.Restore();
764 }
765
766 public override void GetResults()
767 {
768 }
769
770 public override bool IsThreaded
771 {
772 get
773 {
774 return (false); // for now we won't be multithreaded
775 }
776 }
777
778 public override void SetTerrain(float[] heightMap)
779 {
780 ////As the same as ODE, heightmap (x,y) must be swapped for BulletX
781 //for (int i = 0; i < 65536; i++)
782 //{
783 // // this._heightmap[i] = (double)heightMap[i];
784 // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
785 // int x = i & 0xff;
786 // int y = i >> 8;
787 // this._heightmap[i] = heightMap[x * 256 + y];
788 //}
789
790 //float[] swappedHeightMap = new float[65536];
791 ////As the same as ODE, heightmap (x,y) must be swapped for BulletX
792 //for (int i = 0; i < 65536; i++)
793 //{
794 // // this._heightmap[i] = (double)heightMap[i];
795 // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
796 // int x = i & 0xff;
797 // int y = i >> 8;
798 // swappedHeightMap[i] = heightMap[x * 256 + y];
799 //}
800 DeleteTerrain();
801 //There is a BulletXLock inside the constructor of BulletXPlanet
802 //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap);
803 _simFlatPlanet = new BulletXPlanet(this, heightMap);
804 //this._heightmap = heightMap;
805 }
806
807 public override void DeleteTerrain()
808 {
809 if (_simFlatPlanet != null)
810 {
811 lock (BulletXLock)
812 {
813 try
814 {
815 ddWorld.RemoveRigidBody(_simFlatPlanet.RigidBody);
816 }
817 catch (Exception ex)
818 {
819 BulletXMessage(is_ex_message + ex.Message, true);
820 _simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation;
821 AddForgottenRigidBody(_simFlatPlanet.RigidBody);
822 }
823 }
824 _simFlatPlanet = null;
825 GC.Collect();
826 BulletXMessage("Terrain erased!", false);
827 }
828
829
830
831 //this._heightmap = null;
832 }
833
834
835
836 internal void AddForgottenRigidBody(RigidBody forgottenRigidBody)
837 {
838 _forgottenRigidBodies.Add(forgottenRigidBody);
839 }
840
841 private void RemoveForgottenRigidBodies()
842 {
843 RigidBody forgottenRigidBody;
844 int nRigidBodies = _forgottenRigidBodies.Count;
845 for (int i = nRigidBodies - 1; i >= 0; i--)
846 {
847 forgottenRigidBody = _forgottenRigidBodies[i];
848 try
849 {
850 ddWorld.RemoveRigidBody(forgottenRigidBody);
851 _forgottenRigidBodies.Remove(forgottenRigidBody);
852 BulletXMessage("Forgotten Rigid Body Removed", false);
853 }
854 catch (Exception ex)
855 {
856 BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false);
857 }
858 }
859 GC.Collect();
860 }
861
862 internal static void BulletXMessage(string message, bool isWarning)
863 {
864 PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning);
865 }
866
867 //temp
868 //private float HeightValue(MonoXnaCompactMaths.Vector3 position)
869 //{
870 // int li_x, li_y;
871 // float height;
872 // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0;
873 // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0;
874
875 // height = this._heightmap[li_y * 256 + li_x];
876 // if (height < 0) height = 0;
877 // else if (height > maxZ) height = maxZ;
878
879 // return height;
880 //}
881 }
882
883 /// <summary>
884 /// Generic Physics Actor for BulletX inherit from PhysicActor
885 /// </summary>
886 public class BulletXActor : PhysicsActor
887 {
888 protected bool flying = false;
889 protected bool _physical = false;
890 protected OpenMetaverse.Vector3 _position;
891 protected OpenMetaverse.Vector3 _velocity;
892 protected OpenMetaverse.Vector3 _size;
893 protected OpenMetaverse.Vector3 _acceleration;
894 protected OpenMetaverse.Quaternion _orientation;
895 protected OpenMetaverse.Vector3 m_rotationalVelocity;
896 protected RigidBody rigidBody;
897 protected int m_PhysicsActorType;
898 private Boolean iscolliding = false;
899 internal string _name;
900
901 public BulletXActor(String name)
902 {
903 _name = name;
904 }
905
906 public override bool Stopped
907 {
908 get { return false; }
909 }
910
911 public override OpenMetaverse.Vector3 Position
912 {
913 get { return _position; }
914 set
915 {
916 lock (BulletXScene.BulletXLock)
917 {
918 _position = value;
919 Translate();
920 }
921 }
922 }
923
924 public override OpenMetaverse.Vector3 RotationalVelocity
925 {
926 get { return m_rotationalVelocity; }
927 set { m_rotationalVelocity = value; }
928 }
929
930 public override OpenMetaverse.Vector3 Velocity
931 {
932 get { return _velocity; }
933 set
934 {
935 lock (BulletXScene.BulletXLock)
936 {
937 //Static objects don' have linear velocity
938 if (_physical)
939 {
940 _velocity = value;
941 Speed();
942 }
943 else
944 {
945 _velocity = OpenMetaverse.Vector3.Zero;
946 }
947 }
948 }
949 }
950 public override float CollisionScore
951 {
952 get { return 0f; }
953 set { }
954 }
955 public override OpenMetaverse.Vector3 Size
956 {
957 get { return _size; }
958 set
959 {
960 lock (BulletXScene.BulletXLock)
961 {
962 _size = value;
963 }
964 }
965 }
966
967 public override OpenMetaverse.Vector3 Force
968 {
969 get { return OpenMetaverse.Vector3.Zero; }
970 set { return; }
971 }
972
973 public override int VehicleType
974 {
975 get { return 0; }
976 set { return; }
977 }
978
979 public override void VehicleFloatParam(int param, float value)
980 {
981
982 }
983
984 public override void VehicleVectorParam(int param, OpenMetaverse.Vector3 value)
985 {
986
987 }
988
989 public override void VehicleRotationParam(int param, OpenMetaverse.Quaternion rotation)
990 {
991
992 }
993
994 public override void VehicleFlags(int param, bool remove)
995 {
996
997 }
998
999 public override void SetVolumeDetect(int param)
1000 {
1001
1002 }
1003
1004 public override OpenMetaverse.Vector3 CenterOfMass
1005 {
1006 get { return OpenMetaverse.Vector3.Zero; }
1007 }
1008
1009 public override OpenMetaverse.Vector3 GeometricCenter
1010 {
1011 get { return OpenMetaverse.Vector3.Zero; }
1012 }
1013
1014 public override PrimitiveBaseShape Shape
1015 {
1016 set { return; }
1017 }
1018
1019 public override bool SetAlwaysRun
1020 {
1021 get { return false; }
1022 set { return; }
1023 }
1024
1025 public override OpenMetaverse.Vector3 Acceleration
1026 {
1027 get { return _acceleration; }
1028 }
1029
1030 public override OpenMetaverse.Quaternion Orientation
1031 {
1032 get { return _orientation; }
1033 set
1034 {
1035 lock (BulletXScene.BulletXLock)
1036 {
1037 _orientation = value;
1038 ReOrient();
1039 }
1040 }
1041 }
1042 public override void link(PhysicsActor obj)
1043 {
1044
1045 }
1046
1047 public override void delink()
1048 {
1049
1050 }
1051
1052 public override void LockAngularMotion(OpenMetaverse.Vector3 axis)
1053 {
1054
1055 }
1056
1057 public override float Mass
1058 {
1059 get { return ActorMass; }
1060 }
1061
1062 public virtual float ActorMass
1063 {
1064 get { return 0; }
1065 }
1066
1067 public override int PhysicsActorType
1068 {
1069 get { return (int) m_PhysicsActorType; }
1070 set { m_PhysicsActorType = value; }
1071 }
1072
1073 public RigidBody RigidBody
1074 {
1075 get { return rigidBody; }
1076 }
1077
1078 public Vector3 RigidBodyPosition
1079 {
1080 get { return rigidBody.CenterOfMassPosition; }
1081 }
1082
1083 public override bool IsPhysical
1084 {
1085 get { return _physical; }
1086 set { _physical = value; }
1087 }
1088
1089 public override bool Flying
1090 {
1091 get { return flying; }
1092 set { flying = value; }
1093 }
1094
1095 public override bool ThrottleUpdates
1096 {
1097 get { return false; }
1098 set { return; }
1099 }
1100
1101 public override bool IsColliding
1102 {
1103 get { return iscolliding; }
1104 set { iscolliding = value; }
1105 }
1106
1107 public override bool CollidingGround
1108 {
1109 get { return false; }
1110 set { return; }
1111 }
1112
1113 public override bool CollidingObj
1114 {
1115 get { return false; }
1116 set { return; }
1117 }
1118
1119 public override uint LocalID
1120 {
1121 set { return; }
1122 }
1123
1124 public override bool Grabbed
1125 {
1126 set { return; }
1127 }
1128
1129 public override bool Selected
1130 {
1131 set { return; }
1132 }
1133
1134 public override float Buoyancy
1135 {
1136 get { return 0f; }
1137 set { return; }
1138 }
1139
1140 public override bool FloatOnWater
1141 {
1142 set { return; }
1143 }
1144
1145 public virtual void SetAcceleration(OpenMetaverse.Vector3 accel)
1146 {
1147 lock (BulletXScene.BulletXLock)
1148 {
1149 _acceleration = accel;
1150 }
1151 }
1152
1153 public override bool Kinematic
1154 {
1155 get { return false; }
1156 set { }
1157 }
1158
1159 public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce)
1160 {
1161 }
1162 public override OpenMetaverse.Vector3 Torque
1163 {
1164 get { return OpenMetaverse.Vector3.Zero; }
1165 set { return; }
1166 }
1167 public override void AddAngularForce(OpenMetaverse.Vector3 force, bool pushforce)
1168 {
1169 }
1170
1171 public override void SetMomentum(OpenMetaverse.Vector3 momentum)
1172 {
1173 }
1174
1175 internal virtual void ValidateHeight(float heighmapPositionValue)
1176 {
1177 }
1178
1179 internal virtual void UpdateKinetics()
1180 {
1181 }
1182
1183 #region Methods for updating values of RigidBody
1184
1185 protected internal void Translate()
1186 {
1187 Translate(_position);
1188 }
1189
1190 protected internal void Translate(OpenMetaverse.Vector3 _newPos)
1191 {
1192 Vector3 _translation;
1193 _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition;
1194 rigidBody.Translate(_translation);
1195 }
1196
1197 protected internal void Speed()
1198 {
1199 Speed(_velocity);
1200 }
1201
1202 protected internal void Speed(OpenMetaverse.Vector3 _newSpeed)
1203 {
1204 Vector3 _speed;
1205 _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed);
1206 rigidBody.LinearVelocity = _speed;
1207 }
1208
1209 protected internal void ReOrient()
1210 {
1211 ReOrient(_orientation);
1212 }
1213
1214 protected internal void ReOrient(OpenMetaverse.Quaternion _newOrient)
1215 {
1216 Quaternion _newOrientation;
1217 _newOrientation = BulletXMaths.QuaternionToXnaQuaternion(_newOrient);
1218 Matrix _comTransform = rigidBody.CenterOfMassTransform;
1219 BulletXMaths.SetRotation(ref _comTransform, _newOrientation);
1220 rigidBody.CenterOfMassTransform = _comTransform;
1221 }
1222
1223 protected internal void ReSize()
1224 {
1225 ReSize(_size);
1226 }
1227
1228 protected internal virtual void ReSize(OpenMetaverse.Vector3 _newSize)
1229 {
1230 }
1231
1232 public virtual void ScheduleTerseUpdate()
1233 {
1234 base.RequestPhysicsterseUpdate();
1235 }
1236
1237 #endregion
1238
1239 public override void CrossingFailure()
1240 {
1241
1242 }
1243 public override OpenMetaverse.Vector3 PIDTarget { set { return; } }
1244 public override bool PIDActive { set { return; } }
1245 public override float PIDTau { set { return; } }
1246
1247 public override float PIDHoverHeight { set { return; } }
1248 public override bool PIDHoverActive { set { return; } }
1249 public override PIDHoverType PIDHoverType { set { return; } }
1250 public override float PIDHoverTau { set { return; } }
1251
1252 public override OpenMetaverse.Quaternion APIDTarget
1253 {
1254 set { return; }
1255 }
1256
1257 public override bool APIDActive
1258 {
1259 set { return; }
1260 }
1261
1262 public override float APIDStrength
1263 {
1264 set { return; }
1265 }
1266
1267 public override float APIDDamping
1268 {
1269 set { return; }
1270 }
1271
1272
1273 public override void SubscribeEvents(int ms)
1274 {
1275
1276 }
1277 public override void UnSubscribeEvents()
1278 {
1279
1280 }
1281 public override bool SubscribedEvents()
1282 {
1283 return false;
1284 }
1285 }
1286
1287 /// <summary>
1288 /// PhysicsActor Character Class for BulletX
1289 /// </summary>
1290 public class BulletXCharacter : BulletXActor
1291 {
1292 public BulletXCharacter(BulletXScene parent_scene, OpenMetaverse.Vector3 pos)
1293 : this(String.Empty, parent_scene, pos)
1294 {
1295 }
1296
1297 public BulletXCharacter(String avName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos)
1298 : this(avName, parent_scene, pos, OpenMetaverse.Vector3.Zero, OpenMetaverse.Vector3.Zero, OpenMetaverse.Vector3.Zero,
1299 OpenMetaverse.Quaternion.Identity)
1300 {
1301 }
1302
1303 public BulletXCharacter(String avName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 velocity,
1304 OpenMetaverse.Vector3 size, OpenMetaverse.Vector3 acceleration, OpenMetaverse.Quaternion orientation)
1305 : base(avName)
1306 {
1307 //This fields will be removed. They're temporal
1308 float _sizeX = 0.5f;
1309 float _sizeY = 0.5f;
1310 float _sizeZ = 1.6f;
1311 //.
1312 _position = pos;
1313 _velocity = velocity;
1314 _size = size;
1315 //---
1316 _size.X = _sizeX;
1317 _size.Y = _sizeY;
1318 _size.Z = _sizeZ;
1319 //.
1320 _acceleration = acceleration;
1321 _orientation = orientation;
1322 _physical = true;
1323
1324 float _mass = 50.0f; //This depends of avatar's dimensions
1325 //For RigidBody Constructor. The next values might change
1326 float _linearDamping = 0.0f;
1327 float _angularDamping = 0.0f;
1328 float _friction = 0.5f;
1329 float _restitution = 0.0f;
1330 Matrix _startTransform = Matrix.Identity;
1331 Matrix _centerOfMassOffset = Matrix.Identity;
1332 lock (BulletXScene.BulletXLock)
1333 {
1334 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
1335 //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f));
1336 //For now, like ODE, collisionShape = sphere of radious = 1.0
1337 CollisionShape _collisionShape = new SphereShape(1.0f);
1338 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
1339 Vector3 _localInertia = new Vector3();
1340 _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0
1341 rigidBody =
1342 new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping,
1343 _friction, _restitution);
1344 //rigidBody.ActivationState = ActivationState.DisableDeactivation;
1345 //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
1346 Vector3 _vDebugTranslation;
1347 _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
1348 rigidBody.Translate(_vDebugTranslation);
1349 parent_scene.ddWorld.AddRigidBody(rigidBody);
1350 }
1351 }
1352
1353 public override int PhysicsActorType
1354 {
1355 get { return (int) ActorTypes.Agent; }
1356 set { return; }
1357 }
1358
1359 public override OpenMetaverse.Vector3 Position
1360 {
1361 get { return base.Position; }
1362 set { base.Position = value; }
1363 }
1364
1365 public override OpenMetaverse.Vector3 Velocity
1366 {
1367 get { return base.Velocity; }
1368 set { base.Velocity = value; }
1369 }
1370
1371 public override OpenMetaverse.Vector3 Size
1372 {
1373 get { return base.Size; }
1374 set { base.Size = value; }
1375 }
1376
1377 public override OpenMetaverse.Vector3 Acceleration
1378 {
1379 get { return base.Acceleration; }
1380 }
1381
1382 public override OpenMetaverse.Quaternion Orientation
1383 {
1384 get { return base.Orientation; }
1385 set { base.Orientation = value; }
1386 }
1387
1388 public override bool Flying
1389 {
1390 get { return base.Flying; }
1391 set { base.Flying = value; }
1392 }
1393
1394 public override bool IsColliding
1395 {
1396 get { return base.IsColliding; }
1397 set { base.IsColliding = value; }
1398 }
1399
1400 public override bool Kinematic
1401 {
1402 get { return base.Kinematic; }
1403 set { base.Kinematic = value; }
1404 }
1405
1406 public override void SetAcceleration(OpenMetaverse.Vector3 accel)
1407 {
1408 base.SetAcceleration(accel);
1409 }
1410
1411 public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce)
1412 {
1413 base.AddForce(force, pushforce);
1414 }
1415
1416 public override void SetMomentum(OpenMetaverse.Vector3 momentum)
1417 {
1418 base.SetMomentum(momentum);
1419 }
1420
1421 internal void Move(float timeStep)
1422 {
1423 Vector3 vec = new Vector3();
1424 //At this point it's supossed that:
1425 //_velocity == rigidBody.LinearVelocity
1426 vec.X = _velocity.X;
1427 vec.Y = _velocity.Y;
1428 vec.Z = _velocity.Z;
1429 if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate();
1430 if (flying)
1431 {
1432 //Antigravity with movement
1433 if (_position.Z <= BulletXScene.HeightLevel0)
1434 {
1435 vec.Z += BulletXScene.Gravity*timeStep;
1436 }
1437 //Lowgravity with movement
1438 else if ((_position.Z > BulletXScene.HeightLevel0)
1439 && (_position.Z <= BulletXScene.HeightLevel1))
1440 {
1441 vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor);
1442 }
1443 //Lowgravity with...
1444 else if (_position.Z > BulletXScene.HeightLevel1)
1445 {
1446 if (vec.Z > 0) //no movement
1447 vec.Z = BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor);
1448 else
1449 vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor);
1450 }
1451 }
1452 rigidBody.LinearVelocity = vec;
1453 }
1454
1455 //This validation is very basic
1456 internal override void ValidateHeight(float heighmapPositionValue)
1457 {
1458 if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f)
1459 {
1460 Matrix m = rigidBody.WorldTransform;
1461 Vector3 v3 = m.Translation;
1462 v3.Z = heighmapPositionValue + _size.Z/2.0f;
1463 m.Translation = v3;
1464 rigidBody.WorldTransform = m;
1465 //When an Avie touch the ground it's vertical velocity it's reduced to ZERO
1466 Speed(new OpenMetaverse.Vector3(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f));
1467 }
1468 }
1469
1470 internal override void UpdateKinetics()
1471 {
1472 _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition);
1473 _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity);
1474 //Orientation it seems that it will be the default.
1475 ReOrient();
1476 }
1477 }
1478
1479 /// <summary>
1480 /// PhysicsActor Prim Class for BulletX
1481 /// </summary>
1482 public class BulletXPrim : BulletXActor
1483 {
1484 //Density it will depends of material.
1485 //For now all prims have the same density, all prims are made of water. Be water my friend! :D
1486 private const float _density = 1000.0f;
1487 private BulletXScene _parent_scene;
1488 private OpenMetaverse.Vector3 m_prev_position;
1489 private bool m_lastUpdateSent = false;
1490 //added by jed zhu
1491 private IMesh _mesh;
1492 public IMesh GetMesh() { return _mesh; }
1493
1494
1495
1496 public BulletXPrim(String primName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 size,
1497 OpenMetaverse.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
1498 : this(
1499 primName, parent_scene, pos, OpenMetaverse.Vector3.Zero, size, OpenMetaverse.Vector3.Zero, rotation, mesh, pbs,
1500 isPhysical)
1501 {
1502 }
1503
1504 public BulletXPrim(String primName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 velocity,
1505 OpenMetaverse.Vector3 size,
1506 OpenMetaverse.Vector3 acceleration, OpenMetaverse.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs,
1507 bool isPhysical)
1508 : base(primName)
1509 {
1510 if ((size.X == 0) || (size.Y == 0) || (size.Z == 0))
1511 throw new Exception("Size 0");
1512 if (OpenMetaverse.Quaternion.Normalize(rotation).Length() == 0f)
1513 rotation = OpenMetaverse.Quaternion.Identity;
1514
1515 _position = pos;
1516 _physical = isPhysical;
1517 _velocity = _physical ? velocity : OpenMetaverse.Vector3.Zero;
1518 _size = size;
1519 _acceleration = acceleration;
1520 _orientation = rotation;
1521
1522 _parent_scene = parent_scene;
1523
1524 CreateRigidBody(parent_scene, mesh, pos, size);
1525 }
1526
1527 public override int PhysicsActorType
1528 {
1529 get { return (int) ActorTypes.Prim; }
1530 set { return; }
1531 }
1532
1533 public override OpenMetaverse.Vector3 Position
1534 {
1535 get { return base.Position; }
1536 set { base.Position = value; }
1537 }
1538
1539 public override OpenMetaverse.Vector3 Velocity
1540 {
1541 get { return base.Velocity; }
1542 set { base.Velocity = value; }
1543 }
1544
1545 public override OpenMetaverse.Vector3 Size
1546 {
1547 get { return _size; }
1548 set
1549 {
1550 lock (BulletXScene.BulletXLock)
1551 {
1552 _size = value;
1553 ReSize();
1554 }
1555 }
1556 }
1557
1558 public override OpenMetaverse.Vector3 Acceleration
1559 {
1560 get { return base.Acceleration; }
1561 }
1562
1563 public override OpenMetaverse.Quaternion Orientation
1564 {
1565 get { return base.Orientation; }
1566 set { base.Orientation = value; }
1567 }
1568
1569 public override float ActorMass
1570 {
1571 get
1572 {
1573 //For now all prims are boxes
1574 return (_physical ? 1 : 0)*_density*_size.X*_size.Y*_size.Z;
1575 }
1576 }
1577
1578 public override bool IsPhysical
1579 {
1580 get { return base.IsPhysical; }
1581 set
1582 {
1583 base.IsPhysical = value;
1584 if (value)
1585 {
1586 //---
1587 PhysicsPluginManager.PhysicsPluginMessage("Physical - Recreate", true);
1588 //---
1589 ReCreateRigidBody(_size);
1590 }
1591 else
1592 {
1593 //---
1594 PhysicsPluginManager.PhysicsPluginMessage("Physical - SetMassProps", true);
1595 //---
1596 rigidBody.SetMassProps(Mass, new Vector3());
1597 }
1598 }
1599 }
1600
1601 public override bool Flying
1602 {
1603 get { return base.Flying; }
1604 set { base.Flying = value; }
1605 }
1606
1607 public override bool IsColliding
1608 {
1609 get { return base.IsColliding; }
1610 set { base.IsColliding = value; }
1611 }
1612
1613 public override bool Kinematic
1614 {
1615 get { return base.Kinematic; }
1616 set { base.Kinematic = value; }
1617 }
1618
1619 public override void SetAcceleration(OpenMetaverse.Vector3 accel)
1620 {
1621 lock (BulletXScene.BulletXLock)
1622 {
1623 _acceleration = accel;
1624 }
1625 }
1626
1627 public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce)
1628 {
1629 base.AddForce(force,pushforce);
1630 }
1631
1632 public override void SetMomentum(OpenMetaverse.Vector3 momentum)
1633 {
1634 base.SetMomentum(momentum);
1635 }
1636
1637 internal override void ValidateHeight(float heighmapPositionValue)
1638 {
1639 if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f)
1640 {
1641 Matrix m = rigidBody.WorldTransform;
1642 Vector3 v3 = m.Translation;
1643 v3.Z = heighmapPositionValue + _size.Z/2.0f;
1644 m.Translation = v3;
1645 rigidBody.WorldTransform = m;
1646 //When a Prim touch the ground it's vertical velocity it's reduced to ZERO
1647 //Static objects don't have linear velocity
1648 if (_physical)
1649 Speed(new OpenMetaverse.Vector3(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f));
1650 }
1651 }
1652
1653 internal override void UpdateKinetics()
1654 {
1655 if (_physical) //Updates properties. Prim updates its properties physically
1656 {
1657 _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition);
1658
1659 _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity);
1660 _orientation = BulletXMaths.XnaQuaternionToQuaternion(rigidBody.Orientation);
1661
1662 if ((Math.Abs(m_prev_position.X - _position.X) < 0.03)
1663 && (Math.Abs(m_prev_position.Y - _position.Y) < 0.03)
1664 && (Math.Abs(m_prev_position.Z - _position.Z) < 0.03))
1665 {
1666 if (!m_lastUpdateSent)
1667 {
1668 _velocity = OpenMetaverse.Vector3.Zero;
1669 base.ScheduleTerseUpdate();
1670 m_lastUpdateSent = true;
1671 }
1672 }
1673 else
1674 {
1675 m_lastUpdateSent = false;
1676 base.ScheduleTerseUpdate();
1677 }
1678 m_prev_position = _position;
1679 }
1680 else //Doesn't updates properties. That's a cancel
1681 {
1682 Translate();
1683 //Speed(); //<- Static objects don't have linear velocity
1684 ReOrient();
1685 }
1686 }
1687
1688 #region Methods for updating values of RigidBody
1689
1690 protected internal void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, OpenMetaverse.Vector3 pos,
1691 OpenMetaverse.Vector3 size)
1692 {
1693 //For RigidBody Constructor. The next values might change
1694 float _linearDamping = 0.0f;
1695 float _angularDamping = 0.0f;
1696 float _friction = 1.0f;
1697 float _restitution = 0.0f;
1698 Matrix _startTransform = Matrix.Identity;
1699 Matrix _centerOfMassOffset = Matrix.Identity;
1700 //added by jed zhu
1701 _mesh = mesh;
1702
1703 lock (BulletXScene.BulletXLock)
1704 {
1705 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
1706 //For now all prims are boxes
1707 CollisionShape _collisionShape;
1708 if (mesh == null)
1709 {
1710 _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size)/2.0f);
1711 }
1712 else
1713 {
1714 int iVertexCount = mesh.getVertexList().Count;
1715 int[] indices = mesh.getIndexListAsInt();
1716 Vector3[] v3Vertices = new Vector3[iVertexCount];
1717 for (int i = 0; i < iVertexCount; i++)
1718 {
1719 OpenMetaverse.Vector3 v = mesh.getVertexList()[i];
1720 if (v != null) // Note, null has special meaning. See meshing code for details
1721 v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v);
1722 else
1723 v3Vertices[i] = Vector3.Zero;
1724 }
1725 TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices);
1726
1727 _collisionShape = new TriangleMeshShape(triMesh);
1728 }
1729 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
1730 Vector3 _localInertia = new Vector3();
1731 if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0
1732 rigidBody =
1733 new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping,
1734 _friction, _restitution);
1735 //rigidBody.ActivationState = ActivationState.DisableDeactivation;
1736 //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
1737 Vector3 _vDebugTranslation;
1738 _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
1739 rigidBody.Translate(_vDebugTranslation);
1740 //---
1741 parent_scene.ddWorld.AddRigidBody(rigidBody);
1742 }
1743 }
1744
1745 protected internal void ReCreateRigidBody(OpenMetaverse.Vector3 size)
1746 {
1747 //There is a bug when trying to remove a rigidBody that is colliding with something..
1748 try
1749 {
1750 _parent_scene.ddWorld.RemoveRigidBody(rigidBody);
1751 }
1752 catch (Exception ex)
1753 {
1754 BulletXScene.BulletXMessage(_parent_scene.is_ex_message + ex.Message, true);
1755 rigidBody.ActivationState = ActivationState.DisableSimulation;
1756 _parent_scene.AddForgottenRigidBody(rigidBody);
1757 }
1758 CreateRigidBody(_parent_scene, null, _position, size);
1759 // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler
1760 if (_physical) Speed(); //Static objects don't have linear velocity
1761 ReOrient();
1762 GC.Collect();
1763 }
1764
1765 protected internal override void ReSize(OpenMetaverse.Vector3 _newSize)
1766 {
1767 //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't
1768 //so i have to do it manually. That's recreating rigidbody
1769 ReCreateRigidBody(_newSize);
1770 }
1771
1772 #endregion
1773 }
1774
1775 /// <summary>
1776 /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene
1777 /// </summary>
1778 internal class BulletXPlanet
1779 {
1780 private OpenMetaverse.Vector3 _staticPosition;
1781// private Vector3 _staticVelocity;
1782// private OpenMetaverse.Quaternion _staticOrientation;
1783 private float _mass;
1784 // private BulletXScene _parentscene;
1785 internal float[] _heightField;
1786 private RigidBody _flatPlanet;
1787
1788 internal RigidBody RigidBody
1789 {
1790 get { return _flatPlanet; }
1791 }
1792
1793 internal BulletXPlanet(BulletXScene parent_scene, float[] heightField)
1794 {
1795 _staticPosition = new OpenMetaverse.Vector3(BulletXScene.MaxXY / 2, BulletXScene.MaxXY / 2, 0);
1796// _staticVelocity = new PhysicsVector();
1797// _staticOrientation = OpenMetaverse.Quaternion.Identity;
1798 _mass = 0; //No active
1799 // _parentscene = parent_scene;
1800 _heightField = heightField;
1801
1802 float _linearDamping = 0.0f;
1803 float _angularDamping = 0.0f;
1804 float _friction = 0.5f;
1805 float _restitution = 0.0f;
1806 Matrix _startTransform = Matrix.Identity;
1807 Matrix _centerOfMassOffset = Matrix.Identity;
1808
1809 lock (BulletXScene.BulletXLock)
1810 {
1811 try
1812 {
1813 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition);
1814 CollisionShape _collisionShape =
1815 new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField,
1816 (float) BulletXScene.MaxZ, 2, true, false);
1817 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
1818 Vector3 _localInertia = new Vector3();
1819 //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0
1820 _flatPlanet =
1821 new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping,
1822 _angularDamping, _friction, _restitution);
1823 //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
1824 Vector3 _vDebugTranslation;
1825 _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition;
1826 _flatPlanet.Translate(_vDebugTranslation);
1827 parent_scene.ddWorld.AddRigidBody(_flatPlanet);
1828 }
1829 catch (Exception ex)
1830 {
1831 BulletXScene.BulletXMessage(ex.Message, true);
1832 }
1833 }
1834 BulletXScene.BulletXMessage("BulletXPlanet created.", false);
1835 }
1836
1837 internal float HeightValue(Vector3 position)
1838 {
1839 int li_x, li_y;
1840 float height;
1841 li_x = (int) Math.Round(position.X);
1842 if (li_x < 0) li_x = 0;
1843 if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1;
1844 li_y = (int) Math.Round(position.Y);
1845 if (li_y < 0) li_y = 0;
1846 if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1;
1847
1848 height = ((HeightfieldTerrainShape) _flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y);
1849 if (height < 0) height = 0;
1850 else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ;
1851
1852 return height;
1853 }
1854 }
1855}
diff --git a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
deleted file mode 100644
index 637cf6e..0000000
--- a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
+++ /dev/null
@@ -1,197 +0,0 @@
1/*
2 Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru
3 Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/*
23 This file contains a class TriangleIndexVertexArray. I tried using the class with the same name
24 from the BulletX implementation and found it unusable for the purpose of using triangle meshes
25 within BulletX as the implementation was painfully incomplete.
26 The attempt to derive from the original class failed as viable members were hidden.
27 Fiddling around with BulletX itself was not my intention.
28 So I copied the class to the BulletX-plugin and modified it.
29 If you want to fiddle around with it it's up to you to move all this to BulletX.
30 If someone someday implements the missing functionality in BulletX, feel free to remove this class.
31 It's just an ugly hack.
32*/
33
34using System;
35using System.Collections.Generic;
36using MonoXnaCompactMaths;
37using XnaDevRu.BulletX;
38
39namespace OpenSim.Region.Physics.BulletXPlugin
40{
41 /// <summary>
42 /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements
43 /// instead of the number of indices, we pass the number of triangles
44 /// </summary>
45 public struct IndexedMesh
46 {
47 private int _numTriangles;
48 private int[] _triangleIndexBase;
49 private int _triangleIndexStride;
50 private int _numVertices;
51 private Vector3[] _vertexBase;
52 private int _vertexStride;
53
54 public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices,
55 Vector3[] vertexBase, int vertexStride)
56 {
57 _numTriangles = numTriangleIndices;
58 _triangleIndexBase = triangleIndexBase;
59 _triangleIndexStride = triangleIndexStride;
60 _vertexBase = vertexBase;
61 _numVertices = numVertices;
62 _vertexStride = vertexStride;
63 }
64
65 public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase)
66 {
67 _numTriangles = triangleIndexBase.Length;
68 _triangleIndexBase = triangleIndexBase;
69 _triangleIndexStride = 32;
70 _vertexBase = vertexBase;
71 _numVertices = vertexBase.Length;
72 _vertexStride = 24;
73 }
74
75 public int TriangleCount
76 {
77 get { return _numTriangles; }
78 set { _numTriangles = value; }
79 }
80
81 public int[] TriangleIndexBase
82 {
83 get { return _triangleIndexBase; }
84 set { _triangleIndexBase = value; }
85 }
86
87 public int TriangleIndexStride
88 {
89 get { return _triangleIndexStride; }
90 set { _triangleIndexStride = value; }
91 }
92
93 public int VertexCount
94 {
95 get { return _numVertices; }
96 set { _numVertices = value; }
97 }
98
99 public Vector3[] VertexBase
100 {
101 get { return _vertexBase; }
102 set { _vertexBase = value; }
103 }
104
105 public int VertexStride
106 {
107 get { return _vertexStride; }
108 set { _vertexStride = value; }
109 }
110 }
111
112 /// <summary>
113 /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays.
114 /// Additional meshes can be added using addIndexedMesh
115 /// </summary>
116 public class TriangleIndexVertexArray : StridingMeshInterface
117 {
118 private List<IndexedMesh> _indexedMeshes = new List<IndexedMesh>();
119
120 public TriangleIndexVertexArray()
121 {
122 }
123
124 public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride,
125 int numVertices, Vector3[] vertexBase, int vertexStride)
126 {
127 IndexedMesh mesh = new IndexedMesh();
128 mesh.TriangleCount = numTriangleIndices;
129 mesh.TriangleIndexBase = triangleIndexBase;
130 mesh.TriangleIndexStride = triangleIndexStride;
131 mesh.VertexBase = vertexBase;
132 mesh.VertexCount = numVertices;
133 mesh.VertexStride = vertexStride;
134
135 AddIndexedMesh(mesh);
136 }
137
138 public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase)
139 : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24)
140 {
141 }
142
143 public void AddIndexedMesh(IndexedMesh indexedMesh)
144 {
145 _indexedMeshes.Add(indexedMesh);
146 }
147
148 public override void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces,
149 int subpart)
150 {
151 throw new Exception("The method or operation is not implemented.");
152 }
153
154 public override void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies,
155 out int numfaces, int subpart)
156 {
157 IndexedMesh m = _indexedMeshes[0];
158 Vector3[] vertexBase = m.VertexBase;
159 verts = new List<Vector3>();
160 foreach (Vector3 v in vertexBase)
161 {
162 verts.Add(v);
163 }
164 int[] indexBase = m.TriangleIndexBase;
165 indicies = new List<int>();
166 foreach (int i in indexBase)
167 {
168 indicies.Add(i);
169 }
170 numfaces = vertexBase.GetLength(0);
171 }
172
173 public override void UnLockVertexBase(int subpart)
174 {
175 throw new Exception("The method or operation is not implemented.");
176 }
177
178 public override void UnLockReadOnlyVertexBase(int subpart)
179 {
180 }
181
182 public override int SubPartsCount()
183 {
184 return _indexedMeshes.Count;
185 }
186
187 public override void PreallocateVertices(int numverts)
188 {
189 throw new Exception("The method or operation is not implemented.");
190 }
191
192 public override void PreallocateIndices(int numindices)
193 {
194 throw new Exception("The method or operation is not implemented.");
195 }
196 }
197}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 0a0d13f..4cc8c59 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -464,10 +464,12 @@ namespace OpenSim.Region.Physics.OdePlugin
464 m_pidControllerActive = true; 464 m_pidControllerActive = true;
465 465
466 Vector3 SetSize = value; 466 Vector3 SetSize = value;
467 m_tainted_CAPSULE_LENGTH = (SetSize.Z*1.15f) - CAPSULE_RADIUS*2.0f; 467 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
468 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); 468// m_log.Info("[SIZE]: " + CAPSULE_LENGTH);
469 469
470 Velocity = Vector3.Zero; 470 // If we reset velocity here, then an avatar stalls when it crosses a border for the first time
471 // (as the height of the new root agent is set).
472// Velocity = Vector3.Zero;
471 473
472 _parent_scene.AddPhysicsActorTaint(this); 474 _parent_scene.AddPhysicsActorTaint(this);
473 } 475 }
@@ -785,6 +787,8 @@ namespace OpenSim.Region.Physics.OdePlugin
785 { 787 {
786 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character"); 788 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
787 } 789 }
790
791// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", _target_velocity);
788 } 792 }
789 } 793 }
790 794
@@ -1325,7 +1329,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1325 { 1329 {
1326 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) 1330 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1327 { 1331 {
1328 1332// m_log.DebugFormat("[PHYSICS]: Changing capsule size");
1333
1329 m_pidControllerActive = true; 1334 m_pidControllerActive = true;
1330 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() 1335 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1331 d.JointDestroy(Amotor); 1336 d.JointDestroy(Amotor);
@@ -1336,7 +1341,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1336 d.GeomDestroy(Shell); 1341 d.GeomDestroy(Shell);
1337 AvatarGeomAndBodyCreation(_position.X, _position.Y, 1342 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1338 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); 1343 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
1339 Velocity = Vector3.Zero; 1344
1345 // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't
1346 // appear to stall initial region crossings when done here. Being done for consistency.
1347// Velocity = Vector3.Zero;
1340 1348
1341 _parent_scene.geom_name_map[Shell] = m_name; 1349 _parent_scene.geom_name_map[Shell] = m_name;
1342 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1350 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
@@ -1361,7 +1369,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1361 _position.Z = m_taintPosition.Z; 1369 _position.Z = m_taintPosition.Z;
1362 } 1370 }
1363 } 1371 }
1364
1365 } 1372 }
1366 1373
1367 internal void AddCollisionFrameTime(int p) 1374 internal void AddCollisionFrameTime(int p)
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 924d7c2..ac92b8b 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -1526,6 +1526,7 @@ Console.WriteLine("changeadd 1");
1526 { 1526 {
1527 if (Body == IntPtr.Zero) 1527 if (Body == IntPtr.Zero)
1528 enableBody(); 1528 enableBody();
1529
1529 //Prim auto disable after 20 frames, 1530 //Prim auto disable after 20 frames,
1530 //if you move it, re-enable the prim manually. 1531 //if you move it, re-enable the prim manually.
1531 if (_parent != null) 1532 if (_parent != null)
@@ -1536,6 +1537,7 @@ Console.WriteLine("changeadd 1");
1536 m_linkJoint = IntPtr.Zero; 1537 m_linkJoint = IntPtr.Zero;
1537 } 1538 }
1538 } 1539 }
1540
1539 if (Body != IntPtr.Zero) 1541 if (Body != IntPtr.Zero)
1540 { 1542 {
1541 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); 1543 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
@@ -1599,7 +1601,6 @@ Console.WriteLine(" JointCreateFixed");
1599 float fy = 0; 1601 float fy = 0;
1600 float fz = 0; 1602 float fz = 0;
1601 1603
1602
1603 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. 1604 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1604 { 1605 {
1605 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1606 if (m_vehicle.Type != Vehicle.TYPE_NONE)
@@ -1818,7 +1819,6 @@ Console.WriteLine(" JointCreateFixed");
1818 // 35x10 = 350n times the mass per second applied maximum. 1819 // 35x10 = 350n times the mass per second applied maximum.
1819 float nmax = 35f * m_mass; 1820 float nmax = 35f * m_mass;
1820 float nmin = -35f * m_mass; 1821 float nmin = -35f * m_mass;
1821
1822 1822
1823 if (fx > nmax) 1823 if (fx > nmax)
1824 fx = nmax; 1824 fx = nmax;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 88e884d..070cdc0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3591,7 +3591,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3591 parentPrim.ScheduleGroupForFullUpdate(); 3591 parentPrim.ScheduleGroupForFullUpdate();
3592 3592
3593 if (client != null) 3593 if (client != null)
3594 parentPrim.GetProperties(client); 3594 parentPrim.SendPropertiesToClient(client);
3595 3595
3596 ScriptSleep(1000); 3596 ScriptSleep(1000);
3597 } 3597 }
@@ -6570,6 +6570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6570 6570
6571 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 6571 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
6572 { 6572 {
6573 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6573 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 6574 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
6574 6575
6575 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 6576 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
@@ -6651,8 +6652,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6651 { 6652 {
6652 twist.y = 1.0f; 6653 twist.y = 1.0f;
6653 } 6654 }
6654 shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); 6655 // A fairly large precision error occurs for some calculations,
6655 shapeBlock.PathTwist = (sbyte)(100 * twist.y); 6656 // if a float or double is directly cast to a byte or sbyte
6657 // variable, in both .Net and Mono. In .Net, coding
6658 // "(sbyte)(float)(some expression)" corrects the precision
6659 // errors. But this does not work for Mono. This longer coding
6660 // form of creating a tempoary float variable from the
6661 // expression first, then casting that variable to a byte or
6662 // sbyte, works for both .Net and Mono. These types of
6663 // assignments occur in SetPrimtiveBlockShapeParams and
6664 // SetPrimitiveShapeParams in support of llSetPrimitiveParams.
6665 tempFloat = (float)(100.0d * twist.x);
6666 shapeBlock.PathTwistBegin = (sbyte)tempFloat;
6667 tempFloat = (float)(100.0d * twist.y);
6668 shapeBlock.PathTwist = (sbyte)tempFloat;
6656 6669
6657 shapeBlock.ObjectLocalID = part.LocalId; 6670 shapeBlock.ObjectLocalID = part.LocalId;
6658 6671
@@ -6663,6 +6676,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6663 // Prim type box, cylinder and prism. 6676 // Prim type box, cylinder and prism.
6664 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) 6677 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve)
6665 { 6678 {
6679 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6666 ObjectShapePacket.ObjectDataBlock shapeBlock; 6680 ObjectShapePacket.ObjectDataBlock shapeBlock;
6667 6681
6668 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 6682 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6683,8 +6697,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6683 { 6697 {
6684 taper_b.y = 2f; 6698 taper_b.y = 2f;
6685 } 6699 }
6686 shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); 6700 tempFloat = (float)(100.0d * (2.0d - taper_b.x));
6687 shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); 6701 shapeBlock.PathScaleX = (byte)tempFloat;
6702 tempFloat = (float)(100.0d * (2.0d - taper_b.y));
6703 shapeBlock.PathScaleY = (byte)tempFloat;
6688 if (topshear.x < -0.5f) 6704 if (topshear.x < -0.5f)
6689 { 6705 {
6690 topshear.x = -0.5f; 6706 topshear.x = -0.5f;
@@ -6701,8 +6717,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6701 { 6717 {
6702 topshear.y = 0.5f; 6718 topshear.y = 0.5f;
6703 } 6719 }
6704 shapeBlock.PathShearX = (byte)(100 * topshear.x); 6720 tempFloat = (float)(100.0d * topshear.x);
6705 shapeBlock.PathShearY = (byte)(100 * topshear.y); 6721 shapeBlock.PathShearX = (byte)tempFloat;
6722 tempFloat = (float)(100.0d * topshear.y);
6723 shapeBlock.PathShearY = (byte)tempFloat;
6706 6724
6707 part.Shape.SculptEntry = false; 6725 part.Shape.SculptEntry = false;
6708 part.UpdateShape(shapeBlock); 6726 part.UpdateShape(shapeBlock);
@@ -6752,6 +6770,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6752 // Prim type torus, tube and ring. 6770 // Prim type torus, tube and ring.
6753 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) 6771 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve)
6754 { 6772 {
6773 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
6755 ObjectShapePacket.ObjectDataBlock shapeBlock; 6774 ObjectShapePacket.ObjectDataBlock shapeBlock;
6756 6775
6757 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 6776 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -6776,8 +6795,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6776 { 6795 {
6777 holesize.y = 0.5f; 6796 holesize.y = 0.5f;
6778 } 6797 }
6779 shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); 6798 tempFloat = (float)(100.0d * (2.0d - holesize.x));
6780 shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); 6799 shapeBlock.PathScaleX = (byte)tempFloat;
6800 tempFloat = (float)(100.0d * (2.0d - holesize.y));
6801 shapeBlock.PathScaleY = (byte)tempFloat;
6781 if (topshear.x < -0.5f) 6802 if (topshear.x < -0.5f)
6782 { 6803 {
6783 topshear.x = -0.5f; 6804 topshear.x = -0.5f;
@@ -6794,8 +6815,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6794 { 6815 {
6795 topshear.y = 0.5f; 6816 topshear.y = 0.5f;
6796 } 6817 }
6797 shapeBlock.PathShearX = (byte)(100 * topshear.x); 6818 tempFloat = (float)(100.0d * topshear.x);
6798 shapeBlock.PathShearY = (byte)(100 * topshear.y); 6819 shapeBlock.PathShearX = (byte)tempFloat;
6820 tempFloat = (float)(100.0d * topshear.y);
6821 shapeBlock.PathShearY = (byte)tempFloat;
6799 if (profilecut.x < 0f) 6822 if (profilecut.x < 0f)
6800 { 6823 {
6801 profilecut.x = 0f; 6824 profilecut.x = 0f;
@@ -6839,8 +6862,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6839 { 6862 {
6840 taper_a.y = 1f; 6863 taper_a.y = 1f;
6841 } 6864 }
6842 shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); 6865 tempFloat = (float)(100.0d * taper_a.x);
6843 shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); 6866 shapeBlock.PathTaperX = (sbyte)tempFloat;
6867 tempFloat = (float)(100.0d * taper_a.y);
6868 shapeBlock.PathTaperY = (sbyte)tempFloat;
6844 if (revolutions < 1f) 6869 if (revolutions < 1f)
6845 { 6870 {
6846 revolutions = 1f; 6871 revolutions = 1f;
@@ -6849,7 +6874,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6849 { 6874 {
6850 revolutions = 4f; 6875 revolutions = 4f;
6851 } 6876 }
6852 shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); 6877 tempFloat = 66.66667f * (revolutions - 1.0f);
6878 shapeBlock.PathRevolutions = (byte)tempFloat;
6853 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 6879 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
6854 if (radiusoffset < 0f) 6880 if (radiusoffset < 0f)
6855 { 6881 {
@@ -6859,7 +6885,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6859 { 6885 {
6860 radiusoffset = 1f; 6886 radiusoffset = 1f;
6861 } 6887 }
6862 shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); 6888 tempFloat = 100.0f * radiusoffset;
6889 shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
6863 if (skew < -0.95f) 6890 if (skew < -0.95f)
6864 { 6891 {
6865 skew = -0.95f; 6892 skew = -0.95f;
@@ -6868,7 +6895,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6868 { 6895 {
6869 skew = 0.95f; 6896 skew = 0.95f;
6870 } 6897 }
6871 shapeBlock.PathSkew = (sbyte)(100 * skew); 6898 tempFloat = 100.0f * skew;
6899 shapeBlock.PathSkew = (sbyte)tempFloat;
6872 6900
6873 part.Shape.SculptEntry = false; 6901 part.Shape.SculptEntry = false;
6874 part.UpdateShape(shapeBlock); 6902 part.UpdateShape(shapeBlock);
@@ -7681,10 +7709,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7681 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); 7709 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
7682 7710
7683 // float revolutions 7711 // float revolutions
7684 res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned 7712 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
7685 // byte is being used to represent the entire 7713 // Slightly inaccurate, because an unsigned byte is being used to represent
7686 // range of floating-point values from 1.0 7714 // the entire range of floating-point values from 1.0 through 4.0 (which is how
7687 // through 4.0 (which is how SL does it). 7715 // SL does it).
7716 //
7717 // Using these formulas to store and retrieve PathRevolutions, it is not
7718 // possible to use all values between 1.00 and 4.00. For instance, you can't
7719 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
7720 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
7721 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
7722 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
7723 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
7724 // such as 1.10. So, SL must store and retreive the actual user input rather
7725 // than only storing the encoded value.
7688 7726
7689 // float radiusoffset 7727 // float radiusoffset
7690 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); 7728 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index 8cd1e84..0cbad41 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
49 49
50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6; 50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; 51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
52 private const double FLOAT_ACCURACY = 0.00005d; 52 private const float FLOAT_ACCURACY = 0.00005f;
53 private LSL_Api m_lslApi; 53 private LSL_Api m_lslApi;
54 54
55 [SetUp] 55 [SetUp]
@@ -194,10 +194,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
194 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type 194 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
195 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type 195 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
196 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut 196 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
197 0.80d, // Prim hollow 197 0.80f, // Prim hollow
198 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist 198 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
199 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple 199 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
200 0.80d); // Prim hollow check 200 0.80f); // Prim hollow check
201 201
202 // Test a prism. 202 // Test a prism.
203 CheckllSetPrimitiveParams( 203 CheckllSetPrimitiveParams(
@@ -206,11 +206,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
206 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type 206 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
207 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type 207 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
208 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 208 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
209 0.90d, // Prim hollow 209 0.90f, // Prim hollow
210 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist 210 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
211 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper 211 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
212 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 212 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
213 0.90d); // Prim hollow check 213 0.90f); // Prim hollow check
214 214
215 // Test a box. 215 // Test a box.
216 CheckllSetPrimitiveParams( 216 CheckllSetPrimitiveParams(
@@ -219,11 +219,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
219 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type 219 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
220 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type 220 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
221 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 221 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
222 0.95d, // Prim hollow 222 0.95f, // Prim hollow
223 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist 223 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
224 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper 224 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
225 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 225 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
226 0.95d); // Prim hollow check 226 0.95f); // Prim hollow check
227 227
228 // Test a tube. 228 // Test a tube.
229 CheckllSetPrimitiveParams( 229 CheckllSetPrimitiveParams(
@@ -232,16 +232,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
232 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type 232 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
233 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type 233 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
234 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 234 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
235 0.00d, // Prim hollow 235 0.00f, // Prim hollow
236 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist 236 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
237 new LSL_Types.Vector3(1.0d, 0.5d, 0.0d), // Prim hole size 237 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
238 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 238 // Expression for y selected to test precision problems during byte
239 // cast in SetPrimitiveShapeParams.
240 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
239 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut 241 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
240 new LSL_Types.Vector3(-1.0d, 1.0d, 0.0d), // Prim taper 242 // Expression for y selected to test precision problems during sbyte
241 1.0d, // Prim revolutions 243 // cast in SetPrimitiveShapeParams.
242 1.0d, // Prim radius 244 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
243 0.0d, // Prim skew 245 1.11f, // Prim revolutions
244 0.00d); // Prim hollow check 246 0.88f, // Prim radius
247 0.95f, // Prim skew
248 0.00f); // Prim hollow check
245 249
246 // Test a prism. 250 // Test a prism.
247 CheckllSetPrimitiveParams( 251 CheckllSetPrimitiveParams(
@@ -250,11 +254,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
250 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type 254 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
251 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type 255 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
252 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 256 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
253 0.95d, // Prim hollow 257 0.95f, // Prim hollow
254 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist 258 // Expression for x selected to test precision problems during sbyte
255 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper 259 // cast in SetPrimitiveShapeBlockParams.
260 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
261 // Expression for y selected to test precision problems during sbyte
262 // cast in SetPrimitiveShapeParams.
263 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
256 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 264 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
257 0.70d); // Prim hollow check 265 0.70f); // Prim hollow check
258 266
259 // Test a sculpted prim. 267 // Test a sculpted prim.
260 CheckllSetPrimitiveParams( 268 CheckllSetPrimitiveParams(
@@ -268,8 +276,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
268 // Set prim params for a box, cylinder or prism and check results. 276 // Set prim params for a box, cylinder or prism and check results.
269 public void CheckllSetPrimitiveParams(string primTest, 277 public void CheckllSetPrimitiveParams(string primTest,
270 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, 278 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
271 double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, 279 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
272 double primHollowCheck) 280 float primHollowCheck)
273 { 281 {
274 // Set the prim params. 282 // Set the prim params.
275 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, 283 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@@ -297,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
297 // Set prim params for a sphere and check results. 305 // Set prim params for a sphere and check results.
298 public void CheckllSetPrimitiveParams(string primTest, 306 public void CheckllSetPrimitiveParams(string primTest,
299 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, 307 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
300 double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, double primHollowCheck) 308 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
301 { 309 {
302 // Set the prim params. 310 // Set the prim params.
303 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, 311 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@@ -324,9 +332,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
324 // Set prim params for a torus, tube or ring and check results. 332 // Set prim params for a torus, tube or ring and check results.
325 public void CheckllSetPrimitiveParams(string primTest, 333 public void CheckllSetPrimitiveParams(string primTest,
326 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, 334 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
327 double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, 335 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
328 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper, 336 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
329 double primRev, double primRadius, double primSkew, double primHollowCheck) 337 float primRev, float primRadius, float primSkew, float primHollowCheck)
330 { 338 {
331 // Set the prim params. 339 // Set the prim params.
332 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, 340 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@@ -353,7 +361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
353 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut"); 361 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
354 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper"); 362 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
355 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY, 363 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
356 "TestllSetPrimitiveParams " + primTest + " prim revolution fail"); 364 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
357 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY, 365 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
358 "TestllSetPrimitiveParams " + primTest + " prim radius fail"); 366 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
359 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY, 367 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index c443669..156fd57 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -339,7 +339,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
339 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), 339 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
340 new Object[] { m_SaveTime }); 340 new Object[] { m_SaveTime });
341 } 341 }
342 }
342 343
344 public void StartProcessing()
345 {
343 m_ThreadPool.Start(); 346 m_ThreadPool.Start();
344 } 347 }
345 348
@@ -591,7 +594,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
591 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 594 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
592 if (part == null) 595 if (part == null)
593 { 596 {
594 m_log.Error("[Script] SceneObjectPart unavailable. Script NOT started."); 597 m_log.ErrorFormat("[Script]: SceneObjectPart with localID {0} unavailable. Script NOT started.", localID);
595 m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n"; 598 m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n";
596 m_ScriptFailCount++; 599 m_ScriptFailCount++;
597 return false; 600 return false;
diff --git a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs
index 7184ba1..cdcdecf 100644
--- a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs
+++ b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs
@@ -1,4 +1,4 @@
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 *
@@ -90,6 +90,11 @@ namespace OpenSim.Services.Connectors
90 { 90 {
91 return m_database.LoadEstateSettings(estateID); 91 return m_database.LoadEstateSettings(estateID);
92 } 92 }
93
94 public EstateSettings CreateNewEstate()
95 {
96 return m_database.CreateNewEstate();
97 }
93 98
94 public List<EstateSettings> LoadEstateSettingsAll() 99 public List<EstateSettings> LoadEstateSettingsAll()
95 { 100 {
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index eeab67a..1648b51 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService
40{ 40{
41 public class XInventoryService : ServiceBase, IInventoryService 41 public class XInventoryService : ServiceBase, IInventoryService
42 { 42 {
43 //private static readonly ILog m_log = 43// private static readonly ILog m_log =
44 // LogManager.GetLogger( 44// LogManager.GetLogger(
45 // MethodBase.GetCurrentMethod().DeclaringType); 45// MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 protected IXInventoryData m_Database; 47 protected IXInventoryData m_Database;
48 protected bool m_AllowDelete = true; 48 protected bool m_AllowDelete = true;
@@ -385,18 +385,22 @@ namespace OpenSim.Services.InventoryService
385 385
386 public virtual bool AddItem(InventoryItemBase item) 386 public virtual bool AddItem(InventoryItemBase item)
387 { 387 {
388 //m_log.DebugFormat( 388// m_log.DebugFormat(
389 // "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); 389// "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner);
390 390
391 return m_Database.StoreItem(ConvertFromOpenSim(item)); 391 return m_Database.StoreItem(ConvertFromOpenSim(item));
392 } 392 }
393 393
394 public virtual bool UpdateItem(InventoryItemBase item) 394 public virtual bool UpdateItem(InventoryItemBase item)
395 { 395 {
396// throw new Exception("urrgh");
396 if (!m_AllowDelete) 397 if (!m_AllowDelete)
397 if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder) 398 if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder)
398 return false; 399 return false;
399 400
401// m_log.InfoFormat(
402// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder);
403
400 return m_Database.StoreItem(ConvertFromOpenSim(item)); 404 return m_Database.StoreItem(ConvertFromOpenSim(item));
401 } 405 }
402 406
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index 8b8a8f9..e071b94 100644
--- a/OpenSim/Services/UserAccountService/UserAccountService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -28,15 +28,15 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net;
31using Nini.Config; 32using Nini.Config;
33using OpenMetaverse;
32using OpenSim.Data; 34using OpenSim.Data;
35using OpenSim.Framework;
33using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
34using OpenSim.Framework.Console; 37using OpenSim.Framework.Console;
35using GridRegion = OpenSim.Services.Interfaces.GridRegion; 38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
36 39
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Services.UserAccountService 40namespace OpenSim.Services.UserAccountService
41{ 41{
42 public class UserAccountService : UserAccountServiceBase, IUserAccountService 42 public class UserAccountService : UserAccountServiceBase, IUserAccountService
@@ -44,10 +44,16 @@ namespace OpenSim.Services.UserAccountService
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static UserAccountService m_RootInstance; 45 private static UserAccountService m_RootInstance;
46 46
47 /// <summary>
48 /// Should we create default entries (minimum body parts/clothing, avatar wearable entries) for a new avatar?
49 /// </summary>
50 private bool m_CreateDefaultAvatarEntries;
51
47 protected IGridService m_GridService; 52 protected IGridService m_GridService;
48 protected IAuthenticationService m_AuthenticationService; 53 protected IAuthenticationService m_AuthenticationService;
49 protected IGridUserService m_GridUserService; 54 protected IGridUserService m_GridUserService;
50 protected IInventoryService m_InventoryService; 55 protected IInventoryService m_InventoryService;
56 protected IAvatarService m_AvatarService;
51 57
52 public UserAccountService(IConfigSource config) 58 public UserAccountService(IConfigSource config)
53 : base(config) 59 : base(config)
@@ -77,6 +83,12 @@ namespace OpenSim.Services.UserAccountService
77 if (invServiceDll != string.Empty) 83 if (invServiceDll != string.Empty)
78 m_InventoryService = LoadPlugin<IInventoryService>(invServiceDll, new Object[] { config }); 84 m_InventoryService = LoadPlugin<IInventoryService>(invServiceDll, new Object[] { config });
79 85
86 string avatarServiceDll = userConfig.GetString("AvatarService", string.Empty);
87 if (avatarServiceDll != string.Empty)
88 m_AvatarService = LoadPlugin<IAvatarService>(avatarServiceDll, new Object[] { config });
89
90 m_CreateDefaultAvatarEntries = userConfig.GetBoolean("CreateDefaultAvatarEntries", false);
91
80 if (MainConsole.Instance != null) 92 if (MainConsole.Instance != null)
81 { 93 {
82 MainConsole.Instance.Commands.AddCommand("UserService", false, 94 MainConsole.Instance.Commands.AddCommand("UserService", false,
@@ -102,9 +114,7 @@ namespace OpenSim.Services.UserAccountService
102 "show account <first> <last>", 114 "show account <first> <last>",
103 "Show account details for the given user", HandleShowAccount); 115 "Show account details for the given user", HandleShowAccount);
104 } 116 }
105
106 } 117 }
107
108 } 118 }
109 119
110 #region IUserAccountService 120 #region IUserAccountService
@@ -330,7 +340,7 @@ namespace OpenSim.Services.UserAccountService
330 email = MainConsole.Instance.CmdPrompt("Email", ""); 340 email = MainConsole.Instance.CmdPrompt("Email", "");
331 else email = cmdparams[5]; 341 else email = cmdparams[5];
332 342
333 CreateUser(firstName, lastName, password, email); 343 CreateUser(UUID.Zero, firstName, lastName, password, email);
334 } 344 }
335 345
336 protected void HandleShowAccount(string module, string[] cmdparams) 346 protected void HandleShowAccount(string module, string[] cmdparams)
@@ -442,11 +452,12 @@ namespace OpenSim.Services.UserAccountService
442 /// <summary> 452 /// <summary>
443 /// Create a user 453 /// Create a user
444 /// </summary> 454 /// </summary>
455 /// <param name="scopeID">Allows hosting of multiple grids in a single database. Normally left as UUID.Zero</param>
445 /// <param name="firstName"></param> 456 /// <param name="firstName"></param>
446 /// <param name="lastName"></param> 457 /// <param name="lastName"></param>
447 /// <param name="password"></param> 458 /// <param name="password"></param>
448 /// <param name="email"></param> 459 /// <param name="email"></param>
449 private void CreateUser(string firstName, string lastName, string password, string email) 460 public UserAccount CreateUser(UUID scopeID, string firstName, string lastName, string password, string email)
450 { 461 {
451 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); 462 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
452 if (null == account) 463 if (null == account)
@@ -493,12 +504,20 @@ namespace OpenSim.Services.UserAccountService
493 { 504 {
494 success = m_InventoryService.CreateUserInventory(account.PrincipalID); 505 success = m_InventoryService.CreateUserInventory(account.PrincipalID);
495 if (!success) 506 if (!success)
507 {
496 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.", 508 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.",
497 firstName, lastName); 509 firstName, lastName);
510 }
511 else if (m_CreateDefaultAvatarEntries)
512 {
513 CreateDefaultAppearanceEntries(account.PrincipalID);
514 }
498 } 515 }
499 516
500 m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", firstName, lastName); 517 m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", firstName, lastName);
501 } else { 518 }
519 else
520 {
502 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Account creation failed for account {0} {1}", firstName, lastName); 521 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Account creation failed for account {0} {1}", firstName, lastName);
503 } 522 }
504 } 523 }
@@ -506,6 +525,128 @@ namespace OpenSim.Services.UserAccountService
506 { 525 {
507 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: A user with the name {0} {1} already exists!", firstName, lastName); 526 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: A user with the name {0} {1} already exists!", firstName, lastName);
508 } 527 }
528
529 return account;
530 }
531
532 private void CreateDefaultAppearanceEntries(UUID principalID)
533 {
534 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID);
535
536 InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Bodypart);
537
538 InventoryItemBase eyes = new InventoryItemBase(UUID.Random(), principalID);
539 eyes.AssetID = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7");
540 eyes.Name = "Default Eyes";
541 eyes.CreatorId = principalID.ToString();
542 eyes.AssetType = (int)AssetType.Bodypart;
543 eyes.InvType = (int)InventoryType.Wearable;
544 eyes.Folder = bodyPartsFolder.ID;
545 eyes.BasePermissions = (uint)PermissionMask.All;
546 eyes.CurrentPermissions = (uint)PermissionMask.All;
547 eyes.EveryOnePermissions = (uint)PermissionMask.All;
548 eyes.GroupPermissions = (uint)PermissionMask.All;
549 eyes.NextPermissions = (uint)PermissionMask.All;
550 eyes.Flags = (uint)WearableType.Eyes;
551 m_InventoryService.AddItem(eyes);
552
553 InventoryItemBase shape = new InventoryItemBase(UUID.Random(), principalID);
554 shape.AssetID = AvatarWearable.DEFAULT_BODY_ASSET;
555 shape.Name = "Default Shape";
556 shape.CreatorId = principalID.ToString();
557 shape.AssetType = (int)AssetType.Bodypart;
558 shape.InvType = (int)InventoryType.Wearable;
559 shape.Folder = bodyPartsFolder.ID;
560 shape.BasePermissions = (uint)PermissionMask.All;
561 shape.CurrentPermissions = (uint)PermissionMask.All;
562 shape.EveryOnePermissions = (uint)PermissionMask.All;
563 shape.GroupPermissions = (uint)PermissionMask.All;
564 shape.NextPermissions = (uint)PermissionMask.All;
565 shape.Flags = (uint)WearableType.Shape;
566 m_InventoryService.AddItem(shape);
567
568 InventoryItemBase skin = new InventoryItemBase(UUID.Random(), principalID);
569 skin.AssetID = AvatarWearable.DEFAULT_SKIN_ASSET;
570 skin.Name = "Default Skin";
571 skin.CreatorId = principalID.ToString();
572 skin.AssetType = (int)AssetType.Bodypart;
573 skin.InvType = (int)InventoryType.Wearable;
574 skin.Folder = bodyPartsFolder.ID;
575 skin.BasePermissions = (uint)PermissionMask.All;
576 skin.CurrentPermissions = (uint)PermissionMask.All;
577 skin.EveryOnePermissions = (uint)PermissionMask.All;
578 skin.GroupPermissions = (uint)PermissionMask.All;
579 skin.NextPermissions = (uint)PermissionMask.All;
580 skin.Flags = (uint)WearableType.Skin;
581 m_InventoryService.AddItem(skin);
582
583 InventoryItemBase hair = new InventoryItemBase(UUID.Random(), principalID);
584 hair.AssetID = AvatarWearable.DEFAULT_HAIR_ASSET;
585 hair.Name = "Default Hair";
586 hair.CreatorId = principalID.ToString();
587 hair.AssetType = (int)AssetType.Bodypart;
588 hair.InvType = (int)InventoryType.Wearable;
589 hair.Folder = bodyPartsFolder.ID;
590 hair.BasePermissions = (uint)PermissionMask.All;
591 hair.CurrentPermissions = (uint)PermissionMask.All;
592 hair.EveryOnePermissions = (uint)PermissionMask.All;
593 hair.GroupPermissions = (uint)PermissionMask.All;
594 hair.NextPermissions = (uint)PermissionMask.All;
595 hair.Flags = (uint)WearableType.Hair;
596 m_InventoryService.AddItem(hair);
597
598 InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Clothing);
599
600 InventoryItemBase shirt = new InventoryItemBase(UUID.Random(), principalID);
601 shirt.AssetID = AvatarWearable.DEFAULT_SHIRT_ASSET;
602 shirt.Name = "Default Shirt";
603 shirt.CreatorId = principalID.ToString();
604 shirt.AssetType = (int)AssetType.Clothing;
605 shirt.InvType = (int)InventoryType.Wearable;
606 shirt.Folder = clothingFolder.ID;
607 shirt.BasePermissions = (uint)PermissionMask.All;
608 shirt.CurrentPermissions = (uint)PermissionMask.All;
609 shirt.EveryOnePermissions = (uint)PermissionMask.All;
610 shirt.GroupPermissions = (uint)PermissionMask.All;
611 shirt.NextPermissions = (uint)PermissionMask.All;
612 shirt.Flags = (uint)WearableType.Shirt;
613 m_InventoryService.AddItem(shirt);
614
615 InventoryItemBase pants = new InventoryItemBase(UUID.Random(), principalID);
616 pants.AssetID = AvatarWearable.DEFAULT_PANTS_ASSET;
617 pants.Name = "Default Pants";
618 pants.CreatorId = principalID.ToString();
619 pants.AssetType = (int)AssetType.Clothing;
620 pants.InvType = (int)InventoryType.Wearable;
621 pants.Folder = clothingFolder.ID;
622 pants.BasePermissions = (uint)PermissionMask.All;
623 pants.CurrentPermissions = (uint)PermissionMask.All;
624 pants.EveryOnePermissions = (uint)PermissionMask.All;
625 pants.GroupPermissions = (uint)PermissionMask.All;
626 pants.NextPermissions = (uint)PermissionMask.All;
627 pants.Flags = (uint)WearableType.Pants;
628 m_InventoryService.AddItem(pants);
629
630 if (m_AvatarService != null)
631 {
632 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default avatar entries for {0}", principalID);
633
634 AvatarWearable[] wearables = new AvatarWearable[6];
635 wearables[AvatarWearable.EYES] = new AvatarWearable(eyes.ID, eyes.AssetID);
636 wearables[AvatarWearable.BODY] = new AvatarWearable(shape.ID, shape.AssetID);
637 wearables[AvatarWearable.SKIN] = new AvatarWearable(skin.ID, skin.AssetID);
638 wearables[AvatarWearable.HAIR] = new AvatarWearable(hair.ID, hair.AssetID);
639 wearables[AvatarWearable.SHIRT] = new AvatarWearable(shirt.ID, shirt.AssetID);
640 wearables[AvatarWearable.PANTS] = new AvatarWearable(pants.ID, pants.AssetID);
641
642 AvatarAppearance ap = new AvatarAppearance();
643 for (int i = 0; i < 6; i++)
644 {
645 ap.SetWearable(i, wearables[i]);
646 }
647
648 m_AvatarService.SetAppearance(principalID, ap);
649 }
509 } 650 }
510 } 651 }
511} 652} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index b7cefeb..71f2bf4 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -234,7 +234,7 @@ namespace OpenSim.Tests.Common.Mock
234 public event ScriptReset OnScriptReset; 234 public event ScriptReset OnScriptReset;
235 public event GetScriptRunning OnGetScriptRunning; 235 public event GetScriptRunning OnGetScriptRunning;
236 public event SetScriptRunning OnSetScriptRunning; 236 public event SetScriptRunning OnSetScriptRunning;
237 public event Action<Vector3, bool> OnAutoPilotGo; 237 public event Action<Vector3, bool, bool> OnAutoPilotGo;
238 238
239 public event TerrainUnacked OnUnackedTerrain; 239 public event TerrainUnacked OnUnackedTerrain;
240 240
diff --git a/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs b/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs
new file mode 100644
index 0000000..b38c382
--- /dev/null
+++ b/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs
@@ -0,0 +1,82 @@
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 OpenMetaverse;
30using NUnit.Framework;
31using NUnit.Framework.Constraints;
32
33namespace OpenSim.Tests.Common
34{
35 public class QuaternionToleranceConstraint : ANumericalToleranceConstraint
36 {
37 private Quaternion _baseValue;
38 private Quaternion _valueToBeTested;
39
40 public QuaternionToleranceConstraint(Quaternion baseValue, double tolerance) : base(tolerance)
41 {
42 _baseValue = baseValue;
43 }
44
45 /// <summary>
46 /// Test whether the constraint is satisfied by a given value
47 /// </summary>
48 /// <param name="valueToBeTested">The value to be tested</param>
49 /// <returns>
50 /// True for success, false for failure
51 /// </returns>
52 public override bool Matches(object valueToBeTested)
53 {
54 if (valueToBeTested == null)
55 {
56 throw new ArgumentException("Constraint cannot be used upon null values.");
57 }
58 if (valueToBeTested.GetType() != typeof (Quaternion))
59 {
60 throw new ArgumentException("Constraint cannot be used upon non quaternion values.");
61 }
62
63 _valueToBeTested = (Quaternion)valueToBeTested;
64
65 return (IsWithinDoubleConstraint(_valueToBeTested.X, _baseValue.X) &&
66 IsWithinDoubleConstraint(_valueToBeTested.Y, _baseValue.Y) &&
67 IsWithinDoubleConstraint(_valueToBeTested.Z, _baseValue.Z) &&
68 IsWithinDoubleConstraint(_valueToBeTested.W, _baseValue.W));
69 }
70
71 public override void WriteDescriptionTo(MessageWriter writer)
72 {
73 writer.WriteExpectedValue(
74 string.Format("A value {0} within tolerance of plus or minus {1}", _baseValue, _tolerance));
75 }
76
77 public override void WriteActualValueTo(MessageWriter writer)
78 {
79 writer.WriteActualValue(_valueToBeTested);
80 }
81 }
82} \ No newline at end of file
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index c36d2a4..925c343 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -149,14 +149,13 @@
149 149
150 ;; Choose one of the physics engines below 150 ;; Choose one of the physics engines below
151 ;; OpenDynamicsEngine is by some distance the most developed physics engine 151 ;; OpenDynamicsEngine is by some distance the most developed physics engine
152 ;; basicphysics effectively does not model physics at all, making all 152 ;; BulletSim is incomplete and experimental but in active development
153 ;; objects phantom 153 ;; basicphysics effectively does not model physics at all, making all objects phantom
154 ;; The Bullet plugins do not work properly right now. A better Bullet plugin is on the way.
155 ;; Default is OpenDynamicsEngine 154 ;; Default is OpenDynamicsEngine
156 ; physics = OpenDynamicsEngine 155 ; physics = OpenDynamicsEngine
156 ; physics = BulletSim
157 ; physics = basicphysics 157 ; physics = basicphysics
158 ; physics = POS 158 ; physics = POS
159 ; physics = modified_BulletX
160 159
161 ;# {permissionmodules} {} {Permission modules to use (may specify multiple modules, separated by space} {} DefaultPermissionsModule 160 ;# {permissionmodules} {} {Permission modules to use (may specify multiple modules, separated by space} {} DefaultPermissionsModule
162 ;; Permission modules to use, separated by space. 161 ;; Permission modules to use, separated by space.
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index 910ba02..7f2636c 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -166,6 +166,14 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
166 PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" 166 PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
167 GridService = "OpenSim.Services.GridService.dll:GridService" 167 GridService = "OpenSim.Services.GridService.dll:GridService"
168 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" 168 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService"
169 ; AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
170
171 ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2
172 ;; to show a default "Ruth" avatar rather than a cloud for a newly created user.
173 ;; Default is false
174 ;; If you enable this you will also need to uncomment the AvatarService line above
175 ; CreateDefaultAvatarEntries = false
176
169 177
170[GridUserService] 178[GridUserService]
171 ; for the server connector 179 ; for the server connector
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index f7781ab..a299a73 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -149,6 +149,14 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
149 PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" 149 PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
150 GridService = "OpenSim.Services.GridService.dll:GridService" 150 GridService = "OpenSim.Services.GridService.dll:GridService"
151 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" 151 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService"
152 ; AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
153
154 ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2
155 ;; to show a default "Ruth" avatar rather than a cloud for a newly created user.
156 ;; Default is false
157 ;; If you enable this you will also need to uncomment the AvatarService line above
158 ; CreateDefaultAvatarEntries = false
159
152 160
153[GridUserService] 161[GridUserService]
154 ; for the server connector 162 ; for the server connector
diff --git a/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml b/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml
index 8ef0fe7..a3d7ba3 100644
--- a/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml
+++ b/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml
@@ -4,7 +4,7 @@
4 <Key Name="assetID" Value="d342e6c0-b9d2-11dc-95ff-0800200c9a66"/> 4 <Key Name="assetID" Value="d342e6c0-b9d2-11dc-95ff-0800200c9a66"/>
5 <Key Name="name" Value="Hair"/> 5 <Key Name="name" Value="Hair"/>
6 <Key Name="assetType" Value="13" /> 6 <Key Name="assetType" Value="13" />
7 <Key Name="fileName" Value="newhair.dat"/> 7 <Key Name="fileName" Value="base_hair.dat"/>
8 </Section> 8 </Section>
9 9
10 <Section Name="Skin"> 10 <Section Name="Skin">
@@ -34,6 +34,14 @@
34 <Key Name="assetType" Value="13" /> 34 <Key Name="assetType" Value="13" />
35 <Key Name="fileName" Value="base_shape.dat"/> 35 <Key Name="fileName" Value="base_shape.dat"/>
36 </Section> 36 </Section>
37
38 <Section Name="Eyes">
39 <Key Name="assetID" Value="4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"/>
40 <Key Name="name" Value="Eyes"/>
41 <Key Name="assetType" Value="13" />
42 <Key Name="fileName" Value="base_eyes.dat"/>
43 </Section>
44
37<!-- 45<!--
38 <Section Name="Jim Shape"> 46 <Section Name="Jim Shape">
39 <Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab74"/> 47 <Key Name="assetID" Value="66c41e39-38f9-f75a-024e-585989bfab74"/>
diff --git a/bin/assets/BodyPartsAssetSet/base_eyes.dat b/bin/assets/BodyPartsAssetSet/base_eyes.dat
new file mode 100644
index 0000000..520157c
--- /dev/null
+++ b/bin/assets/BodyPartsAssetSet/base_eyes.dat
@@ -0,0 +1,26 @@
1LLWearable version 22
2New Eyes
3
4 permissions 0
5 {
6 base_mask 7fffffff
7 owner_mask 7fffffff
8 group_mask 00000000
9 everyone_mask 00000000
10 next_owner_mask 00082000
11 creator_id 11111111-1111-0000-0000-000100bba000
12 owner_id 11111111-1111-0000-0000-000100bba000
13 last_owner_id 00000000-0000-0000-0000-000000000000
14 group_id 00000000-0000-0000-0000-000000000000
15 }
16 sale_info 0
17 {
18 sale_type not
19 sale_price 10
20 }
21type 3
22parameters 2
2398 0
2499 0
25textures 1
263 6522e74d-1660-4e7f-b601-6f48c1659a77
diff --git a/bin/assets/BodyPartsAssetSet/newhair.dat b/bin/assets/BodyPartsAssetSet/base_hair.dat
index 3c5a8c9..05e21d8 100644
--- a/bin/assets/BodyPartsAssetSet/newhair.dat
+++ b/bin/assets/BodyPartsAssetSet/base_hair.dat
@@ -8,8 +8,8 @@ New Hair
8 group_mask 00000000 8 group_mask 00000000
9 everyone_mask 00000000 9 everyone_mask 00000000
10 next_owner_mask 00082000 10 next_owner_mask 00082000
11 creator_id a52db6d0-e96c-4454-85e5-3523722daa25 11 creator_id 11111111-1111-0000-0000-000100bba000
12 owner_id a52db6d0-e96c-4454-85e5-3523722daa25 12 owner_id 11111111-1111-0000-0000-000100bba000
13 last_owner_id 00000000-0000-0000-0000-000000000000 13 last_owner_id 00000000-0000-0000-0000-000000000000
14 group_id 00000000-0000-0000-0000-000000000000 14 group_id 00000000-0000-0000-0000-000000000000
15 } 15 }
@@ -19,7 +19,7 @@ New Hair
19 sale_price 10 19 sale_price 10
20 } 20 }
21type 2 21type 2
22parameters 39 22parameters 90
2316 0 2316 0
2431 .5 2431 .5
25112 0 25112 0
@@ -38,26 +38,77 @@ parameters 39
38140 0 38140 0
39141 0 39141 0
40142 0 40142 0
41143 .13 41143 .12
42144 .1
43145 0
44146 0
45147 0
46148 .22
47149 0
42166 0 48166 0
43167 0 49167 0
44168 0 50168 0
45169 0 51169 0
52171 0
53172 .5
54173 0
55174 0
56175 .3
57176 0
46177 0 58177 0
59178 0
60179 0
61180 .13
47181 .14 62181 .14
48182 .7 63182 .7
49183 .05 64183 .05
50184 0 65184 0
66190 0
67191 0
51192 0 68192 0
69400 .75
70640 0
71641 0
72642 0
73643 0
74644 0
75645 0
52674 -.3 76674 -.3
53750 .7 77750 .7
78751 0
54752 .5 79752 .5
55754 0 80754 0
56755 .05 81755 .05
57757 -1 82757 -1
83761 0
58762 0 84762 0
59763 .55 85763 .55
86771 0
87774 0
88782 0
89783 0
90784 0
60785 0 91785 0
92786 0
93787 0
94788 0
61789 0 95789 0
96790 0
97870 -.29
98871 0
99872 .25
1001000 .5
1011001 .5
1021002 .7
1031003 .7
1041004 0
1051005 0
1061006 0
1071007 0
1081008 0
1091009 0
1101010 0
1111011 0
1121012 .25
62textures 1 113textures 1
634 7ca39b4c-bd19-4699-aff7-f93fd03d3e7b 1144 7ca39b4c-bd19-4699-aff7-f93fd03d3e7b
diff --git a/bin/assets/BodyPartsAssetSet/base_shape.dat b/bin/assets/BodyPartsAssetSet/base_shape.dat
index d9a361f..bf719c9 100644
--- a/bin/assets/BodyPartsAssetSet/base_shape.dat
+++ b/bin/assets/BodyPartsAssetSet/base_shape.dat
@@ -1,105 +1,165 @@
1LLWearable version 22 1LLWearable version 22
2Female Shape and Outfit 3 Shape 2New Shape
3Created by system from avatar's appearance. 3
4 permissions 0 4 permissions 0
5 { 5 {
6 base_mask 00000000 6 base_mask 7fffffff
7 owner_mask 00000000 7 owner_mask 7fffffff
8 group_mask 00000000 8 group_mask 00000000
9 everyone_mask 00000000 9 everyone_mask 00000000
10 next_owner_mask 00000000 10 next_owner_mask 00082000
11 creator_id 11111111-1111-0000-0000-000100bba000 11 creator_id 11111111-1111-0000-0000-000100bba000
12 owner_id 11111111-1111-0000-0000-000100bba000 12 owner_id 11111111-1111-0000-0000-000100bba000
13 last_owner_id 11111111-1111-0000-0000-000100bba000 13 last_owner_id 00000000-0000-0000-0000-000000000000
14 group_id 00000000-0000-0000-0000-000000000000 14 group_id 00000000-0000-0000-0000-000000000000
15 } 15 }
16 sale_info 0 16 sale_info 0
17 { 17 {
18 sale_type not 18 sale_type not
19 sale_price 0 19 sale_price 10
20 } 20 }
21type 0 21type 0
22parameters 82 22parameters 142
231 .21 231 0
242 -.5 242 0
254 -.11 254 0
265 -.1 265 0
276 -.3 276 0
287 -.4 287 0
298 -.5 298 0
3010 .7 3010 0
3111 .34 3111 0
3212 -.5 3212 0
3313 0 3313 0
3414 .04 3414 0
3515 .58 3515 0
3617 .56 3617 0
3718 -.26 3718 0
3819 -.73 3819 0
3920 -.34 3920 0
4021 -.01 4021 0
4122 1 4122 0
4223 -.5 4223 0
4324 -.63 4324 0
4425 .44 4425 0
4527 .05 4526 0
4633 -.24 4627 0
4734 -.7 4728 0
4835 -.16 4829 .12
4936 -.2 4930 .12
5037 -.98 5032 0
5138 -.5 5133 0
5234 0
5335 0
5436 -.5
5537 0
5638 0
5740 0
5280 0 5880 0
53105 .07 59100 0
54155 -.22 60104 0
61105 .5
62106 0
63151 0
64152 0
65153 0
66155 0
67156 0
55157 0 68157 0
56185 -1 69185 0
57193 .86 70186 0
58196 -.74 71187 0
59505 .65 72188 0
60506 .12 73189 0
61507 -1.5 74193 .5
75194 .67
76195 .33
77196 0
78505 .5
79506 0
80507 0
62515 0 81515 0
63517 .16 82517 0
64518 .8 83518 0
65629 0 84626 0
85627 0
86629 .5
87630 0
88631 0
89633 0
90634 0
91635 0
66637 0 92637 0
67646 .4 93646 0
68647 1 94647 0
69649 .36 95648 0
70650 .85 96649 .5
71652 .49 97650 0
72653 -1 98651 0
99652 .5
100653 0
101655 -.08
73656 0 102656 0
74659 .65 103657 0
104658 0
105659 .5
106660 0
107661 0
75662 .5 108662 .5
76663 0 109663 0
77664 0 110664 0
78665 0 111665 0
79675 -.15 112675 0
80676 .26 113676 0
81678 .28 114677 0
82682 .27 115678 .5
83683 -.19 116679 -.08
84684 -.09 117680 -.08
118681 -.08
119682 .5
120683 -.15
121684 0
85685 0 122685 0
86690 .45 123686 0
87692 .4 124687 0
88693 -0 125688 0
89753 -.5 126689 0
90756 -.08 127690 .5
91758 .24 128691 0
92759 .6 129692 0
93760 .11 130693 .6
94764 -.38 131694 -.08
95765 -.3 132695 0
96769 .42 133753 0
97773 .51 134756 0
98795 .16 135758 0
99796 .11 136759 .5
100799 .36 137760 0
138764 0
139765 0
140767 0
141768 0
142769 .5
143770 0
144772 0
145773 .5
146794 .17
147795 .25
148796 0
149797 0
150798 0
151799 .5
101841 0 152841 0
102842 -.82 153842 0
154843 0
155853 0
156854 0
157855 0
103879 0 158879 0
104880 0 159880 0
1601103 0
1611104 0
1621105 0
1631200 0
1641201 0
105textures 0 165textures 0
diff --git a/bin/assets/TexturesAssetSet/TexturesAssetSet.xml b/bin/assets/TexturesAssetSet/TexturesAssetSet.xml
index 3af9c99..ecf2005 100644
--- a/bin/assets/TexturesAssetSet/TexturesAssetSet.xml
+++ b/bin/assets/TexturesAssetSet/TexturesAssetSet.xml
@@ -430,6 +430,13 @@
430 <Key Name="fileName" Value="default_avatar.jp2" /> 430 <Key Name="fileName" Value="default_avatar.jp2" />
431 </Section> 431 </Section>
432 432
433 <Section Name="Default Iris">
434 <Key Name="assetID" Value="6522e74d-1660-4e7f-b601-6f48c1659a77"/>
435 <Key Name="name" Value="Default Iris"/>
436 <Key Name="assetType" Value="0" />
437 <Key Name="fileName" Value="default_iris.jp2" />
438 </Section>
439
433 <Section Name="Cypress 1"> 440 <Section Name="Cypress 1">
434 <Key Name="assetID" Value="fb2ae204-3fd1-df33-594f-c9f882830e66"/> 441 <Key Name="assetID" Value="fb2ae204-3fd1-df33-594f-c9f882830e66"/>
435 <Key Name="name" Value="Cypress 1"/> 442 <Key Name="name" Value="Cypress 1"/>
diff --git a/bin/assets/TexturesAssetSet/default_iris.jp2 b/bin/assets/TexturesAssetSet/default_iris.jp2
new file mode 100644
index 0000000..b932a06
--- /dev/null
+++ b/bin/assets/TexturesAssetSet/default_iris.jp2
Binary files differ
diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini
index bf89d0b..6ad4ac9 100644
--- a/bin/config-include/Standalone.ini
+++ b/bin/config-include/Standalone.ini
@@ -17,12 +17,12 @@
17 AvatarServices = "LocalAvatarServicesConnector" 17 AvatarServices = "LocalAvatarServicesConnector"
18 EntityTransferModule = "BasicEntityTransferModule" 18 EntityTransferModule = "BasicEntityTransferModule"
19 InventoryAccessModule = "BasicInventoryAccessModule" 19 InventoryAccessModule = "BasicInventoryAccessModule"
20 MapImageService = "MapImageServiceModule" 20 MapImageService = "MapImageServiceModule"
21 21
22 LibraryModule = true 22 LibraryModule = true
23 LLLoginServiceInConnector = true 23 LLLoginServiceInConnector = true
24 GridInfoServiceInConnector = true 24 GridInfoServiceInConnector = true
25 MapImageServiceInConnector = true 25 MapImageServiceInConnector = true
26 26
27[Profile] 27[Profile]
28 Module = "BasicProfileModule" 28 Module = "BasicProfileModule"
@@ -70,6 +70,10 @@
70 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" 70 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
71 GridService = "OpenSim.Services.GridService.dll:GridService" 71 GridService = "OpenSim.Services.GridService.dll:GridService"
72 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" 72 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService"
73 AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
74
75 ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 to show a default "Ruth" avatar rather than a cloud.
76 CreateDefaultAvatarEntries = true
73 77
74[GridUserService] 78[GridUserService]
75 LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService" 79 LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
diff --git a/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml b/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml
index a018a0d..9b5080d 100644
--- a/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml
+++ b/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml
@@ -561,4 +561,14 @@
561 <Key Name="assetType" Value="0" /> 561 <Key Name="assetType" Value="0" />
562 <Key Name="inventoryType" Value="0" /> 562 <Key Name="inventoryType" Value="0" />
563 </Section> 563 </Section>
564
565 <Section Name="Default Iris Texture">
566 <Key Name="inventoryID" Value="00000000-0000-2222-9999-000000000013"/>
567 <Key Name="assetID" Value="6522e74d-1660-4e7f-b601-6f48c1659a77"/>
568 <Key Name="folderID" Value="00000112-000f-0000-0000-000100bba001"/>
569 <Key Name="description" Value=""/>
570 <Key Name="name" Value="Default Iris Texture" />
571 <Key Name="assetType" Value="0" />
572 <Key Name="inventoryType" Value="0" />
573 </Section>
564</Nini> 574</Nini>
diff --git a/prebuild.xml b/prebuild.xml
index 392fbdc..690de5a 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -573,34 +573,6 @@
573 </Files> 573 </Files>
574 </Project> 574 </Project>
575 575
576 <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletXPlugin" path="OpenSim/Region/Physics/BulletXPlugin" type="Library">
577 <Configuration name="Debug">
578 <Options>
579 <OutputPath>../../../../bin/Physics/</OutputPath>
580 </Options>
581 </Configuration>
582 <Configuration name="Release">
583 <Options>
584 <OutputPath>../../../../bin/Physics/</OutputPath>
585 </Options>
586 </Configuration>
587
588 <ReferencePath>../../../../bin/</ReferencePath>
589 <Reference name="System"/>
590 <Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
591 <Reference name="Nini" path="../../../../bin/"/>
592 <Reference name="OpenSim.Framework"/>
593 <Reference name="OpenSim.Framework.Console"/>
594 <Reference name="OpenSim.Region.Physics.Manager"/>
595 <Reference name="MonoXnaCompactMaths" path="../../../../bin/"/>
596 <Reference name="Modified.XnaDevRu.BulletX" path="../../../../bin/"/>
597 <Reference name="log4net" path="../../../../bin/"/>
598
599 <Files>
600 <Match pattern="*.cs" recurse="true"/>
601 </Files>
602 </Project>
603
604 <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ConvexDecompositionDotNet" path="OpenSim/Region/Physics/ConvexDecompositionDotNet" type="Library"> 576 <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ConvexDecompositionDotNet" path="OpenSim/Region/Physics/ConvexDecompositionDotNet" type="Library">
605 <Configuration name="Debug"> 577 <Configuration name="Debug">
606 <Options> 578 <Options>
@@ -690,34 +662,6 @@
690 </Files> 662 </Files>
691 </Project> 663 </Project>
692 664
693 <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletDotNETPlugin" path="OpenSim/Region/Physics/BulletDotNETPlugin" type="Library">
694 <Configuration name="Debug">
695 <Options>
696 <OutputPath>../../../../bin/Physics/</OutputPath>
697 </Options>
698 </Configuration>
699 <Configuration name="Release">
700 <Options>
701 <OutputPath>../../../../bin/Physics/</OutputPath>
702 </Options>
703 </Configuration>
704
705 <ReferencePath>../../../../bin/</ReferencePath>
706 <Reference name="System"/>
707 <Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
708 <Reference name="Nini" path="../../../../bin/"/>
709 <Reference name="OpenSim.Framework"/>
710 <Reference name="OpenSim.Framework.Console"/>
711 <Reference name="OpenSim.Region.Physics.Manager"/>
712 <Reference name="BulletDotNET" path="../../../../bin/"/>
713 <Reference name="nunit.framework" path="../../../../bin/"/>
714 <Reference name="log4net" path="../../../../bin/"/>
715
716 <Files>
717 <Match pattern="*.cs" recurse="true"/>
718 </Files>
719 </Project>
720
721 <Project frameworkVersion="v3_5" name="OpenSim.Capabilities" path="OpenSim/Capabilities" type="Library"> 665 <Project frameworkVersion="v3_5" name="OpenSim.Capabilities" path="OpenSim/Capabilities" type="Library">
722 <Configuration name="Debug"> 666 <Configuration name="Debug">
723 <Options> 667 <Options>
@@ -1840,6 +1784,9 @@
1840 <Reference name="OpenSim.Region.ClientStack"/> 1784 <Reference name="OpenSim.Region.ClientStack"/>
1841 <Reference name="OpenSim.Framework.Communications"/> 1785 <Reference name="OpenSim.Framework.Communications"/>
1842 <Reference name="OpenSim.Server.Base"/> 1786 <Reference name="OpenSim.Server.Base"/>
1787 <Reference name="OpenSim.Services.Base"/>
1788 <Reference name="OpenSim.Services.Interfaces"/>
1789 <Reference name="OpenSim.Services.UserAccountService"/>
1843 <Reference name="XMLRPC" path="../../../bin/"/> 1790 <Reference name="XMLRPC" path="../../../bin/"/>
1844 <Reference name="Nini" path="../../../bin/"/> 1791 <Reference name="Nini" path="../../../bin/"/>
1845 <Reference name="log4net" path="../../../bin/"/> 1792 <Reference name="log4net" path="../../../bin/"/>