aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs742
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs328
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs523
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs227
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs750
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs334
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs804
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs389
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
27 files changed, 3570 insertions, 832 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index eb07165..69ce967 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -75,6 +76,10 @@ namespace OpenSim.Region.Framework.Interfaces
75 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 76 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
76 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 77 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
77 78
79 // Same as above, but also load script states from a separate doc
80 ISceneEntity RezSingleAttachmentFromInventory(
81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
82
78 /// <summary> 83 /// <summary>
79 /// Rez multiple attachments from a user's inventory 84 /// Rez multiple attachments from a user's inventory
80 /// </summary> 85 /// </summary>
@@ -96,7 +101,6 @@ namespace OpenSim.Region.Framework.Interfaces
96 /// <param name="itemID"></param> 101 /// <param name="itemID"></param>
97 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID); 102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
98 103
99 /// <summary>
100 /// Update the position of an attachment. 104 /// Update the position of an attachment.
101 /// </summary> 105 /// </summary>
102 /// <param name="sog"></param> 106 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 15060fd..4b17b9a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -229,5 +231,6 @@ namespace OpenSim.Region.Framework.Interfaces
229 /// A <see cref="Dictionary`2"/> 231 /// A <see cref="Dictionary`2"/>
230 /// </returns> 232 /// </returns>
231 Dictionary<UUID, string> GetScriptStates(); 233 Dictionary<UUID, string> GetScriptStates();
234 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
232 } 235 }
233} 236}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 07e97d5..76f1641 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -35,16 +35,18 @@ using OpenSim.Region.Framework.Scenes;
35 35
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
39
38 public interface IEntityTransferModule 40 public interface IEntityTransferModule
39 { 41 {
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 42 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 43 Vector3 lookAt, uint teleportFlags);
42 44
45 bool TeleportHome(UUID id, IClientAPI client);
46
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 47 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 48 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 49
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 50 bool Cross(ScenePresence agent, bool isFlying);
49 51
50 void AgentArrivedAtDestination(UUID agent); 52 void AgentArrivedAtDestination(UUID agent);
@@ -53,7 +55,12 @@ namespace OpenSim.Region.Framework.Interfaces
53 55
54 void EnableChildAgent(ScenePresence agent, GridRegion region); 56 void EnableChildAgent(ScenePresence agent, GridRegion region);
55 57
58 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos);
59
56 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 60 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
61
62 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
63
57 } 64 }
58 65
59 public interface IUserAgentVerificationModule 66 public interface IUserAgentVerificationModule
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 721f0ee..72e79ed 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,5 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 } 50 }
49} 51}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 18c45dd..2d6758b 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -68,6 +68,8 @@ namespace OpenSim.Region.Framework.Interfaces
68 68
69 ArrayList GetScriptErrors(UUID itemID); 69 ArrayList GetScriptErrors(UUID itemID);
70 70
71 bool HasScript(UUID itemID, out bool running);
72
71 void SaveAllState(); 73 void SaveAllState();
72 74
73 /// <summary> 75 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 569c235..9fcd5fe 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -852,6 +856,26 @@ namespace OpenSim.Region.Framework.Scenes
852 } 856 }
853 } 857 }
854 } 858 }
859 public void TriggerTerrainUpdate()
860 {
861 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
862 if (handlerTerrainUpdate != null)
863 {
864 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
865 {
866 try
867 {
868 d();
869 }
870 catch (Exception e)
871 {
872 m_log.ErrorFormat(
873 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
874 e.Message, e.StackTrace);
875 }
876 }
877 }
878 }
855 879
856 public void TriggerTerrainTick() 880 public void TriggerTerrainTick()
857 { 881 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
new file mode 100644
index 0000000..d3c2d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,742 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using System.Xml;
34using OpenSim.Framework.Serialization;
35using OpenSim.Framework.Serialization.External;
36using OpenSim.Region.Framework.Scenes.Serialization;
37using OpenSim.Region.Framework.Scenes.Serialization;
38
39namespace OpenSim.Region.Framework.Scenes
40{
41 public class SOPVehicle
42 {
43 public VehicleData vd;
44
45 public Vehicle Type
46 {
47 get { return vd.m_type; }
48 }
49
50 public SOPVehicle()
51 {
52 vd = new VehicleData();
53 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
54 }
55
56 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
57 {
58 float len;
59 float timestep = 0.01f;
60 switch (pParam)
61 {
62 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
63 if (pValue < 0f) pValue = 0f;
64 if (pValue > 1f) pValue = 1f;
65 vd.m_angularDeflectionEfficiency = pValue;
66 break;
67 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
68 if (pValue < timestep) pValue = timestep;
69 vd.m_angularDeflectionTimescale = pValue;
70 break;
71 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
72 if (pValue < timestep) pValue = timestep;
73 else if (pValue > 120) pValue = 120;
74 vd.m_angularMotorDecayTimescale = pValue;
75 break;
76 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
77 if (pValue < timestep) pValue = timestep;
78 vd.m_angularMotorTimescale = pValue;
79 break;
80 case Vehicle.BANKING_EFFICIENCY:
81 if (pValue < -1f) pValue = -1f;
82 if (pValue > 1f) pValue = 1f;
83 vd.m_bankingEfficiency = pValue;
84 break;
85 case Vehicle.BANKING_MIX:
86 if (pValue < 0f) pValue = 0f;
87 if (pValue > 1f) pValue = 1f;
88 vd.m_bankingMix = pValue;
89 break;
90 case Vehicle.BANKING_TIMESCALE:
91 if (pValue < timestep) pValue = timestep;
92 vd.m_bankingTimescale = pValue;
93 break;
94 case Vehicle.BUOYANCY:
95 if (pValue < -1f) pValue = -1f;
96 if (pValue > 1f) pValue = 1f;
97 vd.m_VehicleBuoyancy = pValue;
98 break;
99 case Vehicle.HOVER_EFFICIENCY:
100 if (pValue < 0f) pValue = 0f;
101 if (pValue > 1f) pValue = 1f;
102 vd.m_VhoverEfficiency = pValue;
103 break;
104 case Vehicle.HOVER_HEIGHT:
105 vd.m_VhoverHeight = pValue;
106 break;
107 case Vehicle.HOVER_TIMESCALE:
108 if (pValue < timestep) pValue = timestep;
109 vd.m_VhoverTimescale = pValue;
110 break;
111 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
112 if (pValue < 0f) pValue = 0f;
113 if (pValue > 1f) pValue = 1f;
114 vd.m_linearDeflectionEfficiency = pValue;
115 break;
116 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
117 if (pValue < timestep) pValue = timestep;
118 vd.m_linearDeflectionTimescale = pValue;
119 break;
120 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
121 if (pValue < timestep) pValue = timestep;
122 else if (pValue > 120) pValue = 120;
123 vd.m_linearMotorDecayTimescale = pValue;
124 break;
125 case Vehicle.LINEAR_MOTOR_TIMESCALE:
126 if (pValue < timestep) pValue = timestep;
127 vd.m_linearMotorTimescale = pValue;
128 break;
129 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
130 if (pValue < 0f) pValue = 0f;
131 if (pValue > 1f) pValue = 1f;
132 vd.m_verticalAttractionEfficiency = pValue;
133 break;
134 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
135 if (pValue < timestep) pValue = timestep;
136 vd.m_verticalAttractionTimescale = pValue;
137 break;
138
139 // These are vector properties but the engine lets you use a single float value to
140 // set all of the components to the same value
141 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
142 if (pValue < timestep) pValue = timestep;
143 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
144 break;
145 case Vehicle.ANGULAR_MOTOR_DIRECTION:
146 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
147 len = vd.m_angularMotorDirection.Length();
148 if (len > 12.566f)
149 vd.m_angularMotorDirection *= (12.566f / len);
150 break;
151 case Vehicle.LINEAR_FRICTION_TIMESCALE:
152 if (pValue < timestep) pValue = timestep;
153 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
154 break;
155 case Vehicle.LINEAR_MOTOR_DIRECTION:
156 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
157 len = vd.m_linearMotorDirection.Length();
158 if (len > 30.0f)
159 vd.m_linearMotorDirection *= (30.0f / len);
160 break;
161 case Vehicle.LINEAR_MOTOR_OFFSET:
162 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
163 len = vd.m_linearMotorOffset.Length();
164 if (len > 100.0f)
165 vd.m_linearMotorOffset *= (100.0f / len);
166 break;
167 }
168 }//end ProcessFloatVehicleParam
169
170 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
171 {
172 float len;
173 float timestep = 0.01f;
174 switch (pParam)
175 {
176 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
177 if (pValue.X < timestep) pValue.X = timestep;
178 if (pValue.Y < timestep) pValue.Y = timestep;
179 if (pValue.Z < timestep) pValue.Z = timestep;
180
181 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
182 break;
183 case Vehicle.ANGULAR_MOTOR_DIRECTION:
184 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
185 // Limit requested angular speed to 2 rps= 4 pi rads/sec
186 len = vd.m_angularMotorDirection.Length();
187 if (len > 12.566f)
188 vd.m_angularMotorDirection *= (12.566f / len);
189 break;
190 case Vehicle.LINEAR_FRICTION_TIMESCALE:
191 if (pValue.X < timestep) pValue.X = timestep;
192 if (pValue.Y < timestep) pValue.Y = timestep;
193 if (pValue.Z < timestep) pValue.Z = timestep;
194 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
195 break;
196 case Vehicle.LINEAR_MOTOR_DIRECTION:
197 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
198 len = vd.m_linearMotorDirection.Length();
199 if (len > 30.0f)
200 vd.m_linearMotorDirection *= (30.0f / len);
201 break;
202 case Vehicle.LINEAR_MOTOR_OFFSET:
203 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
204 len = vd.m_linearMotorOffset.Length();
205 if (len > 100.0f)
206 vd.m_linearMotorOffset *= (100.0f / len);
207 break;
208 }
209 }//end ProcessVectorVehicleParam
210
211 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
212 {
213 switch (pParam)
214 {
215 case Vehicle.REFERENCE_FRAME:
216 vd.m_referenceFrame = Quaternion.Inverse(pValue);
217 break;
218 }
219 }//end ProcessRotationVehicleParam
220
221 public void ProcessVehicleFlags(int pParam, bool remove)
222 {
223 if (remove)
224 {
225 vd.m_flags &= ~((VehicleFlag)pParam);
226 }
227 else
228 {
229 vd.m_flags |= (VehicleFlag)pParam;
230 }
231 }//end ProcessVehicleFlags
232
233 public void ProcessTypeChange(Vehicle pType)
234 {
235 vd.m_linearMotorDirection = Vector3.Zero;
236 vd.m_angularMotorDirection = Vector3.Zero;
237 vd.m_linearMotorOffset = Vector3.Zero;
238 vd.m_referenceFrame = Quaternion.Identity;
239
240 // Set Defaults For Type
241 vd.m_type = pType;
242 switch (pType)
243 {
244 case Vehicle.TYPE_NONE:
245 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
246 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_linearMotorTimescale = 1000;
248 vd.m_linearMotorDecayTimescale = 120;
249 vd.m_angularMotorTimescale = 1000;
250 vd.m_angularMotorDecayTimescale = 1000;
251 vd.m_VhoverHeight = 0;
252 vd.m_VhoverEfficiency = 1;
253 vd.m_VhoverTimescale = 1000;
254 vd.m_VehicleBuoyancy = 0;
255 vd.m_linearDeflectionEfficiency = 0;
256 vd.m_linearDeflectionTimescale = 1000;
257 vd.m_angularDeflectionEfficiency = 0;
258 vd.m_angularDeflectionTimescale = 1000;
259 vd.m_bankingEfficiency = 0;
260 vd.m_bankingMix = 1;
261 vd.m_bankingTimescale = 1000;
262 vd.m_verticalAttractionEfficiency = 0;
263 vd.m_verticalAttractionTimescale = 1000;
264
265 vd.m_flags = (VehicleFlag)0;
266 break;
267
268 case Vehicle.TYPE_SLED:
269 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
270 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
271 vd.m_linearMotorTimescale = 1000;
272 vd.m_linearMotorDecayTimescale = 120;
273 vd.m_angularMotorTimescale = 1000;
274 vd.m_angularMotorDecayTimescale = 120;
275 vd.m_VhoverHeight = 0;
276 vd.m_VhoverEfficiency = 1;
277 vd.m_VhoverTimescale = 10;
278 vd.m_VehicleBuoyancy = 0;
279 vd.m_linearDeflectionEfficiency = 1;
280 vd.m_linearDeflectionTimescale = 1;
281 vd.m_angularDeflectionEfficiency = 0;
282 vd.m_angularDeflectionTimescale = 1000;
283 vd.m_bankingEfficiency = 0;
284 vd.m_bankingMix = 1;
285 vd.m_bankingTimescale = 10;
286 vd.m_flags &=
287 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
288 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
289 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
290 break;
291 case Vehicle.TYPE_CAR:
292 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
293 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
294 vd.m_linearMotorTimescale = 1;
295 vd.m_linearMotorDecayTimescale = 60;
296 vd.m_angularMotorTimescale = 1;
297 vd.m_angularMotorDecayTimescale = 0.8f;
298 vd.m_VhoverHeight = 0;
299 vd.m_VhoverEfficiency = 0;
300 vd.m_VhoverTimescale = 1000;
301 vd.m_VehicleBuoyancy = 0;
302 vd.m_linearDeflectionEfficiency = 1;
303 vd.m_linearDeflectionTimescale = 2;
304 vd.m_angularDeflectionEfficiency = 0;
305 vd.m_angularDeflectionTimescale = 10;
306 vd.m_verticalAttractionEfficiency = 1f;
307 vd.m_verticalAttractionTimescale = 10f;
308 vd.m_bankingEfficiency = -0.2f;
309 vd.m_bankingMix = 1;
310 vd.m_bankingTimescale = 1;
311 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
312 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
313 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
314 break;
315 case Vehicle.TYPE_BOAT:
316 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
317 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
318 vd.m_linearMotorTimescale = 5;
319 vd.m_linearMotorDecayTimescale = 60;
320 vd.m_angularMotorTimescale = 4;
321 vd.m_angularMotorDecayTimescale = 4;
322 vd.m_VhoverHeight = 0;
323 vd.m_VhoverEfficiency = 0.5f;
324 vd.m_VhoverTimescale = 2;
325 vd.m_VehicleBuoyancy = 1;
326 vd.m_linearDeflectionEfficiency = 0.5f;
327 vd.m_linearDeflectionTimescale = 3;
328 vd.m_angularDeflectionEfficiency = 0.5f;
329 vd.m_angularDeflectionTimescale = 5;
330 vd.m_verticalAttractionEfficiency = 0.5f;
331 vd.m_verticalAttractionTimescale = 5f;
332 vd.m_bankingEfficiency = -0.3f;
333 vd.m_bankingMix = 0.8f;
334 vd.m_bankingTimescale = 1;
335 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
336 VehicleFlag.HOVER_GLOBAL_HEIGHT |
337 VehicleFlag.HOVER_UP_ONLY |
338 VehicleFlag.LIMIT_ROLL_ONLY);
339 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
340 VehicleFlag.LIMIT_MOTOR_UP |
341 VehicleFlag.HOVER_WATER_ONLY);
342 break;
343 case Vehicle.TYPE_AIRPLANE:
344 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
345 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
346 vd.m_linearMotorTimescale = 2;
347 vd.m_linearMotorDecayTimescale = 60;
348 vd.m_angularMotorTimescale = 4;
349 vd.m_angularMotorDecayTimescale = 8;
350 vd.m_VhoverHeight = 0;
351 vd.m_VhoverEfficiency = 0.5f;
352 vd.m_VhoverTimescale = 1000;
353 vd.m_VehicleBuoyancy = 0;
354 vd.m_linearDeflectionEfficiency = 0.5f;
355 vd.m_linearDeflectionTimescale = 0.5f;
356 vd.m_angularDeflectionEfficiency = 1;
357 vd.m_angularDeflectionTimescale = 2;
358 vd.m_verticalAttractionEfficiency = 0.9f;
359 vd.m_verticalAttractionTimescale = 2f;
360 vd.m_bankingEfficiency = 1;
361 vd.m_bankingMix = 0.7f;
362 vd.m_bankingTimescale = 2;
363 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
364 VehicleFlag.HOVER_TERRAIN_ONLY |
365 VehicleFlag.HOVER_GLOBAL_HEIGHT |
366 VehicleFlag.HOVER_UP_ONLY |
367 VehicleFlag.NO_DEFLECTION_UP |
368 VehicleFlag.LIMIT_MOTOR_UP);
369 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
370 break;
371 case Vehicle.TYPE_BALLOON:
372 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
373 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
374 vd.m_linearMotorTimescale = 5;
375 vd.m_linearMotorDecayTimescale = 60;
376 vd.m_angularMotorTimescale = 6;
377 vd.m_angularMotorDecayTimescale = 10;
378 vd.m_VhoverHeight = 5;
379 vd.m_VhoverEfficiency = 0.8f;
380 vd.m_VhoverTimescale = 10;
381 vd.m_VehicleBuoyancy = 1;
382 vd.m_linearDeflectionEfficiency = 0;
383 vd.m_linearDeflectionTimescale = 5;
384 vd.m_angularDeflectionEfficiency = 0;
385 vd.m_angularDeflectionTimescale = 5;
386 vd.m_verticalAttractionEfficiency = 0f;
387 vd.m_verticalAttractionTimescale = 1000f;
388 vd.m_bankingEfficiency = 0;
389 vd.m_bankingMix = 0.7f;
390 vd.m_bankingTimescale = 5;
391 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
392 VehicleFlag.HOVER_TERRAIN_ONLY |
393 VehicleFlag.HOVER_UP_ONLY |
394 VehicleFlag.NO_DEFLECTION_UP |
395 VehicleFlag.LIMIT_MOTOR_UP);
396 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
397 VehicleFlag.HOVER_GLOBAL_HEIGHT);
398 break;
399 }
400 }
401 public void SetVehicle(PhysicsActor ph)
402 {
403 if (ph == null)
404 return;
405 ph.SetVehicle(vd);
406 }
407
408 private XmlTextWriter writer;
409
410 private void XWint(string name, int i)
411 {
412 writer.WriteElementString(name, i.ToString());
413 }
414
415 private void XWfloat(string name, float f)
416 {
417 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
418 }
419
420 private void XWVector(string name, Vector3 vec)
421 {
422 writer.WriteStartElement(name);
423 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
424 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
426 writer.WriteEndElement();
427 }
428
429 private void XWQuat(string name, Quaternion quat)
430 {
431 writer.WriteStartElement(name);
432 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
433 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
436 writer.WriteEndElement();
437 }
438
439 public void ToXml2(XmlTextWriter twriter)
440 {
441 writer = twriter;
442 writer.WriteStartElement("Vehicle");
443
444 XWint("TYPE", (int)vd.m_type);
445 XWint("FLAGS", (int)vd.m_flags);
446
447 // Linear properties
448 XWVector("LMDIR", vd.m_linearMotorDirection);
449 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
450 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
451 XWfloat("LMTIME", vd.m_linearMotorTimescale);
452 XWVector("LMOFF", vd.m_linearMotorOffset);
453
454 //Angular properties
455 XWVector("AMDIR", vd.m_angularMotorDirection);
456 XWfloat("AMTIME", vd.m_angularMotorTimescale);
457 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
458 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
459
460 //Deflection properties
461 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
462 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
463 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
464 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
465
466 //Banking properties
467 XWfloat("BEFF", vd.m_bankingEfficiency);
468 XWfloat("BMIX", vd.m_bankingMix);
469 XWfloat("BTIME", vd.m_bankingTimescale);
470
471 //Hover and Buoyancy properties
472 XWfloat("HHEI", vd.m_VhoverHeight);
473 XWfloat("HEFF", vd.m_VhoverEfficiency);
474 XWfloat("HTIME", vd.m_VhoverTimescale);
475 XWfloat("VBUO", vd.m_VehicleBuoyancy);
476
477 //Attractor properties
478 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
479 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
480
481 XWQuat("REF_FRAME", vd.m_referenceFrame);
482
483 writer.WriteEndElement();
484 writer = null;
485 }
486
487
488
489 XmlTextReader reader;
490
491 private int XRint()
492 {
493 return reader.ReadElementContentAsInt();
494 }
495
496 private float XRfloat()
497 {
498 return reader.ReadElementContentAsFloat();
499 }
500
501 public Vector3 XRvector()
502 {
503 Vector3 vec;
504 reader.ReadStartElement();
505 vec.X = reader.ReadElementContentAsFloat();
506 vec.Y = reader.ReadElementContentAsFloat();
507 vec.Z = reader.ReadElementContentAsFloat();
508 reader.ReadEndElement();
509 return vec;
510 }
511
512 public Quaternion XRquat()
513 {
514 Quaternion q;
515 reader.ReadStartElement();
516 q.X = reader.ReadElementContentAsFloat();
517 q.Y = reader.ReadElementContentAsFloat();
518 q.Z = reader.ReadElementContentAsFloat();
519 q.W = reader.ReadElementContentAsFloat();
520 reader.ReadEndElement();
521 return q;
522 }
523
524 public static bool EReadProcessors(
525 Dictionary<string, Action> processors,
526 XmlTextReader xtr)
527 {
528 bool errors = false;
529
530 string nodeName = string.Empty;
531 while (xtr.NodeType != XmlNodeType.EndElement)
532 {
533 nodeName = xtr.Name;
534
535 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
536
537 Action p = null;
538 if (processors.TryGetValue(xtr.Name, out p))
539 {
540 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
541
542 try
543 {
544 p();
545 }
546 catch (Exception e)
547 {
548 errors = true;
549 if (xtr.NodeType == XmlNodeType.EndElement)
550 xtr.Read();
551 }
552 }
553 else
554 {
555 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
556 xtr.ReadOuterXml(); // ignore
557 }
558 }
559
560 return errors;
561 }
562
563
564
565 public void FromXml2(XmlTextReader _reader, out bool errors)
566 {
567 errors = false;
568 reader = _reader;
569
570 Dictionary<string, Action> m_VehicleXmlProcessors
571 = new Dictionary<string, Action>();
572
573 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
574 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
575
576 // Linear properties
577 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
578 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
579 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
580 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
581 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
582
583 //Angular properties
584 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
585 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
586 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
587 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
588
589 //Deflection properties
590 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
591 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
592 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
593 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
594
595 //Banking properties
596 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
597 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
598 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
599
600 //Hover and Buoyancy properties
601 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
602 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
603 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
604
605 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
606
607 //Attractor properties
608 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
609 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
610
611 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
612
613 vd = new VehicleData();
614
615 reader.ReadStartElement("Vehicle", String.Empty);
616
617 errors = EReadProcessors(
618 m_VehicleXmlProcessors,
619 reader);
620
621 reader.ReadEndElement();
622 reader = null;
623 }
624
625 private void ProcessXR_type()
626 {
627 vd.m_type = (Vehicle)XRint();
628 }
629 private void ProcessXR_flags()
630 {
631 vd.m_flags = (VehicleFlag)XRint();
632 }
633 // Linear properties
634 private void ProcessXR_linearMotorDirection()
635 {
636 vd.m_linearMotorDirection = XRvector();
637 }
638
639 private void ProcessXR_linearFrictionTimescale()
640 {
641 vd.m_linearFrictionTimescale = XRvector();
642 }
643
644 private void ProcessXR_linearMotorDecayTimescale()
645 {
646 vd.m_linearMotorDecayTimescale = XRfloat();
647 }
648 private void ProcessXR_linearMotorTimescale()
649 {
650 vd.m_linearMotorTimescale = XRfloat();
651 }
652 private void ProcessXR_linearMotorOffset()
653 {
654 vd.m_linearMotorOffset = XRvector();
655 }
656
657
658 //Angular properties
659 private void ProcessXR_angularMotorDirection()
660 {
661 vd.m_angularMotorDirection = XRvector();
662 }
663 private void ProcessXR_angularMotorTimescale()
664 {
665 vd.m_angularMotorTimescale = XRfloat();
666 }
667 private void ProcessXR_angularMotorDecayTimescale()
668 {
669 vd.m_angularMotorDecayTimescale = XRfloat();
670 }
671 private void ProcessXR_angularFrictionTimescale()
672 {
673 vd.m_angularFrictionTimescale = XRvector();
674 }
675
676 //Deflection properties
677 private void ProcessXR_angularDeflectionEfficiency()
678 {
679 vd.m_angularDeflectionEfficiency = XRfloat();
680 }
681 private void ProcessXR_angularDeflectionTimescale()
682 {
683 vd.m_angularDeflectionTimescale = XRfloat();
684 }
685 private void ProcessXR_linearDeflectionEfficiency()
686 {
687 vd.m_linearDeflectionEfficiency = XRfloat();
688 }
689 private void ProcessXR_linearDeflectionTimescale()
690 {
691 vd.m_linearDeflectionTimescale = XRfloat();
692 }
693
694 //Banking properties
695 private void ProcessXR_bankingEfficiency()
696 {
697 vd.m_bankingEfficiency = XRfloat();
698 }
699 private void ProcessXR_bankingMix()
700 {
701 vd.m_bankingMix = XRfloat();
702 }
703 private void ProcessXR_bankingTimescale()
704 {
705 vd.m_bankingTimescale = XRfloat();
706 }
707
708 //Hover and Buoyancy properties
709 private void ProcessXR_VhoverHeight()
710 {
711 vd.m_VhoverHeight = XRfloat();
712 }
713 private void ProcessXR_VhoverEfficiency()
714 {
715 vd.m_VhoverEfficiency = XRfloat();
716 }
717 private void ProcessXR_VhoverTimescale()
718 {
719 vd.m_VhoverTimescale = XRfloat();
720 }
721
722 private void ProcessXR_VehicleBuoyancy()
723 {
724 vd.m_VehicleBuoyancy = XRfloat();
725 }
726
727 //Attractor properties
728 private void ProcessXR_verticalAttractionEfficiency()
729 {
730 vd.m_verticalAttractionEfficiency = XRfloat();
731 }
732 private void ProcessXR_verticalAttractionTimescale()
733 {
734 vd.m_verticalAttractionTimescale = XRfloat();
735 }
736
737 private void ProcessXR_referenceFrame()
738 {
739 vd.m_referenceFrame = XRquat();
740 }
741 }
742} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 23f39a8..719c300 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 { 126 {
125// m_log.DebugFormat( 127 folder = InventoryService.GetRootFolder(item.Owner);
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 128
127// f.Name, (AssetType)f.Type, item.Name); 129 if (folder == null)
128
129 item.Folder = f.ID;
130 }
131 else
132 {
133 f = InventoryService.GetRootFolder(item.Owner);
134 if (f != null)
135 {
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 268
287 // Tell anyone managing scripts that a script has been reloaded/changed 269 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -349,6 +331,7 @@ namespace OpenSim.Region.Framework.Scenes
349 331
350 if (UUID.Zero == transactionID) 332 if (UUID.Zero == transactionID)
351 { 333 {
334 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
352 item.Name = itemUpd.Name; 335 item.Name = itemUpd.Name;
353 item.Description = itemUpd.Description; 336 item.Description = itemUpd.Description;
354 337
@@ -736,6 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
736 return; 719 return;
737 } 720 }
738 721
722 if (newName == null) newName = item.Name;
723
739 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 724 AssetBase asset = AssetService.Get(item.AssetID.ToString());
740 725
741 if (asset != null) 726 if (asset != null)
@@ -792,6 +777,24 @@ namespace OpenSim.Region.Framework.Scenes
792 } 777 }
793 778
794 /// <summary> 779 /// <summary>
780 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
781 /// </summary>
782 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
783 {
784 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
785 foreach (InventoryItemBase b in items)
786 {
787 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
788 InventoryItemBase n = InventoryService.GetItem(b);
789 n.Folder = destfolder;
790 moveitems.Add(n);
791 remoteClient.SendInventoryItemCreateUpdate(n, 0);
792 }
793
794 MoveInventoryItem(remoteClient, moveitems);
795 }
796
797 /// <summary>
795 /// Move an item within the agent's inventory. 798 /// Move an item within the agent's inventory.
796 /// </summary> 799 /// </summary>
797 /// <param name="remoteClient"></param> 800 /// <param name="remoteClient"></param>
@@ -1134,6 +1137,10 @@ namespace OpenSim.Region.Framework.Scenes
1134 { 1137 {
1135 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1138 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1136 1139
1140 // Can't move a null item
1141 if (itemId == UUID.Zero)
1142 return;
1143
1137 if (null == part) 1144 if (null == part)
1138 { 1145 {
1139 m_log.WarnFormat( 1146 m_log.WarnFormat(
@@ -1243,6 +1250,10 @@ namespace OpenSim.Region.Framework.Scenes
1243 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1250 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1244 return; 1251 return;
1245 1252
1253 bool overrideNoMod = false;
1254 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1255 overrideNoMod = true;
1256
1246 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1257 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1247 { 1258 {
1248 // object cannot copy items to an object owned by a different owner 1259 // object cannot copy items to an object owned by a different owner
@@ -1252,7 +1263,7 @@ namespace OpenSim.Region.Framework.Scenes
1252 } 1263 }
1253 1264
1254 // must have both move and modify permission to put an item in an object 1265 // must have both move and modify permission to put an item in an object
1255 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1266 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1256 { 1267 {
1257 return; 1268 return;
1258 } 1269 }
@@ -1311,6 +1322,14 @@ namespace OpenSim.Region.Framework.Scenes
1311 1322
1312 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1323 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1313 { 1324 {
1325 SceneObjectPart destPart = GetSceneObjectPart(destID);
1326 if (destPart != null) // Move into a prim
1327 {
1328 foreach(UUID itemID in items)
1329 MoveTaskInventoryItem(destID, host, itemID);
1330 return destID; // Prim folder ID == prim ID
1331 }
1332
1314 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1333 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1315 1334
1316 UUID newFolderID = UUID.Random(); 1335 UUID newFolderID = UUID.Random();
@@ -1496,12 +1515,12 @@ namespace OpenSim.Region.Framework.Scenes
1496 agentTransactions.HandleTaskItemUpdateFromTransaction( 1515 agentTransactions.HandleTaskItemUpdateFromTransaction(
1497 remoteClient, part, transactionID, currentItem); 1516 remoteClient, part, transactionID, currentItem);
1498 1517
1499 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1518// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1500 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1519// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1501 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1520// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1502 remoteClient.SendAgentAlertMessage("Script saved", false); 1521// remoteClient.SendAgentAlertMessage("Script saved", false);
1503 else 1522// else
1504 remoteClient.SendAgentAlertMessage("Item saved", false); 1523// remoteClient.SendAgentAlertMessage("Item saved", false);
1505 } 1524 }
1506 } 1525 }
1507 1526
@@ -1685,7 +1704,7 @@ namespace OpenSim.Region.Framework.Scenes
1685 } 1704 }
1686 1705
1687 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1706 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1688 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1707 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1689 agentID); 1708 agentID);
1690 AssetService.Store(asset); 1709 AssetService.Store(asset);
1691 1710
@@ -1841,23 +1860,32 @@ namespace OpenSim.Region.Framework.Scenes
1841 // build a list of eligible objects 1860 // build a list of eligible objects
1842 List<uint> deleteIDs = new List<uint>(); 1861 List<uint> deleteIDs = new List<uint>();
1843 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1862 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1844 1863 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1845 // Start with true for both, then remove the flags if objects
1846 // that we can't derez are part of the selection
1847 bool permissionToTake = true;
1848 bool permissionToTakeCopy = true;
1849 bool permissionToDelete = true;
1850 1864
1851 foreach (uint localID in localIDs) 1865 foreach (uint localID in localIDs)
1852 { 1866 {
1867 // Start with true for both, then remove the flags if objects
1868 // that we can't derez are part of the selection
1869 bool permissionToTake = true;
1870 bool permissionToTakeCopy = true;
1871 bool permissionToDelete = true;
1872
1853 // Invalid id 1873 // Invalid id
1854 SceneObjectPart part = GetSceneObjectPart(localID); 1874 SceneObjectPart part = GetSceneObjectPart(localID);
1855 if (part == null) 1875 if (part == null)
1876 {
1877 //Client still thinks the object exists, kill it
1878 deleteIDs.Add(localID);
1856 continue; 1879 continue;
1880 }
1857 1881
1858 // Already deleted by someone else 1882 // Already deleted by someone else
1859 if (part.ParentGroup.IsDeleted) 1883 if (part.ParentGroup.IsDeleted)
1884 {
1885 //Client still thinks the object exists, kill it
1886 deleteIDs.Add(localID);
1860 continue; 1887 continue;
1888 }
1861 1889
1862 // Can't delete child prims 1890 // Can't delete child prims
1863 if (part != part.ParentGroup.RootPart) 1891 if (part != part.ParentGroup.RootPart)
@@ -1865,9 +1893,6 @@ namespace OpenSim.Region.Framework.Scenes
1865 1893
1866 SceneObjectGroup grp = part.ParentGroup; 1894 SceneObjectGroup grp = part.ParentGroup;
1867 1895
1868 deleteIDs.Add(localID);
1869 deleteGroups.Add(grp);
1870
1871 if (remoteClient == null) 1896 if (remoteClient == null)
1872 { 1897 {
1873 // Autoreturn has a null client. Nothing else does. So 1898 // Autoreturn has a null client. Nothing else does. So
@@ -1884,83 +1909,195 @@ namespace OpenSim.Region.Framework.Scenes
1884 } 1909 }
1885 else 1910 else
1886 { 1911 {
1887 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1912 if (action == DeRezAction.TakeCopy)
1913 {
1914 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1915 permissionToTakeCopy = false;
1916 }
1917 else
1918 {
1888 permissionToTakeCopy = false; 1919 permissionToTakeCopy = false;
1889 1920 }
1890 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1921 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1891 permissionToTake = false; 1922 permissionToTake = false;
1892 1923
1893 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1924 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1894 permissionToDelete = false; 1925 permissionToDelete = false;
1895 } 1926 }
1896 }
1897 1927
1898 // Handle god perms 1928 // Handle god perms
1899 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1929 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1900 { 1930 {
1901 permissionToTake = true; 1931 permissionToTake = true;
1902 permissionToTakeCopy = true; 1932 permissionToTakeCopy = true;
1903 permissionToDelete = true; 1933 permissionToDelete = true;
1904 } 1934 }
1905 1935
1906 // If we're re-saving, we don't even want to delete 1936 // If we're re-saving, we don't even want to delete
1907 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1937 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1908 permissionToDelete = false; 1938 permissionToDelete = false;
1909 1939
1910 // if we want to take a copy, we also don't want to delete 1940 // if we want to take a copy, we also don't want to delete
1911 // Note: after this point, the permissionToTakeCopy flag 1941 // Note: after this point, the permissionToTakeCopy flag
1912 // becomes irrelevant. It already includes the permissionToTake 1942 // becomes irrelevant. It already includes the permissionToTake
1913 // permission and after excluding no copy items here, we can 1943 // permission and after excluding no copy items here, we can
1914 // just use that. 1944 // just use that.
1915 if (action == DeRezAction.TakeCopy) 1945 if (action == DeRezAction.TakeCopy)
1916 { 1946 {
1917 // If we don't have permission, stop right here 1947 // If we don't have permission, stop right here
1918 if (!permissionToTakeCopy) 1948 if (!permissionToTakeCopy)
1919 return; 1949 return;
1920 1950
1921 permissionToTake = true; 1951 permissionToTake = true;
1922 // Don't delete 1952 // Don't delete
1923 permissionToDelete = false; 1953 permissionToDelete = false;
1924 } 1954 }
1925 1955
1926 if (action == DeRezAction.Return) 1956 if (action == DeRezAction.Return)
1927 {
1928 if (remoteClient != null)
1929 { 1957 {
1930 if (Permissions.CanReturnObjects( 1958 if (remoteClient != null)
1931 null,
1932 remoteClient.AgentId,
1933 deleteGroups))
1934 { 1959 {
1935 permissionToTake = true; 1960 if (Permissions.CanReturnObjects(
1936 permissionToDelete = true; 1961 null,
1937 1962 remoteClient.AgentId,
1938 foreach (SceneObjectGroup g in deleteGroups) 1963 deleteGroups))
1939 { 1964 {
1940 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1965 permissionToTake = true;
1966 permissionToDelete = true;
1967
1968 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1941 } 1969 }
1942 } 1970 }
1971 else // Auto return passes through here with null agent
1972 {
1973 permissionToTake = true;
1974 permissionToDelete = true;
1975 }
1943 } 1976 }
1944 else // Auto return passes through here with null agent 1977
1978 if (permissionToTake && (!permissionToDelete))
1979 takeGroups.Add(grp);
1980
1981 if (permissionToDelete)
1945 { 1982 {
1946 permissionToTake = true; 1983 if (permissionToTake)
1947 permissionToDelete = true; 1984 deleteGroups.Add(grp);
1985 deleteIDs.Add(grp.LocalId);
1948 } 1986 }
1949 } 1987 }
1950 1988
1951 if (permissionToTake) 1989 SendKillObject(deleteIDs);
1990
1991 if (deleteGroups.Count > 0)
1952 { 1992 {
1993 foreach (SceneObjectGroup g in deleteGroups)
1994 deleteIDs.Remove(g.LocalId);
1995
1953 m_asyncSceneObjectDeleter.DeleteToInventory( 1996 m_asyncSceneObjectDeleter.DeleteToInventory(
1954 action, destinationID, deleteGroups, remoteClient, 1997 action, destinationID, deleteGroups, remoteClient,
1955 permissionToDelete); 1998 true);
1999 }
2000 if (takeGroups.Count > 0)
2001 {
2002 m_asyncSceneObjectDeleter.DeleteToInventory(
2003 action, destinationID, takeGroups, remoteClient,
2004 false);
1956 } 2005 }
1957 else if (permissionToDelete) 2006 if (deleteIDs.Count > 0)
1958 { 2007 {
1959 foreach (SceneObjectGroup g in deleteGroups) 2008 foreach (SceneObjectGroup g in deleteGroups)
1960 DeleteSceneObject(g, false); 2009 DeleteSceneObject(g, true);
1961 } 2010 }
1962 } 2011 }
1963 2012
2013 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2014 {
2015 itemID = UUID.Zero;
2016 if (grp != null)
2017 {
2018 Vector3 inventoryStoredPosition = new Vector3
2019 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2020 ? 250
2021 : grp.AbsolutePosition.X)
2022 ,
2023 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2024 ? 250
2025 : grp.AbsolutePosition.X,
2026 grp.AbsolutePosition.Z);
2027
2028 Vector3 originalPosition = grp.AbsolutePosition;
2029
2030 grp.AbsolutePosition = inventoryStoredPosition;
2031
2032 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2033
2034 grp.AbsolutePosition = originalPosition;
2035
2036 AssetBase asset = CreateAsset(
2037 grp.GetPartName(grp.LocalId),
2038 grp.GetPartDescription(grp.LocalId),
2039 (sbyte)AssetType.Object,
2040 Utils.StringToBytes(sceneObjectXml),
2041 remoteClient.AgentId);
2042 AssetService.Store(asset);
2043
2044 InventoryItemBase item = new InventoryItemBase();
2045 item.CreatorId = grp.RootPart.CreatorID.ToString();
2046 item.CreatorData = grp.RootPart.CreatorData;
2047 item.Owner = remoteClient.AgentId;
2048 item.ID = UUID.Random();
2049 item.AssetID = asset.FullID;
2050 item.Description = asset.Description;
2051 item.Name = asset.Name;
2052 item.AssetType = asset.Type;
2053 item.InvType = (int)InventoryType.Object;
2054
2055 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2056 if (folder != null)
2057 item.Folder = folder.ID;
2058 else // oopsies
2059 item.Folder = UUID.Zero;
2060
2061 // Set up base perms properly
2062 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2063 permsBase &= grp.RootPart.BaseMask;
2064 permsBase |= (uint)PermissionMask.Move;
2065
2066 // Make sure we don't lock it
2067 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2068
2069 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2070 {
2071 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2072 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2073 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2074 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2075 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2076 }
2077 else
2078 {
2079 item.BasePermissions = permsBase;
2080 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2081 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2082 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2083 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2084 }
2085 item.CreationDate = Util.UnixTimeSinceEpoch();
2086
2087 // sets itemID so client can show item as 'attached' in inventory
2088 grp.SetFromItemID(item.ID);
2089
2090 if (AddInventoryItem(item))
2091 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2092 else
2093 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2094
2095 itemID = item.ID;
2096 return item.AssetID;
2097 }
2098 return UUID.Zero;
2099 }
2100
1964 /// <summary> 2101 /// <summary>
1965 /// Event Handler Rez an object into a scene 2102 /// Event Handler Rez an object into a scene
1966 /// Calls the non-void event handler 2103 /// Calls the non-void event handler
@@ -2087,6 +2224,9 @@ namespace OpenSim.Region.Framework.Scenes
2087 2224
2088 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2225 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2089 { 2226 {
2227 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2228 return;
2229
2090 SceneObjectPart part = GetSceneObjectPart(objectID); 2230 SceneObjectPart part = GetSceneObjectPart(objectID);
2091 if (part == null) 2231 if (part == null)
2092 return; 2232 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 3355ebe..bf2e775 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -346,7 +346,10 @@ namespace OpenSim.Region.Framework.Scenes
346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
347 347
348 if (accounts == null) 348 if (accounts == null)
349 {
350 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
349 return; 351 return;
352 }
350 353
351 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 354 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
352 // TODO: don't create new blocks if recycling an old packet 355 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index cf6e6af..b7162da 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -104,6 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 // TODO: need to figure out how allow client agents but deny 104 // TODO: need to figure out how allow client agents but deny
105 // root agents when ACL denies access to root agent 105 // root agents when ACL denies access to root agent
106 public bool m_strictAccessControl = true; 106 public bool m_strictAccessControl = true;
107 public bool m_seeIntoBannedRegion = false;
107 public int MaxUndoCount = 5; 108 public int MaxUndoCount = 5;
108 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 109 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
109 public bool LoginLock = false; 110 public bool LoginLock = false;
@@ -119,12 +120,14 @@ namespace OpenSim.Region.Framework.Scenes
119 120
120 protected int m_splitRegionID; 121 protected int m_splitRegionID;
121 protected Timer m_restartWaitTimer = new Timer(); 122 protected Timer m_restartWaitTimer = new Timer();
123 protected Timer m_timerWatchdog = new Timer();
122 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 124 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
123 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 125 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
124 protected string m_simulatorVersion = "OpenSimulator Server"; 126 protected string m_simulatorVersion = "OpenSimulator Server";
125 protected ModuleLoader m_moduleLoader; 127 protected ModuleLoader m_moduleLoader;
126 protected AgentCircuitManager m_authenticateHandler; 128 protected AgentCircuitManager m_authenticateHandler;
127 protected SceneCommunicationService m_sceneGridService; 129 protected SceneCommunicationService m_sceneGridService;
130 protected ISnmpModule m_snmpService = null;
128 131
129 protected ISimulationDataService m_SimulationDataService; 132 protected ISimulationDataService m_SimulationDataService;
130 protected IEstateDataService m_EstateDataService; 133 protected IEstateDataService m_EstateDataService;
@@ -177,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
177 private int m_update_events = 1; 180 private int m_update_events = 1;
178 private int m_update_backup = 200; 181 private int m_update_backup = 200;
179 private int m_update_terrain = 50; 182 private int m_update_terrain = 50;
180// private int m_update_land = 1; 183 private int m_update_land = 10;
181 private int m_update_coarse_locations = 50; 184 private int m_update_coarse_locations = 50;
182 185
183 private int agentMS; 186 private int agentMS;
@@ -192,6 +195,7 @@ namespace OpenSim.Region.Framework.Scenes
192 private int landMS; 195 private int landMS;
193 private int lastCompletedFrame; 196 private int lastCompletedFrame;
194 197
198 public bool CombineRegions = false;
195 /// <summary> 199 /// <summary>
196 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 200 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
197 /// asynchronously from the update loop. 201 /// asynchronously from the update loop.
@@ -214,11 +218,14 @@ namespace OpenSim.Region.Framework.Scenes
214 private bool m_scripts_enabled = true; 218 private bool m_scripts_enabled = true;
215 private string m_defaultScriptEngine; 219 private string m_defaultScriptEngine;
216 private int m_LastLogin; 220 private int m_LastLogin;
217 private Thread HeartbeatThread; 221 private Thread HeartbeatThread = null;
218 private volatile bool shuttingdown; 222 private volatile bool shuttingdown;
219 223
220 private int m_lastUpdate; 224 private int m_lastUpdate;
225 private int m_lastIncoming;
226 private int m_lastOutgoing;
221 private bool m_firstHeartbeat = true; 227 private bool m_firstHeartbeat = true;
228 private int m_hbRestarts = 0;
222 229
223 private object m_deleting_scene_object = new object(); 230 private object m_deleting_scene_object = new object();
224 231
@@ -265,6 +272,19 @@ namespace OpenSim.Region.Framework.Scenes
265 get { return m_sceneGridService; } 272 get { return m_sceneGridService; }
266 } 273 }
267 274
275 public ISnmpModule SnmpService
276 {
277 get
278 {
279 if (m_snmpService == null)
280 {
281 m_snmpService = RequestModuleInterface<ISnmpModule>();
282 }
283
284 return m_snmpService;
285 }
286 }
287
268 public ISimulationDataService SimulationDataService 288 public ISimulationDataService SimulationDataService
269 { 289 {
270 get 290 get
@@ -546,6 +566,9 @@ namespace OpenSim.Region.Framework.Scenes
546 m_EstateDataService = estateDataService; 566 m_EstateDataService = estateDataService;
547 m_regionHandle = m_regInfo.RegionHandle; 567 m_regionHandle = m_regInfo.RegionHandle;
548 m_regionName = m_regInfo.RegionName; 568 m_regionName = m_regInfo.RegionName;
569 m_lastUpdate = Util.EnvironmentTickCount();
570 m_lastIncoming = 0;
571 m_lastOutgoing = 0;
549 572
550 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 573 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
551 m_asyncSceneObjectDeleter.Enabled = true; 574 m_asyncSceneObjectDeleter.Enabled = true;
@@ -677,6 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
677 m_persistAfter *= 10000000; 700 m_persistAfter *= 10000000;
678 701
679 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 702 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
703 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
680 704
681 IConfig packetConfig = m_config.Configs["PacketPool"]; 705 IConfig packetConfig = m_config.Configs["PacketPool"];
682 if (packetConfig != null) 706 if (packetConfig != null)
@@ -686,6 +710,8 @@ namespace OpenSim.Region.Framework.Scenes
686 } 710 }
687 711
688 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 712 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
713 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
714 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
689 715
690 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 716 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
691 if (m_generateMaptiles) 717 if (m_generateMaptiles)
@@ -721,9 +747,9 @@ namespace OpenSim.Region.Framework.Scenes
721 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 747 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
722 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 748 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
723 } 749 }
724 catch 750 catch (Exception e)
725 { 751 {
726 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 752 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
727 } 753 }
728 754
729 #endregion Region Config 755 #endregion Region Config
@@ -1133,7 +1159,22 @@ namespace OpenSim.Region.Framework.Scenes
1133 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1159 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1134 if (HeartbeatThread != null) 1160 if (HeartbeatThread != null)
1135 { 1161 {
1162 m_hbRestarts++;
1163 if(m_hbRestarts > 10)
1164 Environment.Exit(1);
1165 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1166
1167//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1168//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1169//proc.EnableRaisingEvents=false;
1170//proc.StartInfo.FileName = "/bin/kill";
1171//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1172//proc.Start();
1173//proc.WaitForExit();
1174//Thread.Sleep(1000);
1175//Environment.Exit(1);
1136 HeartbeatThread.Abort(); 1176 HeartbeatThread.Abort();
1177 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1137 HeartbeatThread = null; 1178 HeartbeatThread = null;
1138 } 1179 }
1139 m_lastUpdate = Util.EnvironmentTickCount(); 1180 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1180,9 +1221,6 @@ namespace OpenSim.Region.Framework.Scenes
1180 m_eventManager.TriggerOnRegionStarted(this); 1221 m_eventManager.TriggerOnRegionStarted(this);
1181 while (!shuttingdown) 1222 while (!shuttingdown)
1182 Update(); 1223 Update();
1183
1184 m_lastUpdate = Util.EnvironmentTickCount();
1185 m_firstHeartbeat = false;
1186 } 1224 }
1187 catch (ThreadAbortException) 1225 catch (ThreadAbortException)
1188 { 1226 {
@@ -1280,6 +1318,13 @@ namespace OpenSim.Region.Framework.Scenes
1280 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1318 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1281 } 1319 }
1282 1320
1321 // if (Frame % m_update_land == 0)
1322 // {
1323 // int ldMS = Util.EnvironmentTickCount();
1324 // UpdateLand();
1325 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1326 // }
1327
1283 if (Frame % m_update_backup == 0) 1328 if (Frame % m_update_backup == 0)
1284 { 1329 {
1285 int backMS = Util.EnvironmentTickCount(); 1330 int backMS = Util.EnvironmentTickCount();
@@ -1389,12 +1434,16 @@ namespace OpenSim.Region.Framework.Scenes
1389 maintc = Util.EnvironmentTickCountSubtract(maintc); 1434 maintc = Util.EnvironmentTickCountSubtract(maintc);
1390 maintc = (int)(MinFrameTime * 1000) - maintc; 1435 maintc = (int)(MinFrameTime * 1000) - maintc;
1391 1436
1437
1438 m_lastUpdate = Util.EnvironmentTickCount();
1439 m_firstHeartbeat = false;
1440
1392 if (maintc > 0) 1441 if (maintc > 0)
1393 Thread.Sleep(maintc); 1442 Thread.Sleep(maintc);
1394 1443
1395 // Tell the watchdog that this thread is still alive 1444 // Tell the watchdog that this thread is still alive
1396 Watchdog.UpdateThread(); 1445 Watchdog.UpdateThread();
1397 } 1446 }
1398 1447
1399 public void AddGroupTarget(SceneObjectGroup grp) 1448 public void AddGroupTarget(SceneObjectGroup grp)
1400 { 1449 {
@@ -1410,9 +1459,9 @@ namespace OpenSim.Region.Framework.Scenes
1410 1459
1411 private void CheckAtTargets() 1460 private void CheckAtTargets()
1412 { 1461 {
1413 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1462 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1414 lock (m_groupsWithTargets) 1463 lock (m_groupsWithTargets)
1415 objs = m_groupsWithTargets.Values; 1464 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1416 1465
1417 foreach (SceneObjectGroup entry in objs) 1466 foreach (SceneObjectGroup entry in objs)
1418 entry.checkAtTargets(); 1467 entry.checkAtTargets();
@@ -1494,7 +1543,7 @@ namespace OpenSim.Region.Framework.Scenes
1494 msg.fromAgentName = "Server"; 1543 msg.fromAgentName = "Server";
1495 msg.dialog = (byte)19; // Object msg 1544 msg.dialog = (byte)19; // Object msg
1496 msg.fromGroup = false; 1545 msg.fromGroup = false;
1497 msg.offline = (byte)0; 1546 msg.offline = (byte)1;
1498 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1547 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1499 msg.Position = Vector3.Zero; 1548 msg.Position = Vector3.Zero;
1500 msg.RegionID = RegionInfo.RegionID.Guid; 1549 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1725,14 +1774,24 @@ namespace OpenSim.Region.Framework.Scenes
1725 /// <returns></returns> 1774 /// <returns></returns>
1726 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1775 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1727 { 1776 {
1777
1778 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1779 Vector3 wpos = Vector3.Zero;
1780 // Check for water surface intersection from above
1781 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1782 {
1783 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1784 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1785 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1786 wpos.Z = wheight;
1787 }
1788
1728 Vector3 pos = Vector3.Zero; 1789 Vector3 pos = Vector3.Zero;
1729 if (RayEndIsIntersection == (byte)1) 1790 if (RayEndIsIntersection == (byte)1)
1730 { 1791 {
1731 pos = RayEnd; 1792 pos = RayEnd;
1732 return pos;
1733 } 1793 }
1734 1794 else if (RayTargetID != UUID.Zero)
1735 if (RayTargetID != UUID.Zero)
1736 { 1795 {
1737 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1796 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1738 1797
@@ -1754,7 +1813,7 @@ namespace OpenSim.Region.Framework.Scenes
1754 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1813 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1755 1814
1756 // Un-comment out the following line to Get Raytrace results printed to the console. 1815 // Un-comment out the following line to Get Raytrace results printed to the console.
1757 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1816 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1758 float ScaleOffset = 0.5f; 1817 float ScaleOffset = 0.5f;
1759 1818
1760 // If we hit something 1819 // If we hit something
@@ -1777,13 +1836,10 @@ namespace OpenSim.Region.Framework.Scenes
1777 //pos.Z -= 0.25F; 1836 //pos.Z -= 0.25F;
1778 1837
1779 } 1838 }
1780
1781 return pos;
1782 } 1839 }
1783 else 1840 else
1784 { 1841 {
1785 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1842 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1786
1787 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1843 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1788 1844
1789 // Un-comment the following line to print the raytrace results to the console. 1845 // Un-comment the following line to print the raytrace results to the console.
@@ -1792,13 +1848,12 @@ namespace OpenSim.Region.Framework.Scenes
1792 if (ei.HitTF) 1848 if (ei.HitTF)
1793 { 1849 {
1794 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1850 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1795 } else 1851 }
1852 else
1796 { 1853 {
1797 // fall back to our stupid functionality 1854 // fall back to our stupid functionality
1798 pos = RayEnd; 1855 pos = RayEnd;
1799 } 1856 }
1800
1801 return pos;
1802 } 1857 }
1803 } 1858 }
1804 else 1859 else
@@ -1809,8 +1864,12 @@ namespace OpenSim.Region.Framework.Scenes
1809 //increase height so its above the ground. 1864 //increase height so its above the ground.
1810 //should be getting the normal of the ground at the rez point and using that? 1865 //should be getting the normal of the ground at the rez point and using that?
1811 pos.Z += scale.Z / 2f; 1866 pos.Z += scale.Z / 2f;
1812 return pos; 1867// return pos;
1813 } 1868 }
1869
1870 // check against posible water intercept
1871 if (wpos.Z > pos.Z) pos = wpos;
1872 return pos;
1814 } 1873 }
1815 1874
1816 1875
@@ -1894,7 +1953,10 @@ namespace OpenSim.Region.Framework.Scenes
1894 public bool AddRestoredSceneObject( 1953 public bool AddRestoredSceneObject(
1895 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1954 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1896 { 1955 {
1897 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1956 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1957 if (result)
1958 sceneObject.IsDeleted = false;
1959 return result;
1898 } 1960 }
1899 1961
1900 /// <summary> 1962 /// <summary>
@@ -1986,6 +2048,15 @@ namespace OpenSim.Region.Framework.Scenes
1986 /// </summary> 2048 /// </summary>
1987 public void DeleteAllSceneObjects() 2049 public void DeleteAllSceneObjects()
1988 { 2050 {
2051 DeleteAllSceneObjects(false);
2052 }
2053
2054 /// <summary>
2055 /// Delete every object from the scene. This does not include attachments worn by avatars.
2056 /// </summary>
2057 public void DeleteAllSceneObjects(bool exceptNoCopy)
2058 {
2059 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1989 lock (Entities) 2060 lock (Entities)
1990 { 2061 {
1991 EntityBase[] entities = Entities.GetEntities(); 2062 EntityBase[] entities = Entities.GetEntities();
@@ -1994,11 +2065,24 @@ namespace OpenSim.Region.Framework.Scenes
1994 if (e is SceneObjectGroup) 2065 if (e is SceneObjectGroup)
1995 { 2066 {
1996 SceneObjectGroup sog = (SceneObjectGroup)e; 2067 SceneObjectGroup sog = (SceneObjectGroup)e;
1997 if (!sog.IsAttachment) 2068 if (sog != null && !sog.IsAttachment)
1998 DeleteSceneObject((SceneObjectGroup)e, false); 2069 {
2070 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2071 {
2072 DeleteSceneObject((SceneObjectGroup)e, false);
2073 }
2074 else
2075 {
2076 toReturn.Add((SceneObjectGroup)e);
2077 }
2078 }
1999 } 2079 }
2000 } 2080 }
2001 } 2081 }
2082 if (toReturn.Count > 0)
2083 {
2084 returnObjects(toReturn.ToArray(), UUID.Zero);
2085 }
2002 } 2086 }
2003 2087
2004 /// <summary> 2088 /// <summary>
@@ -2046,6 +2130,8 @@ namespace OpenSim.Region.Framework.Scenes
2046 } 2130 }
2047 2131
2048 group.DeleteGroupFromScene(silent); 2132 group.DeleteGroupFromScene(silent);
2133 if (!silent)
2134 SendKillObject(new List<uint>() { group.LocalId });
2049 2135
2050// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2136// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2051 } 2137 }
@@ -2403,10 +2489,17 @@ namespace OpenSim.Region.Framework.Scenes
2403 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2489 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2404 public bool AddSceneObject(SceneObjectGroup sceneObject) 2490 public bool AddSceneObject(SceneObjectGroup sceneObject)
2405 { 2491 {
2492 if (sceneObject.OwnerID == UUID.Zero)
2493 {
2494 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2495 return false;
2496 }
2497
2406 // If the user is banned, we won't let any of their objects 2498 // If the user is banned, we won't let any of their objects
2407 // enter. Period. 2499 // enter. Period.
2408 // 2500 //
2409 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2501 int flags = GetUserFlags(sceneObject.OwnerID);
2502 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2410 { 2503 {
2411 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2504 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2412 2505
@@ -2452,12 +2545,23 @@ namespace OpenSim.Region.Framework.Scenes
2452 } 2545 }
2453 else 2546 else
2454 { 2547 {
2548 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2455 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2549 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2456 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2550 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2457 } 2551 }
2552 if (sceneObject.OwnerID == UUID.Zero)
2553 {
2554 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2555 return false;
2556 }
2458 } 2557 }
2459 else 2558 else
2460 { 2559 {
2560 if (sceneObject.OwnerID == UUID.Zero)
2561 {
2562 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2563 return false;
2564 }
2461 AddRestoredSceneObject(sceneObject, true, false); 2565 AddRestoredSceneObject(sceneObject, true, false);
2462 2566
2463 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2567 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2486,6 +2590,24 @@ namespace OpenSim.Region.Framework.Scenes
2486 return 2; // StateSource.PrimCrossing 2590 return 2; // StateSource.PrimCrossing
2487 } 2591 }
2488 2592
2593 public int GetUserFlags(UUID user)
2594 {
2595 //Unfortunately the SP approach means that the value is cached until region is restarted
2596 /*
2597 ScenePresence sp;
2598 if (TryGetScenePresence(user, out sp))
2599 {
2600 return sp.UserFlags;
2601 }
2602 else
2603 {
2604 */
2605 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2606 if (uac == null)
2607 return 0;
2608 return uac.UserFlags;
2609 //}
2610 }
2489 #endregion 2611 #endregion
2490 2612
2491 #region Add/Remove Avatar Methods 2613 #region Add/Remove Avatar Methods
@@ -2500,6 +2622,7 @@ namespace OpenSim.Region.Framework.Scenes
2500 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2622 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2501 2623
2502 CheckHeartbeat(); 2624 CheckHeartbeat();
2625 ScenePresence presence;
2503 2626
2504 ScenePresence sp = GetScenePresence(client.AgentId); 2627 ScenePresence sp = GetScenePresence(client.AgentId);
2505 2628
@@ -2548,7 +2671,13 @@ namespace OpenSim.Region.Framework.Scenes
2548 2671
2549 EventManager.TriggerOnNewClient(client); 2672 EventManager.TriggerOnNewClient(client);
2550 if (vialogin) 2673 if (vialogin)
2674 {
2551 EventManager.TriggerOnClientLogin(client); 2675 EventManager.TriggerOnClientLogin(client);
2676 // Send initial parcel data
2677 Vector3 pos = sp.AbsolutePosition;
2678 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2679 land.SendLandUpdateToClient(client);
2680 }
2552 2681
2553 return sp; 2682 return sp;
2554 } 2683 }
@@ -2638,19 +2767,12 @@ namespace OpenSim.Region.Framework.Scenes
2638 // and the scene presence and the client, if they exist 2767 // and the scene presence and the client, if they exist
2639 try 2768 try
2640 { 2769 {
2641 // We need to wait for the client to make UDP contact first. 2770 ScenePresence sp = GetScenePresence(agentID);
2642 // It's the UDP contact that creates the scene presence 2771 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2643 ScenePresence sp = WaitGetScenePresence(agentID); 2772
2644 if (sp != null) 2773 if (sp != null)
2645 {
2646 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2647
2648 sp.ControllingClient.Close(); 2774 sp.ControllingClient.Close();
2649 } 2775
2650 else
2651 {
2652 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2653 }
2654 // BANG! SLASH! 2776 // BANG! SLASH!
2655 m_authenticateHandler.RemoveCircuit(agentID); 2777 m_authenticateHandler.RemoveCircuit(agentID);
2656 2778
@@ -2751,6 +2873,7 @@ namespace OpenSim.Region.Framework.Scenes
2751 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2873 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2752 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2874 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2753 client.OnCopyInventoryItem += CopyInventoryItem; 2875 client.OnCopyInventoryItem += CopyInventoryItem;
2876 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2754 client.OnMoveInventoryItem += MoveInventoryItem; 2877 client.OnMoveInventoryItem += MoveInventoryItem;
2755 client.OnRemoveInventoryItem += RemoveInventoryItem; 2878 client.OnRemoveInventoryItem += RemoveInventoryItem;
2756 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2879 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2926,15 +3049,16 @@ namespace OpenSim.Region.Framework.Scenes
2926 /// </summary> 3049 /// </summary>
2927 /// <param name="agentId">The avatar's Unique ID</param> 3050 /// <param name="agentId">The avatar's Unique ID</param>
2928 /// <param name="client">The IClientAPI for the client</param> 3051 /// <param name="client">The IClientAPI for the client</param>
2929 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3052 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2930 { 3053 {
2931 if (m_teleportModule != null) 3054 if (m_teleportModule != null)
2932 m_teleportModule.TeleportHome(agentId, client); 3055 return m_teleportModule.TeleportHome(agentId, client);
2933 else 3056 else
2934 { 3057 {
2935 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3058 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2936 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3059 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2937 } 3060 }
3061 return false;
2938 } 3062 }
2939 3063
2940 /// <summary> 3064 /// <summary>
@@ -3044,6 +3168,16 @@ namespace OpenSim.Region.Framework.Scenes
3044 /// <param name="flags"></param> 3168 /// <param name="flags"></param>
3045 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3169 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3046 { 3170 {
3171 //Add half the avatar's height so that the user doesn't fall through prims
3172 ScenePresence presence;
3173 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3174 {
3175 if (presence.Appearance != null)
3176 {
3177 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3178 }
3179 }
3180
3047 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3181 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3048 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3182 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3049 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3183 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3112,8 +3246,9 @@ namespace OpenSim.Region.Framework.Scenes
3112 regions.Remove(RegionInfo.RegionHandle); 3246 regions.Remove(RegionInfo.RegionHandle);
3113 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3247 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3114 } 3248 }
3115 3249 m_log.Debug("[Scene] Beginning ClientClosed");
3116 m_eventManager.TriggerClientClosed(agentID, this); 3250 m_eventManager.TriggerClientClosed(agentID, this);
3251 m_log.Debug("[Scene] Finished ClientClosed");
3117 } 3252 }
3118 catch (NullReferenceException) 3253 catch (NullReferenceException)
3119 { 3254 {
@@ -3175,9 +3310,10 @@ namespace OpenSim.Region.Framework.Scenes
3175 { 3310 {
3176 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3311 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3177 } 3312 }
3178 3313 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3179 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3314 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3180// CleanDroppedAttachments(); 3315// CleanDroppedAttachments();
3316 m_log.Debug("[Scene] The avatar has left the building");
3181 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3317 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3182 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3318 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3183 } 3319 }
@@ -3299,13 +3435,16 @@ namespace OpenSim.Region.Framework.Scenes
3299 sp = null; 3435 sp = null;
3300 } 3436 }
3301 3437
3302 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3303 3438
3304 //On login test land permisions 3439 //On login test land permisions
3305 if (vialogin) 3440 if (vialogin)
3306 { 3441 {
3307 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3442 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3443 if (cache != null)
3444 cache.Remove(agent.firstname + " " + agent.lastname);
3445 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3308 { 3446 {
3447 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3309 return false; 3448 return false;
3310 } 3449 }
3311 } 3450 }
@@ -3329,8 +3468,13 @@ namespace OpenSim.Region.Framework.Scenes
3329 3468
3330 try 3469 try
3331 { 3470 {
3332 if (!AuthorizeUser(agent, out reason)) 3471 // Always check estate if this is a login. Always
3333 return false; 3472 // check if banned regions are to be blacked out.
3473 if (vialogin || (!m_seeIntoBannedRegion))
3474 {
3475 if (!AuthorizeUser(agent, out reason))
3476 return false;
3477 }
3334 } 3478 }
3335 catch (Exception e) 3479 catch (Exception e)
3336 { 3480 {
@@ -3456,6 +3600,8 @@ namespace OpenSim.Region.Framework.Scenes
3456 } 3600 }
3457 3601
3458 // Honor parcel landing type and position. 3602 // Honor parcel landing type and position.
3603 /*
3604 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3459 if (land != null) 3605 if (land != null)
3460 { 3606 {
3461 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3607 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3463,26 +3609,34 @@ namespace OpenSim.Region.Framework.Scenes
3463 agent.startpos = land.LandData.UserLocation; 3609 agent.startpos = land.LandData.UserLocation;
3464 } 3610 }
3465 } 3611 }
3612 */// This is now handled properly in ScenePresence.MakeRootAgent
3466 } 3613 }
3467 3614
3468 return true; 3615 return true;
3469 } 3616 }
3470 3617
3471 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3618 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3472 { 3619 {
3473 3620 reason = String.Empty;
3474 bool banned = land.IsBannedFromLand(agent.AgentID); 3621 if (Permissions.IsGod(agentID))
3475 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3622 return true;
3623
3624 ILandObject land = LandChannel.GetLandObject(posX, posY);
3625 if (land == null)
3626 return false;
3627
3628 bool banned = land.IsBannedFromLand(agentID);
3629 bool restricted = land.IsRestrictedFromLand(agentID);
3476 3630
3477 if (banned || restricted) 3631 if (banned || restricted)
3478 { 3632 {
3479 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3633 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3480 if (nearestParcel != null) 3634 if (nearestParcel != null)
3481 { 3635 {
3482 //Move agent to nearest allowed 3636 //Move agent to nearest allowed
3483 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3637 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3484 agent.startpos.X = newPosition.X; 3638 posX = newPosition.X;
3485 agent.startpos.Y = newPosition.Y; 3639 posY = newPosition.Y;
3486 } 3640 }
3487 else 3641 else
3488 { 3642 {
@@ -3544,7 +3698,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3698
3545 if (!m_strictAccessControl) return true; 3699 if (!m_strictAccessControl) return true;
3546 if (Permissions.IsGod(agent.AgentID)) return true; 3700 if (Permissions.IsGod(agent.AgentID)) return true;
3547 3701
3548 if (AuthorizationService != null) 3702 if (AuthorizationService != null)
3549 { 3703 {
3550 if (!AuthorizationService.IsAuthorizedForRegion( 3704 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3552,14 +3706,14 @@ namespace OpenSim.Region.Framework.Scenes
3552 { 3706 {
3553 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3707 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3554 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3708 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3555 3709
3556 return false; 3710 return false;
3557 } 3711 }
3558 } 3712 }
3559 3713
3560 if (m_regInfo.EstateSettings != null) 3714 if (m_regInfo.EstateSettings != null)
3561 { 3715 {
3562 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3716 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3563 { 3717 {
3564 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3718 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3565 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3719 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3751,6 +3905,13 @@ namespace OpenSim.Region.Framework.Scenes
3751 3905
3752 // We have to wait until the viewer contacts this region after receiving EAC. 3906 // We have to wait until the viewer contacts this region after receiving EAC.
3753 // That calls AddNewClient, which finally creates the ScenePresence 3907 // That calls AddNewClient, which finally creates the ScenePresence
3908 int flags = GetUserFlags(cAgentData.AgentID);
3909 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3910 {
3911 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3912 return false;
3913 }
3914
3754 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3915 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3755 if (nearestParcel == null) 3916 if (nearestParcel == null)
3756 { 3917 {
@@ -3832,12 +3993,22 @@ namespace OpenSim.Region.Framework.Scenes
3832 return false; 3993 return false;
3833 } 3994 }
3834 3995
3996 public bool IncomingCloseAgent(UUID agentID)
3997 {
3998 return IncomingCloseAgent(agentID, false);
3999 }
4000
4001 public bool IncomingCloseChildAgent(UUID agentID)
4002 {
4003 return IncomingCloseAgent(agentID, true);
4004 }
4005
3835 /// <summary> 4006 /// <summary>
3836 /// Tell a single agent to disconnect from the region. 4007 /// Tell a single agent to disconnect from the region.
3837 /// </summary> 4008 /// </summary>
3838 /// <param name="regionHandle"></param>
3839 /// <param name="agentID"></param> 4009 /// <param name="agentID"></param>
3840 public bool IncomingCloseAgent(UUID agentID) 4010 /// <param name="childOnly"></param>
4011 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3841 { 4012 {
3842 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4013 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3843 4014
@@ -3849,7 +4020,7 @@ namespace OpenSim.Region.Framework.Scenes
3849 { 4020 {
3850 m_sceneGraph.removeUserCount(false); 4021 m_sceneGraph.removeUserCount(false);
3851 } 4022 }
3852 else 4023 else if (!childOnly)
3853 { 4024 {
3854 m_sceneGraph.removeUserCount(true); 4025 m_sceneGraph.removeUserCount(true);
3855 } 4026 }
@@ -3865,9 +4036,12 @@ namespace OpenSim.Region.Framework.Scenes
3865 } 4036 }
3866 else 4037 else
3867 presence.ControllingClient.SendShutdownConnectionNotice(); 4038 presence.ControllingClient.SendShutdownConnectionNotice();
4039 presence.ControllingClient.Close(false);
4040 }
4041 else if (!childOnly)
4042 {
4043 presence.ControllingClient.Close(true);
3868 } 4044 }
3869
3870 presence.ControllingClient.Close();
3871 return true; 4045 return true;
3872 } 4046 }
3873 4047
@@ -4454,34 +4628,78 @@ namespace OpenSim.Region.Framework.Scenes
4454 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4628 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4455 } 4629 }
4456 4630
4457 public int GetHealth() 4631 public int GetHealth(out int flags, out string message)
4458 { 4632 {
4459 // Returns: 4633 // Returns:
4460 // 1 = sim is up and accepting http requests. The heartbeat has 4634 // 1 = sim is up and accepting http requests. The heartbeat has
4461 // stopped and the sim is probably locked up, but a remote 4635 // stopped and the sim is probably locked up, but a remote
4462 // admin restart may succeed 4636 // admin restart may succeed
4463 // 4637 //
4464 // 2 = Sim is up and the heartbeat is running. The sim is likely 4638 // 2 = Sim is up and the heartbeat is running. The sim is likely
4465 // usable for people within and logins _may_ work 4639 // usable for people within
4640 //
4641 // 3 = Sim is up and one packet thread is running. Sim is
4642 // unstable and will not accept new logins
4643 //
4644 // 4 = Sim is up and both packet threads are running. Sim is
4645 // likely usable
4466 // 4646 //
4467 // 3 = We have seen a new user enter within the past 4 minutes 4647 // 5 = We have seen a new user enter within the past 4 minutes
4468 // which can be seen as positive confirmation of sim health 4648 // which can be seen as positive confirmation of sim health
4469 // 4649 //
4650
4651 flags = 0;
4652 message = String.Empty;
4653
4654 CheckHeartbeat();
4655
4656 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4657 {
4658 // We're still starting
4659 // 0 means "in startup", it can't happen another way, since
4660 // to get here, we must be able to accept http connections
4661 return 0;
4662 }
4663
4470 int health=1; // Start at 1, means we're up 4664 int health=1; // Start at 1, means we're up
4471 4665
4472 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4666 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4667 {
4668 health+=1;
4669 flags |= 1;
4670 }
4671
4672 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4673 {
4674 health+=1;
4675 flags |= 2;
4676 }
4677
4678 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4679 {
4473 health+=1; 4680 health+=1;
4681 flags |= 4;
4682 }
4474 else 4683 else
4684 {
4685int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4686System.Diagnostics.Process proc = new System.Diagnostics.Process();
4687proc.EnableRaisingEvents=false;
4688proc.StartInfo.FileName = "/bin/kill";
4689proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4690proc.Start();
4691proc.WaitForExit();
4692Thread.Sleep(1000);
4693Environment.Exit(1);
4694 }
4695
4696 if (flags != 7)
4475 return health; 4697 return health;
4476 4698
4477 // A login in the last 4 mins? We can't be doing too badly 4699 // A login in the last 4 mins? We can't be doing too badly
4478 // 4700 //
4479 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4701 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4480 health++; 4702 health++;
4481 else
4482 return health;
4483
4484 CheckHeartbeat();
4485 4703
4486 return health; 4704 return health;
4487 } 4705 }
@@ -4570,7 +4788,7 @@ namespace OpenSim.Region.Framework.Scenes
4570 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4788 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4571 if (wasUsingPhysics) 4789 if (wasUsingPhysics)
4572 { 4790 {
4573 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 4791 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
4574 } 4792 }
4575 } 4793 }
4576 4794
@@ -4674,7 +4892,7 @@ namespace OpenSim.Region.Framework.Scenes
4674 if (m_firstHeartbeat) 4892 if (m_firstHeartbeat)
4675 return; 4893 return;
4676 4894
4677 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4895 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4678 StartTimer(); 4896 StartTimer();
4679 } 4897 }
4680 4898
@@ -4688,9 +4906,14 @@ namespace OpenSim.Region.Framework.Scenes
4688 get { return m_allowScriptCrossings; } 4906 get { return m_allowScriptCrossings; }
4689 } 4907 }
4690 4908
4691 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 4909 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4692 { 4910 {
4693 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 4911 return GetNearestAllowedPosition(avatar, null);
4912 }
4913
4914 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4915 {
4916 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4694 4917
4695 if (nearestParcel != null) 4918 if (nearestParcel != null)
4696 { 4919 {
@@ -4699,10 +4922,7 @@ namespace OpenSim.Region.Framework.Scenes
4699 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 4922 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4700 if (nearestPoint != null) 4923 if (nearestPoint != null)
4701 { 4924 {
4702// m_log.DebugFormat( 4925 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4703// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4704// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4705
4706 return nearestPoint.Value; 4926 return nearestPoint.Value;
4707 } 4927 }
4708 4928
@@ -4712,16 +4932,12 @@ namespace OpenSim.Region.Framework.Scenes
4712 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 4932 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4713 if (nearestPoint != null) 4933 if (nearestPoint != null)
4714 { 4934 {
4715// m_log.DebugFormat( 4935 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4716// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4717
4718 return nearestPoint.Value; 4936 return nearestPoint.Value;
4719 } 4937 }
4720 4938
4721 //Ultimate backup if we have no idea where they are 4939 //Ultimate backup if we have no idea where they are
4722// m_log.DebugFormat( 4940 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
4723// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition);
4724
4725 return avatar.lastKnownAllowedPosition; 4941 return avatar.lastKnownAllowedPosition;
4726 } 4942 }
4727 4943
@@ -4756,13 +4972,18 @@ namespace OpenSim.Region.Framework.Scenes
4756 4972
4757 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 4973 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4758 { 4974 {
4975 return GetNearestAllowedParcel(avatarId, x, y, null);
4976 }
4977
4978 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
4979 {
4759 List<ILandObject> all = AllParcels(); 4980 List<ILandObject> all = AllParcels();
4760 float minParcelDistance = float.MaxValue; 4981 float minParcelDistance = float.MaxValue;
4761 ILandObject nearestParcel = null; 4982 ILandObject nearestParcel = null;
4762 4983
4763 foreach (var parcel in all) 4984 foreach (var parcel in all)
4764 { 4985 {
4765 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 4986 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4766 { 4987 {
4767 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 4988 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4768 if (parcelDistance < minParcelDistance) 4989 if (parcelDistance < minParcelDistance)
@@ -5004,7 +5225,55 @@ namespace OpenSim.Region.Framework.Scenes
5004 mapModule.GenerateMaptile(); 5225 mapModule.GenerateMaptile();
5005 } 5226 }
5006 5227
5007 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5228// public void CleanDroppedAttachments()
5229// {
5230// List<SceneObjectGroup> objectsToDelete =
5231// new List<SceneObjectGroup>();
5232//
5233// lock (m_cleaningAttachments)
5234// {
5235// ForEachSOG(delegate (SceneObjectGroup grp)
5236// {
5237// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5238// {
5239// UUID agentID = grp.OwnerID;
5240// if (agentID == UUID.Zero)
5241// {
5242// objectsToDelete.Add(grp);
5243// return;
5244// }
5245//
5246// ScenePresence sp = GetScenePresence(agentID);
5247// if (sp == null)
5248// {
5249// objectsToDelete.Add(grp);
5250// return;
5251// }
5252// }
5253// });
5254// }
5255//
5256// foreach (SceneObjectGroup grp in objectsToDelete)
5257// {
5258// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5259// DeleteSceneObject(grp, true);
5260// }
5261// }
5262
5263 public void ThreadAlive(int threadCode)
5264 {
5265 switch(threadCode)
5266 {
5267 case 1: // Incoming
5268 m_lastIncoming = Util.EnvironmentTickCount();
5269 break;
5270 case 2: // Incoming
5271 m_lastOutgoing = Util.EnvironmentTickCount();
5272 break;
5273 }
5274 }
5275
5276 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5008 { 5277 {
5009 RegenerateMaptile(); 5278 RegenerateMaptile();
5010 5279
@@ -5023,6 +5292,14 @@ namespace OpenSim.Region.Framework.Scenes
5023 // child agent creation, thereby emulating the SL behavior. 5292 // child agent creation, thereby emulating the SL behavior.
5024 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5293 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5025 { 5294 {
5295 reason = "You are banned from the region";
5296
5297 if (Permissions.IsGod(agentID))
5298 {
5299 reason = String.Empty;
5300 return true;
5301 }
5302
5026 int num = m_sceneGraph.GetNumberOfScenePresences(); 5303 int num = m_sceneGraph.GetNumberOfScenePresences();
5027 5304
5028 if (num >= RegionInfo.RegionSettings.AgentLimit) 5305 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5034,6 +5311,41 @@ namespace OpenSim.Region.Framework.Scenes
5034 } 5311 }
5035 } 5312 }
5036 5313
5314 ScenePresence presence = GetScenePresence(agentID);
5315 IClientAPI client = null;
5316 AgentCircuitData aCircuit = null;
5317
5318 if (presence != null)
5319 {
5320 client = presence.ControllingClient;
5321 if (client != null)
5322 aCircuit = client.RequestClientInfo();
5323 }
5324
5325 // We may be called before there is a presence or a client.
5326 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5327 if (client == null)
5328 {
5329 aCircuit = new AgentCircuitData();
5330 aCircuit.AgentID = agentID;
5331 aCircuit.firstname = String.Empty;
5332 aCircuit.lastname = String.Empty;
5333 }
5334
5335 try
5336 {
5337 if (!AuthorizeUser(aCircuit, out reason))
5338 {
5339 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5340 return false;
5341 }
5342 }
5343 catch (Exception e)
5344 {
5345 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5346 return false;
5347 }
5348
5037 if (position == Vector3.Zero) // Teleport 5349 if (position == Vector3.Zero) // Teleport
5038 { 5350 {
5039 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5351 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5062,13 +5374,46 @@ namespace OpenSim.Region.Framework.Scenes
5062 } 5374 }
5063 } 5375 }
5064 } 5376 }
5377
5378 float posX = 128.0f;
5379 float posY = 128.0f;
5380
5381 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5382 {
5383 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5384 return false;
5385 }
5386 }
5387 else // Walking
5388 {
5389 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5390 if (land == null)
5391 return false;
5392
5393 bool banned = land.IsBannedFromLand(agentID);
5394 bool restricted = land.IsRestrictedFromLand(agentID);
5395
5396 if (banned || restricted)
5397 return false;
5065 } 5398 }
5066 5399
5067 reason = String.Empty; 5400 reason = String.Empty;
5068 return true; 5401 return true;
5069 } 5402 }
5070 5403
5071 /// <summary> 5404 public void StartTimerWatchdog()
5405 {
5406 m_timerWatchdog.Interval = 1000;
5407 m_timerWatchdog.Elapsed += TimerWatchdog;
5408 m_timerWatchdog.AutoReset = true;
5409 m_timerWatchdog.Start();
5410 }
5411
5412 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5413 {
5414 CheckHeartbeat();
5415 }
5416
5072 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5417 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5073 /// autopilot that moves an avatar to a sit target!. 5418 /// autopilot that moves an avatar to a sit target!.
5074 /// </summary> 5419 /// </summary>
@@ -5127,7 +5472,7 @@ namespace OpenSim.Region.Framework.Scenes
5127// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); 5472// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget);
5128 5473
5129 Vector3 agent_control_v3 = new Vector3(); 5474 Vector3 agent_control_v3 = new Vector3();
5130 presence.HandleMoveToTargetUpdate(1, ref agent_control_v3); 5475 presence.HandleMoveToTargetUpdate(ref agent_control_v3);
5131 presence.AddNewMovement(agent_control_v3); 5476 presence.AddNewMovement(agent_control_v3);
5132 } 5477 }
5133 } 5478 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 712e094..da3b4dd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 19c9745..65ffe92 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 92 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 93 }
94 else 94 else
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 103
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
105 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
106 foreach (GridRegion n in neighbours) 106 foreach (GridRegion n in neighbours)
107 { 107 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -180,10 +180,13 @@ namespace OpenSim.Region.Framework.Scenes
180 } 180 }
181 } 181 }
182 182
183 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
184
183 /// <summary> 185 /// <summary>
184 /// Closes a child agent on a given region 186 /// This Closes child agents on neighboring regions
187 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
185 /// </summary> 188 /// </summary>
186 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 189 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
187 { 190 {
188 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 191 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
189 192
@@ -192,31 +195,29 @@ namespace OpenSim.Region.Framework.Scenes
192 Utils.LongToUInts(regionHandle, out x, out y); 195 Utils.LongToUInts(regionHandle, out x, out y);
193 196
194 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 197 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
198 m_scene.SimulationService.CloseChildAgent(destination, agentID);
199 }
195 200
196 m_log.DebugFormat( 201 private void SendCloseChildAgentCompleted(IAsyncResult iar)
197 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 202 {
198 agentID, destination.RegionCoordX, destination.RegionCoordY); 203 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
199 204 icon.EndInvoke(iar);
200 m_scene.SimulationService.CloseAgent(destination, agentID);
201 } 205 }
202 206
203 /// <summary>
204 /// Closes a child agents in a collection of regions. Does so asynchronously
205 /// so that the caller doesn't wait.
206 /// </summary>
207 /// <param name="agentID"></param>
208 /// <param name="regionslst"></param>
209 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 207 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
210 { 208 {
211 foreach (ulong handle in regionslst) 209 foreach (ulong handle in regionslst)
212 { 210 {
213 SendCloseChildAgent(agentID, handle); 211 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
212 d.BeginInvoke(agentID, handle,
213 SendCloseChildAgentCompleted,
214 d);
214 } 215 }
215 } 216 }
216 217
217 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 218 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
218 { 219 {
219 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 220 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
220 } 221 }
221 } 222 }
222} \ No newline at end of file 223}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 66fb493..5a7f124 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes
120 130
121 protected internal void Close() 131 protected internal void Close()
122 { 132 {
123 lock (m_presenceLock) 133 m_scenePresencesLock.EnterWriteLock();
134 try
124 { 135 {
125 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 136 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
126 List<ScenePresence> newlist = new List<ScenePresence>(); 137 List<ScenePresence> newlist = new List<ScenePresence>();
127 m_scenePresenceMap = newmap; 138 m_scenePresenceMap = newmap;
128 m_scenePresenceArray = newlist; 139 m_scenePresenceArray = newlist;
129 } 140 }
141 finally
142 {
143 m_scenePresencesLock.ExitWriteLock();
144 }
130 145
131 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
132 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
@@ -265,6 +280,33 @@ namespace OpenSim.Region.Framework.Scenes
265 protected internal bool AddRestoredSceneObject( 280 protected internal bool AddRestoredSceneObject(
266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
267 { 282 {
283 if (!m_parentScene.CombineRegions)
284 {
285 // KF: Check for out-of-region, move inside and make static.
286 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
287 sceneObject.RootPart.GroupPosition.Y,
288 sceneObject.RootPart.GroupPosition.Z);
289 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
290 npos.X > Constants.RegionSize ||
291 npos.Y > Constants.RegionSize))
292 {
293 if (npos.X < 0.0) npos.X = 1.0f;
294 if (npos.Y < 0.0) npos.Y = 1.0f;
295 if (npos.Z < 0.0) npos.Z = 0.0f;
296 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
297 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
298
299 foreach (SceneObjectPart part in sceneObject.Parts)
300 {
301 part.GroupPosition = npos;
302 }
303 sceneObject.RootPart.Velocity = Vector3.Zero;
304 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
305 sceneObject.RootPart.Acceleration = Vector3.Zero;
306 sceneObject.RootPart.Velocity = Vector3.Zero;
307 }
308 }
309
268 if (attachToBackup && (!alreadyPersisted)) 310 if (attachToBackup && (!alreadyPersisted))
269 { 311 {
270 sceneObject.ForceInventoryPersistence(); 312 sceneObject.ForceInventoryPersistence();
@@ -354,6 +396,11 @@ namespace OpenSim.Region.Framework.Scenes
354 /// </returns> 396 /// </returns>
355 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 397 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
356 { 398 {
399 if (sceneObject == null)
400 {
401 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
402 return false;
403 }
357 if (sceneObject.UUID == UUID.Zero) 404 if (sceneObject.UUID == UUID.Zero)
358 { 405 {
359 m_log.ErrorFormat( 406 m_log.ErrorFormat(
@@ -488,6 +535,30 @@ namespace OpenSim.Region.Framework.Scenes
488 m_updateList[obj.UUID] = obj; 535 m_updateList[obj.UUID] = obj;
489 } 536 }
490 537
538 public void FireAttachToBackup(SceneObjectGroup obj)
539 {
540 if (OnAttachToBackup != null)
541 {
542 OnAttachToBackup(obj);
543 }
544 }
545
546 public void FireDetachFromBackup(SceneObjectGroup obj)
547 {
548 if (OnDetachFromBackup != null)
549 {
550 OnDetachFromBackup(obj);
551 }
552 }
553
554 public void FireChangeBackup(SceneObjectGroup obj)
555 {
556 if (OnChangeBackup != null)
557 {
558 OnChangeBackup(obj);
559 }
560 }
561
491 /// <summary> 562 /// <summary>
492 /// Process all pending updates 563 /// Process all pending updates
493 /// </summary> 564 /// </summary>
@@ -605,7 +676,8 @@ namespace OpenSim.Region.Framework.Scenes
605 676
606 Entities[presence.UUID] = presence; 677 Entities[presence.UUID] = presence;
607 678
608 lock (m_presenceLock) 679 m_scenePresencesLock.EnterWriteLock();
680 try
609 { 681 {
610 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 682 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
611 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 683 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -629,6 +701,10 @@ namespace OpenSim.Region.Framework.Scenes
629 m_scenePresenceMap = newmap; 701 m_scenePresenceMap = newmap;
630 m_scenePresenceArray = newlist; 702 m_scenePresenceArray = newlist;
631 } 703 }
704 finally
705 {
706 m_scenePresencesLock.ExitWriteLock();
707 }
632 } 708 }
633 709
634 /// <summary> 710 /// <summary>
@@ -643,7 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
643 agentID); 719 agentID);
644 } 720 }
645 721
646 lock (m_presenceLock) 722 m_scenePresencesLock.EnterWriteLock();
723 try
647 { 724 {
648 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 725 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
649 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 726 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -665,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes
665 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 742 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
666 } 743 }
667 } 744 }
745 finally
746 {
747 m_scenePresencesLock.ExitWriteLock();
748 }
668 } 749 }
669 750
670 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 751 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1380,8 +1461,13 @@ namespace OpenSim.Region.Framework.Scenes
1380 { 1461 {
1381 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1462 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1382 { 1463 {
1383 if (m_parentScene.AttachmentsModule != null) 1464 // Set the new attachment point data in the object
1384 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1465 byte attachmentPoint = group.GetAttachmentPoint();
1466 group.UpdateGroupPosition(pos);
1467 group.IsAttachment = false;
1468 group.AbsolutePosition = group.RootPart.AttachedPos;
1469 group.AttachmentPoint = attachmentPoint;
1470 group.HasGroupChanged = true;
1385 } 1471 }
1386 else 1472 else
1387 { 1473 {
@@ -1653,8 +1739,11 @@ namespace OpenSim.Region.Framework.Scenes
1653 return; 1739 return;
1654 1740
1655 Monitor.Enter(m_updateLock); 1741 Monitor.Enter(m_updateLock);
1742
1656 try 1743 try
1657 { 1744 {
1745 parentGroup.areUpdatesSuspended = true;
1746
1658 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1747 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1659 1748
1660 // We do this in reverse to get the link order of the prims correct 1749 // We do this in reverse to get the link order of the prims correct
@@ -1669,9 +1758,13 @@ namespace OpenSim.Region.Framework.Scenes
1669 // Make sure no child prim is set for sale 1758 // Make sure no child prim is set for sale
1670 // So that, on delink, no prims are unwittingly 1759 // So that, on delink, no prims are unwittingly
1671 // left for sale and sold off 1760 // left for sale and sold off
1672 child.RootPart.ObjectSaleType = 0; 1761
1673 child.RootPart.SalePrice = 10; 1762 if (child != null)
1674 childGroups.Add(child); 1763 {
1764 child.RootPart.ObjectSaleType = 0;
1765 child.RootPart.SalePrice = 10;
1766 childGroups.Add(child);
1767 }
1675 } 1768 }
1676 1769
1677 foreach (SceneObjectGroup child in childGroups) 1770 foreach (SceneObjectGroup child in childGroups)
@@ -1698,6 +1791,16 @@ namespace OpenSim.Region.Framework.Scenes
1698 } 1791 }
1699 finally 1792 finally
1700 { 1793 {
1794 lock (SceneObjectGroupsByLocalPartID)
1795 {
1796 foreach (SceneObjectPart part in parentGroup.Parts)
1797 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1798 }
1799
1800 parentGroup.areUpdatesSuspended = false;
1801 parentGroup.HasGroupChanged = true;
1802 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1803 parentGroup.ScheduleGroupForFullUpdate();
1701 Monitor.Exit(m_updateLock); 1804 Monitor.Exit(m_updateLock);
1702 } 1805 }
1703 } 1806 }
@@ -1734,21 +1837,24 @@ namespace OpenSim.Region.Framework.Scenes
1734 1837
1735 SceneObjectGroup group = part.ParentGroup; 1838 SceneObjectGroup group = part.ParentGroup;
1736 if (!affectedGroups.Contains(group)) 1839 if (!affectedGroups.Contains(group))
1840 {
1841 group.areUpdatesSuspended = true;
1737 affectedGroups.Add(group); 1842 affectedGroups.Add(group);
1843 }
1738 } 1844 }
1739 } 1845 }
1740 } 1846 }
1741 1847
1742 foreach (SceneObjectPart child in childParts) 1848 if (childParts.Count > 0)
1743 { 1849 {
1744 // Unlink all child parts from their groups 1850 foreach (SceneObjectPart child in childParts)
1745 // 1851 {
1746 child.ParentGroup.DelinkFromGroup(child, true); 1852 // Unlink all child parts from their groups
1747 1853 //
1748 // These are not in affected groups and will not be 1854 child.ParentGroup.DelinkFromGroup(child, true);
1749 // handled further. Do the honors here. 1855 child.ParentGroup.HasGroupChanged = true;
1750 child.ParentGroup.HasGroupChanged = true; 1856 child.ParentGroup.ScheduleGroupForFullUpdate();
1751 child.ParentGroup.ScheduleGroupForFullUpdate(); 1857 }
1752 } 1858 }
1753 1859
1754 foreach (SceneObjectPart root in rootParts) 1860 foreach (SceneObjectPart root in rootParts)
@@ -1758,56 +1864,68 @@ namespace OpenSim.Region.Framework.Scenes
1758 // However, editing linked parts and unlinking may be different 1864 // However, editing linked parts and unlinking may be different
1759 // 1865 //
1760 SceneObjectGroup group = root.ParentGroup; 1866 SceneObjectGroup group = root.ParentGroup;
1867 group.areUpdatesSuspended = true;
1761 1868
1762 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1869 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1763 int numChildren = newSet.Count; 1870 int numChildren = newSet.Count;
1764 1871
1872 if (numChildren == 1)
1873 break;
1874
1765 // If there are prims left in a link set, but the root is 1875 // If there are prims left in a link set, but the root is
1766 // slated for unlink, we need to do this 1876 // slated for unlink, we need to do this
1877 // Unlink the remaining set
1767 // 1878 //
1768 if (numChildren != 1) 1879 bool sendEventsToRemainder = true;
1769 { 1880 if (numChildren > 1)
1770 // Unlink the remaining set 1881 sendEventsToRemainder = false;
1771 //
1772 bool sendEventsToRemainder = true;
1773 if (numChildren > 1)
1774 sendEventsToRemainder = false;
1775 1882
1776 foreach (SceneObjectPart p in newSet) 1883 foreach (SceneObjectPart p in newSet)
1884 {
1885 if (p != group.RootPart)
1777 { 1886 {
1778 if (p != group.RootPart) 1887 group.DelinkFromGroup(p, sendEventsToRemainder);
1779 group.DelinkFromGroup(p, sendEventsToRemainder); 1888 if (numChildren > 2)
1889 {
1890 p.ParentGroup.areUpdatesSuspended = true;
1891 }
1892 else
1893 {
1894 p.ParentGroup.HasGroupChanged = true;
1895 p.ParentGroup.ScheduleGroupForFullUpdate();
1896 }
1780 } 1897 }
1898 }
1899
1900 // If there is more than one prim remaining, we
1901 // need to re-link
1902 //
1903 if (numChildren > 2)
1904 {
1905 // Remove old root
1906 //
1907 if (newSet.Contains(root))
1908 newSet.Remove(root);
1781 1909
1782 // If there is more than one prim remaining, we 1910 // Preserve link ordering
1783 // need to re-link
1784 // 1911 //
1785 if (numChildren > 2) 1912 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1786 { 1913 {
1787 // Remove old root 1914 return a.LinkNum.CompareTo(b.LinkNum);
1788 // 1915 });
1789 if (newSet.Contains(root))
1790 newSet.Remove(root);
1791
1792 // Preserve link ordering
1793 //
1794 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1795 {
1796 return a.LinkNum.CompareTo(b.LinkNum);
1797 });
1798 1916
1799 // Determine new root 1917 // Determine new root
1800 // 1918 //
1801 SceneObjectPart newRoot = newSet[0]; 1919 SceneObjectPart newRoot = newSet[0];
1802 newSet.RemoveAt(0); 1920 newSet.RemoveAt(0);
1803 1921
1804 foreach (SceneObjectPart newChild in newSet) 1922 foreach (SceneObjectPart newChild in newSet)
1805 newChild.ClearUpdateSchedule(); 1923 newChild.ClearUpdateSchedule();
1806 1924
1807 LinkObjects(newRoot, newSet); 1925 newRoot.ParentGroup.areUpdatesSuspended = true;
1808 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1926 LinkObjects(newRoot, newSet);
1809 affectedGroups.Add(newRoot.ParentGroup); 1927 if (!affectedGroups.Contains(newRoot.ParentGroup))
1810 } 1928 affectedGroups.Add(newRoot.ParentGroup);
1811 } 1929 }
1812 } 1930 }
1813 1931
@@ -1815,8 +1933,14 @@ namespace OpenSim.Region.Framework.Scenes
1815 // 1933 //
1816 foreach (SceneObjectGroup g in affectedGroups) 1934 foreach (SceneObjectGroup g in affectedGroups)
1817 { 1935 {
1936 // Child prims that have been unlinked and deleted will
1937 // return unless the root is deleted. This will remove them
1938 // from the database. They will be rewritten immediately,
1939 // minus the rows for the unlinked child prims.
1940 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1818 g.TriggerScriptChangedEvent(Changed.LINK); 1941 g.TriggerScriptChangedEvent(Changed.LINK);
1819 g.HasGroupChanged = true; // Persist 1942 g.HasGroupChanged = true; // Persist
1943 g.areUpdatesSuspended = false;
1820 g.ScheduleGroupForFullUpdate(); 1944 g.ScheduleGroupForFullUpdate();
1821 } 1945 }
1822 } 1946 }
@@ -1918,9 +2042,6 @@ namespace OpenSim.Region.Framework.Scenes
1918 child.ApplyNextOwnerPermissions(); 2042 child.ApplyNextOwnerPermissions();
1919 } 2043 }
1920 } 2044 }
1921
1922 copy.RootPart.ObjectSaleType = 0;
1923 copy.RootPart.SalePrice = 10;
1924 } 2045 }
1925 2046
1926 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2047 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index a73d9b6..f3660a5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -227,6 +223,11 @@ namespace OpenSim.Region.Framework.Scenes
227 223
228 public uint GetEffectivePermissions() 224 public uint GetEffectivePermissions()
229 { 225 {
226 return GetEffectivePermissions(false);
227 }
228
229 public uint GetEffectivePermissions(bool useBase)
230 {
230 uint perms=(uint)(PermissionMask.Modify | 231 uint perms=(uint)(PermissionMask.Modify |
231 PermissionMask.Copy | 232 PermissionMask.Copy |
232 PermissionMask.Move | 233 PermissionMask.Move |
@@ -238,7 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
238 for (int i = 0; i < parts.Length; i++) 239 for (int i = 0; i < parts.Length; i++)
239 { 240 {
240 SceneObjectPart part = parts[i]; 241 SceneObjectPart part = parts[i];
241 ownerMask &= part.OwnerMask; 242 if (useBase)
243 ownerMask &= part.BaseMask;
244 else
245 ownerMask &= part.OwnerMask;
242 perms &= part.Inventory.MaskEffectivePermissions(); 246 perms &= part.Inventory.MaskEffectivePermissions();
243 } 247 }
244 248
@@ -380,6 +384,9 @@ namespace OpenSim.Region.Framework.Scenes
380 384
381 public void ResumeScripts() 385 public void ResumeScripts()
382 { 386 {
387 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
388 return;
389
383 SceneObjectPart[] parts = m_parts.GetArray(); 390 SceneObjectPart[] parts = m_parts.GetArray();
384 for (int i = 0; i < parts.Length; i++) 391 for (int i = 0; i < parts.Length; i++)
385 parts[i].Inventory.ResumeScripts(); 392 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 878476e..cf8637f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -42,6 +43,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
42 43
43namespace OpenSim.Region.Framework.Scenes 44namespace OpenSim.Region.Framework.Scenes
44{ 45{
46
45 [Flags] 47 [Flags]
46 public enum scriptEvents 48 public enum scriptEvents
47 { 49 {
@@ -105,8 +107,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 107 /// since the group's last persistent backup
106 /// </summary> 108 /// </summary>
107 private bool m_hasGroupChanged = false; 109 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 110 private long timeFirstChanged = 0;
109 private long timeLastChanged; 111 private long timeLastChanged = 0;
112 private long m_maxPersistTime = 0;
113 private long m_minPersistTime = 0;
114 private Random m_rand;
115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117
118 public bool areUpdatesSuspended
119 {
120 get
121 {
122 return m_suspendUpdates;
123 }
124 set
125 {
126 m_suspendUpdates = value;
127 if (!value)
128 {
129 QueueForUpdateCheck();
130 }
131 }
132 }
110 133
111 public bool HasGroupChanged 134 public bool HasGroupChanged
112 { 135 {
@@ -114,9 +137,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 137 {
115 if (value) 138 if (value)
116 { 139 {
140 if (m_isBackedUp)
141 {
142 m_scene.SceneGraph.FireChangeBackup(this);
143 }
117 timeLastChanged = DateTime.Now.Ticks; 144 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 145 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 146 timeFirstChanged = DateTime.Now.Ticks;
147 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
148 {
149 if (m_rand == null)
150 {
151 byte[] val = new byte[16];
152 m_rootPart.UUID.ToBytes(val, 0);
153 m_rand = new Random(BitConverter.ToInt32(val, 0));
154 }
155
156 if (m_scene.GetRootAgentCount() == 0)
157 {
158 //If the region is empty, this change has been made by an automated process
159 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
160
161 float factor = 1.5f + (float)(m_rand.NextDouble());
162 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
163 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
164 }
165 else
166 {
167 //If the region is not empty, we want to obey the minimum and maximum persist times
168 //but add a random factor so we stagger the object persistance a little
169 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
170 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
171 }
172 }
120 } 173 }
121 m_hasGroupChanged = value; 174 m_hasGroupChanged = value;
122 175
@@ -131,7 +184,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 184 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 185 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 186 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 187 public bool HasGroupChangedDueToDelink { get; set; }
135 188
136 private bool isTimeToPersist() 189 private bool isTimeToPersist()
137 { 190 {
@@ -141,8 +194,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 194 return false;
142 if (m_scene.ShuttingDown) 195 if (m_scene.ShuttingDown)
143 return true; 196 return true;
197
198 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
199 {
200 m_maxPersistTime = m_scene.m_persistAfter;
201 m_minPersistTime = m_scene.m_dontPersistBefore;
202 }
203
144 long currentTime = DateTime.Now.Ticks; 204 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 205
206 if (timeLastChanged == 0) timeLastChanged = currentTime;
207 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
208
209 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 210 return true;
147 return false; 211 return false;
148 } 212 }
@@ -247,10 +311,10 @@ namespace OpenSim.Region.Framework.Scenes
247 311
248 private bool m_scriptListens_atTarget; 312 private bool m_scriptListens_atTarget;
249 private bool m_scriptListens_notAtTarget; 313 private bool m_scriptListens_notAtTarget;
250
251 private bool m_scriptListens_atRotTarget; 314 private bool m_scriptListens_atRotTarget;
252 private bool m_scriptListens_notAtRotTarget; 315 private bool m_scriptListens_notAtRotTarget;
253 316
317 public bool m_dupeInProgress = false;
254 internal Dictionary<UUID, string> m_savedScriptState; 318 internal Dictionary<UUID, string> m_savedScriptState;
255 319
256 #region Properties 320 #region Properties
@@ -287,6 +351,16 @@ namespace OpenSim.Region.Framework.Scenes
287 get { return m_parts.Count; } 351 get { return m_parts.Count; }
288 } 352 }
289 353
354// protected Quaternion m_rotation = Quaternion.Identity;
355//
356// public virtual Quaternion Rotation
357// {
358// get { return m_rotation; }
359// set {
360// m_rotation = value;
361// }
362// }
363
290 public Quaternion GroupRotation 364 public Quaternion GroupRotation
291 { 365 {
292 get { return m_rootPart.RotationOffset; } 366 get { return m_rootPart.RotationOffset; }
@@ -388,14 +462,98 @@ namespace OpenSim.Region.Framework.Scenes
388 462
389 if (Scene != null) 463 if (Scene != null)
390 { 464 {
391 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 465 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
392 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 466 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
467 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
468 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
469 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
393 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 470 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
394 { 471 {
395 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 472 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
473 uint x = 0;
474 uint y = 0;
475 string version = String.Empty;
476 Vector3 newpos = Vector3.Zero;
477 OpenSim.Services.Interfaces.GridRegion destination = null;
478
479 bool canCross = true;
480 foreach (ScenePresence av in m_linkedAvatars)
481 {
482 // We need to cross these agents. First, let's find
483 // out if any of them can't cross for some reason.
484 // We have to deny the crossing entirely if any
485 // of them are banned. Alternatively, we could
486 // unsit banned agents....
487
488
489 // We set the avatar position as being the object
490 // position to get the region to send to
491 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
492 {
493 canCross = false;
494 break;
495 }
496
497 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
498 }
499
500 if (canCross)
501 {
502 // We unparent the SP quietly so that it won't
503 // be made to stand up
504 foreach (ScenePresence av in m_linkedAvatars)
505 {
506 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
507 if (parentPart != null)
508 av.ParentUUID = parentPart.UUID;
509
510 av.ParentID = 0;
511 }
512
513 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
514
515 // Normalize
516 if (val.X >= Constants.RegionSize)
517 val.X -= Constants.RegionSize;
518 if (val.Y >= Constants.RegionSize)
519 val.Y -= Constants.RegionSize;
520 if (val.X < 0)
521 val.X += Constants.RegionSize;
522 if (val.Y < 0)
523 val.Y += Constants.RegionSize;
524
525 // If it's deleted, crossing was successful
526 if (IsDeleted)
527 {
528 foreach (ScenePresence av in m_linkedAvatars)
529 {
530 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
531
532 av.IsInTransit = true;
533
534 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
535 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
536 }
537
538 return;
539 }
540 }
541 else if (RootPart.PhysActor != null)
542 {
543 RootPart.PhysActor.CrossingFailure();
544 }
545
546 Vector3 oldp = AbsolutePosition;
547 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
548 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
549 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
396 } 550 }
397 } 551 }
398 552
553 foreach (SceneObjectPart part in m_parts.GetArray())
554 {
555 part.IgnoreUndoUpdate = true;
556 }
399 if (RootPart.GetStatusSandbox()) 557 if (RootPart.GetStatusSandbox())
400 { 558 {
401 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 559 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -409,10 +567,30 @@ namespace OpenSim.Region.Framework.Scenes
409 return; 567 return;
410 } 568 }
411 } 569 }
412
413 SceneObjectPart[] parts = m_parts.GetArray(); 570 SceneObjectPart[] parts = m_parts.GetArray();
414 for (int i = 0; i < parts.Length; i++) 571 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
415 parts[i].GroupPosition = val; 572 if (m_dupeInProgress)
573 triggerScriptEvent = false;
574 foreach (SceneObjectPart part in parts)
575 {
576 part.GroupPosition = val;
577 if (triggerScriptEvent)
578 part.TriggerScriptChangedEvent(Changed.POSITION);
579 }
580 if (!m_dupeInProgress)
581 {
582 foreach (ScenePresence av in m_linkedAvatars)
583 {
584 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
585 if (m_parts.TryGetValue(p.UUID, out p))
586 {
587 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
588 av.AbsolutePosition += offset;
589 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
590 av.SendAvatarDataToAllAgents();
591 }
592 }
593 }
416 594
417 //if (m_rootPart.PhysActor != null) 595 //if (m_rootPart.PhysActor != null)
418 //{ 596 //{
@@ -427,6 +605,29 @@ namespace OpenSim.Region.Framework.Scenes
427 } 605 }
428 } 606 }
429 607
608 public override Vector3 Velocity
609 {
610 get { return RootPart.Velocity; }
611 set { RootPart.Velocity = value; }
612 }
613
614 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
615 {
616 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
617 ScenePresence agent = icon.EndInvoke(iar);
618
619 //// If the cross was successful, this agent is a child agent
620 //if (agent.IsChildAgent)
621 // agent.Reset();
622 //else // Not successful
623 // agent.RestoreInCurrentScene();
624
625 // In any case
626 agent.IsInTransit = false;
627
628 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
629 }
630
430 public override uint LocalId 631 public override uint LocalId
431 { 632 {
432 get { return m_rootPart.LocalId; } 633 get { return m_rootPart.LocalId; }
@@ -578,6 +779,7 @@ namespace OpenSim.Region.Framework.Scenes
578 /// </summary> 779 /// </summary>
579 public SceneObjectGroup() 780 public SceneObjectGroup()
580 { 781 {
782
581 } 783 }
582 784
583 /// <summary> 785 /// <summary>
@@ -594,7 +796,7 @@ namespace OpenSim.Region.Framework.Scenes
594 /// Constructor. This object is added to the scene later via AttachToScene() 796 /// Constructor. This object is added to the scene later via AttachToScene()
595 /// </summary> 797 /// </summary>
596 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 798 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
597 { 799 {
598 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 800 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
599 } 801 }
600 802
@@ -642,6 +844,9 @@ namespace OpenSim.Region.Framework.Scenes
642 /// </summary> 844 /// </summary>
643 public virtual void AttachToBackup() 845 public virtual void AttachToBackup()
644 { 846 {
847 if (IsAttachment) return;
848 m_scene.SceneGraph.FireAttachToBackup(this);
849
645 if (InSceneBackup) 850 if (InSceneBackup)
646 { 851 {
647 //m_log.DebugFormat( 852 //m_log.DebugFormat(
@@ -684,6 +889,9 @@ namespace OpenSim.Region.Framework.Scenes
684 889
685 ApplyPhysics(); 890 ApplyPhysics();
686 891
892 if (RootPart.PhysActor != null)
893 RootPart.Buoyancy = RootPart.Buoyancy;
894
687 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 895 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
688 // for the same object with very different properties. The caller must schedule the update. 896 // for the same object with very different properties. The caller must schedule the update.
689 //ScheduleGroupForFullUpdate(); 897 //ScheduleGroupForFullUpdate();
@@ -699,6 +907,10 @@ namespace OpenSim.Region.Framework.Scenes
699 EntityIntersection result = new EntityIntersection(); 907 EntityIntersection result = new EntityIntersection();
700 908
701 SceneObjectPart[] parts = m_parts.GetArray(); 909 SceneObjectPart[] parts = m_parts.GetArray();
910
911 // Find closest hit here
912 float idist = float.MaxValue;
913
702 for (int i = 0; i < parts.Length; i++) 914 for (int i = 0; i < parts.Length; i++)
703 { 915 {
704 SceneObjectPart part = parts[i]; 916 SceneObjectPart part = parts[i];
@@ -713,11 +925,6 @@ namespace OpenSim.Region.Framework.Scenes
713 925
714 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 926 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
715 927
716 // This may need to be updated to the maximum draw distance possible..
717 // We might (and probably will) be checking for prim creation from other sims
718 // when the camera crosses the border.
719 float idist = Constants.RegionSize;
720
721 if (inter.HitTF) 928 if (inter.HitTF)
722 { 929 {
723 // We need to find the closest prim to return to the testcaller along the ray 930 // We need to find the closest prim to return to the testcaller along the ray
@@ -728,10 +935,11 @@ namespace OpenSim.Region.Framework.Scenes
728 result.obj = part; 935 result.obj = part;
729 result.normal = inter.normal; 936 result.normal = inter.normal;
730 result.distance = inter.distance; 937 result.distance = inter.distance;
938
939 idist = inter.distance;
731 } 940 }
732 } 941 }
733 } 942 }
734
735 return result; 943 return result;
736 } 944 }
737 945
@@ -751,17 +959,19 @@ namespace OpenSim.Region.Framework.Scenes
751 minZ = 8192f; 959 minZ = 8192f;
752 960
753 SceneObjectPart[] parts = m_parts.GetArray(); 961 SceneObjectPart[] parts = m_parts.GetArray();
754 for (int i = 0; i < parts.Length; i++) 962 foreach (SceneObjectPart part in parts)
755 { 963 {
756 SceneObjectPart part = parts[i];
757
758 Vector3 worldPos = part.GetWorldPosition(); 964 Vector3 worldPos = part.GetWorldPosition();
759 Vector3 offset = worldPos - AbsolutePosition; 965 Vector3 offset = worldPos - AbsolutePosition;
760 Quaternion worldRot; 966 Quaternion worldRot;
761 if (part.ParentID == 0) 967 if (part.ParentID == 0)
968 {
762 worldRot = part.RotationOffset; 969 worldRot = part.RotationOffset;
970 }
763 else 971 else
972 {
764 worldRot = part.GetWorldRotation(); 973 worldRot = part.GetWorldRotation();
974 }
765 975
766 Vector3 frontTopLeft; 976 Vector3 frontTopLeft;
767 Vector3 frontTopRight; 977 Vector3 frontTopRight;
@@ -773,6 +983,8 @@ namespace OpenSim.Region.Framework.Scenes
773 Vector3 backBottomLeft; 983 Vector3 backBottomLeft;
774 Vector3 backBottomRight; 984 Vector3 backBottomRight;
775 985
986 // Vector3[] corners = new Vector3[8];
987
776 Vector3 orig = Vector3.Zero; 988 Vector3 orig = Vector3.Zero;
777 989
778 frontTopLeft.X = orig.X - (part.Scale.X / 2); 990 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -807,6 +1019,38 @@ namespace OpenSim.Region.Framework.Scenes
807 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1019 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
808 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1020 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
809 1021
1022
1023
1024 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1025 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1026 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1027 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1028 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1029 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1030 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1031 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1032
1033 //for (int i = 0; i < 8; i++)
1034 //{
1035 // corners[i] = corners[i] * worldRot;
1036 // corners[i] += offset;
1037
1038 // if (corners[i].X > maxX)
1039 // maxX = corners[i].X;
1040 // if (corners[i].X < minX)
1041 // minX = corners[i].X;
1042
1043 // if (corners[i].Y > maxY)
1044 // maxY = corners[i].Y;
1045 // if (corners[i].Y < minY)
1046 // minY = corners[i].Y;
1047
1048 // if (corners[i].Z > maxZ)
1049 // maxZ = corners[i].Y;
1050 // if (corners[i].Z < minZ)
1051 // minZ = corners[i].Z;
1052 //}
1053
810 frontTopLeft = frontTopLeft * worldRot; 1054 frontTopLeft = frontTopLeft * worldRot;
811 frontTopRight = frontTopRight * worldRot; 1055 frontTopRight = frontTopRight * worldRot;
812 frontBottomLeft = frontBottomLeft * worldRot; 1056 frontBottomLeft = frontBottomLeft * worldRot;
@@ -828,6 +1072,15 @@ namespace OpenSim.Region.Framework.Scenes
828 backTopLeft += offset; 1072 backTopLeft += offset;
829 backTopRight += offset; 1073 backTopRight += offset;
830 1074
1075 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1076 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1077 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1078 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1079 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1080 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1081 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1082 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1083
831 if (frontTopRight.X > maxX) 1084 if (frontTopRight.X > maxX)
832 maxX = frontTopRight.X; 1085 maxX = frontTopRight.X;
833 if (frontTopLeft.X > maxX) 1086 if (frontTopLeft.X > maxX)
@@ -973,15 +1226,20 @@ namespace OpenSim.Region.Framework.Scenes
973 1226
974 public void SaveScriptedState(XmlTextWriter writer) 1227 public void SaveScriptedState(XmlTextWriter writer)
975 { 1228 {
1229 SaveScriptedState(writer, false);
1230 }
1231
1232 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1233 {
976 XmlDocument doc = new XmlDocument(); 1234 XmlDocument doc = new XmlDocument();
977 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1235 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
978 1236
979 SceneObjectPart[] parts = m_parts.GetArray(); 1237 SceneObjectPart[] parts = m_parts.GetArray();
980 for (int i = 0; i < parts.Length; i++) 1238 for (int i = 0; i < parts.Length; i++)
981 { 1239 {
982 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1240 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
983 foreach (KeyValuePair<UUID, string> kvp in pstates) 1241 foreach (KeyValuePair<UUID, string> kvp in pstates)
984 states.Add(kvp.Key, kvp.Value); 1242 states[kvp.Key] = kvp.Value;
985 } 1243 }
986 1244
987 if (states.Count > 0) 1245 if (states.Count > 0)
@@ -1001,6 +1259,169 @@ namespace OpenSim.Region.Framework.Scenes
1001 } 1259 }
1002 1260
1003 /// <summary> 1261 /// <summary>
1262 /// Add the avatar to this linkset (avatar is sat).
1263 /// </summary>
1264 /// <param name="agentID"></param>
1265 public void AddAvatar(UUID agentID)
1266 {
1267 ScenePresence presence;
1268 if (m_scene.TryGetScenePresence(agentID, out presence))
1269 {
1270 if (!m_linkedAvatars.Contains(presence))
1271 {
1272 m_linkedAvatars.Add(presence);
1273 }
1274 }
1275 }
1276
1277 /// <summary>
1278 /// Delete the avatar from this linkset (avatar is unsat).
1279 /// </summary>
1280 /// <param name="agentID"></param>
1281 public void DeleteAvatar(UUID agentID)
1282 {
1283 ScenePresence presence;
1284 if (m_scene.TryGetScenePresence(agentID, out presence))
1285 {
1286 if (m_linkedAvatars.Contains(presence))
1287 {
1288 m_linkedAvatars.Remove(presence);
1289 }
1290 }
1291 }
1292
1293 /// <summary>
1294 /// Returns the list of linked presences (avatars sat on this group)
1295 /// </summary>
1296 /// <param name="agentID"></param>
1297 public List<ScenePresence> GetLinkedAvatars()
1298 {
1299 return m_linkedAvatars;
1300 }
1301
1302 /// <summary>
1303 /// Attach this scene object to the given avatar.
1304 /// </summary>
1305 /// <param name="agentID"></param>
1306 /// <param name="attachmentpoint"></param>
1307 /// <param name="AttachOffset"></param>
1308 private void AttachToAgent(
1309 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1310 {
1311 if (avatar != null)
1312 {
1313 // don't attach attachments to child agents
1314 if (avatar.IsChildAgent) return;
1315
1316 // Remove from database and parcel prim count
1317 m_scene.DeleteFromStorage(so.UUID);
1318 m_scene.EventManager.TriggerParcelPrimCountTainted();
1319
1320 so.AttachedAvatar = avatar.UUID;
1321
1322 if (so.RootPart.PhysActor != null)
1323 {
1324 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1325 so.RootPart.PhysActor = null;
1326 }
1327
1328 so.AbsolutePosition = attachOffset;
1329 so.RootPart.AttachedPos = attachOffset;
1330 so.IsAttachment = true;
1331 so.RootPart.SetParentLocalId(avatar.LocalId);
1332 so.AttachmentPoint = attachmentpoint;
1333
1334 avatar.AddAttachment(this);
1335
1336 if (!silent)
1337 {
1338 // Killing it here will cause the client to deselect it
1339 // It then reappears on the avatar, deselected
1340 // through the full update below
1341 //
1342 if (IsSelected)
1343 {
1344 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1345 }
1346
1347 IsSelected = false; // fudge....
1348 ScheduleGroupForFullUpdate();
1349 }
1350 }
1351 else
1352 {
1353 m_log.WarnFormat(
1354 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1355 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1356 }
1357 }
1358
1359 public byte GetAttachmentPoint()
1360 {
1361 return m_rootPart.Shape.State;
1362 }
1363
1364 public void DetachToGround()
1365 {
1366 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1367 if (avatar == null)
1368 return;
1369
1370 avatar.RemoveAttachment(this);
1371
1372 Vector3 detachedpos = new Vector3(127f,127f,127f);
1373 if (avatar == null)
1374 return;
1375
1376 detachedpos = avatar.AbsolutePosition;
1377 RootPart.FromItemID = UUID.Zero;
1378
1379 AbsolutePosition = detachedpos;
1380 AttachedAvatar = UUID.Zero;
1381
1382 //SceneObjectPart[] parts = m_parts.GetArray();
1383 //for (int i = 0; i < parts.Length; i++)
1384 // parts[i].AttachedAvatar = UUID.Zero;
1385
1386 m_rootPart.SetParentLocalId(0);
1387 AttachmentPoint = (byte)0;
1388 // must check if buildind should be true or false here
1389 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1390 HasGroupChanged = true;
1391 RootPart.Rezzed = DateTime.Now;
1392 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1393 AttachToBackup();
1394 m_scene.EventManager.TriggerParcelPrimCountTainted();
1395 m_rootPart.ScheduleFullUpdate();
1396 m_rootPart.ClearUndoState();
1397 }
1398
1399 public void DetachToInventoryPrep()
1400 {
1401 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1402 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1403 if (avatar != null)
1404 {
1405 //detachedpos = avatar.AbsolutePosition;
1406 avatar.RemoveAttachment(this);
1407 }
1408
1409 AttachedAvatar = UUID.Zero;
1410
1411 /*SceneObjectPart[] parts = m_parts.GetArray();
1412 for (int i = 0; i < parts.Length; i++)
1413 parts[i].AttachedAvatar = UUID.Zero;*/
1414
1415 m_rootPart.SetParentLocalId(0);
1416 //m_rootPart.SetAttachmentPoint((byte)0);
1417 IsAttachment = false;
1418 AbsolutePosition = m_rootPart.AttachedPos;
1419 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1420 //AttachToBackup();
1421 //m_rootPart.ScheduleFullUpdate();
1422 }
1423
1424 /// <summary>
1004 /// 1425 ///
1005 /// </summary> 1426 /// </summary>
1006 /// <param name="part"></param> 1427 /// <param name="part"></param>
@@ -1050,7 +1471,10 @@ namespace OpenSim.Region.Framework.Scenes
1050 public void AddPart(SceneObjectPart part) 1471 public void AddPart(SceneObjectPart part)
1051 { 1472 {
1052 part.SetParent(this); 1473 part.SetParent(this);
1053 part.LinkNum = m_parts.Add(part.UUID, part); 1474 m_parts.Add(part.UUID, part);
1475
1476 part.LinkNum = m_parts.Count;
1477
1054 if (part.LinkNum == 2) 1478 if (part.LinkNum == 2)
1055 RootPart.LinkNum = 1; 1479 RootPart.LinkNum = 1;
1056 } 1480 }
@@ -1158,6 +1582,11 @@ namespace OpenSim.Region.Framework.Scenes
1158 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1582 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1159 public void DeleteGroupFromScene(bool silent) 1583 public void DeleteGroupFromScene(bool silent)
1160 { 1584 {
1585 // We need to keep track of this state in case this group is still queued for backup.
1586 IsDeleted = true;
1587
1588 DetachFromBackup();
1589
1161 SceneObjectPart[] parts = m_parts.GetArray(); 1590 SceneObjectPart[] parts = m_parts.GetArray();
1162 for (int i = 0; i < parts.Length; i++) 1591 for (int i = 0; i < parts.Length; i++)
1163 { 1592 {
@@ -1180,6 +1609,8 @@ namespace OpenSim.Region.Framework.Scenes
1180 } 1609 }
1181 }); 1610 });
1182 } 1611 }
1612
1613
1183 } 1614 }
1184 1615
1185 public void AddScriptLPS(int count) 1616 public void AddScriptLPS(int count)
@@ -1254,28 +1685,43 @@ namespace OpenSim.Region.Framework.Scenes
1254 /// </summary> 1685 /// </summary>
1255 public void ApplyPhysics() 1686 public void ApplyPhysics()
1256 { 1687 {
1257 // Apply physics to the root prim
1258 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1259
1260 // Apply physics to child prims
1261 SceneObjectPart[] parts = m_parts.GetArray(); 1688 SceneObjectPart[] parts = m_parts.GetArray();
1262 if (parts.Length > 1) 1689 if (parts.Length > 1)
1263 { 1690 {
1691 ResetChildPrimPhysicsPositions();
1692
1693 // Apply physics to the root prim
1694 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1695
1696
1264 for (int i = 0; i < parts.Length; i++) 1697 for (int i = 0; i < parts.Length; i++)
1265 { 1698 {
1266 SceneObjectPart part = parts[i]; 1699 SceneObjectPart part = parts[i];
1267 if (part.LocalId != m_rootPart.LocalId) 1700 if (part.LocalId != m_rootPart.LocalId)
1268 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1701 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1269 } 1702 }
1270
1271 // Hack to get the physics scene geometries in the right spot 1703 // Hack to get the physics scene geometries in the right spot
1272 ResetChildPrimPhysicsPositions(); 1704// ResetChildPrimPhysicsPositions();
1705 if (m_rootPart.PhysActor != null)
1706 {
1707 m_rootPart.PhysActor.Building = false;
1708 }
1709 }
1710 else
1711 {
1712 // Apply physics to the root prim
1713 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1273 } 1714 }
1274 } 1715 }
1275 1716
1276 public void SetOwnerId(UUID userId) 1717 public void SetOwnerId(UUID userId)
1277 { 1718 {
1278 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1719 ForEachPart(delegate(SceneObjectPart part)
1720 {
1721
1722 part.OwnerID = userId;
1723
1724 });
1279 } 1725 }
1280 1726
1281 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1727 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1307,11 +1753,17 @@ namespace OpenSim.Region.Framework.Scenes
1307 return; 1753 return;
1308 } 1754 }
1309 1755
1756 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1757 return;
1758
1310 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1759 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1311 // any exception propogate upwards. 1760 // any exception propogate upwards.
1312 try 1761 try
1313 { 1762 {
1314 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1763 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1764 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1765 m_scene.LoadingPrims) // Land may not be valid yet
1766
1315 { 1767 {
1316 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1768 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1317 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1769 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1338,6 +1790,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 } 1790 }
1339 } 1791 }
1340 } 1792 }
1793
1341 } 1794 }
1342 1795
1343 if (m_scene.UseBackup && HasGroupChanged) 1796 if (m_scene.UseBackup && HasGroupChanged)
@@ -1345,6 +1798,20 @@ namespace OpenSim.Region.Framework.Scenes
1345 // don't backup while it's selected or you're asking for changes mid stream. 1798 // don't backup while it's selected or you're asking for changes mid stream.
1346 if (isTimeToPersist() || forcedBackup) 1799 if (isTimeToPersist() || forcedBackup)
1347 { 1800 {
1801 if (m_rootPart.PhysActor != null &&
1802 (!m_rootPart.PhysActor.IsPhysical))
1803 {
1804 // Possible ghost prim
1805 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1806 {
1807 foreach (SceneObjectPart part in m_parts.GetArray())
1808 {
1809 // Re-set physics actor positions and
1810 // orientations
1811 part.GroupPosition = m_rootPart.GroupPosition;
1812 }
1813 }
1814 }
1348// m_log.DebugFormat( 1815// m_log.DebugFormat(
1349// "[SCENE]: Storing {0}, {1} in {2}", 1816// "[SCENE]: Storing {0}, {1} in {2}",
1350// Name, UUID, m_scene.RegionInfo.RegionName); 1817// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1414,6 +1881,7 @@ namespace OpenSim.Region.Framework.Scenes
1414 /// <returns></returns> 1881 /// <returns></returns>
1415 public SceneObjectGroup Copy(bool userExposed) 1882 public SceneObjectGroup Copy(bool userExposed)
1416 { 1883 {
1884 m_dupeInProgress = true;
1417 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1885 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1418 dupe.m_isBackedUp = false; 1886 dupe.m_isBackedUp = false;
1419 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1887 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1428,7 +1896,7 @@ namespace OpenSim.Region.Framework.Scenes
1428 // This is only necessary when userExposed is false! 1896 // This is only necessary when userExposed is false!
1429 1897
1430 bool previousAttachmentStatus = dupe.IsAttachment; 1898 bool previousAttachmentStatus = dupe.IsAttachment;
1431 1899
1432 if (!userExposed) 1900 if (!userExposed)
1433 dupe.IsAttachment = true; 1901 dupe.IsAttachment = true;
1434 1902
@@ -1446,11 +1914,11 @@ namespace OpenSim.Region.Framework.Scenes
1446 dupe.m_rootPart.TrimPermissions(); 1914 dupe.m_rootPart.TrimPermissions();
1447 1915
1448 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1916 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1449 1917
1450 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1918 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1451 { 1919 {
1452 return p1.LinkNum.CompareTo(p2.LinkNum); 1920 return p1.LinkNum.CompareTo(p2.LinkNum);
1453 } 1921 }
1454 ); 1922 );
1455 1923
1456 foreach (SceneObjectPart part in partList) 1924 foreach (SceneObjectPart part in partList)
@@ -1470,21 +1938,24 @@ namespace OpenSim.Region.Framework.Scenes
1470 if (part.PhysActor != null && userExposed) 1938 if (part.PhysActor != null && userExposed)
1471 { 1939 {
1472 PrimitiveBaseShape pbs = newPart.Shape; 1940 PrimitiveBaseShape pbs = newPart.Shape;
1473 1941
1474 newPart.PhysActor 1942 newPart.PhysActor
1475 = m_scene.PhysicsScene.AddPrimShape( 1943 = m_scene.PhysicsScene.AddPrimShape(
1476 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1944 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1477 pbs, 1945 pbs,
1478 newPart.AbsolutePosition, 1946 newPart.AbsolutePosition,
1479 newPart.Scale, 1947 newPart.Scale,
1480 newPart.RotationOffset, 1948 //newPart.RotationOffset,
1949 newPart.GetWorldRotation(),
1481 part.PhysActor.IsPhysical, 1950 part.PhysActor.IsPhysical,
1482 newPart.LocalId); 1951 newPart.LocalId);
1483 1952
1484 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1953 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1485 } 1954 }
1486 } 1955 }
1487 1956 if (dupe.m_rootPart.PhysActor != null && userExposed)
1957 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
1958
1488 if (userExposed) 1959 if (userExposed)
1489 { 1960 {
1490 dupe.UpdateParentIDs(); 1961 dupe.UpdateParentIDs();
@@ -1494,6 +1965,7 @@ namespace OpenSim.Region.Framework.Scenes
1494 ScheduleGroupForFullUpdate(); 1965 ScheduleGroupForFullUpdate();
1495 } 1966 }
1496 1967
1968 m_dupeInProgress = false;
1497 return dupe; 1969 return dupe;
1498 } 1970 }
1499 1971
@@ -1599,6 +2071,7 @@ namespace OpenSim.Region.Framework.Scenes
1599 return Vector3.Zero; 2071 return Vector3.Zero;
1600 } 2072 }
1601 2073
2074 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1602 public void moveToTarget(Vector3 target, float tau) 2075 public void moveToTarget(Vector3 target, float tau)
1603 { 2076 {
1604 if (IsAttachment) 2077 if (IsAttachment)
@@ -1626,6 +2099,46 @@ namespace OpenSim.Region.Framework.Scenes
1626 RootPart.PhysActor.PIDActive = false; 2099 RootPart.PhysActor.PIDActive = false;
1627 } 2100 }
1628 2101
2102 public void rotLookAt(Quaternion target, float strength, float damping)
2103 {
2104 SceneObjectPart rootpart = m_rootPart;
2105 if (rootpart != null)
2106 {
2107 if (IsAttachment)
2108 {
2109 /*
2110 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2111 if (avatar != null)
2112 {
2113 Rotate the Av?
2114 } */
2115 }
2116 else
2117 {
2118 if (rootpart.PhysActor != null)
2119 { // APID must be implemented in your physics system for this to function.
2120 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2121 rootpart.PhysActor.APIDStrength = strength;
2122 rootpart.PhysActor.APIDDamping = damping;
2123 rootpart.PhysActor.APIDActive = true;
2124 }
2125 }
2126 }
2127 }
2128
2129 public void stopLookAt()
2130 {
2131 SceneObjectPart rootpart = m_rootPart;
2132 if (rootpart != null)
2133 {
2134 if (rootpart.PhysActor != null)
2135 { // APID must be implemented in your physics system for this to function.
2136 rootpart.PhysActor.APIDActive = false;
2137 }
2138 }
2139
2140 }
2141
1629 /// <summary> 2142 /// <summary>
1630 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2143 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1631 /// </summary> 2144 /// </summary>
@@ -1681,6 +2194,8 @@ namespace OpenSim.Region.Framework.Scenes
1681 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2194 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1682 { 2195 {
1683 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2196 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2197 newPart.SetParent(this);
2198
1684 AddPart(newPart); 2199 AddPart(newPart);
1685 2200
1686 SetPartAsNonRoot(newPart); 2201 SetPartAsNonRoot(newPart);
@@ -1809,11 +2324,11 @@ namespace OpenSim.Region.Framework.Scenes
1809 /// Immediately send a full update for this scene object. 2324 /// Immediately send a full update for this scene object.
1810 /// </summary> 2325 /// </summary>
1811 public void SendGroupFullUpdate() 2326 public void SendGroupFullUpdate()
1812 { 2327 {
1813 if (IsDeleted) 2328 if (IsDeleted)
1814 return; 2329 return;
1815 2330
1816// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2331// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1817 2332
1818 RootPart.SendFullUpdateToAllClients(); 2333 RootPart.SendFullUpdateToAllClients();
1819 2334
@@ -1957,6 +2472,11 @@ namespace OpenSim.Region.Framework.Scenes
1957 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2472 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1958 public void LinkToGroup(SceneObjectGroup objectGroup) 2473 public void LinkToGroup(SceneObjectGroup objectGroup)
1959 { 2474 {
2475 LinkToGroup(objectGroup, false);
2476 }
2477
2478 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2479 {
1960// m_log.DebugFormat( 2480// m_log.DebugFormat(
1961// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2481// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1962// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2482// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1990,7 +2510,20 @@ namespace OpenSim.Region.Framework.Scenes
1990 2510
1991 lock (m_parts.SyncRoot) 2511 lock (m_parts.SyncRoot)
1992 { 2512 {
1993 int linkNum = PrimCount + 1; 2513 int linkNum;
2514 if (insert)
2515 {
2516 linkNum = 2;
2517 foreach (SceneObjectPart part in Parts)
2518 {
2519 if (part.LinkNum > 1)
2520 part.LinkNum++;
2521 }
2522 }
2523 else
2524 {
2525 linkNum = PrimCount + 1;
2526 }
1994 2527
1995 m_parts.Add(linkPart.UUID, linkPart); 2528 m_parts.Add(linkPart.UUID, linkPart);
1996 2529
@@ -2018,7 +2551,7 @@ namespace OpenSim.Region.Framework.Scenes
2018 objectGroup.IsDeleted = true; 2551 objectGroup.IsDeleted = true;
2019 2552
2020 objectGroup.m_parts.Clear(); 2553 objectGroup.m_parts.Clear();
2021 2554
2022 // Can't do this yet since backup still makes use of the root part without any synchronization 2555 // Can't do this yet since backup still makes use of the root part without any synchronization
2023// objectGroup.m_rootPart = null; 2556// objectGroup.m_rootPart = null;
2024 2557
@@ -2152,6 +2685,7 @@ namespace OpenSim.Region.Framework.Scenes
2152 /// <param name="objectGroup"></param> 2685 /// <param name="objectGroup"></param>
2153 public virtual void DetachFromBackup() 2686 public virtual void DetachFromBackup()
2154 { 2687 {
2688 m_scene.SceneGraph.FireDetachFromBackup(this);
2155 if (m_isBackedUp && Scene != null) 2689 if (m_isBackedUp && Scene != null)
2156 m_scene.EventManager.OnBackup -= ProcessBackup; 2690 m_scene.EventManager.OnBackup -= ProcessBackup;
2157 2691
@@ -2170,7 +2704,8 @@ namespace OpenSim.Region.Framework.Scenes
2170 2704
2171 axPos *= parentRot; 2705 axPos *= parentRot;
2172 part.OffsetPosition = axPos; 2706 part.OffsetPosition = axPos;
2173 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2707 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2708 part.GroupPosition = newPos;
2174 part.OffsetPosition = Vector3.Zero; 2709 part.OffsetPosition = Vector3.Zero;
2175 part.RotationOffset = worldRot; 2710 part.RotationOffset = worldRot;
2176 2711
@@ -2181,7 +2716,7 @@ namespace OpenSim.Region.Framework.Scenes
2181 2716
2182 part.LinkNum = linkNum; 2717 part.LinkNum = linkNum;
2183 2718
2184 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2719 part.OffsetPosition = newPos - AbsolutePosition;
2185 2720
2186 Quaternion rootRotation = m_rootPart.RotationOffset; 2721 Quaternion rootRotation = m_rootPart.RotationOffset;
2187 2722
@@ -2191,7 +2726,7 @@ namespace OpenSim.Region.Framework.Scenes
2191 2726
2192 parentRot = m_rootPart.RotationOffset; 2727 parentRot = m_rootPart.RotationOffset;
2193 oldRot = part.RotationOffset; 2728 oldRot = part.RotationOffset;
2194 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2729 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2195 part.RotationOffset = newRot; 2730 part.RotationOffset = newRot;
2196 } 2731 }
2197 2732
@@ -2438,8 +2973,31 @@ namespace OpenSim.Region.Framework.Scenes
2438 } 2973 }
2439 } 2974 }
2440 2975
2976/*
2977 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2441 for (int i = 0; i < parts.Length; i++) 2978 for (int i = 0; i < parts.Length; i++)
2442 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2979 {
2980 if (parts[i] != RootPart)
2981 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2982 }
2983*/
2984 if (parts.Length > 1)
2985 {
2986 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
2987
2988 for (int i = 0; i < parts.Length; i++)
2989 {
2990
2991 if (parts[i].UUID != m_rootPart.UUID)
2992 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
2993 }
2994
2995 if (m_rootPart.PhysActor != null)
2996 m_rootPart.PhysActor.Building = false;
2997 }
2998 else
2999 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3000
2443 } 3001 }
2444 } 3002 }
2445 3003
@@ -2452,6 +3010,17 @@ namespace OpenSim.Region.Framework.Scenes
2452 } 3010 }
2453 } 3011 }
2454 3012
3013
3014
3015 /// <summary>
3016 /// Gets the number of parts
3017 /// </summary>
3018 /// <returns></returns>
3019 public int GetPartCount()
3020 {
3021 return Parts.Count();
3022 }
3023
2455 /// <summary> 3024 /// <summary>
2456 /// Update the texture entry for this part 3025 /// Update the texture entry for this part
2457 /// </summary> 3026 /// </summary>
@@ -2513,7 +3082,6 @@ namespace OpenSim.Region.Framework.Scenes
2513 { 3082 {
2514// m_log.DebugFormat( 3083// m_log.DebugFormat(
2515// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3084// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2516
2517 RootPart.StoreUndoState(true); 3085 RootPart.StoreUndoState(true);
2518 3086
2519 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3087 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2614,7 +3182,6 @@ namespace OpenSim.Region.Framework.Scenes
2614 prevScale.X *= x; 3182 prevScale.X *= x;
2615 prevScale.Y *= y; 3183 prevScale.Y *= y;
2616 prevScale.Z *= z; 3184 prevScale.Z *= z;
2617
2618// RootPart.IgnoreUndoUpdate = true; 3185// RootPart.IgnoreUndoUpdate = true;
2619 RootPart.Resize(prevScale); 3186 RootPart.Resize(prevScale);
2620// RootPart.IgnoreUndoUpdate = false; 3187// RootPart.IgnoreUndoUpdate = false;
@@ -2645,7 +3212,9 @@ namespace OpenSim.Region.Framework.Scenes
2645 } 3212 }
2646 3213
2647// obPart.IgnoreUndoUpdate = false; 3214// obPart.IgnoreUndoUpdate = false;
2648// obPart.StoreUndoState(); 3215 HasGroupChanged = true;
3216 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3217 ScheduleGroupForTerseUpdate();
2649 } 3218 }
2650 3219
2651// m_log.DebugFormat( 3220// m_log.DebugFormat(
@@ -2705,9 +3274,9 @@ namespace OpenSim.Region.Framework.Scenes
2705 { 3274 {
2706 SceneObjectPart part = GetChildPart(localID); 3275 SceneObjectPart part = GetChildPart(localID);
2707 3276
2708// SceneObjectPart[] parts = m_parts.GetArray(); 3277 SceneObjectPart[] parts = m_parts.GetArray();
2709// for (int i = 0; i < parts.Length; i++) 3278 for (int i = 0; i < parts.Length; i++)
2710// parts[i].StoreUndoState(); 3279 parts[i].StoreUndoState();
2711 3280
2712 if (part != null) 3281 if (part != null)
2713 { 3282 {
@@ -2763,10 +3332,27 @@ namespace OpenSim.Region.Framework.Scenes
2763 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3332 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2764 } 3333 }
2765 3334
2766 AbsolutePosition = newPos; 3335 //We have to set undoing here because otherwise an undo state will be saved
3336 if (!m_rootPart.Undoing)
3337 {
3338 m_rootPart.Undoing = true;
3339 AbsolutePosition = newPos;
3340 m_rootPart.Undoing = false;
3341 }
3342 else
3343 {
3344 AbsolutePosition = newPos;
3345 }
2767 3346
2768 HasGroupChanged = true; 3347 HasGroupChanged = true;
2769 ScheduleGroupForTerseUpdate(); 3348 if (m_rootPart.Undoing)
3349 {
3350 ScheduleGroupForFullUpdate();
3351 }
3352 else
3353 {
3354 ScheduleGroupForTerseUpdate();
3355 }
2770 } 3356 }
2771 3357
2772 #endregion 3358 #endregion
@@ -2843,10 +3429,7 @@ namespace OpenSim.Region.Framework.Scenes
2843 public void UpdateSingleRotation(Quaternion rot, uint localID) 3429 public void UpdateSingleRotation(Quaternion rot, uint localID)
2844 { 3430 {
2845 SceneObjectPart part = GetChildPart(localID); 3431 SceneObjectPart part = GetChildPart(localID);
2846
2847 SceneObjectPart[] parts = m_parts.GetArray(); 3432 SceneObjectPart[] parts = m_parts.GetArray();
2848 for (int i = 0; i < parts.Length; i++)
2849 parts[i].StoreUndoState();
2850 3433
2851 if (part != null) 3434 if (part != null)
2852 { 3435 {
@@ -2884,7 +3467,16 @@ namespace OpenSim.Region.Framework.Scenes
2884 if (part.UUID == m_rootPart.UUID) 3467 if (part.UUID == m_rootPart.UUID)
2885 { 3468 {
2886 UpdateRootRotation(rot); 3469 UpdateRootRotation(rot);
2887 AbsolutePosition = pos; 3470 if (!m_rootPart.Undoing)
3471 {
3472 m_rootPart.Undoing = true;
3473 AbsolutePosition = pos;
3474 m_rootPart.Undoing = false;
3475 }
3476 else
3477 {
3478 AbsolutePosition = pos;
3479 }
2888 } 3480 }
2889 else 3481 else
2890 { 3482 {
@@ -2908,9 +3500,10 @@ namespace OpenSim.Region.Framework.Scenes
2908 3500
2909 Quaternion axRot = rot; 3501 Quaternion axRot = rot;
2910 Quaternion oldParentRot = m_rootPart.RotationOffset; 3502 Quaternion oldParentRot = m_rootPart.RotationOffset;
2911
2912 m_rootPart.StoreUndoState(); 3503 m_rootPart.StoreUndoState();
2913 m_rootPart.UpdateRotation(rot); 3504
3505 //Don't use UpdateRotation because it schedules an update prematurely
3506 m_rootPart.RotationOffset = rot;
2914 if (m_rootPart.PhysActor != null) 3507 if (m_rootPart.PhysActor != null)
2915 { 3508 {
2916 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3509 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2924,15 +3517,17 @@ namespace OpenSim.Region.Framework.Scenes
2924 if (prim.UUID != m_rootPart.UUID) 3517 if (prim.UUID != m_rootPart.UUID)
2925 { 3518 {
2926 prim.IgnoreUndoUpdate = true; 3519 prim.IgnoreUndoUpdate = true;
3520
3521 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3522 NewRot = Quaternion.Inverse(axRot) * NewRot;
3523 prim.RotationOffset = NewRot;
3524
2927 Vector3 axPos = prim.OffsetPosition; 3525 Vector3 axPos = prim.OffsetPosition;
3526
2928 axPos *= oldParentRot; 3527 axPos *= oldParentRot;
2929 axPos *= Quaternion.Inverse(axRot); 3528 axPos *= Quaternion.Inverse(axRot);
2930 prim.OffsetPosition = axPos; 3529 prim.OffsetPosition = axPos;
2931 Quaternion primsRot = prim.RotationOffset; 3530
2932 Quaternion newRot = oldParentRot * primsRot;
2933 newRot = Quaternion.Inverse(axRot) * newRot;
2934 prim.RotationOffset = newRot;
2935 prim.ScheduleTerseUpdate();
2936 prim.IgnoreUndoUpdate = false; 3531 prim.IgnoreUndoUpdate = false;
2937 } 3532 }
2938 } 3533 }
@@ -2946,8 +3541,8 @@ namespace OpenSim.Region.Framework.Scenes
2946//// childpart.StoreUndoState(); 3541//// childpart.StoreUndoState();
2947// } 3542// }
2948// } 3543// }
2949 3544 HasGroupChanged = true;
2950 m_rootPart.ScheduleTerseUpdate(); 3545 ScheduleGroupForFullUpdate();
2951 3546
2952// m_log.DebugFormat( 3547// m_log.DebugFormat(
2953// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3548// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3175,7 +3770,6 @@ namespace OpenSim.Region.Framework.Scenes
3175 public float GetMass() 3770 public float GetMass()
3176 { 3771 {
3177 float retmass = 0f; 3772 float retmass = 0f;
3178
3179 SceneObjectPart[] parts = m_parts.GetArray(); 3773 SceneObjectPart[] parts = m_parts.GetArray();
3180 for (int i = 0; i < parts.Length; i++) 3774 for (int i = 0; i < parts.Length; i++)
3181 retmass += parts[i].GetMass(); 3775 retmass += parts[i].GetMass();
@@ -3271,6 +3865,14 @@ namespace OpenSim.Region.Framework.Scenes
3271 SetFromItemID(uuid); 3865 SetFromItemID(uuid);
3272 } 3866 }
3273 3867
3868 public void ResetOwnerChangeFlag()
3869 {
3870 ForEachPart(delegate(SceneObjectPart part)
3871 {
3872 part.ResetOwnerChangeFlag();
3873 });
3874 }
3875
3274 #endregion 3876 #endregion
3275 } 3877 }
3276} 3878}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 65905a0..dd9431b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -251,6 +260,7 @@ namespace OpenSim.Region.Framework.Scenes
251 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 260 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
252 private Vector3 m_sitTargetPosition; 261 private Vector3 m_sitTargetPosition;
253 private string m_sitAnimation = "SIT"; 262 private string m_sitAnimation = "SIT";
263 private bool m_occupied; // KF if any av is sitting on this prim
254 private string m_text = String.Empty; 264 private string m_text = String.Empty;
255 private string m_touchName = String.Empty; 265 private string m_touchName = String.Empty;
256 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 266 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -283,6 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
283 protected Vector3 m_lastAcceleration; 293 protected Vector3 m_lastAcceleration;
284 protected Vector3 m_lastAngularVelocity; 294 protected Vector3 m_lastAngularVelocity;
285 protected int m_lastTerseSent; 295 protected int m_lastTerseSent;
296 protected float m_buoyancy = 0.0f;
286 297
287 /// <summary> 298 /// <summary>
288 /// Stores media texture data 299 /// Stores media texture data
@@ -299,6 +310,9 @@ namespace OpenSim.Region.Framework.Scenes
299 private UUID m_collisionSound; 310 private UUID m_collisionSound;
300 private float m_collisionSoundVolume; 311 private float m_collisionSoundVolume;
301 312
313
314 private SOPVehicle m_vehicle = null;
315
302 #endregion Fields 316 #endregion Fields
303 317
304// ~SceneObjectPart() 318// ~SceneObjectPart()
@@ -341,7 +355,7 @@ namespace OpenSim.Region.Framework.Scenes
341 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 355 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
342 Quaternion rotationOffset, Vector3 offsetPosition) : this() 356 Quaternion rotationOffset, Vector3 offsetPosition) : this()
343 { 357 {
344 m_name = "Primitive"; 358 m_name = "Object";
345 359
346 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 360 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
347 LastOwnerID = CreatorID = OwnerID = ownerID; 361 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -381,7 +395,7 @@ namespace OpenSim.Region.Framework.Scenes
381 private uint _ownerMask = (uint)PermissionMask.All; 395 private uint _ownerMask = (uint)PermissionMask.All;
382 private uint _groupMask = (uint)PermissionMask.None; 396 private uint _groupMask = (uint)PermissionMask.None;
383 private uint _everyoneMask = (uint)PermissionMask.None; 397 private uint _everyoneMask = (uint)PermissionMask.None;
384 private uint _nextOwnerMask = (uint)PermissionMask.All; 398 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
385 private PrimFlags _flags = PrimFlags.None; 399 private PrimFlags _flags = PrimFlags.None;
386 private DateTime m_expires; 400 private DateTime m_expires;
387 private DateTime m_rezzed; 401 private DateTime m_rezzed;
@@ -475,12 +489,16 @@ namespace OpenSim.Region.Framework.Scenes
475 } 489 }
476 490
477 /// <value> 491 /// <value>
478 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 492 /// Get the inventory list
479 /// </value> 493 /// </value>
480 public TaskInventoryDictionary TaskInventory 494 public TaskInventoryDictionary TaskInventory
481 { 495 {
482 get { return m_inventory.Items; } 496 get {
483 set { m_inventory.Items = value; } 497 return m_inventory.Items;
498 }
499 set {
500 m_inventory.Items = value;
501 }
484 } 502 }
485 503
486 /// <summary> 504 /// <summary>
@@ -624,14 +642,12 @@ namespace OpenSim.Region.Framework.Scenes
624 set { m_LoopSoundSlavePrims = value; } 642 set { m_LoopSoundSlavePrims = value; }
625 } 643 }
626 644
627
628 public Byte[] TextureAnimation 645 public Byte[] TextureAnimation
629 { 646 {
630 get { return m_TextureAnimation; } 647 get { return m_TextureAnimation; }
631 set { m_TextureAnimation = value; } 648 set { m_TextureAnimation = value; }
632 } 649 }
633 650
634
635 public Byte[] ParticleSystem 651 public Byte[] ParticleSystem
636 { 652 {
637 get { return m_particleSystem; } 653 get { return m_particleSystem; }
@@ -668,9 +684,11 @@ namespace OpenSim.Region.Framework.Scenes
668 { 684 {
669 // If this is a linkset, we don't want the physics engine mucking up our group position here. 685 // If this is a linkset, we don't want the physics engine mucking up our group position here.
670 PhysicsActor actor = PhysActor; 686 PhysicsActor actor = PhysActor;
671 if (actor != null && ParentID == 0) 687 if (ParentID == 0)
672 { 688 {
673 m_groupPosition = actor.Position; 689 if (actor != null)
690 m_groupPosition = actor.Position;
691 return m_groupPosition;
674 } 692 }
675 693
676 if (ParentGroup.IsAttachment) 694 if (ParentGroup.IsAttachment)
@@ -680,12 +698,14 @@ namespace OpenSim.Region.Framework.Scenes
680 return sp.AbsolutePosition; 698 return sp.AbsolutePosition;
681 } 699 }
682 700
701 // use root prim's group position. Physics may have updated it
702 if (ParentGroup.RootPart != this)
703 m_groupPosition = ParentGroup.RootPart.GroupPosition;
683 return m_groupPosition; 704 return m_groupPosition;
684 } 705 }
685 set 706 set
686 { 707 {
687 m_groupPosition = value; 708 m_groupPosition = value;
688
689 PhysicsActor actor = PhysActor; 709 PhysicsActor actor = PhysActor;
690 if (actor != null) 710 if (actor != null)
691 { 711 {
@@ -711,16 +731,6 @@ namespace OpenSim.Region.Framework.Scenes
711 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 731 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
712 } 732 }
713 } 733 }
714
715 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
716 if (SitTargetAvatar != UUID.Zero)
717 {
718 ScenePresence avatar;
719 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
720 {
721 avatar.ParentPosition = GetWorldPosition();
722 }
723 }
724 } 734 }
725 } 735 }
726 736
@@ -729,7 +739,7 @@ namespace OpenSim.Region.Framework.Scenes
729 get { return m_offsetPosition; } 739 get { return m_offsetPosition; }
730 set 740 set
731 { 741 {
732// StoreUndoState(); 742 Vector3 oldpos = m_offsetPosition;
733 m_offsetPosition = value; 743 m_offsetPosition = value;
734 744
735 if (ParentGroup != null && !ParentGroup.IsDeleted) 745 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -744,7 +754,22 @@ namespace OpenSim.Region.Framework.Scenes
744 if (ParentGroup.Scene != null) 754 if (ParentGroup.Scene != null)
745 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 755 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
746 } 756 }
757
758 if (!m_parentGroup.m_dupeInProgress)
759 {
760 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
761 foreach (ScenePresence av in avs)
762 {
763 if (av.ParentID == m_localId)
764 {
765 Vector3 offset = (m_offsetPosition - oldpos);
766 av.AbsolutePosition += offset;
767 av.SendAvatarDataToAllAgents();
768 }
769 }
770 }
747 } 771 }
772 TriggerScriptChangedEvent(Changed.POSITION);
748 } 773 }
749 } 774 }
750 775
@@ -893,7 +918,16 @@ namespace OpenSim.Region.Framework.Scenes
893 /// <summary></summary> 918 /// <summary></summary>
894 public Vector3 Acceleration 919 public Vector3 Acceleration
895 { 920 {
896 get { return m_acceleration; } 921 get
922 {
923 PhysicsActor actor = PhysActor;
924 if (actor != null)
925 {
926 m_acceleration = actor.Acceleration;
927 }
928 return m_acceleration;
929 }
930
897 set { m_acceleration = value; } 931 set { m_acceleration = value; }
898 } 932 }
899 933
@@ -1030,10 +1064,7 @@ namespace OpenSim.Region.Framework.Scenes
1030 { 1064 {
1031 get 1065 get
1032 { 1066 {
1033 if (ParentGroup.IsAttachment) 1067 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1034 return GroupPosition;
1035
1036 return m_offsetPosition + m_groupPosition;
1037 } 1068 }
1038 } 1069 }
1039 1070
@@ -1203,6 +1234,13 @@ namespace OpenSim.Region.Framework.Scenes
1203 _flags = value; 1234 _flags = value;
1204 } 1235 }
1205 } 1236 }
1237
1238 [XmlIgnore]
1239 public bool IsOccupied // KF If an av is sittingon this prim
1240 {
1241 get { return m_occupied; }
1242 set { m_occupied = value; }
1243 }
1206 1244
1207 /// <summary> 1245 /// <summary>
1208 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1246 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1262,6 +1300,19 @@ namespace OpenSim.Region.Framework.Scenes
1262 set { m_collisionSoundVolume = value; } 1300 set { m_collisionSoundVolume = value; }
1263 } 1301 }
1264 1302
1303 public float Buoyancy
1304 {
1305 get { return m_buoyancy; }
1306 set
1307 {
1308 m_buoyancy = value;
1309 if (PhysActor != null)
1310 {
1311 PhysActor.Buoyancy = value;
1312 }
1313 }
1314 }
1315
1265 #endregion Public Properties with only Get 1316 #endregion Public Properties with only Get
1266 1317
1267 private uint ApplyMask(uint val, bool set, uint mask) 1318 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1458,7 +1509,8 @@ namespace OpenSim.Region.Framework.Scenes
1458 /// </summary> 1509 /// </summary>
1459 /// <param name="rootObjectFlags"></param> 1510 /// <param name="rootObjectFlags"></param>
1460 /// <param name="VolumeDetectActive"></param> 1511 /// <param name="VolumeDetectActive"></param>
1461 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1512// public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive)
1513 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building)
1462 { 1514 {
1463 if (!ParentGroup.Scene.CollidablePrims) 1515 if (!ParentGroup.Scene.CollidablePrims)
1464 return; 1516 return;
@@ -1487,6 +1539,8 @@ namespace OpenSim.Region.Framework.Scenes
1487 // or flexible 1539 // or flexible
1488 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 1540 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1489 { 1541 {
1542 Vector3 velocity = Velocity;
1543 Vector3 rotationalVelocity = AngularVelocity;
1490 try 1544 try
1491 { 1545 {
1492 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( 1546 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
@@ -1494,7 +1548,8 @@ namespace OpenSim.Region.Framework.Scenes
1494 Shape, 1548 Shape,
1495 AbsolutePosition, 1549 AbsolutePosition,
1496 Scale, 1550 Scale,
1497 RotationOffset, 1551// RotationOffset,
1552 GetWorldRotation(), // physics wants world rotation
1498 RigidBody, 1553 RigidBody,
1499 m_localId); 1554 m_localId);
1500 } 1555 }
@@ -1509,8 +1564,21 @@ namespace OpenSim.Region.Framework.Scenes
1509 { 1564 {
1510 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 1565 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
1511 PhysActor.SetMaterial(Material); 1566 PhysActor.SetMaterial(Material);
1567
1568 // if root part apply vehicle
1569 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
1570 m_vehicle.SetVehicle(PhysActor);
1571
1512 DoPhysicsPropertyUpdate(RigidBody, true); 1572 DoPhysicsPropertyUpdate(RigidBody, true);
1513 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1573 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1574
1575 Velocity = velocity;
1576 AngularVelocity = rotationalVelocity;
1577 PhysActor.Velocity = velocity;
1578 PhysActor.RotationalVelocity = rotationalVelocity;
1579
1580 if (!building)
1581 PhysActor.Building = false;
1514 } 1582 }
1515 } 1583 }
1516 } 1584 }
@@ -1582,6 +1650,9 @@ namespace OpenSim.Region.Framework.Scenes
1582 1650
1583 // Move afterwards ResetIDs as it clears the localID 1651 // Move afterwards ResetIDs as it clears the localID
1584 dupe.LocalId = localID; 1652 dupe.LocalId = localID;
1653 if(dupe.PhysActor != null)
1654 dupe.PhysActor.LocalID = localID;
1655
1585 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1656 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1586 dupe.LastOwnerID = OwnerID; 1657 dupe.LastOwnerID = OwnerID;
1587 1658
@@ -1743,6 +1814,10 @@ namespace OpenSim.Region.Framework.Scenes
1743 if (!isNew) 1814 if (!isNew)
1744 ParentGroup.Scene.RemovePhysicalPrim(1); 1815 ParentGroup.Scene.RemovePhysicalPrim(1);
1745 1816
1817 Velocity = new Vector3(0, 0, 0);
1818 Acceleration = new Vector3(0, 0, 0);
1819 AngularVelocity = new Vector3(0, 0, 0);
1820
1746 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 1821 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1747 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; 1822 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
1748 PhysActor.delink(); 1823 PhysActor.delink();
@@ -2564,9 +2639,9 @@ namespace OpenSim.Region.Framework.Scenes
2564 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); 2639 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0);
2565 2640
2566 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2641 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2567 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2642 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2568 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2643 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2569 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2644 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2570 { 2645 {
2571 ParentGroup.AbsolutePosition = newpos; 2646 ParentGroup.AbsolutePosition = newpos;
2572 return; 2647 return;
@@ -2587,17 +2662,18 @@ namespace OpenSim.Region.Framework.Scenes
2587 //Trys to fetch sound id from prim's inventory. 2662 //Trys to fetch sound id from prim's inventory.
2588 //Prim's inventory doesn't support non script items yet 2663 //Prim's inventory doesn't support non script items yet
2589 2664
2590 lock (TaskInventory) 2665 TaskInventory.LockItemsForRead(true);
2666
2667 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2591 { 2668 {
2592 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2669 if (item.Value.Name == sound)
2593 { 2670 {
2594 if (item.Value.Name == sound) 2671 soundID = item.Value.ItemID;
2595 { 2672 break;
2596 soundID = item.Value.ItemID;
2597 break;
2598 }
2599 } 2673 }
2600 } 2674 }
2675
2676 TaskInventory.LockItemsForRead(false);
2601 } 2677 }
2602 2678
2603 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2679 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2917,8 +2993,8 @@ namespace OpenSim.Region.Framework.Scenes
2917 { 2993 {
2918 const float ROTATION_TOLERANCE = 0.01f; 2994 const float ROTATION_TOLERANCE = 0.01f;
2919 const float VELOCITY_TOLERANCE = 0.001f; 2995 const float VELOCITY_TOLERANCE = 0.001f;
2920 const float POSITION_TOLERANCE = 0.05f; 2996 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2921 const int TIME_MS_TOLERANCE = 3000; 2997 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2922 2998
2923 switch (UpdateFlag) 2999 switch (UpdateFlag)
2924 { 3000 {
@@ -2980,17 +3056,16 @@ namespace OpenSim.Region.Framework.Scenes
2980 if (!UUID.TryParse(sound, out soundID)) 3056 if (!UUID.TryParse(sound, out soundID))
2981 { 3057 {
2982 // search sound file from inventory 3058 // search sound file from inventory
2983 lock (TaskInventory) 3059 TaskInventory.LockItemsForRead(true);
3060 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2984 { 3061 {
2985 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3062 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2986 { 3063 {
2987 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3064 soundID = item.Value.ItemID;
2988 { 3065 break;
2989 soundID = item.Value.ItemID;
2990 break;
2991 }
2992 } 3066 }
2993 } 3067 }
3068 TaskInventory.LockItemsForRead(false);
2994 } 3069 }
2995 3070
2996 if (soundID == UUID.Zero) 3071 if (soundID == UUID.Zero)
@@ -3112,17 +3187,74 @@ namespace OpenSim.Region.Framework.Scenes
3112 } 3187 }
3113 } 3188 }
3114 3189
3190 public SOPVehicle sopVehicle
3191 {
3192 get
3193 {
3194 return m_vehicle;
3195 }
3196 set
3197 {
3198 m_vehicle = value;
3199 }
3200 }
3201
3202
3203 public int VehicleType
3204 {
3205 get
3206 {
3207 if (m_vehicle == null)
3208 return (int)Vehicle.TYPE_NONE;
3209 else
3210 return (int)m_vehicle.Type;
3211 }
3212 set
3213 {
3214 SetVehicleType(value);
3215 }
3216 }
3217
3115 public void SetVehicleType(int type) 3218 public void SetVehicleType(int type)
3116 { 3219 {
3117 if (PhysActor != null) 3220 m_vehicle = null;
3221
3222 if (type == (int)Vehicle.TYPE_NONE)
3223 {
3224 if (_parentID ==0 && PhysActor != null)
3225 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3226 return;
3227 }
3228 m_vehicle = new SOPVehicle();
3229 m_vehicle.ProcessTypeChange((Vehicle)type);
3230 {
3231 if (_parentID ==0 && PhysActor != null)
3232 PhysActor.VehicleType = type;
3233 return;
3234 }
3235 }
3236
3237 public void SetVehicleFlags(int param, bool remove)
3238 {
3239 if (m_vehicle == null)
3240 return;
3241
3242 m_vehicle.ProcessVehicleFlags(param, remove);
3243
3244 if (_parentID ==0 && PhysActor != null)
3118 { 3245 {
3119 PhysActor.VehicleType = type; 3246 PhysActor.VehicleFlags(param, remove);
3120 } 3247 }
3121 } 3248 }
3122 3249
3123 public void SetVehicleFloatParam(int param, float value) 3250 public void SetVehicleFloatParam(int param, float value)
3124 { 3251 {
3125 if (PhysActor != null) 3252 if (m_vehicle == null)
3253 return;
3254
3255 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
3256
3257 if (_parentID == 0 && PhysActor != null)
3126 { 3258 {
3127 PhysActor.VehicleFloatParam(param, value); 3259 PhysActor.VehicleFloatParam(param, value);
3128 } 3260 }
@@ -3130,7 +3262,12 @@ namespace OpenSim.Region.Framework.Scenes
3130 3262
3131 public void SetVehicleVectorParam(int param, Vector3 value) 3263 public void SetVehicleVectorParam(int param, Vector3 value)
3132 { 3264 {
3133 if (PhysActor != null) 3265 if (m_vehicle == null)
3266 return;
3267
3268 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
3269
3270 if (_parentID == 0 && PhysActor != null)
3134 { 3271 {
3135 PhysActor.VehicleVectorParam(param, value); 3272 PhysActor.VehicleVectorParam(param, value);
3136 } 3273 }
@@ -3138,7 +3275,12 @@ namespace OpenSim.Region.Framework.Scenes
3138 3275
3139 public void SetVehicleRotationParam(int param, Quaternion rotation) 3276 public void SetVehicleRotationParam(int param, Quaternion rotation)
3140 { 3277 {
3141 if (PhysActor != null) 3278 if (m_vehicle == null)
3279 return;
3280
3281 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
3282
3283 if (_parentID == 0 && PhysActor != null)
3142 { 3284 {
3143 PhysActor.VehicleRotationParam(param, rotation); 3285 PhysActor.VehicleRotationParam(param, rotation);
3144 } 3286 }
@@ -3325,13 +3467,6 @@ namespace OpenSim.Region.Framework.Scenes
3325 hasProfileCut = hasDimple; // is it the same thing? 3467 hasProfileCut = hasDimple; // is it the same thing?
3326 } 3468 }
3327 3469
3328 public void SetVehicleFlags(int param, bool remove)
3329 {
3330 if (PhysActor != null)
3331 {
3332 PhysActor.VehicleFlags(param, remove);
3333 }
3334 }
3335 3470
3336 public void SetGroup(UUID groupID, IClientAPI client) 3471 public void SetGroup(UUID groupID, IClientAPI client)
3337 { 3472 {
@@ -3457,10 +3592,10 @@ namespace OpenSim.Region.Framework.Scenes
3457 // TODO: May need to fix for group comparison 3592 // TODO: May need to fix for group comparison
3458 if (last.Compare(this)) 3593 if (last.Compare(this))
3459 { 3594 {
3460 // m_log.DebugFormat( 3595 // m_log.DebugFormat(
3461 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3596 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3462 // Name, LocalId, m_undo.Count); 3597 // Name, LocalId, m_undo.Count);
3463 3598
3464 return; 3599 return;
3465 } 3600 }
3466 } 3601 }
@@ -3473,29 +3608,29 @@ namespace OpenSim.Region.Framework.Scenes
3473 if (ParentGroup.GetSceneMaxUndo() > 0) 3608 if (ParentGroup.GetSceneMaxUndo() > 0)
3474 { 3609 {
3475 UndoState nUndo = new UndoState(this, forGroup); 3610 UndoState nUndo = new UndoState(this, forGroup);
3476 3611
3477 m_undo.Push(nUndo); 3612 m_undo.Push(nUndo);
3478 3613
3479 if (m_redo.Count > 0) 3614 if (m_redo.Count > 0)
3480 m_redo.Clear(); 3615 m_redo.Clear();
3481 3616
3482 // m_log.DebugFormat( 3617 // m_log.DebugFormat(
3483 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3618 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3484 // Name, LocalId, forGroup, m_undo.Count); 3619 // Name, LocalId, forGroup, m_undo.Count);
3485 } 3620 }
3486 } 3621 }
3487 } 3622 }
3488 } 3623 }
3489// else 3624 // else
3490// { 3625 // {
3491// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3626 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3492// } 3627 // }
3493 } 3628 }
3494// else 3629 // else
3495// { 3630 // {
3496// m_log.DebugFormat( 3631 // m_log.DebugFormat(
3497// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3632 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3498// } 3633 // }
3499 } 3634 }
3500 3635
3501 /// <summary> 3636 /// <summary>
@@ -4219,13 +4354,17 @@ namespace OpenSim.Region.Framework.Scenes
4219 /// <param name="SetTemporary"></param> 4354 /// <param name="SetTemporary"></param>
4220 /// <param name="SetPhantom"></param> 4355 /// <param name="SetPhantom"></param>
4221 /// <param name="SetVD"></param> 4356 /// <param name="SetVD"></param>
4222 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4357// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
4358 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4223 { 4359 {
4224 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4360 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4225 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4361 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
4226 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4362 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4227 bool wasVD = VolumeDetectActive; 4363 bool wasVD = VolumeDetectActive;
4228 4364
4365// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4366// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4367
4229 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4368 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4230 return; 4369 return;
4231 4370
@@ -4234,6 +4373,9 @@ namespace OpenSim.Region.Framework.Scenes
4234 // that... 4373 // that...
4235 // ... if VD is changed, all others are not. 4374 // ... if VD is changed, all others are not.
4236 // ... if one of the others is changed, VD is not. 4375 // ... if one of the others is changed, VD is not.
4376 // do this first
4377 if (building && PhysActor != null && PhysActor.Building != building)
4378 PhysActor.Building = building;
4237 if (SetVD) // VD is active, special logic applies 4379 if (SetVD) // VD is active, special logic applies
4238 { 4380 {
4239 // State machine logic for VolumeDetect 4381 // State machine logic for VolumeDetect
@@ -4255,6 +4397,11 @@ namespace OpenSim.Region.Framework.Scenes
4255 SetPhantom = false; 4397 SetPhantom = false;
4256 } 4398 }
4257 } 4399 }
4400 else if (wasVD)
4401 {
4402 // Correspondingly, if VD is turned off, also turn off phantom
4403 SetPhantom = false;
4404 }
4258 4405
4259 if (UsePhysics && IsJoint()) 4406 if (UsePhysics && IsJoint())
4260 { 4407 {
@@ -4310,11 +4457,17 @@ namespace OpenSim.Region.Framework.Scenes
4310 Shape, 4457 Shape,
4311 AbsolutePosition, 4458 AbsolutePosition,
4312 Scale, 4459 Scale,
4313 RotationOffset, 4460// RotationOffset,
4461 GetWorldRotation(), //physics wants world rotation like all other functions send
4314 UsePhysics, 4462 UsePhysics,
4315 m_localId); 4463 m_localId);
4316 4464
4317 PhysActor.SetMaterial(Material); 4465 PhysActor.SetMaterial(Material);
4466
4467 // if root part apply vehicle
4468 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4469 m_vehicle.SetVehicle(PhysActor);
4470
4318 DoPhysicsPropertyUpdate(UsePhysics, true); 4471 DoPhysicsPropertyUpdate(UsePhysics, true);
4319 4472
4320 if (!ParentGroup.IsDeleted) 4473 if (!ParentGroup.IsDeleted)
@@ -4390,6 +4543,9 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4543 }
4391 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4544 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4392 4545
4546 // and last in case we have a new actor and not building
4547 if (PhysActor != null && PhysActor.Building != building)
4548 PhysActor.Building = building;
4393 if (ParentGroup != null) 4549 if (ParentGroup != null)
4394 { 4550 {
4395 ParentGroup.HasGroupChanged = true; 4551 ParentGroup.HasGroupChanged = true;
@@ -4753,5 +4909,17 @@ namespace OpenSim.Region.Framework.Scenes
4753 Color color = Color; 4909 Color color = Color;
4754 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4910 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4755 } 4911 }
4912
4913 public void ResetOwnerChangeFlag()
4914 {
4915 List<UUID> inv = Inventory.GetInventoryList();
4916
4917 foreach (UUID itemID in inv)
4918 {
4919 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4920 item.OwnerChanged = false;
4921 Inventory.UpdateInventoryItem(item, false, false);
4922 }
4923 }
4756 } 4924 }
4757} 4925}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index f2d1915..ca85d10 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
217 } 231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -271,7 +330,10 @@ namespace OpenSim.Region.Framework.Scenes
271// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 330// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
272 331
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 332 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
333 {
334 StoreScriptError(item.ItemID, "no permission");
274 return; 335 return;
336 }
275 337
276 m_part.AddFlag(PrimFlags.Scripted); 338 m_part.AddFlag(PrimFlags.Scripted);
277 339
@@ -280,14 +342,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 342 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 343 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 344 {
283 lock (m_items) 345 m_items.LockItemsForWrite(true);
284 { 346 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 347 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 348 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 349 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 350 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
351 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 352 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 353 m_part.ScheduleFullUpdate();
293 return; 354 return;
@@ -296,6 +357,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 357 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 358 if (null == asset)
298 { 359 {
360 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
361 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 362 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 363 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
301 item.Name, item.ItemID, m_part.AbsolutePosition, 364 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -306,16 +369,21 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 369 if (m_part.ParentGroup.m_savedScriptState != null)
307 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 370 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
308 371
309 lock (m_items) 372 m_items.LockItemsForWrite(true);
310 {
311 m_items[item.ItemID].OldItemID = item.OldItemID;
312 m_items[item.ItemID].PermsMask = 0;
313 m_items[item.ItemID].PermsGranter = UUID.Zero;
314 }
315 373
374 m_items[item.ItemID].OldItemID = item.OldItemID;
375 m_items[item.ItemID].PermsMask = 0;
376 m_items[item.ItemID].PermsGranter = UUID.Zero;
377
378 m_items.LockItemsForWrite(false);
379
316 string script = Utils.BytesToString(asset.Data); 380 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 381 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 382 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
383 StoreScriptErrors(item.ItemID, null);
384 if (!item.ScriptRunning)
385 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
386 m_part.LocalId, item.ItemID);
319 m_part.ParentGroup.AddActiveScriptCount(1); 387 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 388 m_part.ScheduleFullUpdate();
321 } 389 }
@@ -386,20 +454,146 @@ namespace OpenSim.Region.Framework.Scenes
386 454
387 /// <summary> 455 /// <summary>
388 /// Start a script which is in this prim's inventory. 456 /// Start a script which is in this prim's inventory.
457 /// Some processing may occur in the background, but this routine returns asap.
389 /// </summary> 458 /// </summary>
390 /// <param name="itemId"> 459 /// <param name="itemId">
391 /// A <see cref="UUID"/> 460 /// A <see cref="UUID"/>
392 /// </param> 461 /// </param>
393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 462 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
394 { 463 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 464 lock (m_scriptErrors)
396 if (item != null) 465 {
397 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 466 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
467 m_scriptErrors.Remove(itemId);
468 }
469 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
470 }
471
472 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
473 {
474 m_items.LockItemsForRead(true);
475 if (m_items.ContainsKey(itemId))
476 {
477 if (m_items.ContainsKey(itemId))
478 {
479 m_items.LockItemsForRead(false);
480 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
481 }
482 else
483 {
484 m_items.LockItemsForRead(false);
485 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
486 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
487 StoreScriptError(itemId, msg);
488 m_log.ErrorFormat(
489 "[PRIM INVENTORY]: " +
490 "Couldn't start script with ID {0} since it {1}", itemId, msg);
491 }
492 }
398 else 493 else
494 {
495 m_items.LockItemsForRead(false);
496 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
497 StoreScriptError(itemId, msg);
399 m_log.ErrorFormat( 498 m_log.ErrorFormat(
400 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 499 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
401 itemId, m_part.Name, m_part.UUID, 500 itemId, m_part.Name, m_part.UUID,
402 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 501 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
502 }
503
504 }
505
506 /// <summary>
507 /// Start a script which is in this prim's inventory and return any compilation error messages.
508 /// </summary>
509 /// <param name="itemId">
510 /// A <see cref="UUID"/>
511 /// </param>
512 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
513 {
514 ArrayList errors;
515
516 // Indicate to CreateScriptInstanceInternal() we want it to
517 // post any compilation/loading error messages
518 lock (m_scriptErrors)
519 {
520 m_scriptErrors[itemId] = null;
521 }
522
523 // Perform compilation/loading
524 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
525
526 // Wait for and retrieve any errors
527 lock (m_scriptErrors)
528 {
529 while ((errors = m_scriptErrors[itemId]) == null)
530 {
531 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
532 {
533 m_log.ErrorFormat(
534 "[PRIM INVENTORY]: " +
535 "timedout waiting for script {0} errors", itemId);
536 errors = m_scriptErrors[itemId];
537 if (errors == null)
538 {
539 errors = new ArrayList(1);
540 errors.Add("timedout waiting for errors");
541 }
542 break;
543 }
544 }
545 m_scriptErrors.Remove(itemId);
546 }
547 return errors;
548 }
549
550 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
551 private void StoreScriptErrors(UUID itemId, ArrayList errors)
552 {
553 lock (m_scriptErrors)
554 {
555 // If compilation/loading initiated via CreateScriptInstance(),
556 // it does not want the errors, so just get out
557 if (!m_scriptErrors.ContainsKey(itemId))
558 {
559 return;
560 }
561
562 // Initiated via CreateScriptInstanceEr(), if we know what the
563 // errors are, save them and wake CreateScriptInstanceEr().
564 if (errors != null)
565 {
566 m_scriptErrors[itemId] = errors;
567 System.Threading.Monitor.PulseAll(m_scriptErrors);
568 return;
569 }
570 }
571
572 // Initiated via CreateScriptInstanceEr() but we don't know what
573 // the errors are yet, so retrieve them from the script engine.
574 // This may involve some waiting internal to GetScriptErrors().
575 errors = GetScriptErrors(itemId);
576
577 // Get a default non-null value to indicate success.
578 if (errors == null)
579 {
580 errors = new ArrayList();
581 }
582
583 // Post to CreateScriptInstanceEr() and wake it up
584 lock (m_scriptErrors)
585 {
586 m_scriptErrors[itemId] = errors;
587 System.Threading.Monitor.PulseAll(m_scriptErrors);
588 }
589 }
590
591 // Like StoreScriptErrors(), but just posts a single string message
592 private void StoreScriptError(UUID itemId, string message)
593 {
594 ArrayList errors = new ArrayList(1);
595 errors.Add(message);
596 StoreScriptErrors(itemId, errors);
403 } 597 }
404 598
405 /// <summary> 599 /// <summary>
@@ -412,15 +606,7 @@ namespace OpenSim.Region.Framework.Scenes
412 /// </param> 606 /// </param>
413 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 607 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
414 { 608 {
415 bool scriptPresent = false; 609 if (m_items.ContainsKey(itemId))
416
417 lock (m_items)
418 {
419 if (m_items.ContainsKey(itemId))
420 scriptPresent = true;
421 }
422
423 if (scriptPresent)
424 { 610 {
425 if (!sceneObjectBeingDeleted) 611 if (!sceneObjectBeingDeleted)
426 m_part.RemoveScriptEvents(itemId); 612 m_part.RemoveScriptEvents(itemId);
@@ -445,14 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
445 /// <returns></returns> 631 /// <returns></returns>
446 private bool InventoryContainsName(string name) 632 private bool InventoryContainsName(string name)
447 { 633 {
448 lock (m_items) 634 m_items.LockItemsForRead(true);
635 foreach (TaskInventoryItem item in m_items.Values)
449 { 636 {
450 foreach (TaskInventoryItem item in m_items.Values) 637 if (item.Name == name)
451 { 638 {
452 if (item.Name == name) 639 m_items.LockItemsForRead(false);
453 return true; 640 return true;
454 } 641 }
455 } 642 }
643 m_items.LockItemsForRead(false);
456 return false; 644 return false;
457 } 645 }
458 646
@@ -494,8 +682,9 @@ namespace OpenSim.Region.Framework.Scenes
494 /// <param name="item"></param> 682 /// <param name="item"></param>
495 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 683 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
496 { 684 {
497 List<TaskInventoryItem> il = GetInventoryItems(); 685 m_items.LockItemsForRead(true);
498 686 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
687 m_items.LockItemsForRead(false);
499 foreach (TaskInventoryItem i in il) 688 foreach (TaskInventoryItem i in il)
500 { 689 {
501 if (i.Name == item.Name) 690 if (i.Name == item.Name)
@@ -533,14 +722,14 @@ namespace OpenSim.Region.Framework.Scenes
533 item.Name = name; 722 item.Name = name;
534 item.GroupID = m_part.GroupID; 723 item.GroupID = m_part.GroupID;
535 724
536 lock (m_items) 725 m_items.LockItemsForWrite(true);
537 m_items.Add(item.ItemID, item); 726 m_items.Add(item.ItemID, item);
538 727 m_items.LockItemsForWrite(false);
539 if (allowedDrop) 728 if (allowedDrop)
540 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 729 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
541 else 730 else
542 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 731 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
543 732
544 m_inventorySerial++; 733 m_inventorySerial++;
545 //m_inventorySerial += 2; 734 //m_inventorySerial += 2;
546 HasInventoryChanged = true; 735 HasInventoryChanged = true;
@@ -556,15 +745,15 @@ namespace OpenSim.Region.Framework.Scenes
556 /// <param name="items"></param> 745 /// <param name="items"></param>
557 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 746 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
558 { 747 {
559 lock (m_items) 748 m_items.LockItemsForWrite(true);
749 foreach (TaskInventoryItem item in items)
560 { 750 {
561 foreach (TaskInventoryItem item in items) 751 m_items.Add(item.ItemID, item);
562 { 752// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 m_items.Add(item.ItemID, item);
564// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
565 }
566 m_inventorySerial++;
567 } 753 }
754 m_items.LockItemsForWrite(false);
755
756 m_inventorySerial++;
568 } 757 }
569 758
570 /// <summary> 759 /// <summary>
@@ -575,10 +764,9 @@ namespace OpenSim.Region.Framework.Scenes
575 public TaskInventoryItem GetInventoryItem(UUID itemId) 764 public TaskInventoryItem GetInventoryItem(UUID itemId)
576 { 765 {
577 TaskInventoryItem item; 766 TaskInventoryItem item;
578 767 m_items.LockItemsForRead(true);
579 lock (m_items) 768 m_items.TryGetValue(itemId, out item);
580 m_items.TryGetValue(itemId, out item); 769 m_items.LockItemsForRead(false);
581
582 return item; 770 return item;
583 } 771 }
584 772
@@ -594,15 +782,16 @@ namespace OpenSim.Region.Framework.Scenes
594 { 782 {
595 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 783 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
596 784
597 lock (m_items) 785 m_items.LockItemsForRead(true);
786
787 foreach (TaskInventoryItem item in m_items.Values)
598 { 788 {
599 foreach (TaskInventoryItem item in m_items.Values) 789 if (item.Name == name)
600 { 790 items.Add(item);
601 if (item.Name == name)
602 items.Add(item);
603 }
604 } 791 }
605 792
793 m_items.LockItemsForRead(false);
794
606 return items; 795 return items;
607 } 796 }
608 797
@@ -621,6 +810,9 @@ namespace OpenSim.Region.Framework.Scenes
621 string xmlData = Utils.BytesToString(rezAsset.Data); 810 string xmlData = Utils.BytesToString(rezAsset.Data);
622 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 811 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
623 812
813 group.RootPart.AttachPoint = group.RootPart.Shape.State;
814 group.RootPart.AttachOffset = group.AbsolutePosition;
815
624 group.ResetIDs(); 816 group.ResetIDs();
625 817
626 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 818 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -695,8 +887,9 @@ namespace OpenSim.Region.Framework.Scenes
695 887
696 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 888 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
697 { 889 {
698 TaskInventoryItem it = GetInventoryItem(item.ItemID); 890 m_items.LockItemsForWrite(true);
699 if (it != null) 891
892 if (m_items.ContainsKey(item.ItemID))
700 { 893 {
701// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 894// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
702 895
@@ -709,14 +902,10 @@ namespace OpenSim.Region.Framework.Scenes
709 item.GroupID = m_part.GroupID; 902 item.GroupID = m_part.GroupID;
710 903
711 if (item.AssetID == UUID.Zero) 904 if (item.AssetID == UUID.Zero)
712 item.AssetID = it.AssetID; 905 item.AssetID = m_items[item.ItemID].AssetID;
713 906
714 lock (m_items) 907 m_items[item.ItemID] = item;
715 { 908 m_inventorySerial++;
716 m_items[item.ItemID] = item;
717 m_inventorySerial++;
718 }
719
720 if (fireScriptEvents) 909 if (fireScriptEvents)
721 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 910 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
722 911
@@ -725,7 +914,7 @@ namespace OpenSim.Region.Framework.Scenes
725 HasInventoryChanged = true; 914 HasInventoryChanged = true;
726 m_part.ParentGroup.HasGroupChanged = true; 915 m_part.ParentGroup.HasGroupChanged = true;
727 } 916 }
728 917 m_items.LockItemsForWrite(false);
729 return true; 918 return true;
730 } 919 }
731 else 920 else
@@ -736,8 +925,9 @@ namespace OpenSim.Region.Framework.Scenes
736 item.ItemID, m_part.Name, m_part.UUID, 925 item.ItemID, m_part.Name, m_part.UUID,
737 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 926 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
738 } 927 }
739 return false; 928 m_items.LockItemsForWrite(false);
740 929
930 return false;
741 } 931 }
742 932
743 /// <summary> 933 /// <summary>
@@ -748,43 +938,59 @@ namespace OpenSim.Region.Framework.Scenes
748 /// in this prim's inventory.</returns> 938 /// in this prim's inventory.</returns>
749 public int RemoveInventoryItem(UUID itemID) 939 public int RemoveInventoryItem(UUID itemID)
750 { 940 {
751 TaskInventoryItem item = GetInventoryItem(itemID); 941 m_items.LockItemsForRead(true);
752 if (item != null) 942
943 if (m_items.ContainsKey(itemID))
753 { 944 {
754 int type = m_items[itemID].InvType; 945 int type = m_items[itemID].InvType;
946 m_items.LockItemsForRead(false);
755 if (type == 10) // Script 947 if (type == 10) // Script
756 { 948 {
757 m_part.RemoveScriptEvents(itemID);
758 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 949 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
759 } 950 }
951 m_items.LockItemsForWrite(true);
760 m_items.Remove(itemID); 952 m_items.Remove(itemID);
953 m_items.LockItemsForWrite(false);
761 m_inventorySerial++; 954 m_inventorySerial++;
762 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 955 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
763 956
764 HasInventoryChanged = true; 957 HasInventoryChanged = true;
765 m_part.ParentGroup.HasGroupChanged = true; 958 m_part.ParentGroup.HasGroupChanged = true;
766 959
767 if (!ContainsScripts()) 960 int scriptcount = 0;
961 m_items.LockItemsForRead(true);
962 foreach (TaskInventoryItem item in m_items.Values)
963 {
964 if (item.Type == 10)
965 {
966 scriptcount++;
967 }
968 }
969 m_items.LockItemsForRead(false);
970
971
972 if (scriptcount <= 0)
973 {
768 m_part.RemFlag(PrimFlags.Scripted); 974 m_part.RemFlag(PrimFlags.Scripted);
975 }
769 976
770 m_part.ScheduleFullUpdate(); 977 m_part.ScheduleFullUpdate();
771 978
772 return type; 979 return type;
773
774 } 980 }
775 else 981 else
776 { 982 {
983 m_items.LockItemsForRead(false);
777 m_log.ErrorFormat( 984 m_log.ErrorFormat(
778 "[PRIM INVENTORY]: " + 985 "[PRIM INVENTORY]: " +
779 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 986 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
780 itemID, m_part.Name, m_part.UUID, 987 itemID, m_part.Name, m_part.UUID);
781 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
782 } 988 }
783 989
784 return -1; 990 return -1;
785 } 991 }
786 992
787 private bool CreateInventoryFile() 993 private bool CreateInventoryFileName()
788 { 994 {
789// m_log.DebugFormat( 995// m_log.DebugFormat(
790// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 996// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -793,116 +999,125 @@ namespace OpenSim.Region.Framework.Scenes
793 if (m_inventoryFileName == String.Empty || 999 if (m_inventoryFileName == String.Empty ||
794 m_inventoryFileNameSerial < m_inventorySerial) 1000 m_inventoryFileNameSerial < m_inventorySerial)
795 { 1001 {
796 // Something changed, we need to create a new file
797 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1002 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
798 m_inventoryFileNameSerial = m_inventorySerial; 1003 m_inventoryFileNameSerial = m_inventorySerial;
799 1004
800 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1005 return true;
1006 }
1007
1008 return false;
1009 }
1010
1011 /// <summary>
1012 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1013 /// </summary>
1014 /// <param name="xferManager"></param>
1015 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1016 {
1017 bool changed = CreateInventoryFileName();
1018
1019 bool includeAssets = false;
1020 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1021 includeAssets = true;
1022
1023 if (m_inventoryPrivileged != includeAssets)
1024 changed = true;
1025
1026 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1027
1028 Items.LockItemsForRead(true);
1029
1030 if (m_inventorySerial == 0) // No inventory
1031 {
1032 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1033 Items.LockItemsForRead(false);
1034 return;
1035 }
801 1036
802 lock (m_items) 1037 if (m_items.Count == 0) // No inventory
1038 {
1039 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1040 Items.LockItemsForRead(false);
1041 return;
1042 }
1043
1044 if (!changed)
1045 {
1046 if (m_inventoryFileData.Length > 2)
803 { 1047 {
804 foreach (TaskInventoryItem item in m_items.Values) 1048 xferManager.AddNewFile(m_inventoryFileName,
805 { 1049 m_inventoryFileData);
806// m_log.DebugFormat( 1050 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
807// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1051 Util.StringToBytes256(m_inventoryFileName));
808// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
809 1052
810 UUID ownerID = item.OwnerID; 1053 Items.LockItemsForRead(false);
811 uint everyoneMask = 0; 1054 return;
812 uint baseMask = item.BasePermissions; 1055 }
813 uint ownerMask = item.CurrentPermissions; 1056 }
814 uint groupMask = item.GroupPermissions;
815 1057
816 invString.AddItemStart(); 1058 m_inventoryPrivileged = includeAssets;
817 invString.AddNameValueLine("item_id", item.ItemID.ToString());
818 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
819 1059
820 invString.AddPermissionsStart(); 1060 foreach (TaskInventoryItem item in m_items.Values)
1061 {
1062 UUID ownerID = item.OwnerID;
1063 uint everyoneMask = 0;
1064 uint baseMask = item.BasePermissions;
1065 uint ownerMask = item.CurrentPermissions;
1066 uint groupMask = item.GroupPermissions;
821 1067
822 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1068 invString.AddItemStart();
823 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1069 invString.AddNameValueLine("item_id", item.ItemID.ToString());
824 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1070 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
825 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
826 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
827 1071
828 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1072 invString.AddPermissionsStart();
829 invString.AddNameValueLine("owner_id", ownerID.ToString());
830 1073
831 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1074 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1075 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1076 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1077 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1078 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
832 1079
833 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1080 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
834 invString.AddSectionEnd(); 1081 invString.AddNameValueLine("owner_id", ownerID.ToString());
835 1082
836 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1083 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
837 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
838 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
839 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
840 1084
841 invString.AddSaleStart(); 1085 invString.AddNameValueLine("group_id", item.GroupID.ToString());
842 invString.AddNameValueLine("sale_type", "not"); 1086 invString.AddSectionEnd();
843 invString.AddNameValueLine("sale_price", "0");
844 invString.AddSectionEnd();
845 1087
846 invString.AddNameValueLine("name", item.Name + "|"); 1088 if (includeAssets)
847 invString.AddNameValueLine("desc", item.Description + "|"); 1089 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1090 else
1091 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1092 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1093 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1094 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
848 1095
849 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1096 invString.AddSaleStart();
850 invString.AddSectionEnd(); 1097 invString.AddNameValueLine("sale_type", "not");
851 } 1098 invString.AddNameValueLine("sale_price", "0");
852 } 1099 invString.AddSectionEnd();
853 1100
854 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1101 invString.AddNameValueLine("name", item.Name + "|");
1102 invString.AddNameValueLine("desc", item.Description + "|");
855 1103
856 return true; 1104 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1105 invString.AddSectionEnd();
857 } 1106 }
858 1107
859 // No need to recreate, the existing file is fine 1108 Items.LockItemsForRead(false);
860 return false;
861 }
862
863 /// <summary>
864 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
865 /// </summary>
866 /// <param name="xferManager"></param>
867 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
868 {
869 lock (m_items)
870 {
871 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
872 // a new script if any previous deletion has left the prim inventory empty.
873 if (m_items.Count == 0) // No inventory
874 {
875// m_log.DebugFormat(
876// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
877// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
878 1109
879 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1110 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
880 return;
881 }
882 1111
883 CreateInventoryFile(); 1112 if (m_inventoryFileData.Length > 2)
884 1113 {
885 // In principle, we should only do the rest if the inventory changed; 1114 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 // by sending m_inventorySerial to the client, it ought to know 1115 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 // that nothing changed and that it doesn't need to request the file. 1116 Util.StringToBytes256(m_inventoryFileName));
888 // Unfortunately, it doesn't look like the client optimizes this; 1117 return;
889 // the client seems to always come back and request the Xfer,
890 // no matter what value m_inventorySerial has.
891 // FIXME: Could probably be > 0 here rather than > 2
892 if (m_inventoryFileData.Length > 2)
893 {
894 // Add the file for Xfer
895 // m_log.DebugFormat(
896 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
897 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
898
899 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
900 }
901
902 // Tell the client we're ready to Xfer the file
903 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
904 Util.StringToBytes256(m_inventoryFileName));
905 } 1118 }
1119
1120 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
906 } 1121 }
907 1122
908 /// <summary> 1123 /// <summary>
@@ -911,13 +1126,19 @@ namespace OpenSim.Region.Framework.Scenes
911 /// <param name="datastore"></param> 1126 /// <param name="datastore"></param>
912 public void ProcessInventoryBackup(ISimulationDataService datastore) 1127 public void ProcessInventoryBackup(ISimulationDataService datastore)
913 { 1128 {
914 if (HasInventoryChanged) 1129// Removed this because linking will cause an immediate delete of the new
915 { 1130// child prim from the database and the subsequent storing of the prim sees
916 HasInventoryChanged = false; 1131// the inventory of it as unchanged and doesn't store it at all. The overhead
917 List<TaskInventoryItem> items = GetInventoryItems(); 1132// of storing prim inventory needlessly is much less than the aggravation
918 datastore.StorePrimInventory(m_part.UUID, items); 1133// of prim inventory loss.
1134// if (HasInventoryChanged)
1135// {
1136 Items.LockItemsForRead(true);
1137 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1138 Items.LockItemsForRead(false);
919 1139
920 } 1140 HasInventoryChanged = false;
1141// }
921 } 1142 }
922 1143
923 public class InventoryStringBuilder 1144 public class InventoryStringBuilder
@@ -983,82 +1204,63 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1204 {
984 uint mask=0x7fffffff; 1205 uint mask=0x7fffffff;
985 1206
986 lock (m_items) 1207 foreach (TaskInventoryItem item in m_items.Values)
987 { 1208 {
988 foreach (TaskInventoryItem item in m_items.Values) 1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1210 mask &= ~((uint)PermissionMask.Copy >> 13);
1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1212 mask &= ~((uint)PermissionMask.Transfer >> 13);
1213 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1214 mask &= ~((uint)PermissionMask.Modify >> 13);
1215
1216 if (item.InvType == (int)InventoryType.Object)
989 { 1217 {
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Copy >> 13); 1219 mask &= ~((uint)PermissionMask.Copy >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Transfer >> 13); 1221 mask &= ~((uint)PermissionMask.Transfer >> 13);
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1222 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Modify >> 13); 1223 mask &= ~((uint)PermissionMask.Modify >> 13);
996
997 if (item.InvType != (int)InventoryType.Object)
998 {
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1000 mask &= ~((uint)PermissionMask.Copy >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1002 mask &= ~((uint)PermissionMask.Transfer >> 13);
1003 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1004 mask &= ~((uint)PermissionMask.Modify >> 13);
1005 }
1006 else
1007 {
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Copy >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Transfer >> 13);
1012 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1013 mask &= ~((uint)PermissionMask.Modify >> 13);
1014 }
1015
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1017 mask &= ~(uint)PermissionMask.Copy;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1019 mask &= ~(uint)PermissionMask.Transfer;
1020 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1021 mask &= ~(uint)PermissionMask.Modify;
1022 } 1224 }
1225
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1227 mask &= ~(uint)PermissionMask.Copy;
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1229 mask &= ~(uint)PermissionMask.Transfer;
1230 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1231 mask &= ~(uint)PermissionMask.Modify;
1023 } 1232 }
1024
1025 return mask; 1233 return mask;
1026 } 1234 }
1027 1235
1028 public void ApplyNextOwnerPermissions() 1236 public void ApplyNextOwnerPermissions()
1029 { 1237 {
1030 lock (m_items) 1238 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1239 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1240 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1033 { 1241 {
1034 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1035 { 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1246 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1247 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1041 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1042 }
1043 item.CurrentPermissions &= item.NextPermissions;
1044 item.BasePermissions &= item.NextPermissions;
1045 item.EveryonePermissions &= item.NextPermissions;
1046 item.OwnerChanged = true;
1047 item.PermsMask = 0;
1048 item.PermsGranter = UUID.Zero;
1049 } 1248 }
1249 item.OwnerChanged = true;
1250 item.CurrentPermissions &= item.NextPermissions;
1251 item.BasePermissions &= item.NextPermissions;
1252 item.EveryonePermissions &= item.NextPermissions;
1253 item.PermsMask = 0;
1254 item.PermsGranter = UUID.Zero;
1050 } 1255 }
1051 } 1256 }
1052 1257
1053 public void ApplyGodPermissions(uint perms) 1258 public void ApplyGodPermissions(uint perms)
1054 { 1259 {
1055 lock (m_items) 1260 foreach (TaskInventoryItem item in m_items.Values)
1056 { 1261 {
1057 foreach (TaskInventoryItem item in m_items.Values) 1262 item.CurrentPermissions = perms;
1058 { 1263 item.BasePermissions = perms;
1059 item.CurrentPermissions = perms;
1060 item.BasePermissions = perms;
1061 }
1062 } 1264 }
1063 1265
1064 m_inventorySerial++; 1266 m_inventorySerial++;
@@ -1071,17 +1273,13 @@ namespace OpenSim.Region.Framework.Scenes
1071 /// <returns></returns> 1273 /// <returns></returns>
1072 public bool ContainsScripts() 1274 public bool ContainsScripts()
1073 { 1275 {
1074 lock (m_items) 1276 foreach (TaskInventoryItem item in m_items.Values)
1075 { 1277 {
1076 foreach (TaskInventoryItem item in m_items.Values) 1278 if (item.InvType == (int)InventoryType.LSL)
1077 { 1279 {
1078 if (item.InvType == (int)InventoryType.LSL) 1280 return true;
1079 {
1080 return true;
1081 }
1082 } 1281 }
1083 } 1282 }
1084
1085 return false; 1283 return false;
1086 } 1284 }
1087 1285
@@ -1089,11 +1287,8 @@ namespace OpenSim.Region.Framework.Scenes
1089 { 1287 {
1090 List<UUID> ret = new List<UUID>(); 1288 List<UUID> ret = new List<UUID>();
1091 1289
1092 lock (m_items) 1290 foreach (TaskInventoryItem item in m_items.Values)
1093 { 1291 ret.Add(item.ItemID);
1094 foreach (TaskInventoryItem item in m_items.Values)
1095 ret.Add(item.ItemID);
1096 }
1097 1292
1098 return ret; 1293 return ret;
1099 } 1294 }
@@ -1124,6 +1319,11 @@ namespace OpenSim.Region.Framework.Scenes
1124 1319
1125 public Dictionary<UUID, string> GetScriptStates() 1320 public Dictionary<UUID, string> GetScriptStates()
1126 { 1321 {
1322 return GetScriptStates(false);
1323 }
1324
1325 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1326 {
1127 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1327 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1128 1328
1129 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1329 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1134,25 +1334,35 @@ namespace OpenSim.Region.Framework.Scenes
1134 if (engines.Length == 0) // No engine at all 1334 if (engines.Length == 0) // No engine at all
1135 return ret; 1335 return ret;
1136 1336
1137 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1337 Items.LockItemsForRead(true);
1138 1338 foreach (TaskInventoryItem item in m_items.Values)
1139 foreach (TaskInventoryItem item in scripts)
1140 { 1339 {
1141 foreach (IScriptModule e in engines) 1340 if (item.InvType == (int)InventoryType.LSL)
1142 { 1341 {
1143 if (e != null) 1342 foreach (IScriptModule e in engines)
1144 { 1343 {
1145 string n = e.GetXMLState(item.ItemID); 1344 if (e != null)
1146 if (n != String.Empty)
1147 { 1345 {
1148 if (!ret.ContainsKey(item.ItemID)) 1346 string n = e.GetXMLState(item.ItemID);
1149 ret[item.ItemID] = n; 1347 if (n != String.Empty)
1150 break; 1348 {
1349 if (oldIDs)
1350 {
1351 if (!ret.ContainsKey(item.OldItemID))
1352 ret[item.OldItemID] = n;
1353 }
1354 else
1355 {
1356 if (!ret.ContainsKey(item.ItemID))
1357 ret[item.ItemID] = n;
1358 }
1359 break;
1360 }
1151 } 1361 }
1152 } 1362 }
1153 } 1363 }
1154 } 1364 }
1155 1365 Items.LockItemsForRead(false);
1156 return ret; 1366 return ret;
1157 } 1367 }
1158 1368
@@ -1162,21 +1372,27 @@ namespace OpenSim.Region.Framework.Scenes
1162 if (engines.Length == 0) 1372 if (engines.Length == 0)
1163 return; 1373 return;
1164 1374
1165 List<TaskInventoryItem> scripts = GetInventoryScripts();
1166 1375
1167 foreach (TaskInventoryItem item in scripts) 1376 Items.LockItemsForRead(true);
1377
1378 foreach (TaskInventoryItem item in m_items.Values)
1168 { 1379 {
1169 foreach (IScriptModule engine in engines) 1380 if (item.InvType == (int)InventoryType.LSL)
1170 { 1381 {
1171 if (engine != null) 1382 foreach (IScriptModule engine in engines)
1172 { 1383 {
1173 if (item.OwnerChanged) 1384 if (engine != null)
1174 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1385 {
1175 item.OwnerChanged = false; 1386 if (item.OwnerChanged)
1176 engine.ResumeScript(item.ItemID); 1387 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1388 item.OwnerChanged = false;
1389 engine.ResumeScript(item.ItemID);
1390 }
1177 } 1391 }
1178 } 1392 }
1179 } 1393 }
1394
1395 Items.LockItemsForRead(false);
1180 } 1396 }
1181 } 1397 }
1182} 1398}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 40c8d06..06da741 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes
91 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 91 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
92 /// issue #1716 92 /// issue #1716
93 /// </summary> 93 /// </summary>
94 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 94 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
95 95
96 /// <summary> 96 /// <summary>
97 /// Movement updates for agents in neighboring regions are sent directly to clients. 97 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -168,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes
168// private int m_lastColCount = -1; //KF: Look for Collision chnages 168// private int m_lastColCount = -1; //KF: Look for Collision chnages
169// private int m_updateCount = 0; //KF: Update Anims for a while 169// private int m_updateCount = 0; //KF: Update Anims for a while
170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
171 private List<uint> m_lastColliders = new List<uint>();
171 172
172 private TeleportFlags m_teleportFlags; 173 private TeleportFlags m_teleportFlags;
173 public TeleportFlags TeleportFlags 174 public TeleportFlags TeleportFlags
@@ -229,6 +230,11 @@ namespace OpenSim.Region.Framework.Scenes
229 //private int m_moveToPositionStateStatus; 230 //private int m_moveToPositionStateStatus;
230 //***************************************************** 231 //*****************************************************
231 232
233 private bool m_collisionEventFlag = false;
234 private object m_collisionEventLock = new Object();
235
236 private Vector3 m_prevSitOffset;
237
232 protected AvatarAppearance m_appearance; 238 protected AvatarAppearance m_appearance;
233 239
234 public AvatarAppearance Appearance 240 public AvatarAppearance Appearance
@@ -640,6 +646,13 @@ namespace OpenSim.Region.Framework.Scenes
640 } 646 }
641 private uint m_parentID; 647 private uint m_parentID;
642 648
649 public UUID ParentUUID
650 {
651 get { return m_parentUUID; }
652 set { m_parentUUID = value; }
653 }
654 private UUID m_parentUUID = UUID.Zero;
655
643 public float Health 656 public float Health
644 { 657 {
645 get { return m_health; } 658 get { return m_health; }
@@ -861,10 +874,37 @@ namespace OpenSim.Region.Framework.Scenes
861 "[SCENE]: Upgrading child to root agent for {0} in {1}", 874 "[SCENE]: Upgrading child to root agent for {0} in {1}",
862 Name, m_scene.RegionInfo.RegionName); 875 Name, m_scene.RegionInfo.RegionName);
863 876
864 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
865
866 bool wasChild = IsChildAgent; 877 bool wasChild = IsChildAgent;
867 IsChildAgent = false; 878
879 if (ParentUUID != UUID.Zero)
880 {
881 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
882 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
883 if (part == null)
884 {
885 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
886 }
887 else
888 {
889 part.ParentGroup.AddAvatar(UUID);
890 if (part.SitTargetPosition != Vector3.Zero)
891 part.SitTargetAvatar = UUID;
892 ParentPosition = part.GetWorldPosition();
893 ParentID = part.LocalId;
894 m_pos = m_prevSitOffset;
895 pos = ParentPosition;
896 }
897 ParentUUID = UUID.Zero;
898
899 IsChildAgent = false;
900
901 Animator.TrySetMovementAnimation("SIT");
902 }
903 else
904 {
905 IsChildAgent = false;
906 }
907
868 908
869 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 909 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
870 if (gm != null) 910 if (gm != null)
@@ -874,62 +914,64 @@ namespace OpenSim.Region.Framework.Scenes
874 914
875 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 915 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
876 916
877 // Moved this from SendInitialData to ensure that Appearance is initialized 917 if (ParentID == 0)
878 // before the inventory is processed in MakeRootAgent. This fixes a race condition
879 // related to the handling of attachments
880 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
881 if (m_scene.TestBorderCross(pos, Cardinals.E))
882 { 918 {
883 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 919 // Moved this from SendInitialData to ensure that Appearance is initialized
884 pos.X = crossedBorder.BorderLine.Z - 1; 920 // before the inventory is processed in MakeRootAgent. This fixes a race condition
885 } 921 // related to the handling of attachments
922 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
923 if (m_scene.TestBorderCross(pos, Cardinals.E))
924 {
925 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
926 pos.X = crossedBorder.BorderLine.Z - 1;
927 }
886 928
887 if (m_scene.TestBorderCross(pos, Cardinals.N)) 929 if (m_scene.TestBorderCross(pos, Cardinals.N))
888 { 930 {
889 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 931 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
890 pos.Y = crossedBorder.BorderLine.Z - 1; 932 pos.Y = crossedBorder.BorderLine.Z - 1;
891 } 933 }
892 934
893 CheckAndAdjustLandingPoint(ref pos); 935 CheckAndAdjustLandingPoint(ref pos);
894 936
895 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 937 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
896 { 938 {
897 m_log.WarnFormat( 939 m_log.WarnFormat(
898 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 940 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
899 pos, Name, UUID); 941 pos, Name, UUID);
900 942
901 if (pos.X < 0f) pos.X = 0f; 943 if (pos.X < 0f) pos.X = 0f;
902 if (pos.Y < 0f) pos.Y = 0f; 944 if (pos.Y < 0f) pos.Y = 0f;
903 if (pos.Z < 0f) pos.Z = 0f; 945 if (pos.Z < 0f) pos.Z = 0f;
904 } 946 }
905 947
906 float localAVHeight = 1.56f; 948 float localAVHeight = 1.56f;
907 if (Appearance.AvatarHeight > 0) 949 if (Appearance.AvatarHeight > 0)
908 localAVHeight = Appearance.AvatarHeight; 950 localAVHeight = Appearance.AvatarHeight;
909 951
910 float posZLimit = 0; 952 float posZLimit = 0;
911 953
912 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 954 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
913 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 955 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
914 956
915 float newPosZ = posZLimit + localAVHeight / 2; 957 float newPosZ = posZLimit + localAVHeight / 2;
916 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 958 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
917 { 959 {
918 pos.Z = newPosZ; 960 pos.Z = newPosZ;
919 } 961 }
920 AbsolutePosition = pos; 962 AbsolutePosition = pos;
921 963
922 AddToPhysicalScene(isFlying); 964 AddToPhysicalScene(isFlying);
923 965
924 if (ForceFly) 966 if (ForceFly)
925 { 967 {
926 Flying = true; 968 Flying = true;
927 } 969 }
928 else if (FlyDisabled) 970 else if (FlyDisabled)
929 { 971 {
930 Flying = false; 972 Flying = false;
973 }
931 } 974 }
932
933 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 975 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
934 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 976 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
935 // elsewhere anyway 977 // elsewhere anyway
@@ -947,14 +989,19 @@ namespace OpenSim.Region.Framework.Scenes
947 { 989 {
948 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 990 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
949 // Resume scripts 991 // Resume scripts
950 foreach (SceneObjectGroup sog in m_attachments) 992 Util.FireAndForget(delegate(object x) {
951 { 993 foreach (SceneObjectGroup sog in m_attachments)
952 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 994 {
953 sog.ResumeScripts(); 995 sog.ScheduleGroupForFullUpdate();
954 } 996 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
997 sog.ResumeScripts();
998 }
999 });
955 } 1000 }
956 } 1001 }
957 1002
1003 SendAvatarDataToAllAgents();
1004
958 // send the animations of the other presences to me 1005 // send the animations of the other presences to me
959 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 1006 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
960 { 1007 {
@@ -1048,7 +1095,7 @@ namespace OpenSim.Region.Framework.Scenes
1048 } 1095 }
1049 1096
1050 /// <summary> 1097 /// <summary>
1051 /// Do not call this directly. Call Scene.RequestTeleportLocation() instead. 1098 ///
1052 /// </summary> 1099 /// </summary>
1053 /// <param name="pos"></param> 1100 /// <param name="pos"></param>
1054 public void Teleport(Vector3 pos) 1101 public void Teleport(Vector3 pos)
@@ -1522,10 +1569,7 @@ namespace OpenSim.Region.Framework.Scenes
1522 } 1569 }
1523 else if (bAllowUpdateMoveToPosition) 1570 else if (bAllowUpdateMoveToPosition)
1524 { 1571 {
1525 // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a 1572 if (HandleMoveToTargetUpdate(ref agent_control_v3))
1526 // certain position. It's only check for tolerance on returning to that position is 0.2
1527 // rather than 1, at which point it removes its force target.
1528 if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3))
1529 update_movementflag = true; 1573 update_movementflag = true;
1530 } 1574 }
1531 } 1575 }
@@ -1587,7 +1631,7 @@ namespace OpenSim.Region.Framework.Scenes
1587 /// </remarks> 1631 /// </remarks>
1588 /// <param value="agent_control_v3">Cumulative agent movement that this method will update.</param> 1632 /// <param value="agent_control_v3">Cumulative agent movement that this method will update.</param>
1589 /// <returns>True if movement has been updated in some way. False otherwise.</returns> 1633 /// <returns>True if movement has been updated in some way. False otherwise.</returns>
1590 public bool HandleMoveToTargetUpdate(double tolerance, ref Vector3 agent_control_v3) 1634 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3)
1591 { 1635 {
1592// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); 1636// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name);
1593 1637
@@ -1604,7 +1648,7 @@ namespace OpenSim.Region.Framework.Scenes
1604// Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); 1648// Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget);
1605 1649
1606 // Check the error term of the current position in relation to the target position 1650 // Check the error term of the current position in relation to the target position
1607 if (distanceToTarget <= tolerance) 1651 if (distanceToTarget <= 1)
1608 { 1652 {
1609 // We are close enough to the target 1653 // We are close enough to the target
1610 AbsolutePosition = MoveToPositionTarget; 1654 AbsolutePosition = MoveToPositionTarget;
@@ -1751,9 +1795,9 @@ namespace OpenSim.Region.Framework.Scenes
1751 if (pos.Z - terrainHeight < 0.2) 1795 if (pos.Z - terrainHeight < 0.2)
1752 pos.Z = terrainHeight; 1796 pos.Z = terrainHeight;
1753 1797
1754 m_log.DebugFormat( 1798// m_log.DebugFormat(
1755 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1799// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1756 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1800// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1757 1801
1758 if (noFly) 1802 if (noFly)
1759 Flying = false; 1803 Flying = false;
@@ -1780,7 +1824,7 @@ namespace OpenSim.Region.Framework.Scenes
1780// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation); 1824// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation);
1781 1825
1782 Vector3 agent_control_v3 = new Vector3(); 1826 Vector3 agent_control_v3 = new Vector3();
1783 HandleMoveToTargetUpdate(1, ref agent_control_v3); 1827 HandleMoveToTargetUpdate(ref agent_control_v3);
1784 AddNewMovement(agent_control_v3); 1828 AddNewMovement(agent_control_v3);
1785 } 1829 }
1786 1830
@@ -1810,8 +1854,11 @@ namespace OpenSim.Region.Framework.Scenes
1810// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1854// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1811 1855
1812 SitGround = false; 1856 SitGround = false;
1857
1858/* move this down so avatar gets physical in the new position and not where it is siting
1813 if (PhysicsActor == null) 1859 if (PhysicsActor == null)
1814 AddToPhysicalScene(false); 1860 AddToPhysicalScene(false);
1861 */
1815 1862
1816 if (ParentID != 0) 1863 if (ParentID != 0)
1817 { 1864 {
@@ -1837,6 +1884,7 @@ namespace OpenSim.Region.Framework.Scenes
1837 if (part.SitTargetAvatar == UUID) 1884 if (part.SitTargetAvatar == UUID)
1838 part.SitTargetAvatar = UUID.Zero; 1885 part.SitTargetAvatar = UUID.Zero;
1839 1886
1887 part.ParentGroup.DeleteAvatar(UUID);
1840 ParentPosition = part.GetWorldPosition(); 1888 ParentPosition = part.GetWorldPosition();
1841 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1889 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1842 } 1890 }
@@ -1845,6 +1893,10 @@ namespace OpenSim.Region.Framework.Scenes
1845 ParentPosition = Vector3.Zero; 1893 ParentPosition = Vector3.Zero;
1846 1894
1847 ParentID = 0; 1895 ParentID = 0;
1896
1897 if (PhysicsActor == null)
1898 AddToPhysicalScene(false);
1899
1848 SendAvatarDataToAllAgents(); 1900 SendAvatarDataToAllAgents();
1849 m_requestedSitTargetID = 0; 1901 m_requestedSitTargetID = 0;
1850 1902
@@ -1852,6 +1904,9 @@ namespace OpenSim.Region.Framework.Scenes
1852 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1904 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1853 } 1905 }
1854 1906
1907 else if (PhysicsActor == null)
1908 AddToPhysicalScene(false);
1909
1855 Animator.TrySetMovementAnimation("STAND"); 1910 Animator.TrySetMovementAnimation("STAND");
1856 } 1911 }
1857 1912
@@ -1975,7 +2030,7 @@ namespace OpenSim.Region.Framework.Scenes
1975 forceMouselook = part.GetForceMouselook(); 2030 forceMouselook = part.GetForceMouselook();
1976 2031
1977 ControllingClient.SendSitResponse( 2032 ControllingClient.SendSitResponse(
1978 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2033 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1979 2034
1980 m_requestedSitTargetUUID = targetID; 2035 m_requestedSitTargetUUID = targetID;
1981 2036
@@ -2257,14 +2312,36 @@ namespace OpenSim.Region.Framework.Scenes
2257 2312
2258 //Quaternion result = (sitTargetOrient * vq) * nq; 2313 //Quaternion result = (sitTargetOrient * vq) * nq;
2259 2314
2260 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2315 double x, y, z, m;
2316
2317 Quaternion r = sitTargetOrient;
2318 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2319
2320 if (Math.Abs(1.0 - m) > 0.000001)
2321 {
2322 m = 1.0 / Math.Sqrt(m);
2323 r.X *= (float)m;
2324 r.Y *= (float)m;
2325 r.Z *= (float)m;
2326 r.W *= (float)m;
2327 }
2328
2329 x = 2 * (r.X * r.Z + r.Y * r.W);
2330 y = 2 * (-r.X * r.W + r.Y * r.Z);
2331 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2332
2333 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2334 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2335 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2261 Rotation = sitTargetOrient; 2336 Rotation = sitTargetOrient;
2262 ParentPosition = part.AbsolutePosition; 2337 ParentPosition = part.AbsolutePosition;
2338 part.ParentGroup.AddAvatar(UUID);
2263 } 2339 }
2264 else 2340 else
2265 { 2341 {
2266 m_pos -= part.AbsolutePosition; 2342 m_pos -= part.AbsolutePosition;
2267 ParentPosition = part.AbsolutePosition; 2343 ParentPosition = part.AbsolutePosition;
2344 part.ParentGroup.AddAvatar(UUID);
2268 2345
2269// m_log.DebugFormat( 2346// m_log.DebugFormat(
2270// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2347// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3106,6 +3183,9 @@ namespace OpenSim.Region.Framework.Scenes
3106 cAgent.AlwaysRun = SetAlwaysRun; 3183 cAgent.AlwaysRun = SetAlwaysRun;
3107 3184
3108 cAgent.Appearance = new AvatarAppearance(Appearance); 3185 cAgent.Appearance = new AvatarAppearance(Appearance);
3186
3187 cAgent.ParentPart = ParentUUID;
3188 cAgent.SitOffset = m_pos;
3109 3189
3110 lock (scriptedcontrols) 3190 lock (scriptedcontrols)
3111 { 3191 {
@@ -3165,6 +3245,8 @@ namespace OpenSim.Region.Framework.Scenes
3165 CameraAtAxis = cAgent.AtAxis; 3245 CameraAtAxis = cAgent.AtAxis;
3166 CameraLeftAxis = cAgent.LeftAxis; 3246 CameraLeftAxis = cAgent.LeftAxis;
3167 m_CameraUpAxis = cAgent.UpAxis; 3247 m_CameraUpAxis = cAgent.UpAxis;
3248 ParentUUID = cAgent.ParentPart;
3249 m_prevSitOffset = cAgent.SitOffset;
3168 3250
3169 // When we get to the point of re-computing neighbors everytime this 3251 // When we get to the point of re-computing neighbors everytime this
3170 // changes, then start using the agent's drawdistance rather than the 3252 // changes, then start using the agent's drawdistance rather than the
@@ -3371,6 +3453,8 @@ namespace OpenSim.Region.Framework.Scenes
3371 } 3453 }
3372 } 3454 }
3373 3455
3456 RaiseCollisionScriptEvents(coldata);
3457
3374 if (Invulnerable) 3458 if (Invulnerable)
3375 return; 3459 return;
3376 3460
@@ -3882,6 +3966,12 @@ namespace OpenSim.Region.Framework.Scenes
3882 3966
3883 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3967 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3884 { 3968 {
3969 string reason;
3970
3971 // Honor bans
3972 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3973 return;
3974
3885 SceneObjectGroup telehub = null; 3975 SceneObjectGroup telehub = null;
3886 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3976 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3887 { 3977 {
@@ -3921,11 +4011,173 @@ namespace OpenSim.Region.Framework.Scenes
3921 pos = land.LandData.UserLocation; 4011 pos = land.LandData.UserLocation;
3922 } 4012 }
3923 } 4013 }
3924 4014
3925 land.SendLandUpdateToClient(ControllingClient); 4015 land.SendLandUpdateToClient(ControllingClient);
3926 } 4016 }
3927 } 4017 }
3928 4018
4019 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
4020 {
4021 lock(m_collisionEventLock)
4022 {
4023 if (m_collisionEventFlag)
4024 return;
4025 m_collisionEventFlag = true;
4026 }
4027
4028 Util.FireAndForget(delegate(object x)
4029 {
4030 try
4031 {
4032 List<uint> thisHitColliders = new List<uint>();
4033 List<uint> endedColliders = new List<uint>();
4034 List<uint> startedColliders = new List<uint>();
4035
4036 foreach (uint localid in coldata.Keys)
4037 {
4038 thisHitColliders.Add(localid);
4039 if (!m_lastColliders.Contains(localid))
4040 {
4041 startedColliders.Add(localid);
4042 }
4043 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
4044 }
4045
4046 // calculate things that ended colliding
4047 foreach (uint localID in m_lastColliders)
4048 {
4049 if (!thisHitColliders.Contains(localID))
4050 {
4051 endedColliders.Add(localID);
4052 }
4053 }
4054 //add the items that started colliding this time to the last colliders list.
4055 foreach (uint localID in startedColliders)
4056 {
4057 m_lastColliders.Add(localID);
4058 }
4059 // remove things that ended colliding from the last colliders list
4060 foreach (uint localID in endedColliders)
4061 {
4062 m_lastColliders.Remove(localID);
4063 }
4064
4065 // do event notification
4066 if (startedColliders.Count > 0)
4067 {
4068 ColliderArgs StartCollidingMessage = new ColliderArgs();
4069 List<DetectedObject> colliding = new List<DetectedObject>();
4070 foreach (uint localId in startedColliders)
4071 {
4072 if (localId == 0)
4073 continue;
4074
4075 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4076 string data = "";
4077 if (obj != null)
4078 {
4079 DetectedObject detobj = new DetectedObject();
4080 detobj.keyUUID = obj.UUID;
4081 detobj.nameStr = obj.Name;
4082 detobj.ownerUUID = obj.OwnerID;
4083 detobj.posVector = obj.AbsolutePosition;
4084 detobj.rotQuat = obj.GetWorldRotation();
4085 detobj.velVector = obj.Velocity;
4086 detobj.colliderType = 0;
4087 detobj.groupUUID = obj.GroupID;
4088 colliding.Add(detobj);
4089 }
4090 }
4091
4092 if (colliding.Count > 0)
4093 {
4094 StartCollidingMessage.Colliders = colliding;
4095
4096 foreach (SceneObjectGroup att in GetAttachments())
4097 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4098 }
4099 }
4100
4101 if (endedColliders.Count > 0)
4102 {
4103 ColliderArgs EndCollidingMessage = new ColliderArgs();
4104 List<DetectedObject> colliding = new List<DetectedObject>();
4105 foreach (uint localId in endedColliders)
4106 {
4107 if (localId == 0)
4108 continue;
4109
4110 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4111 string data = "";
4112 if (obj != null)
4113 {
4114 DetectedObject detobj = new DetectedObject();
4115 detobj.keyUUID = obj.UUID;
4116 detobj.nameStr = obj.Name;
4117 detobj.ownerUUID = obj.OwnerID;
4118 detobj.posVector = obj.AbsolutePosition;
4119 detobj.rotQuat = obj.GetWorldRotation();
4120 detobj.velVector = obj.Velocity;
4121 detobj.colliderType = 0;
4122 detobj.groupUUID = obj.GroupID;
4123 colliding.Add(detobj);
4124 }
4125 }
4126
4127 if (colliding.Count > 0)
4128 {
4129 EndCollidingMessage.Colliders = colliding;
4130
4131 foreach (SceneObjectGroup att in GetAttachments())
4132 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4133 }
4134 }
4135
4136 if (thisHitColliders.Count > 0)
4137 {
4138 ColliderArgs CollidingMessage = new ColliderArgs();
4139 List<DetectedObject> colliding = new List<DetectedObject>();
4140 foreach (uint localId in thisHitColliders)
4141 {
4142 if (localId == 0)
4143 continue;
4144
4145 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4146 string data = "";
4147 if (obj != null)
4148 {
4149 DetectedObject detobj = new DetectedObject();
4150 detobj.keyUUID = obj.UUID;
4151 detobj.nameStr = obj.Name;
4152 detobj.ownerUUID = obj.OwnerID;
4153 detobj.posVector = obj.AbsolutePosition;
4154 detobj.rotQuat = obj.GetWorldRotation();
4155 detobj.velVector = obj.Velocity;
4156 detobj.colliderType = 0;
4157 detobj.groupUUID = obj.GroupID;
4158 colliding.Add(detobj);
4159 }
4160 }
4161
4162 if (colliding.Count > 0)
4163 {
4164 CollidingMessage.Colliders = colliding;
4165
4166 lock (m_attachments)
4167 {
4168 foreach (SceneObjectGroup att in m_attachments)
4169 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4170 }
4171 }
4172 }
4173 }
4174 finally
4175 {
4176 m_collisionEventFlag = false;
4177 }
4178 });
4179 }
4180
3929 private void TeleportFlagsDebug() { 4181 private void TeleportFlagsDebug() {
3930 4182
3931 // Some temporary debugging help to show all the TeleportFlags we have... 4183 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3950,6 +4202,5 @@ namespace OpenSim.Region.Framework.Scenes
3950 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4202 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3951 4203
3952 } 4204 }
3953
3954 } 4205 }
3955} 4206}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e6b88a3..72a0ec3 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -347,6 +347,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
347 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 347 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
348 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 348 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
349 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 349 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
350
351 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
352 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
353
354 //Ubit comented until proper testing
355 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
356
357
350 #endregion 358 #endregion
351 359
352 #region TaskInventoryXmlProcessors initialization 360 #region TaskInventoryXmlProcessors initialization
@@ -569,6 +577,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
569 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 577 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
570 } 578 }
571 579
580 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
581 {
582 bool errors = false;
583 SOPVehicle _vehicle = new SOPVehicle();
584
585 _vehicle.FromXml2(reader, out errors);
586
587 if (errors)
588 {
589 obj.sopVehicle = null;
590 m_log.DebugFormat(
591 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
592 obj.Name, obj.UUID);
593 }
594 else
595 obj.sopVehicle = _vehicle;
596 }
597
598
572 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 599 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
573 { 600 {
574 List<string> errorNodeNames; 601 List<string> errorNodeNames;
@@ -733,6 +760,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
733 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 760 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
734 } 761 }
735 762
763 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
764 {
765 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
766 }
767
768 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
769 {
770 obj.VolumeDetectActive = Util.ReadBoolean(reader);
771 }
772
736 #endregion 773 #endregion
737 774
738 #region TaskInventoryXmlProcessors 775 #region TaskInventoryXmlProcessors
@@ -1218,6 +1255,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1218 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1255 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1219 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1256 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1220 1257
1258 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1259 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1260
1261 //Ubit comented until proper testing
1262 if (sop.sopVehicle != null)
1263 sop.sopVehicle.ToXml2(writer);
1264
1221 writer.WriteEndElement(); 1265 writer.WriteEndElement();
1222 } 1266 }
1223 1267
@@ -1487,12 +1531,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1487 { 1531 {
1488 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1532 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1489 1533
1490 if (reader.IsEmptyElement)
1491 {
1492 reader.Read();
1493 return tinv;
1494 }
1495
1496 reader.ReadStartElement(name, String.Empty); 1534 reader.ReadStartElement(name, String.Empty);
1497 1535
1498 while (reader.Name == "TaskInventoryItem") 1536 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..5ed3c79 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,12 +30,27 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 54
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
@@ -57,37 +72,37 @@ namespace OpenSim.Region.Framework.Scenes
57 { 72 {
58 ForGroup = forGroup; 73 ForGroup = forGroup;
59 74
60// if (ForGroup) 75 // if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition; 76 Position = part.ParentGroup.AbsolutePosition;
62// else 77 // else
63// Position = part.OffsetPosition; 78 // Position = part.OffsetPosition;
64 79
65// m_log.DebugFormat( 80 // m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position); 81 // "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 82
68 Rotation = part.RotationOffset; 83 Rotation = part.RotationOffset;
69 84
70// m_log.DebugFormat( 85 // m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 86 // "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72 87
73 Scale = part.Shape.Scale; 88 Scale = part.Shape.Scale;
74 89
75// m_log.DebugFormat( 90 // m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale); 91 // "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 92 }
78 else 93 else
79 { 94 {
80 Position = part.OffsetPosition; 95 Position = part.OffsetPosition;
81// m_log.DebugFormat( 96 // m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 97 // "[UNDO STATE]: Storing undo position {0} for child part", Position);
83 98
84 Rotation = part.RotationOffset; 99 Rotation = part.RotationOffset;
85// m_log.DebugFormat( 100 // m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 101 // "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87 102
88 Scale = part.Shape.Scale; 103 Scale = part.Shape.Scale;
89// m_log.DebugFormat( 104 // m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 105 // "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 106 }
92 } 107 }
93 108
@@ -121,9 +136,9 @@ namespace OpenSim.Region.Framework.Scenes
121 136
122 if (part.ParentID == 0) 137 if (part.ParentID == 0)
123 { 138 {
124// m_log.DebugFormat( 139 // m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}", 140 // "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId); 141 // Position, part.Name, part.LocalId);
127 142
128 if (Position != Vector3.Zero) 143 if (Position != Vector3.Zero)
129 { 144 {
@@ -133,9 +148,9 @@ namespace OpenSim.Region.Framework.Scenes
133 part.ParentGroup.UpdateRootPosition(Position); 148 part.ParentGroup.UpdateRootPosition(Position);
134 } 149 }
135 150
136// m_log.DebugFormat( 151 // m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 152 // "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 153 // part.RotationOffset, Rotation, part.Name, part.LocalId);
139 154
140 if (ForGroup) 155 if (ForGroup)
141 part.UpdateRotation(Rotation); 156 part.UpdateRotation(Rotation);
@@ -144,9 +159,9 @@ namespace OpenSim.Region.Framework.Scenes
144 159
145 if (Scale != Vector3.Zero) 160 if (Scale != Vector3.Zero)
146 { 161 {
147// m_log.DebugFormat( 162 // m_log.DebugFormat(
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 163 // "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
149// part.Shape.Scale, Scale, part.Name, part.LocalId); 164 // part.Shape.Scale, Scale, part.Name, part.LocalId);
150 165
151 if (ForGroup) 166 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale); 167 part.ParentGroup.GroupResize(Scale);
@@ -161,24 +176,24 @@ namespace OpenSim.Region.Framework.Scenes
161 // Note: Updating these properties on sop automatically schedules an update if needed 176 // Note: Updating these properties on sop automatically schedules an update if needed
162 if (Position != Vector3.Zero) 177 if (Position != Vector3.Zero)
163 { 178 {
164// m_log.DebugFormat( 179 // m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}", 180 // "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId); 181 // part.OffsetPosition, Position, part.Name, part.LocalId);
167 182
168 part.OffsetPosition = Position; 183 part.OffsetPosition = Position;
169 } 184 }
170 185
171// m_log.DebugFormat( 186 // m_log.DebugFormat(
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 187 // "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 188 // part.RotationOffset, Rotation, part.Name, part.LocalId);
174 189
175 part.UpdateRotation(Rotation); 190 part.UpdateRotation(Rotation);
176 191
177 if (Scale != Vector3.Zero) 192 if (Scale != Vector3.Zero)
178 { 193 {
179// m_log.DebugFormat( 194 // m_log.DebugFormat(
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 195 // "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
181// part.Shape.Scale, Scale, part.Name, part.LocalId); 196 // part.Shape.Scale, Scale, part.Name, part.LocalId);
182 197
183 part.Resize(Scale); 198 part.Resize(Scale);
184 } 199 }
@@ -247,4 +262,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 262 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 263 }
249 } 264 }
250} \ No newline at end of file 265}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;