aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Scenes
diff options
context:
space:
mode:
authorDr Scofield2009-02-06 16:55:34 +0000
committerDr Scofield2009-02-06 16:55:34 +0000
commit9b66108081a8c8cf79faaa6c541554091c40850e (patch)
tree095a232ae5a9de3a9244bcd34da08294f61eeea5 /OpenSim/Region/Environment/Scenes
parent* removed superfluous constants class (diff)
downloadopensim-SC_OLD-9b66108081a8c8cf79faaa6c541554091c40850e.zip
opensim-SC_OLD-9b66108081a8c8cf79faaa6c541554091c40850e.tar.gz
opensim-SC_OLD-9b66108081a8c8cf79faaa6c541554091c40850e.tar.bz2
opensim-SC_OLD-9b66108081a8c8cf79faaa6c541554091c40850e.tar.xz
This changeset is the step 1 of 2 in refactoring
OpenSim.Region.Environment into a "framework" part and a modules only part. This first changeset refactors OpenSim.Region.Environment.Scenes, OpenSim.Region.Environment.Interfaces, and OpenSim.Region.Interfaces into OpenSim.Region.Framework.{Interfaces,Scenes} leaving only region modules in OpenSim.Region.Environment. The next step will be to move region modules up from OpenSim.Region.Environment.Modules to OpenSim.Region.CoreModules and then sort out which modules are really core modules and which should move out to forge. I've been very careful to NOT BREAK anything. i hope i've succeeded. as this is the work of a whole week i hope i managed to keep track with the applied patches of the last week --- could any of you that did check in stuff have a look at whether it survived? thx!
Diffstat (limited to 'OpenSim/Region/Environment/Scenes')
-rw-r--r--OpenSim/Region/Environment/Scenes/Animation.cs59
-rw-r--r--OpenSim/Region/Environment/Scenes/AnimationSet.cs155
-rw-r--r--OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs165
-rw-r--r--OpenSim/Region/Environment/Scenes/AvatarAnimations.cs63
-rw-r--r--OpenSim/Region/Environment/Scenes/EntityBase.cs253
-rw-r--r--OpenSim/Region/Environment/Scenes/EntityManager.cs279
-rw-r--r--OpenSim/Region/Environment/Scenes/EventManager.cs980
-rw-r--r--OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs376
-rw-r--r--OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.Inventory.cs152
-rw-r--r--OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.cs84
-rw-r--r--OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs363
-rw-r--r--OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs37
-rw-r--r--OpenSim/Region/Environment/Scenes/ReturnInfo.cs39
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.Inventory.cs2665
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs632
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.Permissions.cs1334
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.cs4237
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneBase.cs419
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs1102
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneGraph.cs1811
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneManager.cs669
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs401
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs3012
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs3826
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs892
-rw-r--r--OpenSim/Region/Environment/Scenes/ScenePresence.cs3651
-rw-r--r--OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs46
-rw-r--r--OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs86
-rw-r--r--OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs38
-rw-r--r--OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs119
-rw-r--r--OpenSim/Region/Environment/Scenes/SimStatsReporter.cs450
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs176
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/SceneObjectBasicTests.cs139
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/SceneObjectLinkingTests.cs249
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/ScenePresenceTests.cs292
-rw-r--r--OpenSim/Region/Environment/Scenes/Tests/StandaloneTeleportTests.cs105
-rw-r--r--OpenSim/Region/Environment/Scenes/UndoState.cs116
37 files changed, 0 insertions, 29472 deletions
diff --git a/OpenSim/Region/Environment/Scenes/Animation.cs b/OpenSim/Region/Environment/Scenes/Animation.cs
deleted file mode 100644
index 2854e06..0000000
--- a/OpenSim/Region/Environment/Scenes/Animation.cs
+++ /dev/null
@@ -1,59 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30
31namespace OpenSim.Region.Environment.Scenes
32{
33 public class Animation
34 {
35 private UUID animID;
36 public UUID AnimID
37 {
38 get { return animID; }
39 set { animID = value; }
40 }
41
42 private int sequenceNum;
43 public int SequenceNum
44 {
45 get { return sequenceNum; }
46 set { sequenceNum = value; }
47 }
48
49 public Animation()
50 {
51 }
52
53 public Animation(UUID animID, int sequenceNum)
54 {
55 this.animID = animID;
56 this.sequenceNum = sequenceNum;
57 }
58 }
59}
diff --git a/OpenSim/Region/Environment/Scenes/AnimationSet.cs b/OpenSim/Region/Environment/Scenes/AnimationSet.cs
deleted file mode 100644
index df25173..0000000
--- a/OpenSim/Region/Environment/Scenes/AnimationSet.cs
+++ /dev/null
@@ -1,155 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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;
31
32namespace OpenSim.Region.Environment.Scenes
33{
34 public class AnimationSet
35 {
36 public static AvatarAnimations Animations = new AvatarAnimations();
37
38 private Animation m_defaultAnimation = new Animation();
39 private List<Animation> m_animations = new List<Animation>();
40
41 public Animation DefaultAnimation
42 {
43 get { return m_defaultAnimation; }
44 }
45 public AnimationSet()
46 {
47 ResetDefaultAnimation();
48 }
49
50 public bool HasAnimation(UUID animID)
51 {
52 if (m_defaultAnimation.AnimID == animID)
53 return true;
54
55 for (int i = 0; i < m_animations.Count; ++i)
56 {
57 if (m_animations[i].AnimID == animID)
58 return true;
59 }
60
61 return false;
62 }
63
64 public bool Add(UUID animID, int sequenceNum)
65 {
66 lock (m_animations)
67 {
68 if (!HasAnimation(animID))
69 {
70 m_animations.Add(new Animation(animID, sequenceNum));
71 return true;
72 }
73 }
74 return false;
75 }
76
77 public bool Remove(UUID animID)
78 {
79 lock (m_animations)
80 {
81 if (m_defaultAnimation.AnimID == animID)
82 {
83 ResetDefaultAnimation();
84 }
85 else if (HasAnimation(animID))
86 {
87 for (int i = 0; i < m_animations.Count; i++)
88 {
89 if (m_animations[i].AnimID == animID)
90 {
91 m_animations.RemoveAt(i);
92 return true;
93 }
94 }
95 }
96 }
97 return false;
98 }
99
100 public void Clear()
101 {
102 ResetDefaultAnimation();
103 m_animations.Clear();
104 }
105
106 /// <summary>
107 /// The default animation is reserved for "main" animations
108 /// that are mutually exclusive, e.g. flying and sitting.
109 /// </summary>
110 public bool SetDefaultAnimation(UUID animID, int sequenceNum)
111 {
112 if (m_defaultAnimation.AnimID != animID)
113 {
114 m_defaultAnimation = new Animation(animID, sequenceNum);
115 return true;
116 }
117 return false;
118 }
119
120 protected bool ResetDefaultAnimation()
121 {
122 return TrySetDefaultAnimation("STAND", 1);
123 }
124
125 /// <summary>
126 /// Set the animation as the default animation if it's known
127 /// </summary>
128 public bool TrySetDefaultAnimation(string anim, int sequenceNum)
129 {
130 if (Animations.AnimsUUID.ContainsKey(anim))
131 {
132 return SetDefaultAnimation(Animations.AnimsUUID[anim], sequenceNum);
133 }
134 return false;
135 }
136
137 public void GetArrays(out UUID[] animIDs, out int[] sequenceNums)
138 {
139 lock (m_animations)
140 {
141 animIDs = new UUID[m_animations.Count + 1];
142 sequenceNums = new int[m_animations.Count + 1];
143
144 animIDs[0] = m_defaultAnimation.AnimID;
145 sequenceNums[0] = m_defaultAnimation.SequenceNum;
146
147 for (int i = 0; i < m_animations.Count; ++i)
148 {
149 animIDs[i + 1] = m_animations[i].AnimID;
150 sequenceNums[i + 1] = m_animations[i].SequenceNum;
151 }
152 }
153 }
154 }
155}
diff --git a/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs
deleted file mode 100644
index 1429452..0000000
--- a/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Timers;
32using log4net;
33using OpenMetaverse;
34using OpenMetaverse.Packets;
35using OpenSim.Framework;
36
37namespace OpenSim.Region.Environment.Scenes
38{
39 class DeleteToInventoryHolder
40 {
41 public DeRezAction action;
42 public IClientAPI remoteClient;
43 public SceneObjectGroup objectGroup;
44 public UUID folderID;
45 public bool permissionToDelete;
46 }
47
48 /// <summary>
49 /// Asynchronously derez objects. This is used to derez large number of objects to inventory without holding
50 /// up the main client thread.
51 /// </summary>
52 public class AsyncSceneObjectGroupDeleter
53 {
54 private static readonly ILog m_log
55 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <value>
58 /// Is the deleter currently enabled?
59 /// </value>
60 public bool Enabled;
61
62 private Timer m_inventoryTicker = new Timer(2000);
63 private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>();
64 private Scene m_scene;
65
66 public AsyncSceneObjectGroupDeleter(Scene scene)
67 {
68 m_scene = scene;
69
70 m_inventoryTicker.AutoReset = false;
71 m_inventoryTicker.Elapsed += InventoryRunDeleteTimer;
72 }
73
74 /// <summary>
75 /// Delete the given object from the scene
76 /// </summary>
77 public void DeleteToInventory(DeRezAction action, UUID folderID,
78 SceneObjectGroup objectGroup, IClientAPI remoteClient,
79 bool permissionToDelete)
80 {
81 if (Enabled)
82 m_inventoryTicker.Stop();
83
84 lock (m_inventoryDeletes)
85 {
86 DeleteToInventoryHolder dtis = new DeleteToInventoryHolder();
87 dtis.action = action;
88 dtis.folderID = folderID;
89 dtis.objectGroup = objectGroup;
90 dtis.remoteClient = remoteClient;
91 dtis.permissionToDelete = permissionToDelete;
92
93 m_inventoryDeletes.Enqueue(dtis);
94 }
95
96 if (Enabled)
97 m_inventoryTicker.Start();
98
99 // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object
100 // has gone to inventory, it will reappear in the region again on restart instead of being lost.
101 // This is not ideal since the object will still be available for manipulation when it should be, but it's
102 // better than losing the object for now.
103 if (permissionToDelete)
104 objectGroup.DeleteGroup(false);
105 }
106
107 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
108 {
109 m_log.Debug("[SCENE]: Starting send to inventory loop");
110
111 while (InventoryDeQueueAndDelete())
112 {
113 m_log.Debug("[SCENE]: Sent item successfully to inventory, continuing...");
114 }
115 }
116
117 /// <summary>
118 /// Move the next object in the queue to inventory. Then delete it properly from the scene.
119 /// </summary>
120 /// <returns></returns>
121 public bool InventoryDeQueueAndDelete()
122 {
123 DeleteToInventoryHolder x = null;
124
125 try
126 {
127 lock (m_inventoryDeletes)
128 {
129 int left = m_inventoryDeletes.Count;
130 if (left > 0)
131 {
132 m_log.DebugFormat(
133 "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left);
134
135 x = m_inventoryDeletes.Dequeue();
136
137 try
138 {
139 m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient);
140 if (x.permissionToDelete)
141 m_scene.DeleteSceneObject(x.objectGroup, false);
142 }
143 catch (Exception e)
144 {
145 m_log.DebugFormat("Exception background sending object: " + e);
146 }
147
148 return true;
149 }
150 }
151 }
152 catch (Exception e)
153 {
154 // We can't put the object group details in here since the root part may have disappeared (which is where these sit).
155 // FIXME: This needs to be fixed.
156 m_log.ErrorFormat(
157 "[SCENE]: Queued sending of scene object to agent {0} {1} failed: {2}",
158 (x != null ? x.remoteClient.Name : "unavailable"), (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), e.ToString());
159 }
160
161 m_log.Debug("[SCENE]: No objects left in inventory send queue.");
162 return false;
163 }
164 }
165}
diff --git a/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs b/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs
deleted file mode 100644
index d4dd0db..0000000
--- a/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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.Collections.Generic;
29using System.Xml;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Environment.Scenes
33{
34 public class AvatarAnimations
35 {
36 public Dictionary<string, UUID> AnimsUUID = new Dictionary<string, UUID>();
37 public Dictionary<UUID, string> AnimsNames = new Dictionary<UUID, string>();
38 public Dictionary<UUID, string> AnimStateNames = new Dictionary<UUID, string>();
39
40 public AvatarAnimations()
41 {
42 using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml"))
43 {
44 XmlDocument doc = new XmlDocument();
45 doc.Load(reader);
46 foreach (XmlNode nod in doc.DocumentElement.ChildNodes)
47 {
48 if (nod.Attributes["name"] != null)
49 {
50 string name = (string)nod.Attributes["name"].Value;
51 UUID id = (UUID)nod.InnerText;
52 string animState = (string)nod.Attributes["state"].Value;
53
54 AnimsUUID.Add(name, id);
55 AnimsNames.Add(id, name);
56 if (animState != "")
57 AnimStateNames.Add(id, animState);
58 }
59 }
60 }
61 }
62 }
63}
diff --git a/OpenSim/Region/Environment/Scenes/EntityBase.cs b/OpenSim/Region/Environment/Scenes/EntityBase.cs
deleted file mode 100644
index 3ae8cde..0000000
--- a/OpenSim/Region/Environment/Scenes/EntityBase.cs
+++ /dev/null
@@ -1,253 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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.Runtime.Serialization;
30using System.Security.Permissions;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Environment.Scenes
34{
35 [Serializable]
36 public abstract class EntityBase : ISerializable
37 {
38 /// <summary>
39 /// The scene to which this entity belongs
40 /// </summary>
41 public Scene Scene
42 {
43 get { return m_scene; }
44 }
45 protected Scene m_scene;
46
47 protected UUID m_uuid;
48
49 public virtual UUID UUID
50 {
51 get { return m_uuid; }
52 set { m_uuid = value; }
53 }
54
55 protected string m_name;
56
57 /// <summary>
58 /// The name of this entity
59 /// </summary>
60 public virtual string Name
61 {
62 get { return m_name; }
63 set { m_name = value; }
64 }
65
66 /// <summary>
67 /// Signals whether this entity was in a scene but has since been removed from it.
68 /// </summary>
69 public bool IsDeleted
70 {
71 get { return m_isDeleted; }
72 }
73 protected bool m_isDeleted;
74
75 protected Vector3 m_pos;
76
77 /// <summary>
78 ///
79 /// </summary>
80 public virtual Vector3 AbsolutePosition
81 {
82 get { return m_pos; }
83 set { m_pos = value; }
84 }
85
86 protected Vector3 m_velocity;
87 protected Vector3 m_rotationalvelocity;
88
89 /// <summary>
90 /// Current velocity of the entity.
91 /// </summary>
92 public virtual Vector3 Velocity
93 {
94 get { return m_velocity; }
95 set { m_velocity = value; }
96 }
97
98 protected Quaternion m_rotation = new Quaternion(0f, 0f, 1f, 0f);
99
100 public virtual Quaternion Rotation
101 {
102 get { return m_rotation; }
103 set { m_rotation = value; }
104 }
105
106 protected uint m_localId;
107
108 public virtual uint LocalId
109 {
110 get { return m_localId; }
111 set { m_localId = value; }
112 }
113
114 /// <summary>
115 /// Creates a new Entity (should not occur on it's own)
116 /// </summary>
117 public EntityBase()
118 {
119 m_uuid = UUID.Zero;
120
121 m_pos = Vector3.Zero;
122 m_velocity = Vector3.Zero;
123 Rotation = Quaternion.Identity;
124 m_name = "(basic entity)";
125 m_rotationalvelocity = Vector3.Zero;
126 }
127
128 /// <summary>
129 ///
130 /// </summary>
131 public abstract void UpdateMovement();
132
133 /// <summary>
134 /// Performs any updates that need to be done at each frame, as opposed to immediately.
135 /// These included scheduled updates and updates that occur due to physics processing.
136 /// </summary>
137 public abstract void Update();
138
139 /// <summary>
140 /// Copies the entity
141 /// </summary>
142 /// <returns></returns>
143 public virtual EntityBase Copy()
144 {
145 return (EntityBase) MemberwiseClone();
146 }
147
148
149 public abstract void SetText(string text, Vector3 color, double alpha);
150
151 protected EntityBase(SerializationInfo info, StreamingContext context)
152 {
153 //System.Console.WriteLine("EntityBase Deserialize BGN");
154
155 if (info == null)
156 {
157 throw new ArgumentNullException("info");
158 }
159
160 m_uuid = new UUID((Guid)info.GetValue("m_uuid", typeof(Guid)));
161 m_name = (string)info.GetValue("m_name", typeof(string));
162
163 m_pos
164 = new Vector3(
165 (float)info.GetValue("m_pos.X", typeof(float)),
166 (float)info.GetValue("m_pos.Y", typeof(float)),
167 (float)info.GetValue("m_pos.Z", typeof(float)));
168
169 m_velocity
170 = new Vector3(
171 (float)info.GetValue("m_velocity.X", typeof(float)),
172 (float)info.GetValue("m_velocity.Y", typeof(float)),
173 (float)info.GetValue("m_velocity.Z", typeof(float)));
174
175 m_rotationalvelocity
176 = new Vector3(
177 (float)info.GetValue("m_rotationalvelocity.X", typeof(float)),
178 (float)info.GetValue("m_rotationalvelocity.Y", typeof(float)),
179 (float)info.GetValue("m_rotationalvelocity.Z", typeof(float)));
180
181 m_rotation
182 = new Quaternion(
183 (float)info.GetValue("m_rotation.X", typeof(float)),
184 (float)info.GetValue("m_rotation.Y", typeof(float)),
185 (float)info.GetValue("m_rotation.Z", typeof(float)),
186 (float)info.GetValue("m_rotation.W", typeof(float)));
187
188 m_localId = (uint)info.GetValue("m_localId", typeof(uint));
189
190 //System.Console.WriteLine("EntityBase Deserialize END");
191 }
192
193 [SecurityPermission(SecurityAction.LinkDemand,
194 Flags = SecurityPermissionFlag.SerializationFormatter)]
195 public virtual void GetObjectData(
196 SerializationInfo info, StreamingContext context)
197 {
198 if (info == null)
199 {
200 throw new ArgumentNullException("info");
201 }
202
203 info.AddValue("m_uuid", m_uuid.Guid);
204 info.AddValue("m_name", m_name);
205
206 // Vector3
207 info.AddValue("m_pos.X", m_pos.X);
208 info.AddValue("m_pos.Y", m_pos.Y);
209 info.AddValue("m_pos.Z", m_pos.Z);
210
211 // Vector3
212 info.AddValue("m_velocity.X", m_velocity.X);
213 info.AddValue("m_velocity.Y", m_velocity.Y);
214 info.AddValue("m_velocity.Z", m_velocity.Z);
215
216 // Vector3
217 info.AddValue("m_rotationalvelocity.X", m_rotationalvelocity.X);
218 info.AddValue("m_rotationalvelocity.Y", m_rotationalvelocity.Y);
219 info.AddValue("m_rotationalvelocity.Z", m_rotationalvelocity.Z);
220
221 // Quaternion
222 info.AddValue("m_rotation.X", m_rotation.X);
223 info.AddValue("m_rotation.Y", m_rotation.Y);
224 info.AddValue("m_rotation.Z", m_rotation.Z);
225 info.AddValue("m_rotation.W", m_rotation.W);
226
227 info.AddValue("m_localId", m_localId);
228 }
229 }
230
231 //Nested Classes
232 public class EntityIntersection
233 {
234 public Vector3 ipoint = new Vector3(0, 0, 0);
235 public Vector3 normal = new Vector3(0, 0, 0);
236 public Vector3 AAfaceNormal = new Vector3(0, 0, 0);
237 public int face = -1;
238 public bool HitTF = false;
239 public SceneObjectPart obj;
240 public float distance = 0;
241
242 public EntityIntersection()
243 {
244 }
245
246 public EntityIntersection(Vector3 _ipoint, Vector3 _normal, bool _HitTF)
247 {
248 ipoint = _ipoint;
249 normal = _normal;
250 HitTF = _HitTF;
251 }
252 }
253}
diff --git a/OpenSim/Region/Environment/Scenes/EntityManager.cs b/OpenSim/Region/Environment/Scenes/EntityManager.cs
deleted file mode 100644
index f89d361..0000000
--- a/OpenSim/Region/Environment/Scenes/EntityManager.cs
+++ /dev/null
@@ -1,279 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34
35
36namespace OpenSim.Region.Environment.Scenes
37{
38 public class EntityManager : IEnumerable<EntityBase>
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>();
42 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>();
43 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>();
44 private readonly Object m_lock = new Object();
45
46 [Obsolete("Use Add() instead.")]
47 public void Add(UUID id, EntityBase eb)
48 {
49 Add(eb);
50 }
51
52 public void Add(EntityBase entity)
53 {
54 lock (m_lock)
55 {
56 try
57 {
58 m_eb_uuid.Add(entity.UUID, entity);
59 m_eb_localID.Add(entity.LocalId, entity);
60 }
61 catch(Exception e)
62 {
63 m_log.ErrorFormat("Add Entity failed: {0}", e.Message);
64 }
65 }
66 }
67
68 public void InsertOrReplace(EntityBase entity)
69 {
70 lock (m_lock)
71 {
72 try
73 {
74 m_eb_uuid[entity.UUID] = entity;
75 m_eb_localID[entity.LocalId] = entity;
76 }
77 catch(Exception e)
78 {
79 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message);
80 }
81 }
82 }
83
84 public void Clear()
85 {
86 lock (m_lock)
87 {
88 m_eb_uuid.Clear();
89 m_eb_localID.Clear();
90 }
91 }
92
93 public int Count
94 {
95 get
96 {
97 lock (m_lock)
98 {
99 return m_eb_uuid.Count;
100 }
101 }
102 }
103
104 public bool ContainsKey(UUID id)
105 {
106 lock (m_lock)
107 {
108 try
109 {
110 return m_eb_uuid.ContainsKey(id);
111 }
112 catch
113 {
114 return false;
115 }
116 }
117 }
118
119 public bool ContainsKey(uint localID)
120 {
121 lock (m_lock)
122 {
123 try
124 {
125 return m_eb_localID.ContainsKey(localID);
126 }
127 catch
128 {
129 return false;
130 }
131 }
132 }
133
134 public bool Remove(uint localID)
135 {
136 lock (m_lock)
137 {
138 try
139 {
140 bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID);
141 bool b = m_eb_localID.Remove(localID);
142 return a && b;
143 }
144 catch (Exception e)
145 {
146 m_log.ErrorFormat("Remove Entity failed for {0}", localID, e);
147 return false;
148 }
149 }
150 }
151
152 public bool Remove(UUID id)
153 {
154 lock (m_lock)
155 {
156 try
157 {
158 bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId);
159 bool b = m_eb_uuid.Remove(id);
160 return a && b;
161 }
162 catch (Exception e)
163 {
164 m_log.ErrorFormat("Remove Entity failed for {0}", id, e);
165 return false;
166 }
167 }
168 }
169
170 public List<EntityBase> GetAllByType<T>()
171 {
172 List<EntityBase> tmp = new List<EntityBase>();
173
174 lock (m_lock)
175 {
176 try
177 {
178 foreach (KeyValuePair<UUID, EntityBase> pair in m_eb_uuid)
179 {
180 if (pair.Value is T)
181 {
182 tmp.Add(pair.Value);
183 }
184 }
185 }
186 catch (Exception e)
187 {
188 m_log.ErrorFormat("GetAllByType failed for {0}", e);
189 tmp = null;
190 }
191 }
192
193 return tmp;
194 }
195
196 public List<EntityBase> GetEntities()
197 {
198 lock (m_lock)
199 {
200 return new List<EntityBase>(m_eb_uuid.Values);
201 }
202 }
203
204 public EntityBase this[UUID id]
205 {
206 get
207 {
208 lock (m_lock)
209 {
210 try
211 {
212 return m_eb_uuid[id];
213 }
214 catch
215 {
216 return null;
217 }
218 }
219 }
220 set
221 {
222 InsertOrReplace(value);
223 }
224 }
225
226 public EntityBase this[uint localID]
227 {
228 get
229 {
230 lock (m_lock)
231 {
232 try
233 {
234 return m_eb_localID[localID];
235 }
236 catch
237 {
238 return null;
239 }
240 }
241 }
242 set
243 {
244 InsertOrReplace(value);
245 }
246 }
247
248 public bool TryGetValue(UUID key, out EntityBase obj)
249 {
250 lock (m_lock)
251 {
252 return m_eb_uuid.TryGetValue(key, out obj);
253 }
254 }
255
256 public bool TryGetValue(uint key, out EntityBase obj)
257 {
258 lock (m_lock)
259 {
260 return m_eb_localID.TryGetValue(key, out obj);
261 }
262 }
263
264 /// <summary>
265 /// This could be optimised to work on the list 'live' rather than making a safe copy and iterating that.
266 /// </summary>
267 /// <returns></returns>
268 public IEnumerator<EntityBase> GetEnumerator()
269 {
270 return GetEntities().GetEnumerator();
271 }
272
273 IEnumerator IEnumerable.GetEnumerator()
274 {
275 return GetEnumerator();
276 }
277
278 }
279}
diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs
deleted file mode 100644
index bba7eed..0000000
--- a/OpenSim/Region/Environment/Scenes/EventManager.cs
+++ /dev/null
@@ -1,980 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30using OpenSim.Framework;
31using OpenSim.Framework.Client;
32using OpenSim.Region.Environment.Interfaces;
33using Caps=OpenSim.Framework.Communications.Capabilities.Caps;
34using System.Collections.Generic;
35
36namespace OpenSim.Region.Environment.Scenes
37{
38 /// <summary>
39 /// A class for triggering remote scene events.
40 /// </summary>
41 public class EventManager
42 {
43 public delegate void OnFrameDelegate();
44
45 public event OnFrameDelegate OnFrame;
46
47 public delegate void ClientMovement(ScenePresence client);
48
49 public event ClientMovement OnClientMovement;
50
51 public delegate void OnTerrainTickDelegate();
52
53 public event OnTerrainTickDelegate OnTerrainTick;
54
55 public delegate void OnBackupDelegate(IRegionDataStore datastore, bool forceBackup);
56
57 public event OnBackupDelegate OnBackup;
58
59 public delegate void OnClientConnectCoreDelegate(IClientCore client);
60
61 public event OnClientConnectCoreDelegate OnClientConnect;
62
63 public delegate void OnNewClientDelegate(IClientAPI client);
64
65 /// <summary>
66 /// Depreciated in favour of OnClientConnect.
67 /// Will be marked Obsolete after IClientCore has 100% of IClientAPI interfaces.
68 /// </summary>
69 public event OnNewClientDelegate OnNewClient;
70
71 public delegate void OnNewPresenceDelegate(ScenePresence presence);
72
73 public event OnNewPresenceDelegate OnNewPresence;
74
75 public delegate void OnRemovePresenceDelegate(UUID agentId);
76
77 public event OnRemovePresenceDelegate OnRemovePresence;
78
79 public delegate void OnParcelPrimCountUpdateDelegate();
80
81 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
82
83 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
84
85 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
86
87 public delegate void OnPluginConsoleDelegate(string[] args);
88
89 public event OnPluginConsoleDelegate OnPluginConsole;
90
91 public delegate void OnShutdownDelegate();
92
93 public event OnShutdownDelegate OnShutdown;
94
95 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
96 public delegate void ObjectDeGrabDelegate(uint localID, uint originalID, IClientAPI remoteClient);
97 public delegate void ScriptResetDelegate(uint localID, UUID itemID);
98
99 public delegate void OnPermissionErrorDelegate(UUID user, string reason);
100
101 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene);
102
103 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
104
105 public event ObjectGrabDelegate OnObjectGrab;
106 public event ObjectDeGrabDelegate OnObjectDeGrab;
107 public event ScriptResetDelegate OnScriptReset;
108
109 public event OnPermissionErrorDelegate OnPermissionError;
110
111 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource);
112
113 public event NewRezScript OnRezScript;
114
115 public delegate void RemoveScript(uint localID, UUID itemID);
116
117 public event RemoveScript OnRemoveScript;
118
119 public delegate void StartScript(uint localID, UUID itemID);
120
121 public event StartScript OnStartScript;
122
123 public delegate void StopScript(uint localID, UUID itemID);
124
125 public event StopScript OnStopScript;
126
127 public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta);
128
129 public event SceneGroupMoved OnSceneGroupMove;
130
131 public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID);
132
133 public event SceneGroupGrabed OnSceneGroupGrab;
134
135 public delegate void LandObjectAdded(ILandObject newParcel);
136
137 public event LandObjectAdded OnLandObjectAdded;
138
139 public delegate void LandObjectRemoved(UUID globalID);
140
141 public event LandObjectRemoved OnLandObjectRemoved;
142
143 public delegate void AvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID);
144
145 public event AvatarEnteringNewParcel OnAvatarEnteringNewParcel;
146
147 public delegate void SignificantClientMovement(IClientAPI remote_client);
148
149 public event SignificantClientMovement OnSignificantClientMovement;
150
151 public delegate void IncomingInstantMessage(GridInstantMessage message);
152
153 public event IncomingInstantMessage OnIncomingInstantMessage;
154
155 public event IncomingInstantMessage OnUnhandledInstantMessage;
156
157 public delegate void ClientClosed(UUID clientID);
158
159 public event ClientClosed OnClientClosed;
160
161 public delegate void ScriptChangedEvent(uint localID, uint change);
162
163 public event ScriptChangedEvent OnScriptChangedEvent;
164
165 public delegate void ScriptControlEvent(uint localID, UUID item, UUID avatarID, uint held, uint changed);
166
167 public event ScriptControlEvent OnScriptControlEvent;
168
169 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos);
170
171 public event ScriptAtTargetEvent OnScriptAtTargetEvent;
172
173 public delegate void ScriptNotAtTargetEvent(uint localID);
174
175 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
176
177 public delegate void ScriptColliding(uint localID, ColliderArgs colliders);
178
179 public event ScriptColliding OnScriptColliderStart;
180 public event ScriptColliding OnScriptColliding;
181 public event ScriptColliding OnScriptCollidingEnd;
182
183 public delegate void OnMakeChildAgentDelegate(ScenePresence presence);
184 public event OnMakeChildAgentDelegate OnMakeChildAgent;
185
186 public delegate void OnMakeRootAgentDelegate(ScenePresence presence);
187 public event OnMakeRootAgentDelegate OnMakeRootAgent;
188
189 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
190
191 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
192
193 public delegate void RequestChangeWaterHeight(float height);
194
195 public event RequestChangeWaterHeight OnRequestChangeWaterHeight;
196
197 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar);
198
199 public event AvatarKillData OnAvatarKilled;
200
201 public delegate void ScriptTimerEvent(uint localID, double timerinterval);
202
203 public event ScriptTimerEvent OnScriptTimerEvent;
204
205 public delegate void EstateToolsTimeUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour);
206 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
207
208 public event EstateToolsTimeUpdate OnEstateToolsTimeUpdate;
209
210 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
211 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
212
213 public delegate void NoticeNoLandDataFromStorage();
214 public event NoticeNoLandDataFromStorage OnNoticeNoLandDataFromStorage;
215
216 public delegate void IncomingLandDataFromStorage(List<LandData> data);
217 public event IncomingLandDataFromStorage OnIncomingLandDataFromStorage;
218
219 public delegate void SetAllowForcefulBan(bool allow);
220 public event SetAllowForcefulBan OnSetAllowForcefulBan;
221
222 public delegate void RequestParcelPrimCountUpdate();
223 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
224
225 public delegate void ParcelPrimCountTainted();
226 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
227 public event GetScriptRunning OnGetScriptRunning;
228
229 /// <summary>
230 /// RegisterCapsEvent is called by Scene after the Caps object
231 /// has been instantiated and before it is return to the
232 /// client and provides region modules to add their caps.
233 /// </summary>
234 public delegate void RegisterCapsEvent(UUID agentID, Caps caps);
235 public event RegisterCapsEvent OnRegisterCaps;
236
237 /// <summary>
238 /// DeregisterCapsEvent is called by Scene when the caps
239 /// handler for an agent are removed.
240 /// </summary>
241 public delegate void DeregisterCapsEvent(UUID agentID, Caps caps);
242 public event DeregisterCapsEvent OnDeregisterCaps;
243
244 /// <summary>
245 /// ChatFromWorldEvent is called via Scene when a chat message
246 /// from world comes in.
247 /// </summary>
248 public delegate void ChatFromWorldEvent(Object sender, OSChatMessage chat);
249 public event ChatFromWorldEvent OnChatFromWorld;
250
251 /// <summary>
252 /// ChatFromClientEvent is triggered via ChatModule (or
253 /// substitutes thereof) when a chat message
254 /// from the client comes in.
255 /// </summary>
256 public delegate void ChatFromClientEvent(Object sender, OSChatMessage chat);
257 public event ChatFromClientEvent OnChatFromClient;
258
259 /// <summary>
260 /// ChatBroadcastEvent is called via Scene when a broadcast chat message
261 /// from world comes in
262 /// </summary>
263 public delegate void ChatBroadcastEvent(Object sender, OSChatMessage chat);
264 public event ChatBroadcastEvent OnChatBroadcast;
265
266 public delegate float SunLindenHour();
267 public event SunLindenHour OnGetSunLindenHour;
268
269 /// <summary>
270 /// Called when oar file has finished loading, although
271 /// the scripts may not have started yet
272 /// Message is non empty string if there were problems loading the oar file
273 /// </summary>
274 public delegate void OarFileLoaded(string message);
275 public event OarFileLoaded OnOarFileLoaded;
276
277 /// <summary>
278 /// Called when an oar file has finished saving
279 /// Message is non empty string if there were problems saving the oar file
280 /// </summary>
281 public delegate void OarFileSaved(string message);
282 public event OarFileSaved OnOarFileSaved;
283
284 /// <summary>
285 /// Called when the script compile queue becomes empty
286 /// Returns the number of scripts which failed to start
287 /// </summary>
288 public delegate void EmptyScriptCompileQueue(int numScriptsFailed, string message);
289 public event EmptyScriptCompileQueue OnEmptyScriptCompileQueue;
290
291 public class MoneyTransferArgs : EventArgs
292 {
293 public UUID sender;
294 public UUID receiver;
295
296 // Always false. The SL protocol sucks.
297 public bool authenticated = false;
298
299 public int amount;
300 public int transactiontype;
301 public string description;
302
303 public MoneyTransferArgs(UUID asender, UUID areceiver, int aamount, int atransactiontype, string adescription)
304 {
305 sender = asender;
306 receiver = areceiver;
307 amount = aamount;
308 transactiontype = atransactiontype;
309 description = adescription;
310 }
311 }
312
313 public class LandBuyArgs : EventArgs
314 {
315 public UUID agentId = UUID.Zero;
316
317 public UUID groupId = UUID.Zero;
318
319 public UUID parcelOwnerID = UUID.Zero;
320
321 public bool final = false;
322 public bool groupOwned = false;
323 public bool removeContribution = false;
324 public int parcelLocalID = 0;
325 public int parcelArea = 0;
326 public int parcelPrice = 0;
327 public bool authenticated = false;
328 public bool landValidated = false;
329 public bool economyValidated = false;
330 public int transactionID = 0;
331 public int amountDebited = 0;
332
333 public LandBuyArgs(UUID pagentId, UUID pgroupId, bool pfinal, bool pgroupOwned,
334 bool premoveContribution, int pparcelLocalID, int pparcelArea, int pparcelPrice,
335 bool pauthenticated)
336 {
337 agentId = pagentId;
338 groupId = pgroupId;
339 final = pfinal;
340 groupOwned = pgroupOwned;
341 removeContribution = premoveContribution;
342 parcelLocalID = pparcelLocalID;
343 parcelArea = pparcelArea;
344 parcelPrice = pparcelPrice;
345 authenticated = pauthenticated;
346 }
347 }
348
349 public delegate void MoneyTransferEvent(Object sender, MoneyTransferArgs e);
350
351 public delegate void LandBuy(Object sender, LandBuyArgs e);
352
353 public event MoneyTransferEvent OnMoneyTransfer;
354 public event LandBuy OnLandBuy;
355 public event LandBuy OnValidateLandBuy;
356
357 /* Designated Event Deletage Instances */
358
359 private ScriptChangedEvent handlerScriptChangedEvent = null; //OnScriptChangedEvent;
360 private ScriptAtTargetEvent handlerScriptAtTargetEvent = null;
361 private ScriptNotAtTargetEvent handlerScriptNotAtTargetEvent = null;
362 private ClientMovement handlerClientMovement = null; //OnClientMovement;
363 private OnPermissionErrorDelegate handlerPermissionError = null; //OnPermissionError;
364 private OnPluginConsoleDelegate handlerPluginConsole = null; //OnPluginConsole;
365 private OnFrameDelegate handlerFrame = null; //OnFrame;
366 private OnNewClientDelegate handlerNewClient = null; //OnNewClient;
367 private OnClientConnectCoreDelegate handlerClientConnect = null; //OnClientConnect
368 private OnNewPresenceDelegate handlerNewPresence = null; //OnNewPresence;
369 private OnRemovePresenceDelegate handlerRemovePresence = null; //OnRemovePresence;
370 private OnBackupDelegate handlerBackup = null; //OnBackup;
371 private OnParcelPrimCountUpdateDelegate handlerParcelPrimCountUpdate = null; //OnParcelPrimCountUpdate;
372 private MoneyTransferEvent handlerMoneyTransfer = null; //OnMoneyTransfer;
373 private OnParcelPrimCountAddDelegate handlerParcelPrimCountAdd = null; //OnParcelPrimCountAdd;
374 private OnShutdownDelegate handlerShutdown = null; //OnShutdown;
375 private ObjectGrabDelegate handlerObjectGrab = null; //OnObjectGrab;
376 private ObjectDeGrabDelegate handlerObjectDeGrab = null; //OnObjectDeGrab;
377 private ScriptResetDelegate handlerScriptReset = null; // OnScriptReset
378 private NewRezScript handlerRezScript = null; //OnRezScript;
379 private RemoveScript handlerRemoveScript = null; //OnRemoveScript;
380 private StartScript handlerStartScript = null; //OnStartScript;
381 private StopScript handlerStopScript = null; //OnStopScript;
382 private SceneGroupMoved handlerSceneGroupMove = null; //OnSceneGroupMove;
383 private SceneGroupGrabed handlerSceneGroupGrab = null; //OnSceneGroupGrab;
384 private LandObjectAdded handlerLandObjectAdded = null; //OnLandObjectAdded;
385 private LandObjectRemoved handlerLandObjectRemoved = null; //OnLandObjectRemoved;
386 private AvatarEnteringNewParcel handlerAvatarEnteringNewParcel = null; //OnAvatarEnteringNewParcel;
387 private IncomingInstantMessage handlerIncomingInstantMessage = null; //OnIncomingInstantMessage;
388 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage;
389 private ClientClosed handlerClientClosed = null; //OnClientClosed;
390 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent;
391 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent;
392 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick;
393 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
394 private DeregisterCapsEvent handlerDeregisterCaps = null; // OnDeregisterCaps;
395 private ChatFromWorldEvent handlerChatFromWorld = null; // OnChatFromWorld;
396 private ChatFromClientEvent handlerChatFromClient = null; // OnChatFromClient;
397 private ChatBroadcastEvent handlerChatBroadcast = null; // OnChatBroadcast;
398 private NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = null;
399 private RequestChangeWaterHeight handlerRequestChangeWaterHeight = null; //OnRequestChangeWaterHeight
400 private ScriptControlEvent handlerScriptControlEvent = null;
401 private SignificantClientMovement handlerSignificantClientMovement = null;
402
403 private LandBuy handlerLandBuy = null;
404 private LandBuy handlerValidateLandBuy = null;
405 private AvatarKillData handlerAvatarKill = null;
406
407 private NoticeNoLandDataFromStorage handlerNoticeNoLandDataFromStorage = null;
408 private IncomingLandDataFromStorage handlerIncomingLandDataFromStorage = null;
409 private SetAllowForcefulBan handlerSetAllowForcefulBan = null;
410 private RequestParcelPrimCountUpdate handlerRequestParcelPrimCountUpdate = null;
411 private ParcelPrimCountTainted handlerParcelPrimCountTainted = null;
412 private ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = null;
413 private ScriptTimerEvent handlerScriptTimerEvent = null;
414 private EstateToolsTimeUpdate handlerEstateToolsTimeUpdate = null;
415
416 private ScriptColliding handlerCollidingStart = null;
417 private ScriptColliding handlerColliding = null;
418 private ScriptColliding handlerCollidingEnd = null;
419 private GetScriptRunning handlerGetScriptRunning = null;
420
421 private SunLindenHour handlerSunGetLindenHour = null;
422 private OnSetRootAgentSceneDelegate handlerSetRootAgentScene = null;
423
424 private OarFileLoaded handlerOarFileLoaded = null;
425 private OarFileSaved handlerOarFileSaved = null;
426
427 private EmptyScriptCompileQueue handlerEmptyScriptCompileQueue = null;
428
429 public void TriggerGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
430 {
431 handlerGetScriptRunning = OnGetScriptRunning;
432 if (handlerGetScriptRunning != null)
433 handlerGetScriptRunning(controllingClient, objectID, itemID);
434 }
435
436 public void TriggerOnScriptChangedEvent(uint localID, uint change)
437 {
438 handlerScriptChangedEvent = OnScriptChangedEvent;
439 if (handlerScriptChangedEvent != null)
440 handlerScriptChangedEvent(localID, change);
441 }
442
443 public void TriggerOnClientMovement(ScenePresence avatar)
444 {
445 handlerClientMovement = OnClientMovement;
446 if (handlerClientMovement != null)
447 handlerClientMovement(avatar);
448 }
449
450 public void TriggerPermissionError(UUID user, string reason)
451 {
452 handlerPermissionError = OnPermissionError;
453 if (handlerPermissionError != null)
454 handlerPermissionError(user, reason);
455 }
456
457 public void TriggerOnPluginConsole(string[] args)
458 {
459 handlerPluginConsole = OnPluginConsole;
460 if (handlerPluginConsole != null)
461 handlerPluginConsole(args);
462 }
463
464 public void TriggerOnFrame()
465 {
466 handlerFrame = OnFrame;
467 if (handlerFrame != null)
468 {
469 handlerFrame();
470 }
471 }
472
473 public void TriggerOnNewClient(IClientAPI client)
474 {
475 handlerNewClient = OnNewClient;
476 if (handlerNewClient != null)
477 handlerNewClient(client);
478
479 if (client is IClientCore)
480 {
481 handlerClientConnect = OnClientConnect;
482 handlerClientConnect((IClientCore) client);
483 }
484 }
485
486 public void TriggerOnNewPresence(ScenePresence presence)
487 {
488 handlerNewPresence = OnNewPresence;
489 if (handlerNewPresence != null)
490 handlerNewPresence(presence);
491 }
492
493 public void TriggerOnRemovePresence(UUID agentId)
494 {
495 handlerRemovePresence = OnRemovePresence;
496 if (handlerRemovePresence != null)
497 {
498 handlerRemovePresence(agentId);
499 }
500 }
501
502 public void TriggerOnBackup(IRegionDataStore dstore)
503 {
504 handlerBackup = OnBackup;
505 if (handlerBackup != null)
506 {
507 handlerBackup(dstore, false);
508 }
509 }
510
511 public void TriggerParcelPrimCountUpdate()
512 {
513 handlerParcelPrimCountUpdate = OnParcelPrimCountUpdate;
514 if (handlerParcelPrimCountUpdate != null)
515 {
516 handlerParcelPrimCountUpdate();
517 }
518 }
519
520 public void TriggerMoneyTransfer(Object sender, MoneyTransferArgs e)
521 {
522 handlerMoneyTransfer = OnMoneyTransfer;
523 if (handlerMoneyTransfer != null)
524 {
525 handlerMoneyTransfer(sender, e);
526 }
527 }
528
529 public void TriggerTerrainTick()
530 {
531 handlerTerrainTick = OnTerrainTick;
532 if (handlerTerrainTick != null)
533 {
534 handlerTerrainTick();
535 }
536 }
537
538 public void TriggerParcelPrimCountAdd(SceneObjectGroup obj)
539 {
540 handlerParcelPrimCountAdd = OnParcelPrimCountAdd;
541 if (handlerParcelPrimCountAdd != null)
542 {
543 handlerParcelPrimCountAdd(obj);
544 }
545 }
546
547 public void TriggerObjectBeingRemovedFromScene(SceneObjectGroup obj)
548 {
549 handlerObjectBeingRemovedFromScene = OnObjectBeingRemovedFromScene;
550 if (handlerObjectBeingRemovedFromScene != null)
551 {
552 handlerObjectBeingRemovedFromScene(obj);
553 }
554 }
555
556 public void TriggerShutdown()
557 {
558 handlerShutdown = OnShutdown;
559 if (handlerShutdown != null)
560 handlerShutdown();
561 }
562
563 public void TriggerObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
564 {
565 handlerObjectGrab = OnObjectGrab;
566 if (handlerObjectGrab != null)
567 {
568 handlerObjectGrab(localID, originalID, offsetPos, remoteClient, surfaceArgs);
569 }
570 }
571
572 public void TriggerObjectDeGrab(uint localID, uint originalID, IClientAPI remoteClient)
573 {
574 handlerObjectDeGrab = OnObjectDeGrab;
575 if (handlerObjectDeGrab != null)
576 {
577 handlerObjectDeGrab(localID, originalID, remoteClient);
578 }
579 }
580
581 public void TriggerScriptReset(uint localID, UUID itemID)
582 {
583 handlerScriptReset = OnScriptReset;
584 if (handlerScriptReset != null)
585 {
586 handlerScriptReset(localID, itemID);
587 }
588 }
589
590 public void TriggerRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
591 {
592 handlerRezScript = OnRezScript;
593 if (handlerRezScript != null)
594 {
595 handlerRezScript(localID, itemID, script, startParam,
596 postOnRez, engine, stateSource);
597 }
598 }
599
600 public void TriggerStartScript(uint localID, UUID itemID)
601 {
602 handlerStartScript = OnStartScript;
603 if (handlerStartScript != null)
604 {
605 handlerStartScript(localID, itemID);
606 }
607 }
608
609 public void TriggerStopScript(uint localID, UUID itemID)
610 {
611 handlerStopScript = OnStopScript;
612 if (handlerStopScript != null)
613 {
614 handlerStopScript(localID, itemID);
615 }
616 }
617
618 public void TriggerRemoveScript(uint localID, UUID itemID)
619 {
620 handlerRemoveScript = OnRemoveScript;
621 if (handlerRemoveScript != null)
622 {
623 handlerRemoveScript(localID, itemID);
624 }
625 }
626
627 public bool TriggerGroupMove(UUID groupID, Vector3 delta)
628 {
629 handlerSceneGroupMove = OnSceneGroupMove;
630
631 if (handlerSceneGroupMove != null)
632 {
633 return handlerSceneGroupMove(groupID, delta);
634 }
635 return true;
636 }
637
638 public void TriggerGroupGrab(UUID groupID, Vector3 offset, UUID userID)
639 {
640 handlerSceneGroupGrab = OnSceneGroupGrab;
641 if (handlerSceneGroupGrab != null)
642 {
643 handlerSceneGroupGrab(groupID, offset, userID);
644 }
645 }
646
647 public void TriggerLandObjectAdded(ILandObject newParcel)
648 {
649 handlerLandObjectAdded = OnLandObjectAdded;
650
651 if (handlerLandObjectAdded != null)
652 {
653 handlerLandObjectAdded(newParcel);
654 }
655 }
656
657 public void TriggerLandObjectRemoved(UUID globalID)
658 {
659 handlerLandObjectRemoved = OnLandObjectRemoved;
660 if (handlerLandObjectRemoved != null)
661 {
662 handlerLandObjectRemoved(globalID);
663 }
664 }
665
666 public void TriggerLandObjectUpdated(uint localParcelID, ILandObject newParcel)
667 {
668 //triggerLandObjectRemoved(localParcelID);
669
670 TriggerLandObjectAdded(newParcel);
671 }
672
673 public void TriggerAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
674 {
675 handlerAvatarEnteringNewParcel = OnAvatarEnteringNewParcel;
676
677 if (handlerAvatarEnteringNewParcel != null)
678 {
679 handlerAvatarEnteringNewParcel(avatar, localLandID, regionID);
680 }
681 }
682
683 public void TriggerIncomingInstantMessage(GridInstantMessage message)
684 {
685 handlerIncomingInstantMessage = OnIncomingInstantMessage;
686 if (handlerIncomingInstantMessage != null)
687 {
688 handlerIncomingInstantMessage(message);
689 }
690 }
691
692 public void TriggerUnhandledInstantMessage(GridInstantMessage message)
693 {
694 handlerUnhandledInstantMessage = OnUnhandledInstantMessage;
695 if (handlerUnhandledInstantMessage != null)
696 {
697 handlerUnhandledInstantMessage(message);
698 }
699 }
700
701 public void TriggerClientClosed(UUID ClientID)
702 {
703 handlerClientClosed = OnClientClosed;
704 if (handlerClientClosed != null)
705 {
706 handlerClientClosed(ClientID);
707 }
708 }
709
710 public void TriggerOnMakeChildAgent(ScenePresence presence)
711 {
712 handlerMakeChildAgent = OnMakeChildAgent;
713 if (handlerMakeChildAgent != null)
714 {
715 handlerMakeChildAgent(presence);
716 }
717 }
718
719 public void TriggerOnMakeRootAgent(ScenePresence presence)
720 {
721 handlerMakeRootAgent = OnMakeRootAgent;
722 if (handlerMakeRootAgent != null)
723 {
724 handlerMakeRootAgent(presence);
725 }
726 }
727
728 public void TriggerOnRegisterCaps(UUID agentID, Caps caps)
729 {
730 handlerRegisterCaps = OnRegisterCaps;
731 if (handlerRegisterCaps != null)
732 {
733 handlerRegisterCaps(agentID, caps);
734 }
735 }
736
737 public void TriggerOnDeregisterCaps(UUID agentID, Caps caps)
738 {
739 handlerDeregisterCaps = OnDeregisterCaps;
740 if (handlerDeregisterCaps != null)
741 {
742 handlerDeregisterCaps(agentID, caps);
743 }
744 }
745
746 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel)
747 {
748 handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
749 if (handlerNewInventoryItemUpdateComplete != null)
750 {
751 handlerNewInventoryItemUpdateComplete(agentID, AssetID, AssetName, userlevel);
752 }
753 }
754
755 public void TriggerLandBuy(Object sender, LandBuyArgs e)
756 {
757 handlerLandBuy = OnLandBuy;
758 if (handlerLandBuy != null)
759 {
760 handlerLandBuy(sender, e);
761 }
762 }
763
764 public void TriggerValidateLandBuy(Object sender, LandBuyArgs e)
765 {
766 handlerValidateLandBuy = OnValidateLandBuy;
767 if (handlerValidateLandBuy != null)
768 {
769 handlerValidateLandBuy(sender, e);
770 }
771 }
772
773 public void TriggerAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 currentpos)
774 {
775 handlerScriptAtTargetEvent = OnScriptAtTargetEvent;
776 if (handlerScriptAtTargetEvent != null)
777 {
778 handlerScriptAtTargetEvent(localID, handle, targetpos, currentpos);
779 }
780 }
781
782 public void TriggerNotAtTargetEvent(uint localID)
783 {
784 handlerScriptNotAtTargetEvent = OnScriptNotAtTargetEvent;
785 if (handlerScriptNotAtTargetEvent != null)
786 {
787 handlerScriptNotAtTargetEvent(localID);
788 }
789 }
790
791 public void TriggerRequestChangeWaterHeight(float height)
792 {
793 handlerRequestChangeWaterHeight = OnRequestChangeWaterHeight;
794 if (handlerRequestChangeWaterHeight != null)
795 {
796 handlerRequestChangeWaterHeight(height);
797 }
798 }
799
800 public void TriggerAvatarKill(uint KillerObjectLocalID, ScenePresence DeadAvatar)
801 {
802 handlerAvatarKill = OnAvatarKilled;
803 if (handlerAvatarKill != null)
804 {
805 handlerAvatarKill(KillerObjectLocalID, DeadAvatar);
806 }
807 }
808
809 public void TriggerSignificantClientMovement(IClientAPI client)
810 {
811 handlerSignificantClientMovement = OnSignificantClientMovement;
812 if (handlerSignificantClientMovement != null)
813 {
814 handlerSignificantClientMovement(client);
815 }
816 }
817
818 public void TriggerOnChatFromWorld(Object sender, OSChatMessage chat)
819 {
820 handlerChatFromWorld = OnChatFromWorld;
821 if (handlerChatFromWorld != null)
822 {
823 handlerChatFromWorld(sender, chat);
824 }
825 }
826
827 public void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
828 {
829 handlerChatFromClient = OnChatFromClient;
830 if (handlerChatFromClient != null)
831 {
832 handlerChatFromClient(sender, chat);
833 }
834 }
835
836 public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat)
837 {
838 handlerChatBroadcast = OnChatBroadcast;
839 if (handlerChatBroadcast != null)
840 {
841 handlerChatBroadcast(sender, chat);
842 }
843 }
844
845 internal void TriggerControlEvent(uint p, UUID scriptUUID, UUID avatarID, uint held, uint _changed)
846 {
847 handlerScriptControlEvent = OnScriptControlEvent;
848 if (handlerScriptControlEvent != null)
849 {
850 handlerScriptControlEvent(p, scriptUUID, avatarID, held, _changed);
851 }
852 }
853
854 public void TriggerNoticeNoLandDataFromStorage()
855 {
856 handlerNoticeNoLandDataFromStorage = OnNoticeNoLandDataFromStorage;
857 if (handlerNoticeNoLandDataFromStorage != null)
858 {
859 handlerNoticeNoLandDataFromStorage();
860
861 }
862 }
863
864 public void TriggerIncomingLandDataFromStorage(List<LandData> landData)
865 {
866 handlerIncomingLandDataFromStorage = OnIncomingLandDataFromStorage;
867 if (handlerIncomingLandDataFromStorage != null)
868 {
869 handlerIncomingLandDataFromStorage(landData);
870
871 }
872 }
873
874 public void TriggerSetAllowForcefulBan(bool allow)
875 {
876 handlerSetAllowForcefulBan = OnSetAllowForcefulBan;
877 if (handlerSetAllowForcefulBan != null)
878 {
879 handlerSetAllowForcefulBan(allow);
880
881 }
882 }
883
884 public void TriggerRequestParcelPrimCountUpdate()
885 {
886 handlerRequestParcelPrimCountUpdate = OnRequestParcelPrimCountUpdate;
887 if (handlerRequestParcelPrimCountUpdate != null)
888 {
889 handlerRequestParcelPrimCountUpdate();
890 }
891 }
892
893 public void TriggerParcelPrimCountTainted()
894 {
895 handlerParcelPrimCountTainted = OnParcelPrimCountTainted;
896 if (handlerParcelPrimCountTainted != null)
897 {
898 handlerParcelPrimCountTainted();
899 }
900 }
901
902 // this lets us keep track of nasty script events like timer, etc.
903 public void TriggerTimerEvent(uint objLocalID, double Interval)
904 {
905 handlerScriptTimerEvent = OnScriptTimerEvent;
906 if (handlerScriptTimerEvent != null)
907 {
908 handlerScriptTimerEvent(objLocalID, Interval);
909 }
910 }
911
912 public void TriggerEstateToolsTimeUpdate(ulong regionHandle, bool FixedTime, bool useEstateTime, float LindenHour)
913 {
914 handlerEstateToolsTimeUpdate = OnEstateToolsTimeUpdate;
915 if (handlerEstateToolsTimeUpdate != null)
916 {
917 handlerEstateToolsTimeUpdate(regionHandle, FixedTime, useEstateTime, LindenHour);
918 }
919 }
920
921 public float GetSunLindenHour()
922 {
923 handlerSunGetLindenHour = OnGetSunLindenHour;
924 if (handlerSunGetLindenHour != null)
925 {
926 return handlerSunGetLindenHour();
927 }
928 return 6;
929 }
930
931 public void TriggerOarFileLoaded(string message)
932 {
933 handlerOarFileLoaded = OnOarFileLoaded;
934 if (handlerOarFileLoaded != null)
935 handlerOarFileLoaded(message);
936 }
937
938 public void TriggerOarFileSaved(string message)
939 {
940 handlerOarFileSaved = OnOarFileSaved;
941 if (handlerOarFileSaved != null)
942 handlerOarFileSaved(message);
943 }
944
945 public void TriggerEmptyScriptCompileQueue(int numScriptsFailed, string message)
946 {
947 handlerEmptyScriptCompileQueue = OnEmptyScriptCompileQueue;
948 if (handlerEmptyScriptCompileQueue != null)
949 handlerEmptyScriptCompileQueue(numScriptsFailed, message);
950 }
951
952 public void TriggerScriptCollidingStart(uint localId, ColliderArgs colliders)
953 {
954 handlerCollidingStart = OnScriptColliderStart;
955 if (handlerCollidingStart != null)
956 handlerCollidingStart(localId, colliders);
957 }
958
959 public void TriggerScriptColliding(uint localId, ColliderArgs colliders)
960 {
961 handlerColliding = OnScriptColliding;
962 if (handlerColliding != null)
963 handlerColliding(localId, colliders);
964 }
965
966 public void TriggerScriptCollidingEnd(uint localId, ColliderArgs colliders)
967 {
968 handlerCollidingEnd = OnScriptCollidingEnd;
969 if (handlerCollidingEnd != null)
970 handlerCollidingEnd(localId, colliders);
971 }
972
973 public void TriggerSetRootAgentScene(UUID agentID, Scene scene)
974 {
975 handlerSetRootAgentScene = OnSetRootAgentScene;
976 if (handlerSetRootAgentScene != null)
977 handlerSetRootAgentScene(agentID, scene);
978 }
979 }
980}
diff --git a/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs b/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs
deleted file mode 100644
index 73a5a3a..0000000
--- a/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs
+++ /dev/null
@@ -1,376 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using System.Reflection;
33using System.Threading;
34
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38
39using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Servers;
43using OpenSim.Region.Environment;
44using OpenSim.Region.Environment.Scenes;
45
46//using HyperGrid.Framework;
47//using OpenSim.Region.Communications.Hypergrid;
48
49namespace OpenSim.Region.Environment.Scenes.Hypergrid
50{
51 public class HGAssetMapper
52 {
53 #region Fields
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 // This maps between asset server URLs and asset server clients
57 private Dictionary<string, GridAssetClient> m_assetServers = new Dictionary<string, GridAssetClient>();
58
59 // This maps between asset UUIDs and asset servers
60 private Dictionary<UUID, GridAssetClient> m_assetMap = new Dictionary<UUID, GridAssetClient>();
61
62 private Scene m_scene;
63 #endregion
64
65 #region Constructor
66
67 public HGAssetMapper(Scene scene)
68 {
69 m_scene = scene;
70 }
71
72 #endregion
73
74 #region Internal functions
75
76 private string UserAssetURL(UUID userID)
77 {
78 CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
79 if (uinfo != null)
80 return (uinfo.UserProfile.UserAssetURI == "") ? null : uinfo.UserProfile.UserAssetURI;
81 return null;
82 }
83
84 private bool IsLocalUser(UUID userID)
85 {
86 CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
87
88 if (uinfo != null)
89 {
90 if (HGNetworkServersInfo.Singleton.IsLocalUser(uinfo.UserProfile))
91 {
92 m_log.Debug("[HGScene]: Home user " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
93 return true;
94 }
95 }
96
97 m_log.Debug("[HGScene]: Foreign user " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
98 return false;
99 }
100
101 private bool IsInAssetMap(UUID uuid)
102 {
103 return m_assetMap.ContainsKey(uuid);
104 }
105
106 private bool FetchAsset(GridAssetClient asscli, UUID assetID, bool isTexture)
107 {
108 // I'm not going over 3 seconds since this will be blocking processing of all the other inbound
109 // packets from the client.
110 int pollPeriod = 200;
111 int maxPolls = 15;
112
113 AssetBase asset;
114
115 // Maybe it came late, and it's already here. Check first.
116 if (m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset))
117 {
118 m_log.Debug("[HGScene]: Asset already in asset cache. " + assetID);
119 return true;
120 }
121
122
123 asscli.RequestAsset(assetID, isTexture);
124
125 do
126 {
127 Thread.Sleep(pollPeriod);
128
129 if (m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset) && (asset != null))
130 {
131 m_log.Debug("[HGScene]: Asset made it to asset cache. " + asset.Metadata.Name + " " + assetID);
132 // I think I need to store it in the asset DB too.
133 // For now, let me just do it for textures and scripts
134 if (((AssetType)asset.Metadata.Type == AssetType.Texture) ||
135 ((AssetType)asset.Metadata.Type == AssetType.LSLBytecode) ||
136 ((AssetType)asset.Metadata.Type == AssetType.LSLText))
137 {
138 AssetBase asset1 = new AssetBase();
139 Copy(asset, asset1);
140 m_scene.AssetCache.AssetServer.StoreAsset(asset1);
141 }
142 return true;
143 }
144 } while (--maxPolls > 0);
145
146 m_log.WarnFormat("[HGScene]: {0} {1} was not received before the retrieval timeout was reached",
147 isTexture ? "texture" : "asset", assetID.ToString());
148
149 return false;
150 }
151
152 private bool PostAsset(GridAssetClient asscli, UUID assetID)
153 {
154 AssetBase asset1;
155 m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset1);
156
157 if (asset1 != null)
158 {
159 // See long comment in AssetCache.AddAsset
160 if (!asset1.Metadata.Temporary || asset1.Metadata.Local)
161 {
162 // The asset cache returns instances of subclasses of AssetBase:
163 // TextureImage or AssetInfo. So in passing them to the remote
164 // server we first need to convert this to instances of AssetBase,
165 // which is the serializable class for assets.
166 AssetBase asset = new AssetBase();
167 Copy(asset1, asset);
168
169 asscli.StoreAsset(asset);
170 }
171 return true;
172 }
173 else
174 m_log.Warn("[HGScene]: Tried to post asset to remote server, but asset not in local cache.");
175
176 return false;
177 }
178
179 private void Copy(AssetBase from, AssetBase to)
180 {
181 to.Data = from.Data;
182 to.Metadata.Description = from.Metadata.Description;
183 to.Metadata.FullID = from.Metadata.FullID;
184 to.Metadata.ID = from.Metadata.ID;
185 to.Metadata.Local = from.Metadata.Local;
186 to.Metadata.Name = from.Metadata.Name;
187 to.Metadata.Temporary = from.Metadata.Temporary;
188 to.Metadata.Type = from.Metadata.Type;
189
190 }
191
192 private void _guardedAdd(Dictionary<UUID, bool> lst, UUID obj, bool val)
193 {
194 if (!lst.ContainsKey(obj))
195 lst.Add(obj, val);
196 }
197
198 private void SniffTextureUUIDs(Dictionary<UUID, bool> uuids, SceneObjectGroup sog)
199 {
200 try
201 {
202 _guardedAdd(uuids, sog.RootPart.Shape.Textures.DefaultTexture.TextureID, true);
203 }
204 catch (Exception) { }
205
206 foreach (Primitive.TextureEntryFace tface in sog.RootPart.Shape.Textures.FaceTextures)
207 {
208 try
209 {
210 _guardedAdd(uuids, tface.TextureID, true);
211 }
212 catch (Exception) { }
213 }
214
215 foreach (SceneObjectPart sop in sog.Children.Values)
216 {
217 try
218 {
219 _guardedAdd(uuids, sop.Shape.Textures.DefaultTexture.TextureID, true);
220 }
221 catch (Exception) { }
222 foreach (Primitive.TextureEntryFace tface in sop.Shape.Textures.FaceTextures)
223 {
224 try
225 {
226 _guardedAdd(uuids, tface.TextureID, true);
227 }
228 catch (Exception) { }
229 }
230 }
231 }
232
233 private void SniffTaskInventoryUUIDs(Dictionary<UUID, bool> uuids, SceneObjectGroup sog)
234 {
235 TaskInventoryDictionary tinv = sog.RootPart.TaskInventory;
236
237 foreach (TaskInventoryItem titem in tinv.Values)
238 {
239 uuids.Add(titem.AssetID, (InventoryType)titem.Type == InventoryType.Texture);
240 }
241 }
242
243 private Dictionary<UUID, bool> SniffUUIDs(AssetBase asset)
244 {
245 Dictionary<UUID, bool> uuids = new Dictionary<UUID, bool>();
246 if ((asset != null) && ((AssetType)asset.Metadata.Type == AssetType.Object))
247 {
248 string ass_str = Utils.BytesToString(asset.Data);
249 SceneObjectGroup sog = new SceneObjectGroup(ass_str, true);
250
251 SniffTextureUUIDs(uuids, sog);
252
253 // We need to sniff further...
254 SniffTaskInventoryUUIDs(uuids, sog);
255
256 }
257
258 return uuids;
259 }
260
261 private Dictionary<UUID, bool> SniffUUIDs(UUID assetID)
262 {
263 //Dictionary<UUID, bool> uuids = new Dictionary<UUID, bool>();
264
265 AssetBase asset;
266 m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset);
267
268 return SniffUUIDs(asset);
269 }
270
271 private void Dump(Dictionary<UUID, bool> lst)
272 {
273 m_log.Debug("XXX -------- UUID DUMP ------- XXX");
274 foreach (KeyValuePair<UUID, bool> kvp in lst)
275 m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
276 m_log.Debug("XXX -------- UUID DUMP ------- XXX");
277 }
278
279 #endregion
280
281
282 #region Public interface
283
284 public void Get(UUID itemID, UUID ownerID)
285 {
286 if (!IsInAssetMap(itemID) && !IsLocalUser(ownerID))
287 {
288 // Get the item from the remote asset server onto the local AssetCache
289 // and place an entry in m_assetMap
290
291 GridAssetClient asscli = null;
292 string userAssetURL = UserAssetURL(ownerID);
293 if (userAssetURL != null)
294 {
295 m_assetServers.TryGetValue(userAssetURL, out asscli);
296 if (asscli == null)
297 {
298 m_log.Debug("[HGScene]: Starting new GridAssetClient for " + userAssetURL);
299 asscli = new GridAssetClient(userAssetURL);
300 asscli.SetReceiver(m_scene.CommsManager.AssetCache); // Straight to the asset cache!
301 m_assetServers.Add(userAssetURL, asscli);
302 }
303
304 m_log.Debug("[HGScene]: Fetching object " + itemID + " to asset server " + userAssetURL);
305 bool success = FetchAsset(asscli, itemID, false); // asscli.RequestAsset(item.ItemID, false);
306
307 // OK, now fetch the inside.
308 Dictionary<UUID, bool> ids = SniffUUIDs(itemID);
309 Dump(ids);
310 foreach (KeyValuePair<UUID, bool> kvp in ids)
311 FetchAsset(asscli, kvp.Key, kvp.Value);
312
313
314 if (success)
315 {
316 m_log.Debug("[HGScene]: Successfully fetched item from remote asset server " + userAssetURL);
317 m_assetMap.Add(itemID, asscli);
318 }
319 else
320 m_log.Warn("[HGScene]: Could not fetch asset from remote asset server " + userAssetURL);
321 }
322 else
323 m_log.Warn("[HGScene]: Unable to locate foreign user's asset server");
324 }
325 }
326
327 public void Post(UUID itemID, UUID ownerID)
328 {
329 if (!IsLocalUser(ownerID))
330 {
331 // Post the item from the local AssetCache ontp the remote asset server
332 // and place an entry in m_assetMap
333
334 GridAssetClient asscli = null;
335 string userAssetURL = UserAssetURL(ownerID);
336 if (userAssetURL != null)
337 {
338 m_assetServers.TryGetValue(userAssetURL, out asscli);
339 if (asscli == null)
340 {
341 m_log.Debug("[HGScene]: Starting new GridAssetClient for " + userAssetURL);
342 asscli = new GridAssetClient(userAssetURL);
343 asscli.SetReceiver(m_scene.CommsManager.AssetCache); // Straight to the asset cache!
344 m_assetServers.Add(userAssetURL, asscli);
345 }
346 m_log.Debug("[HGScene]: Posting object " + itemID + " to asset server " + userAssetURL);
347 bool success = PostAsset(asscli, itemID);
348
349 // Now the inside
350 Dictionary<UUID, bool> ids = SniffUUIDs(itemID);
351 Dump(ids);
352 foreach (KeyValuePair<UUID, bool> kvp in ids)
353 PostAsset(asscli, kvp.Key);
354
355 if (success)
356 {
357 m_log.Debug("[HGScene]: Successfully posted item to remote asset server " + userAssetURL);
358 if (!m_assetMap.ContainsKey(itemID))
359 m_assetMap.Add(itemID, asscli);
360 }
361 else
362 m_log.Warn("[HGScene]: Could not post asset to remote asset server " + userAssetURL);
363
364 //if (!m_assetMap.ContainsKey(itemID))
365 // m_assetMap.Add(itemID, asscli);
366 }
367 else
368 m_log.Warn("[HGScene]: Unable to locate foreign user's asset server");
369
370 }
371 }
372
373 #endregion
374
375 }
376}
diff --git a/OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.Inventory.cs
deleted file mode 100644
index bdb90d8..0000000
--- a/OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.Inventory.cs
+++ /dev/null
@@ -1,152 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using System.Reflection;
33using System.Threading;
34
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38
39using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Servers;
43using OpenSim.Region.Environment;
44using OpenSim.Region.Environment.Scenes;
45
46namespace OpenSim.Region.Environment.Scenes.Hypergrid
47{
48 public partial class HGScene : Scene
49 {
50 #region Fields
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 private HGAssetMapper m_assMapper;
54
55 #endregion
56
57 #region Constructors
58
59 public HGScene(RegionInfo regInfo, AgentCircuitManager authen,
60 CommunicationsManager commsMan, SceneCommunicationService sceneGridService,
61 AssetCache assetCach, StorageManager storeManager,
62 ModuleLoader moduleLoader, bool dumpAssetsToFile, bool physicalPrim,
63 bool SeeIntoRegionFromNeighbor, IConfigSource config, string simulatorVersion)
64 : base(regInfo, authen, commsMan, sceneGridService, assetCach, storeManager, moduleLoader,
65 dumpAssetsToFile, physicalPrim, SeeIntoRegionFromNeighbor, config, simulatorVersion)
66 {
67 m_log.Info("[HGScene]: Starting HGScene.");
68 m_assMapper = new HGAssetMapper(this);
69
70 EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
71 }
72
73 #endregion
74
75 #region Event handlers
76
77 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
78 {
79 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(avatarID);
80 if (userInfo != null)
81 {
82 m_assMapper.Post(assetID, avatarID);
83 }
84 }
85
86 #endregion
87
88 #region Overrides of Scene.Inventory methods
89
90 ///
91 /// CapsUpdateInventoryItemAsset
92 ///
93 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
94 {
95 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
96
97 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0);
98
99 return newAssetID;
100 }
101
102 ///
103 /// DeleteToInventory
104 ///
105 public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient)
106 {
107 UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient);
108
109 if (!assetID.Equals(UUID.Zero))
110 {
111 UploadInventoryItem(remoteClient.AgentId, assetID, "", 0);
112 }
113 else
114 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
115
116 return assetID;
117 }
118
119 ///
120 /// RezObject
121 ///
122 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
123 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
124 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
125 {
126 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
127 if (userInfo != null)
128 {
129 if (userInfo.RootFolder != null)
130 {
131 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
132
133 if (item != null)
134 {
135 m_assMapper.Get(item.AssetID, remoteClient.AgentId);
136
137 }
138 }
139 }
140
141 // OK, we're done fetching. Pass it up to the default RezObject
142 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
143 RezSelected, RemoveItem, fromTaskID, attachment);
144
145 }
146
147
148 #endregion
149
150 }
151
152}
diff --git a/OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.cs b/OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.cs
deleted file mode 100644
index ca644a6..0000000
--- a/OpenSim/Region/Environment/Scenes/Hypergrid/HGScene.cs
+++ /dev/null
@@ -1,84 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections.Generic;
31
32using OpenMetaverse;
33
34using OpenSim.Framework;
35
36using OpenSim.Framework.Communications.Cache;
37using OpenSim.Region.Environment;
38using OpenSim.Region.Environment.Scenes;
39using TPFlags = OpenSim.Framework.Constants.TeleportFlags;
40
41namespace OpenSim.Region.Environment.Scenes.Hypergrid
42{
43 public partial class HGScene : Scene
44 {
45 /// <summary>
46 /// Teleport an avatar to their home region
47 /// </summary>
48 /// <param name="agentId"></param>
49 /// <param name="client"></param>
50 public override void TeleportClientHome(UUID agentId, IClientAPI client)
51 {
52 m_log.Debug("[HGScene]: TeleportClientHome " + client.FirstName + " " + client.LastName);
53
54 CachedUserInfo uinfo = CommsManager.UserProfileCacheService.GetUserDetails(agentId);
55 if (uinfo != null)
56 {
57 UserProfileData UserProfile = uinfo.UserProfile;
58
59 if (UserProfile != null)
60 {
61 RegionInfo regionInfo = CommsManager.GridService.RequestNeighbourInfo(UserProfile.HomeRegion);
62 //if (regionInfo != null)
63 //{
64 // UserProfile.HomeRegionID = regionInfo.RegionID;
65 // //CommsManager.UserService.UpdateUserProfile(UserProfile);
66 //}
67 if (regionInfo == null)
68 {
69 // can't find the Home region: Tell viewer and abort
70 client.SendTeleportFailed("Your home-region could not be found.");
71 return;
72 }
73 RequestTeleportLocation(
74 client, regionInfo.RegionHandle, UserProfile.HomeLocation, UserProfile.HomeLookAt,
75 (uint)(TPFlags.SetLastToTarget | TPFlags.ViaHome));
76 }
77 }
78 else
79 client.SendTeleportFailed("Sorry! I lost your home-region information.");
80
81 }
82
83 }
84}
diff --git a/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs
deleted file mode 100644
index 5e3e03f..0000000
--- a/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs
+++ /dev/null
@@ -1,363 +0,0 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Threading;
34using log4net;
35using OpenMetaverse;
36using OSD = OpenMetaverse.StructuredData.OSD;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using OpenSim.Framework.Communications.Capabilities;
41using OpenSim.Region.Environment.Scenes;
42using OpenSim.Region.Environment;
43using OpenSim.Region.Interfaces;
44
45namespace OpenSim.Region.Environment.Scenes.Hypergrid
46{
47 public class HGSceneCommunicationService : SceneCommunicationService
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 public readonly IHyperlink m_hg;
52
53 public HGSceneCommunicationService(CommunicationsManager commsMan, IHyperlink hg) : base(commsMan)
54 {
55 m_hg = hg;
56 }
57
58
59 /// <summary>
60 /// Try to teleport an agent to a new region.
61 /// </summary>
62 /// <param name="remoteClient"></param>
63 /// <param name="RegionHandle"></param>
64 /// <param name="position"></param>
65 /// <param name="lookAt"></param>
66 /// <param name="flags"></param>
67 public override void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
68 Vector3 lookAt, uint teleportFlags)
69 {
70 if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
71 return;
72
73 bool destRegionUp = true;
74
75 IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
76
77 if (regionHandle == m_regionInfo.RegionHandle)
78 {
79 // Teleport within the same region
80 if (position.X < 0 || position.X > Constants.RegionSize || position.Y < 0 || position.Y > Constants.RegionSize || position.Z < 0)
81 {
82 Vector3 emergencyPos = new Vector3(128, 128, 128);
83
84 m_log.WarnFormat(
85 "[HGSceneCommService]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
86 position, avatar.Name, avatar.UUID, emergencyPos);
87 position = emergencyPos;
88 }
89 // TODO: Get proper AVG Height
90 float localAVHeight = 1.56f;
91 float posZLimit = (float)avatar.Scene.GetLandHeight((int)position.X, (int)position.Y);
92 float newPosZ = posZLimit + localAVHeight;
93 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
94 {
95 position.Z = newPosZ;
96 }
97
98 // Only send this if the event queue is null
99 if (eq == null)
100 avatar.ControllingClient.SendTeleportLocationStart();
101
102
103 avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
104 avatar.Teleport(position);
105 }
106 else
107 {
108 RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle);
109 if (reg != null)
110 {
111
112 uint newRegionX = (uint)(reg.RegionHandle >> 40);
113 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
114 uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
115 uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);
116
117 ///
118 /// Hypergrid mod start
119 ///
120 ///
121 bool isHyperLink = m_hg.IsHyperlinkRegion(reg.RegionHandle);
122 bool isHomeUser = true;
123 ulong realHandle = regionHandle;
124 CachedUserInfo uinfo = m_commsProvider.UserProfileCacheService.GetUserDetails(avatar.UUID);
125 if (uinfo != null)
126 {
127 isHomeUser = HGNetworkServersInfo.Singleton.IsLocalUser(uinfo.UserProfile);
128 realHandle = m_hg.FindRegionHandle(regionHandle);
129 Console.WriteLine("XXX ---- home user? " + isHomeUser + " --- hyperlink? " + isHyperLink + " --- real handle: " + realHandle.ToString());
130 }
131 ///
132 /// Hypergrid mod stop
133 ///
134 ///
135
136 if (eq == null)
137 avatar.ControllingClient.SendTeleportLocationStart();
138
139
140 // Let's do DNS resolution only once in this process, please!
141 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
142 // it's actually doing a lot of work.
143 IPEndPoint endPoint = reg.ExternalEndPoint;
144 if (endPoint.Address == null)
145 {
146 // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
147 destRegionUp = false;
148 }
149
150 if (destRegionUp)
151 {
152 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
153 // both regions
154 if (avatar.ParentID != (uint)0)
155 avatar.StandUp();
156
157 if (!avatar.ValidateAttachments())
158 {
159 avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
160 return;
161 }
162
163 // the avatar.Close below will clear the child region list. We need this below for (possibly)
164 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
165 //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
166 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
167 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
168 // once we reach here...
169 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
170
171 string capsPath = String.Empty;
172 AgentCircuitData agentCircuit = avatar.ControllingClient.RequestClientInfo();
173 agentCircuit.BaseFolder = UUID.Zero;
174 agentCircuit.InventoryFolder = UUID.Zero;
175 agentCircuit.startpos = position;
176 agentCircuit.child = true;
177 if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
178 {
179 // brand new agent, let's create a new caps seed
180 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
181 }
182
183 //if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
184 if (!m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, agentCircuit))
185 {
186 avatar.ControllingClient.SendTeleportFailed("Destination is not accepting teleports.");
187 return;
188 }
189
190 // Let's close some agents
191 if (isHyperLink) // close them all except this one
192 {
193 List<ulong> regions = new List<ulong>(avatar.KnownChildRegionHandles);
194 regions.Remove(avatar.Scene.RegionInfo.RegionHandle);
195 SendCloseChildAgentConnections(avatar.UUID, regions);
196 }
197 else // close just a few
198 avatar.CloseChildAgents(newRegionX, newRegionY);
199
200 if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY) || isHyperLink)
201 {
202 capsPath
203 = "http://"
204 + reg.ExternalHostName
205 + ":"
206 + reg.HttpPort
207 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
208
209 if (eq != null)
210 {
211 OSD Item = EventQueueHelper.EnableSimulator(realHandle, endPoint);
212 eq.Enqueue(Item, avatar.UUID);
213
214 // ES makes the client send a UseCircuitCode message to the destination,
215 // which triggers a bunch of things there.
216 // So let's wait
217 Thread.Sleep(2000);
218
219 Item = EventQueueHelper.EstablishAgentCommunication(avatar.UUID, endPoint.ToString(), capsPath);
220 eq.Enqueue(Item, avatar.UUID);
221 }
222 else
223 {
224 avatar.ControllingClient.InformClientOfNeighbour(realHandle, endPoint);
225 // TODO: make Event Queue disablable!
226 }
227 }
228 else
229 {
230 // child agent already there
231 agentCircuit.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, reg.RegionHandle);
232 capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
233 + "/CAPS/" + agentCircuit.CapsPath + "0000/";
234 }
235
236 //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
237 // position, false);
238
239 //if (!m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
240 // position, false))
241 //{
242 // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
243 // // We should close that agent we just created over at destination...
244 // List<ulong> lst = new List<ulong>();
245 // lst.Add(realHandle);
246 // SendCloseChildAgentAsync(avatar.UUID, lst);
247 // return;
248 //}
249
250 SetInTransit(avatar.UUID);
251 // Let's send a full update of the agent. This is a synchronous call.
252 AgentData agent = new AgentData();
253 avatar.CopyTo(agent);
254 agent.Position = position;
255 agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort +
256 "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/";
257
258 m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent);
259
260 m_log.DebugFormat(
261 "[CAPS]: Sending new CAPS seed url {0} to client {1}", agentCircuit.CapsPath, avatar.UUID);
262
263
264 ///
265 /// Hypergrid mod: realHandle instead of reg.RegionHandle
266 ///
267 ///
268 if (eq != null)
269 {
270 OSD Item = EventQueueHelper.TeleportFinishEvent(realHandle, 13, endPoint,
271 4, teleportFlags, capsPath, avatar.UUID);
272 eq.Enqueue(Item, avatar.UUID);
273 }
274 else
275 {
276 avatar.ControllingClient.SendRegionTeleport(realHandle, 13, endPoint, 4,
277 teleportFlags, capsPath);
278 }
279 ///
280 /// Hypergrid mod stop
281 ///
282
283
284 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
285 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
286 // that the client contacted the destination before we send the attachments and close things here.
287 if (!WaitForCallback(avatar.UUID))
288 {
289 // Client never contacted destination. Let's restore everything back
290 avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
291
292 ResetFromTransit(avatar.UUID);
293 // Yikes! We should just have a ref to scene here.
294 avatar.Scene.InformClientOfNeighbours(avatar);
295
296 // Finally, kill the agent we just created at the destination.
297 m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID);
298
299 return;
300 }
301
302 // Can't go back from here
303 if (KiPrimitive != null)
304 {
305 KiPrimitive(avatar.LocalId);
306 }
307
308 avatar.MakeChildAgent();
309
310 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
311 avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);
312
313
314 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
315 ///
316 /// Hypergrid mod: extra check for isHyperLink
317 ///
318 if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY) || isHyperLink)
319 {
320 Thread.Sleep(5000);
321 avatar.Close();
322 CloseConnection(avatar.UUID);
323 }
324 // if (teleport success) // seems to be always success here
325 // the user may change their profile information in other region,
326 // so the userinfo in UserProfileCache is not reliable any more, delete it
327 if (avatar.Scene.NeedSceneCacheClear(avatar.UUID) || isHyperLink)
328 {
329 m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
330 m_log.DebugFormat(
331 "[HGSceneCommService]: User {0} is going to another region, profile cache removed",
332 avatar.UUID);
333 }
334 }
335 else
336 {
337 avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
338 }
339 }
340 else
341 {
342 // TP to a place that doesn't exist (anymore)
343 // Inform the viewer about that
344 avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
345
346 // and set the map-tile to '(Offline)'
347 uint regX, regY;
348 Utils.LongToUInts(regionHandle, out regX, out regY);
349
350 MapBlockData block = new MapBlockData();
351 block.X = (ushort)(regX / Constants.RegionSize);
352 block.Y = (ushort)(regY / Constants.RegionSize);
353 block.Access = 254; // == not there
354
355 List<MapBlockData> blocks = new List<MapBlockData>();
356 blocks.Add(block);
357 avatar.ControllingClient.SendMapBlock(blocks, 0);
358 }
359 }
360 }
361
362 }
363}
diff --git a/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs b/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs
deleted file mode 100644
index 9a4c72f..0000000
--- a/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 OpenMetaverse;
29using OpenSim.Framework;
30
31namespace OpenSim.Region.Environment.Scenes
32{
33 public interface IScenePresenceBody
34 {
35 void processMovement(IClientAPI remoteClient, uint flags, Quaternion bodyRotation);
36 }
37}
diff --git a/OpenSim/Region/Environment/Scenes/ReturnInfo.cs b/OpenSim/Region/Environment/Scenes/ReturnInfo.cs
deleted file mode 100644
index 898baab..0000000
--- a/OpenSim/Region/Environment/Scenes/ReturnInfo.cs
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 OpenMetaverse;
29
30namespace OpenSim.Region.Environment.Scenes
31{
32 public struct ReturnInfo
33 {
34 public int count;
35 public Vector3 location;
36 public string objectName;
37 public string reason;
38 }
39}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
deleted file mode 100644
index bc80d56..0000000
--- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
+++ /dev/null
@@ -1,2665 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Timers;
33using OpenMetaverse;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications.Cache;
37using OpenSim.Region.Interfaces;
38using OpenSim.Region.Environment.Interfaces;
39
40namespace OpenSim.Region.Environment.Scenes
41{
42 public partial class Scene
43 {
44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 /// Allows asynchronous derezzing of objects from the scene into a client's inventory.
49 /// </summary>
50 protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
51
52 /// <summary>
53 /// Start all the scripts in the scene which should be started.
54 /// </summary>
55 public void CreateScriptInstances()
56 {
57 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene");
58
59 foreach (EntityBase group in Entities)
60 {
61 if (group is SceneObjectGroup)
62 {
63 ((SceneObjectGroup) group).CreateScriptInstances(0, false, DefaultScriptEngine, 0);
64 }
65 }
66 }
67
68 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)
69 {
70 IMoneyModule money=RequestModuleInterface<IMoneyModule>();
71 if (money != null)
72 {
73 money.ApplyUploadCharge(agentID);
74 }
75
76 AddInventoryItem(agentID, item);
77 }
78
79 public bool AddInventoryItemReturned(UUID AgentId, InventoryItemBase item)
80 {
81 CachedUserInfo userInfo
82 = CommsManager.UserProfileCacheService.GetUserDetails(AgentId);
83 if (userInfo != null)
84 {
85 userInfo.AddItem(item);
86 return true;
87 }
88 else
89 {
90 m_log.ErrorFormat(
91 "[AGENT INVENTORY]: Agent was not found for add of item {1} {2}", item.Name, item.ID);
92
93 return false;
94 }
95 }
96
97 public void AddInventoryItem(UUID AgentID, InventoryItemBase item)
98 {
99 CachedUserInfo userInfo
100 = CommsManager.UserProfileCacheService.GetUserDetails(AgentID);
101
102 if (userInfo != null)
103 {
104 userInfo.AddItem(item);
105
106 int userlevel = 0;
107 if (Permissions.IsGod(AgentID))
108 {
109 userlevel = 1;
110 }
111 // TODO: remove this cruft once MasterAvatar is fully deprecated
112 //
113 if (m_regInfo.MasterAvatarAssignedUUID == AgentID)
114 {
115 userlevel = 2;
116 }
117 EventManager.TriggerOnNewInventoryItemUploadComplete(AgentID, item.AssetID, item.Name, userlevel);
118 }
119 else
120 {
121 m_log.ErrorFormat(
122 "[AGENT INVENTORY]: Agent {1} was not found for add of item {2} {3}",
123 AgentID, item.Name, item.ID);
124
125 return;
126 }
127 }
128
129 /// <summary>
130 /// Add an inventory item to an avatar's inventory.
131 /// </summary>
132 /// <param name="remoteClient">The remote client controlling the avatar</param>
133 /// <param name="item">The item. This structure contains all the item metadata, including the folder
134 /// in which the item is to be placed.</param>
135 public void AddInventoryItem(IClientAPI remoteClient, InventoryItemBase item)
136 {
137 CachedUserInfo userInfo
138 = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
139
140 if (userInfo != null)
141 {
142 AddInventoryItem(remoteClient.AgentId, item);
143 remoteClient.SendInventoryItemCreateUpdate(item);
144 }
145 else
146 {
147 m_log.ErrorFormat(
148 "[AGENT INVENTORY]: Could not resolve user {0} for adding an inventory item",
149 remoteClient.AgentId);
150 }
151 }
152
153 /// <summary>
154 /// Capability originating call to update the asset of an item in an agent's inventory
155 /// </summary>
156 /// <param name="remoteClient"></param>
157 /// <param name="itemID"></param>
158 /// <param name="data"></param>
159 /// <returns></returns>
160 public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
161 {
162 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
163 if (userInfo != null)
164 {
165 if (userInfo.RootFolder != null)
166 {
167 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
168
169 if (item != null)
170 {
171 if ((InventoryType)item.InvType == InventoryType.Notecard)
172 {
173 if (!Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId))
174 {
175 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
176 return UUID.Zero;
177 }
178
179 remoteClient.SendAgentAlertMessage("Notecard saved", false);
180 }
181 else if ((InventoryType)item.InvType == InventoryType.LSL)
182 {
183 if (!Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
184 {
185 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
186 return UUID.Zero;
187 }
188
189 remoteClient.SendAgentAlertMessage("Script saved", false);
190 }
191
192 AssetBase asset =
193 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data);
194 AssetCache.AddAsset(asset);
195
196 item.AssetID = asset.Metadata.FullID;
197 userInfo.UpdateItem(item);
198
199 // remoteClient.SendInventoryItemCreateUpdate(item);
200 return (asset.Metadata.FullID);
201 }
202 }
203 }
204 else
205 {
206 m_log.ErrorFormat(
207 "[AGENT INVENTORY]: Could not resolve user {0} for caps inventory update",
208 remoteClient.AgentId);
209 }
210
211 return UUID.Zero;
212 }
213
214 /// <summary>
215 /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see>
216 /// </summary>
217 public UUID CapsUpdateInventoryItemAsset(UUID avatarId, UUID itemID, byte[] data)
218 {
219 ScenePresence avatar;
220
221 if (TryGetAvatar(avatarId, out avatar))
222 {
223 return CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data);
224 }
225 else
226 {
227 m_log.ErrorFormat(
228 "[AGENT INVENTORY]: " +
229 "Avatar {0} cannot be found to update its inventory item asset",
230 avatarId);
231 }
232
233 return UUID.Zero;
234 }
235
236 /// <summary>
237 /// Capability originating call to update the asset of a script in a prim's (task's) inventory
238 /// </summary>
239 /// <param name="remoteClient"></param>
240 /// <param name="itemID"></param>
241 /// <param name="primID">The prim which contains the item to update</param>
242 /// <param name="isScriptRunning">Indicates whether the script to update is currently running</param>
243 /// <param name="data"></param>
244 public void CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId,
245 UUID primId, bool isScriptRunning, byte[] data)
246 {
247 if (!Permissions.CanEditScript(itemId, primId, remoteClient.AgentId))
248 {
249 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
250 return;
251 }
252
253 // Retrieve group
254 SceneObjectPart part = GetSceneObjectPart(primId);
255 SceneObjectGroup group = part.ParentGroup;
256 if (null == group)
257 {
258 m_log.ErrorFormat(
259 "[PRIM INVENTORY]: " +
260 "Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist",
261 itemId, primId);
262
263 return;
264 }
265
266 // Retrieve item
267 TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemId);
268
269 if (null == item)
270 {
271 m_log.ErrorFormat(
272 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for caps script update "
273 + " but the item does not exist in this inventory",
274 itemId, part.Name, part.UUID);
275
276 return;
277 }
278
279 AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data);
280 AssetCache.AddAsset(asset);
281
282 if (isScriptRunning)
283 {
284 part.Inventory.RemoveScriptInstance(item.ItemID);
285 }
286
287 // Update item with new asset
288 item.AssetID = asset.Metadata.FullID;
289 group.UpdateInventoryItem(item);
290 part.GetProperties(remoteClient);
291
292 // Trigger rerunning of script (use TriggerRezScript event, see RezScript)
293 if (isScriptRunning)
294 {
295 // Needs to determine which engine was running it and use that
296 //
297 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0);
298 }
299 else
300 {
301 remoteClient.SendAgentAlertMessage("Script saved", false);
302 }
303 }
304
305 /// <summary>
306 /// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
307 /// </summary>
308 public void CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
309 UUID primId, bool isScriptRunning, byte[] data)
310 {
311 ScenePresence avatar;
312
313 if (TryGetAvatar(avatarId, out avatar))
314 {
315 CapsUpdateTaskInventoryScriptAsset(
316 avatar.ControllingClient, itemId, primId, isScriptRunning, data);
317 }
318 else
319 {
320 m_log.ErrorFormat(
321 "[PRIM INVENTORY]: " +
322 "Avatar {0} cannot be found to update its prim item asset",
323 avatarId);
324 }
325 }
326
327 /// <summary>
328 /// Update an item which is either already in the client's inventory or is within
329 /// a transaction
330 /// </summary>
331 /// <param name="remoteClient"></param>
332 /// <param name="transactionID">The transaction ID. If this is UUID.Zero we will
333 /// assume that we are not in a transaction</param>
334 /// <param name="itemID">The ID of the updated item</param>
335 /// <param name="name">The name of the updated item</param>
336 /// <param name="description">The description of the updated item</param>
337 /// <param name="nextOwnerMask">The permissions of the updated item</param>
338/* public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID,
339 UUID itemID, string name, string description,
340 uint nextOwnerMask)*/
341 public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID,
342 UUID itemID, InventoryItemBase itemUpd)
343 {
344 CachedUserInfo userInfo
345 = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
346
347 if (userInfo != null && userInfo.RootFolder != null)
348 {
349 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
350
351 if (item != null)
352 {
353 if (UUID.Zero == transactionID)
354 {
355 item.Name = itemUpd.Name;
356 item.Description = itemUpd.Description;
357 item.NextPermissions = itemUpd.NextPermissions;
358 item.CurrentPermissions |= 8; // Slam!
359 item.EveryOnePermissions = itemUpd.EveryOnePermissions;
360 item.GroupPermissions = itemUpd.GroupPermissions;
361
362 item.GroupID = itemUpd.GroupID;
363 item.GroupOwned = itemUpd.GroupOwned;
364 item.CreationDate = itemUpd.CreationDate;
365 // The client sends zero if its newly created?
366
367 if (itemUpd.CreationDate == 0)
368 item.CreationDate = Util.UnixTimeSinceEpoch();
369 else
370 item.CreationDate = itemUpd.CreationDate;
371
372 // TODO: Check if folder changed and move item
373 //item.NextPermissions = itemUpd.Folder;
374 item.InvType = itemUpd.InvType;
375 item.SalePrice = itemUpd.SalePrice;
376 item.SaleType = itemUpd.SaleType;
377 item.Flags = itemUpd.Flags;
378
379 userInfo.UpdateItem(item);
380 }
381 else
382 {
383 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
384 if (agentTransactions != null)
385 {
386 agentTransactions.HandleItemUpdateFromTransaction(
387 remoteClient, transactionID, item);
388 }
389 }
390 }
391 else
392 {
393 m_log.Error(
394 "[AGENTINVENTORY]: Item ID " + itemID + " not found for an inventory item update.");
395 }
396 }
397 else
398 {
399 m_log.Error(
400 "[AGENT INVENTORY]: Agent ID " + remoteClient.AgentId + " not found for an inventory item update.");
401 }
402 }
403
404 /// <summary>
405 /// Give an inventory item from one user to another
406 /// </summary>
407 /// <param name="recipientClient"></param>
408 /// <param name="senderId">ID of the sender of the item</param>
409 /// <param name="itemId"></param>
410 public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId)
411 {
412 InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId);
413
414 if (itemCopy != null)
415 recipientClient.SendBulkUpdateInventory(itemCopy);
416 }
417
418 /// <summary>
419 /// Give an inventory item from one user to another
420 /// </summary>
421 /// <param name="recipient"></param>
422 /// <param name="senderId">ID of the sender of the item</param>
423 /// <param name="itemId"></param>
424 /// <returns>The inventory item copy given, null if the give was unsuccessful</returns>
425 public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId)
426 {
427 return GiveInventoryItem(recipient, senderId, itemId, UUID.Zero);
428 }
429
430 /// <summary>
431 /// Give an inventory item from one user to another
432 /// </summary>
433 /// <param name="recipient"></param>
434 /// <param name="senderId">ID of the sender of the item</param>
435 /// <param name="itemId"></param>
436 /// <param name="recipientFolderId">
437 /// The id of the folder in which the copy item should go. If UUID.Zero then the item is placed in the most
438 /// appropriate default folder.
439 /// </param>
440 /// <returns>
441 /// The inventory item copy given, null if the give was unsuccessful
442 /// </returns>
443 public virtual InventoryItemBase GiveInventoryItem(
444 UUID recipient, UUID senderId, UUID itemId, UUID recipientFolderId)
445 {
446 // Retrieve the item from the sender
447 CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId);
448
449 if (senderUserInfo == null)
450 {
451 m_log.ErrorFormat(
452 "[AGENT INVENTORY]: Failed to find sending user {0} for item {1}", senderId, itemId);
453
454 return null;
455 }
456
457 if (senderUserInfo.RootFolder != null)
458 {
459 InventoryItemBase item = senderUserInfo.RootFolder.FindItem(itemId);
460
461 if (item != null)
462 {
463 if (!Permissions.BypassPermissions())
464 {
465 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
466 return null;
467 }
468
469 CachedUserInfo recipientUserInfo
470 = CommsManager.UserProfileCacheService.GetUserDetails(recipient);
471
472 if (recipientUserInfo != null)
473 {
474 if (!recipientUserInfo.HasReceivedInventory)
475 CommsManager.UserProfileCacheService.RequestInventoryForUser(recipient);
476
477 // Insert a copy of the item into the recipient
478 InventoryItemBase itemCopy = new InventoryItemBase();
479 itemCopy.Owner = recipient;
480 itemCopy.Creator = item.Creator;
481 itemCopy.ID = UUID.Random();
482 itemCopy.AssetID = item.AssetID;
483 itemCopy.Description = item.Description;
484 itemCopy.Name = item.Name;
485 itemCopy.AssetType = item.AssetType;
486 itemCopy.InvType = item.InvType;
487 itemCopy.Folder = recipientFolderId;
488
489 if (Permissions.PropagatePermissions())
490 {
491 if (item.InvType == 6)
492 {
493 itemCopy.BasePermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
494 itemCopy.BasePermissions |= (item.CurrentPermissions & 7) << 13;
495 }
496 else
497 {
498 itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions;
499 }
500
501 itemCopy.CurrentPermissions = itemCopy.BasePermissions;
502 if ((item.CurrentPermissions & 8) != 0) // Propagate slam bit
503 {
504 itemCopy.BasePermissions &= item.NextPermissions;
505 itemCopy.CurrentPermissions = itemCopy.BasePermissions;
506 itemCopy.CurrentPermissions |= 8;
507 }
508
509 itemCopy.NextPermissions = item.NextPermissions;
510 itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions;
511 itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions;
512 }
513 else
514 {
515 itemCopy.CurrentPermissions = item.CurrentPermissions;
516 itemCopy.NextPermissions = item.NextPermissions;
517 itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions;
518 itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions;
519 itemCopy.BasePermissions = item.BasePermissions;
520 }
521 itemCopy.GroupID = UUID.Zero;
522 itemCopy.GroupOwned = false;
523 itemCopy.Flags = item.Flags;
524 itemCopy.SalePrice = item.SalePrice;
525 itemCopy.SaleType = item.SaleType;
526
527 itemCopy.CreationDate = item.CreationDate;
528
529 recipientUserInfo.AddItem(itemCopy);
530
531 if (!Permissions.BypassPermissions())
532 {
533 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
534 senderUserInfo.DeleteItem(itemId);
535 }
536
537 return itemCopy;
538 }
539 else
540 {
541 m_log.ErrorFormat(
542 "[AGENT INVENTORY]: Could not find userinfo for recipient user {0} of item {1}, {2} from {3}",
543 recipient, item.Name,
544 item.ID, senderId);
545 }
546 }
547 else
548 {
549 m_log.ErrorFormat(
550 "[AGENT INVENTORY]: Failed to find item {0} to give to {1}", itemId, senderId);
551
552 return null;
553 }
554 }
555 else
556 {
557 m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemId.ToString() + ", no root folder");
558 return null;
559 }
560
561 return null;
562 }
563
564 /// <summary>
565 /// Give an entire inventory folder from one user to another. The entire contents (including all descendent
566 /// folders) is given.
567 /// </summary>
568 /// <param name="recipientId"></param>
569 /// <param name="senderId">ID of the sender of the item</param>
570 /// <param name="folderId"></param>
571 /// <param name="recipientParentFolderId">
572 /// The id of the receipient folder in which the send folder should be placed. If UUID.Zero then the
573 /// recipient folder is the root folder
574 /// </param>
575 /// <returns>
576 /// The inventory folder copy given, null if the copy was unsuccessful
577 /// </returns>
578 public virtual InventoryFolderImpl GiveInventoryFolder(
579 UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId)
580 {
581 // Retrieve the folder from the sender
582 CachedUserInfo senderUserInfo = CommsManager.UserProfileCacheService.GetUserDetails(senderId);
583
584 if (null == senderUserInfo)
585 {
586 m_log.ErrorFormat(
587 "[AGENT INVENTORY]: Failed to find sending user {0} for folder {1}", senderId, folderId);
588
589 return null;
590 }
591
592 if (!senderUserInfo.HasReceivedInventory)
593 {
594 m_log.DebugFormat(
595 "[AGENT INVENTORY]: Could not give inventory folder - have not yet received inventory for {0}",
596 senderId);
597
598 return null;
599 }
600
601 InventoryFolderImpl folder = senderUserInfo.RootFolder.FindFolder(folderId);
602
603 if (null == folder)
604 {
605 m_log.ErrorFormat(
606 "[AGENT INVENTORY]: Could not find inventory folder {0} to give", folderId);
607
608 return null;
609 }
610
611 CachedUserInfo recipientUserInfo
612 = CommsManager.UserProfileCacheService.GetUserDetails(recipientId);
613
614 if (null == recipientUserInfo)
615 {
616 m_log.ErrorFormat(
617 "[AGENT INVENTORY]: Failed to find receiving user {0} for folder {1}", recipientId, folderId);
618
619 return null;
620 }
621
622 if (recipientParentFolderId == UUID.Zero)
623 recipientParentFolderId = recipientUserInfo.RootFolder.ID;
624
625 UUID newFolderId = UUID.Random();
626 recipientUserInfo.CreateFolder(folder.Name, newFolderId, (ushort)folder.Type, recipientParentFolderId);
627
628 // XXX: Messy - we should really get this back in the CreateFolder call
629 InventoryFolderImpl copiedFolder = recipientUserInfo.RootFolder.FindFolder(newFolderId);
630
631 // Give all the subfolders
632 List<InventoryFolderImpl> subFolders = folder.RequestListOfFolderImpls();
633 foreach (InventoryFolderImpl childFolder in subFolders)
634 {
635 GiveInventoryFolder(recipientId, senderId, childFolder.ID, copiedFolder.ID);
636 }
637
638 // Give all the items
639 List<InventoryItemBase> items = folder.RequestListOfItems();
640 foreach (InventoryItemBase item in items)
641 {
642 GiveInventoryItem(recipientId, senderId, item.ID, copiedFolder.ID);
643 }
644
645 return copiedFolder;
646 }
647
648 public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, UUID oldAgentID, UUID oldItemID,
649 UUID newFolderID, string newName)
650 {
651 m_log.DebugFormat(
652 "[AGENT INVENTORY]: CopyInventoryItem received by {0} with oldAgentID {1}, oldItemID {2}, new FolderID {3}, newName {4}",
653 remoteClient.AgentId, oldAgentID, oldItemID, newFolderID, newName);
654
655 InventoryItemBase item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(oldItemID);
656
657 if (item == null)
658 {
659 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(oldAgentID);
660 if (userInfo == null)
661 {
662 m_log.Error("[AGENT INVENTORY]: Failed to find user " + oldAgentID.ToString());
663 return;
664 }
665
666 if (userInfo.RootFolder != null)
667 {
668 item = userInfo.RootFolder.FindItem(oldItemID);
669
670 if (item == null)
671 {
672 m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString());
673 return;
674 }
675 }
676 else
677 {
678 m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString());
679 return;
680 }
681 }
682
683 AssetBase asset
684 = AssetCache.GetAsset(
685 item.AssetID, (item.AssetType == (int)AssetType.Texture ? true : false));
686
687 if (asset != null)
688 {
689 if (newName != String.Empty)
690 {
691 asset.Metadata.Name = newName;
692 }
693 else
694 {
695 newName = item.Name;
696 }
697
698 if (remoteClient.AgentId == oldAgentID)
699 {
700 CreateNewInventoryItem(
701 remoteClient, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType,
702 item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
703 }
704 else
705 {
706 CreateNewInventoryItem(
707 remoteClient, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType,
708 item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
709 }
710 }
711 else
712 {
713 m_log.ErrorFormat(
714 "[AGENT INVENTORY]: Could not copy item {0} since asset {1} could not be found",
715 item.Name, item.AssetID);
716 }
717 }
718
719 /// <summary>
720 /// Create a new asset data structure.
721 /// </summary>
722 /// <param name="name"></param>
723 /// <param name="description"></param>
724 /// <param name="invType"></param>
725 /// <param name="assetType"></param>
726 /// <param name="data"></param>
727 /// <returns></returns>
728 private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data)
729 {
730 AssetBase asset = new AssetBase();
731 asset.Metadata.Name = name;
732 asset.Metadata.Description = description;
733 asset.Metadata.Type = assetType;
734 asset.Metadata.FullID = UUID.Random();
735 asset.Data = (data == null) ? new byte[1] : data;
736
737 return asset;
738 }
739
740 /// <summary>
741 /// Move an item within the agent's inventory.
742 /// </summary>
743 /// <param name="remoteClient"></param>
744 /// <param name="folderID"></param>
745 /// <param name="itemID"></param>
746 /// <param name="length"></param>
747 /// <param name="newName"></param>
748 public void MoveInventoryItem(IClientAPI remoteClient, UUID folderID, UUID itemID, int length,
749 string newName)
750 {
751 m_log.DebugFormat(
752 "[AGENT INVENTORY]: Moving item {0} to {1} for {2}", itemID, folderID, remoteClient.AgentId);
753
754 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
755
756 if (userInfo == null)
757 {
758 m_log.Error("[AGENT INVENTORY]: Failed to find user " + remoteClient.AgentId.ToString());
759
760 return;
761 }
762
763 if (userInfo.RootFolder != null)
764 {
765 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
766
767 if (item != null)
768 {
769 if (newName != String.Empty)
770 {
771 item.Name = newName;
772 }
773 item.Folder = folderID;
774
775 userInfo.DeleteItem(item.ID);
776
777 AddInventoryItem(remoteClient, item);
778 }
779 else
780 {
781 m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemID.ToString());
782
783 return;
784 }
785 }
786 else
787 {
788 m_log.Error("[AGENT INVENTORY]: Failed to find item " + itemID.ToString() + ", no root folder");
789
790 return;
791 }
792 }
793
794 /// <summary>
795 /// Create a new inventory item.
796 /// </summary>
797 /// <param name="remoteClient"></param>
798 /// <param name="folderID"></param>
799 /// <param name="callbackID"></param>
800 /// <param name="asset"></param>
801 /// <param name="invType"></param>
802 /// <param name="nextOwnerMask"></param>
803 private void CreateNewInventoryItem(IClientAPI remoteClient, UUID folderID, string name, uint flags, uint callbackID,
804 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate)
805 {
806 CreateNewInventoryItem(
807 remoteClient, folderID, name, flags, callbackID, asset, invType,
808 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate);
809 }
810
811 /// <summary>
812 /// Create a new Inventory Item
813 /// </summary>
814 /// <param name="remoteClient"></param>
815 /// <param name="folderID"></param>
816 /// <param name="callbackID"></param>
817 /// <param name="asset"></param>
818 /// <param name="invType"></param>
819 /// <param name="nextOwnerMask"></param>
820 /// <param name="creationDate"></param>
821 private void CreateNewInventoryItem(
822 IClientAPI remoteClient, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType,
823 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
824 {
825 CachedUserInfo userInfo
826 = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
827
828 if (userInfo != null)
829 {
830 InventoryItemBase item = new InventoryItemBase();
831 item.Owner = remoteClient.AgentId;
832 item.Creator = remoteClient.AgentId;
833 item.ID = UUID.Random();
834 item.AssetID = asset.Metadata.FullID;
835 item.Description = asset.Metadata.Description;
836 item.Name = name;
837 item.Flags = flags;
838 item.AssetType = asset.Metadata.Type;
839 item.InvType = invType;
840 item.Folder = folderID;
841 item.CurrentPermissions = currentMask;
842 item.NextPermissions = nextOwnerMask;
843 item.EveryOnePermissions = everyoneMask;
844 item.GroupPermissions = groupMask;
845 item.BasePermissions = baseMask;
846 item.CreationDate = creationDate;
847
848 userInfo.AddItem(item);
849 remoteClient.SendInventoryItemCreateUpdate(item);
850 }
851 else
852 {
853 m_log.WarnFormat(
854 "No user details associated with client {0} uuid {1} in CreateNewInventoryItem!",
855 remoteClient.Name, remoteClient.AgentId);
856 }
857 }
858
859 /// <summary>
860 /// Create a new inventory item. Called when the client creates a new item directly within their
861 /// inventory (e.g. by selecting a context inventory menu option).
862 /// </summary>
863 /// <param name="remoteClient"></param>
864 /// <param name="transactionID"></param>
865 /// <param name="folderID"></param>
866 /// <param name="callbackID"></param>
867 /// <param name="description"></param>
868 /// <param name="name"></param>
869 /// <param name="invType"></param>
870 /// <param name="type"></param>
871 /// <param name="wearableType"></param>
872 /// <param name="nextOwnerMask"></param>
873 public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
874 uint callbackID, string description, string name, sbyte invType,
875 sbyte assetType,
876 byte wearableType, uint nextOwnerMask, int creationDate)
877 {
878 m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID);
879
880 if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
881 return;
882
883 if (transactionID == UUID.Zero)
884 {
885 CachedUserInfo userInfo
886 = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
887
888 if (userInfo != null)
889 {
890 ScenePresence presence;
891 TryGetAvatar(remoteClient.AgentId, out presence);
892 byte[] data = null;
893
894 if (invType == 3 && presence != null) // OpenMetaverse.asset.assettype.landmark = 3 - needs to be turned into an enum
895 {
896 Vector3 pos = presence.AbsolutePosition;
897 string strdata = String.Format(
898 "Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n",
899 presence.Scene.RegionInfo.RegionID,
900 pos.X, pos.Y, pos.Z,
901 presence.RegionHandle);
902 data = Encoding.ASCII.GetBytes(strdata);
903 }
904
905 AssetBase asset = CreateAsset(name, description, assetType, data);
906 AssetCache.AddAsset(asset);
907
908 CreateNewInventoryItem(remoteClient, folderID, asset.Metadata.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
909 }
910 else
911 {
912 m_log.ErrorFormat(
913 "userInfo for agent uuid {0} unexpectedly null in CreateNewInventoryItem",
914 remoteClient.AgentId);
915 }
916 }
917 else
918 {
919 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
920 if (agentTransactions != null)
921 {
922 agentTransactions.HandleItemCreationFromTransaction(
923 remoteClient, transactionID, folderID, callbackID, description,
924 name, invType, assetType, wearableType, nextOwnerMask);
925 }
926 }
927 }
928
929 /// <summary>
930 /// Remove an inventory item for the client's inventory
931 /// </summary>
932 /// <param name="remoteClient"></param>
933 /// <param name="itemID"></param>
934 private void RemoveInventoryItem(IClientAPI remoteClient, UUID itemID)
935 {
936 CachedUserInfo userInfo
937 = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
938
939 if (userInfo == null)
940 {
941 m_log.WarnFormat(
942 "[AGENT INVENTORY]: Failed to find user {0} {1} to delete inventory item {2}",
943 remoteClient.Name, remoteClient.AgentId, itemID);
944
945 return;
946 }
947
948 userInfo.DeleteItem(itemID);
949 }
950
951 /// <summary>
952 /// Removes an inventory folder. Although there is a packet in the Linden protocol for this, it may be
953 /// legacy and not currently used (purge folder is used to remove folders from trash instead).
954 /// </summary>
955 /// <param name="remoteClient"></param>
956 /// <param name="folderID"></param>
957 private void RemoveInventoryFolder(IClientAPI remoteClient, UUID folderID)
958 {
959 CachedUserInfo userInfo
960 = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
961
962 if (userInfo == null)
963 {
964 m_log.Warn("[AGENT INVENTORY]: Failed to find user " + remoteClient.AgentId.ToString());
965 return;
966 }
967
968 if (userInfo.RootFolder != null)
969 {
970 InventoryItemBase folder = userInfo.RootFolder.FindItem(folderID);
971
972 if (folder != null)
973 {
974 m_log.WarnFormat(
975 "[AGENT INVENTORY]: Remove folder not implemented in request by {0} {1} for {2}",
976 remoteClient.Name, remoteClient.AgentId, folderID);
977
978 // doesn't work just yet, commented out. will fix in next patch.
979 // userInfo.DeleteItem(folder);
980 }
981 }
982 }
983
984 private SceneObjectGroup GetGroupByPrim(uint localID)
985 {
986 List<EntityBase> EntityList = GetEntities();
987
988 foreach (EntityBase ent in EntityList)
989 {
990 if (ent is SceneObjectGroup)
991 {
992 if (((SceneObjectGroup) ent).HasChildPrim(localID))
993 return (SceneObjectGroup) ent;
994 }
995 }
996 return null;
997 }
998
999 /// <summary>
1000 /// Send the details of a prim's inventory to the client.
1001 /// </summary>
1002 /// <param name="remoteClient"></param>
1003 /// <param name="primLocalID"></param>
1004 public void RequestTaskInventory(IClientAPI remoteClient, uint primLocalID)
1005 {
1006 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1007 if (group != null)
1008 {
1009 bool fileChange = group.GetPartInventoryFileName(remoteClient, primLocalID);
1010 if (fileChange)
1011 {
1012 if (XferManager != null)
1013 {
1014 group.RequestInventoryFile(remoteClient, primLocalID, XferManager);
1015 }
1016 }
1017 }
1018 else
1019 {
1020 m_log.ErrorFormat(
1021 "[PRIM INVENTORY]: Inventory requested of prim {0} which doesn't exist", primLocalID);
1022 }
1023 }
1024
1025 /// <summary>
1026 /// Remove an item from a prim (task) inventory
1027 /// </summary>
1028 /// <param name="remoteClient">Unused at the moment but retained since the avatar ID might
1029 /// be necessary for a permissions check at some stage.</param>
1030 /// <param name="itemID"></param>
1031 /// <param name="localID"></param>
1032 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
1033 {
1034 SceneObjectPart part = GetSceneObjectPart(localID);
1035 SceneObjectGroup group = part.ParentGroup;
1036 if (group != null)
1037 {
1038 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
1039 if (item == null)
1040 return;
1041
1042 if (item.Type == 10)
1043 {
1044 EventManager.TriggerRemoveScript(localID, itemID);
1045 }
1046 group.RemoveInventoryItem(localID, itemID);
1047 part.GetProperties(remoteClient);
1048 }
1049 else
1050 {
1051 m_log.ErrorFormat(
1052 "[PRIM INVENTORY]: " +
1053 "Removal of item {0} requested of prim {1} but this prim does not exist",
1054 itemID,
1055 localID);
1056 }
1057 }
1058
1059 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
1060 {
1061 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId);
1062
1063 if (null == taskItem)
1064 {
1065 m_log.ErrorFormat(
1066 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for creating an avatar"
1067 + " inventory item from a prim's inventory item "
1068 + " but the required item does not exist in the prim's inventory",
1069 itemId, part.Name, part.UUID);
1070
1071 return null;
1072 }
1073
1074 if ((destAgent != taskItem.OwnerID) && ((taskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1075 {
1076 return null;
1077 }
1078
1079 InventoryItemBase agentItem = new InventoryItemBase();
1080
1081 agentItem.ID = UUID.Random();
1082 agentItem.Creator = taskItem.CreatorID;
1083 agentItem.Owner = destAgent;
1084 agentItem.AssetID = taskItem.AssetID;
1085 agentItem.Description = taskItem.Description;
1086 agentItem.Name = taskItem.Name;
1087 agentItem.AssetType = taskItem.Type;
1088 agentItem.InvType = taskItem.InvType;
1089 agentItem.Flags = taskItem.Flags;
1090
1091 if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions())
1092 {
1093 if (taskItem.InvType == 6)
1094 agentItem.BasePermissions = taskItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13);
1095 else
1096 agentItem.BasePermissions = taskItem.BasePermissions;
1097 agentItem.BasePermissions &= taskItem.NextPermissions;
1098 agentItem.CurrentPermissions = agentItem.BasePermissions | 8;
1099 agentItem.NextPermissions = taskItem.NextPermissions;
1100 agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions;
1101 agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions;
1102 }
1103 else
1104 {
1105 agentItem.BasePermissions = taskItem.BasePermissions;
1106 agentItem.CurrentPermissions = taskItem.CurrentPermissions;
1107 agentItem.NextPermissions = taskItem.NextPermissions;
1108 agentItem.EveryOnePermissions = taskItem.EveryonePermissions;
1109 agentItem.GroupPermissions = taskItem.GroupPermissions;
1110 }
1111
1112 if (!Permissions.BypassPermissions())
1113 {
1114 if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1115 part.Inventory.RemoveInventoryItem(itemId);
1116 }
1117
1118 return agentItem;
1119 }
1120
1121 /// <summary>
1122 /// Move the given item in the given prim to a folder in the client's inventory
1123 /// </summary>
1124 /// <param name="remoteClient"></param>
1125 /// <param name="folderID"></param>
1126 /// <param name="part"></param>
1127 /// <param name="itemID"></param>
1128 public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId)
1129 {
1130 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId);
1131
1132 if (agentItem == null)
1133 return null;
1134
1135 agentItem.Folder = folderId;
1136 AddInventoryItem(remoteClient, agentItem);
1137 return agentItem;
1138 }
1139
1140 /// <summary>
1141 /// <see>ClientMoveTaskInventoryItem</see>
1142 /// </summary>
1143 /// <param name="remoteClient"></param>
1144 /// <param name="folderID"></param>
1145 /// <param name="primLocalID"></param>
1146 /// <param name="itemID"></param>
1147 public void ClientMoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, uint primLocalId, UUID itemId)
1148 {
1149 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1150
1151 if (null == part)
1152 {
1153 m_log.WarnFormat(
1154 "[PRIM INVENTORY]: " +
1155 "Move of inventory item {0} from prim with local id {1} failed because the prim could not be found",
1156 itemId, primLocalId);
1157
1158 return;
1159 }
1160
1161 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId);
1162
1163 if (null == taskItem)
1164 {
1165 m_log.WarnFormat("[PRIM INVENTORY]: Move of inventory item {0} from prim with local id {1} failed"
1166 + " because the inventory item could not be found",
1167 itemId, primLocalId);
1168
1169 return;
1170 }
1171
1172 // Only owner can copy
1173 if (remoteClient.AgentId != taskItem.OwnerID)
1174 return;
1175
1176 MoveTaskInventoryItem(remoteClient, folderId, part, itemId);
1177 }
1178
1179 /// <summary>
1180 /// <see>MoveTaskInventoryItem</see>
1181 /// </summary>
1182 /// <param name="remoteClient"></param>
1183 /// <param name="folderID"></param>
1184 /// <param name="part"></param>
1185 /// <param name="itemID"></param>
1186 public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId)
1187 {
1188 ScenePresence avatar;
1189
1190 if (TryGetAvatar(avatarId, out avatar))
1191 {
1192 return MoveTaskInventoryItem(avatar.ControllingClient, folderId, part, itemId);
1193 }
1194 else
1195 {
1196 CachedUserInfo profile = CommsManager.UserProfileCacheService.GetUserDetails(avatarId);
1197 if (profile == null || profile.RootFolder == null)
1198 {
1199 m_log.ErrorFormat(
1200 "[PRIM INVENTORY]: " +
1201 "Avatar {0} cannot be found to add item",
1202 avatarId);
1203 }
1204 if (!profile.HasReceivedInventory)
1205 CommsManager.UserProfileCacheService.RequestInventoryForUser(avatarId);
1206 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(avatarId, part, itemId);
1207
1208 if (agentItem == null)
1209 return null;
1210
1211 agentItem.Folder = folderId;
1212
1213 AddInventoryItem(avatarId, agentItem);
1214
1215 return agentItem;
1216 }
1217 }
1218
1219 /// <summary>
1220 /// Copy a task (prim) inventory item to another task (prim)
1221 /// </summary>
1222 /// <param name="destId"></param>
1223 /// <param name="part"></param>
1224 /// <param name="itemId"></param>
1225 public void MoveTaskInventoryItem(UUID destId, SceneObjectPart part, UUID itemId)
1226 {
1227 TaskInventoryItem srcTaskItem = part.Inventory.GetInventoryItem(itemId);
1228
1229 if (srcTaskItem == null)
1230 {
1231 m_log.ErrorFormat(
1232 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for moving"
1233 + " but the item does not exist in this inventory",
1234 itemId, part.Name, part.UUID);
1235
1236 return;
1237 }
1238
1239 SceneObjectPart destPart = GetSceneObjectPart(destId);
1240
1241 if (destPart == null)
1242 {
1243 m_log.ErrorFormat(
1244 "[PRIM INVENTORY]: " +
1245 "Could not find prim for ID {0}",
1246 destId);
1247 return;
1248 }
1249
1250 // Can't transfer this
1251 //
1252 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1253 return;
1254
1255 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1256 {
1257 // object cannot copy items to an object owned by a different owner
1258 // unless llAllowInventoryDrop has been called
1259
1260 return;
1261 }
1262
1263 // must have both move and modify permission to put an item in an object
1264 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0)
1265 {
1266 return;
1267 }
1268
1269 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1270
1271 destTaskItem.ItemID = UUID.Random();
1272 destTaskItem.CreatorID = srcTaskItem.CreatorID;
1273 destTaskItem.AssetID = srcTaskItem.AssetID;
1274 destTaskItem.GroupID = destPart.GroupID;
1275 destTaskItem.OwnerID = destPart.OwnerID;
1276 destTaskItem.ParentID = destPart.UUID;
1277 destTaskItem.ParentPartID = destPart.UUID;
1278
1279 destTaskItem.BasePermissions = srcTaskItem.BasePermissions;
1280 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions;
1281 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions;
1282 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions;
1283 destTaskItem.NextPermissions = srcTaskItem.NextPermissions;
1284 destTaskItem.Flags = srcTaskItem.Flags;
1285
1286 if (destPart.OwnerID != part.OwnerID)
1287 {
1288 if (Permissions.PropagatePermissions())
1289 {
1290 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions &
1291 srcTaskItem.NextPermissions;
1292 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions &
1293 srcTaskItem.NextPermissions;
1294 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions &
1295 srcTaskItem.NextPermissions;
1296 destTaskItem.BasePermissions = srcTaskItem.BasePermissions &
1297 srcTaskItem.NextPermissions;
1298 destTaskItem.CurrentPermissions |= 8; // Slam!
1299 }
1300 }
1301
1302 destTaskItem.Description = srcTaskItem.Description;
1303 destTaskItem.Name = srcTaskItem.Name;
1304 destTaskItem.InvType = srcTaskItem.InvType;
1305 destTaskItem.Type = srcTaskItem.Type;
1306
1307 destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID);
1308
1309 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1310 part.Inventory.RemoveInventoryItem(itemId);
1311
1312 ScenePresence avatar;
1313
1314 if (TryGetAvatar(srcTaskItem.OwnerID, out avatar))
1315 {
1316 destPart.GetProperties(avatar.ControllingClient);
1317 }
1318 }
1319
1320 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1321 {
1322 CachedUserInfo profile = CommsManager.UserProfileCacheService.GetUserDetails(destID);
1323 if (profile == null || profile.RootFolder == null)
1324 {
1325 m_log.ErrorFormat(
1326 "[PRIM INVENTORY]: " +
1327 "Avatar {0} cannot be found to add items",
1328 destID);
1329 return UUID.Zero;
1330 }
1331
1332 UUID newFolderID = UUID.Random();
1333
1334 profile.CreateFolder(category, newFolderID, 0xffff, profile.RootFolder.ID);
1335
1336 foreach (UUID itemID in items)
1337 {
1338 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host, itemID);
1339
1340 if (agentItem != null)
1341 {
1342 agentItem.Folder = newFolderID;
1343
1344 AddInventoryItem(destID, agentItem);
1345 }
1346 }
1347
1348 ScenePresence avatar;
1349
1350 if (TryGetAvatar(destID, out avatar))
1351 {
1352 profile.SendInventoryDecendents(avatar.ControllingClient,
1353 profile.RootFolder.ID, true, false);
1354 profile.SendInventoryDecendents(avatar.ControllingClient,
1355 newFolderID, false, true);
1356 }
1357
1358 return newFolderID;
1359 }
1360
1361 /// <summary>
1362 /// Update an item in a prim (task) inventory.
1363 /// This method does not handle scripts, <see>RezScript(IClientAPI, UUID, unit)</see>
1364 /// </summary>
1365 /// <param name="remoteClient"></param>
1366 /// <param name="transactionID"></param>
1367 /// <param name="itemInfo"></param>
1368 /// <param name="primLocalID"></param>
1369 public void UpdateTaskInventory(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem itemInfo,
1370 uint primLocalID)
1371 {
1372 UUID itemID = itemInfo.ItemID;
1373
1374 // Find the prim we're dealing with
1375 SceneObjectPart part = GetSceneObjectPart(primLocalID);
1376
1377 if (part != null)
1378 {
1379 TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID);
1380 bool allowInventoryDrop = (part.GetEffectiveObjectFlags()
1381 & (uint)PrimFlags.AllowInventoryDrop) != 0;
1382
1383 // Explicity allow anyone to add to the inventory if the
1384 // AllowInventoryDrop flag has been set. Don't however let
1385 // them update an item unless they pass the external checks
1386 //
1387 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)
1388 && (currentItem != null || !allowInventoryDrop))
1389 return;
1390
1391 if (currentItem == null)
1392 {
1393 UUID copyID = UUID.Random();
1394 if (itemID != UUID.Zero)
1395 {
1396 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
1397
1398 if (userInfo != null && userInfo.RootFolder != null)
1399 {
1400 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
1401
1402 // Try library
1403 // XXX clumsy, possibly should be one call
1404 if (null == item)
1405 {
1406 item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID);
1407 }
1408
1409 if (item != null)
1410 {
1411 part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID);
1412 m_log.InfoFormat(
1413 "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}",
1414 item.Name, primLocalID, remoteClient.Name);
1415 part.GetProperties(remoteClient);
1416 if (!Permissions.BypassPermissions())
1417 {
1418 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1419 RemoveInventoryItem(remoteClient, itemID);
1420 }
1421 }
1422 else
1423 {
1424 m_log.ErrorFormat(
1425 "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!",
1426 itemID, remoteClient.Name);
1427 }
1428 }
1429 }
1430 }
1431 else // Updating existing item with new perms etc
1432 {
1433 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
1434 if (agentTransactions != null)
1435 {
1436 agentTransactions.HandleTaskItemUpdateFromTransaction(
1437 remoteClient, part, transactionID, currentItem);
1438 }
1439 if (part.Inventory.UpdateInventoryItem(itemInfo))
1440 part.GetProperties(remoteClient);
1441 }
1442 }
1443 else
1444 {
1445 m_log.WarnFormat(
1446 "[PRIM INVENTORY]: " +
1447 "Update with item {0} requested of prim {1} for {2} but this prim does not exist",
1448 itemID, primLocalID, remoteClient.Name);
1449 }
1450 }
1451
1452 /// <summary>
1453 /// Rez a script into a prim's inventory, either ex nihilo or from an existing avatar inventory
1454 /// </summary>
1455 /// <param name="remoteClient"></param>
1456 /// <param name="itemID"> </param>
1457 /// <param name="localID"></param>
1458 public void RezScript(IClientAPI remoteClient, InventoryItemBase itemBase, UUID transactionID, uint localID)
1459 {
1460 UUID itemID = itemBase.ID;
1461 UUID copyID = UUID.Random();
1462
1463 if (itemID != UUID.Zero) // transferred from an avatar inventory to the prim's inventory
1464 {
1465 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
1466
1467 if (userInfo != null && userInfo.RootFolder != null)
1468 {
1469 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
1470
1471 // Try library
1472 // XXX clumsy, possibly should be one call
1473 if (null == item)
1474 {
1475 item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID);
1476 }
1477
1478 if (item != null)
1479 {
1480 SceneObjectPart part = GetSceneObjectPart(localID);
1481 if (part != null)
1482 {
1483 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
1484 return;
1485
1486 part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID);
1487 // TODO: switch to posting on_rez here when scripts
1488 // have state in inventory
1489 part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0);
1490
1491 // m_log.InfoFormat("[PRIMINVENTORY]: " +
1492 // "Rezzed script {0} into prim local ID {1} for user {2}",
1493 // item.inventoryName, localID, remoteClient.Name);
1494 part.GetProperties(remoteClient);
1495 }
1496 else
1497 {
1498 m_log.ErrorFormat(
1499 "[PRIM INVENTORY]: " +
1500 "Could not rez script {0} into prim local ID {1} for user {2}"
1501 + " because the prim could not be found in the region!",
1502 item.Name, localID, remoteClient.Name);
1503 }
1504 }
1505 else
1506 {
1507 m_log.ErrorFormat(
1508 "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!",
1509 itemID, remoteClient.Name);
1510 }
1511 }
1512 }
1513 else // script has been rezzed directly into a prim's inventory
1514 {
1515 SceneObjectPart part = GetSceneObjectPart(itemBase.Folder);
1516 if (part == null)
1517 return;
1518
1519 if (part.OwnerID != remoteClient.AgentId)
1520 return;
1521
1522 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1523 return;
1524
1525 if (!Permissions.CanCreateObjectInventory(
1526 itemBase.InvType, part.UUID, remoteClient.AgentId))
1527 return;
1528
1529 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"));
1530 AssetCache.AddAsset(asset);
1531
1532 TaskInventoryItem taskItem = new TaskInventoryItem();
1533
1534 taskItem.ResetIDs(itemBase.Folder);
1535 taskItem.ParentID = itemBase.Folder;
1536 taskItem.CreationDate = (uint)itemBase.CreationDate;
1537 taskItem.Name = itemBase.Name;
1538 taskItem.Description = itemBase.Description;
1539 taskItem.Type = itemBase.AssetType;
1540 taskItem.InvType = itemBase.InvType;
1541 taskItem.OwnerID = itemBase.Owner;
1542 taskItem.CreatorID = itemBase.Creator;
1543 taskItem.BasePermissions = itemBase.BasePermissions;
1544 taskItem.CurrentPermissions = itemBase.CurrentPermissions;
1545 taskItem.EveryonePermissions = itemBase.EveryOnePermissions;
1546 taskItem.GroupPermissions = itemBase.GroupPermissions;
1547 taskItem.NextPermissions = itemBase.NextPermissions;
1548 taskItem.GroupID = itemBase.GroupID;
1549 taskItem.GroupPermissions = 0;
1550 taskItem.Flags = itemBase.Flags;
1551 taskItem.PermsGranter = UUID.Zero;
1552 taskItem.PermsMask = 0;
1553 taskItem.AssetID = asset.Metadata.FullID;
1554
1555 part.Inventory.AddInventoryItem(taskItem, false);
1556 part.GetProperties(remoteClient);
1557
1558 part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
1559 }
1560 }
1561
1562 /// <summary>
1563 /// Rez a script into a prim's inventory from another prim
1564 /// </summary>
1565 /// <param name="remoteClient"></param>
1566 /// <param name="itemID"> </param>
1567 /// <param name="localID"></param>
1568 public void RezScript(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param)
1569 {
1570 TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId);
1571
1572 if (srcTaskItem == null)
1573 {
1574 m_log.ErrorFormat(
1575 "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for rezzing a script but the "
1576 + " item does not exist in this inventory",
1577 srcId, srcPart.Name, srcPart.UUID);
1578
1579 return;
1580 }
1581
1582 SceneObjectPart destPart = GetSceneObjectPart(destId);
1583
1584 if (destPart == null)
1585 {
1586 m_log.ErrorFormat(
1587 "[PRIM INVENTORY]: " +
1588 "Could not find script for ID {0}",
1589 destId);
1590 return;
1591 }
1592
1593 // Must own the object, and have modify rights
1594 if (srcPart.OwnerID != destPart.OwnerID)
1595 return;
1596
1597 if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0)
1598 return;
1599
1600 if (destPart.ScriptAccessPin != pin)
1601 {
1602 m_log.WarnFormat(
1603 "[PRIM INVENTORY]: " +
1604 "Script in object {0} : {1}, attempted to load script {2} : {3} into object {4} : {5} with invalid pin {6}",
1605 srcPart.Name, srcId, srcTaskItem.Name, srcTaskItem.ItemID, destPart.Name, destId, pin);
1606 // the LSL Wiki says we are supposed to shout on the DEBUG_CHANNEL -
1607 // "Object: Task Object trying to illegally load script onto task Other_Object!"
1608 // How do we shout from in here?
1609 return;
1610 }
1611
1612 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1613
1614 destTaskItem.ItemID = UUID.Random();
1615 destTaskItem.CreatorID = srcTaskItem.CreatorID;
1616 destTaskItem.AssetID = srcTaskItem.AssetID;
1617 destTaskItem.GroupID = destPart.GroupID;
1618 destTaskItem.OwnerID = destPart.OwnerID;
1619 destTaskItem.ParentID = destPart.UUID;
1620 destTaskItem.ParentPartID = destPart.UUID;
1621
1622 destTaskItem.BasePermissions = srcTaskItem.BasePermissions;
1623 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions;
1624 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions;
1625 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions;
1626 destTaskItem.NextPermissions = srcTaskItem.NextPermissions;
1627 destTaskItem.Flags = srcTaskItem.Flags;
1628
1629 if (destPart.OwnerID != srcPart.OwnerID)
1630 {
1631 if (Permissions.PropagatePermissions())
1632 {
1633 destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions &
1634 srcTaskItem.NextPermissions;
1635 destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions &
1636 srcTaskItem.NextPermissions;
1637 destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions &
1638 srcTaskItem.NextPermissions;
1639 destTaskItem.BasePermissions = srcTaskItem.BasePermissions &
1640 srcTaskItem.NextPermissions;
1641 destTaskItem.CurrentPermissions |= 8; // Slam!
1642 }
1643 }
1644
1645 destTaskItem.Description = srcTaskItem.Description;
1646 destTaskItem.Name = srcTaskItem.Name;
1647 destTaskItem.InvType = srcTaskItem.InvType;
1648 destTaskItem.Type = srcTaskItem.Type;
1649
1650 destPart.Inventory.AddInventoryItemExclusive(destTaskItem, false);
1651
1652 if (running > 0)
1653 {
1654 destPart.Inventory.CreateScriptInstance(destTaskItem, 0, false, DefaultScriptEngine, 0);
1655 }
1656
1657 ScenePresence avatar;
1658
1659 if (TryGetAvatar(srcTaskItem.OwnerID, out avatar))
1660 {
1661 destPart.GetProperties(avatar.ControllingClient);
1662 }
1663 }
1664
1665 /// <summary>
1666 /// Called when an object is removed from the environment into inventory.
1667 /// </summary>
1668 /// <param name="remoteClient"></param>
1669 /// <param name="localID"></param>
1670 /// <param name="groupID"></param>
1671 /// <param name="action"></param>
1672 /// <param name="destinationID"></param>
1673 public virtual void DeRezObject(IClientAPI remoteClient, uint localID,
1674 UUID groupID, DeRezAction action, UUID destinationID)
1675 {
1676 SceneObjectPart part = GetSceneObjectPart(localID);
1677 if (part == null)
1678 return;
1679
1680 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1681 return;
1682
1683 // Can't delete child prims
1684 if (part != part.ParentGroup.RootPart)
1685 return;
1686
1687 SceneObjectGroup grp = part.ParentGroup;
1688
1689 //force a database backup/update on this SceneObjectGroup
1690 //So that we know the database is upto date, for when deleting the object from it
1691 ForceSceneObjectBackup(grp);
1692
1693 bool permissionToTake = false;
1694 bool permissionToDelete = false;
1695
1696 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1697 {
1698 if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero)
1699 {
1700 permissionToTake = true;
1701 permissionToDelete = false;
1702 }
1703 }
1704 else if (action == DeRezAction.TakeCopy)
1705 {
1706 permissionToTake =
1707 Permissions.CanTakeCopyObject(
1708 grp.UUID,
1709 remoteClient.AgentId);
1710 }
1711 else if (action == DeRezAction.GodTakeCopy)
1712 {
1713 permissionToTake =
1714 Permissions.IsGod(
1715 remoteClient.AgentId);
1716 }
1717 else if (action == DeRezAction.Take)
1718 {
1719 permissionToTake =
1720 Permissions.CanTakeObject(
1721 grp.UUID,
1722 remoteClient.AgentId);
1723
1724 //If they can take, they can delete!
1725 permissionToDelete = permissionToTake;
1726 }
1727 else if (action == DeRezAction.Delete)
1728 {
1729 permissionToTake =
1730 Permissions.CanDeleteObject(
1731 grp.UUID,
1732 remoteClient.AgentId);
1733 permissionToDelete = permissionToTake;
1734 }
1735 else if (action == DeRezAction.Return)
1736 {
1737 if (remoteClient != null)
1738 {
1739 permissionToTake =
1740 Permissions.CanReturnObject(
1741 grp.UUID,
1742 remoteClient.AgentId);
1743 permissionToDelete = permissionToTake;
1744
1745 if (permissionToDelete)
1746 {
1747 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1748 }
1749 }
1750 else // Auto return passes through here with null agent
1751 {
1752 permissionToTake = true;
1753 permissionToDelete = true;
1754 }
1755 }
1756 else
1757 {
1758 m_log.DebugFormat(
1759 "[AGENT INVENTORY]: Ignoring unexpected derez action {0} for {1}", action, remoteClient.Name);
1760 return;
1761 }
1762
1763 if (permissionToTake)
1764 {
1765 m_asyncSceneObjectDeleter.DeleteToInventory(
1766 action, destinationID, grp, remoteClient,
1767 permissionToDelete);
1768 }
1769 else if (permissionToDelete)
1770 {
1771 DeleteSceneObject(grp, false);
1772 }
1773 }
1774
1775 private bool WaitForInventory(CachedUserInfo info)
1776 {
1777 // 200 Seconds wait. This is called in the context of the
1778 // background delete thread, so we can afford to waste time
1779 // here.
1780 //
1781 int count = 200;
1782
1783 while (count > 0)
1784 {
1785 System.Threading.Thread.Sleep(100);
1786 count--;
1787 if (info.HasReceivedInventory)
1788 return true;
1789 }
1790 m_log.DebugFormat("Timed out waiting for inventory of user {0}",
1791 info.UserProfile.ID.ToString());
1792 return false;
1793 }
1794
1795 /// <summary>
1796 /// Delete a scene object from a scene and place in the given avatar's inventory.
1797 /// Returns the UUID of the newly created asset.
1798 /// </summary>
1799 /// <param name="action"></param>
1800 /// <param name="folderID"></param>
1801 /// <param name="objectGroup"></param>
1802 /// <param name="remoteClient"> </param>
1803 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
1804 SceneObjectGroup objectGroup, IClientAPI remoteClient)
1805 {
1806 UUID assetID = UUID.Zero;
1807
1808 string sceneObjectXml = objectGroup.ToXmlString();
1809
1810 // Get the user info of the item destination
1811 //
1812 CachedUserInfo userInfo;
1813
1814 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
1815 action == DeRezAction.SaveToExistingUserInventoryItem)
1816 {
1817 // Take or take copy require a taker
1818 // Saving changes requires a local user
1819 //
1820 if (remoteClient == null)
1821 return UUID.Zero;
1822
1823 userInfo = CommsManager.UserProfileCacheService.GetUserDetails(
1824 remoteClient.AgentId);
1825 }
1826 else
1827 {
1828 // All returns / deletes go to the object owner
1829 //
1830 userInfo = CommsManager.UserProfileCacheService.GetUserDetails(
1831 objectGroup.RootPart.OwnerID);
1832 }
1833
1834 if (userInfo == null) // Can't proceed
1835 {
1836 return UUID.Zero;
1837 }
1838
1839 if (!userInfo.HasReceivedInventory)
1840 {
1841 // Async inventory requests will queue, but they will never
1842 // execute unless inventory is actually fetched
1843 //
1844 CommsManager.UserProfileCacheService.RequestInventoryForUser(
1845 userInfo.UserProfile.ID);
1846 }
1847
1848 if (userInfo != null)
1849 {
1850 // If we're returning someone's item, it goes back to the
1851 // owner's Lost And Found folder.
1852 // Delete is treated like return in this case
1853 // Deleting your own items makes them go to trash
1854 //
1855
1856 InventoryFolderBase folder = null;
1857 InventoryItemBase item = null;
1858
1859 if (DeRezAction.SaveToExistingUserInventoryItem == action)
1860 {
1861 item = userInfo.RootFolder.FindItem(
1862 objectGroup.RootPart.FromUserInventoryItemID);
1863
1864 if (null == item)
1865 {
1866 m_log.DebugFormat(
1867 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
1868 objectGroup.Name, objectGroup.UUID);
1869 return UUID.Zero;
1870 }
1871 }
1872 else
1873 {
1874 // Folder magic
1875 //
1876 if (action == DeRezAction.Delete)
1877 {
1878 // Deleting someone else's item
1879 //
1880 if (remoteClient == null ||
1881 objectGroup.OwnerID != remoteClient.AgentId)
1882 {
1883 // Folder skeleton may not be loaded and we
1884 // have to wait for the inventory to find
1885 // the destination folder
1886 //
1887 if (!WaitForInventory(userInfo))
1888 return UUID.Zero;
1889 folder = userInfo.FindFolderForType(
1890 (int)AssetType.LostAndFoundFolder);
1891 }
1892 else
1893 {
1894 // Assume inventory skeleton was loaded during login
1895 // and all folders can be found
1896 //
1897 folder = userInfo.FindFolderForType(
1898 (int)AssetType.TrashFolder);
1899 }
1900 }
1901 else if (action == DeRezAction.Return)
1902 {
1903 // Wait if needed
1904 //
1905 if (!userInfo.HasReceivedInventory)
1906 {
1907 if (!WaitForInventory(userInfo))
1908 return UUID.Zero;
1909 }
1910
1911 // Dump to lost + found unconditionally
1912 //
1913 folder = userInfo.FindFolderForType(
1914 (int)AssetType.LostAndFoundFolder);
1915 }
1916
1917 if (folderID == UUID.Zero && folder == null)
1918 {
1919 // Catch all. Use lost & found
1920 //
1921 if (!userInfo.HasReceivedInventory)
1922 {
1923 if (!WaitForInventory(userInfo))
1924 return UUID.Zero;
1925 }
1926
1927 folder = userInfo.FindFolderForType(
1928 (int)AssetType.LostAndFoundFolder);
1929 }
1930
1931 if (folder == null) // None of the above
1932 {
1933 folder = userInfo.RootFolder.FindFolder(folderID);
1934
1935 if (folder == null) // Nowhere to put it
1936 {
1937 return UUID.Zero;
1938 }
1939 }
1940
1941 item = new InventoryItemBase();
1942 item.Creator = objectGroup.RootPart.CreatorID;
1943 item.ID = UUID.Random();
1944 item.InvType = (int)InventoryType.Object;
1945 item.Folder = folder.ID;
1946 item.Owner = userInfo.UserProfile.ID;
1947
1948 }
1949
1950 AssetBase asset = CreateAsset(
1951 objectGroup.GetPartName(objectGroup.RootPart.LocalId),
1952 objectGroup.GetPartDescription(objectGroup.RootPart.LocalId),
1953 (sbyte)AssetType.Object,
1954 Utils.StringToBytes(sceneObjectXml));
1955 AssetCache.AddAsset(asset);
1956 assetID = asset.Metadata.FullID;
1957
1958 if (DeRezAction.SaveToExistingUserInventoryItem == action)
1959 {
1960 item.AssetID = asset.Metadata.FullID;
1961 userInfo.UpdateItem(item);
1962 }
1963 else
1964 {
1965 item.AssetID = asset.Metadata.FullID;
1966
1967 if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && Permissions.PropagatePermissions())
1968 {
1969 uint perms=objectGroup.GetEffectivePermissions();
1970 uint nextPerms=(perms & 7) << 13;
1971 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
1972 perms &= ~(uint)PermissionMask.Copy;
1973 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
1974 perms &= ~(uint)PermissionMask.Transfer;
1975 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
1976 perms &= ~(uint)PermissionMask.Modify;
1977
1978 item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask;
1979 item.CurrentPermissions = item.BasePermissions;
1980 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
1981 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask;
1982 item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask;
1983 item.CurrentPermissions |= 8; // Slam!
1984 }
1985 else
1986 {
1987 item.BasePermissions = objectGroup.GetEffectivePermissions();
1988 item.CurrentPermissions = objectGroup.GetEffectivePermissions();
1989 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
1990 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask;
1991 item.GroupPermissions = objectGroup.RootPart.GroupMask;
1992
1993 item.CurrentPermissions |= 8; // Slam!
1994 }
1995
1996 // TODO: add the new fields (Flags, Sale info, etc)
1997 item.CreationDate = Util.UnixTimeSinceEpoch();
1998 item.Description = asset.Metadata.Description;
1999 item.Name = asset.Metadata.Name;
2000 item.AssetType = asset.Metadata.Type;
2001
2002 userInfo.AddItem(item);
2003
2004 if (remoteClient != null && item.Owner == remoteClient.AgentId)
2005 {
2006 remoteClient.SendInventoryItemCreateUpdate(item);
2007 }
2008 else
2009 {
2010 ScenePresence notifyUser = GetScenePresence(item.Owner);
2011 if (notifyUser != null)
2012 {
2013 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item);
2014 }
2015 }
2016 }
2017 }
2018
2019 return assetID;
2020 }
2021
2022 public void updateKnownAsset(IClientAPI remoteClient, SceneObjectGroup grp, UUID assetID, UUID agentID)
2023 {
2024 SceneObjectGroup objectGroup = grp;
2025 if (objectGroup != null)
2026 {
2027 if (!grp.HasGroupChanged)
2028 {
2029 m_log.InfoFormat("[ATTACHMENT]: Save request for {0} which is unchanged", grp.UUID);
2030 return;
2031 }
2032
2033 m_log.InfoFormat(
2034 "[ATTACHMENT]: Updating asset for attachment {0}, attachpoint {1}",
2035 grp.UUID, grp.GetAttachmentPoint());
2036
2037 string sceneObjectXml = objectGroup.ToXmlString();
2038
2039 CachedUserInfo userInfo =
2040 CommsManager.UserProfileCacheService.GetUserDetails(agentID);
2041 if (userInfo != null && userInfo.RootFolder != null)
2042 {
2043 Queue<InventoryFolderImpl> searchfolders = new Queue<InventoryFolderImpl>();
2044 searchfolders.Enqueue(userInfo.RootFolder);
2045
2046 UUID foundFolder = UUID.Zero;
2047 InventoryItemBase item = null;
2048
2049 // search through folders to find the asset.
2050 while (searchfolders.Count > 0)
2051 {
2052 InventoryFolderImpl fld = searchfolders.Dequeue();
2053 lock (fld)
2054 {
2055 if (fld != null)
2056 {
2057 if (fld.Items.ContainsKey(assetID))
2058 {
2059 item = fld.Items[assetID];
2060 foundFolder = fld.ID;
2061 searchfolders.Clear();
2062 break;
2063 }
2064 else
2065 {
2066 foreach (InventoryFolderImpl subfld in fld.RequestListOfFolderImpls())
2067 {
2068 searchfolders.Enqueue(subfld);
2069 }
2070 }
2071 }
2072 }
2073 }
2074
2075 if (foundFolder != UUID.Zero && item != null)
2076 {
2077 AssetBase asset = CreateAsset(
2078 objectGroup.GetPartName(objectGroup.LocalId),
2079 objectGroup.GetPartDescription(objectGroup.LocalId),
2080 (sbyte)AssetType.Object,
2081 Utils.StringToBytes(sceneObjectXml));
2082 AssetCache.AddAsset(asset);
2083
2084 item.AssetID = asset.Metadata.FullID;
2085 item.Description = asset.Metadata.Description;
2086 item.Name = asset.Metadata.Name;
2087 item.AssetType = asset.Metadata.Type;
2088 item.InvType = (int)InventoryType.Object;
2089 item.Folder = foundFolder;
2090
2091 userInfo.UpdateItem(item);
2092
2093 // this gets called when the agent loggs off!
2094 if (remoteClient != null)
2095 {
2096 remoteClient.SendInventoryItemCreateUpdate(item);
2097 }
2098 }
2099 }
2100 }
2101 }
2102
2103 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2104 {
2105 itemID = UUID.Zero;
2106 if (grp != null)
2107 {
2108 string sceneObjectXml = grp.ToXmlString();
2109
2110 CachedUserInfo userInfo =
2111 CommsManager.UserProfileCacheService.GetUserDetails(AgentId);
2112 if (userInfo != null)
2113 {
2114 AssetBase asset = CreateAsset(
2115 grp.GetPartName(grp.LocalId),
2116 grp.GetPartDescription(grp.LocalId),
2117 (sbyte)AssetType.Object,
2118 Utils.StringToBytes(sceneObjectXml));
2119 AssetCache.AddAsset(asset);
2120
2121 InventoryItemBase item = new InventoryItemBase();
2122 item.Creator = grp.RootPart.CreatorID;
2123 item.Owner = remoteClient.AgentId;
2124 item.ID = UUID.Random();
2125 item.AssetID = asset.Metadata.FullID;
2126 item.Description = asset.Metadata.Description;
2127 item.Name = asset.Metadata.Name;
2128 item.AssetType = asset.Metadata.Type;
2129 item.InvType = (int)InventoryType.Object;
2130
2131 item.Folder = UUID.Zero; // Objects folder!
2132
2133 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2134 {
2135 item.BasePermissions = grp.RootPart.NextOwnerMask;
2136 item.CurrentPermissions = grp.RootPart.NextOwnerMask;
2137 item.NextPermissions = grp.RootPart.NextOwnerMask;
2138 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2139 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2140 }
2141 else
2142 {
2143 item.BasePermissions = grp.RootPart.BaseMask;
2144 item.CurrentPermissions = grp.RootPart.OwnerMask;
2145 item.NextPermissions = grp.RootPart.NextOwnerMask;
2146 item.EveryOnePermissions = grp.RootPart.EveryoneMask;
2147 item.GroupPermissions = grp.RootPart.GroupMask;
2148 }
2149 item.CreationDate = Util.UnixTimeSinceEpoch();
2150
2151 // sets assetID so client can show asset as 'attached' in inventory
2152 grp.SetFromAssetID(item.ID);
2153
2154 userInfo.AddItem(item);
2155 remoteClient.SendInventoryItemCreateUpdate(item);
2156
2157 itemID = item.ID;
2158 return item.AssetID;
2159 }
2160 return UUID.Zero;
2161 }
2162 return UUID.Zero;
2163 }
2164
2165 /// <summary>
2166 /// Event Handler Rez an object into a scene
2167 /// Calls the non-void event handler
2168 /// </summary>
2169 /// <param name="remoteClient"></param>
2170 /// <param name="itemID"></param>
2171 /// <param name="RayEnd"></param>
2172 /// <param name="RayStart"></param>
2173 /// <param name="RayTargetID"></param>
2174 /// <param name="BypassRayCast"></param>
2175 /// <param name="RayEndIsIntersection"></param>
2176 /// <param name="EveryoneMask"></param>
2177 /// <param name="GroupMask"></param>
2178 /// <param name="RezSelected"></param>
2179 /// <param name="RemoveItem"></param>
2180 /// <param name="fromTaskID"></param>
2181 public virtual void RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
2182 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
2183 bool RezSelected, bool RemoveItem, UUID fromTaskID)
2184 {
2185 RezObject(
2186 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
2187 RezSelected, RemoveItem, fromTaskID, false);
2188 }
2189
2190 /// <summary>
2191 /// Rez an object into the scene from the user's inventory
2192 /// </summary>
2193 /// <param name="remoteClient"></param>
2194 /// <param name="itemID"></param>
2195 /// <param name="RayEnd"></param>
2196 /// <param name="RayStart"></param>
2197 /// <param name="RayTargetID"></param>
2198 /// <param name="BypassRayCast"></param>
2199 /// <param name="RayEndIsIntersection"></param>
2200 /// <param name="RezSelected"></param>
2201 /// <param name="RemoveItem"></param>
2202 /// <param name="fromTaskID"></param>
2203 /// <param name="attachment"></param>
2204 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns>
2205 public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
2206 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
2207 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
2208 {
2209 // Work out position details
2210 byte bRayEndIsIntersection = (byte)0;
2211
2212 if (RayEndIsIntersection)
2213 {
2214 bRayEndIsIntersection = (byte)1;
2215 }
2216 else
2217 {
2218 bRayEndIsIntersection = (byte)0;
2219 }
2220
2221 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
2222
2223
2224 Vector3 pos = GetNewRezLocation(
2225 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2226 BypassRayCast, bRayEndIsIntersection,true,scale, false);
2227
2228 // Rez object
2229 CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
2230 if (userInfo != null)
2231 {
2232 // Do NOT use HasReceivedInventory here, this is called
2233 // from within ItemReceive during login for attachments.
2234 // Using HasReceivedInventory here will break attachment
2235 // persistence!
2236 //
2237 if (userInfo.RootFolder != null)
2238 {
2239 InventoryItemBase item = userInfo.RootFolder.FindItem(itemID);
2240
2241 if (item != null)
2242 {
2243 AssetBase rezAsset = AssetCache.GetAsset(item.AssetID, false);
2244
2245 if (rezAsset != null)
2246 {
2247 UUID itemId = UUID.Zero;
2248
2249 // If we have permission to copy then link the rezzed object back to the user inventory
2250 // item that it came from. This allows us to enable 'save object to inventory'
2251 if (!Permissions.BypassPermissions())
2252 {
2253 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy)
2254 {
2255 itemId = item.ID;
2256 }
2257 }
2258
2259 string xmlData = Utils.BytesToString(rezAsset.Data);
2260 SceneObjectGroup group = new SceneObjectGroup(itemId, xmlData, true);
2261
2262 if (!Permissions.CanRezObject(
2263 group.Children.Count, remoteClient.AgentId, pos)
2264 && !attachment)
2265 {
2266 return null;
2267 }
2268
2269 group.ResetIDs();
2270
2271 AddNewSceneObject(group, true);
2272
2273 // if attachment we set it's asset id so object updates can reflect that
2274 // if not, we set it's position in world.
2275 if (!attachment)
2276 {
2277 pos = GetNewRezLocation(
2278 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2279 BypassRayCast, bRayEndIsIntersection, true, group.GroupScale(), false);
2280 group.AbsolutePosition = pos;
2281 }
2282 else
2283 {
2284 group.SetFromAssetID(itemID);
2285 }
2286
2287 SceneObjectPart rootPart = null;
2288 try
2289 {
2290 rootPart = group.GetChildPart(group.UUID);
2291 }
2292 catch (NullReferenceException)
2293 {
2294 string isAttachment = "";
2295
2296 if (attachment)
2297 isAttachment = " Object was an attachment";
2298
2299 m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
2300 }
2301
2302 // Since renaming the item in the inventory does not affect the name stored
2303 // in the serialization, transfer the correct name from the inventory to the
2304 // object itself before we rez.
2305 rootPart.Name = item.Name;
2306 rootPart.Description = item.Description;
2307
2308 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values);
2309
2310 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
2311 if (rootPart.OwnerID != item.Owner)
2312 {
2313 //Need to kill the for sale here
2314 rootPart.ObjectSaleType = 0;
2315 rootPart.SalePrice = 10;
2316
2317 if (Permissions.PropagatePermissions())
2318 {
2319 if ((item.CurrentPermissions & 8) != 0)
2320 {
2321 foreach (SceneObjectPart part in partList)
2322 {
2323 part.EveryoneMask = item.EveryOnePermissions;
2324 part.NextOwnerMask = item.NextPermissions;
2325 part.GroupMask = 0; // DO NOT propagate here
2326 }
2327 }
2328 group.ApplyNextOwnerPermissions();
2329 }
2330 }
2331
2332 foreach (SceneObjectPart part in partList)
2333 {
2334 if (part.OwnerID != item.Owner)
2335 {
2336 part.LastOwnerID = part.OwnerID;
2337 part.OwnerID = item.Owner;
2338 part.Inventory.ChangeInventoryOwner(item.Owner);
2339 }
2340 else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam!
2341 {
2342 part.EveryoneMask = item.EveryOnePermissions;
2343 part.NextOwnerMask = item.NextPermissions;
2344
2345 part.GroupMask = 0; // DO NOT propagate here
2346 }
2347 }
2348
2349 rootPart.TrimPermissions();
2350
2351 if (!attachment)
2352 {
2353 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
2354 {
2355 group.ClearPartAttachmentData();
2356 }
2357 }
2358
2359 if (!attachment)
2360 {
2361 // Fire on_rez
2362 group.CreateScriptInstances(0, true, DefaultScriptEngine, 0);
2363
2364 rootPart.ScheduleFullUpdate();
2365 }
2366
2367 if (!Permissions.BypassPermissions())
2368 {
2369 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
2370 {
2371 // If this is done on attachments, no
2372 // copy ones will be lost, so avoid it
2373 //
2374 if (!attachment)
2375 userInfo.DeleteItem(item.ID);
2376 }
2377 }
2378
2379 return rootPart.ParentGroup;
2380 }
2381 }
2382 }
2383 else
2384 m_log.WarnFormat("[AGENT INVENTORY]: Root folder not found in {0}", RegionInfo.RegionName);
2385 }
2386 else
2387 m_log.WarnFormat("[AGENT INVENTORY]: User profile not found in {0}", RegionInfo.RegionName);
2388
2389 return null;
2390 }
2391
2392 /// <summary>
2393 /// Rez an object into the scene from a prim's inventory.
2394 /// </summary>
2395 /// <param name="sourcePart"></param>
2396 /// <param name="item"></param>
2397 /// <param name="pos"></param>
2398 /// <param name="rot"></param>
2399 /// <param name="vel"></param>
2400 /// <param name="param"></param>
2401 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns>
2402 public virtual SceneObjectGroup RezObject(
2403 SceneObjectPart sourcePart, TaskInventoryItem item,
2404 Vector3 pos, Quaternion rot, Vector3 vel, int param)
2405 {
2406 // Rez object
2407 if (item != null)
2408 {
2409 UUID ownerID = item.OwnerID;
2410
2411 AssetBase rezAsset = AssetCache.GetAsset(item.AssetID, false);
2412
2413 if (rezAsset != null)
2414 {
2415 string xmlData = Utils.BytesToString(rezAsset.Data);
2416 SceneObjectGroup group = new SceneObjectGroup(xmlData, true);
2417
2418 if (!Permissions.CanRezObject(group.Children.Count, ownerID, pos))
2419 {
2420 return null;
2421 }
2422 group.ResetIDs();
2423
2424 AddNewSceneObject(group, true);
2425
2426 // we set it's position in world.
2427 group.AbsolutePosition = pos;
2428
2429 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
2430
2431 // Since renaming the item in the inventory does not affect the name stored
2432 // in the serialization, transfer the correct name from the inventory to the
2433 // object itself before we rez.
2434 rootPart.Name = item.Name;
2435 rootPart.Description = item.Description;
2436
2437 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values);
2438
2439 group.SetGroup(sourcePart.GroupID, null);
2440
2441 if (rootPart.OwnerID != item.OwnerID)
2442 {
2443 if (Permissions.PropagatePermissions())
2444 {
2445 if ((item.CurrentPermissions & 8) != 0)
2446 {
2447 foreach (SceneObjectPart part in partList)
2448 {
2449 part.EveryoneMask = item.EveryonePermissions;
2450 part.NextOwnerMask = item.NextPermissions;
2451 }
2452 }
2453 group.ApplyNextOwnerPermissions();
2454 }
2455 }
2456
2457 foreach (SceneObjectPart part in partList)
2458 {
2459 if (part.OwnerID != item.OwnerID)
2460 {
2461 part.LastOwnerID = part.OwnerID;
2462 part.OwnerID = item.OwnerID;
2463 part.Inventory.ChangeInventoryOwner(item.OwnerID);
2464 }
2465 else if ((item.CurrentPermissions & 8) != 0) // Slam!
2466 {
2467 part.EveryoneMask = item.EveryonePermissions;
2468 part.NextOwnerMask = item.NextPermissions;
2469 }
2470 }
2471 rootPart.TrimPermissions();
2472 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
2473 {
2474 group.ClearPartAttachmentData();
2475 }
2476 group.UpdateGroupRotation(rot);
2477 //group.ApplyPhysics(m_physicalPrim);
2478 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
2479 {
2480 group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
2481 group.Velocity = vel;
2482 rootPart.ScheduleFullUpdate();
2483 }
2484 group.CreateScriptInstances(param, true, DefaultScriptEngine, 2);
2485 rootPart.ScheduleFullUpdate();
2486
2487 if (!Permissions.BypassPermissions())
2488 {
2489 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
2490 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2491 }
2492 return rootPart.ParentGroup;
2493 }
2494 }
2495
2496 return null;
2497 }
2498
2499 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, UUID AgentId)
2500 {
2501 foreach (SceneObjectGroup grp in returnobjects)
2502 {
2503 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
2504 DeRezObject(null, grp.RootPart.LocalId,
2505 grp.RootPart.GroupID, DeRezAction.Return, UUID.Zero);
2506 }
2507
2508 return true;
2509 }
2510
2511 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2512 {
2513 SceneObjectPart part = GetSceneObjectPart(objectID);
2514 if (part == null)
2515 return;
2516
2517 if (running)
2518 EventManager.TriggerStartScript(part.LocalId, itemID);
2519 else
2520 EventManager.TriggerStopScript(part.LocalId, itemID);
2521 }
2522
2523 public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID,
2524 uint AttachmentPt)
2525 {
2526 SceneObjectGroup att = m_sceneGraph.RezSingleAttachment(remoteClient, itemID, AttachmentPt);
2527
2528 if (att == null)
2529 {
2530 DetachSingleAttachmentToInv(itemID, remoteClient);
2531 return UUID.Zero;
2532 }
2533
2534 return RezSingleAttachment(att, remoteClient, itemID, AttachmentPt);
2535 }
2536
2537 public UUID RezSingleAttachment(SceneObjectGroup att,
2538 IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
2539 {
2540 if (!att.IsDeleted)
2541 AttachmentPt = att.RootPart.AttachmentPoint;
2542
2543 ScenePresence presence;
2544 if (TryGetAvatar(remoteClient.AgentId, out presence))
2545 {
2546 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, att.UUID);
2547 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>();
2548 if (ava != null)
2549 {
2550 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2551 }
2552
2553 }
2554 return att.UUID;
2555 }
2556
2557 public void AttachObject(IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent)
2558 {
2559 m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent);
2560 }
2561
2562 public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
2563 {
2564 if (UUID.Zero == itemID)
2565 {
2566 m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID.");
2567 return;
2568 }
2569
2570 if (0 == AttachmentPt)
2571 {
2572 m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error attachment point.");
2573 return;
2574 }
2575
2576 if (null == att.RootPart)
2577 {
2578 m_log.Error("[SCENE INVENTORY]: Unable to save attachment for a prim without the rootpart!");
2579 return;
2580 }
2581
2582 ScenePresence presence;
2583 if (TryGetAvatar(remoteClient.AgentId, out presence))
2584 {
2585 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, att.UUID);
2586 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>();
2587 if (ava != null)
2588 {
2589 m_log.InfoFormat("[SCENE INVENTORY]: Saving avatar attachment. AgentID:{0} ItemID:{1} AttachmentPoint:{2}", remoteClient.AgentId, itemID, AttachmentPt);
2590 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2591 }
2592 }
2593 }
2594
2595 public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient)
2596 {
2597 SceneObjectPart part = GetSceneObjectPart(itemID);
2598 if (part == null || part.ParentGroup == null)
2599 return;
2600
2601 UUID inventoryID = part.ParentGroup.GetFromAssetID();
2602
2603 ScenePresence presence;
2604 if (TryGetAvatar(remoteClient.AgentId, out presence))
2605 {
2606 if (!Permissions.CanRezObject(part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition))
2607 return;
2608
2609 presence.Appearance.DetachAttachment(itemID);
2610 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>();
2611 if (ava != null)
2612 {
2613 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2614 }
2615 part.ParentGroup.DetachToGround();
2616 CachedUserInfo userInfo =
2617 CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
2618 if (userInfo != null)
2619 {
2620 userInfo.DeleteItem(inventoryID);
2621 remoteClient.SendRemoveInventoryItem(inventoryID);
2622 }
2623 }
2624 }
2625
2626 public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient)
2627 {
2628 ScenePresence presence;
2629 if (TryGetAvatar(remoteClient.AgentId, out presence))
2630 {
2631 presence.Appearance.DetachAttachment(itemID);
2632 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>();
2633 if (ava != null)
2634 {
2635 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2636 }
2637
2638 }
2639
2640 m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient);
2641 }
2642
2643 public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
2644 {
2645 EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID);
2646 }
2647
2648 void ObjectOwner(IClientAPI remoteClient, UUID ownerID, UUID groupID, List<uint> localIDs)
2649 {
2650 if (!Permissions.IsGod(remoteClient.AgentId))
2651 return;
2652
2653 foreach (uint localID in localIDs)
2654 {
2655 SceneObjectPart part = GetSceneObjectPart(localID);
2656 if (part != null && part.ParentGroup != null)
2657 {
2658 part.ParentGroup.SetOwnerId(ownerID);
2659 part.Inventory.ChangeInventoryOwner(ownerID);
2660 part.ParentGroup.SetGroup(groupID, remoteClient);
2661 }
2662 }
2663 }
2664 }
2665}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs
deleted file mode 100644
index 3334e81..0000000
--- a/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs
+++ /dev/null
@@ -1,632 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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.Collections.Generic;
29using System.Threading;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34using OpenSim.Framework.Communications.Cache;
35
36namespace OpenSim.Region.Environment.Scenes
37{
38 public partial class Scene
39 {
40 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
41 UUID fromID, bool fromAgent, bool broadcast)
42 {
43 OSChatMessage args = new OSChatMessage();
44
45 args.Message = Utils.BytesToString(message);
46 args.Channel = channel;
47 args.Type = type;
48 args.Position = fromPos;
49 args.SenderUUID = fromID;
50 args.Scene = this;
51
52 if (fromAgent)
53 {
54 ScenePresence user = GetScenePresence(fromID);
55 if (user != null)
56 args.Sender = user.ControllingClient;
57 }
58 else
59 {
60 SceneObjectPart obj = GetSceneObjectPart(fromID);
61 args.SenderObject = obj;
62 }
63
64 args.From = fromName;
65 //args.
66
67 if (broadcast)
68 EventManager.TriggerOnChatBroadcast(this, args);
69 else
70 EventManager.TriggerOnChatFromWorld(this, args);
71
72 }
73 /// <summary>
74 ///
75 /// </summary>
76 /// <param name="message"></param>
77 /// <param name="type"></param>
78 /// <param name="fromPos"></param>
79 /// <param name="fromName"></param>
80 /// <param name="fromAgentID"></param>
81 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
82 UUID fromID, bool fromAgent)
83 {
84 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, false);
85 }
86
87 /// <summary>
88 ///
89 /// </summary>
90 /// <param name="message"></param>
91 /// <param name="type"></param>
92 /// <param name="fromPos"></param>
93 /// <param name="fromName"></param>
94 /// <param name="fromAgentID"></param>
95 public void SimChatBroadcast(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
96 UUID fromID, bool fromAgent)
97 {
98 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true);
99 }
100
101 /// <summary>
102 /// Invoked when the client selects a prim.
103 /// </summary>
104 /// <param name="primLocalID"></param>
105 /// <param name="remoteClient"></param>
106 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
107 {
108 List<EntityBase> EntityList = GetEntities();
109
110 foreach (EntityBase ent in EntityList)
111 {
112 if (ent is SceneObjectGroup)
113 {
114 if (((SceneObjectGroup) ent).LocalId == primLocalID)
115 {
116 ((SceneObjectGroup) ent).GetProperties(remoteClient);
117 ((SceneObjectGroup) ent).IsSelected = true;
118 // A prim is only tainted if it's allowed to be edited by the person clicking it.
119 if (Permissions.CanEditObject(((SceneObjectGroup)ent).UUID, remoteClient.AgentId)
120 || Permissions.CanMoveObject(((SceneObjectGroup)ent).UUID, remoteClient.AgentId))
121 {
122 EventManager.TriggerParcelPrimCountTainted();
123 }
124 break;
125 }
126 else
127 {
128 // We also need to check the children of this prim as they
129 // can be selected as well and send property information
130 bool foundPrim = false;
131 foreach (KeyValuePair<UUID, SceneObjectPart> child in ((SceneObjectGroup) ent).Children)
132 {
133 if (child.Value.LocalId == primLocalID)
134 {
135 child.Value.GetProperties(remoteClient);
136 foundPrim = true;
137 break;
138 }
139 }
140 if (foundPrim) break;
141 }
142 }
143 }
144 }
145
146 /// <summary>
147 /// Handle the deselection of a prim from the client.
148 /// </summary>
149 /// <param name="primLocalID"></param>
150 /// <param name="remoteClient"></param>
151 public void DeselectPrim(uint primLocalID, IClientAPI remoteClient)
152 {
153 SceneObjectPart part = GetSceneObjectPart(primLocalID);
154 if (part == null)
155 return;
156
157 // The prim is in the process of being deleted.
158 if (null == part.ParentGroup.RootPart)
159 return;
160
161 // A deselect packet contains all the local prims being deselected. However, since selection is still
162 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
163 // we end up sending many duplicate ObjectUpdates
164 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
165 return;
166
167 bool isAttachment = false;
168
169 // This is wrong, wrong, wrong. Selection should not be
170 // handled by group, but by prim. Legacy cruft.
171 // TODO: Make selection flagging per prim!
172 //
173 part.ParentGroup.IsSelected = false;
174
175 if (part.ParentGroup.IsAttachment)
176 isAttachment = true;
177 else
178 part.ParentGroup.ScheduleGroupForFullUpdate();
179
180 // If it's not an attachment, and we are allowed to move it,
181 // then we might have done so. If we moved across a parcel
182 // boundary, we will need to recount prims on the parcels.
183 // For attachments, that makes no sense.
184 //
185 if (!isAttachment)
186 {
187 if (Permissions.CanEditObject(
188 part.UUID, remoteClient.AgentId)
189 || Permissions.CanMoveObject(
190 part.UUID, remoteClient.AgentId))
191 EventManager.TriggerParcelPrimCountTainted();
192 }
193 }
194
195 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
196 int transactiontype, string description)
197 {
198 EventManager.MoneyTransferArgs args = new EventManager.MoneyTransferArgs(source, destination, amount,
199 transactiontype, description);
200
201 EventManager.TriggerMoneyTransfer(this, args);
202 }
203
204 public virtual void ProcessParcelBuy(UUID agentId, UUID groupId, bool final, bool groupOwned,
205 bool removeContribution, int parcelLocalID, int parcelArea, int parcelPrice, bool authenticated)
206 {
207 EventManager.LandBuyArgs args = new EventManager.LandBuyArgs(agentId, groupId, final, groupOwned,
208 removeContribution, parcelLocalID, parcelArea,
209 parcelPrice, authenticated);
210
211 // First, allow all validators a stab at it
212 m_eventManager.TriggerValidateLandBuy(this, args);
213
214 // Then, check validation and transfer
215 m_eventManager.TriggerLandBuy(this, args);
216 }
217
218 public virtual void ProcessObjectGrab(uint localID, Vector3 offsetPos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
219 {
220 List<EntityBase> EntityList = GetEntities();
221
222 SurfaceTouchEventArgs surfaceArg = null;
223 if (surfaceArgs != null && surfaceArgs.Count > 0)
224 surfaceArg = surfaceArgs[0];
225
226 foreach (EntityBase ent in EntityList)
227 {
228 if (ent is SceneObjectGroup)
229 {
230 SceneObjectGroup obj = ent as SceneObjectGroup;
231 if (obj != null)
232 {
233 // Is this prim part of the group
234 if (obj.HasChildPrim(localID))
235 {
236 // Currently only grab/touch for the single prim
237 // the client handles rez correctly
238 obj.ObjectGrabHandler(localID, offsetPos, remoteClient);
239
240 SceneObjectPart part = obj.GetChildPart(localID);
241
242 // If the touched prim handles touches, deliver it
243 // If not, deliver to root prim
244 if ((part.ScriptEvents & scriptEvents.touch_start) != 0)
245 EventManager.TriggerObjectGrab(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg);
246 else
247 EventManager.TriggerObjectGrab(obj.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg);
248
249 return;
250 }
251 }
252 }
253 }
254 }
255
256 public virtual void ProcessObjectDeGrab(uint localID, IClientAPI remoteClient)
257 {
258 List<EntityBase> EntityList = GetEntities();
259
260 foreach (EntityBase ent in EntityList)
261 {
262 if (ent is SceneObjectGroup)
263 {
264 SceneObjectGroup obj = ent as SceneObjectGroup;
265
266 // Is this prim part of the group
267 if (obj.HasChildPrim(localID))
268 {
269 SceneObjectPart part=obj.GetChildPart(localID);
270 if (part != null)
271 {
272 // If the touched prim handles touches, deliver it
273 // If not, deliver to root prim
274 if ((part.ScriptEvents & scriptEvents.touch_end) != 0)
275 EventManager.TriggerObjectDeGrab(part.LocalId, 0, remoteClient);
276 else
277 EventManager.TriggerObjectDeGrab(obj.RootPart.LocalId, part.LocalId, remoteClient);
278
279 return;
280 }
281 return;
282 }
283 }
284 }
285 }
286
287 public void ProcessAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
288 {
289 //EventManager.TriggerAvatarPickerRequest();
290
291 List<AvatarPickerAvatar> AvatarResponses = new List<AvatarPickerAvatar>();
292 AvatarResponses = m_sceneGridService.GenerateAgentPickerRequestResponse(RequestID, query);
293
294 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
295 // TODO: don't create new blocks if recycling an old packet
296
297 AvatarPickerReplyPacket.DataBlock[] searchData =
298 new AvatarPickerReplyPacket.DataBlock[AvatarResponses.Count];
299 AvatarPickerReplyPacket.AgentDataBlock agentData = new AvatarPickerReplyPacket.AgentDataBlock();
300
301 agentData.AgentID = avatarID;
302 agentData.QueryID = RequestID;
303 replyPacket.AgentData = agentData;
304 //byte[] bytes = new byte[AvatarResponses.Count*32];
305
306 int i = 0;
307 foreach (AvatarPickerAvatar item in AvatarResponses)
308 {
309 UUID translatedIDtem = item.AvatarID;
310 searchData[i] = new AvatarPickerReplyPacket.DataBlock();
311 searchData[i].AvatarID = translatedIDtem;
312 searchData[i].FirstName = Utils.StringToBytes((string) item.firstName);
313 searchData[i].LastName = Utils.StringToBytes((string) item.lastName);
314 i++;
315 }
316 if (AvatarResponses.Count == 0)
317 {
318 searchData = new AvatarPickerReplyPacket.DataBlock[0];
319 }
320 replyPacket.Data = searchData;
321
322 AvatarPickerReplyAgentDataArgs agent_data = new AvatarPickerReplyAgentDataArgs();
323 agent_data.AgentID = replyPacket.AgentData.AgentID;
324 agent_data.QueryID = replyPacket.AgentData.QueryID;
325
326 List<AvatarPickerReplyDataArgs> data_args = new List<AvatarPickerReplyDataArgs>();
327 for (i = 0; i < replyPacket.Data.Length; i++)
328 {
329 AvatarPickerReplyDataArgs data_arg = new AvatarPickerReplyDataArgs();
330 data_arg.AvatarID = replyPacket.Data[i].AvatarID;
331 data_arg.FirstName = replyPacket.Data[i].FirstName;
332 data_arg.LastName = replyPacket.Data[i].LastName;
333 data_args.Add(data_arg);
334 }
335 client.SendAvatarPickerReply(agent_data, data_args);
336 }
337
338 public void ProcessScriptReset(IClientAPI remoteClient, UUID objectID,
339 UUID itemID)
340 {
341 SceneObjectPart part=GetSceneObjectPart(objectID);
342 if (part == null)
343 return;
344
345 if (Permissions.CanResetScript(objectID, itemID, remoteClient.AgentId))
346 {
347 EventManager.TriggerScriptReset(part.LocalId, itemID);
348 }
349 }
350
351 /// <summary>
352 /// Handle a fetch inventory request from the client
353 /// </summary>
354 /// <param name="remoteClient"></param>
355 /// <param name="itemID"></param>
356 /// <param name="ownerID"></param>
357 public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
358 {
359 if (ownerID == CommsManager.UserProfileCacheService.LibraryRoot.Owner)
360 {
361 //Console.WriteLine("request info for library item");
362 return;
363 }
364
365 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
366
367 if (null == userProfile)
368 {
369 m_log.ErrorFormat(
370 "[AGENT INVENTORY]: Could not find user profile for {0} {1}",
371 remoteClient.Name, remoteClient.AgentId);
372 return;
373 }
374
375 if (userProfile.HasReceivedInventory)
376 {
377 InventoryItemBase item = null;
378 if (userProfile.RootFolder == null)
379 m_log.ErrorFormat(
380 "[AGENT INVENTORY]: User {0} {1} does not have a root folder.",
381 remoteClient.Name, remoteClient.AgentId);
382 else
383 item = userProfile.RootFolder.FindItem(itemID);
384
385 if (item != null)
386 {
387 remoteClient.SendInventoryItemDetails(ownerID, item);
388 }
389 }
390 }
391
392 /// <summary>
393 /// Tell the client about the various child items and folders contained in the requested folder.
394 /// </summary>
395 /// <param name="remoteClient"></param>
396 /// <param name="folderID"></param>
397 /// <param name="ownerID"></param>
398 /// <param name="fetchFolders"></param>
399 /// <param name="fetchItems"></param>
400 /// <param name="sortOrder"></param>
401 public void HandleFetchInventoryDescendents(IClientAPI remoteClient, UUID folderID, UUID ownerID,
402 bool fetchFolders, bool fetchItems, int sortOrder)
403 {
404 // FIXME MAYBE: We're not handling sortOrder!
405
406 // TODO: This code for looking in the folder for the library should be folded back into the
407 // CachedUserInfo so that this class doesn't have to know the details (and so that multiple libraries, etc.
408 // can be handled transparently).
409 InventoryFolderImpl fold = null;
410 if ((fold = CommsManager.UserProfileCacheService.LibraryRoot.FindFolder(folderID)) != null)
411 {
412 remoteClient.SendInventoryFolderDetails(
413 fold.Owner, folderID, fold.RequestListOfItems(),
414 fold.RequestListOfFolders(), fetchFolders, fetchItems);
415 return;
416 }
417
418 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
419
420 if (null == userProfile)
421 {
422 m_log.ErrorFormat(
423 "[AGENT INVENTORY]: Could not find user profile for {0} {1}",
424 remoteClient.Name, remoteClient.AgentId);
425 return;
426 }
427
428 userProfile.SendInventoryDecendents(remoteClient, folderID, fetchFolders, fetchItems);
429 }
430
431 /// <summary>
432 /// Handle the caps inventory descendents fetch.
433 ///
434 /// Since the folder structure is sent to the client on login, I believe we only need to handle items.
435 /// </summary>
436 /// <param name="agentID"></param>
437 /// <param name="folderID"></param>
438 /// <param name="ownerID"></param>
439 /// <param name="fetchFolders"></param>
440 /// <param name="fetchItems"></param>
441 /// <param name="sortOrder"></param>
442 /// <returns>null if the inventory look up failed</returns>
443 public List<InventoryItemBase> HandleFetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID,
444 bool fetchFolders, bool fetchItems, int sortOrder)
445 {
446// m_log.DebugFormat(
447// "[INVENTORY CACHE]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
448// fetchFolders, fetchItems, folderID, agentID);
449
450 // FIXME MAYBE: We're not handling sortOrder!
451
452 // TODO: This code for looking in the folder for the library should be folded back into the
453 // CachedUserInfo so that this class doesn't have to know the details (and so that multiple libraries, etc.
454 // can be handled transparently).
455 InventoryFolderImpl fold;
456 if ((fold = CommsManager.UserProfileCacheService.LibraryRoot.FindFolder(folderID)) != null)
457 {
458 return fold.RequestListOfItems();
459 }
460
461 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(agentID);
462
463 if (null == userProfile)
464 {
465 m_log.ErrorFormat("[AGENT INVENTORY]: Could not find user profile for {0}", agentID);
466 return null;
467 }
468
469 // XXX: When a client crosses into a scene, their entire inventory is fetched
470 // asynchronously. If the client makes a request before the inventory is received, we need
471 // to give the inventory a chance to come in.
472 //
473 // This is a crude way of dealing with that by retrying the lookup. It's not quite as bad
474 // in CAPS as doing this with the udp request, since here it won't hold up other packets.
475 // In fact, here we'll be generous and try for longer.
476 if (!userProfile.HasReceivedInventory)
477 {
478 int attempts = 0;
479 while (attempts++ < 30)
480 {
481 m_log.DebugFormat(
482 "[INVENTORY CACHE]: Poll number {0} for inventory items in folder {1} for user {2}",
483 attempts, folderID, agentID);
484
485 Thread.Sleep(2000);
486
487 if (userProfile.HasReceivedInventory)
488 {
489 break;
490 }
491 }
492 }
493
494 if (userProfile.HasReceivedInventory)
495 {
496 if ((fold = userProfile.RootFolder.FindFolder(folderID)) != null)
497 {
498 return fold.RequestListOfItems();
499 }
500 else
501 {
502 m_log.WarnFormat(
503 "[AGENT INVENTORY]: Could not find folder {0} requested by user {1}",
504 folderID, agentID);
505 return null;
506 }
507 }
508 else
509 {
510 m_log.ErrorFormat("[INVENTORY CACHE]: Could not find root folder for user {0}", agentID);
511 return null;
512 }
513 }
514
515 /// <summary>
516 /// Handle an inventory folder creation request from the client.
517 /// </summary>
518 /// <param name="remoteClient"></param>
519 /// <param name="folderID"></param>
520 /// <param name="folderType"></param>
521 /// <param name="folderName"></param>
522 /// <param name="parentID"></param>
523 public void HandleCreateInventoryFolder(IClientAPI remoteClient, UUID folderID, ushort folderType,
524 string folderName, UUID parentID)
525 {
526 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
527
528 if (null == userProfile)
529 {
530 m_log.ErrorFormat(
531 "[AGENT INVENTORY]: Could not find user profile for {0} {1}",
532 remoteClient.Name, remoteClient.AgentId);
533 return;
534 }
535
536 if (!userProfile.CreateFolder(folderName, folderID, folderType, parentID))
537 {
538 m_log.ErrorFormat(
539 "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}",
540 remoteClient.Name, remoteClient.AgentId);
541 }
542 }
543
544 /// <summary>
545 /// Handle a client request to update the inventory folder
546 /// </summary>
547 ///
548 /// FIXME: We call add new inventory folder because in the data layer, we happen to use an SQL REPLACE
549 /// so this will work to rename an existing folder. Needless to say, to rely on this is very confusing,
550 /// and needs to be changed.
551 ///
552 /// <param name="remoteClient"></param>
553 /// <param name="folderID"></param>
554 /// <param name="type"></param>
555 /// <param name="name"></param>
556 /// <param name="parentID"></param>
557 public void HandleUpdateInventoryFolder(IClientAPI remoteClient, UUID folderID, ushort type, string name,
558 UUID parentID)
559 {
560// m_log.DebugFormat(
561// "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId);
562
563 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
564
565 if (null == userProfile)
566 {
567 m_log.ErrorFormat(
568 "[AGENT INVENTORY]: Could not find user profile for {0} {1}",
569 remoteClient.Name, remoteClient.AgentId);
570 return;
571 }
572
573 if (!userProfile.UpdateFolder(name, folderID, type, parentID))
574 {
575 m_log.ErrorFormat(
576 "[AGENT INVENTORY]: Failed to update folder for user {0} {1}",
577 remoteClient.Name, remoteClient.AgentId);
578 }
579 }
580
581 /// <summary>
582 /// Handle an inventory folder move request from the client.
583 /// </summary>
584 /// <param name="remoteClient"></param>
585 /// <param name="folderID"></param>
586 /// <param name="parentID"></param>
587 public void HandleMoveInventoryFolder(IClientAPI remoteClient, UUID folderID, UUID parentID)
588 {
589 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
590
591 if (null == userProfile)
592 {
593 m_log.ErrorFormat(
594 "[AGENT INVENTORY]: Could not find user profile for {0} {1}",
595 remoteClient.Name, remoteClient.AgentId);
596 return;
597 }
598
599 if (!userProfile.MoveFolder(folderID, parentID))
600 {
601 m_log.ErrorFormat(
602 "[AGENT INVENTORY]: Failed to move folder {0} to {1} for user {2}",
603 folderID, parentID, remoteClient.Name);
604 }
605 }
606
607 /// <summary>
608 /// This should delete all the items and folders in the given directory.
609 /// </summary>
610 /// <param name="remoteClient"></param>
611 /// <param name="folderID"></param>
612 public void HandlePurgeInventoryDescendents(IClientAPI remoteClient, UUID folderID)
613 {
614 CachedUserInfo userProfile = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
615
616 if (null == userProfile)
617 {
618 m_log.ErrorFormat(
619 "[AGENT INVENTORY]: Could not find user profile for {0} {1}",
620 remoteClient.Name, remoteClient.AgentId);
621 return;
622 }
623
624 if (!userProfile.PurgeFolder(folderID))
625 {
626 m_log.ErrorFormat(
627 "[AGENT INVENTORY]: Failed to purge folder for user {0} {1}",
628 remoteClient.Name, remoteClient.AgentId);
629 }
630 }
631 }
632}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.Permissions.cs b/OpenSim/Region/Environment/Scenes/Scene.Permissions.cs
deleted file mode 100644
index 0872128..0000000
--- a/OpenSim/Region/Environment/Scenes/Scene.Permissions.cs
+++ /dev/null
@@ -1,1334 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Environment.Interfaces;
34
35namespace OpenSim.Region.Environment.Scenes
36{
37 public class ScenePermissions
38 {
39 private Scene m_scene;
40
41 public ScenePermissions(Scene scene)
42 {
43 m_scene = scene;
44 }
45
46 #region Object Permission Checks
47
48 public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectIDID);
49 private List<GenerateClientFlagsHandler> GenerateClientFlagsCheckFunctions = new List<GenerateClientFlagsHandler>();
50
51 public void AddGenerateClientFlagsHandler(GenerateClientFlagsHandler delegateFunc)
52 {
53 if (!GenerateClientFlagsCheckFunctions.Contains(delegateFunc))
54 GenerateClientFlagsCheckFunctions.Add(delegateFunc);
55 }
56
57 public void RemoveGenerateClientFlagsHandler(GenerateClientFlagsHandler delegateFunc)
58 {
59 if (GenerateClientFlagsCheckFunctions.Contains(delegateFunc))
60 GenerateClientFlagsCheckFunctions.Remove(delegateFunc);
61 }
62
63 public uint GenerateClientFlags(UUID userID, UUID objectID)
64 {
65 SceneObjectPart part=m_scene.GetSceneObjectPart(objectID);
66
67 if (part == null)
68 return 0;
69
70 // libomv will moan about PrimFlags.ObjectYouOfficer being
71 // obsolete...
72 #pragma warning disable 0612
73 uint perms=part.GetEffectiveObjectFlags() |
74 (uint)PrimFlags.ObjectModify |
75 (uint)PrimFlags.ObjectCopy |
76 (uint)PrimFlags.ObjectMove |
77 (uint)PrimFlags.ObjectTransfer |
78 (uint)PrimFlags.ObjectYouOwner |
79 (uint)PrimFlags.ObjectAnyOwner |
80 (uint)PrimFlags.ObjectOwnerModify |
81 (uint)PrimFlags.ObjectYouOfficer;
82 #pragma warning restore 0612
83
84 foreach (GenerateClientFlagsHandler check in GenerateClientFlagsCheckFunctions)
85 {
86 perms &= check(userID, objectID);
87 }
88 return perms;
89 }
90
91 public delegate void SetBypassPermissionsHandler(bool value);
92 private List<SetBypassPermissionsHandler> SetBypassPermissionsCheckFunctions = new List<SetBypassPermissionsHandler>();
93
94 public void AddSetBypassPermissionsHandler(SetBypassPermissionsHandler delegateFunc)
95 {
96 if (!SetBypassPermissionsCheckFunctions.Contains(delegateFunc))
97 SetBypassPermissionsCheckFunctions.Add(delegateFunc);
98 }
99
100 public void RemoveSetBypassPermissionsHandler(SetBypassPermissionsHandler delegateFunc)
101 {
102 if (SetBypassPermissionsCheckFunctions.Contains(delegateFunc))
103 SetBypassPermissionsCheckFunctions.Remove(delegateFunc);
104 }
105
106 public void SetBypassPermissions(bool value)
107 {
108 foreach (SetBypassPermissionsHandler check in SetBypassPermissionsCheckFunctions)
109 {
110 check(value);
111 }
112 }
113
114 public delegate bool BypassPermissionsHandler();
115 private List<BypassPermissionsHandler> BypassPermissionsCheckFunctions = new List<BypassPermissionsHandler>();
116
117 public void AddBypassPermissionsHandler(BypassPermissionsHandler delegateFunc)
118 {
119 if (!BypassPermissionsCheckFunctions.Contains(delegateFunc))
120 BypassPermissionsCheckFunctions.Add(delegateFunc);
121 }
122
123 public void RemoveBypassPermissionsHandler(BypassPermissionsHandler delegateFunc)
124 {
125 if (BypassPermissionsCheckFunctions.Contains(delegateFunc))
126 BypassPermissionsCheckFunctions.Remove(delegateFunc);
127 }
128
129 public bool BypassPermissions()
130 {
131 foreach (BypassPermissionsHandler check in BypassPermissionsCheckFunctions)
132 {
133 if (check() == false)
134 {
135 return false;
136 }
137 }
138 return true;
139 }
140
141 public delegate bool PropagatePermissionsHandler();
142 private List<PropagatePermissionsHandler> PropagatePermissionsCheckFunctions = new List<PropagatePermissionsHandler>();
143
144 public void AddPropagatePermissionsHandler(PropagatePermissionsHandler delegateFunc)
145 {
146 if (!PropagatePermissionsCheckFunctions.Contains(delegateFunc))
147 PropagatePermissionsCheckFunctions.Add(delegateFunc);
148 }
149
150 public void RemovePropagatePermissionsHandler(PropagatePermissionsHandler delegateFunc)
151 {
152 if (PropagatePermissionsCheckFunctions.Contains(delegateFunc))
153 PropagatePermissionsCheckFunctions.Remove(delegateFunc);
154 }
155
156 public bool PropagatePermissions()
157 {
158 foreach (PropagatePermissionsHandler check in PropagatePermissionsCheckFunctions)
159 {
160 if (check() == false)
161 {
162 return false;
163 }
164 }
165 return true;
166 }
167
168 #region REZ OBJECT
169 public delegate bool CanRezObjectHandler(int objectCount, UUID owner, Vector3 objectPosition, Scene scene);
170 private List<CanRezObjectHandler> CanRezObjectCheckFunctions = new List<CanRezObjectHandler>();
171
172 public void AddRezObjectHandler(CanRezObjectHandler delegateFunc)
173 {
174 if (!CanRezObjectCheckFunctions.Contains(delegateFunc))
175 CanRezObjectCheckFunctions.Add(delegateFunc);
176 }
177
178 public void RemoveRezObjectHandler(CanRezObjectHandler delegateFunc)
179 {
180 if (CanRezObjectCheckFunctions.Contains(delegateFunc))
181 CanRezObjectCheckFunctions.Remove(delegateFunc);
182 }
183
184 public bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition)
185 {
186 foreach (CanRezObjectHandler check in CanRezObjectCheckFunctions)
187 {
188 if (check(objectCount, owner,objectPosition, m_scene) == false)
189 {
190 return false;
191 }
192 }
193 return true;
194 }
195
196 #endregion
197
198 #region DELETE OBJECT
199 public delegate bool CanDeleteObjectHandler(UUID objectID, UUID deleter, Scene scene);
200 private List<CanDeleteObjectHandler> CanDeleteObjectCheckFunctions = new List<CanDeleteObjectHandler>();
201
202 public void AddDeleteObjectHandler(CanDeleteObjectHandler delegateFunc)
203 {
204 if (!CanDeleteObjectCheckFunctions.Contains(delegateFunc))
205 CanDeleteObjectCheckFunctions.Add(delegateFunc);
206 }
207
208 public void RemoveDeleteObjectHandler(CanDeleteObjectHandler delegateFunc)
209 {
210 if (CanDeleteObjectCheckFunctions.Contains(delegateFunc))
211 CanDeleteObjectCheckFunctions.Remove(delegateFunc);
212 }
213
214 public bool CanDeleteObject(UUID objectID, UUID deleter)
215 {
216 foreach (CanDeleteObjectHandler check in CanDeleteObjectCheckFunctions)
217 {
218 if (check(objectID,deleter,m_scene) == false)
219 {
220 return false;
221 }
222 }
223 return true;
224 }
225
226 #endregion
227
228 #region TAKE OBJECT
229 public delegate bool CanTakeObjectHandler(UUID objectID, UUID stealer, Scene scene);
230 private List<CanTakeObjectHandler> CanTakeObjectCheckFunctions = new List<CanTakeObjectHandler>();
231
232 public void AddTakeObjectHandler(CanTakeObjectHandler delegateFunc)
233 {
234 if (!CanTakeObjectCheckFunctions.Contains(delegateFunc))
235 CanTakeObjectCheckFunctions.Add(delegateFunc);
236 }
237
238 public void RemoveTakeObjectHandler(CanTakeObjectHandler delegateFunc)
239 {
240 if (CanTakeObjectCheckFunctions.Contains(delegateFunc))
241 CanTakeObjectCheckFunctions.Remove(delegateFunc);
242 }
243
244 public bool CanTakeObject(UUID objectID, UUID AvatarTakingUUID)
245 {
246 foreach (CanTakeObjectHandler check in CanTakeObjectCheckFunctions)
247 {
248 if (check(objectID, AvatarTakingUUID, m_scene) == false)
249 {
250 return false;
251 }
252 }
253 return true;
254 }
255
256 #endregion
257
258 #region TAKE COPY OBJECT
259 public delegate bool CanTakeCopyObjectHandler(UUID objectID, UUID userID, Scene inScene);
260 private List<CanTakeCopyObjectHandler> CanTakeCopyObjectCheckFunctions = new List<CanTakeCopyObjectHandler>();
261
262 public void AddTakeCopyObjectHandler(CanTakeCopyObjectHandler delegateFunc)
263 {
264 if (!CanTakeCopyObjectCheckFunctions.Contains(delegateFunc))
265 CanTakeCopyObjectCheckFunctions.Add(delegateFunc);
266 }
267
268 public void RemoveTakeCopyObjectHandler(CanTakeCopyObjectHandler delegateFunc)
269 {
270 if (CanTakeCopyObjectCheckFunctions.Contains(delegateFunc))
271 CanTakeCopyObjectCheckFunctions.Remove(delegateFunc);
272 }
273
274 public bool CanTakeCopyObject(UUID objectID, UUID userID)
275 {
276 foreach (CanTakeCopyObjectHandler check in CanTakeCopyObjectCheckFunctions)
277 {
278 if (check(objectID,userID,m_scene) == false)
279 {
280 return false;
281 }
282 }
283 return true;
284 }
285
286 #endregion
287
288 #region DUPLICATE OBJECT
289 public delegate bool CanDuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
290 private List<CanDuplicateObjectHandler> CanDuplicateObjectCheckFunctions = new List<CanDuplicateObjectHandler>();
291
292 public void AddDuplicateObjectHandler(CanDuplicateObjectHandler delegateFunc)
293 {
294 if (!CanDuplicateObjectCheckFunctions.Contains(delegateFunc))
295 CanDuplicateObjectCheckFunctions.Add(delegateFunc);
296 }
297
298 public void RemoveDuplicateObjectHandler(CanDuplicateObjectHandler delegateFunc)
299 {
300 if (CanDuplicateObjectCheckFunctions.Contains(delegateFunc))
301 CanDuplicateObjectCheckFunctions.Remove(delegateFunc);
302 }
303
304 public bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Vector3 objectPosition)
305 {
306 foreach (CanDuplicateObjectHandler check in CanDuplicateObjectCheckFunctions)
307 {
308 if (check(objectCount, objectID, owner, m_scene, objectPosition) == false)
309 {
310 return false;
311 }
312 }
313 return true;
314 }
315
316 #endregion
317
318 #region EDIT OBJECT
319 public delegate bool CanEditObjectHandler(UUID objectID, UUID editorID, Scene scene);
320 private List<CanEditObjectHandler> CanEditObjectCheckFunctions = new List<CanEditObjectHandler>();
321
322 public void AddEditObjectHandler(CanEditObjectHandler delegateFunc)
323 {
324 if (!CanEditObjectCheckFunctions.Contains(delegateFunc))
325 CanEditObjectCheckFunctions.Add(delegateFunc);
326 }
327
328 public void RemoveEditObjectHandler(CanEditObjectHandler delegateFunc)
329 {
330 if (CanEditObjectCheckFunctions.Contains(delegateFunc))
331 CanEditObjectCheckFunctions.Remove(delegateFunc);
332 }
333
334 public bool CanEditObject(UUID objectID, UUID editorID)
335 {
336 foreach (CanEditObjectHandler check in CanEditObjectCheckFunctions)
337 {
338 if (check(objectID, editorID, m_scene) == false)
339 {
340 return false;
341 }
342 }
343 return true;
344 }
345
346 public delegate bool CanEditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
347 private List<CanEditObjectInventoryHandler> CanEditObjectInventoryCheckFunctions = new List<CanEditObjectInventoryHandler>();
348
349 public void AddEditObjectInventoryHandler(CanEditObjectInventoryHandler delegateFunc)
350 {
351 if (!CanEditObjectInventoryCheckFunctions.Contains(delegateFunc))
352 CanEditObjectInventoryCheckFunctions.Add(delegateFunc);
353 }
354
355 public void RemoveEditObjectInventoryHandler(CanEditObjectInventoryHandler delegateFunc)
356 {
357 if (CanEditObjectInventoryCheckFunctions.Contains(delegateFunc))
358 CanEditObjectInventoryCheckFunctions.Remove(delegateFunc);
359 }
360
361 public bool CanEditObjectInventory(UUID objectID, UUID editorID)
362 {
363 foreach (CanEditObjectInventoryHandler check in CanEditObjectInventoryCheckFunctions)
364 {
365 if (check(objectID, editorID, m_scene) == false)
366 {
367 return false;
368 }
369 }
370 return true;
371 }
372
373 #endregion
374
375 #region MOVE OBJECT
376 public delegate bool CanMoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
377 private List<CanMoveObjectHandler> CanMoveObjectCheckFunctions = new List<CanMoveObjectHandler>();
378
379 public void AddMoveObjectHandler(CanMoveObjectHandler delegateFunc)
380 {
381 if (!CanMoveObjectCheckFunctions.Contains(delegateFunc))
382 CanMoveObjectCheckFunctions.Add(delegateFunc);
383 }
384
385 public void RemoveMoveObjectHandler(CanMoveObjectHandler delegateFunc)
386 {
387 if (CanMoveObjectCheckFunctions.Contains(delegateFunc))
388 CanMoveObjectCheckFunctions.Remove(delegateFunc);
389 }
390
391 public bool CanMoveObject(UUID objectID, UUID moverID)
392 {
393 foreach (CanMoveObjectHandler check in CanMoveObjectCheckFunctions)
394 {
395 if (check(objectID,moverID,m_scene) == false)
396 {
397 return false;
398 }
399 }
400 return true;
401 }
402
403 #endregion
404
405 #region OBJECT ENTRY
406 public delegate bool CanObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
407 private List<CanObjectEntryHandler> CanObjectEntryCheckFunctions = new List<CanObjectEntryHandler>();
408
409 public void AddObjectEntryHandler(CanObjectEntryHandler delegateFunc)
410 {
411 if (!CanObjectEntryCheckFunctions.Contains(delegateFunc))
412 CanObjectEntryCheckFunctions.Add(delegateFunc);
413 }
414
415 public void RemoveObjectEntryHandler(CanObjectEntryHandler delegateFunc)
416 {
417 if (CanObjectEntryCheckFunctions.Contains(delegateFunc))
418 CanObjectEntryCheckFunctions.Remove(delegateFunc);
419 }
420
421 public bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint)
422 {
423 foreach (CanObjectEntryHandler check in CanObjectEntryCheckFunctions)
424 {
425 if (check(objectID, enteringRegion, newPoint, m_scene) == false)
426 {
427 return false;
428 }
429 }
430 return true;
431 }
432
433 #endregion
434
435 #region RETURN OBJECT
436 public delegate bool CanReturnObjectHandler(UUID objectID, UUID returnerID, Scene scene);
437 private List<CanReturnObjectHandler> CanReturnObjectCheckFunctions = new List<CanReturnObjectHandler>();
438
439 public void AddReturnObjectHandler(CanReturnObjectHandler delegateFunc)
440 {
441 if (!CanReturnObjectCheckFunctions.Contains(delegateFunc))
442 CanReturnObjectCheckFunctions.Add(delegateFunc);
443 }
444
445 public void RemoveReturnObjectHandler(CanReturnObjectHandler delegateFunc)
446 {
447 if (CanReturnObjectCheckFunctions.Contains(delegateFunc))
448 CanReturnObjectCheckFunctions.Remove(delegateFunc);
449 }
450
451 public bool CanReturnObject(UUID objectID, UUID returnerID)
452 {
453 foreach (CanReturnObjectHandler check in CanReturnObjectCheckFunctions)
454 {
455 if (check(objectID,returnerID,m_scene) == false)
456 {
457 return false;
458 }
459 }
460 return true;
461 }
462
463 #endregion
464
465 #region INSTANT MESSAGE
466 public delegate bool CanInstantMessageHandler(UUID user, UUID target, Scene startScene);
467 private List<CanInstantMessageHandler> CanInstantMessageCheckFunctions = new List<CanInstantMessageHandler>();
468
469 public void AddInstantMessageHandler(CanInstantMessageHandler delegateFunc)
470 {
471 if (!CanInstantMessageCheckFunctions.Contains(delegateFunc))
472 CanInstantMessageCheckFunctions.Add(delegateFunc);
473 }
474
475 public void RemoveInstantMessageHandler(CanInstantMessageHandler delegateFunc)
476 {
477 if (CanInstantMessageCheckFunctions.Contains(delegateFunc))
478 CanInstantMessageCheckFunctions.Remove(delegateFunc);
479 }
480
481 public bool CanInstantMessage(UUID user, UUID target)
482 {
483 foreach (CanInstantMessageHandler check in CanInstantMessageCheckFunctions)
484 {
485 if (check(user, target, m_scene) == false)
486 {
487 return false;
488 }
489 }
490 return true;
491 }
492
493 #endregion
494
495 #region INVENTORY TRANSFER
496 public delegate bool CanInventoryTransferHandler(UUID user, UUID target, Scene startScene);
497 private List<CanInventoryTransferHandler> CanInventoryTransferCheckFunctions = new List<CanInventoryTransferHandler>();
498
499 public void AddInventoryTransferHandler(CanInventoryTransferHandler delegateFunc)
500 {
501 if (!CanInventoryTransferCheckFunctions.Contains(delegateFunc))
502 CanInventoryTransferCheckFunctions.Add(delegateFunc);
503 }
504
505 public void RemoveInventoryTransferHandler(CanInventoryTransferHandler delegateFunc)
506 {
507 if (CanInventoryTransferCheckFunctions.Contains(delegateFunc))
508 CanInventoryTransferCheckFunctions.Remove(delegateFunc);
509 }
510
511 public bool CanInventoryTransfer(UUID user, UUID target)
512 {
513 foreach (CanInventoryTransferHandler check in CanInventoryTransferCheckFunctions)
514 {
515 if (check(user, target, m_scene) == false)
516 {
517 return false;
518 }
519 }
520 return true;
521 }
522
523 #endregion
524
525 #region VIEW SCRIPT
526 public delegate bool CanViewScriptHandler(UUID script, UUID objectID, UUID user, Scene scene);
527 private List<CanViewScriptHandler> CanViewScriptCheckFunctions = new List<CanViewScriptHandler>();
528
529 public void AddViewScriptHandler(CanViewScriptHandler delegateFunc)
530 {
531 if (!CanViewScriptCheckFunctions.Contains(delegateFunc))
532 CanViewScriptCheckFunctions.Add(delegateFunc);
533 }
534
535 public void RemoveViewScriptHandler(CanViewScriptHandler delegateFunc)
536 {
537 if (CanViewScriptCheckFunctions.Contains(delegateFunc))
538 CanViewScriptCheckFunctions.Remove(delegateFunc);
539 }
540
541 public bool CanViewScript(UUID script, UUID objectID, UUID user)
542 {
543 foreach (CanViewScriptHandler check in CanViewScriptCheckFunctions)
544 {
545 if (check(script, objectID, user, m_scene) == false)
546 {
547 return false;
548 }
549 }
550 return true;
551 }
552
553 public delegate bool CanViewNotecardHandler(UUID script, UUID objectID, UUID user, Scene scene);
554 private List<CanViewNotecardHandler> CanViewNotecardCheckFunctions = new List<CanViewNotecardHandler>();
555
556 public void AddViewNotecardHandler(CanViewNotecardHandler delegateFunc)
557 {
558 if (!CanViewNotecardCheckFunctions.Contains(delegateFunc))
559 CanViewNotecardCheckFunctions.Add(delegateFunc);
560 }
561
562 public void RemoveViewNotecardHandler(CanViewNotecardHandler delegateFunc)
563 {
564 if (CanViewNotecardCheckFunctions.Contains(delegateFunc))
565 CanViewNotecardCheckFunctions.Remove(delegateFunc);
566 }
567
568 public bool CanViewNotecard(UUID script, UUID objectID, UUID user)
569 {
570 foreach (CanViewNotecardHandler check in CanViewNotecardCheckFunctions)
571 {
572 if (check(script, objectID, user, m_scene) == false)
573 {
574 return false;
575 }
576 }
577 return true;
578 }
579
580 #endregion
581
582 #region EDIT SCRIPT
583 public delegate bool CanEditScriptHandler(UUID script, UUID objectID, UUID user, Scene scene);
584 private List<CanEditScriptHandler> CanEditScriptCheckFunctions = new List<CanEditScriptHandler>();
585
586 public void AddEditScriptHandler(CanEditScriptHandler delegateFunc)
587 {
588 if (!CanEditScriptCheckFunctions.Contains(delegateFunc))
589 CanEditScriptCheckFunctions.Add(delegateFunc);
590 }
591
592 public void RemoveEditScriptHandler(CanEditScriptHandler delegateFunc)
593 {
594 if (CanEditScriptCheckFunctions.Contains(delegateFunc))
595 CanEditScriptCheckFunctions.Remove(delegateFunc);
596 }
597
598 public bool CanEditScript(UUID script, UUID objectID, UUID user)
599 {
600 foreach (CanEditScriptHandler check in CanEditScriptCheckFunctions)
601 {
602 if (check(script, objectID, user, m_scene) == false)
603 {
604 return false;
605 }
606 }
607 return true;
608 }
609
610 public delegate bool CanEditNotecardHandler(UUID notecard, UUID objectID, UUID user, Scene scene);
611 private List<CanEditNotecardHandler> CanEditNotecardCheckFunctions = new List<CanEditNotecardHandler>();
612
613 public void AddEditNotecardHandler(CanEditNotecardHandler delegateFunc)
614 {
615 if (!CanEditNotecardCheckFunctions.Contains(delegateFunc))
616 CanEditNotecardCheckFunctions.Add(delegateFunc);
617 }
618
619 public void RemoveEditNotecardHandler(CanEditNotecardHandler delegateFunc)
620 {
621 if (CanEditNotecardCheckFunctions.Contains(delegateFunc))
622 CanEditNotecardCheckFunctions.Remove(delegateFunc);
623 }
624
625 public bool CanEditNotecard(UUID script, UUID objectID, UUID user)
626 {
627 foreach (CanEditNotecardHandler check in CanEditNotecardCheckFunctions)
628 {
629 if (check(script, objectID, user, m_scene) == false)
630 {
631 return false;
632 }
633 }
634 return true;
635 }
636
637 #endregion
638
639 #region RUN SCRIPT (When Script Placed in Object)
640 public delegate bool CanRunScriptHandler(UUID script, UUID objectID, UUID user, Scene scene);
641 private List<CanRunScriptHandler> CanRunScriptCheckFunctions = new List<CanRunScriptHandler>();
642
643 public void AddRunScriptHandler(CanRunScriptHandler delegateFunc)
644 {
645 if (!CanRunScriptCheckFunctions.Contains(delegateFunc))
646 CanRunScriptCheckFunctions.Add(delegateFunc);
647 }
648
649 public void RemoveRunScriptHandler(CanRunScriptHandler delegateFunc)
650 {
651 if (CanRunScriptCheckFunctions.Contains(delegateFunc))
652 CanRunScriptCheckFunctions.Remove(delegateFunc);
653 }
654
655 public bool CanRunScript(UUID script, UUID objectID, UUID user)
656 {
657 foreach (CanRunScriptHandler check in CanRunScriptCheckFunctions)
658 {
659 if (check(script, objectID, user, m_scene) == false)
660 {
661 return false;
662 }
663 }
664 return true;
665 }
666
667 #endregion
668
669 #region START SCRIPT (When Script run box is Checked after placed in object)
670 public delegate bool CanStartScriptHandler(UUID script, UUID user, Scene scene);
671 private List<CanStartScriptHandler> CanStartScriptCheckFunctions = new List<CanStartScriptHandler>();
672
673 public void AddStartScriptHandler(CanStartScriptHandler delegateFunc)
674 {
675 if (!CanStartScriptCheckFunctions.Contains(delegateFunc))
676 CanStartScriptCheckFunctions.Add(delegateFunc);
677 }
678
679 public void RemoveStartScriptHandler(CanStartScriptHandler delegateFunc)
680 {
681 if (CanStartScriptCheckFunctions.Contains(delegateFunc))
682 CanStartScriptCheckFunctions.Remove(delegateFunc);
683 }
684
685 public bool CanStartScript(UUID script, UUID user)
686 {
687 foreach (CanStartScriptHandler check in CanStartScriptCheckFunctions)
688 {
689 if (check(script, user, m_scene) == false)
690 {
691 return false;
692 }
693 }
694 return true;
695 }
696
697 #endregion
698
699 #region STOP SCRIPT (When Script run box is unchecked after placed in object)
700 public delegate bool CanStopScriptHandler(UUID script, UUID user, Scene scene);
701 private List<CanStopScriptHandler> CanStopScriptCheckFunctions = new List<CanStopScriptHandler>();
702
703 public void AddStopScriptHandler(CanStopScriptHandler delegateFunc)
704 {
705 if (!CanStopScriptCheckFunctions.Contains(delegateFunc))
706 CanStopScriptCheckFunctions.Add(delegateFunc);
707 }
708
709 public void RemoveStopScriptHandler(CanStopScriptHandler delegateFunc)
710 {
711 if (CanStopScriptCheckFunctions.Contains(delegateFunc))
712 CanStopScriptCheckFunctions.Remove(delegateFunc);
713 }
714
715 public bool CanStopScript(UUID script, UUID user)
716 {
717 foreach (CanStopScriptHandler check in CanStopScriptCheckFunctions)
718 {
719 if (check(script, user, m_scene) == false)
720 {
721 return false;
722 }
723 }
724 return true;
725 }
726
727 #endregion
728
729 #region RESET SCRIPT
730 public delegate bool CanResetScriptHandler(UUID prim, UUID script, UUID user, Scene scene);
731 private List<CanResetScriptHandler> CanResetScriptCheckFunctions = new List<CanResetScriptHandler>();
732
733 public void AddResetScriptHandler(CanResetScriptHandler delegateFunc)
734 {
735 if (!CanResetScriptCheckFunctions.Contains(delegateFunc))
736 CanResetScriptCheckFunctions.Add(delegateFunc);
737 }
738
739 public void RemoveResetScriptHandler(CanResetScriptHandler delegateFunc)
740 {
741 if (CanResetScriptCheckFunctions.Contains(delegateFunc))
742 CanResetScriptCheckFunctions.Remove(delegateFunc);
743 }
744
745 public bool CanResetScript(UUID prim, UUID script, UUID user)
746 {
747 foreach (CanResetScriptHandler check in CanResetScriptCheckFunctions)
748 {
749 if (check(prim, script, user, m_scene) == false)
750 {
751 return false;
752 }
753 }
754 return true;
755 }
756
757 #endregion
758
759 #region TERRAFORM LAND
760 public delegate bool CanTerraformLandHandler(UUID user, Vector3 position, Scene requestFromScene);
761 private List<CanTerraformLandHandler> CanTerraformLandCheckFunctions = new List<CanTerraformLandHandler>();
762
763 public void AddTerraformLandHandler(CanTerraformLandHandler delegateFunc)
764 {
765 if (!CanTerraformLandCheckFunctions.Contains(delegateFunc))
766 CanTerraformLandCheckFunctions.Add(delegateFunc);
767 }
768
769 public void RemoveTerraformLandHandler(CanTerraformLandHandler delegateFunc)
770 {
771 if (CanTerraformLandCheckFunctions.Contains(delegateFunc))
772 CanTerraformLandCheckFunctions.Remove(delegateFunc);
773 }
774
775 public bool CanTerraformLand(UUID user, Vector3 pos)
776 {
777 foreach (CanTerraformLandHandler check in CanTerraformLandCheckFunctions)
778 {
779 if (check(user, pos, m_scene) == false)
780 {
781 return false;
782 }
783 }
784 return true;
785 }
786
787 #endregion
788
789 #region RUN CONSOLE COMMAND
790 public delegate bool CanRunConsoleCommandHandler(UUID user, Scene requestFromScene);
791 private List<CanRunConsoleCommandHandler> CanRunConsoleCommandCheckFunctions = new List<CanRunConsoleCommandHandler>();
792
793 public void AddRunConsoleCommandHandler(CanRunConsoleCommandHandler delegateFunc)
794 {
795 if (!CanRunConsoleCommandCheckFunctions.Contains(delegateFunc))
796 CanRunConsoleCommandCheckFunctions.Add(delegateFunc);
797 }
798
799 public void RemoveRunConsoleCommandHandler(CanRunConsoleCommandHandler delegateFunc)
800 {
801 if (CanRunConsoleCommandCheckFunctions.Contains(delegateFunc))
802 CanRunConsoleCommandCheckFunctions.Remove(delegateFunc);
803 }
804
805 public bool CanRunConsoleCommand(UUID user)
806 {
807 foreach (CanRunConsoleCommandHandler check in CanRunConsoleCommandCheckFunctions)
808 {
809 if (check(user, m_scene) == false)
810 {
811 return false;
812 }
813 }
814 return true;
815 }
816
817 #endregion
818
819 #region CAN ISSUE ESTATE COMMAND
820 public delegate bool CanIssueEstateCommandHandler(UUID user, Scene requestFromScene, bool ownerCommand);
821 private List<CanIssueEstateCommandHandler> CanIssueEstateCommandCheckFunctions = new List<CanIssueEstateCommandHandler>();
822
823 public void AddIssueEstateCommandHandler(CanIssueEstateCommandHandler delegateFunc)
824 {
825 if (!CanIssueEstateCommandCheckFunctions.Contains(delegateFunc))
826 CanIssueEstateCommandCheckFunctions.Add(delegateFunc);
827 }
828
829 public void RemoveIssueEstateCommandHandler(CanIssueEstateCommandHandler delegateFunc)
830 {
831 if (CanIssueEstateCommandCheckFunctions.Contains(delegateFunc))
832 CanIssueEstateCommandCheckFunctions.Remove(delegateFunc);
833 }
834
835 public bool CanIssueEstateCommand(UUID user, bool ownerCommand)
836 {
837 foreach (CanIssueEstateCommandHandler check in CanIssueEstateCommandCheckFunctions)
838 {
839 if (check(user, m_scene, ownerCommand) == false)
840 {
841 return false;
842 }
843 }
844 return true;
845 }
846 #endregion
847
848 #region CAN BE GODLIKE
849 public delegate bool IsGodHandler(UUID user, Scene requestFromScene);
850 private List<IsGodHandler> IsGodCheckFunctions = new List<IsGodHandler>();
851
852 public void AddIsGodHandler(IsGodHandler delegateFunc)
853 {
854 if (!IsGodCheckFunctions.Contains(delegateFunc))
855 IsGodCheckFunctions.Add(delegateFunc);
856 }
857
858 public void RemoveIsGodHandler(IsGodHandler delegateFunc)
859 {
860 if (IsGodCheckFunctions.Contains(delegateFunc))
861 IsGodCheckFunctions.Remove(delegateFunc);
862 }
863
864 public bool IsGod(UUID user)
865 {
866 foreach (IsGodHandler check in IsGodCheckFunctions)
867 {
868 if (check(user, m_scene) == false)
869 {
870 return false;
871 }
872 }
873 return true;
874 }
875 #endregion
876
877 #region EDIT PARCEL
878 public delegate bool CanEditParcelHandler(UUID user, ILandObject parcel, Scene scene);
879 private List<CanEditParcelHandler> CanEditParcelCheckFunctions = new List<CanEditParcelHandler>();
880
881 public void AddEditParcelHandler(CanEditParcelHandler delegateFunc)
882 {
883 if (!CanEditParcelCheckFunctions.Contains(delegateFunc))
884 CanEditParcelCheckFunctions.Add(delegateFunc);
885 }
886
887 public void RemoveEditParcelHandler(CanEditParcelHandler delegateFunc)
888 {
889 if (CanEditParcelCheckFunctions.Contains(delegateFunc))
890 CanEditParcelCheckFunctions.Remove(delegateFunc);
891 }
892
893 public bool CanEditParcel(UUID user, ILandObject parcel)
894 {
895 foreach (CanEditParcelHandler check in CanEditParcelCheckFunctions)
896 {
897 if (check(user, parcel, m_scene) == false)
898 {
899 return false;
900 }
901 }
902 return true;
903 }
904 #endregion
905
906 #region SELL PARCEL
907 public delegate bool CanSellParcelHandler(UUID user, ILandObject parcel, Scene scene);
908 private List<CanSellParcelHandler> CanSellParcelCheckFunctions = new List<CanSellParcelHandler>();
909
910 public void AddSellParcelHandler(CanSellParcelHandler delegateFunc)
911 {
912 if (!CanSellParcelCheckFunctions.Contains(delegateFunc))
913 CanSellParcelCheckFunctions.Add(delegateFunc);
914 }
915
916 public void RemoveSellParcelHandler(CanSellParcelHandler delegateFunc)
917 {
918 if (CanSellParcelCheckFunctions.Contains(delegateFunc))
919 CanSellParcelCheckFunctions.Remove(delegateFunc);
920 }
921
922 public bool CanSellParcel(UUID user, ILandObject parcel)
923 {
924 foreach (CanSellParcelHandler check in CanSellParcelCheckFunctions)
925 {
926 if (check(user, parcel, m_scene) == false)
927 {
928 return false;
929 }
930 }
931 return true;
932 }
933 #endregion
934
935 #region ABANDON PARCEL
936 public delegate bool CanAbandonParcelHandler(UUID user, ILandObject parcel, Scene scene);
937 private List<CanAbandonParcelHandler> CanAbandonParcelCheckFunctions = new List<CanAbandonParcelHandler>();
938
939 public void AddAbandonParcelHandler(CanAbandonParcelHandler delegateFunc)
940 {
941 if (!CanAbandonParcelCheckFunctions.Contains(delegateFunc))
942 CanAbandonParcelCheckFunctions.Add(delegateFunc);
943 }
944
945 public void RemoveAbandonParcelHandler(CanAbandonParcelHandler delegateFunc)
946 {
947 if (CanAbandonParcelCheckFunctions.Contains(delegateFunc))
948 CanAbandonParcelCheckFunctions.Remove(delegateFunc);
949 }
950
951 public bool CanAbandonParcel(UUID user, ILandObject parcel)
952 {
953 foreach (CanAbandonParcelHandler check in CanAbandonParcelCheckFunctions)
954 {
955 if (check(user, parcel, m_scene) == false)
956 {
957 return false;
958 }
959 }
960 return true;
961 }
962 #endregion
963
964 public delegate bool CanReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene);
965 private List<CanReclaimParcelHandler> CanReclaimParcelCheckFunctions = new List<CanReclaimParcelHandler>();
966
967 public void AddReclaimParcelHandler(CanReclaimParcelHandler delegateFunc)
968 {
969 if (!CanReclaimParcelCheckFunctions.Contains(delegateFunc))
970 CanReclaimParcelCheckFunctions.Add(delegateFunc);
971 }
972
973 public void RemoveReclaimParcelHandler(CanReclaimParcelHandler delegateFunc)
974 {
975 if (CanReclaimParcelCheckFunctions.Contains(delegateFunc))
976 CanReclaimParcelCheckFunctions.Remove(delegateFunc);
977 }
978
979 public bool CanReclaimParcel(UUID user, ILandObject parcel)
980 {
981 foreach (CanReclaimParcelHandler check in CanReclaimParcelCheckFunctions)
982 {
983 if (check(user, parcel, m_scene) == false)
984 {
985 return false;
986 }
987 }
988 return true;
989 }
990 public delegate bool CanBuyLandHandler(UUID user, ILandObject parcel, Scene scene);
991 private List<CanBuyLandHandler> CanBuyLandCheckFunctions = new List<CanBuyLandHandler>();
992
993 public void AddCanBuyLandHandler(CanBuyLandHandler delegateFunc)
994 {
995 if (!CanBuyLandCheckFunctions.Contains(delegateFunc))
996 CanBuyLandCheckFunctions.Add(delegateFunc);
997 }
998
999 public void RemoveCanBuyLandHandler(CanBuyLandHandler delegateFunc)
1000 {
1001 if (CanBuyLandCheckFunctions.Contains(delegateFunc))
1002 CanBuyLandCheckFunctions.Remove(delegateFunc);
1003 }
1004
1005 public bool CanBuyLand(UUID user, ILandObject parcel)
1006 {
1007 foreach (CanBuyLandHandler check in CanBuyLandCheckFunctions)
1008 {
1009 if (check(user, parcel, m_scene) == false)
1010 {
1011 return false;
1012 }
1013 }
1014 return true;
1015 }
1016
1017 public delegate bool CanLinkObjectHandler(UUID user, UUID objectID);
1018 private List<CanLinkObjectHandler> CanLinkObjectCheckFunctions = new List<CanLinkObjectHandler>();
1019
1020 public void AddCanLinkObjectHandler(CanLinkObjectHandler delegateFunc)
1021 {
1022 if (!CanLinkObjectCheckFunctions.Contains(delegateFunc))
1023 CanLinkObjectCheckFunctions.Add(delegateFunc);
1024 }
1025
1026 public void RemoveCanLinkObjectHandler(CanLinkObjectHandler delegateFunc)
1027 {
1028 if (CanLinkObjectCheckFunctions.Contains(delegateFunc))
1029 CanLinkObjectCheckFunctions.Remove(delegateFunc);
1030 }
1031
1032 public bool CanLinkObject(UUID user, UUID objectID)
1033 {
1034 foreach (CanLinkObjectHandler check in CanLinkObjectCheckFunctions)
1035 {
1036 if (check(user, objectID) == false)
1037 {
1038 return false;
1039 }
1040 }
1041 return true;
1042 }
1043
1044 public delegate bool CanDelinkObjectHandler(UUID user, UUID objectID);
1045 private List<CanDelinkObjectHandler> CanDelinkObjectCheckFunctions = new List<CanDelinkObjectHandler>();
1046
1047 public void AddCanDelinkObjectHandler(CanDelinkObjectHandler delegateFunc)
1048 {
1049 if (!CanDelinkObjectCheckFunctions.Contains(delegateFunc))
1050 CanDelinkObjectCheckFunctions.Add(delegateFunc);
1051 }
1052
1053 public void RemoveCanDelinkObjectHandler(CanDelinkObjectHandler delegateFunc)
1054 {
1055 if (CanDelinkObjectCheckFunctions.Contains(delegateFunc))
1056 CanDelinkObjectCheckFunctions.Remove(delegateFunc);
1057 }
1058
1059 public bool CanDelinkObject(UUID user, UUID objectID)
1060 {
1061 foreach (CanDelinkObjectHandler check in CanDelinkObjectCheckFunctions)
1062 {
1063 if (check(user, objectID) == false)
1064 {
1065 return false;
1066 }
1067 }
1068 return true;
1069 }
1070
1071 #endregion
1072
1073 public delegate bool CanCreateObjectInventoryHandler(int invType, UUID objectID, UUID userID);
1074 private List<CanCreateObjectInventoryHandler> CanCreateObjectInventoryCheckFunctions
1075 = new List<CanCreateObjectInventoryHandler>();
1076
1077
1078 public void AddCanCreateObjectInventoryHandler(CanCreateObjectInventoryHandler delegateFunc)
1079 {
1080 if (!CanCreateObjectInventoryCheckFunctions.Contains(delegateFunc))
1081 CanCreateObjectInventoryCheckFunctions.Add(delegateFunc);
1082 }
1083
1084 public void RemoveCanCreateObjectInventoryHandler(CanCreateObjectInventoryHandler delegateFunc)
1085 {
1086 if (CanCreateObjectInventoryCheckFunctions.Contains(delegateFunc))
1087 CanCreateObjectInventoryCheckFunctions.Remove(delegateFunc);
1088 }
1089
1090 /// <summary>
1091 /// Check whether the specified user is allowed to directly create the given inventory type in a prim's
1092 /// inventory (e.g. the New Script button in the 1.21 Linden Lab client).
1093 /// </summary>
1094 /// <param name="invType"></param>
1095 /// <param name="objectID"></param>
1096 /// <param name="userID"></param>
1097 /// <returns></returns>
1098 public bool CanCreateObjectInventory(int invType, UUID objectID, UUID userID)
1099 {
1100 foreach (CanCreateObjectInventoryHandler check in CanCreateObjectInventoryCheckFunctions)
1101 {
1102 if (check(invType, objectID, userID) == false)
1103 {
1104 return false;
1105 }
1106 }
1107
1108 return true;
1109 }
1110
1111 public delegate bool CanCopyObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
1112 private List<CanCopyObjectInventoryHandler> CanCopyObjectInventoryCheckFunctions = new List<CanCopyObjectInventoryHandler>();
1113
1114 public void AddCanCopyObjectInventoryHandler(CanCopyObjectInventoryHandler delegateFunc)
1115 {
1116 if (!CanCopyObjectInventoryCheckFunctions.Contains(delegateFunc))
1117 CanCopyObjectInventoryCheckFunctions.Add(delegateFunc);
1118 }
1119
1120 public void RemoveCanCopyObjectInventoryHandler(CanCopyObjectInventoryHandler delegateFunc)
1121 {
1122 if (CanCopyObjectInventoryCheckFunctions.Contains(delegateFunc))
1123 CanCopyObjectInventoryCheckFunctions.Remove(delegateFunc);
1124 }
1125
1126 public bool CanCopyObjectInventory(UUID itemID, UUID objectID, UUID userID)
1127 {
1128 foreach (CanCopyObjectInventoryHandler check in CanCopyObjectInventoryCheckFunctions)
1129 {
1130 if (check(itemID, objectID, userID) == false)
1131 {
1132 return false;
1133 }
1134 }
1135 return true;
1136 }
1137
1138 public delegate bool CanDeleteObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
1139 private List<CanDeleteObjectInventoryHandler> CanDeleteObjectInventoryCheckFunctions
1140 = new List<CanDeleteObjectInventoryHandler>();
1141
1142 public void AddCanDeleteObjectInventoryHandler(CanDeleteObjectInventoryHandler delegateFunc)
1143 {
1144 if (!CanDeleteObjectInventoryCheckFunctions.Contains(delegateFunc))
1145 CanDeleteObjectInventoryCheckFunctions.Add(delegateFunc);
1146 }
1147
1148 public void RemoveCanDeleteObjectInventoryHandler(CanDeleteObjectInventoryHandler delegateFunc)
1149 {
1150 if (CanDeleteObjectInventoryCheckFunctions.Contains(delegateFunc))
1151 CanDeleteObjectInventoryCheckFunctions.Remove(delegateFunc);
1152 }
1153
1154 public bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID)
1155 {
1156 foreach (CanDeleteObjectInventoryHandler check in CanDeleteObjectInventoryCheckFunctions)
1157 {
1158 if (check(itemID, objectID, userID) == false)
1159 {
1160 return false;
1161 }
1162 }
1163
1164 return true;
1165 }
1166
1167 public delegate bool CanCreateUserInventoryHandler(int invType, UUID userID);
1168 private List<CanCreateUserInventoryHandler> CanCreateUserInventoryCheckFunctions
1169 = new List<CanCreateUserInventoryHandler>();
1170
1171 public void AddCanCreateUserInventoryHandler(CanCreateUserInventoryHandler delegateFunc)
1172 {
1173 if (!CanCreateUserInventoryCheckFunctions.Contains(delegateFunc))
1174 CanCreateUserInventoryCheckFunctions.Add(delegateFunc);
1175 }
1176
1177 public void RemoveCanCreateUserInventoryHandler(CanCreateUserInventoryHandler delegateFunc)
1178 {
1179 if (CanCreateUserInventoryCheckFunctions.Contains(delegateFunc))
1180 CanCreateUserInventoryCheckFunctions.Remove(delegateFunc);
1181 }
1182
1183 /// <summary>
1184 /// Check whether the specified user is allowed to create the given inventory type in their inventory.
1185 /// </summary>
1186 /// <param name="invType"></param>
1187 /// <param name="userID"></param>
1188 /// <returns></returns>
1189 public bool CanCreateUserInventory(int invType, UUID userID)
1190 {
1191 foreach (CanCreateUserInventoryHandler check in CanCreateUserInventoryCheckFunctions)
1192 {
1193 if (check(invType, userID) == false)
1194 {
1195 return false;
1196 }
1197 }
1198
1199 return true;
1200 }
1201
1202 public delegate bool CanEditUserInventoryHandler(UUID itemID, UUID userID);
1203 private List<CanEditUserInventoryHandler> CanEditUserInventoryCheckFunctions
1204 = new List<CanEditUserInventoryHandler>();
1205
1206 public void AddCanEditUserInventoryHandler(CanEditUserInventoryHandler delegateFunc)
1207 {
1208 if (!CanEditUserInventoryCheckFunctions.Contains(delegateFunc))
1209 CanEditUserInventoryCheckFunctions.Add(delegateFunc);
1210 }
1211
1212 public void RemoveCanEditUserInventoryHandler(CanEditUserInventoryHandler delegateFunc)
1213 {
1214 if (CanEditUserInventoryCheckFunctions.Contains(delegateFunc))
1215 CanEditUserInventoryCheckFunctions.Remove(delegateFunc);
1216 }
1217
1218 /// <summary>
1219 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
1220 /// </summary>
1221 /// <param name="itemID"></param>
1222 /// <param name="userID"></param>
1223 /// <returns></returns>
1224 public bool CanEditUserInventory(UUID itemID, UUID userID)
1225 {
1226 foreach (CanEditUserInventoryHandler check in CanEditUserInventoryCheckFunctions)
1227 {
1228 if (check(itemID, userID) == false)
1229 {
1230 return false;
1231 }
1232 }
1233
1234 return true;
1235 }
1236
1237 public delegate bool CanCopyUserInventoryHandler(UUID itemID, UUID userID);
1238 private List<CanCopyUserInventoryHandler> CanCopyUserInventoryCheckFunctions
1239 = new List<CanCopyUserInventoryHandler>();
1240
1241 public void AddCanCopyUserInventoryHandler(CanCopyUserInventoryHandler delegateFunc)
1242 {
1243 if (!CanCopyUserInventoryCheckFunctions.Contains(delegateFunc))
1244 CanCopyUserInventoryCheckFunctions.Add(delegateFunc);
1245 }
1246
1247 public void RemoveCanCopyUserInventoryHandler(CanCopyUserInventoryHandler delegateFunc)
1248 {
1249 if (CanCopyUserInventoryCheckFunctions.Contains(delegateFunc))
1250 CanCopyUserInventoryCheckFunctions.Remove(delegateFunc);
1251 }
1252
1253 /// <summary>
1254 /// Check whether the specified user is allowed to copy the given inventory item from their own inventory.
1255 /// </summary>
1256 /// <param name="itemID"></param>
1257 /// <param name="userID"></param>
1258 /// <returns></returns>
1259 public bool CanCopyUserInventory(UUID itemID, UUID userID)
1260 {
1261 foreach (CanCopyUserInventoryHandler check in CanCopyUserInventoryCheckFunctions)
1262 {
1263 if (check(itemID, userID) == false)
1264 {
1265 return false;
1266 }
1267 }
1268
1269 return true;
1270 }
1271
1272 public delegate bool CanDeleteUserInventoryHandler(UUID itemID, UUID userID);
1273 private List<CanDeleteUserInventoryHandler> CanDeleteUserInventoryCheckFunctions
1274 = new List<CanDeleteUserInventoryHandler>();
1275
1276 public void AddCanDeleteUserInventoryHandler(CanDeleteUserInventoryHandler delegateFunc)
1277 {
1278 if (!CanDeleteUserInventoryCheckFunctions.Contains(delegateFunc))
1279 CanDeleteUserInventoryCheckFunctions.Add(delegateFunc);
1280 }
1281
1282 public void RemoveCanDeleteUserInventoryHandler(CanDeleteUserInventoryHandler delegateFunc)
1283 {
1284 if (CanDeleteUserInventoryCheckFunctions.Contains(delegateFunc))
1285 CanDeleteUserInventoryCheckFunctions.Remove(delegateFunc);
1286 }
1287
1288 /// <summary>
1289 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
1290 /// </summary>
1291 /// <param name="itemID"></param>
1292 /// <param name="userID"></param>
1293 /// <returns></returns>
1294 public bool CanDeleteUserInventory(UUID itemID, UUID userID)
1295 {
1296 foreach (CanDeleteUserInventoryHandler check in CanDeleteUserInventoryCheckFunctions)
1297 {
1298 if (check(itemID, userID) == false)
1299 {
1300 return false;
1301 }
1302 }
1303
1304 return true;
1305 }
1306
1307 public delegate bool CanTeleportHandler(UUID userID);
1308 private List<CanTeleportHandler> CanTeleportCheckFunctions = new List<CanTeleportHandler>();
1309
1310 public void AddCanTeleportHandler(CanTeleportHandler delegateFunc)
1311 {
1312 if (!CanTeleportCheckFunctions.Contains(delegateFunc))
1313 CanTeleportCheckFunctions.Add(delegateFunc);
1314 }
1315
1316 public void RemoveCanTeleportHandler(CanTeleportHandler delegateFunc)
1317 {
1318 if (CanTeleportCheckFunctions.Contains(delegateFunc))
1319 CanTeleportCheckFunctions.Remove(delegateFunc);
1320 }
1321
1322 public bool CanTeleport(UUID userID)
1323 {
1324 foreach (CanTeleportHandler check in CanTeleportCheckFunctions)
1325 {
1326 if (check(userID) == false)
1327 {
1328 return false;
1329 }
1330 }
1331 return true;
1332 }
1333 }
1334}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
deleted file mode 100644
index f798a0e..0000000
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ /dev/null
@@ -1,4237 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Drawing.Imaging;
32using System.IO;
33using System.Xml;
34using System.Threading;
35using System.Timers;
36using OpenMetaverse;
37using OpenMetaverse.Imaging;
38using OpenMetaverse.Packets;
39using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Servers;
43using OpenSim.Region.Environment.Interfaces;
44using OpenSim.Region.Interfaces;
45using OpenSim.Region.Environment.Modules.World.Terrain;
46using OpenSim.Region.Environment.Scenes.Scripting;
47using OpenSim.Region.Physics.Manager;
48using Nini.Config;
49using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
50using Image = System.Drawing.Image;
51using TPFlags = OpenSim.Framework.Constants.TeleportFlags;
52using Timer = System.Timers.Timer;
53using OSD = OpenMetaverse.StructuredData.OSD;
54
55namespace OpenSim.Region.Environment.Scenes
56{
57 public delegate bool FilterAvatarList(ScenePresence avatar);
58
59 public partial class Scene : SceneBase
60 {
61 public delegate void SynchronizeSceneHandler(Scene scene);
62 public SynchronizeSceneHandler SynchronizeScene = null;
63 public int splitID = 0;
64
65 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
66 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
67
68 #region Fields
69
70 protected Timer m_restartWaitTimer = new Timer();
71
72 public SimStatsReporter StatsReporter;
73
74 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
75 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
76
77 /// <value>
78 /// The scene graph for this scene
79 /// </value>
80 /// TODO: Possibly stop other classes being able to manipulate this directly.
81 public SceneGraph m_sceneGraph;
82
83 /// <summary>
84 /// Are we applying physics to any of the prims in this scene?
85 /// </summary>
86 public bool m_physicalPrim;
87 public float m_maxNonphys = 65536;
88 public float m_maxPhys = 10;
89 public bool m_clampPrimSize = false;
90 public bool m_trustBinaries = false;
91 public bool m_allowScriptCrossings = false;
92
93 public bool m_seeIntoRegionFromNeighbor;
94 public int MaxUndoCount = 5;
95 private int m_RestartTimerCounter;
96 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
97 private int m_incrementsof15seconds = 0;
98 private volatile bool m_backingup = false;
99
100 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
101
102 protected string m_simulatorVersion = "OpenSimulator Server";
103
104 protected ModuleLoader m_moduleLoader;
105 protected StorageManager m_storageManager;
106 protected AgentCircuitManager m_authenticateHandler;
107 public CommunicationsManager CommsManager;
108
109 protected SceneCommunicationService m_sceneGridService;
110
111 public SceneCommunicationService SceneGridService
112 {
113 get { return m_sceneGridService; }
114 }
115
116 public IXfer XferManager;
117
118 protected IXMLRPC m_xmlrpcModule;
119 protected IWorldComm m_worldCommModule;
120 protected IAvatarFactory m_AvatarFactory;
121 protected IConfigSource m_config;
122 protected IRegionSerialiserModule m_serialiser;
123 protected IInterregionCommsOut m_interregionCommsOut;
124 protected IInterregionCommsIn m_interregionCommsIn;
125 protected IDialogModule m_dialogModule;
126 protected internal ICapabilitiesModule CapsModule;
127
128 // Central Update Loop
129
130 protected int m_fps = 10;
131 protected int m_frame = 0;
132 protected float m_timespan = 0.089f;
133 protected DateTime m_lastupdate = DateTime.Now;
134
135 protected float m_timedilation = 1.0f;
136
137 private int m_update_physics = 1;
138 private int m_update_entitymovement = 1;
139 private int m_update_entities = 1; // Run through all objects checking for updates
140 private int m_update_entitiesquick = 200; // Run through objects that have scheduled updates checking for updates
141 private int m_update_presences = 1; // Update scene presence movements
142 private int m_update_events = 1;
143 private int m_update_backup = 200;
144 private int m_update_terrain = 50;
145 private int m_update_land = 1;
146
147 private int frameMS = 0;
148 private int physicsMS2 = 0;
149 private int physicsMS = 0;
150 private int otherMS = 0;
151
152 private bool m_physics_enabled = true;
153 private bool m_scripts_enabled = true;
154 private string m_defaultScriptEngine;
155 private int m_LastLogin = 0;
156 private Thread HeartbeatThread;
157 private volatile bool shuttingdown = false;
158
159 private object m_deleting_scene_object = new object();
160
161 // the minimum time that must elapse before a changed object will be considered for persisted
162 public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L;
163 // the maximum time that must elapse before a changed object will be considered for persisted
164 public long m_persistAfter = DEFAULT_MAX_TIME_FOR_PERSISTENCE * 10000000L;
165
166 #endregion
167
168 #region Properties
169
170 public AgentCircuitManager AuthenticateHandler
171 {
172 get { return m_authenticateHandler; }
173 }
174
175 public SceneGraph SceneContents
176 {
177 get { return m_sceneGraph; }
178 }
179
180 // an instance to the physics plugin's Scene object.
181 public PhysicsScene PhysicsScene
182 {
183 get { return m_sceneGraph.PhysicsScene; }
184 set
185 {
186 // If we're not doing the initial set
187 // Then we've got to remove the previous
188 // event handler
189 if (PhysicsScene != null && PhysicsScene.SupportsNINJAJoints)
190 {
191 PhysicsScene.OnJointMoved -= jointMoved;
192 PhysicsScene.OnJointDeactivated -= jointDeactivated;
193 PhysicsScene.OnJointErrorMessage -= jointErrorMessage;
194 }
195
196 m_sceneGraph.PhysicsScene = value;
197
198 if (PhysicsScene != null && m_sceneGraph.PhysicsScene.SupportsNINJAJoints)
199 {
200 // register event handlers to respond to joint movement/deactivation
201 PhysicsScene.OnJointMoved += jointMoved;
202 PhysicsScene.OnJointDeactivated += jointDeactivated;
203 PhysicsScene.OnJointErrorMessage += jointErrorMessage;
204 }
205
206 }
207 }
208
209 // This gets locked so things stay thread safe.
210 public object SyncRoot
211 {
212 get { return m_sceneGraph.m_syncRoot; }
213 }
214
215 public float TimeDilation
216 {
217 get { return m_timedilation; }
218 }
219
220 /// <summary>
221 /// This is for llGetRegionFPS
222 /// </summary>
223 public float SimulatorFPS
224 {
225 get { return StatsReporter.getLastReportedSimFPS(); }
226 }
227
228 public string DefaultScriptEngine
229 {
230 get { return m_defaultScriptEngine; }
231 }
232
233 // Local reference to the objects in the scene (which are held in the scenegraph)
234 // public Dictionary<UUID, SceneObjectGroup> Objects
235 // {
236 // get { return m_sceneGraph.SceneObjects; }
237 // }
238
239 // Reference to all of the agents in the scene (root and child)
240 protected Dictionary<UUID, ScenePresence> m_scenePresences
241 {
242 get { return m_sceneGraph.ScenePresences; }
243 set { m_sceneGraph.ScenePresences = value; }
244 }
245
246 // protected Dictionary<UUID, SceneObjectGroup> m_sceneObjects
247 // {
248 // get { return m_sceneGraph.SceneObjects; }
249 // set { m_sceneGraph.SceneObjects = value; }
250 // }
251
252 public EntityManager Entities
253 {
254 get { return m_sceneGraph.Entities; }
255 }
256
257 public Dictionary<UUID, ScenePresence> m_restorePresences
258 {
259 get { return m_sceneGraph.RestorePresences; }
260 set { m_sceneGraph.RestorePresences = value; }
261 }
262
263 public int objectCapacity = 45000;
264
265 #endregion
266
267 #region Constructors
268
269 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
270 CommunicationsManager commsMan, SceneCommunicationService sceneGridService,
271 AssetCache assetCach, StorageManager storeManager,
272 ModuleLoader moduleLoader, bool dumpAssetsToFile, bool physicalPrim,
273 bool SeeIntoRegionFromNeighbor, IConfigSource config, string simulatorVersion)
274 {
275 m_config = config;
276
277 Random random = new Random();
278 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue/2))+(uint)(uint.MaxValue/4);
279 m_moduleLoader = moduleLoader;
280 m_authenticateHandler = authen;
281 CommsManager = commsMan;
282 m_sceneGridService = sceneGridService;
283 m_storageManager = storeManager;
284 AssetCache = assetCach;
285 m_regInfo = regInfo;
286 m_regionHandle = m_regInfo.RegionHandle;
287 m_regionName = m_regInfo.RegionName;
288 m_datastore = m_regInfo.DataStore;
289
290 m_physicalPrim = physicalPrim;
291 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
292
293 m_eventManager = new EventManager();
294 m_permissions = new ScenePermissions(this);
295
296 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
297 m_asyncSceneObjectDeleter.Enabled = true;
298
299 // Load region settings
300 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
301 if (m_storageManager.EstateDataStore != null)
302 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID);
303
304 //Bind Storage Manager functions to some land manager functions for this scene
305 EventManager.OnLandObjectAdded +=
306 new EventManager.LandObjectAdded(m_storageManager.DataStore.StoreLandObject);
307 EventManager.OnLandObjectRemoved +=
308 new EventManager.LandObjectRemoved(m_storageManager.DataStore.RemoveLandObject);
309
310 m_sceneGraph = new SceneGraph(this, m_regInfo);
311
312 // If the scene graph has an Unrecoverable error, restart this sim.
313 // Currently the only thing that causes it to happen is two kinds of specific
314 // Physics based crashes.
315 //
316 // Out of memory
317 // Operating system has killed the plugin
318 m_sceneGraph.UnRecoverableError += RestartNow;
319
320 RegisterDefaultSceneEvents();
321
322 DumpAssetsToFile = dumpAssetsToFile;
323
324 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
325
326 m_physics_enabled = !RegionInfo.RegionSettings.DisablePhysics;
327
328 StatsReporter = new SimStatsReporter(this);
329 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
330 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
331
332 StatsReporter.SetObjectCapacity(objectCapacity);
333
334 m_simulatorVersion = simulatorVersion
335 + " (OS " + Util.GetOperatingSystemInformation() + ")"
336 + " ChilTasks:" + m_seeIntoRegionFromNeighbor.ToString()
337 + " PhysPrim:" + m_physicalPrim.ToString();
338
339 try
340 {
341 // Region config overrides global config
342 //
343 IConfig startupConfig = m_config.Configs["Startup"];
344 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", 65536.0f);
345 if (RegionInfo.NonphysPrimMax > 0)
346 m_maxNonphys = RegionInfo.NonphysPrimMax;
347
348 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", 10.0f);
349
350 if (RegionInfo.PhysPrimMax > 0)
351 m_maxPhys = RegionInfo.PhysPrimMax;
352
353 // Here, if clamping is requested in either global or
354 // local config, it will be used
355 //
356 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", false);
357 if (RegionInfo.ClampPrimSize)
358 m_clampPrimSize = true;
359
360 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", false);
361 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", false);
362 m_dontPersistBefore =
363 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
364 m_dontPersistBefore *= 10000000;
365 m_persistAfter =
366 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
367 m_persistAfter *= 10000000;
368
369 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "DotNetEngine");
370 }
371 catch
372 {
373 m_log.Warn("[SCENE]: Failed to load StartupConfig");
374 }
375 }
376
377 /// <summary>
378 /// Mock constructor for scene group persistency unit tests.
379 /// SceneObjectGroup RegionId property is delegated to Scene.
380 /// </summary>
381 /// <param name="regInfo"></param>
382 public Scene(RegionInfo regInfo)
383 {
384 m_regInfo = regInfo;
385 m_eventManager = new EventManager();
386 }
387
388 #endregion
389
390 #region Startup / Close Methods
391
392 public bool ShuttingDown
393 {
394 get { return shuttingdown; }
395 }
396
397 protected virtual void RegisterDefaultSceneEvents()
398 {
399 IDialogModule dm = RequestModuleInterface<IDialogModule>();
400
401 if (dm != null)
402 m_eventManager.OnPermissionError += dm.SendAlertToUser;
403 }
404
405 public override string GetSimulatorVersion()
406 {
407 return m_simulatorVersion;
408 }
409
410 /// <summary>
411 /// Another region is up. Gets called from Grid Comms:
412 /// (OGS1 -> LocalBackEnd -> RegionListened -> SceneCommunicationService)
413 /// We have to tell all our ScenePresences about it, and add it to the
414 /// neighbor list.
415 ///
416 /// We only add it to the neighbor list if it's within 1 region from here.
417 /// Agents may have draw distance values that cross two regions though, so
418 /// we add it to the notify list regardless of distance. We'll check
419 /// the agent's draw distance before notifying them though.
420 /// </summary>
421 /// <param name="otherRegion">RegionInfo handle for the new region.</param>
422 /// <returns>True after all operations complete, throws exceptions otherwise.</returns>
423 public override bool OtherRegionUp(RegionInfo otherRegion)
424 {
425 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
426 {
427 for (int i = 0; i < m_neighbours.Count; i++)
428 {
429 // The purpose of this loop is to re-update the known neighbors
430 // when another region comes up on top of another one.
431 // The latest region in that location ends up in the
432 // 'known neighbors list'
433 // Additionally, the commFailTF property gets reset to false.
434 if (m_neighbours[i].RegionHandle == otherRegion.RegionHandle)
435 {
436 lock (m_neighbours)
437 {
438 m_neighbours[i] = otherRegion;
439 }
440 }
441 }
442
443 // If the value isn't in the neighbours, add it.
444 // If the RegionInfo isn't exact but is for the same XY World location,
445 // then the above loop will fix that.
446
447 if (!(CheckNeighborRegion(otherRegion)))
448 {
449 lock (m_neighbours)
450 {
451 m_neighbours.Add(otherRegion);
452 //m_log.Info("[UP]: " + otherRegion.RegionHandle.ToString());
453 }
454 }
455
456 // If these are cast to INT because long + negative values + abs returns invalid data
457 int resultX = Math.Abs((int)otherRegion.RegionLocX - (int)RegionInfo.RegionLocX);
458 int resultY = Math.Abs((int)otherRegion.RegionLocY - (int)RegionInfo.RegionLocY);
459 if (resultX <= 1 && resultY <= 1)
460 {
461 try
462 {
463 ForEachScenePresence(delegate(ScenePresence agent)
464 {
465 // If agent is a root agent.
466 if (!agent.IsChildAgent)
467 {
468 //agent.ControllingClient.new
469 //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo());
470 InformClientOfNeighbor(agent, otherRegion);
471 }
472 }
473 );
474 }
475 catch (NullReferenceException)
476 {
477 // This means that we're not booted up completely yet.
478 // This shouldn't happen too often anymore.
479 m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception");
480 }
481 }
482 else
483 {
484 m_log.Info("[INTERGRID]: Got notice about far away Region: " + otherRegion.RegionName.ToString() +
485 " at (" + otherRegion.RegionLocX.ToString() + ", " +
486 otherRegion.RegionLocY.ToString() + ")");
487 }
488 }
489 return true;
490 }
491
492 public void AddNeighborRegion(RegionInfo region)
493 {
494 lock (m_neighbours)
495 {
496 if (!CheckNeighborRegion(region))
497 {
498 m_neighbours.Add(region);
499 }
500 }
501 }
502
503 public bool CheckNeighborRegion(RegionInfo region)
504 {
505 bool found = false;
506 lock (m_neighbours)
507 {
508 foreach (RegionInfo reg in m_neighbours)
509 {
510 if (reg.RegionHandle == region.RegionHandle)
511 {
512 found = true;
513 break;
514 }
515 }
516 }
517 return found;
518 }
519
520 /// <summary>
521 /// Given float seconds, this will restart the region.
522 /// </summary>
523 /// <param name="seconds">float indicating duration before restart.</param>
524 public virtual void Restart(float seconds)
525 {
526 // notifications are done in 15 second increments
527 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
528 // It's a 'Cancel restart' request.
529
530 // RestartNow() does immediate restarting.
531 if (seconds < 15)
532 {
533 m_restartTimer.Stop();
534 m_dialogModule.SendGeneralAlert("Restart Aborted");
535 }
536 else
537 {
538 // Now we figure out what to set the timer to that does the notifications and calls, RestartNow()
539 m_restartTimer.Interval = 15000;
540 m_incrementsof15seconds = (int)seconds / 15;
541 m_RestartTimerCounter = 0;
542 m_restartTimer.AutoReset = true;
543 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
544 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
545 m_restartTimer.Start();
546 m_dialogModule.SendNotificationToUsersInRegion(
547 UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in 2 Minutes");
548 }
549 }
550
551 // The Restart timer has occured.
552 // We have to figure out if this is a notification or if the number of seconds specified in Restart
553 // have elapsed.
554 // If they have elapsed, call RestartNow()
555 public void RestartTimer_Elapsed(object sender, ElapsedEventArgs e)
556 {
557 m_RestartTimerCounter++;
558 if (m_RestartTimerCounter <= m_incrementsof15seconds)
559 {
560 if (m_RestartTimerCounter == 4 || m_RestartTimerCounter == 6 || m_RestartTimerCounter == 7)
561 m_dialogModule.SendNotificationToUsersInRegion(
562 UUID.Random(),
563 String.Empty,
564 RegionInfo.RegionName + ": Restarting in " + ((8 - m_RestartTimerCounter) * 15) + " seconds");
565 }
566 else
567 {
568 m_restartTimer.Stop();
569 m_restartTimer.AutoReset = false;
570 RestartNow();
571 }
572 }
573
574 // This causes the region to restart immediatley.
575 public void RestartNow()
576 {
577 if (PhysicsScene != null)
578 {
579 PhysicsScene.Dispose();
580 }
581
582 m_log.Error("[REGION]: Closing");
583 Close();
584 m_log.Error("[REGION]: Firing Region Restart Message");
585 base.Restart(0);
586 }
587
588 // This is a helper function that notifies root agents in this region that a new sim near them has come up
589 // This is in the form of a timer because when an instance of OpenSim.exe is started,
590 // Even though the sims initialize, they don't listen until 'all of the sims are initialized'
591 // If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it.
592 // subsequently the agent will never see the region come back online.
593 public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e)
594 {
595 m_restartWaitTimer.Stop();
596 lock (m_regionRestartNotifyList)
597 {
598 foreach (RegionInfo region in m_regionRestartNotifyList)
599 {
600 try
601 {
602 ForEachScenePresence(delegate(ScenePresence agent)
603 {
604 // If agent is a root agent.
605 if (!agent.IsChildAgent)
606 {
607 //agent.ControllingClient.new
608 //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo());
609 InformClientOfNeighbor(agent, region);
610 }
611 }
612 );
613 }
614 catch (NullReferenceException)
615 {
616 // This means that we're not booted up completely yet.
617 // This shouldn't happen too often anymore.
618 }
619 }
620
621 // Reset list to nothing.
622 m_regionRestartNotifyList.Clear();
623 }
624 }
625
626 public void SetSceneCoreDebug(bool ScriptEngine, bool CollisionEvents, bool PhysicsEngine)
627 {
628 if (m_scripts_enabled != !ScriptEngine)
629 {
630 // Tedd! Here's the method to disable the scripting engine!
631 if (ScriptEngine)
632 {
633 m_log.Info("Stopping all Scripts in Scene");
634 foreach (EntityBase ent in Entities)
635 {
636 if (ent is SceneObjectGroup)
637 {
638 ((SceneObjectGroup) ent).RemoveScriptInstances();
639 }
640 }
641 }
642 else
643 {
644 m_log.Info("Starting all Scripts in Scene");
645 lock (Entities)
646 {
647 foreach (EntityBase ent in Entities)
648 {
649 if (ent is SceneObjectGroup)
650 {
651 ((SceneObjectGroup)ent).CreateScriptInstances(0, false, DefaultScriptEngine, 0);
652 }
653 }
654 }
655 }
656 m_scripts_enabled = !ScriptEngine;
657 m_log.Info("[TOTEDD]: Here is the method to trigger disabling of the scripting engine");
658 }
659
660 if (m_physics_enabled != !PhysicsEngine)
661 {
662 m_physics_enabled = !PhysicsEngine;
663 }
664 }
665
666 public int GetInaccurateNeighborCount()
667 {
668 lock (m_neighbours)
669 {
670 return m_neighbours.Count;
671 }
672 }
673
674 // This is the method that shuts down the scene.
675 public override void Close()
676 {
677 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
678
679 // Kick all ROOT agents with the message, 'The simulator is going down'
680 ForEachScenePresence(delegate(ScenePresence avatar)
681 {
682 if (avatar.KnownChildRegionHandles.Contains(RegionInfo.RegionHandle))
683 avatar.KnownChildRegionHandles.Remove(RegionInfo.RegionHandle);
684
685 if (!avatar.IsChildAgent)
686 avatar.ControllingClient.Kick("The simulator is going down.");
687
688 avatar.ControllingClient.SendShutdownConnectionNotice();
689 });
690
691 // Wait here, or the kick messages won't actually get to the agents before the scene terminates.
692 Thread.Sleep(500);
693
694 // Stop all client threads.
695 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); });
696
697 // Stop updating the scene objects and agents.
698 //m_heartbeatTimer.Close();
699 shuttingdown = true;
700
701 m_log.Debug("[SCENE]: Persisting changed objects");
702 List<EntityBase> entities = GetEntities();
703 foreach (EntityBase entity in entities)
704 {
705 if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
706 {
707 ((SceneObjectGroup)entity).ProcessBackup(m_storageManager.DataStore, false);
708 }
709 }
710
711 m_sceneGraph.Close();
712
713 // De-register with region communications (events cleanup)
714 UnRegisterRegionWithComms();
715
716 // call the base class Close method.
717 base.Close();
718 }
719
720 /// <summary>
721 /// Start the timer which triggers regular scene updates
722 /// </summary>
723 public void StartTimer()
724 {
725 //m_log.Debug("[SCENE]: Starting timer");
726 //m_heartbeatTimer.Enabled = true;
727 //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
728 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
729 HeartbeatThread = new Thread(new ParameterizedThreadStart(Heartbeat));
730 HeartbeatThread.SetApartmentState(ApartmentState.MTA);
731 HeartbeatThread.Name = "Heartbeat";
732 HeartbeatThread.Priority = ThreadPriority.AboveNormal;
733 ThreadTracker.Add(HeartbeatThread);
734 HeartbeatThread.Start();
735 }
736
737 /// <summary>
738 /// Sets up references to modules required by the scene
739 /// </summary>
740 public void SetModuleInterfaces()
741 {
742 m_xmlrpcModule = RequestModuleInterface<IXMLRPC>();
743 m_worldCommModule = RequestModuleInterface<IWorldComm>();
744 XferManager = RequestModuleInterface<IXfer>();
745 m_AvatarFactory = RequestModuleInterface<IAvatarFactory>();
746 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>();
747 m_interregionCommsOut = RequestModuleInterface<IInterregionCommsOut>();
748 m_interregionCommsIn = RequestModuleInterface<IInterregionCommsIn>();
749 m_dialogModule = RequestModuleInterface<IDialogModule>();
750 CapsModule = RequestModuleInterface<ICapabilitiesModule>();
751 }
752
753 #endregion
754
755 #region Update Methods
756
757 /// <summary>
758 /// Performs per-frame updates regularly
759 /// </summary>
760 /// <param name="sender"></param>
761 /// <param name="e"></param>
762 private void Heartbeat(object sender)
763 {
764 Update();
765 }
766
767 /// <summary>
768 /// Performs per-frame updates on the scene, this should be the central scene loop
769 /// </summary>
770 public override void Update()
771 {
772 int maintc = 0;
773 while (!shuttingdown)
774 {
775 maintc = System.Environment.TickCount;
776
777 TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate;
778 // Aquire a lock so only one update call happens at once
779 //updateLock.WaitOne();
780 float physicsFPS = 0;
781 //m_log.Info("sadfadf" + m_neighbours.Count.ToString());
782 int agentsInScene = m_sceneGraph.GetRootAgentCount() + m_sceneGraph.GetChildAgentCount();
783
784 if (agentsInScene > 21)
785 {
786 if (m_update_entities == 1)
787 {
788 m_update_entities = 5;
789 StatsReporter.SetUpdateMS(6000);
790 }
791 }
792 else
793 {
794 if (m_update_entities == 5)
795 {
796 m_update_entities = 1;
797 StatsReporter.SetUpdateMS(3000);
798 }
799 }
800
801 frameMS = System.Environment.TickCount;
802 try
803 {
804 // Increment the frame counter
805 m_frame++;
806
807 // Loop it
808 if (m_frame == Int32.MaxValue)
809 m_frame = 0;
810
811 physicsMS2 = System.Environment.TickCount;
812 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
813 m_sceneGraph.UpdatePreparePhysics();
814 physicsMS2 = System.Environment.TickCount - physicsMS2;
815
816 if (m_frame % m_update_entitymovement == 0)
817 m_sceneGraph.UpdateEntityMovement();
818
819 physicsMS = System.Environment.TickCount;
820 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
821 physicsFPS = m_sceneGraph.UpdatePhysics(
822 Math.Max(SinceLastFrame.TotalSeconds, m_timespan)
823 );
824 if (m_frame % m_update_physics == 0 && SynchronizeScene != null)
825 SynchronizeScene(this);
826
827 physicsMS = System.Environment.TickCount - physicsMS;
828 physicsMS += physicsMS2;
829
830 otherMS = System.Environment.TickCount;
831 // run through all entities looking for updates (slow)
832 if (m_frame % m_update_entities == 0)
833 m_sceneGraph.UpdateEntities();
834
835 // run through entities that have scheduled themselves for
836 // updates looking for updates(faster)
837 if (m_frame % m_update_entitiesquick == 0)
838 m_sceneGraph.ProcessUpdates();
839
840 // Run through scenepresences looking for updates
841 if (m_frame % m_update_presences == 0)
842 m_sceneGraph.UpdatePresences();
843
844 // Delete temp-on-rez stuff
845 if (m_frame % m_update_backup == 0)
846 CleanTempObjects();
847
848 if (Region_Status != RegionStatus.SlaveScene)
849 {
850 if (m_frame % m_update_events == 0)
851 UpdateEvents();
852
853 if (m_frame % m_update_backup == 0)
854 {
855 UpdateStorageBackup();
856 }
857
858 if (m_frame % m_update_terrain == 0)
859 UpdateTerrain();
860
861 if (m_frame % m_update_land == 0)
862 UpdateLand();
863 otherMS = System.Environment.TickCount - otherMS;
864 // if (m_frame%m_update_avatars == 0)
865 // UpdateInWorldTime();
866 StatsReporter.AddPhysicsFPS(physicsFPS);
867 StatsReporter.AddTimeDilation(m_timedilation);
868 StatsReporter.AddFPS(1);
869 StatsReporter.AddInPackets(0);
870 StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
871 StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
872 StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
873 StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
874 frameMS = System.Environment.TickCount - frameMS;
875 StatsReporter.addFrameMS(frameMS);
876 StatsReporter.addPhysicsMS(physicsMS);
877 StatsReporter.addOtherMS(otherMS);
878 StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
879 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
880 }
881 }
882 catch (NotImplementedException)
883 {
884 throw;
885 }
886 catch (AccessViolationException e)
887 {
888 m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
889 }
890 //catch (NullReferenceException e)
891 //{
892 // m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
893 //}
894 catch (InvalidOperationException e)
895 {
896 m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
897 }
898 catch (Exception e)
899 {
900 m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
901 }
902 finally
903 {
904 //updateLock.ReleaseMutex();
905 // Get actual time dilation
906 float tmpval = (m_timespan / (float)SinceLastFrame.TotalSeconds);
907
908 // If actual time dilation is greater then one, we're catching up, so subtract
909 // the amount that's greater then 1 from the time dilation
910 if (tmpval > 1.0)
911 {
912 tmpval = tmpval - (tmpval - 1.0f);
913 }
914 m_timedilation = tmpval;
915
916 m_lastupdate = DateTime.Now;
917 }
918 maintc = System.Environment.TickCount - maintc;
919 maintc = (int)(m_timespan * 1000) - maintc;
920
921 if ((maintc < (m_timespan * 1000)) && maintc > 0)
922 Thread.Sleep(maintc);
923 }
924 }
925
926 private void SendSimStatsPackets(SimStats stats)
927 {
928 List<ScenePresence> StatSendAgents = GetScenePresences();
929 foreach (ScenePresence agent in StatSendAgents)
930 {
931 if (!agent.IsChildAgent)
932 {
933 agent.ControllingClient.SendSimStats(stats);
934 }
935 }
936 }
937
938 private void UpdateLand()
939 {
940 if (LandChannel != null)
941 {
942 if (LandChannel.IsLandPrimCountTainted())
943 {
944 EventManager.TriggerParcelPrimCountUpdate();
945 }
946 }
947 }
948
949 private void UpdateTerrain()
950 {
951 EventManager.TriggerTerrainTick();
952 }
953
954 private void UpdateStorageBackup()
955 {
956 if (!m_backingup)
957 {
958 m_backingup = true;
959 Thread backupthread = new Thread(Backup);
960 backupthread.Name = "BackupWriter";
961 backupthread.IsBackground = true;
962 backupthread.Start();
963 }
964 }
965
966 private void UpdateEvents()
967 {
968 m_eventManager.TriggerOnFrame();
969 }
970
971 /// <summary>
972 /// Perform delegate action on all clients subscribing to updates from this region.
973 /// </summary>
974 /// <returns></returns>
975 internal void Broadcast(Action<IClientAPI> whatToDo)
976 {
977 ForEachScenePresence(delegate(ScenePresence presence) { whatToDo(presence.ControllingClient); });
978 }
979
980 /// <summary>
981 /// Backup the scene. This acts as the main method of the backup thread.
982 /// </summary>
983 /// <returns></returns>
984 public void Backup()
985 {
986 lock (m_returns)
987 {
988 EventManager.TriggerOnBackup(m_storageManager.DataStore);
989 m_backingup = false;
990
991 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
992 {
993 UUID transaction = UUID.Random();
994
995 GridInstantMessage msg = new GridInstantMessage();
996 msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server
997 msg.toAgentID = new Guid(ret.Key.ToString());
998 msg.imSessionID = new Guid(transaction.ToString());
999 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
1000 msg.fromAgentName = "Server";
1001 msg.dialog = (byte)19; // Object msg
1002 msg.fromGroup = false;
1003 msg.offline = (byte)1;
1004 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1005 msg.Position = Vector3.Zero;
1006 msg.RegionID = RegionInfo.RegionID.Guid;
1007 msg.binaryBucket = new byte[0];
1008 if (ret.Value.count > 1)
1009 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
1010 else
1011 msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
1012
1013 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
1014 if (tr != null)
1015 tr.SendInstantMessage(msg, delegate(bool success) {} );
1016 }
1017 m_returns.Clear();
1018 }
1019 }
1020
1021 public void ForceSceneObjectBackup(SceneObjectGroup group)
1022 {
1023 if (group != null)
1024 {
1025 group.ProcessBackup(m_storageManager.DataStore, true);
1026 }
1027 }
1028
1029 public void AddReturn(UUID agentID, string objectName, Vector3 location, string reason)
1030 {
1031 lock (m_returns)
1032 {
1033 if (m_returns.ContainsKey(agentID))
1034 {
1035 ReturnInfo info = m_returns[agentID];
1036 info.count++;
1037 m_returns[agentID] = info;
1038 }
1039 else
1040 {
1041 ReturnInfo info = new ReturnInfo();
1042 info.count = 1;
1043 info.objectName = objectName;
1044 info.location = location;
1045 info.reason = reason;
1046 m_returns[agentID] = info;
1047 }
1048 }
1049 }
1050
1051 #endregion
1052
1053 #region Load Terrain
1054
1055 public void ExportWorldMap(string fileName)
1056 {
1057 List<MapBlockData> mapBlocks =
1058 m_sceneGridService.RequestNeighbourMapBlocks((int)(RegionInfo.RegionLocX - 9),
1059 (int)(RegionInfo.RegionLocY - 9),
1060 (int)(RegionInfo.RegionLocX + 9),
1061 (int)(RegionInfo.RegionLocY + 9));
1062 List<AssetBase> textures = new List<AssetBase>();
1063 List<Image> bitImages = new List<Image>();
1064
1065 foreach (MapBlockData mapBlock in mapBlocks)
1066 {
1067 AssetBase texAsset = AssetCache.GetAsset(mapBlock.MapImageId, true);
1068
1069 if (texAsset != null)
1070 {
1071 textures.Add(texAsset);
1072 }
1073 else
1074 {
1075 texAsset = AssetCache.GetAsset(mapBlock.MapImageId, true);
1076 if (texAsset != null)
1077 {
1078 textures.Add(texAsset);
1079 }
1080 }
1081 }
1082
1083 foreach (AssetBase asset in textures)
1084 {
1085 ManagedImage managedImage;
1086 Image image;
1087
1088 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
1089 bitImages.Add(image);
1090 }
1091
1092 Bitmap mapTexture = new Bitmap(2560, 2560);
1093 Graphics g = Graphics.FromImage(mapTexture);
1094 SolidBrush sea = new SolidBrush(Color.DarkBlue);
1095 g.FillRectangle(sea, 0, 0, 2560, 2560);
1096
1097 for (int i = 0; i < mapBlocks.Count; i++)
1098 {
1099 ushort x = (ushort)((mapBlocks[i].X - RegionInfo.RegionLocX) + 10);
1100 ushort y = (ushort)((mapBlocks[i].Y - RegionInfo.RegionLocY) + 10);
1101 g.DrawImage(bitImages[i], (x * 128), (y * 128), 128, 128);
1102 }
1103 mapTexture.Save(fileName, ImageFormat.Jpeg);
1104 }
1105
1106 public void SaveTerrain()
1107 {
1108 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1109 }
1110
1111 /// <summary>
1112 /// Loads the World heightmap
1113 /// </summary>
1114 public override void LoadWorldMap()
1115 {
1116 try
1117 {
1118 double[,] map = m_storageManager.DataStore.LoadTerrain(RegionInfo.RegionID);
1119 if (map == null)
1120 {
1121 m_log.Info("[TERRAIN]: No default terrain. Generating a new terrain.");
1122 Heightmap = new TerrainChannel();
1123
1124 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1125 }
1126 else
1127 {
1128 Heightmap = new TerrainChannel(map);
1129 }
1130
1131 }
1132 catch (Exception e)
1133 {
1134 m_log.Warn("[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception " + e.ToString());
1135 }
1136 }
1137
1138 /// <summary>
1139 /// Register this region with a grid service
1140 /// </summary>
1141 /// <exception cref="System.Exception">Thrown if registration of the region itself fails.</exception>
1142 public void RegisterRegionWithGrid()
1143 {
1144 RegisterCommsEvents();
1145
1146 // These two 'commands' *must be* next to each other or sim rebooting fails.
1147 m_sceneGridService.RegisterRegion(m_interregionCommsOut, RegionInfo);
1148 m_sceneGridService.InformNeighborsThatRegionisUp(RegionInfo);
1149
1150 Dictionary<string, string> dGridSettings = m_sceneGridService.GetGridSettings();
1151
1152 if (dGridSettings.ContainsKey("allow_forceful_banlines"))
1153 {
1154 if (dGridSettings["allow_forceful_banlines"] != "TRUE")
1155 {
1156 m_log.Info("[GRID]: Grid is disabling forceful parcel banlists");
1157 EventManager.TriggerSetAllowForcefulBan(false);
1158 }
1159 else
1160 {
1161 m_log.Info("[GRID]: Grid is allowing forceful parcel banlists");
1162 EventManager.TriggerSetAllowForcefulBan(true);
1163 }
1164 }
1165 }
1166
1167 /// <summary>
1168 ///
1169 /// </summary>
1170 public void CreateTerrainTexture(bool temporary)
1171 {
1172 //create a texture asset of the terrain
1173 IMapImageGenerator terrain = RequestModuleInterface<IMapImageGenerator>();
1174
1175 // Cannot create a map for a nonexistant heightmap yet.
1176 if (Heightmap == null)
1177 return;
1178
1179 if (terrain == null)
1180 {
1181 #region Fallback default maptile generation
1182
1183 int tc = System.Environment.TickCount;
1184 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain");
1185 Bitmap mapbmp = new Bitmap(256, 256);
1186 double[,] hm = Heightmap.GetDoubles();
1187 bool ShadowDebugContinue = true;
1188 //Color prim = Color.FromArgb(120, 120, 120);
1189 //Vector3 RayEnd = new Vector3(0, 0, 0);
1190 //Vector3 RayStart = new Vector3(0, 0, 0);
1191 //Vector3 direction = new Vector3(0, 0, -1);
1192 //Vector3 AXOrigin = new Vector3();
1193 //Vector3 AXdirection = new Vector3();
1194 //Ray testRay = new Ray();
1195 //EntityIntersection rt = new EntityIntersection();
1196 bool terraincorruptedwarningsaid = false;
1197
1198 float low = 255;
1199 float high = 0;
1200 for (int x = 0; x < 256; x++)
1201 {
1202 for (int y = 0; y < 256; y++)
1203 {
1204 float hmval = (float)hm[x, y];
1205 if (hmval < low)
1206 low = hmval;
1207 if (hmval > high)
1208 high = hmval;
1209 }
1210 }
1211
1212 float mid = (high + low) * 0.5f;
1213
1214 // temporary initializer
1215 float hfvalue = (float)m_regInfo.RegionSettings.WaterHeight;
1216 float hfvaluecompare = hfvalue;
1217 float hfdiff = hfvalue;
1218 int hfdiffi = 0;
1219
1220 for (int x = 0; x < 256; x++)
1221 {
1222 //int tc = System.Environment.TickCount;
1223 for (int y = 0; y < 256; y++)
1224 {
1225 //RayEnd = new Vector3(x, y, 0);
1226 //RayStart = new Vector3(x, y, 255);
1227
1228 //direction = Vector3.Norm(RayEnd - RayStart);
1229 //AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
1230 //AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
1231
1232 //testRay = new Ray(AXOrigin, AXdirection);
1233 //rt = m_sceneGraph.GetClosestIntersectingPrim(testRay);
1234
1235 //if (rt.HitTF)
1236 //{
1237 //mapbmp.SetPixel(x, y, prim);
1238 //}
1239 //else
1240 //{
1241 //float tmpval = (float)hm[x, y];
1242 float heightvalue = (float)hm[x, y];
1243
1244 if (heightvalue > (float)m_regInfo.RegionSettings.WaterHeight)
1245 {
1246 // scale height value
1247 heightvalue = low + mid * (heightvalue - low) / mid;
1248
1249 if (heightvalue > 255)
1250 heightvalue = 255;
1251
1252 if (heightvalue < 0)
1253 heightvalue = 0;
1254
1255 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
1256 heightvalue = 0;
1257
1258 try
1259 {
1260 Color green = Color.FromArgb((int)heightvalue, 100, (int)heightvalue);
1261
1262 // Y flip the cordinates
1263 mapbmp.SetPixel(x, (256 - y) - 1, green);
1264
1265 //X
1266 // .
1267 //
1268 // Shade the terrain for shadows
1269 if ((x - 1 > 0) && (y - 1 > 0))
1270 {
1271 hfvalue = (float)hm[x, y];
1272 hfvaluecompare = (float)hm[x - 1, y - 1];
1273
1274 if (Single.IsInfinity(hfvalue) || Single.IsNaN(hfvalue))
1275 hfvalue = 0;
1276
1277 if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare))
1278 hfvaluecompare = 0;
1279
1280 hfdiff = hfvaluecompare - hfvalue;
1281
1282 if (hfdiff > 0.3f)
1283 {
1284
1285 }
1286 else if (hfdiff < -0.3f)
1287 {
1288 // We have to desaturate and blacken the land at the same time
1289 // we use floats, colors use bytes, so shrink are space down to
1290 // 0-255
1291
1292 try
1293 {
1294 hfdiffi = Math.Abs((int)((hfdiff * 4) + (hfdiff * 0.5))) + 1;
1295 if (hfdiff % 1 != 0)
1296 {
1297 hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1);
1298 }
1299 }
1300 catch (System.OverflowException)
1301 {
1302 m_log.Debug("[MAPTILE]: Shadow failed at value: " + hfdiff.ToString());
1303 ShadowDebugContinue = false;
1304 }
1305
1306 if (ShadowDebugContinue)
1307 {
1308 if ((256 - y) - 1 > 0)
1309 {
1310 Color Shade = mapbmp.GetPixel(x - 1, (256 - y) - 1);
1311
1312 int r = Shade.R;
1313
1314 int g = Shade.G;
1315 int b = Shade.B;
1316 Shade = Color.FromArgb((r - hfdiffi > 0) ? r - hfdiffi : 0, (g - hfdiffi > 0) ? g - hfdiffi : 0, (b - hfdiffi > 0) ? b - hfdiffi : 0);
1317 //Console.WriteLine("d:" + hfdiff.ToString() + ", i:" + hfdiffi + ", pos: " + x + "," + y + " - R:" + Shade.R.ToString() + ", G:" + Shade.G.ToString() + ", B:" + Shade.G.ToString());
1318 mapbmp.SetPixel(x - 1, (256 - y) - 1, Shade);
1319 }
1320 }
1321 }
1322 }
1323 }
1324 catch (System.ArgumentException)
1325 {
1326 if (!terraincorruptedwarningsaid)
1327 {
1328 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", RegionInfo.RegionName);
1329 terraincorruptedwarningsaid = true;
1330 }
1331 Color black = Color.Black;
1332 mapbmp.SetPixel(x, (256 - y) - 1, black);
1333 }
1334 }
1335 else
1336 {
1337 // Y flip the cordinates
1338 heightvalue = (float)m_regInfo.RegionSettings.WaterHeight - heightvalue;
1339 if (heightvalue > 19)
1340 heightvalue = 19;
1341 if (heightvalue < 0)
1342 heightvalue = 0;
1343
1344 heightvalue = 100 - (heightvalue * 100) / 19;
1345
1346 if (heightvalue > 255)
1347 heightvalue = 255;
1348
1349 if (heightvalue < 0)
1350 heightvalue = 0;
1351
1352 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
1353 heightvalue = 0;
1354
1355 try
1356 {
1357 Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255);
1358 mapbmp.SetPixel(x, (256 - y) - 1, water);
1359 }
1360 catch (System.ArgumentException)
1361 {
1362 if (!terraincorruptedwarningsaid)
1363 {
1364 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", RegionInfo.RegionName);
1365 terraincorruptedwarningsaid = true;
1366 }
1367 Color black = Color.Black;
1368 mapbmp.SetPixel(x, (256 - y) - 1, black);
1369 }
1370 }
1371 }
1372 //}
1373
1374 //tc = System.Environment.TickCount - tc;
1375 //m_log.Info("[MAPTILE]: Completed One row in " + tc + " ms");
1376 }
1377
1378 m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms");
1379
1380 bool drawPrimVolume = true;
1381
1382 try
1383 {
1384 IConfig startupConfig = m_config.Configs["Startup"];
1385 drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", true);
1386 }
1387 catch
1388 {
1389 m_log.Warn("[MAPTILE]: Failed to load StartupConfig");
1390 }
1391
1392 if (drawPrimVolume)
1393 {
1394 tc = System.Environment.TickCount;
1395 m_log.Info("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
1396 List<EntityBase> objs = GetEntities();
1397
1398 lock (objs)
1399 {
1400 foreach (EntityBase obj in objs)
1401 {
1402 // Only draw the contents of SceneObjectGroup
1403 if (obj is SceneObjectGroup)
1404 {
1405 SceneObjectGroup mapdot = (SceneObjectGroup)obj;
1406 Color mapdotspot = Color.Gray; // Default color when prim color is white
1407 // Loop over prim in group
1408 foreach (SceneObjectPart part in mapdot.Children.Values)
1409 {
1410 if (part == null)
1411 continue;
1412
1413 // Draw if the object is at least 1 meter wide in any direction
1414 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
1415 {
1416 // Try to get the RGBA of the default texture entry..
1417 //
1418 try
1419 {
1420 if (part == null)
1421 continue;
1422
1423 if (part.Shape == null)
1424 continue;
1425
1426 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree)
1427 continue; // eliminates trees from this since we don't really have a good tree representation
1428 // if you want tree blocks on the map comment the above line and uncomment the below line
1429 //mapdotspot = Color.PaleGreen;
1430
1431 if (part.Shape.Textures == null)
1432 continue;
1433
1434 if (part.Shape.Textures.DefaultTexture == null)
1435 continue;
1436
1437 Color4 texcolor = part.Shape.Textures.DefaultTexture.RGBA;
1438
1439 // Not sure why some of these are null, oh well.
1440
1441 int colorr = 255 - (int)(texcolor.R * 255f);
1442 int colorg = 255 - (int)(texcolor.G * 255f);
1443 int colorb = 255 - (int)(texcolor.B * 255f);
1444
1445 if (!(colorr == 255 && colorg == 255 && colorb == 255))
1446 {
1447 //Try to set the map spot color
1448 try
1449 {
1450 // If the color gets goofy somehow, skip it *shakes fist at Color4
1451 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
1452 }
1453 catch (ArgumentException)
1454 {
1455 }
1456 }
1457 }
1458 catch (IndexOutOfRangeException)
1459 {
1460 // Windows Array
1461 }
1462 catch (ArgumentOutOfRangeException)
1463 {
1464 // Mono Array
1465 }
1466
1467 Vector3 pos = part.GetWorldPosition();
1468
1469 // skip prim outside of retion
1470 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
1471 continue;
1472
1473 // skip prim in non-finite position
1474 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || Single.IsInfinity(pos.X)
1475 || Single.IsInfinity(pos.Y))
1476 continue;
1477
1478 // Figure out if object is under 256m above the height of the terrain
1479 bool isBelow256AboveTerrain = false;
1480
1481 try
1482 {
1483 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
1484 }
1485 catch (Exception)
1486 {
1487 }
1488
1489 if (isBelow256AboveTerrain)
1490 {
1491 // Translate scale by rotation so scale is represented properly when object is rotated
1492 Vector3 scale = part.Shape.Scale;
1493 Quaternion rot = part.GetWorldRotation();
1494 scale *= rot;
1495
1496 // negative scales don't work in this situation
1497 scale.X = Math.Abs(scale.X);
1498 scale.Y = Math.Abs(scale.Y);
1499 scale.Z = Math.Abs(scale.Z);
1500
1501 // This scaling isn't very accurate and doesn't take into account the face rotation :P
1502 int mapdrawstartX = (int)(pos.X - scale.X);
1503 int mapdrawstartY = (int)(pos.Y - scale.Y);
1504 int mapdrawendX = (int)(pos.X + scale.X);
1505 int mapdrawendY = (int)(pos.Y + scale.Y);
1506
1507 // If object is beyond the edge of the map, don't draw it to avoid errors
1508 if (mapdrawstartX < 0 || mapdrawstartX > 255 || mapdrawendX < 0 || mapdrawendX > 255
1509 || mapdrawstartY < 0 || mapdrawstartY > 255 || mapdrawendY < 0
1510 || mapdrawendY > 255)
1511 continue;
1512
1513 int wy = 0;
1514
1515 bool breakYN = false; // If we run into an error drawing, break out of the
1516 // loop so we don't lag to death on error handling
1517 for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
1518 {
1519 for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
1520 {
1521 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
1522 try
1523 {
1524 // Remember, flip the y!
1525 mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
1526 }
1527 catch (ArgumentException)
1528 {
1529 breakYN = true;
1530 }
1531
1532 if (breakYN)
1533 break;
1534 }
1535
1536 if (breakYN)
1537 break;
1538 }
1539 } // Object is within 256m Z of terrain
1540 } // object is at least a meter wide
1541 } // loop over group children
1542 } // entitybase is sceneobject group
1543 } // foreach loop over entities
1544 } // lock entities objs
1545
1546 m_log.Info("[MAPTILE]: Generating Maptile Step 2: Done in " + (System.Environment.TickCount - tc) + " ms");
1547 } // end if drawPrimOnMaptle
1548
1549 byte[] data;
1550 try
1551 {
1552 data = OpenJPEG.EncodeFromImage(mapbmp, false);
1553 }
1554 catch (Exception)
1555 {
1556 return;
1557 }
1558
1559 LazySaveGeneratedMaptile(data,temporary);
1560
1561 #endregion
1562 }
1563 else
1564 {
1565 // Use the module to generate the maptile.
1566 byte[] data = terrain.WriteJpeg2000Image("defaultstripe.png");
1567 if (data != null)
1568 {
1569 LazySaveGeneratedMaptile(data,temporary);
1570 }
1571 }
1572 }
1573
1574 public void LazySaveGeneratedMaptile(byte[] data, bool temporary)
1575 {
1576 // Overwrites the local Asset cache with new maptile data
1577 // Assets are single write, this causes the asset server to ignore this update,
1578 // but the local asset cache does not
1579
1580 // this is on purpose! The net result of this is the region always has the most up to date
1581 // map tile while protecting the (grid) asset database from bloat caused by a new asset each
1582 // time a mapimage is generated!
1583
1584 UUID lastMapRegionUUID = m_regInfo.lastMapUUID;
1585
1586 int lastMapRefresh = 0;
1587 int twoDays = 172800;
1588 int RefreshSeconds = twoDays;
1589
1590 try
1591 {
1592 lastMapRefresh = Convert.ToInt32(m_regInfo.lastMapRefresh);
1593 }
1594 catch (ArgumentException)
1595 {
1596 }
1597 catch (FormatException)
1598 {
1599 }
1600 catch (OverflowException)
1601 {
1602 }
1603
1604 UUID TerrainImageUUID = UUID.Random();
1605
1606 if (lastMapRegionUUID == UUID.Zero || (lastMapRefresh + RefreshSeconds) < Util.UnixTimeSinceEpoch())
1607 {
1608 m_regInfo.SaveLastMapUUID(TerrainImageUUID);
1609
1610 m_log.Warn("[MAPTILE]: STORING MAPTILE IMAGE");
1611 }
1612 else
1613 {
1614 TerrainImageUUID = lastMapRegionUUID;
1615 m_log.Warn("[MAPTILE]: REUSING OLD MAPTILE IMAGE ID");
1616 }
1617
1618 m_regInfo.RegionSettings.TerrainImageID = TerrainImageUUID;
1619
1620 AssetBase asset = new AssetBase();
1621 asset.Metadata.FullID = m_regInfo.RegionSettings.TerrainImageID;
1622 asset.Data = data;
1623 asset.Metadata.Name = "terrainImage_" + m_regInfo.RegionID.ToString() + "_" + lastMapRefresh.ToString();
1624 asset.Metadata.Description = RegionInfo.RegionName;
1625
1626 asset.Metadata.Type = 0;
1627 asset.Metadata.Temporary = temporary;
1628 AssetCache.AddAsset(asset);
1629 }
1630
1631 #endregion
1632
1633 #region Load Land
1634
1635 public void loadAllLandObjectsFromStorage(UUID regionID)
1636 {
1637 m_log.Info("[SCENE]: Loading land objects from storage");
1638 List<LandData> landData = m_storageManager.DataStore.LoadLandObjects(regionID);
1639
1640 if (LandChannel != null)
1641 {
1642 if (landData.Count == 0)
1643 {
1644 EventManager.TriggerNoticeNoLandDataFromStorage();
1645 }
1646 else
1647 {
1648 EventManager.TriggerIncomingLandDataFromStorage(landData);
1649 }
1650 }
1651 else
1652 {
1653 m_log.Error("[SCENE]: Land Channel is not defined. Cannot load from storage!");
1654 }
1655 }
1656
1657 #endregion
1658
1659 #region Primitives Methods
1660
1661 /// <summary>
1662 /// Loads the World's objects
1663 /// </summary>
1664 public virtual void LoadPrimsFromStorage(UUID regionID)
1665 {
1666 m_log.Info("[SCENE]: Loading objects from datastore");
1667
1668 List<SceneObjectGroup> PrimsFromDB = m_storageManager.DataStore.LoadObjects(regionID);
1669 foreach (SceneObjectGroup group in PrimsFromDB)
1670 {
1671 if (group.RootPart == null)
1672 {
1673 m_log.ErrorFormat("[SCENE] Found a SceneObjectGroup with m_rootPart == null and {0} children",
1674 group.Children == null ? 0 : group.Children.Count);
1675 }
1676
1677 AddRestoredSceneObject(group, true, true);
1678 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
1679 rootPart.ObjectFlags &= ~(uint)PrimFlags.Scripted;
1680 rootPart.TrimPermissions();
1681 group.CheckSculptAndLoad();
1682 //rootPart.DoPhysicsPropertyUpdate(UsePhysics, true);
1683 }
1684
1685 m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)");
1686 }
1687
1688 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1689 {
1690 Vector3 pos = Vector3.Zero;
1691 if (RayEndIsIntersection == (byte)1)
1692 {
1693 pos = RayEnd;
1694 return pos;
1695 }
1696
1697 if (RayTargetID != UUID.Zero)
1698 {
1699 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1700
1701 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
1702 Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
1703 Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
1704
1705 if (target != null)
1706 {
1707 pos = target.AbsolutePosition;
1708 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
1709
1710 // TODO: Raytrace better here
1711
1712 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
1713 Ray NewRay = new Ray(AXOrigin, AXdirection);
1714
1715 // Ray Trace against target here
1716 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1717
1718 // Un-comment out the following line to Get Raytrace results printed to the console.
1719 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1720 float ScaleOffset = 0.5f;
1721
1722 // If we hit something
1723 if (ei.HitTF)
1724 {
1725 Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
1726 if (scaleComponent.X != 0) ScaleOffset = scale.X;
1727 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
1728 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
1729 ScaleOffset = Math.Abs(ScaleOffset);
1730 Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1731 Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
1732 // Set the position to the intersection point
1733 Vector3 offset = (normal * (ScaleOffset / 2f));
1734 pos = (intersectionpoint + offset);
1735
1736 // Un-offset the prim (it gets offset later by the consumer method)
1737 pos.Z -= 0.25F;
1738 }
1739
1740 return pos;
1741 }
1742 else
1743 {
1744 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1745
1746 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1747
1748 // Un-comment the following line to print the raytrace results to the console.
1749 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1750
1751 if (ei.HitTF)
1752 {
1753 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1754 } else
1755 {
1756 // fall back to our stupid functionality
1757 pos = RayEnd;
1758 }
1759
1760 return pos;
1761 }
1762 }
1763 else
1764 {
1765 // fall back to our stupid functionality
1766 pos = RayEnd;
1767 return pos;
1768 }
1769 }
1770
1771 public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape,
1772 byte bypassRaycast, Vector3 RayStart, UUID RayTargetID,
1773 byte RayEndIsIntersection)
1774 {
1775 Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection, true, new Vector3(0.5f, 0.5f, 0.5f), false);
1776
1777 if (Permissions.CanRezObject(1, ownerID, pos))
1778 {
1779 // rez ON the ground, not IN the ground
1780 pos.Z += 0.25F;
1781
1782 AddNewPrim(ownerID, groupID, pos, rot, shape);
1783 }
1784 }
1785
1786 public virtual SceneObjectGroup AddNewPrim(
1787 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
1788 {
1789 //m_log.DebugFormat(
1790 // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName);
1791
1792 // If an entity creator has been registered for this prim type then use that
1793 if (m_entityCreators.ContainsKey((PCode)shape.PCode))
1794 return m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape);
1795
1796 // Otherwise, use this default creation code;
1797 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
1798 AddNewSceneObject(sceneObject, true);
1799 sceneObject.SetGroup(groupID, null);
1800
1801 return sceneObject;
1802 }
1803
1804 /// <summary>
1805 /// Add an object into the scene that has come from storage
1806 /// </summary>
1807 ///
1808 /// <param name="sceneObject"></param>
1809 /// <param name="attachToBackup">
1810 /// If true, changes to the object will be reflected in its persisted data
1811 /// If false, the persisted data will not be changed even if the object in the scene is changed
1812 /// </param>
1813 /// <param name="alreadyPersisted">
1814 /// If true, we won't persist this object until it changes
1815 /// If false, we'll persist this object immediately
1816 /// </param>
1817 /// <returns>
1818 /// true if the object was added, false if an object with the same uuid was already in the scene
1819 /// </returns>
1820 public bool AddRestoredSceneObject(
1821 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted)
1822 {
1823 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted);
1824 }
1825
1826 /// <summary>
1827 /// Add a newly created object to the scene
1828 /// </summary>
1829 /// <param name="sceneObject"></param>
1830 /// <param name="attachToBackup">
1831 /// If true, the object is made persistent into the scene.
1832 /// If false, the object will not persist over server restarts
1833 /// </param>
1834 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup)
1835 {
1836 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup);
1837 }
1838
1839 /// <summary>
1840 /// Delete every object from the scene
1841 /// </summary>
1842 public void DeleteAllSceneObjects()
1843 {
1844 lock (Entities)
1845 {
1846 ICollection<EntityBase> entities = new List<EntityBase>(Entities);
1847
1848 foreach (EntityBase e in entities)
1849 {
1850 if (e is SceneObjectGroup)
1851 DeleteSceneObject((SceneObjectGroup)e, false);
1852 }
1853 }
1854 }
1855
1856 /// <summary>
1857 /// Synchronously delete the given object from the scene.
1858 /// </summary>
1859 /// <param name="group">Object Id</param>
1860 /// <param name="silent">Suppress broadcasting changes to other clients.</param>
1861 public void DeleteSceneObject(SceneObjectGroup group, bool silent)
1862 {
1863 //SceneObjectPart rootPart = group.GetChildPart(group.UUID);
1864
1865 // Serialise calls to RemoveScriptInstances to avoid
1866 // deadlocking on m_parts inside SceneObjectGroup
1867 lock (m_deleting_scene_object)
1868 {
1869 group.RemoveScriptInstances();
1870 }
1871
1872 foreach (SceneObjectPart part in group.Children.Values)
1873 {
1874 if (part.IsJoint() && ((part.ObjectFlags&(uint)PrimFlags.Physics) != 0) )
1875 {
1876 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
1877 }
1878 else if (part.PhysActor != null)
1879 {
1880 PhysicsScene.RemovePrim(part.PhysActor);
1881 part.PhysActor = null;
1882 }
1883 }
1884// if (rootPart.PhysActor != null)
1885// {
1886// PhysicsScene.RemovePrim(rootPart.PhysActor);
1887// rootPart.PhysActor = null;
1888// }
1889
1890 if (UnlinkSceneObject(group.UUID, false))
1891 {
1892 EventManager.TriggerObjectBeingRemovedFromScene(group);
1893 EventManager.TriggerParcelPrimCountTainted();
1894 }
1895
1896 group.DeleteGroup(silent);
1897 }
1898
1899 /// <summary>
1900 /// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the
1901 /// object itself is not destroyed.
1902 /// </summary>
1903 /// <param name="uuid">Id of object.</param>
1904 /// <returns>true if the object was in the scene, false if it was not</returns>
1905 /// <param name="softDelete">If true, only deletes from scene, but keeps object in database.</param>
1906 public bool UnlinkSceneObject(UUID uuid, bool softDelete)
1907 {
1908 if (m_sceneGraph.DeleteSceneObject(uuid, softDelete))
1909 {
1910 if (!softDelete)
1911 {
1912 m_storageManager.DataStore.RemoveObject(uuid,
1913 m_regInfo.RegionID);
1914 }
1915
1916 return true;
1917 }
1918
1919 return false;
1920 }
1921
1922 /// <summary>
1923 /// Move the given scene object into a new region depending on which region its absolute position has moved
1924 /// into.
1925 ///
1926 /// This method locates the new region handle and offsets the prim position for the new region
1927 /// </summary>
1928 /// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
1929 /// <param name="grp">the scene object that we're crossing</param>
1930 public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent)
1931 {
1932 if (grp == null)
1933 return;
1934 if (grp.IsDeleted)
1935 return;
1936
1937 if (grp.RootPart.DIE_AT_EDGE)
1938 {
1939 // We remove the object here
1940 try
1941 {
1942 DeleteSceneObject(grp, false);
1943 }
1944 catch (Exception)
1945 {
1946 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
1947 }
1948 return;
1949 }
1950
1951 int thisx = (int)RegionInfo.RegionLocX;
1952 int thisy = (int)RegionInfo.RegionLocY;
1953
1954 ulong newRegionHandle = 0;
1955 Vector3 pos = attemptedPosition;
1956
1957 if (attemptedPosition.X > Constants.RegionSize + 0.1f)
1958 {
1959 pos.X = ((pos.X - Constants.RegionSize));
1960 newRegionHandle
1961 = Util.UIntsToLong((uint)((thisx + 1) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize));
1962 // x + 1
1963 }
1964 else if (attemptedPosition.X < -0.1f)
1965 {
1966 pos.X = ((pos.X + Constants.RegionSize));
1967 newRegionHandle
1968 = Util.UIntsToLong((uint)((thisx - 1) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize));
1969 // x - 1
1970 }
1971
1972 if (attemptedPosition.Y > Constants.RegionSize + 0.1f)
1973 {
1974 pos.Y = ((pos.Y - Constants.RegionSize));
1975 newRegionHandle
1976 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + 1) * Constants.RegionSize));
1977 // y + 1
1978 }
1979 else if (attemptedPosition.Y < -0.1f)
1980 {
1981 pos.Y = ((pos.Y + Constants.RegionSize));
1982 newRegionHandle
1983 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - 1) * Constants.RegionSize));
1984 // y - 1
1985 }
1986
1987 // Offset the positions for the new region across the border
1988 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
1989 grp.OffsetForNewRegion(pos);
1990
1991 // If we fail to cross the border, then reset the position of the scene object on that border.
1992 if (!CrossPrimGroupIntoNewRegion(newRegionHandle, grp, silent))
1993 {
1994 grp.OffsetForNewRegion(oldGroupPosition);
1995 grp.ScheduleGroupForFullUpdate();
1996 }
1997 }
1998
1999 /// <summary>
2000 /// Move the given scene object into a new region
2001 /// </summary>
2002 /// <param name="newRegionHandle"></param>
2003 /// <param name="grp">Scene Object Group that we're crossing</param>
2004 /// <returns>
2005 /// true if the crossing itself was successful, false on failure
2006 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
2007 /// </returns>
2008 public bool CrossPrimGroupIntoNewRegion(ulong newRegionHandle, SceneObjectGroup grp, bool silent)
2009 {
2010 bool successYN = false;
2011 grp.RootPart.UpdateFlag = 0;
2012 int primcrossingXMLmethod = 0;
2013
2014 if (newRegionHandle != 0)
2015 {
2016 string objectState = grp.GetStateSnapshot();
2017
2018 successYN
2019 = m_sceneGridService.PrimCrossToNeighboringRegion(
2020 newRegionHandle, grp.UUID, m_serialiser.SaveGroupToXml2(grp), primcrossingXMLmethod);
2021 if (successYN && (objectState != "") && m_allowScriptCrossings)
2022 {
2023 successYN = m_sceneGridService.PrimCrossToNeighboringRegion(
2024 newRegionHandle, grp.UUID, objectState, 100);
2025 }
2026
2027 if (successYN)
2028 {
2029 // We remove the object here
2030 try
2031 {
2032 DeleteSceneObject(grp, silent);
2033 }
2034 catch (Exception e)
2035 {
2036 m_log.ErrorFormat(
2037 "[INTERREGION]: Exception deleting the old object left behind on a border crossing for {0}, {1}",
2038 grp, e);
2039 }
2040 }
2041 else
2042 {
2043 if (!grp.IsDeleted)
2044 {
2045 if (grp.RootPart.PhysActor != null)
2046 {
2047 grp.RootPart.PhysActor.CrossingFailure();
2048 }
2049 }
2050
2051 m_log.ErrorFormat("[INTERREGION]: Prim crossing failed for {0}", grp);
2052 }
2053 }
2054 else
2055 {
2056 m_log.Error("[INTERREGION]: region handle was unexpectedly 0 in Scene.CrossPrimGroupIntoNewRegion()");
2057 }
2058
2059 return successYN;
2060 }
2061
2062 /// <summary>
2063 /// Handle a scene object that is crossing into this region from another.
2064 /// </summary>
2065 /// <param name="regionHandle"></param>
2066 /// <param name="primID"></param>
2067 /// <param name="objXMLData"></param>
2068 /// <param name="XMLMethod"></param>
2069 /// <returns></returns>
2070 public bool IncomingInterRegionPrimGroup(UUID primID, string objXMLData, int XMLMethod)
2071 {
2072
2073 if (XMLMethod == 0)
2074 {
2075 m_log.DebugFormat("[INTERREGION]: A new prim {0} arrived from a neighbor", primID);
2076 SceneObjectGroup sceneObject = m_serialiser.DeserializeGroupFromXml2(objXMLData);
2077
2078 // If the user is banned, we won't let any of their objects
2079 // enter. Period.
2080 //
2081 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID))
2082 {
2083 m_log.Info("[INTERREGION]: Denied prim crossing for "+
2084 "banned avatar");
2085
2086 return false;
2087 }
2088
2089 // Force allocation of new LocalId
2090 //
2091 foreach (SceneObjectPart p in sceneObject.Children.Values)
2092 p.LocalId = 0;
2093
2094 if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim)
2095 {
2096 if (sceneObject.RootPart.Shape.State != 0)
2097 {
2098 // Fix up attachment Parent Local ID
2099 //
2100 ScenePresence sp = GetScenePresence(sceneObject.OwnerID);
2101
2102 uint parentLocalID = 0;
2103 if (sp != null)
2104 parentLocalID = sp.LocalId;
2105
2106 sceneObject.RootPart.IsAttachment = true;
2107 sceneObject.RootPart.SetParentLocalId(parentLocalID);
2108
2109 AddRestoredSceneObject(sceneObject, false, false);
2110
2111 // Handle attachment special case
2112 //
2113 SceneObjectPart RootPrim = GetSceneObjectPart(primID);
2114
2115 if (RootPrim != null)
2116 {
2117 SceneObjectGroup grp = RootPrim.ParentGroup;
2118
2119 RootPrim.SetParentLocalId(parentLocalID);
2120
2121 if (grp != null)
2122 {
2123 m_log.DebugFormat("[ATTACHMENT]: Received "+
2124 "attachment {0}, inworld asset id {1}",
2125 grp.RootPart.LastOwnerID.ToString(),
2126 grp.UUID.ToString());
2127
2128 if (sp != null)
2129 {
2130 grp.SetFromAssetID(grp.RootPart.LastOwnerID);
2131 m_log.DebugFormat("[ATTACHMENT]: Attach "+
2132 "to avatar {0}",
2133 sp.UUID.ToString());
2134 AttachObject(sp.ControllingClient,
2135 grp.LocalId, (uint)0,
2136 grp.GroupRotation,
2137 grp.AbsolutePosition, false);
2138 grp.SendGroupFullUpdate();
2139 }
2140 else
2141 {
2142 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2143 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2144 }
2145 }
2146 }
2147 }
2148 else
2149 {
2150 AddRestoredSceneObject(sceneObject, true, false);
2151
2152 if (!Permissions.CanObjectEntry(sceneObject.UUID,
2153 true, sceneObject.AbsolutePosition))
2154 {
2155 // Deny non attachments based on parcel settings
2156 //
2157 m_log.Info("[INTERREGION]: Denied prim crossing "+
2158 "because of parcel settings");
2159
2160 DeleteSceneObject(sceneObject, false);
2161
2162 return false;
2163 }
2164 }
2165 }
2166 }
2167 else if ((XMLMethod == 100) && m_allowScriptCrossings)
2168 {
2169 m_log.Warn("[INTERREGION]: Prim state data arrived from a neighbor");
2170 XmlDocument doc = new XmlDocument();
2171 doc.LoadXml(objXMLData);
2172
2173 XmlNodeList rootL = doc.GetElementsByTagName("ScriptData");
2174 if (rootL.Count == 1)
2175 {
2176 XmlNode rootNode = rootL[0];
2177 if (rootNode != null)
2178 {
2179 XmlNodeList partL = rootNode.ChildNodes;
2180
2181 foreach (XmlNode part in partL)
2182 {
2183 XmlNodeList nodeL = part.ChildNodes;
2184
2185 switch (part.Name)
2186 {
2187 case "Assemblies":
2188 foreach (XmlNode asm in nodeL)
2189 {
2190 string fn = asm.Attributes.GetNamedItem("Filename").Value;
2191
2192 Byte[] filedata = Convert.FromBase64String(asm.InnerText);
2193 string path = Path.Combine("ScriptEngines", RegionInfo.RegionID.ToString());
2194 path = Path.Combine(path, fn);
2195
2196 if (!File.Exists(path))
2197 {
2198 FileStream fs = File.Create(path);
2199 fs.Write(filedata, 0, filedata.Length);
2200 fs.Close();
2201 }
2202 }
2203 break;
2204 case "ScriptStates":
2205 foreach (XmlNode st in nodeL)
2206 {
2207 string id = st.Attributes.GetNamedItem("UUID").Value;
2208 UUID uuid = new UUID(id);
2209 XmlNode state = st.ChildNodes[0];
2210
2211 XmlDocument sdoc = new XmlDocument();
2212 XmlNode sxmlnode = sdoc.CreateNode(
2213 XmlNodeType.XmlDeclaration,
2214 "", "");
2215 sdoc.AppendChild(sxmlnode);
2216
2217 XmlNode newnode = sdoc.ImportNode(state, true);
2218 sdoc.AppendChild(newnode);
2219
2220 string spath = Path.Combine("ScriptEngines", RegionInfo.RegionID.ToString());
2221 spath = Path.Combine(spath, uuid.ToString());
2222 FileStream sfs = File.Create(spath + ".state");
2223 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
2224 Byte[] buf = enc.GetBytes(sdoc.InnerXml);
2225 sfs.Write(buf, 0, buf.Length);
2226 sfs.Close();
2227 }
2228 break;
2229 }
2230 }
2231 }
2232 }
2233
2234 SceneObjectPart RootPrim = GetSceneObjectPart(primID);
2235 RootPrim.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1);
2236
2237 return true;
2238 }
2239
2240 return true;
2241 }
2242
2243 #endregion
2244
2245 #region Add/Remove Avatar Methods
2246
2247 public override void AddNewClient(IClientAPI client)
2248 {
2249 SubscribeToClientEvents(client);
2250 ScenePresence presence;
2251
2252 if (m_restorePresences.ContainsKey(client.AgentId))
2253 {
2254 m_log.DebugFormat("[SCENE]: Restoring agent {0} {1} in {2}", client.Name, client.AgentId, RegionInfo.RegionName);
2255
2256 presence = m_restorePresences[client.AgentId];
2257 m_restorePresences.Remove(client.AgentId);
2258
2259 // This is one of two paths to create avatars that are
2260 // used. This tends to get called more in standalone
2261 // than grid, not really sure why, but as such needs
2262 // an explicity appearance lookup here.
2263 AvatarAppearance appearance = null;
2264 GetAvatarAppearance(client, out appearance);
2265 presence.Appearance = appearance;
2266
2267 presence.initializeScenePresence(client, RegionInfo, this);
2268
2269 m_sceneGraph.AddScenePresence(presence);
2270
2271 lock (m_restorePresences)
2272 {
2273 Monitor.PulseAll(m_restorePresences);
2274 }
2275 }
2276 else
2277 {
2278 m_log.DebugFormat(
2279 "[SCENE]: Adding new child agent for {0} in {1}",
2280 client.Name, RegionInfo.RegionName);
2281
2282 CommsManager.UserProfileCacheService.AddNewUser(client.AgentId);
2283
2284 CreateAndAddScenePresence(client);
2285 }
2286
2287 m_LastLogin = System.Environment.TickCount;
2288 EventManager.TriggerOnNewClient(client);
2289 }
2290
2291 protected virtual void SubscribeToClientEvents(IClientAPI client)
2292 {
2293 client.OnRegionHandShakeReply += SendLayerData;
2294 client.OnAddPrim += AddNewPrim;
2295 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition;
2296 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2297 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation;
2298 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimRotation;
2299 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
2300 client.OnUpdatePrimScale += m_sceneGraph.UpdatePrimScale;
2301 client.OnUpdatePrimGroupScale += m_sceneGraph.UpdatePrimGroupScale;
2302 client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam;
2303 client.OnUpdatePrimShape += m_sceneGraph.UpdatePrimShape;
2304 client.OnUpdatePrimTexture += m_sceneGraph.UpdatePrimTexture;
2305 client.OnTeleportLocationRequest += RequestTeleportLocation;
2306 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
2307 client.OnObjectSelect += SelectPrim;
2308 client.OnObjectDeselect += DeselectPrim;
2309 client.OnGrabUpdate += m_sceneGraph.MoveObject;
2310 client.OnDeRezObject += DeRezObject;
2311 client.OnRezObject += RezObject;
2312 client.OnRezSingleAttachmentFromInv += RezSingleAttachment;
2313 client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv;
2314 client.OnObjectAttach += m_sceneGraph.AttachObject;
2315 client.OnObjectDetach += m_sceneGraph.DetachObject;
2316 client.OnObjectDrop += m_sceneGraph.DropObject;
2317 client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest;
2318 client.OnObjectDescription += m_sceneGraph.PrimDescription;
2319 client.OnObjectName += m_sceneGraph.PrimName;
2320 client.OnObjectClickAction += m_sceneGraph.PrimClickAction;
2321 client.OnObjectMaterial += m_sceneGraph.PrimMaterial;
2322 client.OnLinkObjects += m_sceneGraph.LinkObjects;
2323 client.OnDelinkObjects += m_sceneGraph.DelinkObjects;
2324 client.OnObjectDuplicate += m_sceneGraph.DuplicateObject;
2325 client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay;
2326 client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags;
2327 client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily;
2328 client.OnRequestGodlikePowers += handleRequestGodlikePowers;
2329 client.OnGodKickUser += HandleGodlikeKickUser;
2330 client.OnObjectPermissions += HandleObjectPermissionsUpdate;
2331 client.OnCreateNewInventoryItem += CreateNewInventoryItem;
2332 client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
2333 client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
2334 client.OnMoveInventoryFolder += HandleMoveInventoryFolder;
2335 client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents;
2336 client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents;
2337 client.OnFetchInventory += HandleFetchInventory;
2338 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2339 client.OnCopyInventoryItem += CopyInventoryItem;
2340 client.OnMoveInventoryItem += MoveInventoryItem;
2341 client.OnRemoveInventoryItem += RemoveInventoryItem;
2342 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
2343 client.OnRezScript += RezScript;
2344 client.OnRequestTaskInventory += RequestTaskInventory;
2345 client.OnRemoveTaskItem += RemoveTaskInventory;
2346 client.OnUpdateTaskInventory += UpdateTaskInventory;
2347 client.OnMoveTaskItem += ClientMoveTaskInventoryItem;
2348 client.OnGrabObject += ProcessObjectGrab;
2349 client.OnDeGrabObject += ProcessObjectDeGrab;
2350 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
2351 client.OnParcelBuy += ProcessParcelBuy;
2352 client.OnAvatarPickerRequest += ProcessAvatarPickerRequest;
2353 client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable;
2354 client.OnTeleportHomeRequest += TeleportClientHome;
2355 client.OnSetStartLocationRequest += SetHomeRezPoint;
2356 client.OnUndo += m_sceneGraph.HandleUndo;
2357 client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate;
2358 client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel;
2359 client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime;
2360 client.OnObjectSaleInfo += ObjectSaleInfo;
2361 client.OnScriptReset += ProcessScriptReset;
2362 client.OnGetScriptRunning += GetScriptRunning;
2363 client.OnSetScriptRunning += SetScriptRunning;
2364 client.OnRegionHandleRequest += RegionHandleRequest;
2365 client.OnUnackedTerrain += TerrainUnAcked;
2366
2367 client.OnObjectOwner += ObjectOwner;
2368
2369 if (StatsReporter != null)
2370 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsFromClientStats;
2371
2372 // EventManager.TriggerOnNewClient(client);
2373 }
2374
2375 /// <summary>
2376 /// Teleport an avatar to their home region
2377 /// </summary>
2378 /// <param name="agentId"></param>
2379 /// <param name="client"></param>
2380 public virtual void TeleportClientHome(UUID agentId, IClientAPI client)
2381 {
2382 UserProfileData UserProfile = CommsManager.UserService.GetUserProfile(agentId);
2383 if (UserProfile != null)
2384 {
2385 RegionInfo regionInfo = CommsManager.GridService.RequestNeighbourInfo(UserProfile.HomeRegionID);
2386 if (regionInfo == null)
2387 {
2388 regionInfo = CommsManager.GridService.RequestNeighbourInfo(UserProfile.HomeRegion);
2389 if (regionInfo != null) // home region can be away temporarily, too
2390 {
2391 UserProfile.HomeRegionID = regionInfo.RegionID;
2392 CommsManager.UserService.UpdateUserProfile(UserProfile);
2393 }
2394 }
2395 if (regionInfo == null)
2396 {
2397 // can't find the Home region: Tell viewer and abort
2398 client.SendTeleportFailed("Your home-region could not be found.");
2399 return;
2400 }
2401 RequestTeleportLocation(
2402 client, regionInfo.RegionHandle, UserProfile.HomeLocation, UserProfile.HomeLookAt,
2403 (uint)(TPFlags.SetLastToTarget | TPFlags.ViaHome));
2404 }
2405 }
2406
2407 public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID,
2408 UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart,
2409 bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates)
2410 {
2411 Vector3 pos;
2412 const bool frontFacesOnly = true;
2413 //m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString());
2414 SceneObjectPart target = GetSceneObjectPart(localID);
2415 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj);
2416
2417 if (target != null && target2 != null)
2418 {
2419 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
2420 Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
2421 Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
2422
2423 if (target2.ParentGroup != null)
2424 {
2425 pos = target2.AbsolutePosition;
2426 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
2427
2428 // TODO: Raytrace better here
2429
2430 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
2431 Ray NewRay = new Ray(AXOrigin, AXdirection);
2432
2433 // Ray Trace against target here
2434 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
2435
2436 // Un-comment out the following line to Get Raytrace results printed to the console.
2437 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2438 float ScaleOffset = 0.5f;
2439
2440 // If we hit something
2441 if (ei.HitTF)
2442 {
2443 Vector3 scale = target.Scale;
2444 Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
2445 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2446 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2447 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2448 ScaleOffset = Math.Abs(ScaleOffset);
2449 Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2450 Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
2451 Vector3 offset = normal * (ScaleOffset / 2f);
2452 pos = intersectionpoint + offset;
2453
2454 // stick in offset format from the original prim
2455 pos = pos - target.ParentGroup.AbsolutePosition;
2456 if (CopyRotates)
2457 {
2458 Quaternion worldRot = target2.GetWorldRotation();
2459
2460 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
2461 m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
2462 //obj.Rotation = worldRot;
2463 //obj.UpdateGroupRotation(worldRot);
2464 }
2465 else
2466 {
2467 m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID);
2468 }
2469 }
2470
2471 return;
2472 }
2473
2474 return;
2475 }
2476 }
2477
2478 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2479 {
2480 UserProfileData UserProfile = CommsManager.UserService.GetUserProfile(remoteClient.AgentId);
2481 if (UserProfile != null)
2482 {
2483 // I know I'm ignoring the regionHandle provided by the teleport location request.
2484 // reusing the TeleportLocationRequest delegate, so regionHandle isn't valid
2485 UserProfile.HomeRegionID = RegionInfo.RegionID;
2486 // TODO: The next line can be removed, as soon as only homeRegionID based UserServers are around.
2487 // TODO: The HomeRegion property can be removed then, too
2488 UserProfile.HomeRegion = RegionInfo.RegionHandle;
2489 UserProfile.HomeLocation = position;
2490 UserProfile.HomeLookAt = lookAt;
2491 CommsManager.UserService.UpdateUserProfile(UserProfile);
2492
2493 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2494 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
2495 }
2496 else
2497 {
2498 m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed.");
2499 }
2500 }
2501
2502 /// <summary>
2503 /// Create a child agent scene presence and add it to this scene.
2504 /// </summary>
2505 /// <param name="client"></param>
2506 /// <returns></returns>
2507 protected virtual ScenePresence CreateAndAddScenePresence(IClientAPI client)
2508 {
2509 AvatarAppearance appearance = null;
2510 GetAvatarAppearance(client, out appearance);
2511
2512 ScenePresence avatar = m_sceneGraph.CreateAndAddChildScenePresence(client, appearance);
2513 //avatar.KnownRegions = GetChildrenSeeds(avatar.UUID);
2514 return avatar;
2515 }
2516
2517 /// <summary>
2518 /// Get the avatar apperance for the given client.
2519 /// </summary>
2520 /// <param name="client"></param>
2521 /// <param name="appearance"></param>
2522 public void GetAvatarAppearance(IClientAPI client, out AvatarAppearance appearance)
2523 {
2524 appearance = new AvatarAppearance();
2525
2526 try
2527 {
2528 if (m_AvatarFactory != null)
2529 {
2530 if (m_AvatarFactory.TryGetAvatarAppearance(client.AgentId, out appearance))
2531 return;
2532 }
2533 }
2534 catch (Exception e)
2535 {
2536 m_log.ErrorFormat("[APPEARANCE]: Problem fetching appearance for avatar {0}, {1}",
2537 client.Name, e);
2538 }
2539
2540 m_log.Warn("[APPEARANCE]: Appearance not found, returning default");
2541 }
2542
2543 /// <summary>
2544 /// Remove the given client from the scene.
2545 /// </summary>
2546 /// <param name="agentID"></param>
2547 public override void RemoveClient(UUID agentID)
2548 {
2549 bool childagentYN = false;
2550 ScenePresence avatar = GetScenePresence(agentID);
2551 if (avatar != null)
2552 {
2553 childagentYN = avatar.IsChildAgent;
2554 }
2555
2556 try
2557 {
2558 m_log.DebugFormat(
2559 "[SCENE]: Removing {0} agent {1} from region {2}",
2560 (childagentYN ? "child" : "root"), agentID, RegionInfo.RegionName);
2561
2562 m_sceneGraph.removeUserCount(!childagentYN);
2563 CapsModule.RemoveCapsHandler(agentID);
2564
2565 if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
2566 {
2567 CommsManager.UserProfileCacheService.RemoveUser(agentID);
2568 }
2569
2570 if (!avatar.IsChildAgent)
2571 {
2572 m_sceneGridService.LogOffUser(agentID, RegionInfo.RegionID, RegionInfo.RegionHandle, avatar.AbsolutePosition, avatar.Lookat);
2573 //List<ulong> childknownRegions = new List<ulong>();
2574 //List<ulong> ckn = avatar.KnownChildRegionHandles;
2575 //for (int i = 0; i < ckn.Count; i++)
2576 //{
2577 // childknownRegions.Add(ckn[i]);
2578 //}
2579 List<ulong> regions = new List<ulong>(avatar.KnownChildRegionHandles);
2580 regions.Remove(RegionInfo.RegionHandle);
2581 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
2582
2583 }
2584 m_eventManager.TriggerClientClosed(agentID);
2585 }
2586 catch (NullReferenceException)
2587 {
2588 // We don't know which count to remove it from
2589 // Avatar is already disposed :/
2590 }
2591
2592 m_eventManager.TriggerOnRemovePresence(agentID);
2593 Broadcast(delegate(IClientAPI client)
2594 {
2595 try
2596 {
2597 client.SendKillObject(avatar.RegionHandle, avatar.LocalId);
2598 }
2599 catch (NullReferenceException)
2600 {
2601 //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway.
2602 }
2603 });
2604
2605 ForEachScenePresence(
2606 delegate(ScenePresence presence) { presence.CoarseLocationChange(); });
2607
2608 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
2609 if (agentTransactions != null)
2610 {
2611 agentTransactions.RemoveAgentAssetTransactions(agentID);
2612 }
2613
2614 m_sceneGraph.RemoveScenePresence(agentID);
2615
2616 try
2617 {
2618 avatar.Close();
2619 }
2620 catch (NullReferenceException)
2621 {
2622 //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway.
2623 }
2624 catch (Exception e)
2625 {
2626 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
2627 }
2628
2629 // Remove client agent from profile, so new logins will work
2630 if (!childagentYN)
2631 {
2632 m_sceneGridService.ClearUserAgent(agentID);
2633 }
2634
2635 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
2636 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
2637 }
2638
2639 public void HandleRemoveKnownRegionsFromAvatar(UUID avatarID, List<ulong> regionslst)
2640 {
2641 ScenePresence av = GetScenePresence(avatarID);
2642 if (av != null)
2643 {
2644 lock (av)
2645 {
2646
2647 for (int i = 0; i < regionslst.Count; i++)
2648 {
2649 av.KnownChildRegionHandles.Remove(regionslst[i]);
2650 }
2651 }
2652 }
2653 }
2654
2655 public override void CloseAllAgents(uint circuitcode)
2656 {
2657 // Called by ClientView to kill all circuit codes
2658 ClientManager.CloseAllAgents(circuitcode);
2659 }
2660
2661 public void NotifyMyCoarseLocationChange()
2662 {
2663 ForEachScenePresence(delegate(ScenePresence presence) { presence.CoarseLocationChange(); });
2664 }
2665
2666 #endregion
2667
2668 #region Entities
2669
2670 public void SendKillObject(uint localID)
2671 {
2672 SceneObjectPart part = GetSceneObjectPart(localID);
2673 if (part != null) // It is a prim
2674 {
2675 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
2676 {
2677 if (part.ParentGroup.RootPart != part) // Child part
2678 return;
2679 }
2680 }
2681 Broadcast(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
2682 }
2683
2684 #endregion
2685
2686 #region RegionComms
2687
2688 /// <summary>
2689 /// Register the methods that should be invoked when this scene receives various incoming events
2690 /// </summary>
2691 public void RegisterCommsEvents()
2692 {
2693 m_sceneGridService.OnExpectUser += NewUserConnection;
2694 m_sceneGridService.OnAvatarCrossingIntoRegion += AgentCrossing;
2695 m_sceneGridService.OnCloseAgentConnection += IncomingCloseAgent;
2696 m_sceneGridService.OnRegionUp += OtherRegionUp;
2697 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
2698 m_sceneGridService.OnExpectPrim += IncomingInterRegionPrimGroup;
2699 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
2700 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
2701 m_sceneGridService.KiPrimitive += SendKillObject;
2702 m_sceneGridService.OnGetLandData += GetLandData;
2703
2704 if (m_interregionCommsIn != null)
2705 {
2706 m_log.Debug("[SCENE]: Registering with InterregionCommsIn");
2707 m_interregionCommsIn.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
2708 }
2709 else
2710 m_log.Debug("[SCENE]: Unable to register with InterregionCommsIn");
2711
2712 }
2713
2714 /// <summary>
2715 /// Deregister this scene from receiving incoming region events
2716 /// </summary>
2717 public void UnRegisterRegionWithComms()
2718 {
2719 m_sceneGridService.KiPrimitive -= SendKillObject;
2720 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
2721 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
2722 m_sceneGridService.OnExpectPrim -= IncomingInterRegionPrimGroup;
2723 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
2724 m_sceneGridService.OnRegionUp -= OtherRegionUp;
2725 m_sceneGridService.OnExpectUser -= NewUserConnection;
2726 m_sceneGridService.OnAvatarCrossingIntoRegion -= AgentCrossing;
2727 m_sceneGridService.OnCloseAgentConnection -= IncomingCloseAgent;
2728 m_sceneGridService.OnGetLandData -= GetLandData;
2729
2730 if (m_interregionCommsIn != null)
2731 m_interregionCommsIn.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
2732
2733 m_sceneGridService.Close();
2734 }
2735
2736 /// <summary>
2737 /// Do the work necessary to initiate a new user connection for a particular scene.
2738 /// At the moment, this consists of setting up the caps infrastructure
2739 /// </summary>
2740 /// <param name="regionHandle"></param>
2741 /// <param name="agent"></param>
2742 public void NewUserConnection(AgentCircuitData agent)
2743 {
2744 CapsModule.NewUserConnection(agent);
2745
2746 ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID);
2747 if (sp != null)
2748 {
2749 m_log.DebugFormat(
2750 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
2751 agent.AgentID, RegionInfo.RegionName);
2752
2753 sp.AdjustKnownSeeds();
2754
2755 return;
2756 }
2757
2758 // Don't disable this log message - it's too helpful
2759 m_log.DebugFormat(
2760 "[CONNECTION BEGIN]: Region {0} told of incoming client {1} {2} {3} (circuit code {4})",
2761 RegionInfo.RegionName, agent.firstname, agent.lastname, agent.AgentID, agent.circuitcode);
2762
2763 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID))
2764 {
2765 m_log.WarnFormat(
2766 "[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user is on the region banlist",
2767 agent.AgentID, RegionInfo.RegionName);
2768 }
2769
2770 CapsModule.AddCapsHandler(agent.AgentID);
2771
2772 if (!agent.child)
2773 {
2774 // Honor parcel landing type and position.
2775 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
2776 if (land != null)
2777 {
2778 if (land.landData.LandingType == (byte)1 && land.landData.UserLocation != Vector3.Zero)
2779 {
2780 agent.startpos = land.landData.UserLocation;
2781 }
2782 }
2783 }
2784
2785 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
2786
2787 // rewrite session_id
2788 CachedUserInfo userinfo = CommsManager.UserProfileCacheService.GetUserDetails(agent.AgentID);
2789
2790 if (userinfo != null)
2791 {
2792 userinfo.SessionID = agent.SessionID;
2793 }
2794 else
2795 {
2796 m_log.WarnFormat(
2797 "[CONNECTION BEGIN]: We couldn't find a User Info record for {0}. This is usually an indication that the UUID we're looking up is invalid", agent.AgentID);
2798 }
2799 }
2800
2801 public void UpdateCircuitData(AgentCircuitData data)
2802 {
2803 m_authenticateHandler.UpdateAgentData(data);
2804 }
2805
2806 public bool ChangeCircuitCode(uint oldcc, uint newcc)
2807 {
2808 return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc);
2809 }
2810
2811 protected void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message)
2812 {
2813 ScenePresence loggingOffUser = null;
2814 loggingOffUser = GetScenePresence(AvatarID);
2815 if (loggingOffUser != null)
2816 {
2817 UUID localRegionSecret = UUID.Zero;
2818 bool parsedsecret = UUID.TryParse(m_regInfo.regionSecret, out localRegionSecret);
2819
2820 // Region Secret is used here in case a new sessionid overwrites an old one on the user server.
2821 // Will update the user server in a few revisions to use it.
2822
2823 if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret))
2824 {
2825 m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, new List<ulong>(loggingOffUser.KnownRegions.Keys));
2826 loggingOffUser.ControllingClient.Kick(message);
2827 // Give them a second to receive the message!
2828 System.Threading.Thread.Sleep(1000);
2829 loggingOffUser.ControllingClient.Close(true);
2830 }
2831 else
2832 {
2833 m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate");
2834 }
2835 }
2836 else
2837 {
2838 m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString());
2839 }
2840 }
2841
2842 /// <summary>
2843 /// Triggered when an agent crosses into this sim. Also happens on initial login.
2844 /// </summary>
2845 /// <param name="agentID"></param>
2846 /// <param name="position"></param>
2847 /// <param name="isFlying"></param>
2848 public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
2849 {
2850 ScenePresence presence;
2851
2852 lock (m_scenePresences)
2853 {
2854 m_scenePresences.TryGetValue(agentID, out presence);
2855 }
2856
2857 if (presence != null)
2858 {
2859 try
2860 {
2861 presence.MakeRootAgent(position, isFlying);
2862 }
2863 catch (Exception e)
2864 {
2865 m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}", e);
2866 }
2867 }
2868 else
2869 {
2870 m_log.ErrorFormat(
2871 "[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
2872 agentID, RegionInfo.RegionName);
2873 }
2874 }
2875
2876 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData)
2877 {
2878// m_log.DebugFormat(
2879// "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
2880
2881 // We have to wait until the viewer contacts this region after receiving EAC.
2882 // That calls AddNewClient, which finally creates the ScenePresence
2883 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
2884 if (childAgentUpdate != null)
2885 {
2886 childAgentUpdate.ChildAgentDataUpdate(cAgentData);
2887 return true;
2888 }
2889
2890 return false;
2891 }
2892
2893 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData)
2894 {
2895 //Console.WriteLine(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
2896 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
2897 if (childAgentUpdate != null)
2898 {
2899 // I can't imagine *yet* why we would get an update if the agent is a root agent..
2900 // however to avoid a race condition crossing borders..
2901 if (childAgentUpdate.IsChildAgent)
2902 {
2903 uint rRegionX = (uint)(cAgentData.RegionHandle >> 40);
2904 uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8);
2905 uint tRegionX = RegionInfo.RegionLocX;
2906 uint tRegionY = RegionInfo.RegionLocY;
2907 //Send Data to ScenePresence
2908 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
2909 // Not Implemented:
2910 //TODO: Do we need to pass the message on to one of our neighbors?
2911 }
2912
2913 return true;
2914 }
2915
2916 return false;
2917 }
2918
2919 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
2920 {
2921 int ntimes = 10;
2922 ScenePresence childAgentUpdate = null;
2923 while ((childAgentUpdate = GetScenePresence(agentID)) == null && (ntimes-- > 0))
2924 Thread.Sleep(1000);
2925 return childAgentUpdate;
2926
2927 }
2928
2929 public virtual bool IncomingReleaseAgent(UUID id)
2930 {
2931 return m_sceneGridService.ReleaseAgent(id);
2932 }
2933
2934 public void SendReleaseAgent(ulong regionHandle, UUID id, string uri)
2935 {
2936 m_interregionCommsOut.SendReleaseAgent(regionHandle, id, uri);
2937 }
2938
2939 /// <summary>
2940 /// Tell a single agent to disconnect from the region.
2941 /// </summary>
2942 /// <param name="regionHandle"></param>
2943 /// <param name="agentID"></param>
2944 public bool IncomingCloseAgent(UUID agentID)
2945 {
2946 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
2947
2948 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
2949 if (presence != null)
2950 {
2951 // Nothing is removed here, so down count it as such
2952 if (presence.IsChildAgent)
2953 {
2954 m_sceneGraph.removeUserCount(false);
2955 }
2956 else
2957 {
2958 m_sceneGraph.removeUserCount(true);
2959 }
2960
2961 // Don't do this to root agents on logout, it's not nice for the viewer
2962 if (presence.IsChildAgent)
2963 {
2964 // Tell a single agent to disconnect from the region.
2965 IEventQueue eq = RequestModuleInterface<IEventQueue>();
2966 if (eq != null)
2967 {
2968 OSD Item = EventQueueHelper.DisableSimulator(RegionInfo.RegionHandle);
2969 eq.Enqueue(Item, agentID);
2970 }
2971 else
2972 presence.ControllingClient.SendShutdownConnectionNotice();
2973 }
2974
2975 presence.ControllingClient.Close(true);
2976 return true;
2977 }
2978
2979 // Agent not here
2980 return false;
2981 }
2982
2983 /// <summary>
2984 /// Tell neighboring regions about this agent
2985 /// When the regions respond with a true value,
2986 /// tell the agents about the region.
2987 ///
2988 /// We have to tell the regions about the agents first otherwise it'll deny them access
2989 ///
2990 /// </summary>
2991 /// <param name="presence"></param>
2992 public void InformClientOfNeighbours(ScenePresence presence)
2993 {
2994 m_sceneGridService.EnableNeighbourChildAgents(presence, m_neighbours);
2995 }
2996
2997 /// <summary>
2998 /// Tell a neighboring region about this agent
2999 /// </summary>
3000 /// <param name="presence"></param>
3001 /// <param name="region"></param>
3002 public void InformClientOfNeighbor(ScenePresence presence, RegionInfo region)
3003 {
3004 m_sceneGridService.InformNeighborChildAgent(presence, region, m_neighbours);
3005 }
3006
3007 /// <summary>
3008 /// Requests information about this region from gridcomms
3009 /// </summary>
3010 /// <param name="regionHandle"></param>
3011 /// <returns></returns>
3012 public RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
3013 {
3014 return m_sceneGridService.RequestNeighbouringRegionInfo(regionHandle);
3015 }
3016
3017 /// <summary>
3018 /// Requests textures for map from minimum region to maximum region in world cordinates
3019 /// </summary>
3020 /// <param name="remoteClient"></param>
3021 /// <param name="minX"></param>
3022 /// <param name="minY"></param>
3023 /// <param name="maxX"></param>
3024 /// <param name="maxY"></param>
3025 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
3026 {
3027 m_log.InfoFormat("[MAPBLOCK]: {0}-{1}, {2}-{3}", minX, minY, maxX, maxY);
3028 m_sceneGridService.RequestMapBlocks(remoteClient, minX, minY, maxX, maxY);
3029 }
3030
3031 /// <summary>
3032 /// Tries to teleport agent to other region.
3033 /// </summary>
3034 /// <param name="remoteClient"></param>
3035 /// <param name="regionName"></param>
3036 /// <param name="position"></param>
3037 /// <param name="lookAt"></param>
3038 /// <param name="teleportFlags"></param>
3039 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position,
3040 Vector3 lookat, uint teleportFlags)
3041 {
3042 RegionInfo regionInfo = m_sceneGridService.RequestClosestRegion(regionName);
3043 if (regionInfo == null)
3044 {
3045 // can't find the region: Tell viewer and abort
3046 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found.");
3047 return;
3048 }
3049
3050 RequestTeleportLocation(remoteClient, regionInfo.RegionHandle, position, lookat, teleportFlags);
3051 }
3052
3053 /// <summary>
3054 /// Tries to teleport agent to other region.
3055 /// </summary>
3056 /// <param name="remoteClient"></param>
3057 /// <param name="regionHandle"></param>
3058 /// <param name="position"></param>
3059 /// <param name="lookAt"></param>
3060 /// <param name="teleportFlags"></param>
3061 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
3062 Vector3 lookAt, uint teleportFlags)
3063 {
3064 ScenePresence sp = null;
3065 lock (m_scenePresences)
3066 {
3067 if (m_scenePresences.ContainsKey(remoteClient.AgentId))
3068 sp = m_scenePresences[remoteClient.AgentId];
3069 }
3070
3071 if (sp != null)
3072 {
3073 m_sceneGridService.RequestTeleportToLocation(sp, regionHandle,
3074 position, lookAt, teleportFlags);
3075 }
3076 }
3077
3078 /// <summary>
3079 /// Tries to teleport agent to landmark.
3080 /// </summary>
3081 /// <param name="remoteClient"></param>
3082 /// <param name="regionHandle"></param>
3083 /// <param name="position"></param>
3084 public void RequestTeleportLandmark(IClientAPI remoteClient, UUID regionID, Vector3 position)
3085 {
3086 RegionInfo info = CommsManager.GridService.RequestNeighbourInfo(regionID);
3087
3088 if (info == null)
3089 {
3090 // can't find the region: Tell viewer and abort
3091 remoteClient.SendTeleportFailed("The teleport destination could not be found.");
3092 return;
3093 }
3094
3095 ScenePresence sp = null;
3096 lock (m_scenePresences)
3097 {
3098 if (m_scenePresences.ContainsKey(remoteClient.AgentId))
3099 sp = m_scenePresences[remoteClient.AgentId];
3100 }
3101 if (sp != null)
3102 {
3103 m_sceneGridService.RequestTeleportToLocation(sp, info.RegionHandle,
3104 position, Vector3.Zero, (uint)(TPFlags.SetLastToTarget | TPFlags.ViaLandmark));
3105 }
3106 }
3107
3108 /// <summary>
3109 /// Agent is crossing the border into a neighbouring region. Tell the neighbour about it!
3110 /// </summary>
3111 /// <param name="regionHandle"></param>
3112 /// <param name="agentID"></param>
3113 /// <param name="position"></param>
3114 /// <param name="isFlying"></param>
3115 /// <returns></returns>
3116 public bool InformNeighbourOfCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isFlying)
3117 {
3118 return m_sceneGridService.CrossToNeighbouringRegion(regionHandle, agentID, position, isFlying);
3119 }
3120
3121 public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence)
3122 {
3123 m_sceneGridService.SendChildAgentDataUpdate(cadu, presence);
3124 }
3125
3126 #endregion
3127
3128 #region Other Methods
3129
3130 public void SetObjectCapacity(int objects)
3131 {
3132 // Region specific config overrides global
3133 //
3134 if (RegionInfo.ObjectCapacity != 0)
3135 objects = RegionInfo.ObjectCapacity;
3136
3137 if (StatsReporter != null)
3138 {
3139 StatsReporter.SetObjectCapacity(objects);
3140 }
3141 objectCapacity = objects;
3142 }
3143
3144 public List<FriendListItem> GetFriendList(UUID avatarID)
3145 {
3146 return CommsManager.GetUserFriendList(avatarID);
3147 }
3148
3149 public Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos(List<UUID> uuids)
3150 {
3151 return CommsManager.GetFriendRegionInfos(uuids);
3152 }
3153
3154 public List<UUID> InformFriendsInOtherRegion(UUID agentId, ulong destRegionHandle, List<UUID> friends, bool online)
3155 {
3156 return CommsManager.InformFriendsInOtherRegion(agentId, destRegionHandle, friends, online);
3157 }
3158
3159 public bool TriggerTerminateFriend(ulong regionHandle, UUID agentID, UUID exFriendID)
3160 {
3161 return CommsManager.TriggerTerminateFriend(regionHandle, agentID, exFriendID);
3162 }
3163
3164 public virtual void StoreAddFriendship(UUID ownerID, UUID friendID, uint perms)
3165 {
3166 m_sceneGridService.AddNewUserFriend(ownerID, friendID, perms);
3167 }
3168
3169 public virtual void StoreUpdateFriendship(UUID ownerID, UUID friendID, uint perms)
3170 {
3171 m_sceneGridService.UpdateUserFriendPerms(ownerID, friendID, perms);
3172 }
3173
3174 public virtual void StoreRemoveFriendship(UUID ownerID, UUID ExfriendID)
3175 {
3176 m_sceneGridService.RemoveUserFriend(ownerID, ExfriendID);
3177 }
3178
3179 public void AddPacketStats(int inPackets, int outPackets, int unAckedBytes)
3180 {
3181 StatsReporter.AddInPackets(inPackets);
3182 StatsReporter.AddOutPackets(outPackets);
3183 StatsReporter.AddunAckedBytes(unAckedBytes);
3184 }
3185
3186 public void AddAgentTime(int ms)
3187 {
3188 StatsReporter.addFrameMS(ms);
3189 StatsReporter.addAgentMS(ms);
3190 }
3191
3192 public void AddAgentUpdates(int count)
3193 {
3194 StatsReporter.AddAgentUpdates(count);
3195 }
3196
3197 public void AddPendingDownloads(int count)
3198 {
3199 StatsReporter.addPendingDownload(count);
3200 }
3201
3202 #endregion
3203
3204 #region Alert Methods
3205
3206 /// <summary>
3207 /// Handle a request for admin rights
3208 /// </summary>
3209 /// <param name="agentID"></param>
3210 /// <param name="sessionID"></param>
3211 /// <param name="token"></param>
3212 /// <param name="controllingClient"></param>
3213 public void handleRequestGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godLike,
3214 IClientAPI controllingClient)
3215 {
3216 ScenePresence sp = null;
3217
3218 lock (m_scenePresences)
3219 {
3220 // User needs to be logged into this sim
3221 m_scenePresences.TryGetValue(agentID, out sp);
3222 }
3223
3224 if (sp != null)
3225 {
3226 if (godLike == false)
3227 {
3228 sp.GrantGodlikePowers(agentID, sessionID, token, godLike);
3229 return;
3230 }
3231
3232 // First check that this is the sim owner
3233 if (Permissions.IsGod(agentID))
3234 {
3235 // Next we check for spoofing.....
3236 UUID testSessionID = sp.ControllingClient.SessionId;
3237 if (sessionID == testSessionID)
3238 {
3239 if (sessionID == controllingClient.SessionId)
3240 {
3241 //m_log.Info("godlike: " + godLike.ToString());
3242 sp.GrantGodlikePowers(agentID, testSessionID, token, godLike);
3243 }
3244 }
3245 }
3246 else
3247 {
3248 m_dialogModule.SendAlertToUser(agentID, "Request for god powers denied");
3249 }
3250 }
3251 }
3252
3253 /// <summary>
3254 /// Kicks User specified from the simulator. This logs them off of the grid
3255 /// If the client gets the UUID: 44e87126e7944ded05b37c42da3d5cdb it assumes
3256 /// that you're kicking it even if the avatar's UUID isn't the UUID that the
3257 /// agent is assigned
3258 /// </summary>
3259 /// <param name="godID">The person doing the kicking</param>
3260 /// <param name="sessionID">The session of the person doing the kicking</param>
3261 /// <param name="agentID">the person that is being kicked</param>
3262 /// <param name="kickflags">This isn't used apparently</param>
3263 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
3264 public void HandleGodlikeKickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
3265 {
3266 // For some reason the client sends this seemingly hard coded UUID for kicking everyone. Dun-know.
3267 UUID kickUserID = new UUID("44e87126e7944ded05b37c42da3d5cdb");
3268 lock (m_scenePresences)
3269 {
3270 if (m_scenePresences.ContainsKey(agentID) || agentID == kickUserID)
3271 {
3272 if (Permissions.IsGod(godID))
3273 {
3274 if (agentID == kickUserID)
3275 {
3276 ClientManager.ForEachClient(delegate(IClientAPI controller)
3277 {
3278 if (controller.AgentId != godID)
3279 controller.Kick(Utils.BytesToString(reason));
3280 }
3281 );
3282
3283 // This is a bit crude. It seems the client will be null before it actually stops the thread
3284 // The thread will kill itself eventually :/
3285 // Is there another way to make sure *all* clients get this 'inter region' message?
3286 ClientManager.ForEachClient(delegate(IClientAPI controller)
3287 {
3288 ScenePresence p = GetScenePresence(controller.AgentId);
3289 bool childagent = p != null && p.IsChildAgent;
3290 if (controller.AgentId != godID && !childagent)
3291 // Do we really want to kick the initiator of this madness?
3292 {
3293 controller.Close(true);
3294 }
3295 }
3296 );
3297 }
3298 else
3299 {
3300 m_sceneGraph.removeUserCount(!m_scenePresences[agentID].IsChildAgent);
3301
3302 m_scenePresences[agentID].ControllingClient.Kick(Utils.BytesToString(reason));
3303 m_scenePresences[agentID].ControllingClient.Close(true);
3304 }
3305 }
3306 else
3307 {
3308 m_dialogModule.SendAlertToUser(godID, "Kick request denied");
3309 }
3310 }
3311 }
3312 }
3313
3314 public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set)
3315 {
3316 // Check for spoofing.. since this is permissions we're talking about here!
3317 if ((controller.SessionId == sessionID) && (controller.AgentId == agentID))
3318 {
3319 // Tell the object to do permission update
3320 if (localId != 0)
3321 {
3322 SceneObjectGroup chObjectGroup = GetGroupByPrim(localId);
3323 if (chObjectGroup != null)
3324 {
3325 chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set);
3326 }
3327 }
3328 }
3329 }
3330
3331 /// <summary>
3332 /// Handle an alert command from the console.
3333 /// FIXME: Command parsing code really shouldn't be in this core Scene class.
3334 /// </summary>
3335 /// <param name="commandParams"></param>
3336 public void HandleAlertCommand(string[] commandParams)
3337 {
3338 if (commandParams[0] == "general")
3339 {
3340 string message = CombineParams(commandParams, 1);
3341 m_dialogModule.SendGeneralAlert(message);
3342 }
3343 else
3344 {
3345 string message = CombineParams(commandParams, 2);
3346 m_dialogModule.SendAlertToUser(commandParams[0], commandParams[1], message, false);
3347 }
3348 }
3349
3350 private string CombineParams(string[] commandParams, int pos)
3351 {
3352 string result = String.Empty;
3353 for (int i = pos; i < commandParams.Length; i++)
3354 {
3355 result += commandParams[i] + " ";
3356 }
3357 return result;
3358 }
3359
3360 #endregion
3361
3362 /// <summary>
3363 /// Causes all clients to get a full object update on all of the objects in the scene.
3364 /// </summary>
3365 public void ForceClientUpdate()
3366 {
3367 List<EntityBase> EntityList = GetEntities();
3368
3369 foreach (EntityBase ent in EntityList)
3370 {
3371 if (ent is SceneObjectGroup)
3372 {
3373 ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate();
3374 }
3375 }
3376 }
3377
3378 /// <summary>
3379 /// This is currently only used for scale (to scale to MegaPrim size)
3380 /// There is a console command that calls this in OpenSimMain
3381 /// </summary>
3382 /// <param name="cmdparams"></param>
3383 public void HandleEditCommand(string[] cmdparams)
3384 {
3385 Console.WriteLine("Searching for Primitive: '" + cmdparams[0] + "'");
3386
3387 List<EntityBase> EntityList = GetEntities();
3388
3389 foreach (EntityBase ent in EntityList)
3390 {
3391 if (ent is SceneObjectGroup)
3392 {
3393 SceneObjectPart part = ((SceneObjectGroup)ent).GetChildPart(((SceneObjectGroup)ent).UUID);
3394 if (part != null)
3395 {
3396 if (part.Name == cmdparams[0])
3397 {
3398 part.Resize(
3399 new Vector3(Convert.ToSingle(cmdparams[1]), Convert.ToSingle(cmdparams[2]),
3400 Convert.ToSingle(cmdparams[3])));
3401
3402 Console.WriteLine("Edited scale of Primitive: " + part.Name);
3403 }
3404 }
3405 }
3406 }
3407 }
3408
3409 public override void Show(string[] showParams)
3410 {
3411 base.Show(showParams);
3412
3413 switch (showParams[0])
3414 {
3415 case "users":
3416 m_log.Error("Current Region: " + RegionInfo.RegionName);
3417 m_log.ErrorFormat("{0,-16}{1,-16}{2,-25}{3,-25}{4,-16}{5,-16}{6,-16}", "Firstname", "Lastname",
3418 "Agent ID", "Session ID", "Circuit", "IP", "World");
3419
3420 foreach (ScenePresence scenePresence in GetAvatars())
3421 {
3422 m_log.ErrorFormat("{0,-16}{1,-16}{2,-25}{3,-25}{4,-16},{5,-16}{6,-16}",
3423 scenePresence.Firstname,
3424 scenePresence.Lastname,
3425 scenePresence.UUID,
3426 scenePresence.ControllingClient.AgentId,
3427 "Unknown",
3428 "Unknown",
3429 RegionInfo.RegionName);
3430 }
3431
3432 break;
3433 }
3434 }
3435
3436 #region Script Handling Methods
3437
3438 /// <summary>
3439 /// Console command handler to send script command to script engine.
3440 /// </summary>
3441 /// <param name="args"></param>
3442 public void SendCommandToPlugins(string[] args)
3443 {
3444 m_eventManager.TriggerOnPluginConsole(args);
3445 }
3446
3447 public double GetLandHeight(int x, int y)
3448 {
3449 return Heightmap[x, y];
3450 }
3451
3452 public UUID GetLandOwner(float x, float y)
3453 {
3454 ILandObject land = LandChannel.GetLandObject(x, y);
3455 if (land == null)
3456 {
3457 return UUID.Zero;
3458 }
3459 else
3460 {
3461 return land.landData.OwnerID;
3462 }
3463 }
3464
3465 public LandData GetLandData(float x, float y)
3466 {
3467 return LandChannel.GetLandObject(x, y).landData;
3468 }
3469
3470 public LandData GetLandData(uint x, uint y)
3471 {
3472 m_log.DebugFormat("[SCENE] returning land for {0},{1}", x, y);
3473 return LandChannel.GetLandObject((int)x, (int)y).landData;
3474 }
3475
3476 public void SetLandMusicURL(float x, float y, string url)
3477 {
3478 ILandObject land = LandChannel.GetLandObject(x, y);
3479 if (land == null)
3480 {
3481 return;
3482 }
3483 else
3484 {
3485 land.landData.MusicURL = url;
3486 land.sendLandUpdateToAvatarsOverMe();
3487 return;
3488 }
3489 }
3490
3491 public void SetLandMediaURL(float x, float y, string url)
3492 {
3493 ILandObject land = LandChannel.GetLandObject(x, y);
3494
3495 if (land == null)
3496 {
3497 return;
3498 }
3499
3500 else
3501 {
3502 land.landData.MediaURL = url;
3503 land.sendLandUpdateToAvatarsOverMe();
3504 return;
3505 }
3506 }
3507
3508 public RegionInfo RequestClosestRegion(string name)
3509 {
3510 return m_sceneGridService.RequestClosestRegion(name);
3511 }
3512
3513 #endregion
3514
3515 #region Script Engine
3516
3517 private List<ScriptEngineInterface> ScriptEngines = new List<ScriptEngineInterface>();
3518 public bool DumpAssetsToFile;
3519
3520 /// <summary>
3521 ///
3522 /// </summary>
3523 /// <param name="scriptEngine"></param>
3524 public void AddScriptEngine(ScriptEngineInterface scriptEngine)
3525 {
3526 ScriptEngines.Add(scriptEngine);
3527 scriptEngine.InitializeEngine(this);
3528 }
3529
3530 public void TriggerObjectChanged(uint localID, uint change)
3531 {
3532 m_eventManager.TriggerOnScriptChangedEvent(localID, change);
3533 }
3534
3535 public void TriggerAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 currentpos)
3536 {
3537 m_eventManager.TriggerAtTargetEvent(localID, handle, targetpos, currentpos);
3538 }
3539
3540 public void TriggerNotAtTargetEvent(uint localID)
3541 {
3542 m_eventManager.TriggerNotAtTargetEvent(localID);
3543 }
3544
3545 private bool ScriptDanger(SceneObjectPart part,Vector3 pos)
3546 {
3547 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
3548 if (part != null)
3549 {
3550 if (parcel != null)
3551 {
3552 if ((parcel.landData.Flags & (uint)Parcel.ParcelFlags.AllowOtherScripts) != 0)
3553 {
3554 return true;
3555 }
3556 else if ((parcel.landData.Flags & (uint)Parcel.ParcelFlags.AllowGroupScripts) != 0)
3557 {
3558 if (part.OwnerID == parcel.landData.OwnerID || (parcel.landData.IsGroupOwned && part.GroupID == parcel.landData.GroupID) || Permissions.IsGod(part.OwnerID))
3559 {
3560 return true;
3561 }
3562 else
3563 {
3564 return false;
3565 }
3566 }
3567 else
3568 {
3569 if (part.OwnerID == parcel.landData.OwnerID)
3570 {
3571 return true;
3572 }
3573 else
3574 {
3575 return false;
3576 }
3577 }
3578 }
3579 else
3580 {
3581
3582 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize)
3583 {
3584 // The only time parcel != null when an object is inside a region is when
3585 // there is nothing behind the landchannel. IE, no land plugin loaded.
3586 return true;
3587 }
3588 else
3589 {
3590 // The object is outside of this region. Stop piping events to it.
3591 return false;
3592 }
3593 }
3594 }
3595 else
3596 {
3597 return false;
3598 }
3599 }
3600
3601 public bool ScriptDanger(uint localID, Vector3 pos)
3602 {
3603 SceneObjectPart part = GetSceneObjectPart(localID);
3604 if (part != null)
3605 {
3606 return ScriptDanger(part, pos);
3607 }
3608 else
3609 {
3610 return false;
3611 }
3612 }
3613
3614 public bool PipeEventsForScript(uint localID)
3615 {
3616 SceneObjectPart part = GetSceneObjectPart(localID);
3617 if (part != null)
3618 {
3619 // Changed so that child prims of attachments return ScriptDanger for their parent, so that
3620 // their scripts will actually run.
3621 // -- Leaf, Tue Aug 12 14:17:05 EDT 2008
3622 SceneObjectPart parent = part.ParentGroup.RootPart;
3623 if (parent != null && parent.IsAttachment)
3624 return ScriptDanger(parent, parent.GetWorldPosition());
3625 else
3626 return ScriptDanger(part, part.GetWorldPosition());
3627 }
3628 else
3629 {
3630 return false;
3631 }
3632 }
3633
3634 #endregion
3635
3636 #region SceneGraph wrapper methods
3637
3638 /// <summary>
3639 ///
3640 /// </summary>
3641 /// <param name="localID"></param>
3642 /// <returns></returns>
3643 public UUID ConvertLocalIDToFullID(uint localID)
3644 {
3645 return m_sceneGraph.ConvertLocalIDToFullID(localID);
3646 }
3647
3648 public void SwapRootAgentCount(bool rootChildChildRootTF)
3649 {
3650 m_sceneGraph.SwapRootChildAgent(rootChildChildRootTF);
3651 }
3652
3653 public void AddPhysicalPrim(int num)
3654 {
3655 m_sceneGraph.AddPhysicalPrim(num);
3656 }
3657
3658 public void RemovePhysicalPrim(int num)
3659 {
3660 m_sceneGraph.RemovePhysicalPrim(num);
3661 }
3662
3663 //The idea is to have a group of method that return a list of avatars meeting some requirement
3664 // ie it could be all m_scenePresences within a certain range of the calling prim/avatar.
3665
3666 /// <summary>
3667 /// Return a list of all avatars in this region.
3668 /// This list is a new object, so it can be iterated over without locking.
3669 /// </summary>
3670 /// <returns></returns>
3671 public List<ScenePresence> GetAvatars()
3672 {
3673 return m_sceneGraph.GetAvatars();
3674 }
3675
3676 /// <summary>
3677 /// Return a list of all ScenePresences in this region. This returns child agents as well as root agents.
3678 /// This list is a new object, so it can be iterated over without locking.
3679 /// </summary>
3680 /// <returns></returns>
3681 public List<ScenePresence> GetScenePresences()
3682 {
3683 return m_sceneGraph.GetScenePresences();
3684 }
3685
3686 /// <summary>
3687 /// Request a filtered list of ScenePresences in this region.
3688 /// This list is a new object, so it can be iterated over without locking.
3689 /// </summary>
3690 /// <param name="filter"></param>
3691 /// <returns></returns>
3692 public List<ScenePresence> GetScenePresences(FilterAvatarList filter)
3693 {
3694 return m_sceneGraph.GetScenePresences(filter);
3695 }
3696
3697 /// <summary>
3698 /// Request a scene presence by UUID
3699 /// </summary>
3700 /// <param name="avatarID"></param>
3701 /// <returns></returns>
3702 public ScenePresence GetScenePresence(UUID avatarID)
3703 {
3704 return m_sceneGraph.GetScenePresence(avatarID);
3705 }
3706
3707 public override bool PresenceChildStatus(UUID avatarID)
3708 {
3709 ScenePresence cp = GetScenePresence(avatarID);
3710
3711 // FIXME: This is really crap - some logout code is relying on a NullReferenceException to halt its processing
3712 // This needs to be fixed properly by cleaning up the logout code.
3713 //if (cp != null)
3714 // return cp.IsChildAgent;
3715
3716 //return false;
3717
3718 return cp.IsChildAgent;
3719 }
3720
3721 /// <summary>
3722 ///
3723 /// </summary>
3724 /// <param name="action"></param>
3725 public void ForEachScenePresence(Action<ScenePresence> action)
3726 {
3727 // We don't want to try to send messages if there are no avatars.
3728 if (m_scenePresences != null)
3729 {
3730 try
3731 {
3732 List<ScenePresence> presenceList = GetScenePresences();
3733 foreach (ScenePresence presence in presenceList)
3734 {
3735 action(presence);
3736 }
3737 }
3738 catch (Exception e)
3739 {
3740 m_log.Info("[BUG]: " + e.ToString());
3741 }
3742 }
3743 }
3744
3745 /// <summary>
3746 ///
3747 /// </summary>
3748 /// <param name="action"></param>
3749 // public void ForEachObject(Action<SceneObjectGroup> action)
3750 // {
3751 // List<SceneObjectGroup> presenceList;
3752 //
3753 // lock (m_sceneObjects)
3754 // {
3755 // presenceList = new List<SceneObjectGroup>(m_sceneObjects.Values);
3756 // }
3757 //
3758 // foreach (SceneObjectGroup presence in presenceList)
3759 // {
3760 // action(presence);
3761 // }
3762 // }
3763
3764 /// <summary>
3765 /// Get a named prim contained in this scene (will return the first
3766 /// found, if there are more than one prim with the same name)
3767 /// </summary>
3768 /// <param name="name"></param>
3769 /// <returns></returns>
3770 public SceneObjectPart GetSceneObjectPart(string name)
3771 {
3772 return m_sceneGraph.GetSceneObjectPart(name);
3773 }
3774
3775 /// <summary>
3776 /// Get a prim via its local id
3777 /// </summary>
3778 /// <param name="localID"></param>
3779 /// <returns></returns>
3780 public SceneObjectPart GetSceneObjectPart(uint localID)
3781 {
3782 return m_sceneGraph.GetSceneObjectPart(localID);
3783 }
3784
3785 /// <summary>
3786 /// Get a prim via its UUID
3787 /// </summary>
3788 /// <param name="fullID"></param>
3789 /// <returns></returns>
3790 public SceneObjectPart GetSceneObjectPart(UUID fullID)
3791 {
3792 return m_sceneGraph.GetSceneObjectPart(fullID);
3793 }
3794
3795 internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
3796 {
3797 return m_sceneGraph.TryGetAvatar(avatarId, out avatar);
3798 }
3799
3800 internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
3801 {
3802 return m_sceneGraph.TryGetAvatarByName(avatarName, out avatar);
3803 }
3804
3805 public void ForEachClient(Action<IClientAPI> action)
3806 {
3807 m_sceneGraph.ForEachClient(action);
3808 }
3809
3810 /// <summary>
3811 /// Returns a list of the entities in the scene. This is a new list so operations perform on the list itself
3812 /// will not affect the original list of objects in the scene.
3813 /// </summary>
3814 /// <returns></returns>
3815 public List<EntityBase> GetEntities()
3816 {
3817 return m_sceneGraph.GetEntities();
3818 }
3819
3820 #endregion
3821
3822 #region Avatar Appearance Default
3823
3824 public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
3825 {
3826 visualParams = GetDefaultVisualParams();
3827 wearables = AvatarWearable.DefaultWearables;
3828 }
3829
3830 private static byte[] GetDefaultVisualParams()
3831 {
3832 byte[] visualParams;
3833 visualParams = new byte[218];
3834 for (int i = 0; i < 218; i++)
3835 {
3836 visualParams[i] = 100;
3837 }
3838 return visualParams;
3839 }
3840
3841 #endregion
3842
3843 public void ParcelMediaSetTime(float time)
3844 {
3845 //should be doing this by parcel, but as its only for testing
3846 // The use of Thread.Sleep here causes the following compiler error under mono 1.2.4
3847 // OpenSim/Region/Environment/Scenes/Scene.cs(3675,17): error CS0103: The name `Thread' does not exist
3848 // in the context of `<>c__CompilerGenerated17'
3849 // MW said it was okay to comment the body of this method out for now since the code is experimental
3850 // and will be replaced anyway
3851// ForEachClient(delegate(IClientAPI client)
3852// {
3853// client.SendParcelMediaCommand((uint)(2), ParcelMediaCommandEnum.Pause, 0);
3854// Thread.Sleep(10);
3855// client.SendParcelMediaCommand((uint)(64), ParcelMediaCommandEnum.Time, time);
3856// Thread.Sleep(200);
3857// client.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0);
3858// });
3859 }
3860
3861 public void RegionHandleRequest(IClientAPI client, UUID regionID)
3862 {
3863 RegionInfo info;
3864 if (regionID == RegionInfo.RegionID)
3865 info = RegionInfo;
3866 else
3867 info = CommsManager.GridService.RequestNeighbourInfo(regionID);
3868
3869 if (info != null)
3870 client.SendRegionHandle(regionID, info.RegionHandle);
3871 }
3872
3873 public void TerrainUnAcked(IClientAPI client, int patchX, int patchY)
3874 {
3875 //Console.WriteLine("Terrain packet unacked, resending patch: " + patchX + " , " + patchY);
3876 client.SendLayerData(patchX, patchY, Heightmap.GetFloatsSerialised());
3877 }
3878
3879 public void SetRootAgentScene(UUID agentID)
3880 {
3881 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
3882 if (inv == null)
3883 return;
3884
3885 inv.SetRootAgentScene(agentID, this);
3886
3887 EventManager.TriggerSetRootAgentScene(agentID, this);
3888 }
3889
3890 public bool NeedSceneCacheClear(UUID agentID)
3891 {
3892 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
3893 if (inv == null)
3894 return true;
3895
3896 return inv.NeedSceneCacheClear(agentID, this);
3897 }
3898
3899 public void ObjectSaleInfo(IClientAPI client, UUID agentID, UUID sessionID, uint localID, byte saleType, int salePrice)
3900 {
3901 SceneObjectPart part = GetSceneObjectPart(localID);
3902 if (part == null || part.ParentGroup == null)
3903 return;
3904
3905 if (part.ParentGroup.IsDeleted)
3906 return;
3907
3908 part = part.ParentGroup.RootPart;
3909
3910 part.ObjectSaleType = saleType;
3911 part.SalePrice = salePrice;
3912
3913 part.ParentGroup.HasGroupChanged = true;
3914
3915 part.GetProperties(client);
3916 }
3917
3918 public bool PerformObjectBuy(IClientAPI remoteClient, UUID categoryID,
3919 uint localID, byte saleType)
3920 {
3921 SceneObjectPart part = GetSceneObjectPart(localID);
3922
3923 if (part == null)
3924 return false;
3925
3926 if (part.ParentGroup == null)
3927 return false;
3928
3929 SceneObjectGroup group = part.ParentGroup;
3930
3931 switch (saleType)
3932 {
3933 case 1: // Sell as original (in-place sale)
3934 uint effectivePerms=group.GetEffectivePermissions();
3935
3936 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
3937 {
3938 m_dialogModule.SendAlertToUser(remoteClient, "This item doesn't appear to be for sale");
3939 return false;
3940 }
3941
3942 group.SetOwnerId(remoteClient.AgentId);
3943 group.SetRootPartOwner(part, remoteClient.AgentId,
3944 remoteClient.ActiveGroupId);
3945
3946 List<SceneObjectPart> partList =
3947 new List<SceneObjectPart>(group.Children.Values);
3948
3949 if (Permissions.PropagatePermissions())
3950 {
3951 foreach (SceneObjectPart child in partList)
3952 {
3953 child.Inventory.ChangeInventoryOwner(remoteClient.AgentId);
3954 child.ApplyNextOwnerPermissions();
3955 }
3956 }
3957
3958 part.ObjectSaleType = 0;
3959 part.SalePrice = 10;
3960
3961 group.HasGroupChanged = true;
3962 part.GetProperties(remoteClient);
3963 part.ScheduleFullUpdate();
3964
3965 break;
3966
3967 case 2: // Sell a copy
3968 string sceneObjectXml = group.ToXmlString();
3969
3970 CachedUserInfo userInfo =
3971 CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId);
3972
3973 if (userInfo != null)
3974 {
3975 uint perms=group.GetEffectivePermissions();
3976
3977 if ((perms & (uint)PermissionMask.Transfer) == 0)
3978 {
3979 m_dialogModule.SendAlertToUser(remoteClient, "This item doesn't appear to be for sale");
3980 return false;
3981 }
3982
3983 AssetBase asset = CreateAsset(
3984 group.GetPartName(localID),
3985 group.GetPartDescription(localID),
3986 (sbyte)AssetType.Object,
3987 Utils.StringToBytes(sceneObjectXml));
3988 AssetCache.AddAsset(asset);
3989
3990 InventoryItemBase item = new InventoryItemBase();
3991 item.Creator = part.CreatorID;
3992
3993 item.ID = UUID.Random();
3994 item.Owner = remoteClient.AgentId;
3995 item.AssetID = asset.Metadata.FullID;
3996 item.Description = asset.Metadata.Description;
3997 item.Name = asset.Metadata.Name;
3998 item.AssetType = asset.Metadata.Type;
3999 item.InvType = (int)InventoryType.Object;
4000 item.Folder = categoryID;
4001
4002 uint nextPerms=(perms & 7) << 13;
4003 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
4004 perms &= ~(uint)PermissionMask.Copy;
4005 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
4006 perms &= ~(uint)PermissionMask.Transfer;
4007 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
4008 perms &= ~(uint)PermissionMask.Modify;
4009
4010 item.BasePermissions = perms & part.NextOwnerMask;
4011 item.CurrentPermissions = perms & part.NextOwnerMask;
4012 item.NextPermissions = part.NextOwnerMask;
4013 item.EveryOnePermissions = part.EveryoneMask &
4014 part.NextOwnerMask;
4015 item.GroupPermissions = part.GroupMask &
4016 part.NextOwnerMask;
4017 item.CurrentPermissions |= 8; // Slam!
4018 item.CreationDate = Util.UnixTimeSinceEpoch();
4019
4020 userInfo.AddItem(item);
4021 remoteClient.SendInventoryItemCreateUpdate(item);
4022 }
4023 else
4024 {
4025 m_dialogModule.SendAlertToUser(remoteClient, "Cannot buy now. Your inventory is unavailable");
4026 return false;
4027 }
4028 break;
4029
4030 case 3: // Sell contents
4031 List<UUID> invList = part.Inventory.GetInventoryList();
4032
4033 bool okToSell = true;
4034
4035 foreach (UUID invID in invList)
4036 {
4037 TaskInventoryItem item = part.Inventory.GetInventoryItem(invID);
4038 if ((item.CurrentPermissions &
4039 (uint)PermissionMask.Transfer) == 0)
4040 {
4041 okToSell = false;
4042 break;
4043 }
4044 }
4045
4046 if (!okToSell)
4047 {
4048 m_dialogModule.SendAlertToUser(
4049 remoteClient, "This item's inventory doesn't appear to be for sale");
4050 return false;
4051 }
4052
4053 if (invList.Count > 0)
4054 MoveTaskInventoryItems(remoteClient.AgentId, part.Name,
4055 part, invList);
4056 break;
4057 }
4058
4059 return true;
4060 }
4061
4062 public void CleanTempObjects()
4063 {
4064 List<EntityBase> objs = GetEntities();
4065
4066 foreach (EntityBase obj in objs)
4067 {
4068 if (obj is SceneObjectGroup)
4069 {
4070 SceneObjectGroup grp = (SceneObjectGroup)obj;
4071
4072 if (!grp.IsDeleted)
4073 {
4074 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
4075 {
4076 if (grp.RootPart.Expires <= DateTime.Now)
4077 DeleteSceneObject(grp, false);
4078 }
4079 }
4080 }
4081 }
4082 }
4083
4084 public void DeleteFromStorage(UUID uuid)
4085 {
4086 m_storageManager.DataStore.RemoveObject(uuid, m_regInfo.RegionID);
4087 }
4088
4089 public int GetHealth()
4090 {
4091 int health=1; // Start at 1, means we're up
4092
4093 // A login in the last 4 mins? We can't be doing too badly
4094 //
4095 if ((System.Environment.TickCount - m_LastLogin) < 240000)
4096 health++;
4097
4098 return 0;
4099 }
4100
4101 // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
4102 // update non-physical objects like the joint proxy objects that represent the position
4103 // of the joints in the scene.
4104
4105 // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene
4106 // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
4107 // from within the OdePhysicsScene.
4108
4109 protected internal void jointMoved(PhysicsJoint joint)
4110 {
4111 // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked
4112 // FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
4113 SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
4114 if (jointProxyObject == null)
4115 {
4116 jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene);
4117 return;
4118 }
4119
4120 // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine
4121 SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup
4122 if (trackedBody == null) return; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy.
4123 jointProxyObject.Velocity = trackedBody.Velocity;
4124 jointProxyObject.RotationalVelocity = trackedBody.RotationalVelocity;
4125 switch (joint.Type)
4126 {
4127 case PhysicsJointType.Ball:
4128 {
4129 PhysicsVector jointAnchor = PhysicsScene.GetJointAnchor(joint);
4130 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z);
4131 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
4132 }
4133 break;
4134
4135 case PhysicsJointType.Hinge:
4136 {
4137 PhysicsVector jointAnchor = PhysicsScene.GetJointAnchor(joint);
4138
4139 // Normally, we would just ask the physics scene to return the axis for the joint.
4140 // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should
4141 // never occur. Therefore we cannot rely on ODE to always return a correct joint axis.
4142 // Therefore the following call does not always work:
4143 //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint);
4144
4145 // instead we compute the joint orientation by saving the original joint orientation
4146 // relative to one of the jointed bodies, and applying this transformation
4147 // to the current position of the jointed bodies (the tracked body) to compute the
4148 // current joint orientation.
4149
4150 if (joint.TrackedBodyName == null)
4151 {
4152 jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene);
4153 }
4154
4155 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z);
4156 Quaternion q = trackedBody.RotationOffset * joint.LocalRotation;
4157
4158 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
4159 jointProxyObject.ParentGroup.UpdateGroupRotation(q); // schedules the entire group for a terse update
4160 }
4161 break;
4162 }
4163 }
4164
4165 // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
4166 // update non-physical objects like the joint proxy objects that represent the position
4167 // of the joints in the scene.
4168
4169 // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene
4170 // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
4171 // from within the OdePhysicsScene.
4172 protected internal void jointDeactivated(PhysicsJoint joint)
4173 {
4174 //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene);
4175 // FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
4176 SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
4177 if (jointProxyObject == null)
4178 {
4179 jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene);
4180 return;
4181 }
4182
4183 // turn the proxy non-physical, which also stops its client-side interpolation
4184 bool wasUsingPhysics = ((jointProxyObject.ObjectFlags & (uint)PrimFlags.Physics) != 0);
4185 if (wasUsingPhysics)
4186 {
4187 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
4188 }
4189 }
4190
4191 // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
4192 // alert the user of errors by using the debug channel in the same way that scripts alert
4193 // the user of compile errors.
4194
4195 // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene
4196 // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
4197 // from within the OdePhysicsScene.
4198 public void jointErrorMessage(PhysicsJoint joint, string message)
4199 {
4200 // FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
4201 if (joint != null)
4202 {
4203 if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages)
4204 return;
4205
4206 SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
4207 if (jointProxyObject != null)
4208 {
4209 SimChat(Utils.StringToBytes("[NINJA] " + message),
4210 ChatTypeEnum.DebugChannel,
4211 2147483647,
4212 jointProxyObject.AbsolutePosition,
4213 jointProxyObject.Name,
4214 jointProxyObject.UUID,
4215 false);
4216
4217 joint.ErrorMessageCount++;
4218
4219 if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages)
4220 {
4221 SimChat(Utils.StringToBytes("[NINJA] Too many messages for this joint, suppressing further messages."),
4222 ChatTypeEnum.DebugChannel,
4223 2147483647,
4224 jointProxyObject.AbsolutePosition,
4225 jointProxyObject.Name,
4226 jointProxyObject.UUID,
4227 false);
4228 }
4229 }
4230 else
4231 {
4232 // couldn't find the joint proxy object; the error message is silently suppressed
4233 }
4234 }
4235 }
4236 }
4237}
diff --git a/OpenSim/Region/Environment/Scenes/SceneBase.cs b/OpenSim/Region/Environment/Scenes/SceneBase.cs
deleted file mode 100644
index 5b78617..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneBase.cs
+++ /dev/null
@@ -1,419 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using OpenMetaverse;
33using log4net;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Region.Environment.Interfaces;
37
38namespace OpenSim.Region.Environment.Scenes
39{
40 public abstract class SceneBase : IScene
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 #region Events
45
46 public event restart OnRestart;
47
48 #endregion
49
50 #region Fields
51
52 /// <value>
53 /// All the region modules attached to this scene.
54 /// </value>
55 public Dictionary<string, IRegionModule> Modules
56 {
57 get { return m_modules; }
58 }
59 protected Dictionary<string, IRegionModule> m_modules = new Dictionary<string, IRegionModule>();
60
61 /// <value>
62 /// The module interfaces available from this scene.
63 /// </value>
64 protected Dictionary<Type, List<object> > ModuleInterfaces = new Dictionary<Type, List<object> >();
65
66 protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>();
67 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
68
69 /// <value>
70 /// Registered classes that are capable of creating entities.
71 /// </value>
72 protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>();
73
74 //API module interfaces
75
76 /// <summary>
77 /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
78 /// dispensed.
79 /// </summary>
80 protected uint m_lastAllocatedLocalId = 720000;
81
82 private readonly Mutex _primAllocateMutex = new Mutex(false);
83
84 private readonly ClientManager m_clientManager = new ClientManager();
85
86 public ClientManager ClientManager
87 {
88 get { return m_clientManager; }
89 }
90
91 protected ulong m_regionHandle;
92 protected string m_regionName;
93 protected RegionInfo m_regInfo;
94
95 //public TerrainEngine Terrain;
96 public ITerrainChannel Heightmap;
97
98 /// <value>
99 /// Allows retrieval of land information for this scene.
100 /// </value>
101 public ILandChannel LandChannel;
102
103 /// <value>
104 /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules
105 /// to subscribe to scene events.
106 /// </value>
107 public EventManager EventManager
108 {
109 get { return m_eventManager; }
110 }
111 protected EventManager m_eventManager;
112
113 protected ScenePermissions m_permissions;
114 public ScenePermissions Permissions
115 {
116 get { return m_permissions; }
117 }
118
119 protected string m_datastore;
120
121 private AssetCache m_assetCache;
122
123 public AssetCache AssetCache
124 {
125 get { return m_assetCache; }
126 set { m_assetCache = value; }
127 }
128
129 protected RegionStatus m_regStatus;
130
131 public RegionStatus Region_Status
132 {
133 get { return m_regStatus; }
134 set { m_regStatus = value; }
135 }
136
137 #endregion
138
139 #region Update Methods
140
141 /// <summary>
142 /// Normally called once every frame/tick to let the world preform anything required (like running the physics simulation)
143 /// </summary>
144 public abstract void Update();
145
146 #endregion
147
148 #region Terrain Methods
149
150 /// <summary>
151 /// Loads the World heightmap
152 /// </summary>
153 public abstract void LoadWorldMap();
154
155 /// <summary>
156 /// Send the region heightmap to the client
157 /// </summary>
158 /// <param name="RemoteClient">Client to send to</param>
159 public virtual void SendLayerData(IClientAPI RemoteClient)
160 {
161 RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
162 }
163
164 #endregion
165
166 #region Add/Remove Agent/Avatar
167
168 /// <summary>
169 /// Register the new client with the scene. The client starts off as a child agent - the later agent crossing
170 /// will promote it to a root agent during login.
171 /// </summary>
172 /// <param name="client"></param
173 public abstract void AddNewClient(IClientAPI client);
174
175 /// <summary>
176 /// Remove a client from the scene
177 /// </summary>
178 /// <param name="agentID"></param>
179 public abstract void RemoveClient(UUID agentID);
180
181 public abstract void CloseAllAgents(uint circuitcode);
182
183 #endregion
184
185 /// <summary>
186 ///
187 /// </summary>
188 /// <returns></returns>
189 public virtual RegionInfo RegionInfo
190 {
191 get { return m_regInfo; }
192 }
193
194 #region admin stuff
195
196 /// <summary>
197 /// Region Restart - Seconds till restart.
198 /// </summary>
199 /// <param name="seconds"></param>
200 public virtual void Restart(int seconds)
201 {
202 m_log.Error("[REGION]: passing Restart Message up the namespace");
203 restart handlerPhysicsCrash = OnRestart;
204 if (handlerPhysicsCrash != null)
205 handlerPhysicsCrash(RegionInfo);
206 }
207
208 public virtual bool PresenceChildStatus(UUID avatarID)
209 {
210 return false;
211 }
212
213 public abstract bool OtherRegionUp(RegionInfo thisRegion);
214
215 public virtual string GetSimulatorVersion()
216 {
217 return "OpenSimulator Server";
218 }
219
220 #endregion
221
222 #region Shutdown
223
224 /// <summary>
225 /// Tidy before shutdown
226 /// </summary>
227 public virtual void Close()
228 {
229 // Shut down all non shared modules.
230 foreach (IRegionModule module in Modules.Values)
231 {
232 if (!module.IsSharedModule)
233 {
234 module.Close();
235 }
236 }
237 Modules.Clear();
238
239 try
240 {
241 EventManager.TriggerShutdown();
242 }
243 catch (Exception e)
244 {
245 m_log.Error("[SCENE]: SceneBase.cs: Close() - Failed with exception " + e.ToString());
246 }
247 }
248
249 #endregion
250
251 /// <summary>
252 /// Returns a new unallocated local ID
253 /// </summary>
254 /// <returns>A brand new local ID</returns>
255 protected internal uint AllocateLocalId()
256 {
257 uint myID;
258
259 _primAllocateMutex.WaitOne();
260 myID = ++m_lastAllocatedLocalId;
261 _primAllocateMutex.ReleaseMutex();
262
263 return myID;
264 }
265
266 #region Module Methods
267
268 /// <summary>
269 /// Add a module to this scene.
270 /// </summary>
271 /// <param name="name"></param>
272 /// <param name="module"></param>
273 public void AddModule(string name, IRegionModule module)
274 {
275 if (!Modules.ContainsKey(name))
276 {
277 Modules.Add(name, module);
278 }
279 }
280
281 public void RegisterModuleCommander(ICommander commander)
282 {
283 lock (m_moduleCommanders)
284 {
285 m_moduleCommanders.Add(commander.Name, commander);
286 }
287 }
288
289 /// <summary>
290 /// Get a module commander
291 /// </summary>
292 /// <param name="name"></param>
293 /// <returns>The module commander, null if no module commander with that name was found</returns>
294 public ICommander GetCommander(string name)
295 {
296 lock (m_moduleCommanders)
297 {
298 if (m_moduleCommanders.ContainsKey(name))
299 return m_moduleCommanders[name];
300 }
301
302 return null;
303 }
304
305 public Dictionary<string, ICommander> GetCommanders()
306 {
307 return m_moduleCommanders;
308 }
309
310 /// <summary>
311 /// Register an interface to a region module. This allows module methods to be called directly as
312 /// well as via events. If there is already a module registered for this interface, it is not replaced
313 /// (is this the best behaviour?)
314 /// </summary>
315 /// <param name="mod"></param>
316 public void RegisterModuleInterface<M>(M mod)
317 {
318 if (!ModuleInterfaces.ContainsKey(typeof(M)))
319 {
320 List<Object> l = new List<Object>();
321 l.Add(mod);
322 ModuleInterfaces.Add(typeof(M), l);
323
324 if (mod is IEntityCreator)
325 {
326 IEntityCreator entityCreator = (IEntityCreator)mod;
327 foreach (PCode pcode in entityCreator.CreationCapabilities)
328 {
329 m_entityCreators[pcode] = entityCreator;
330 }
331 }
332 }
333 }
334
335 public void StackModuleInterface<M>(M mod)
336 {
337 List<Object> l;
338 if (ModuleInterfaces.ContainsKey(typeof(M)))
339 l = ModuleInterfaces[typeof(M)];
340 else
341 l = new List<Object>();
342
343 if (l.Contains(mod))
344 return;
345
346 l.Add(mod);
347
348 if (mod is IEntityCreator)
349 {
350 IEntityCreator entityCreator = (IEntityCreator)mod;
351 foreach (PCode pcode in entityCreator.CreationCapabilities)
352 {
353 m_entityCreators[pcode] = entityCreator;
354 }
355 }
356
357 ModuleInterfaces[typeof(M)] = l;
358 }
359
360 /// <summary>
361 /// For the given interface, retrieve the region module which implements it.
362 /// </summary>
363 /// <returns>null if there is no registered module implementing that interface</returns>
364 public T RequestModuleInterface<T>()
365 {
366 if (ModuleInterfaces.ContainsKey(typeof(T)))
367 {
368 return (T)ModuleInterfaces[typeof(T)][0];
369 }
370 else
371 {
372 return default(T);
373 }
374 }
375
376 /// <summary>
377 /// For the given interface, retrieve an array of region modules that implement it.
378 /// </summary>
379 /// <returns>an empty array if there are no registered modules implementing that interface</returns>
380 public T[] RequestModuleInterfaces<T>()
381 {
382 if (ModuleInterfaces.ContainsKey(typeof(T)))
383 {
384 List<T> ret = new List<T>();
385
386 foreach (Object o in ModuleInterfaces[typeof(T)])
387 ret.Add((T)o);
388 return ret.ToArray();
389 }
390 else
391 {
392 return new T[] { default(T) };
393 }
394 }
395
396 #endregion
397
398 /// <summary>
399 /// Shows various details about the sim based on the parameters supplied by the console command in openSimMain.
400 /// </summary>
401 /// <param name="showParams">What to show</param>
402 public virtual void Show(string[] showParams)
403 {
404 switch (showParams[0])
405 {
406 case "modules":
407 m_log.Error("The currently loaded modules in " + RegionInfo.RegionName + " are:");
408 foreach (IRegionModule module in Modules.Values)
409 {
410 if (!module.IsSharedModule)
411 {
412 m_log.Error("Region Module: " + module.Name);
413 }
414 }
415 break;
416 }
417 }
418 }
419}
diff --git a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs
deleted file mode 100644
index 9935512..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs
+++ /dev/null
@@ -1,1102 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using System.Threading;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using log4net;
36using OpenSim.Region.Environment.Interfaces;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Capabilities;
40using OpenSim.Region.Interfaces;
41using OSD = OpenMetaverse.StructuredData.OSD;
42
43namespace OpenSim.Region.Environment.Scenes
44{
45 public delegate void KiPrimitiveDelegate(uint localID);
46
47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
48
49 public class SceneCommunicationService //one instance per region
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 protected CommunicationsManager m_commsProvider;
54 protected IInterregionCommsOut m_interregionCommsOut;
55 protected RegionInfo m_regionInfo;
56
57 protected RegionCommsListener regionCommsHost;
58
59 protected List<UUID> m_agentsInTransit;
60
61 public event AgentCrossing OnAvatarCrossingIntoRegion;
62 public event ExpectUserDelegate OnExpectUser;
63 public event ExpectPrimDelegate OnExpectPrim;
64 public event CloseAgentConnection OnCloseAgentConnection;
65 public event PrimCrossing OnPrimCrossingIntoRegion;
66 public event RegionUp OnRegionUp;
67 public event ChildAgentUpdate OnChildAgentUpdate;
68 //public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
69 public event LogOffUser OnLogOffUser;
70 public event GetLandData OnGetLandData;
71
72 private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
73 private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
74 private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim;
75 private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
76 private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
77 private RegionUp handlerRegionUp = null; // OnRegionUp;
78 private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
79 //private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
80 private LogOffUser handlerLogOffUser = null;
81 private GetLandData handlerGetLandData = null; // OnGetLandData
82
83 public KiPrimitiveDelegate KiPrimitive;
84
85 public SceneCommunicationService(CommunicationsManager commsMan)
86 {
87 m_commsProvider = commsMan;
88 m_agentsInTransit = new List<UUID>();
89 }
90
91 /// <summary>
92 /// Register a region with the grid
93 /// </summary>
94 /// <param name="regionInfos"></param>
95 /// <exception cref="System.Exception">Thrown if region registration fails.</exception>
96 public void RegisterRegion(IInterregionCommsOut comms_out, RegionInfo regionInfos)
97 {
98 m_interregionCommsOut = comms_out;
99
100 m_regionInfo = regionInfos;
101 m_commsProvider.GridService.gdebugRegionName = regionInfos.RegionName;
102 m_commsProvider.InterRegion.rdebugRegionName = regionInfos.RegionName;
103 regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo);
104
105 if (regionCommsHost != null)
106 {
107 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString());
108
109 regionCommsHost.debugRegionName = regionInfos.RegionName;
110 regionCommsHost.OnExpectPrim += IncomingPrimCrossing;
111 regionCommsHost.OnExpectUser += NewUserConnection;
112 regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing;
113 regionCommsHost.OnCloseAgentConnection += CloseConnection;
114 regionCommsHost.OnRegionUp += newRegionUp;
115 regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
116 regionCommsHost.OnLogOffUser += GridLogOffUser;
117 regionCommsHost.OnGetLandData += FetchLandData;
118 }
119 else
120 {
121 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null");
122 }
123 }
124
125 public RegionInfo RequestClosestRegion(string name)
126 {
127 return m_commsProvider.GridService.RequestClosestRegion(name);
128 }
129
130 public void Close()
131 {
132 if (regionCommsHost != null)
133 {
134 regionCommsHost.OnLogOffUser -= GridLogOffUser;
135 regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate;
136 regionCommsHost.OnRegionUp -= newRegionUp;
137 regionCommsHost.OnExpectUser -= NewUserConnection;
138 regionCommsHost.OnExpectPrim -= IncomingPrimCrossing;
139 regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing;
140 regionCommsHost.OnCloseAgentConnection -= CloseConnection;
141 regionCommsHost.OnGetLandData -= FetchLandData;
142
143 try
144 {
145 m_commsProvider.GridService.DeregisterRegion(m_regionInfo);
146 }
147 catch (Exception e)
148 {
149 m_log.ErrorFormat(
150 "[GRID]: Deregistration of region {0} from the grid failed - {1}. Continuing",
151 m_regionInfo.RegionName, e);
152 }
153
154 regionCommsHost = null;
155 }
156 }
157
158 #region CommsManager Event handlers
159
160 /// <summary>
161 ///
162 /// </summary>
163 /// <param name="regionHandle"></param>
164 /// <param name="agent"></param>
165 ///
166 protected void NewUserConnection(AgentCircuitData agent)
167 {
168 handlerExpectUser = OnExpectUser;
169 if (handlerExpectUser != null)
170 {
171 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname);
172 handlerExpectUser(agent);
173 }
174 }
175
176 protected void GridLogOffUser(UUID AgentID, UUID RegionSecret, string message)
177 {
178 handlerLogOffUser = OnLogOffUser;
179 if (handlerLogOffUser != null)
180 {
181 handlerLogOffUser(AgentID, RegionSecret, message);
182 }
183 }
184
185 protected bool newRegionUp(RegionInfo region)
186 {
187 handlerRegionUp = OnRegionUp;
188 if (handlerRegionUp != null)
189 {
190 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName);
191 handlerRegionUp(region);
192 }
193 return true;
194 }
195
196 protected bool ChildAgentUpdate(ChildAgentDataUpdate cAgentData)
197 {
198 handlerChildAgentUpdate = OnChildAgentUpdate;
199 if (handlerChildAgentUpdate != null)
200 handlerChildAgentUpdate(cAgentData);
201
202
203 return true;
204 }
205
206 protected void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
207 {
208 handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
209 if (handlerAvatarCrossingIntoRegion != null)
210 {
211 handlerAvatarCrossingIntoRegion(agentID, position, isFlying);
212 }
213 }
214
215 protected bool IncomingPrimCrossing(UUID primID, String objXMLData, int XMLMethod)
216 {
217 handlerExpectPrim = OnExpectPrim;
218 if (handlerExpectPrim != null)
219 {
220 return handlerExpectPrim(primID, objXMLData, XMLMethod);
221 }
222 else
223 {
224 return false;
225 }
226
227 }
228
229 protected void PrimCrossing(UUID primID, Vector3 position, bool isPhysical)
230 {
231 handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion;
232 if (handlerPrimCrossingIntoRegion != null)
233 {
234 handlerPrimCrossingIntoRegion(primID, position, isPhysical);
235 }
236 }
237
238 protected bool CloseConnection(UUID agentID)
239 {
240 m_log.Debug("[INTERREGION]: Incoming Agent Close Request for agent: " + agentID);
241
242 handlerCloseAgentConnection = OnCloseAgentConnection;
243 if (handlerCloseAgentConnection != null)
244 {
245 return handlerCloseAgentConnection(agentID);
246 }
247
248 return false;
249 }
250
251 protected LandData FetchLandData(uint x, uint y)
252 {
253 handlerGetLandData = OnGetLandData;
254 if (handlerGetLandData != null)
255 {
256 return handlerGetLandData(x, y);
257 }
258 return null;
259 }
260
261 #endregion
262
263 #region Inform Client of Neighbours
264
265 private delegate void InformClientOfNeighbourDelegate(
266 ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg, IPEndPoint endPoint, bool newAgent);
267
268 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
269 {
270 InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate) iar.AsyncState;
271 icon.EndInvoke(iar);
272 }
273
274 /// <summary>
275 /// Async component for informing client of which neighbours exist
276 /// </summary>
277 /// <remarks>
278 /// This needs to run asynchronesously, as a network timeout may block the thread for a long while
279 /// </remarks>
280 /// <param name="remoteClient"></param>
281 /// <param name="a"></param>
282 /// <param name="regionHandle"></param>
283 /// <param name="endPoint"></param>
284 private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg,
285 IPEndPoint endPoint, bool newAgent)
286 {
287 // Let's wait just a little to give time to originating regions to catch up with closing child agents
288 // after a cross here
289 Thread.Sleep(500);
290
291 uint x, y;
292 Utils.LongToUInts(reg.RegionHandle, out x, out y);
293 x = x / Constants.RegionSize;
294 y = y / Constants.RegionSize;
295 m_log.Info("[INTERGRID]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")");
296
297 string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
298 + "/CAPS/" + a.CapsPath + "0000/";
299
300 //bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a);
301 bool regionAccepted = m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a);
302
303 if (regionAccepted && newAgent)
304 {
305 IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
306 if (eq != null)
307 {
308 OSD Item = EventQueueHelper.EnableSimulator(reg.RegionHandle, endPoint);
309 eq.Enqueue(Item, avatar.UUID);
310
311 Item = EventQueueHelper.EstablishAgentCommunication(avatar.UUID, endPoint.ToString(), capsPath);
312 eq.Enqueue(Item, avatar.UUID);
313
314 m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}", capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName);
315 }
316 else
317 {
318 avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
319 // TODO: make Event Queue disablable!
320 }
321
322 m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString());
323 }
324 }
325
326 public void RequestNeighbors(RegionInfo region)
327 {
328 // List<SimpleRegionInfo> neighbours =
329 m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
330 //IPEndPoint blah = new IPEndPoint();
331
332 //blah.Address = region.RemotingAddress;
333 //blah.Port = region.RemotingPort;
334 }
335
336 /// <summary>
337 /// This informs all neighboring regions about agent "avatar".
338 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
339 /// </summary>
340 public void EnableNeighbourChildAgents(ScenePresence avatar, List<RegionInfo> lstneighbours)
341 {
342 List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
343
344 //m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
345 for (int i = 0; i < lstneighbours.Count; i++)
346 {
347 // We don't want to keep sending to regions that consistently fail on comms.
348 if (!(lstneighbours[i].commFailTF))
349 {
350 neighbours.Add(new SimpleRegionInfo(lstneighbours[i]));
351 }
352 }
353 // we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be
354 // So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/
355 neighbours =
356 m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
357
358 /// We need to find the difference between the new regions where there are no child agents
359 /// and the regions where there are already child agents. We only send notification to the former.
360 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
361 neighbourHandles.Add(avatar.Scene.RegionInfo.RegionHandle); // add this region too
362 List<ulong> previousRegionNeighbourHandles
363 = new List<ulong>(avatar.Scene.CapsModule.GetChildrenSeeds(avatar.UUID).Keys);
364 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
365 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
366
367 //Dump("Current Neighbors", neighbourHandles);
368 //Dump("Previous Neighbours", previousRegionNeighbourHandles);
369 //Dump("New Neighbours", newRegions);
370 //Dump("Old Neighbours", oldRegions);
371
372 /// Update the scene presence's known regions here on this region
373 avatar.DropOldNeighbours(oldRegions);
374
375 /// Collect as many seeds as possible
376 Dictionary<ulong, string> seeds
377 = new Dictionary<ulong, string>(avatar.Scene.CapsModule.GetChildrenSeeds(avatar.UUID));
378
379 //Console.WriteLine(" !!! No. of seeds: " + seeds.Count);
380 if (!seeds.ContainsKey(avatar.Scene.RegionInfo.RegionHandle))
381 seeds.Add(avatar.Scene.RegionInfo.RegionHandle, avatar.ControllingClient.RequestClientInfo().CapsPath);
382
383 /// Create the necessary child agents
384 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
385 foreach (SimpleRegionInfo neighbour in neighbours)
386 {
387 if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
388 {
389
390 AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
391 agent.BaseFolder = UUID.Zero;
392 agent.InventoryFolder = UUID.Zero;
393 agent.startpos = new Vector3(128, 128, 70);
394 agent.child = true;
395
396 if (newRegions.Contains(neighbour.RegionHandle))
397 {
398 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
399 avatar.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
400 seeds.Add(neighbour.RegionHandle, agent.CapsPath);
401 }
402 else
403 agent.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, neighbour.RegionHandle);
404
405 cagents.Add(agent);
406 }
407 }
408
409 /// Update all child agent with everyone's seeds
410 foreach (AgentCircuitData a in cagents)
411 {
412 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
413 }
414 // These two are the same thing!
415 avatar.Scene.CapsModule.SetChildrenSeed(avatar.UUID, seeds);
416 avatar.KnownRegions = seeds;
417 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
418 //avatar.DumpKnownRegions();
419
420 bool newAgent = false;
421 int count = 0;
422 foreach (SimpleRegionInfo neighbour in neighbours)
423 {
424 // Don't do it if there's already an agent in that region
425 if (newRegions.Contains(neighbour.RegionHandle))
426 newAgent = true;
427 else
428 newAgent = false;
429
430 if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
431 {
432 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
433 try
434 {
435 d.BeginInvoke(avatar, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
436 InformClientOfNeighbourCompleted,
437 d);
438 }
439 catch (Exception e)
440 {
441 m_log.ErrorFormat(
442 "[REGIONINFO]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
443 neighbour.ExternalHostName,
444 neighbour.RegionHandle,
445 neighbour.RegionLocX,
446 neighbour.RegionLocY,
447 e);
448
449 // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
450 // since I don't know what will happen if we just let the client continue
451
452 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
453 // throw e;
454
455 }
456 }
457 count++;
458 }
459 }
460
461 /// <summary>
462 /// This informs a single neighboring region about agent "avatar".
463 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
464 /// </summary>
465 public void InformNeighborChildAgent(ScenePresence avatar, SimpleRegionInfo region, List<RegionInfo> neighbours)
466 {
467 AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
468 agent.BaseFolder = UUID.Zero;
469 agent.InventoryFolder = UUID.Zero;
470 agent.startpos = new Vector3(128, 128, 70);
471 agent.child = true;
472
473 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
474 d.BeginInvoke(avatar, agent, region, region.ExternalEndPoint, true,
475 InformClientOfNeighbourCompleted,
476 d);
477 }
478
479 #endregion
480
481 public delegate void InformNeighbourThatRegionUpDelegate(RegionInfo region, ulong regionhandle);
482
483 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
484 {
485 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
486 icon.EndInvoke(iar);
487 }
488
489 /// <summary>
490 /// Asynchronous call to information neighbouring regions that this region is up
491 /// </summary>
492 /// <param name="region"></param>
493 /// <param name="regionhandle"></param>
494 private void InformNeighboursThatRegionIsUpAsync(RegionInfo region, ulong regionhandle)
495 {
496 m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here");
497 //RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port);
498
499 bool regionAccepted =
500 m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle);
501
502 if (regionAccepted)
503 {
504 m_log.Info("[INTERGRID]: Completed informing neighbors that I'm here");
505 handlerRegionUp = OnRegionUp;
506
507 // yes, we're notifying ourselves.
508 if (handlerRegionUp != null)
509 handlerRegionUp(region);
510 }
511 else
512 {
513 m_log.Warn("[INTERGRID]: Failed to inform neighbors that I'm here.");
514 }
515 }
516
517 /// <summary>
518 /// Called by scene when region is initialized (not always when it's listening for agents)
519 /// This is an inter-region message that informs the surrounding neighbors that the sim is up.
520 /// </summary>
521 public void InformNeighborsThatRegionisUp(RegionInfo region)
522 {
523 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
524
525
526 List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
527 // This stays uncached because we don't already know about our neighbors at this point.
528 neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
529 if (neighbours != null)
530 {
531 for (int i = 0; i < neighbours.Count; i++)
532 {
533 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
534
535 d.BeginInvoke(region, neighbours[i].RegionHandle,
536 InformNeighborsThatRegionisUpCompleted,
537 d);
538 }
539 }
540
541 //bool val = m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region));
542 }
543
544 public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, ulong regionHandle);
545
546 /// <summary>
547 /// This informs all neighboring regions about the settings of it's child agent.
548 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
549 ///
550 /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
551 ///
552 /// </summary>
553 private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, ulong regionHandle)
554 {
555 //m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
556 try
557 {
558 //m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
559 m_interregionCommsOut.SendChildAgentUpdate(regionHandle, cAgentData);
560 }
561 catch
562 {
563 // Ignore; we did our best
564 }
565
566 //if (regionAccepted)
567 //{
568 // //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
569 //}
570 //else
571 //{
572 // //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
573 //}
574
575 }
576
577 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
578 {
579 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
580 icon.EndInvoke(iar);
581 }
582
583 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
584 {
585 // This assumes that we know what our neighbors are.
586 try
587 {
588 foreach (ulong regionHandle in presence.KnownChildRegionHandles)
589 {
590 if (regionHandle != m_regionInfo.RegionHandle)
591 {
592 SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
593 d.BeginInvoke(cAgentData, regionHandle,
594 SendChildAgentDataUpdateCompleted,
595 d);
596 }
597 }
598 }
599 catch (InvalidOperationException)
600 {
601 // We're ignoring a collection was modified error because this data gets old and outdated fast.
602 }
603
604 }
605
606 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
607
608 /// <summary>
609 /// This Closes child agents on neighboring regions
610 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
611 /// </summary>
612 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
613 {
614
615 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
616 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
617
618 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
619 m_interregionCommsOut.SendCloseAgent(regionHandle, agentID);
620 }
621
622 private void SendCloseChildAgentCompleted(IAsyncResult iar)
623 {
624 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
625 icon.EndInvoke(iar);
626 }
627
628 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
629 {
630 foreach (ulong handle in regionslst)
631 {
632 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
633 d.BeginInvoke(agentID, handle,
634 SendCloseChildAgentCompleted,
635 d);
636 }
637 }
638
639 /// <summary>
640 /// Helper function to request neighbors from grid-comms
641 /// </summary>
642 /// <param name="regionHandle"></param>
643 /// <returns></returns>
644 public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
645 {
646 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString());
647 return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle);
648 }
649
650 /// <summary>
651 /// Helper function to request neighbors from grid-comms
652 /// </summary>
653 /// <param name="regionID"></param>
654 /// <returns></returns>
655 public virtual RegionInfo RequestNeighbouringRegionInfo(UUID regionID)
656 {
657 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionID);
658 return m_commsProvider.GridService.RequestNeighbourInfo(regionID);
659 }
660
661 /// <summary>
662 /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
663 /// </summary>
664 /// <param name="minX"></param>
665 /// <param name="minY"></param>
666 /// <param name="maxX"></param>
667 /// <param name="maxY"></param>
668 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
669 {
670 List<MapBlockData> mapBlocks;
671 mapBlocks = m_commsProvider.GridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, minX + 4, minY + 4);
672 remoteClient.SendMapBlock(mapBlocks, 0);
673 }
674
675 /// <summary>
676 /// Try to teleport an agent to a new region.
677 /// </summary>
678 /// <param name="remoteClient"></param>
679 /// <param name="RegionHandle"></param>
680 /// <param name="position"></param>
681 /// <param name="lookAt"></param>
682 /// <param name="flags"></param>
683 public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
684 Vector3 lookAt, uint teleportFlags)
685 {
686 if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
687 return;
688
689 bool destRegionUp = true;
690
691 IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
692
693 if (regionHandle == m_regionInfo.RegionHandle)
694 {
695 m_log.DebugFormat(
696 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}",
697 position, m_regionInfo.RegionName);
698
699 // Teleport within the same region
700 if (position.X < 0 || position.X > Constants.RegionSize || position.Y < 0 || position.Y > Constants.RegionSize || position.Z < 0)
701 {
702 Vector3 emergencyPos = new Vector3(128, 128, 128);
703
704 m_log.WarnFormat(
705 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
706 position, avatar.Name, avatar.UUID, emergencyPos);
707 position = emergencyPos;
708 }
709
710 // TODO: Get proper AVG Height
711 float localAVHeight = 1.56f;
712 float posZLimit = (float)avatar.Scene.GetLandHeight((int)position.X, (int)position.Y);
713 float newPosZ = posZLimit + localAVHeight;
714 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
715 {
716 position.Z = newPosZ;
717 }
718
719 // Only send this if the event queue is null
720 if (eq == null)
721 avatar.ControllingClient.SendTeleportLocationStart();
722
723 avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
724 avatar.Teleport(position);
725 }
726 else
727 {
728 RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle);
729 if (reg != null)
730 {
731 m_log.DebugFormat(
732 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation to {0} in {1}",
733 position, reg.RegionName);
734
735 if (eq == null)
736 avatar.ControllingClient.SendTeleportLocationStart();
737
738 // Let's do DNS resolution only once in this process, please!
739 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
740 // it's actually doing a lot of work.
741 IPEndPoint endPoint = reg.ExternalEndPoint;
742 if (endPoint.Address == null)
743 {
744 // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
745 destRegionUp = false;
746 }
747
748 if (destRegionUp)
749 {
750 uint newRegionX = (uint)(reg.RegionHandle >> 40);
751 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
752 uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
753 uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);
754
755 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
756 // both regions
757 if (avatar.ParentID != (uint)0)
758 avatar.StandUp();
759
760 if (!avatar.ValidateAttachments())
761 {
762 avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
763 return;
764 }
765
766 // the avatar.Close below will clear the child region list. We need this below for (possibly)
767 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
768 //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
769 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
770 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
771 // once we reach here...
772 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
773
774 string capsPath = String.Empty;
775 AgentCircuitData agentCircuit = avatar.ControllingClient.RequestClientInfo();
776 agentCircuit.BaseFolder = UUID.Zero;
777 agentCircuit.InventoryFolder = UUID.Zero;
778 agentCircuit.startpos = position;
779 agentCircuit.child = true;
780
781 if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
782 {
783 // brand new agent, let's create a new caps seed
784 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
785 }
786
787 // Let's create an agent there if one doesn't exist yet.
788 //if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
789 if (!m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, agentCircuit))
790 {
791 avatar.ControllingClient.SendTeleportFailed("Destination is not accepting teleports.");
792 return;
793 }
794
795 // OK, it got this agent. Let's close some child agents
796 avatar.CloseChildAgents(newRegionX, newRegionY);
797
798 if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
799 {
800 capsPath
801 = "http://"
802 + reg.ExternalHostName
803 + ":"
804 + reg.HttpPort
805 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
806
807 if (eq != null)
808 {
809 OSD Item = EventQueueHelper.EnableSimulator(reg.RegionHandle, endPoint);
810 eq.Enqueue(Item, avatar.UUID);
811
812 // ES makes the client send a UseCircuitCode message to the destination,
813 // which triggers a bunch of things there.
814 // So let's wait
815 Thread.Sleep(2000);
816
817 Item = EventQueueHelper.EstablishAgentCommunication(avatar.UUID, endPoint.ToString(), capsPath);
818 eq.Enqueue(Item, avatar.UUID);
819 }
820 else
821 {
822 avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
823 }
824 }
825 else
826 {
827 agentCircuit.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, reg.RegionHandle);
828 capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
829 + "/CAPS/" + agentCircuit.CapsPath + "0000/";
830 }
831
832 // Expect avatar crossing is a heavy-duty function at the destination.
833 // That is where MakeRoot is called, which fetches appearance and inventory.
834 // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
835 //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
836 // position, false);
837
838 //{
839 // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
840 // // We should close that agent we just created over at destination...
841 // List<ulong> lst = new List<ulong>();
842 // lst.Add(reg.RegionHandle);
843 // SendCloseChildAgentAsync(avatar.UUID, lst);
844 // return;
845 //}
846
847 SetInTransit(avatar.UUID);
848 // Let's send a full update of the agent. This is a synchronous call.
849 AgentData agent = new AgentData();
850 avatar.CopyTo(agent);
851 agent.Position = position;
852 agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort +
853 "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/";
854
855 m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent);
856
857 m_log.DebugFormat(
858 "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);
859
860
861 if (eq != null)
862 {
863 OSD Item = EventQueueHelper.TeleportFinishEvent(reg.RegionHandle, 13, endPoint,
864 4, teleportFlags, capsPath, avatar.UUID);
865 eq.Enqueue(Item, avatar.UUID);
866 }
867 else
868 {
869 avatar.ControllingClient.SendRegionTeleport(reg.RegionHandle, 13, endPoint, 4,
870 teleportFlags, capsPath);
871 }
872
873 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
874 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
875 // that the client contacted the destination before we send the attachments and close things here.
876 if (!WaitForCallback(avatar.UUID))
877 {
878 // Client never contacted destination. Let's restore everything back
879 avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
880
881 ResetFromTransit(avatar.UUID);
882
883 // Yikes! We should just have a ref to scene here.
884 avatar.Scene.InformClientOfNeighbours(avatar);
885
886 // Finally, kill the agent we just created at the destination.
887 m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID);
888
889 return;
890 }
891
892 // Can't go back from here
893 if (KiPrimitive != null)
894 {
895 KiPrimitive(avatar.LocalId);
896 }
897
898 avatar.MakeChildAgent();
899
900 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
901 avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);
902
903 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
904
905 if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
906 {
907 Thread.Sleep(5000);
908 avatar.Close();
909 CloseConnection(avatar.UUID);
910 }
911
912 // if (teleport success) // seems to be always success here
913 // the user may change their profile information in other region,
914 // so the userinfo in UserProfileCache is not reliable any more, delete it
915 if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
916 {
917 m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
918 m_log.DebugFormat(
919 "[SCENE COMMUNICATION SERVICE]: User {0} is going to another region, profile cache removed",
920 avatar.UUID);
921 }
922 }
923 else
924 {
925 avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
926 }
927 }
928 else
929 {
930 // TP to a place that doesn't exist (anymore)
931 // Inform the viewer about that
932 avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
933
934 // and set the map-tile to '(Offline)'
935 uint regX, regY;
936 Utils.LongToUInts(regionHandle, out regX, out regY);
937
938 MapBlockData block = new MapBlockData();
939 block.X = (ushort)(regX / Constants.RegionSize);
940 block.Y = (ushort)(regY / Constants.RegionSize);
941 block.Access = 254; // == not there
942
943 List<MapBlockData> blocks = new List<MapBlockData>();
944 blocks.Add(block);
945 avatar.ControllingClient.SendMapBlock(blocks, 0);
946 }
947 }
948 }
949
950 protected bool WaitForCallback(UUID id)
951 {
952 int count = 20;
953 while (m_agentsInTransit.Contains(id) && count-- > 0)
954 {
955 //Console.WriteLine(" >>> Waiting... " + count);
956 Thread.Sleep(1000);
957 }
958
959 if (count > 0)
960 return true;
961 else
962 return false;
963 }
964
965 public bool ReleaseAgent(UUID id)
966 {
967 //Console.WriteLine(" >>> ReleaseAgent called <<< ");
968 return ResetFromTransit(id);
969 }
970
971 protected void SetInTransit(UUID id)
972 {
973 lock (m_agentsInTransit)
974 {
975 if (!m_agentsInTransit.Contains(id))
976 m_agentsInTransit.Add(id);
977 }
978 }
979
980 protected bool ResetFromTransit(UUID id)
981 {
982 lock (m_agentsInTransit)
983 {
984 if (m_agentsInTransit.Contains(id))
985 {
986 m_agentsInTransit.Remove(id);
987 return true;
988 }
989 }
990 return false;
991 }
992
993 private List<ulong> NeighbourHandles(List<SimpleRegionInfo> neighbours)
994 {
995 List<ulong> handles = new List<ulong>();
996 foreach (SimpleRegionInfo reg in neighbours)
997 {
998 handles.Add(reg.RegionHandle);
999 }
1000 return handles;
1001 }
1002
1003 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1004 {
1005 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
1006 }
1007
1008// private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1009// {
1010// return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
1011// }
1012
1013 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1014 {
1015 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
1016 }
1017 /// <summary>
1018 /// Inform a neighbouring region that an avatar is about to cross into it.
1019 /// </summary>
1020 /// <param name="regionhandle"></param>
1021 /// <param name="agentID"></param>
1022 /// <param name="position"></param>
1023 public bool CrossToNeighbouringRegion(ulong regionhandle, UUID agentID, Vector3 position, bool isFlying)
1024 {
1025 return m_commsProvider.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position, isFlying);
1026 }
1027
1028 public bool PrimCrossToNeighboringRegion(ulong regionhandle, UUID primID, string objData, int XMLMethod)
1029 {
1030 return m_commsProvider.InterRegion.InformRegionOfPrimCrossing(regionhandle, primID, objData, XMLMethod);
1031 }
1032
1033 public Dictionary<string, string> GetGridSettings()
1034 {
1035 return m_commsProvider.GridService.GetGridSettings();
1036 }
1037
1038 public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
1039 {
1040 m_commsProvider.LogOffUser(userid, regionid, regionhandle, position, lookat);
1041 }
1042
1043 // deprecated as of 2008-08-27
1044 public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
1045 {
1046 m_commsProvider.LogOffUser(userid, regionid, regionhandle, posx, posy, posz);
1047 }
1048
1049 public void ClearUserAgent(UUID avatarID)
1050 {
1051 m_commsProvider.UserService.ClearUserAgent(avatarID);
1052 }
1053
1054 public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
1055 {
1056 m_commsProvider.AddNewUserFriend(friendlistowner, friend, perms);
1057 }
1058
1059 public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
1060 {
1061 m_commsProvider.UpdateUserFriendPerms(friendlistowner, friend, perms);
1062 }
1063
1064 public void RemoveUserFriend(UUID friendlistowner, UUID friend)
1065 {
1066 m_commsProvider.RemoveUserFriend(friendlistowner, friend);
1067 }
1068
1069 public List<FriendListItem> GetUserFriendList(UUID friendlistowner)
1070 {
1071 return m_commsProvider.GetUserFriendList(friendlistowner);
1072 }
1073
1074 public List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
1075 {
1076 return m_commsProvider.GridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
1077 }
1078
1079 public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
1080 {
1081 return m_commsProvider.GenerateAgentPickerRequestResponse(queryID, query);
1082 }
1083
1084 public List<RegionInfo> RequestNamedRegions(string name, int maxNumber)
1085 {
1086 return m_commsProvider.GridService.RequestNamedRegions(name, maxNumber);
1087 }
1088
1089// private void Dump(string msg, List<ulong> handles)
1090// {
1091// Console.WriteLine("-------------- HANDLE DUMP ({0}) ---------", msg);
1092// foreach (ulong handle in handles)
1093// {
1094// uint x, y;
1095// Utils.LongToUInts(handle, out x, out y);
1096// x = x / Constants.RegionSize;
1097// y = y / Constants.RegionSize;
1098// Console.WriteLine("({0}, {1})", x, y);
1099// }
1100// }
1101 }
1102}
diff --git a/OpenSim/Region/Environment/Scenes/SceneGraph.cs b/OpenSim/Region/Environment/Scenes/SceneGraph.cs
deleted file mode 100644
index 24eaad1..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneGraph.cs
+++ /dev/null
@@ -1,1811 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using log4net;
34using OpenSim.Framework;
35using OpenSim.Region.Environment.Types;
36using OpenSim.Region.Physics.Manager;
37
38namespace OpenSim.Region.Environment.Scenes
39{
40 public delegate void PhysicsCrash();
41
42 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
43
44 public delegate void ObjectCreateDelegate(EntityBase obj);
45
46 public delegate void ObjectDeleteDelegate(EntityBase obj);
47
48 /// <summary>
49 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
50 /// should be migrated out over time.
51 /// </summary>
52 public class SceneGraph
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 #region Events
57
58 protected internal event PhysicsCrash UnRecoverableError;
59 private PhysicsCrash handlerPhysicsCrash = null;
60
61 public event ObjectDuplicateDelegate OnObjectDuplicate;
62 public event ObjectCreateDelegate OnObjectCreate;
63 public event ObjectDeleteDelegate OnObjectRemove;
64
65 #endregion
66
67 #region Fields
68
69 protected internal Dictionary<UUID, ScenePresence> ScenePresences = new Dictionary<UUID, ScenePresence>();
70 // SceneObjects is not currently populated or used.
71 //public Dictionary<UUID, SceneObjectGroup> SceneObjects;
72 protected internal EntityManager Entities = new EntityManager();
73// protected internal Dictionary<UUID, EntityBase> Entities = new Dictionary<UUID, EntityBase>();
74 protected internal Dictionary<UUID, ScenePresence> RestorePresences = new Dictionary<UUID, ScenePresence>();
75
76 protected internal BasicQuadTreeNode QuadTree;
77
78 protected RegionInfo m_regInfo;
79 protected Scene m_parentScene;
80 protected List<EntityBase> m_updateList = new List<EntityBase>();
81 protected int m_numRootAgents = 0;
82 protected int m_numPrim = 0;
83 protected int m_numChildAgents = 0;
84 protected int m_physicalPrim = 0;
85
86 protected int m_activeScripts = 0;
87 protected int m_scriptLPS = 0;
88
89 protected internal object m_syncRoot = new object();
90
91 protected internal PhysicsScene _PhyScene;
92
93 #endregion
94
95 protected internal SceneGraph(Scene parent, RegionInfo regInfo)
96 {
97 m_parentScene = parent;
98 m_regInfo = regInfo;
99 QuadTree = new BasicQuadTreeNode(null, "/0/", 0, 0, (short)Constants.RegionSize, (short)Constants.RegionSize);
100 QuadTree.Subdivide();
101 QuadTree.Subdivide();
102 }
103
104 public PhysicsScene PhysicsScene
105 {
106 get { return _PhyScene; }
107 set
108 {
109 // If we're not doing the initial set
110 // Then we've got to remove the previous
111 // event handler
112
113 if (_PhyScene != null)
114 _PhyScene.OnPhysicsCrash -= physicsBasedCrash;
115
116 _PhyScene = value;
117
118 if (_PhyScene != null)
119 _PhyScene.OnPhysicsCrash += physicsBasedCrash;
120 }
121 }
122
123 protected internal void Close()
124 {
125 lock (ScenePresences)
126 {
127 ScenePresences.Clear();
128 }
129
130 Entities.Clear();
131 }
132
133 #region Update Methods
134
135 protected internal void UpdatePreparePhysics()
136 {
137 // If we are using a threaded physics engine
138 // grab the latest scene from the engine before
139 // trying to process it.
140
141 // PhysX does this (runs in the background).
142
143 if (_PhyScene.IsThreaded)
144 {
145 _PhyScene.GetResults();
146 }
147 }
148
149 protected internal void UpdateEntities()
150 {
151 List<EntityBase> updateEntities = GetEntities();
152
153 foreach (EntityBase entity in updateEntities)
154 {
155 entity.Update();
156 }
157 }
158
159 protected internal void UpdatePresences()
160 {
161 List<ScenePresence> updateScenePresences = GetScenePresences();
162 foreach (ScenePresence pres in updateScenePresences)
163 {
164 pres.Update();
165 }
166 }
167
168 protected internal float UpdatePhysics(double elapsed)
169 {
170 lock (m_syncRoot)
171 {
172 // Here is where the Scene calls the PhysicsScene. This is a one-way
173 // interaction; the PhysicsScene cannot access the calling Scene directly.
174 // But with joints, we want a PhysicsActor to be able to influence a
175 // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
176 // with a joint should be able to move the SceneObjectPart which is the visual
177 // representation of that joint (for editing and serialization purposes).
178 // However the PhysicsActor normally cannot directly influence anything outside
179 // of the PhysicsScene, and the non-physical SceneObjectPart which represents
180 // the joint in the Scene does not exist in the PhysicsScene.
181 //
182 // To solve this, we have an event in the PhysicsScene that is fired when a joint
183 // has changed position (because one of its associated PhysicsActors has changed
184 // position).
185 //
186 // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
187
188 return _PhyScene.Simulate((float)elapsed);
189 }
190 }
191
192 protected internal void UpdateEntityMovement()
193 {
194 List<EntityBase> moveEntities = GetEntities();
195
196 foreach (EntityBase entity in moveEntities)
197 {
198 //cfk. This throws occaisional exceptions on a heavily used region
199 //and I added this null check to try to preclude the exception.
200 if (entity != null)
201 entity.UpdateMovement();
202 }
203 }
204
205 #endregion
206
207 #region Entity Methods
208
209 /// <summary>
210 /// Add an object into the scene that has come from storage
211 /// </summary>
212 /// <param name="sceneObject"></param>
213 /// <param name="attachToBackup">
214 /// If true, changes to the object will be reflected in its persisted data
215 /// If false, the persisted data will not be changed even if the object in the scene is changed
216 /// </param>
217 /// <param name="alreadyPersisted">
218 /// If true, we won't persist this object until it changes
219 /// If false, we'll persist this object immediately
220 /// </param>
221 /// <returns>
222 /// true if the object was added, false if an object with the same uuid was already in the scene
223 /// </returns>
224 protected internal bool AddRestoredSceneObject(
225 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted)
226 {
227 if (!alreadyPersisted)
228 {
229 sceneObject.ForceInventoryPersistence();
230 sceneObject.HasGroupChanged = true;
231 }
232
233 return AddSceneObject(sceneObject, attachToBackup);
234 }
235
236 /// <summary>
237 /// Add a newly created object to the scene. This will both update the scene, and send information about the
238 /// new object to all clients interested in the scene.
239 /// </summary>
240 /// <param name="sceneObject"></param>
241 /// <param name="attachToBackup">
242 /// If true, the object is made persistent into the scene.
243 /// If false, the object will not persist over server restarts
244 /// </param>
245 /// <returns>
246 /// true if the object was added, false if an object with the same uuid was already in the scene
247 /// </returns>
248 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup)
249 {
250 // Ensure that we persist this new scene object
251 sceneObject.HasGroupChanged = true;
252
253 return AddSceneObject(sceneObject, attachToBackup);
254 }
255
256 /// <summary>
257 /// Add an object to the scene. This will both update the scene, and send information about the
258 /// new object to all clients interested in the scene.
259 /// </summary>
260 /// <param name="sceneObject"></param>
261 /// <param name="attachToBackup">
262 /// If true, the object is made persistent into the scene.
263 /// If false, the object will not persist over server restarts
264 /// </param>
265 /// <returns>true if the object was added, false if an object with the same uuid was already in the scene
266 /// </returns>
267 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup)
268 {
269 if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero)
270 return false;
271
272 if (m_parentScene.m_clampPrimSize)
273 {
274 foreach (SceneObjectPart part in sceneObject.Children.Values)
275 {
276 Vector3 scale = part.Shape.Scale;
277
278 if (scale.X > m_parentScene.m_maxNonphys)
279 scale.X = m_parentScene.m_maxNonphys;
280 if (scale.Y > m_parentScene.m_maxNonphys)
281 scale.Y = m_parentScene.m_maxNonphys;
282 if (scale.Z > m_parentScene.m_maxNonphys)
283 scale.Z = m_parentScene.m_maxNonphys;
284
285 part.Shape.Scale = scale;
286 }
287 }
288
289 sceneObject.AttachToScene(m_parentScene);
290
291 lock (sceneObject)
292 {
293 if (!Entities.ContainsKey(sceneObject.UUID))
294 {
295 Entities.Add(sceneObject);
296 m_numPrim += sceneObject.Children.Count;
297
298 if (attachToBackup)
299 sceneObject.AttachToBackup();
300
301 if (OnObjectCreate != null)
302 OnObjectCreate(sceneObject);
303
304 return true;
305 }
306 }
307
308 return false;
309 }
310
311 /// <summary>
312 /// Delete an object from the scene
313 /// </summary>
314 /// <returns>true if the object was deleted, false if there was no object to delete</returns>
315 protected internal bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
316 {
317 if (Entities.ContainsKey(uuid))
318 {
319 if (!resultOfObjectLinked)
320 {
321 m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count;
322
323 if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
324 {
325 RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count);
326 }
327 }
328
329 if (OnObjectRemove != null)
330 OnObjectRemove(Entities[uuid]);
331
332 Entities.Remove(uuid);
333 //SceneObjectGroup part;
334 //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
335
336 return true;
337 }
338
339 return false;
340 }
341
342 /// <summary>
343 /// Add an entity to the list of prims to process on the next update
344 /// </summary>
345 /// <param name="obj">
346 /// A <see cref="EntityBase"/>
347 /// </param>
348 protected internal void AddToUpdateList(EntityBase obj)
349 {
350 lock (m_updateList)
351 {
352 if (!m_updateList.Contains(obj))
353 {
354 m_updateList.Add(obj);
355 }
356 }
357 }
358
359 /// <summary>
360 /// Process all pending updates
361 /// </summary>
362 protected internal void ProcessUpdates()
363 {
364 lock (m_updateList)
365 {
366 for (int i = 0; i < m_updateList.Count; i++)
367 {
368 EntityBase entity = m_updateList[i];
369
370 // Don't abort the whole update if one entity happens to give us an exception.
371 try
372 {
373 m_updateList[i].Update();
374 }
375 catch (Exception e)
376 {
377 m_log.ErrorFormat(
378 "[INNER SCENE]: Failed to update {0}, {1} - {2}", entity.Name, entity.UUID, e);
379 }
380 }
381
382 m_updateList.Clear();
383 }
384 }
385
386 protected internal void AddPhysicalPrim(int number)
387 {
388 m_physicalPrim++;
389 }
390
391 protected internal void RemovePhysicalPrim(int number)
392 {
393 m_physicalPrim--;
394 }
395
396 protected internal void AddToScriptLPS(int number)
397 {
398 m_scriptLPS += number;
399 }
400
401 protected internal void AddActiveScripts(int number)
402 {
403 m_activeScripts += number;
404 }
405
406 protected internal void DropObject(uint objectLocalID, IClientAPI remoteClient)
407 {
408 List<EntityBase> EntityList = GetEntities();
409
410 foreach (EntityBase obj in EntityList)
411 {
412 if (obj is SceneObjectGroup)
413 {
414 if (((SceneObjectGroup)obj).LocalId == objectLocalID)
415 {
416 SceneObjectGroup group = (SceneObjectGroup)obj;
417
418 m_parentScene.DetachSingleAttachmentToGround(group.UUID,remoteClient);
419 }
420 }
421 }
422 }
423
424 protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient)
425 {
426 List<EntityBase> EntityList = GetEntities();
427
428 foreach (EntityBase obj in EntityList)
429 {
430 if (obj is SceneObjectGroup)
431 {
432 if (((SceneObjectGroup)obj).LocalId == objectLocalID)
433 {
434 SceneObjectGroup group = (SceneObjectGroup)obj;
435
436 //group.DetachToGround();
437 m_parentScene.DetachSingleAttachmentToInv(group.GetFromAssetID(),remoteClient);
438 }
439 }
440 }
441 }
442
443 protected internal void HandleUndo(IClientAPI remoteClient, UUID primId)
444 {
445 if (primId != UUID.Zero)
446 {
447 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId);
448 if (part != null)
449 part.Undo();
450 }
451 }
452
453 protected internal void HandleObjectGroupUpdate(
454 IClientAPI remoteClient, UUID GroupID, uint objectLocalID, UUID Garbage)
455 {
456 List<EntityBase> EntityList = GetEntities();
457
458 foreach (EntityBase obj in EntityList)
459 {
460 if (obj is SceneObjectGroup)
461 {
462 if (((SceneObjectGroup)obj).LocalId == objectLocalID)
463 {
464 SceneObjectGroup group = (SceneObjectGroup)obj;
465
466 if (group.OwnerID == remoteClient.AgentId)
467 group.SetGroup(GroupID, remoteClient);
468 }
469 }
470 }
471 }
472
473 /// <summary>
474 /// Event Handling routine for Attach Object
475 /// </summary>
476 /// <param name="remoteClient"></param>
477 /// <param name="objectLocalID"></param>
478 /// <param name="AttachmentPt"></param>
479 /// <param name="rot"></param>
480 protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent)
481 {
482 // If we can't take it, we can't attach it!
483 //
484 SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID);
485 if (part == null)
486 return;
487
488 if (!m_parentScene.Permissions.CanTakeObject(
489 part.UUID, remoteClient.AgentId))
490 return;
491
492 // Calls attach with a Zero position
493 //
494 AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false);
495 }
496
497 public SceneObjectGroup RezSingleAttachment(
498 IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
499 {
500 SceneObjectGroup objatt = m_parentScene.RezObject(remoteClient,
501 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
502 false, false, remoteClient.AgentId, true);
503
504
505 if (objatt != null)
506 {
507 bool tainted = false;
508 if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint())
509 tainted = true;
510
511 AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false);
512 objatt.ScheduleGroupForFullUpdate();
513 if (tainted)
514 objatt.HasGroupChanged = true;
515
516 // Fire after attach, so we don't get messy perms dialogs
517 //
518 objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 0);
519 }
520 return objatt;
521 }
522
523 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
524 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
525 public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient)
526 {
527 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
528 return;
529
530 List<EntityBase> EntityList = GetEntities();
531
532 foreach (EntityBase obj in EntityList)
533 {
534 if (obj is SceneObjectGroup)
535 {
536 if (((SceneObjectGroup)obj).GetFromAssetID() == itemID)
537 {
538 SceneObjectGroup group = (SceneObjectGroup)obj;
539 group.DetachToInventoryPrep();
540 m_log.Debug("[DETACH]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
541 m_parentScene.updateKnownAsset(remoteClient, group, group.GetFromAssetID(), group.OwnerID);
542 m_parentScene.DeleteSceneObject(group, false);
543 }
544 }
545 }
546 }
547
548 protected internal void AttachObject(
549 IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent)
550 {
551 List<EntityBase> EntityList = GetEntities();
552 foreach (EntityBase obj in EntityList)
553 {
554 if (obj is SceneObjectGroup)
555 {
556 if (((SceneObjectGroup)obj).LocalId == objectLocalID)
557 {
558 SceneObjectGroup group = (SceneObjectGroup)obj;
559 if (m_parentScene.Permissions.CanTakeObject(obj.UUID, remoteClient.AgentId))
560 {
561 // If the attachment point isn't the same as the one previously used
562 // set it's offset position = 0 so that it appears on the attachment point
563 // and not in a weird location somewhere unknown.
564 if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint())
565 {
566
567 attachPos = Vector3.Zero;
568 }
569
570 // AttachmentPt 0 means the client chose to 'wear' the attachment.
571 if (AttachmentPt == 0)
572 {
573
574 // Check object for stored attachment point
575 AttachmentPt = (uint)group.GetAttachmentPoint();
576
577
578 }
579
580 // if we still didn't find a suitable attachment point.......
581 if (AttachmentPt == 0)
582 {
583 // Stick it on left hand with Zero Offset from the attachment point.
584 AttachmentPt = (uint)AttachmentPoint.LeftHand;
585 attachPos = Vector3.Zero;
586 }
587
588 group.SetAttachmentPoint(Convert.ToByte(AttachmentPt));
589 group.AbsolutePosition = attachPos;
590
591 // Saves and gets assetID
592 UUID itemId;
593 if (group.GetFromAssetID() == UUID.Zero)
594 {
595 m_parentScene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId);
596 }
597 else
598 {
599 itemId = group.GetFromAssetID();
600 }
601
602 m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group);
603
604 group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent);
605 // In case it is later dropped again, don't let
606 // it get cleaned up
607 //
608 group.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
609 group.HasGroupChanged = false;
610 }
611 else
612 {
613 remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false);
614 }
615
616 }
617 }
618 }
619 }
620
621 protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance)
622 {
623 ScenePresence newAvatar = null;
624
625 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance);
626 newAvatar.IsChildAgent = true;
627
628 AddScenePresence(newAvatar);
629
630 return newAvatar;
631 }
632
633 /// <summary>
634 /// Add a presence to the scene
635 /// </summary>
636 /// <param name="presence"></param>
637 protected internal void AddScenePresence(ScenePresence presence)
638 {
639 bool child = presence.IsChildAgent;
640
641 if (child)
642 {
643 m_numChildAgents++;
644 }
645 else
646 {
647 m_numRootAgents++;
648 presence.AddToPhysicalScene();
649 }
650
651 Entities[presence.UUID] = presence;
652
653 lock (ScenePresences)
654 {
655 ScenePresences[presence.UUID] = presence;
656 }
657 }
658
659 /// <summary>
660 /// Remove a presence from the scene
661 /// </summary>
662 protected internal void RemoveScenePresence(UUID agentID)
663 {
664 if (!Entities.Remove(agentID))
665 {
666 m_log.WarnFormat(
667 "[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
668 agentID);
669 }
670
671 lock (ScenePresences)
672 {
673 if (!ScenePresences.Remove(agentID))
674 {
675 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
676 }
677// else
678// {
679// m_log.InfoFormat("[SCENE] Removed scene presence {0} from scene presences list", agentID);
680// }
681 }
682 }
683
684 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
685 {
686 if (direction_RC_CR_T_F)
687 {
688 m_numRootAgents--;
689 m_numChildAgents++;
690 }
691 else
692 {
693 m_numChildAgents--;
694 m_numRootAgents++;
695 }
696 }
697
698 protected internal void removeUserCount(bool TypeRCTF)
699 {
700 if (TypeRCTF)
701 {
702 m_numRootAgents--;
703 }
704 else
705 {
706 m_numChildAgents--;
707 }
708 }
709
710 public void RecalculateStats()
711 {
712 List<ScenePresence> SPList = GetScenePresences();
713 int rootcount = 0;
714 int childcount = 0;
715
716 foreach (ScenePresence user in SPList)
717 {
718 if (user.IsChildAgent)
719 childcount++;
720 else
721 rootcount++;
722 }
723 m_numRootAgents = rootcount;
724 m_numChildAgents = childcount;
725
726 }
727
728 public int GetChildAgentCount()
729 {
730 // some network situations come in where child agents get closed twice.
731 if (m_numChildAgents < 0)
732 {
733 m_numChildAgents = 0;
734 }
735
736 return m_numChildAgents;
737 }
738
739 public int GetRootAgentCount()
740 {
741 return m_numRootAgents;
742 }
743
744 public int GetTotalObjectsCount()
745 {
746 return m_numPrim;
747 }
748
749 public int GetActiveObjectsCount()
750 {
751 return m_physicalPrim;
752 }
753
754 public int GetActiveScriptsCount()
755 {
756 return m_activeScripts;
757 }
758
759 public int GetScriptLPS()
760 {
761 int returnval = m_scriptLPS;
762 m_scriptLPS = 0;
763 return returnval;
764 }
765
766 #endregion
767
768 #region Get Methods
769
770 /// <summary>
771 /// Request a List of all scene presences in this scene. This is a new list, so no
772 /// locking is required to iterate over it.
773 /// </summary>
774 /// <returns></returns>
775 protected internal List<ScenePresence> GetScenePresences()
776 {
777 lock (ScenePresences)
778 {
779 return new List<ScenePresence>(ScenePresences.Values);
780 }
781 }
782
783 protected internal List<ScenePresence> GetAvatars()
784 {
785 List<ScenePresence> result =
786 GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; });
787
788 return result;
789 }
790
791 /// <summary>
792 /// Get the controlling client for the given avatar, if there is one.
793 ///
794 /// FIXME: The only user of the method right now is Caps.cs, in order to resolve a client API since it can't
795 /// use the ScenePresence. This could be better solved in a number of ways - we could establish an
796 /// OpenSim.Framework.IScenePresence, or move the caps code into a region package (which might be the more
797 /// suitable solution).
798 /// </summary>
799 /// <param name="agentId"></param>
800 /// <returns>null if either the avatar wasn't in the scene, or they do not have a controlling client</returns>
801 protected internal IClientAPI GetControllingClient(UUID agentId)
802 {
803 ScenePresence presence = GetScenePresence(agentId);
804
805 if (presence != null)
806 {
807 return presence.ControllingClient;
808 }
809
810 return null;
811 }
812
813 /// <summary>
814 /// Request a filtered list of m_scenePresences in this World
815 /// </summary>
816 /// <returns></returns>
817 protected internal List<ScenePresence> GetScenePresences(FilterAvatarList filter)
818 {
819 // No locking of scene presences here since we're passing back a list...
820
821 List<ScenePresence> result = new List<ScenePresence>();
822 List<ScenePresence> ScenePresencesList = GetScenePresences();
823
824 foreach (ScenePresence avatar in ScenePresencesList)
825 {
826 if (filter(avatar))
827 {
828 result.Add(avatar);
829 }
830 }
831
832 return result;
833 }
834
835 /// <summary>
836 /// Request a scene presence by UUID
837 /// </summary>
838 /// <param name="avatarID"></param>
839 /// <returns>null if the agent was not found</returns>
840 protected internal ScenePresence GetScenePresence(UUID agentID)
841 {
842 ScenePresence sp;
843
844 lock (ScenePresences)
845 {
846 ScenePresences.TryGetValue(agentID, out sp);
847 }
848
849 return sp;
850 }
851
852 /// <summary>
853 /// Get a scene object group that contains the prim with the given local id
854 /// </summary>
855 /// <param name="localID"></param>
856 /// <returns>null if no scene object group containing that prim is found</returns>
857 private SceneObjectGroup GetGroupByPrim(uint localID)
858 {
859 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
860 List<EntityBase> EntityList = GetEntities();
861 foreach (EntityBase ent in EntityList)
862 {
863 //m_log.DebugFormat("Looking at entity {0}", ent.UUID);
864 if (ent is SceneObjectGroup)
865 {
866 if (((SceneObjectGroup)ent).HasChildPrim(localID))
867 return (SceneObjectGroup)ent;
868 }
869 }
870 return null;
871 }
872
873 /// <summary>
874 /// Get a scene object group that contains the prim with the given uuid
875 /// </summary>
876 /// <param name="fullID"></param>
877 /// <returns>null if no scene object group containing that prim is found</returns>
878 private SceneObjectGroup GetGroupByPrim(UUID fullID)
879 {
880 List<EntityBase> EntityList = GetEntities();
881
882 foreach (EntityBase ent in EntityList)
883 {
884 if (ent is SceneObjectGroup)
885 {
886 if (((SceneObjectGroup)ent).HasChildPrim(fullID))
887 return (SceneObjectGroup)ent;
888 }
889 }
890 return null;
891 }
892
893 protected internal EntityIntersection GetClosestIntersectingPrim(Ray hray, bool frontFacesOnly, bool faceCenters)
894 {
895 // Primitive Ray Tracing
896 float closestDistance = 280f;
897 EntityIntersection returnResult = new EntityIntersection();
898 List<EntityBase> EntityList = GetEntities();
899 foreach (EntityBase ent in EntityList)
900 {
901 if (ent is SceneObjectGroup)
902 {
903 SceneObjectGroup reportingG = (SceneObjectGroup)ent;
904 EntityIntersection result = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
905 if (result.HitTF)
906 {
907 if (result.distance < closestDistance)
908 {
909 closestDistance = result.distance;
910 returnResult = result;
911 }
912 }
913 }
914 }
915 return returnResult;
916 }
917
918 /// <summary>
919 /// Get a part contained in this scene.
920 /// </summary>
921 /// <param name="localID"></param>
922 /// <returns>null if the part was not found</returns>
923 protected internal SceneObjectPart GetSceneObjectPart(uint localID)
924 {
925 SceneObjectGroup group = GetGroupByPrim(localID);
926
927 if (group != null)
928 return group.GetChildPart(localID);
929 else
930 return null;
931 }
932
933 /// <summary>
934 /// Get a named prim contained in this scene (will return the first
935 /// found, if there are more than one prim with the same name)
936 /// </summary>
937 /// <param name="name"></param>
938 /// <returns>null if the part was not found</returns>
939 protected internal SceneObjectPart GetSceneObjectPart(string name)
940 {
941 List<EntityBase> EntityList = GetEntities();
942
943 // FIXME: use a dictionary here
944 foreach (EntityBase ent in EntityList)
945 {
946 if (ent is SceneObjectGroup)
947 {
948 foreach (SceneObjectPart p in ((SceneObjectGroup) ent).GetParts())
949 {
950 if (p.Name==name)
951 {
952 return p;
953 }
954 }
955 }
956 }
957 return null;
958 }
959
960 /// <summary>
961 /// Get a part contained in this scene.
962 /// </summary>
963 /// <param name="fullID"></param>
964 /// <returns>null if the part was not found</returns>
965 protected internal SceneObjectPart GetSceneObjectPart(UUID fullID)
966 {
967 SceneObjectGroup group = GetGroupByPrim(fullID);
968
969 if (group != null)
970 return group.GetChildPart(fullID);
971 else
972 return null;
973 }
974
975 protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
976 {
977 ScenePresence presence;
978
979 lock (ScenePresences)
980 {
981 if (ScenePresences.TryGetValue(avatarId, out presence))
982 {
983 avatar = presence;
984 return true;
985
986 //if (!presence.IsChildAgent)
987 //{
988 // avatar = presence;
989 // return true;
990 //}
991 //else
992 //{
993 // m_log.WarnFormat(
994 // "[INNER SCENE]: Requested avatar {0} could not be found in scene {1} since it is only registered as a child agent!",
995 // avatarId, m_parentScene.RegionInfo.RegionName);
996 //}
997 }
998 }
999
1000 avatar = null;
1001 return false;
1002 }
1003
1004 protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
1005 {
1006 lock (ScenePresences)
1007 {
1008 foreach (ScenePresence presence in ScenePresences.Values)
1009 {
1010 if (!presence.IsChildAgent)
1011 {
1012 string name = presence.ControllingClient.Name;
1013
1014 if (String.Compare(avatarName, name, true) == 0)
1015 {
1016 avatar = presence;
1017 return true;
1018 }
1019 }
1020 }
1021 }
1022
1023 avatar = null;
1024 return false;
1025 }
1026
1027 /// <summary>
1028 /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over
1029 /// it
1030 /// </summary>
1031 /// <returns></returns>
1032 protected internal List<EntityBase> GetEntities()
1033 {
1034 return Entities.GetEntities();
1035 }
1036
1037 protected internal Dictionary<uint, float> GetTopScripts()
1038 {
1039 Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
1040
1041 List<EntityBase> EntityList = GetEntities();
1042 int limit = 0;
1043 foreach (EntityBase ent in EntityList)
1044 {
1045 if (ent is SceneObjectGroup)
1046 {
1047 SceneObjectGroup grp = (SceneObjectGroup)ent;
1048 if ((grp.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
1049 {
1050 if (grp.scriptScore >= 0.01)
1051 {
1052 topScripts.Add(grp.LocalId, grp.scriptScore);
1053 limit++;
1054 if (limit >= 100)
1055 {
1056 break;
1057 }
1058 }
1059 grp.scriptScore = 0;
1060 }
1061 }
1062 }
1063
1064 return topScripts;
1065 }
1066
1067 #endregion
1068
1069 #region Other Methods
1070
1071 protected internal void physicsBasedCrash()
1072 {
1073 handlerPhysicsCrash = UnRecoverableError;
1074 if (handlerPhysicsCrash != null)
1075 {
1076 handlerPhysicsCrash();
1077 }
1078 }
1079
1080 protected internal UUID ConvertLocalIDToFullID(uint localID)
1081 {
1082 SceneObjectGroup group = GetGroupByPrim(localID);
1083 if (group != null)
1084 return group.GetPartsFullID(localID);
1085 else
1086 return UUID.Zero;
1087 }
1088
1089 protected internal void ForEachClient(Action<IClientAPI> action)
1090 {
1091 List<ScenePresence> splist = GetScenePresences();
1092 foreach (ScenePresence presence in splist)
1093 {
1094 try
1095 {
1096 action(presence.ControllingClient);
1097 }
1098 catch (Exception e)
1099 {
1100 // Catch it and move on. This includes situations where splist has inconsistent info
1101 m_log.WarnFormat("[SCENE]: Problem processing action in ForEachClient: ", e.Message);
1102 }
1103 }
1104 }
1105
1106 #endregion
1107
1108 #region Client Event handlers
1109
1110 /// <summary>
1111 ///
1112 /// </summary>
1113 /// <param name="localID"></param>
1114 /// <param name="scale"></param>
1115 /// <param name="remoteClient"></param>
1116 protected internal void UpdatePrimScale(uint localID, Vector3 scale, IClientAPI remoteClient)
1117 {
1118 SceneObjectGroup group = GetGroupByPrim(localID);
1119 if (group != null)
1120 {
1121 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1122 {
1123 group.Resize(scale, localID);
1124 }
1125 }
1126 }
1127
1128 protected internal void UpdatePrimGroupScale(uint localID, Vector3 scale, IClientAPI remoteClient)
1129 {
1130 SceneObjectGroup group = GetGroupByPrim(localID);
1131 if (group != null)
1132 {
1133 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1134 {
1135 group.GroupResize(scale, localID);
1136 }
1137 }
1138 }
1139
1140 /// <summary>
1141 /// This handles the nifty little tool tip that you get when you drag your mouse over an object
1142 /// Send to the Object Group to process. We don't know enough to service the request
1143 /// </summary>
1144 /// <param name="remoteClient"></param>
1145 /// <param name="AgentID"></param>
1146 /// <param name="RequestFlags"></param>
1147 /// <param name="ObjectID"></param>
1148 protected internal void RequestObjectPropertiesFamily(
1149 IClientAPI remoteClient, UUID AgentID, uint RequestFlags, UUID ObjectID)
1150 {
1151 SceneObjectGroup group = GetGroupByPrim(ObjectID);
1152 if (group != null)
1153 {
1154 group.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags);
1155 }
1156 }
1157
1158 /// <summary>
1159 ///
1160 /// </summary>
1161 /// <param name="localID"></param>
1162 /// <param name="rot"></param>
1163 /// <param name="remoteClient"></param>
1164 protected internal void UpdatePrimSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
1165 {
1166 SceneObjectGroup group = GetGroupByPrim(localID);
1167 if (group != null)
1168 {
1169 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))
1170 {
1171 group.UpdateSingleRotation(rot, localID);
1172 }
1173 }
1174 }
1175
1176 /// <summary>
1177 ///
1178 /// </summary>
1179 /// <param name="localID"></param>
1180 /// <param name="rot"></param>
1181 /// <param name="remoteClient"></param>
1182 protected internal void UpdatePrimRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
1183 {
1184 SceneObjectGroup group = GetGroupByPrim(localID);
1185 if (group != null)
1186 {
1187 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))
1188 {
1189 group.UpdateGroupRotation(rot);
1190 }
1191 }
1192 }
1193
1194 /// <summary>
1195 ///
1196 /// </summary>
1197 /// <param name="localID"></param>
1198 /// <param name="pos"></param>
1199 /// <param name="rot"></param>
1200 /// <param name="remoteClient"></param>
1201 protected internal void UpdatePrimRotation(uint localID, Vector3 pos, Quaternion rot, IClientAPI remoteClient)
1202 {
1203 SceneObjectGroup group = GetGroupByPrim(localID);
1204 if (group != null)
1205 {
1206 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))
1207 {
1208 group.UpdateGroupRotation(pos, rot);
1209 }
1210 }
1211 }
1212
1213 /// <summary>
1214 /// Update the position of the given part
1215 /// </summary>
1216 /// <param name="localID"></param>
1217 /// <param name="pos"></param>
1218 /// <param name="remoteClient"></param>
1219 protected internal void UpdatePrimSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient)
1220 {
1221 SceneObjectGroup group = GetGroupByPrim(localID);
1222 if (group != null)
1223 {
1224 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) || group.IsAttachment)
1225 {
1226 group.UpdateSinglePosition(pos, localID);
1227 }
1228 }
1229 }
1230
1231 /// <summary>
1232 /// Update the position of the given part
1233 /// </summary>
1234 /// <param name="localID"></param>
1235 /// <param name="pos"></param>
1236 /// <param name="remoteClient"></param>
1237 protected internal void UpdatePrimPosition(uint localID, Vector3 pos, IClientAPI remoteClient)
1238 {
1239 SceneObjectGroup group = GetGroupByPrim(localID);
1240 if (group != null)
1241 {
1242
1243 // Vector3 oldPos = group.AbsolutePosition;
1244 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1245 {
1246 group.UpdateGroupPosition(pos);
1247 }
1248 else
1249 {
1250 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos))
1251 {
1252 group.UpdateGroupPosition(pos);
1253 }
1254 }
1255 }
1256 }
1257
1258 /// <summary>
1259 ///
1260 /// </summary>
1261 /// <param name="localID"></param>
1262 /// <param name="texture"></param>
1263 /// <param name="remoteClient"></param>
1264 protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient)
1265 {
1266 SceneObjectGroup group = GetGroupByPrim(localID);
1267 if (group != null)
1268 {
1269 if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId))
1270 {
1271 group.UpdateTextureEntry(localID, texture);
1272 }
1273 }
1274 }
1275
1276 /// <summary>
1277 ///
1278 /// </summary>
1279 /// <param name="localID"></param>
1280 /// <param name="packet"></param>
1281 /// <param name="remoteClient"></param>
1282 /// This routine seems to get called when a user changes object settings in the viewer.
1283 /// If some one can confirm that, please change the comment according.
1284 protected internal void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, IClientAPI remoteClient)
1285 {
1286 SceneObjectGroup group = GetGroupByPrim(localID);
1287 if (group != null)
1288 {
1289 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1290 {
1291 group.UpdatePrimFlags(localID, UsePhysics, IsTemporary, IsPhantom, false); // VolumeDetect can't be set via UI and will always be off when a change is made there
1292 }
1293 }
1294 }
1295
1296 /// <summary>
1297 /// Move the given object
1298 /// </summary>
1299 /// <param name="objectID"></param>
1300 /// <param name="offset"></param>
1301 /// <param name="pos"></param>
1302 /// <param name="remoteClient"></param>
1303 protected internal void MoveObject(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
1304 {
1305 SceneObjectGroup group = GetGroupByPrim(objectID);
1306 if (group != null)
1307 {
1308 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.)
1309 {
1310 group.GrabMovement(offset, pos, remoteClient);
1311 }
1312 // This is outside the above permissions condition
1313 // so that if the object is locked the client moving the object
1314 // get's it's position on the simulator even if it was the same as before
1315 // This keeps the moving user's client in sync with the rest of the world.
1316 group.SendGroupTerseUpdate();
1317 }
1318 }
1319
1320 /// <summary>
1321 ///
1322 /// </summary>
1323 /// <param name="primLocalID"></param>
1324 /// <param name="description"></param>
1325 protected internal void PrimName(IClientAPI remoteClient, uint primLocalID, string name)
1326 {
1327 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1328 if (group != null)
1329 {
1330 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1331 {
1332 group.SetPartName(Util.CleanString(name), primLocalID);
1333 group.HasGroupChanged = true;
1334 }
1335 }
1336 }
1337
1338 /// <summary>
1339 ///
1340 /// </summary>
1341 /// <param name="primLocalID"></param>
1342 /// <param name="description"></param>
1343 protected internal void PrimDescription(IClientAPI remoteClient, uint primLocalID, string description)
1344 {
1345 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1346 if (group != null)
1347 {
1348 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1349 {
1350 group.SetPartDescription(Util.CleanString(description), primLocalID);
1351 group.HasGroupChanged = true;
1352 }
1353 }
1354 }
1355
1356 protected internal void PrimClickAction(IClientAPI remoteClient, uint primLocalID, string clickAction)
1357 {
1358 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1359 if (group != null)
1360 {
1361 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1362 {
1363 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID);
1364 part.ClickAction = Convert.ToByte(clickAction);
1365 group.HasGroupChanged = true;
1366 }
1367 }
1368 }
1369
1370 protected internal void PrimMaterial(IClientAPI remoteClient, uint primLocalID, string material)
1371 {
1372 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1373 if (group != null)
1374 {
1375 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1376 {
1377 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID);
1378 part.Material = Convert.ToByte(material);
1379 group.HasGroupChanged = true;
1380 }
1381 }
1382 }
1383
1384 protected internal void UpdateExtraParam(UUID agentID, uint primLocalID, ushort type, bool inUse, byte[] data)
1385 {
1386 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1387
1388 if (group != null)
1389 {
1390 if (m_parentScene.Permissions.CanEditObject(group.UUID,agentID))
1391 {
1392 group.UpdateExtraParam(primLocalID, type, inUse, data);
1393 }
1394 }
1395 }
1396
1397 /// <summary>
1398 ///
1399 /// </summary>
1400 /// <param name="primLocalID"></param>
1401 /// <param name="shapeBlock"></param>
1402 protected internal void UpdatePrimShape(UUID agentID, uint primLocalID, UpdateShapeArgs shapeBlock)
1403 {
1404 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1405 if (group != null)
1406 {
1407 if (m_parentScene.Permissions.CanEditObject(group.GetPartsFullID(primLocalID), agentID))
1408 {
1409 ObjectShapePacket.ObjectDataBlock shapeData = new ObjectShapePacket.ObjectDataBlock();
1410 shapeData.ObjectLocalID = shapeBlock.ObjectLocalID;
1411 shapeData.PathBegin = shapeBlock.PathBegin;
1412 shapeData.PathCurve = shapeBlock.PathCurve;
1413 shapeData.PathEnd = shapeBlock.PathEnd;
1414 shapeData.PathRadiusOffset = shapeBlock.PathRadiusOffset;
1415 shapeData.PathRevolutions = shapeBlock.PathRevolutions;
1416 shapeData.PathScaleX = shapeBlock.PathScaleX;
1417 shapeData.PathScaleY = shapeBlock.PathScaleY;
1418 shapeData.PathShearX = shapeBlock.PathShearX;
1419 shapeData.PathShearY = shapeBlock.PathShearY;
1420 shapeData.PathSkew = shapeBlock.PathSkew;
1421 shapeData.PathTaperX = shapeBlock.PathTaperX;
1422 shapeData.PathTaperY = shapeBlock.PathTaperY;
1423 shapeData.PathTwist = shapeBlock.PathTwist;
1424 shapeData.PathTwistBegin = shapeBlock.PathTwistBegin;
1425 shapeData.ProfileBegin = shapeBlock.ProfileBegin;
1426 shapeData.ProfileCurve = shapeBlock.ProfileCurve;
1427 shapeData.ProfileEnd = shapeBlock.ProfileEnd;
1428 shapeData.ProfileHollow = shapeBlock.ProfileHollow;
1429
1430 group.UpdateShape(shapeData, primLocalID);
1431 }
1432 }
1433 }
1434
1435 /// <summary>
1436 /// Initial method invoked when we receive a link objects request from the client.
1437 /// </summary>
1438 /// <param name="client"></param>
1439 /// <param name="parentPrim"></param>
1440 /// <param name="childPrims"></param>
1441 protected internal void LinkObjects(IClientAPI client, uint parentPrim, List<uint> childPrims)
1442 {
1443 List<EntityBase> EntityList = GetEntities();
1444
1445 SceneObjectGroup parenPrim = null;
1446 foreach (EntityBase ent in EntityList)
1447 {
1448 if (ent is SceneObjectGroup)
1449 {
1450 if (((SceneObjectGroup)ent).LocalId == parentPrim)
1451 {
1452 parenPrim = (SceneObjectGroup)ent;
1453 break;
1454 }
1455 }
1456 }
1457
1458 List<SceneObjectGroup> children = new List<SceneObjectGroup>();
1459 if (parenPrim != null)
1460 {
1461 // We do this in reverse to get the link order of the prims correct
1462 for (int i = childPrims.Count - 1; i >= 0; i--)
1463 {
1464 foreach (EntityBase ent in EntityList)
1465 {
1466 if (ent is SceneObjectGroup)
1467 {
1468 if (((SceneObjectGroup)ent).LocalId == childPrims[i])
1469 {
1470 // Make sure no child prim is set for sale
1471 // So that, on delink, no prims are unwittingly
1472 // left for sale and sold off
1473 ((SceneObjectGroup)ent).RootPart.ObjectSaleType = 0;
1474 ((SceneObjectGroup)ent).RootPart.SalePrice = 10;
1475 children.Add((SceneObjectGroup)ent);
1476 }
1477 }
1478 }
1479 }
1480 }
1481 else
1482 {
1483 return; // parent is null so not in this region
1484 }
1485
1486 foreach (SceneObjectGroup sceneObj in children)
1487 {
1488 parenPrim.LinkToGroup(sceneObj);
1489
1490 // this is here so physics gets updated!
1491 // Don't remove! Bad juju! Stay away! or fix physics!
1492 sceneObj.AbsolutePosition = sceneObj.AbsolutePosition;
1493 }
1494
1495 // We need to explicitly resend the newly link prim's object properties since no other actions
1496 // occur on link to invoke this elsewhere (such as object selection)
1497 parenPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
1498 parenPrim.TriggerScriptChangedEvent(Changed.LINK);
1499
1500 if (client != null)
1501 {
1502 parenPrim.GetProperties(client);
1503 }
1504 else
1505 {
1506 foreach (ScenePresence p in GetScenePresences())
1507 {
1508 parenPrim.GetProperties(p.ControllingClient);
1509 }
1510 }
1511 }
1512
1513 /// <summary>
1514 /// Delink a linkset
1515 /// </summary>
1516 /// <param name="prims"></param>
1517 protected internal void DelinkObjects(List<uint> primIds)
1518 {
1519 DelinkObjects(primIds, true);
1520 }
1521
1522 protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
1523 {
1524 SceneObjectGroup parenPrim = null;
1525
1526 // Need a list of the SceneObjectGroup local ids
1527 // XXX I'm anticipating that building this dictionary once is more efficient than
1528 // repeated scanning of the Entity.Values for a large number of primIds. However, it might
1529 // be more efficient yet to keep this dictionary permanently on hand.
1530
1531 Dictionary<uint, SceneObjectGroup> sceneObjects = new Dictionary<uint, SceneObjectGroup>();
1532
1533 List<EntityBase> EntityList = GetEntities();
1534 foreach (EntityBase ent in EntityList)
1535 {
1536 if (ent is SceneObjectGroup)
1537 {
1538 SceneObjectGroup obj = (SceneObjectGroup)ent;
1539 // Nasty one. Can't unlink anything in the sim
1540 // If a duplicate local ID sneaks in
1541 // So, check it here!
1542 //
1543 if (!sceneObjects.ContainsKey(obj.LocalId))
1544 sceneObjects.Add(obj.LocalId, obj);
1545
1546 }
1547 }
1548
1549 // Find the root prim among the prim ids we've been given
1550 for (int i = 0; i < primIds.Count; i++)
1551 {
1552
1553 if (sceneObjects.ContainsKey(primIds[i]))
1554 {
1555 parenPrim = sceneObjects[primIds[i]];
1556 primIds.RemoveAt(i);
1557 break;
1558 }
1559 }
1560
1561 if (parenPrim != null)
1562 {
1563 foreach (uint childPrimId in primIds)
1564 {
1565 parenPrim.DelinkFromGroup(childPrimId, sendEvents);
1566 }
1567
1568 if (parenPrim.Children.Count == 1)
1569 {
1570 // The link set has been completely torn down
1571 // This is the case if you select a link set and delink
1572 //
1573 parenPrim.RootPart.LinkNum = 0;
1574 if (sendEvents)
1575 parenPrim.TriggerScriptChangedEvent(Changed.LINK);
1576 }
1577 else
1578 {
1579 // The link set has prims remaining. This path is taken
1580 // when a subset of a link set's prims are selected
1581 // and the root prim is part of that selection
1582 //
1583 List<SceneObjectPart> parts = new List<SceneObjectPart>(parenPrim.Children.Values);
1584
1585 List<uint> unlink_ids = new List<uint>();
1586 foreach (SceneObjectPart unlink_part in parts)
1587 unlink_ids.Add(unlink_part.LocalId);
1588
1589 // Tear down the remaining link set
1590 //
1591 if (unlink_ids.Count == 2)
1592 {
1593 DelinkObjects(unlink_ids, true);
1594 return;
1595 }
1596
1597 DelinkObjects(unlink_ids, false);
1598
1599 // Send event to root prim, then we're done with it
1600 parenPrim.TriggerScriptChangedEvent(Changed.LINK);
1601
1602 unlink_ids.Remove(parenPrim.RootPart.LocalId);
1603
1604 foreach (uint localId in unlink_ids)
1605 {
1606 SceneObjectPart nr = GetSceneObjectPart(localId);
1607 nr.UpdateFlag = 0;
1608 }
1609
1610 uint newRoot = unlink_ids[0];
1611 unlink_ids.Remove(newRoot);
1612
1613 LinkObjects(null, newRoot, unlink_ids);
1614 }
1615 }
1616 else
1617 {
1618 // The selected prims were all child prims. Edit linked parts
1619 // without the root prim selected will get us here
1620 //
1621 List<SceneObjectGroup> parents = new List<SceneObjectGroup>();
1622
1623 // If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow
1624 // We know that this is not the root prim now essentially, so we don't have to worry about remapping
1625 // which one is the root prim
1626 bool delinkedSomething = false;
1627 for (int i = 0; i < primIds.Count; i++)
1628 {
1629 foreach (SceneObjectGroup grp in sceneObjects.Values)
1630 {
1631 SceneObjectPart gPart = grp.GetChildPart(primIds[i]);
1632 if (gPart != null)
1633 {
1634 grp.DelinkFromGroup(primIds[i]);
1635 delinkedSomething = true;
1636 if (!parents.Contains(grp))
1637 parents.Add(grp);
1638 }
1639
1640 }
1641 }
1642 if (!delinkedSomething)
1643 {
1644 m_log.InfoFormat("[SCENE]: " +
1645 "DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!",
1646 primIds);
1647 }
1648 else
1649 {
1650 foreach (SceneObjectGroup g in parents)
1651 {
1652 g.TriggerScriptChangedEvent(Changed.LINK);
1653 }
1654 }
1655 }
1656 }
1657
1658 protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID)
1659 {
1660 UUID user = remoteClient.AgentId;
1661 UUID objid = UUID.Zero;
1662 SceneObjectPart obj = null;
1663
1664 List<EntityBase> EntityList = GetEntities();
1665 foreach (EntityBase ent in EntityList)
1666 {
1667 if (ent is SceneObjectGroup)
1668 {
1669 foreach (KeyValuePair<UUID, SceneObjectPart> subent in ((SceneObjectGroup)ent).Children)
1670 {
1671 if (subent.Value.LocalId == localID)
1672 {
1673 objid = subent.Key;
1674 obj = subent.Value;
1675 }
1676 }
1677 }
1678 }
1679
1680 //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
1681 //aka ObjectFlags.JointWheel = IncludeInSearch
1682
1683 //Permissions model: Object can be REMOVED from search IFF:
1684 // * User owns object
1685 //use CanEditObject
1686
1687 //Object can be ADDED to search IFF:
1688 // * User owns object
1689 // * Asset/DRM permission bit "modify" is enabled
1690 //use CanEditObjectPosition
1691
1692 // libomv will complain about PrimFlags.JointWheel being
1693 // deprecated, so we
1694 #pragma warning disable 0612
1695 if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user))
1696 {
1697 obj.ParentGroup.RootPart.AddFlag(PrimFlags.JointWheel);
1698 obj.ParentGroup.HasGroupChanged = true;
1699 }
1700 else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(objid,user))
1701 {
1702 obj.ParentGroup.RootPart.RemFlag(PrimFlags.JointWheel);
1703 obj.ParentGroup.HasGroupChanged = true;
1704 }
1705 #pragma warning restore 0612
1706 }
1707
1708 /// <summary>
1709 /// Duplicate the given object, Fire and Forget, No rotation, no return wrapper
1710 /// </summary>
1711 /// <param name="originalPrim"></param>
1712 /// <param name="offset"></param>
1713 /// <param name="flags"></param>
1714 protected internal void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID)
1715 {
1716 //m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
1717
1718 // SceneObjectGroup dupe = DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Zero);
1719 DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity);
1720 }
1721
1722 /// <summary>
1723 /// Duplicate the given object.
1724 /// </summary>
1725 /// <param name="originalPrim"></param>
1726 /// <param name="offset"></param>
1727 /// <param name="flags"></param>
1728 protected internal SceneObjectGroup DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1729 {
1730 //m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
1731
1732 List<EntityBase> EntityList = GetEntities();
1733
1734 SceneObjectGroup originPrim = null;
1735 foreach (EntityBase ent in EntityList)
1736 {
1737 if (ent is SceneObjectGroup)
1738 {
1739 if (((SceneObjectGroup)ent).LocalId == originalPrim)
1740 {
1741 originPrim = (SceneObjectGroup)ent;
1742 break;
1743 }
1744 }
1745 }
1746
1747 if (originPrim != null)
1748 {
1749 if (m_parentScene.Permissions.CanDuplicateObject(originPrim.Children.Count, originPrim.UUID, AgentID, originPrim.AbsolutePosition))
1750 {
1751 SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID, true);
1752 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1753
1754 Entities.Add(copy);
1755
1756 // Since we copy from a source group that is in selected
1757 // state, but the copy is shown deselected in the viewer,
1758 // We need to clear the selection flag here, else that
1759 // prim never gets persisted at all. The client doesn't
1760 // think it's selected, so it will never send a deselect...
1761 copy.IsSelected = false;
1762
1763 m_numPrim += copy.Children.Count;
1764
1765 if (rot != Quaternion.Identity)
1766 {
1767 copy.UpdateGroupRotation(rot);
1768 }
1769
1770 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0);
1771 copy.HasGroupChanged = true;
1772 copy.ScheduleGroupForFullUpdate();
1773
1774 // required for physics to update it's position
1775 copy.AbsolutePosition = copy.AbsolutePosition;
1776
1777 if (OnObjectDuplicate != null)
1778 OnObjectDuplicate(originPrim, copy);
1779
1780 return copy;
1781 }
1782 }
1783 else
1784 {
1785 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
1786 }
1787
1788 return null;
1789 }
1790
1791 /// <summary>
1792 /// Calculates the distance between two Vector3s
1793 /// </summary>
1794 /// <param name="v1"></param>
1795 /// <param name="v2"></param>
1796 /// <returns></returns>
1797 protected internal float Vector3Distance(Vector3 v1, Vector3 v2)
1798 {
1799 // We don't really need the double floating point precision...
1800 // so casting it to a single
1801
1802 return
1803 (float)
1804 Math.Sqrt((v1.X - v2.X) * (v1.X - v2.X) + (v1.Y - v2.Y) * (v1.Y - v2.Y) + (v1.Z - v2.Z) * (v1.Z - v2.Z));
1805 }
1806
1807 #endregion
1808
1809
1810 }
1811}
diff --git a/OpenSim/Region/Environment/Scenes/SceneManager.cs b/OpenSim/Region/Environment/Scenes/SceneManager.cs
deleted file mode 100644
index b28eef2..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneManager.cs
+++ /dev/null
@@ -1,669 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using OpenSim.Framework;
35using OpenSim.Region.Environment.Interfaces;
36
37namespace OpenSim.Region.Environment.Scenes
38{
39 public delegate void RestartSim(RegionInfo thisregion);
40
41 /// <summary>
42 /// Manager for adding, closing and restarting scenes.
43 /// </summary>
44 public class SceneManager
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public event RestartSim OnRestartSim;
49
50 private readonly List<Scene> m_localScenes;
51 private Scene m_currentScene = null;
52
53 public List<Scene> Scenes
54 {
55 get { return m_localScenes; }
56 }
57
58 public Scene CurrentScene
59 {
60 get { return m_currentScene; }
61 }
62
63 public Scene CurrentOrFirstScene
64 {
65 get
66 {
67 if (m_currentScene == null)
68 {
69 return m_localScenes[0];
70 }
71 else
72 {
73 return m_currentScene;
74 }
75 }
76 }
77
78 public SceneManager()
79 {
80 m_localScenes = new List<Scene>();
81 }
82
83 public void Close()
84 {
85 // collect known shared modules in sharedModules
86 Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>();
87 for (int i = 0; i < m_localScenes.Count; i++)
88 {
89 // extract known shared modules from scene
90 foreach (string k in m_localScenes[i].Modules.Keys)
91 {
92 if (m_localScenes[i].Modules[k].IsSharedModule &&
93 !sharedModules.ContainsKey(k))
94 sharedModules[k] = m_localScenes[i].Modules[k];
95 }
96 // close scene/region
97 m_localScenes[i].Close();
98 }
99
100 // all regions/scenes are now closed, we can now safely
101 // close all shared modules
102 foreach (IRegionModule mod in sharedModules.Values)
103 {
104 mod.Close();
105 }
106 }
107
108 public void Close(Scene cscene)
109 {
110 if (m_localScenes.Contains(cscene))
111 {
112 for (int i = 0; i < m_localScenes.Count; i++)
113 {
114 if (m_localScenes[i].Equals(cscene))
115 {
116 m_localScenes[i].Close();
117 }
118 }
119 }
120 }
121
122 public void Add(Scene scene)
123 {
124 scene.OnRestart += HandleRestart;
125 m_localScenes.Add(scene);
126 }
127
128 public void HandleRestart(RegionInfo rdata)
129 {
130 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
131 int RegionSceneElement = -1;
132 for (int i = 0; i < m_localScenes.Count; i++)
133 {
134 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
135 {
136 RegionSceneElement = i;
137 }
138 }
139
140 // Now we make sure the region is no longer known about by the SceneManager
141 // Prevents duplicates.
142
143 if (RegionSceneElement >= 0)
144 {
145 m_localScenes.RemoveAt(RegionSceneElement);
146 }
147
148 // Send signal to main that we're restarting this sim.
149 OnRestartSim(rdata);
150 }
151
152 public void SendSimOnlineNotification(ulong regionHandle)
153 {
154 RegionInfo Result = null;
155
156 for (int i = 0; i < m_localScenes.Count; i++)
157 {
158 if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
159 {
160 // Inform other regions to tell their avatar about me
161 Result = m_localScenes[i].RegionInfo;
162 }
163 }
164 if (Result != null)
165 {
166 for (int i = 0; i < m_localScenes.Count; i++)
167 {
168 if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle)
169 {
170 // Inform other regions to tell their avatar about me
171 //m_localScenes[i].OtherRegionUp(Result);
172 }
173 }
174 }
175 else
176 {
177 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
178 }
179 }
180
181 /// <summary>
182 /// Save the prims in the current scene to an xml file in OpenSimulator's original 'xml' format
183 /// </summary>
184 /// <param name="filename"></param>
185 public void SaveCurrentSceneToXml(string filename)
186 {
187 IRegionSerialiserModule serialiser = CurrentOrFirstScene.RequestModuleInterface<IRegionSerialiserModule>();
188 if (serialiser != null)
189 serialiser.SavePrimsToXml(CurrentOrFirstScene, filename);
190 }
191
192 /// <summary>
193 /// Load an xml file of prims in OpenSimulator's original 'xml' file format to the current scene
194 /// </summary>
195 /// <param name="filename"></param>
196 /// <param name="generateNewIDs"></param>
197 /// <param name="loadOffset"></param>
198 public void LoadCurrentSceneFromXml(string filename, bool generateNewIDs, Vector3 loadOffset)
199 {
200 IRegionSerialiserModule serialiser = CurrentOrFirstScene.RequestModuleInterface<IRegionSerialiserModule>();
201 if (serialiser != null)
202 serialiser.LoadPrimsFromXml(CurrentOrFirstScene, filename, generateNewIDs, loadOffset);
203 }
204
205 /// <summary>
206 /// Save the prims in the current scene to an xml file in OpenSimulator's current 'xml2' format
207 /// </summary>
208 /// <param name="filename"></param>
209 public void SaveCurrentSceneToXml2(string filename)
210 {
211 IRegionSerialiserModule serialiser = CurrentOrFirstScene.RequestModuleInterface<IRegionSerialiserModule>();
212 if (serialiser != null)
213 serialiser.SavePrimsToXml2(CurrentOrFirstScene, filename);
214 }
215
216 public void SaveNamedPrimsToXml2(string primName, string filename)
217 {
218 IRegionSerialiserModule serialiser = CurrentOrFirstScene.RequestModuleInterface<IRegionSerialiserModule>();
219 if (serialiser != null)
220 serialiser.SaveNamedPrimsToXml2(CurrentOrFirstScene, primName, filename);
221 }
222
223 /// <summary>
224 /// Load an xml file of prims in OpenSimulator's current 'xml2' file format to the current scene
225 /// </summary>
226 public void LoadCurrentSceneFromXml2(string filename)
227 {
228 IRegionSerialiserModule serialiser = CurrentOrFirstScene.RequestModuleInterface<IRegionSerialiserModule>();
229 if (serialiser != null)
230 serialiser.LoadPrimsFromXml2(CurrentOrFirstScene, filename);
231 }
232
233 /// <summary>
234 /// Save the current scene to an OpenSimulator archive. This archive will eventually include the prim's assets
235 /// as well as the details of the prims themselves.
236 /// </summary>
237 /// <param name="filename"></param>
238 public void SaveCurrentSceneToArchive(string filename)
239 {
240 IRegionArchiverModule archiver = CurrentOrFirstScene.RequestModuleInterface<IRegionArchiverModule>();
241 if (archiver != null)
242 archiver.ArchiveRegion(filename);
243 }
244
245 /// <summary>
246 /// Load an OpenSim archive into the current scene. This will load both the shapes of the prims and upload
247 /// their assets to the asset service.
248 /// </summary>
249 /// <param name="filename"></param>
250 public void LoadArchiveToCurrentScene(string filename)
251 {
252 IRegionArchiverModule archiver = CurrentOrFirstScene.RequestModuleInterface<IRegionArchiverModule>();
253 if (archiver != null)
254 archiver.DearchiveRegion(filename);
255 }
256
257 public string SaveCurrentSceneMapToXmlString()
258 {
259 return CurrentOrFirstScene.Heightmap.SaveToXmlString();
260 }
261
262 public void LoadCurrenSceneMapFromXmlString(string mapData)
263 {
264 CurrentOrFirstScene.Heightmap.LoadFromXmlString(mapData);
265 }
266
267 public void SendCommandToPluginModules(string[] cmdparams)
268 {
269 ForEachCurrentScene(delegate(Scene scene) { scene.SendCommandToPlugins(cmdparams); });
270 }
271
272 public void SetBypassPermissionsOnCurrentScene(bool bypassPermissions)
273 {
274 ForEachCurrentScene(delegate(Scene scene) { scene.Permissions.SetBypassPermissions(bypassPermissions); });
275 }
276
277 private void ForEachCurrentScene(Action<Scene> func)
278 {
279 if (m_currentScene == null)
280 {
281 m_localScenes.ForEach(func);
282 }
283 else
284 {
285 func(m_currentScene);
286 }
287 }
288
289 public void RestartCurrentScene()
290 {
291 ForEachCurrentScene(delegate(Scene scene) { scene.RestartNow(); });
292 }
293
294 public void BackupCurrentScene()
295 {
296 ForEachCurrentScene(delegate(Scene scene) { scene.Backup(); });
297 }
298
299 public void HandleAlertCommandOnCurrentScene(string[] cmdparams)
300 {
301 ForEachCurrentScene(delegate(Scene scene) { scene.HandleAlertCommand(cmdparams); });
302 }
303
304 public void SendGeneralMessage(string msg)
305 {
306 ForEachCurrentScene(delegate(Scene scene) { scene.HandleAlertCommand(new string[] { "general", msg }); });
307 }
308
309 public bool TrySetCurrentScene(string regionName)
310 {
311 if ((String.Compare(regionName, "root") == 0)
312 || (String.Compare(regionName, "..") == 0)
313 || (String.Compare(regionName, "/") == 0))
314 {
315 m_currentScene = null;
316 return true;
317 }
318 else
319 {
320 foreach (Scene scene in m_localScenes)
321 {
322 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
323 {
324 m_currentScene = scene;
325 return true;
326 }
327 }
328
329 return false;
330 }
331 }
332
333 public bool TrySetCurrentScene(UUID regionID)
334 {
335 Console.WriteLine("Searching for Region: '{0}'", regionID.ToString());
336
337 foreach (Scene scene in m_localScenes)
338 {
339 if (scene.RegionInfo.RegionID == regionID)
340 {
341 m_currentScene = scene;
342 return true;
343 }
344 }
345
346 return false;
347 }
348
349 public bool TryGetScene(string regionName, out Scene scene)
350 {
351 foreach (Scene mscene in m_localScenes)
352 {
353 if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
354 {
355 scene = mscene;
356 return true;
357 }
358 }
359 scene = null;
360 return false;
361 }
362
363 public bool TryGetScene(UUID regionID, out Scene scene)
364 {
365 foreach (Scene mscene in m_localScenes)
366 {
367 if (mscene.RegionInfo.RegionID == regionID)
368 {
369 scene = mscene;
370 return true;
371 }
372 }
373
374 scene = null;
375 return false;
376 }
377
378 public bool TryGetScene(uint locX, uint locY, out Scene scene)
379 {
380 foreach (Scene mscene in m_localScenes)
381 {
382 if (mscene.RegionInfo.RegionLocX == locX &&
383 mscene.RegionInfo.RegionLocY == locY)
384 {
385 scene = mscene;
386 return true;
387 }
388 }
389
390 scene = null;
391 return false;
392 }
393
394 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
395 {
396 foreach (Scene mscene in m_localScenes)
397 {
398 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
399 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
400 {
401 scene = mscene;
402 return true;
403 }
404 }
405
406 scene = null;
407 return false;
408 }
409
410 /// <summary>
411 /// Set the debug packet level on the current scene. This level governs which packets are printed out to the
412 /// console.
413 /// </summary>
414 /// <param name="newDebug"></param>
415 public void SetDebugPacketLevelOnCurrentScene(int newDebug)
416 {
417 ForEachCurrentScene(delegate(Scene scene)
418 {
419 List<ScenePresence> scenePresences = scene.GetScenePresences();
420
421 foreach (ScenePresence scenePresence in scenePresences)
422 {
423 if (!scenePresence.IsChildAgent)
424 {
425 m_log.ErrorFormat("Packet debug for {0} {1} set to {2}",
426 scenePresence.Firstname,
427 scenePresence.Lastname,
428 newDebug);
429
430 scenePresence.ControllingClient.SetDebugPacketLevel(newDebug);
431 }
432 }
433 });
434 }
435
436 public List<ScenePresence> GetCurrentSceneAvatars()
437 {
438 List<ScenePresence> avatars = new List<ScenePresence>();
439
440 ForEachCurrentScene(delegate(Scene scene)
441 {
442 List<ScenePresence> scenePresences = scene.GetScenePresences();
443
444 foreach (ScenePresence scenePresence in scenePresences)
445 {
446 if (!scenePresence.IsChildAgent)
447 {
448 avatars.Add(scenePresence);
449 }
450 }
451 });
452
453 return avatars;
454 }
455
456 public List<ScenePresence> GetCurrentScenePresences()
457 {
458 List<ScenePresence> presences = new List<ScenePresence>();
459
460 ForEachCurrentScene(delegate(Scene scene)
461 {
462 List<ScenePresence> scenePresences = scene.GetScenePresences();
463 presences.AddRange(scenePresences);
464 });
465
466 return presences;
467 }
468
469 public RegionInfo GetRegionInfo(ulong regionHandle)
470 {
471 foreach (Scene scene in m_localScenes)
472 {
473 if (scene.RegionInfo.RegionHandle == regionHandle)
474 {
475 return scene.RegionInfo;
476 }
477 }
478
479 return null;
480 }
481
482 public void ForceCurrentSceneClientUpdate()
483 {
484 ForEachCurrentScene(delegate(Scene scene) { scene.ForceClientUpdate(); });
485 }
486
487 public void HandleEditCommandOnCurrentScene(string[] cmdparams)
488 {
489 ForEachCurrentScene(delegate(Scene scene) { scene.HandleEditCommand(cmdparams); });
490 }
491
492 public bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
493 {
494 foreach (Scene scene in m_localScenes)
495 {
496 if (scene.TryGetAvatar(avatarId, out avatar))
497 {
498 return true;
499 }
500 }
501
502 avatar = null;
503 return false;
504 }
505
506 public bool TryGetAvatarsScene(UUID avatarId, out Scene scene)
507 {
508 ScenePresence avatar = null;
509 foreach (Scene mScene in m_localScenes)
510 {
511 if (mScene.TryGetAvatar(avatarId, out avatar))
512 {
513 scene = mScene;
514 return true;
515 }
516 }
517
518 scene = null;
519 return false;
520 }
521
522 public void CloseScene(Scene scene)
523 {
524 m_localScenes.Remove(scene);
525 scene.Close();
526 }
527
528 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
529 {
530 foreach (Scene scene in m_localScenes)
531 {
532 if (scene.TryGetAvatarByName(avatarName, out avatar))
533 {
534 return true;
535 }
536 }
537
538 avatar = null;
539 return false;
540 }
541
542 public void ForEachScene(Action<Scene> action)
543 {
544 m_localScenes.ForEach(action);
545 }
546
547 public void CacheJ2kDecode(int threads)
548 {
549 if (threads < 1) threads = 1;
550
551 IJ2KDecoder m_decoder = m_localScenes[0].RequestModuleInterface<IJ2KDecoder>();
552
553 List<UUID> assetRequestList = new List<UUID>();
554
555 #region AssetGathering!
556 foreach (Scene scene in m_localScenes)
557 {
558 List<EntityBase> entitles = scene.GetEntities();
559 foreach (EntityBase entity in entitles)
560 {
561 if (entity is SceneObjectGroup)
562 {
563 SceneObjectGroup sog = (SceneObjectGroup) entity;
564 foreach (SceneObjectPart part in sog.Children.Values)
565 {
566 if (part.Shape != null)
567 {
568 if (part.Shape.TextureEntry.Length > 0)
569 {
570 OpenMetaverse.Primitive.TextureEntry te =
571 new Primitive.TextureEntry(part.Shape.TextureEntry, 0,
572 part.Shape.TextureEntry.Length);
573 if (te.DefaultTexture != null) // this has been null for some reason...
574 {
575 if (te.DefaultTexture.TextureID != UUID.Zero)
576 assetRequestList.Add(te.DefaultTexture.TextureID);
577 }
578 for (int i=0; i<te.FaceTextures.Length; i++)
579 {
580 if (te.FaceTextures[i] != null)
581 {
582 if (te.FaceTextures[i].TextureID != UUID.Zero)
583 {
584 assetRequestList.Add(te.FaceTextures[i].TextureID);
585 }
586 }
587 }
588 }
589 if (part.Shape.SculptTexture != UUID.Zero)
590 {
591 assetRequestList.Add(part.Shape.SculptTexture);
592 }
593
594 }
595 }
596 }
597 }
598 }
599 #endregion
600
601 int entries_per_thread = (assetRequestList.Count / threads) + 1;
602
603 UUID[] arrAssetRequestList = assetRequestList.ToArray();
604
605 List<UUID[]> arrvalus = new List<UUID[]>();
606
607 //split into separate arrays
608 for (int j = 0; j < threads; j++)
609 {
610 List<UUID> val = new List<UUID>();
611
612 for (int k = j * entries_per_thread; k < ((j + 1) * entries_per_thread); k++)
613 {
614 if (k < arrAssetRequestList.Length)
615 {
616 val.Add(arrAssetRequestList[k]);
617 }
618
619 }
620 arrvalus.Add(val.ToArray());
621 }
622
623 for (int l = 0; l < arrvalus.Count; l++)
624 {
625 DecodeThreadContents threadworkItem = new DecodeThreadContents();
626 threadworkItem.sn = m_localScenes[0];
627 threadworkItem.j2kdecode = m_decoder;
628 threadworkItem.arrassets = arrvalus[l];
629
630 System.Threading.Thread decodethread =
631 new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(threadworkItem.run));
632
633 threadworkItem.SetThread(decodethread);
634
635 decodethread.Priority = System.Threading.ThreadPriority.Lowest;
636 decodethread.Name = "J2kCacheDecodeThread_" + l + 1;
637 ThreadTracker.Add(decodethread);
638 decodethread.Start();
639
640 }
641 }
642 }
643
644 public class DecodeThreadContents
645 {
646 public Scene sn;
647 public UUID[] arrassets;
648 public IJ2KDecoder j2kdecode;
649 private System.Threading.Thread thisthread;
650
651 public void run( object o)
652 {
653 for (int i=0;i<arrassets.Length;i++)
654 {
655 AssetBase ab = sn.AssetCache.GetAsset(arrassets[i], true);
656 if (ab != null && ab.Data != null)
657 {
658 j2kdecode.syncdecode(arrassets[i], ab.Data);
659 }
660 }
661 ThreadTracker.Remove(thisthread);
662 }
663
664 public void SetThread(System.Threading.Thread thr)
665 {
666 thisthread = thr;
667 }
668 }
669}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs
deleted file mode 100644
index 053e0da..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs
+++ /dev/null
@@ -1,401 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.Environment.Interfaces;
35using System.Collections.Generic;
36using System.Xml;
37
38namespace OpenSim.Region.Environment.Scenes
39{
40 public partial class SceneObjectGroup : EntityBase
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 /// <summary>
45 /// Force all task inventories of prims in the scene object to persist
46 /// </summary>
47 public void ForceInventoryPersistence()
48 {
49 lock (m_parts)
50 {
51 foreach (SceneObjectPart part in m_parts.Values)
52 {
53 part.Inventory.ForceInventoryPersistence();
54 }
55 }
56 }
57
58 /// <summary>
59 /// Start the scripts contained in all the prims in this group.
60 /// </summary>
61 public void CreateScriptInstances(int startParam, bool postOnRez,
62 string engine, int stateSource)
63 {
64 // Don't start scripts if they're turned off in the region!
65 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
66 {
67 foreach (SceneObjectPart part in m_parts.Values)
68 {
69 part.Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource);
70 }
71 }
72 }
73
74 /// <summary>
75 /// Stop the scripts contained in all the prims in this group
76 /// </summary>
77 public void RemoveScriptInstances()
78 {
79 lock (m_parts)
80 {
81 foreach (SceneObjectPart part in m_parts.Values)
82 {
83 part.Inventory.RemoveScriptInstances();
84 }
85 }
86 }
87
88 /// <summary>
89 ///
90 /// </summary>
91 /// <param name="remoteClient"></param>
92 /// <param name="localID"></param>
93 public bool GetPartInventoryFileName(IClientAPI remoteClient, uint localID)
94 {
95 SceneObjectPart part = GetChildPart(localID);
96 if (part != null)
97 {
98 return part.Inventory.GetInventoryFileName(remoteClient, localID);
99 }
100 else
101 {
102 m_log.ErrorFormat(
103 "[PRIM INVENTORY]: " +
104 "Couldn't find part {0} in object group {1}, {2} to retreive prim inventory",
105 localID, Name, UUID);
106 }
107 return false;
108 }
109
110 /// <summary>
111 /// Return serialized inventory metadata for the given constituent prim
112 /// </summary>
113 /// <param name="localID"></param>
114 /// <param name="xferManager"></param>
115 public void RequestInventoryFile(IClientAPI client, uint localID, IXfer xferManager)
116 {
117 SceneObjectPart part = GetChildPart(localID);
118 if (part != null)
119 {
120 part.Inventory.RequestInventoryFile(client, xferManager);
121 }
122 else
123 {
124 m_log.ErrorFormat(
125 "[PRIM INVENTORY]: " +
126 "Couldn't find part {0} in object group {1}, {2} to request inventory data",
127 localID, Name, UUID);
128 }
129 }
130
131 /// <summary>
132 /// Add an inventory item to a prim in this group.
133 /// </summary>
134 /// <param name="remoteClient"></param>
135 /// <param name="localID"></param>
136 /// <param name="item"></param>
137 /// <param name="copyItemID">The item UUID that should be used by the new item.</param>
138 /// <returns></returns>
139 public bool AddInventoryItem(IClientAPI remoteClient, uint localID,
140 InventoryItemBase item, UUID copyItemID)
141 {
142 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
143
144 SceneObjectPart part = GetChildPart(localID);
145 if (part != null)
146 {
147 TaskInventoryItem taskItem = new TaskInventoryItem();
148
149 taskItem.ItemID = newItemId;
150 taskItem.AssetID = item.AssetID;
151 taskItem.Name = item.Name;
152 taskItem.Description = item.Description;
153 taskItem.OwnerID = part.OwnerID; // Transfer ownership
154 taskItem.CreatorID = item.Creator;
155 taskItem.Type = item.AssetType;
156 taskItem.InvType = item.InvType;
157
158 if (remoteClient != null &&
159 remoteClient.AgentId != part.OwnerID &&
160 m_scene.Permissions.PropagatePermissions())
161 {
162 taskItem.BasePermissions = item.BasePermissions &
163 item.NextPermissions;
164 taskItem.CurrentPermissions = item.CurrentPermissions &
165 item.NextPermissions;
166 taskItem.EveryonePermissions = item.EveryOnePermissions &
167 item.NextPermissions;
168 taskItem.GroupPermissions = item.GroupPermissions &
169 item.NextPermissions;
170 taskItem.NextPermissions = item.NextPermissions;
171 taskItem.CurrentPermissions |= 8;
172 } else {
173 taskItem.BasePermissions = item.BasePermissions;
174 taskItem.CurrentPermissions = item.CurrentPermissions;
175 taskItem.CurrentPermissions |= 8;
176 taskItem.EveryonePermissions = item.EveryOnePermissions;
177 taskItem.GroupPermissions = item.GroupPermissions;
178 taskItem.NextPermissions = item.NextPermissions;
179 }
180
181 taskItem.Flags = item.Flags;
182 // TODO: These are pending addition of those fields to TaskInventoryItem
183// taskItem.SalePrice = item.SalePrice;
184// taskItem.SaleType = item.SaleType;
185 taskItem.CreationDate = (uint)item.CreationDate;
186
187 bool addFromAllowedDrop = false;
188 if (remoteClient!=null)
189 {
190 addFromAllowedDrop = remoteClient.AgentId != part.OwnerID;
191 }
192
193 part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop);
194
195 return true;
196 }
197 else
198 {
199 m_log.ErrorFormat(
200 "[PRIM INVENTORY]: " +
201 "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}",
202 localID, Name, UUID, newItemId);
203 }
204
205 return false;
206 }
207
208 /// <summary>
209 /// Returns an existing inventory item. Returns the original, so any changes will be live.
210 /// </summary>
211 /// <param name="primID"></param>
212 /// <param name="itemID"></param>
213 /// <returns>null if the item does not exist</returns>
214 public TaskInventoryItem GetInventoryItem(uint primID, UUID itemID)
215 {
216 SceneObjectPart part = GetChildPart(primID);
217 if (part != null)
218 {
219 return part.Inventory.GetInventoryItem(itemID);
220 }
221 else
222 {
223 m_log.ErrorFormat(
224 "[PRIM INVENTORY]: " +
225 "Couldn't find prim local ID {0} in prim {1}, {2} to get inventory item ID {3}",
226 primID, part.Name, part.UUID, itemID);
227 }
228
229 return null;
230 }
231
232 /// <summary>
233 /// Update an existing inventory item.
234 /// </summary>
235 /// <param name="item">The updated item. An item with the same id must already exist
236 /// in this prim's inventory</param>
237 /// <returns>false if the item did not exist, true if the update occurred succesfully</returns>
238 public bool UpdateInventoryItem(TaskInventoryItem item)
239 {
240 SceneObjectPart part = GetChildPart(item.ParentPartID);
241 if (part != null)
242 {
243 part.Inventory.UpdateInventoryItem(item);
244
245 return true;
246 }
247 else
248 {
249 m_log.ErrorFormat(
250 "[PRIM INVENTORY]: " +
251 "Couldn't find prim ID {0} to update item {1}, {2}",
252 item.ParentPartID, item.Name, item.ItemID);
253 }
254
255 return false;
256 }
257
258 public int RemoveInventoryItem(uint localID, UUID itemID)
259 {
260 SceneObjectPart part = GetChildPart(localID);
261 if (part != null)
262 {
263 int type = part.Inventory.RemoveInventoryItem(itemID);
264
265 return type;
266 }
267
268 return -1;
269 }
270
271 public uint GetEffectivePermissions()
272 {
273 uint perms=(uint)(PermissionMask.Modify |
274 PermissionMask.Copy |
275 PermissionMask.Move |
276 PermissionMask.Transfer) | 7;
277
278 uint ownerMask = 0x7ffffff;
279 foreach (SceneObjectPart part in m_parts.Values)
280 {
281 ownerMask &= part.OwnerMask;
282 perms &= part.Inventory.MaskEffectivePermissions();
283 }
284
285 if ((ownerMask & (uint)PermissionMask.Modify) == 0)
286 perms &= ~(uint)PermissionMask.Modify;
287 if ((ownerMask & (uint)PermissionMask.Copy) == 0)
288 perms &= ~(uint)PermissionMask.Copy;
289 if ((ownerMask & (uint)PermissionMask.Transfer) == 0)
290 perms &= ~(uint)PermissionMask.Transfer;
291
292 if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0)
293 perms &= ~((uint)PermissionMask.Modify >> 13);
294 if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0)
295 perms &= ~((uint)PermissionMask.Copy >> 13);
296 if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0)
297 perms &= ~((uint)PermissionMask.Transfer >> 13);
298
299 return perms;
300 }
301
302 public void ApplyNextOwnerPermissions()
303 {
304 foreach (SceneObjectPart part in m_parts.Values)
305 {
306 part.ApplyNextOwnerPermissions();
307 }
308 }
309
310 public string GetStateSnapshot()
311 {
312 List<string> assemblies = new List<string>();
313 Dictionary<UUID, string> states = new Dictionary<UUID, string>();
314
315 foreach (SceneObjectPart part in m_parts.Values)
316 {
317 foreach (string a in part.Inventory.GetScriptAssemblies())
318 {
319 if (a != "" && !assemblies.Contains(a))
320 assemblies.Add(a);
321 }
322
323 foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates())
324 {
325 states[s.Key] = s.Value;
326 }
327 }
328
329 if (states.Count < 1 || assemblies.Count < 1)
330 return "";
331
332 XmlDocument xmldoc = new XmlDocument();
333
334 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
335 "", "");
336
337 xmldoc.AppendChild(xmlnode);
338 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData",
339 "");
340
341 xmldoc.AppendChild(rootElement);
342
343 XmlElement wrapper = xmldoc.CreateElement("", "Assemblies",
344 "");
345
346 rootElement.AppendChild(wrapper);
347
348 foreach (string assembly in assemblies)
349 {
350 string fn = Path.GetFileName(assembly);
351 if (fn == String.Empty)
352 continue;
353
354 FileInfo fi = new FileInfo(assembly);
355
356 if (fi == null)
357 continue;
358
359 Byte[] data = new Byte[fi.Length];
360
361 FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read);
362 fs.Read(data, 0, data.Length);
363 fs.Close();
364
365 XmlElement assemblyData = xmldoc.CreateElement("", "Assembly", "");
366 XmlAttribute assemblyName = xmldoc.CreateAttribute("", "Filename", "");
367 assemblyName.Value = fn;
368 assemblyData.Attributes.Append(assemblyName);
369
370 assemblyData.InnerText = System.Convert.ToBase64String(data);
371
372 wrapper.AppendChild(assemblyData);
373 }
374
375 wrapper = xmldoc.CreateElement("", "ScriptStates",
376 "");
377
378 rootElement.AppendChild(wrapper);
379
380 foreach (KeyValuePair<UUID, string> state in states)
381 {
382 XmlElement stateData = xmldoc.CreateElement("", "State", "");
383
384 XmlAttribute stateID = xmldoc.CreateAttribute("", "UUID", "");
385 stateID.Value = state.Key.ToString();
386 stateData.Attributes.Append(stateID);
387
388 XmlDocument sdoc = new XmlDocument();
389 sdoc.LoadXml(state.Value);
390 XmlNodeList rootL = sdoc.GetElementsByTagName("ScriptState");
391 XmlNode rootNode = rootL[0];
392
393 XmlNode newNode = xmldoc.ImportNode(rootNode, true);
394 stateData.AppendChild(newNode);
395 wrapper.AppendChild(stateData);
396 }
397
398 return xmldoc.InnerXml;
399 }
400 }
401}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
deleted file mode 100644
index 5ae95ee..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ /dev/null
@@ -1,3012 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.IO;
32using System.Xml;
33using System.Xml.Serialization;
34using OpenMetaverse;
35using OpenMetaverse.Packets;
36using OpenSim.Framework;
37using OpenSim.Region.Environment.Interfaces;
38using OpenSim.Region.Physics.Manager;
39
40namespace OpenSim.Region.Environment.Scenes
41{
42 [Flags]
43 public enum scriptEvents
44 {
45 None = 0,
46 attach = 1,
47 collision = 16,
48 collision_end = 32,
49 collision_start = 64,
50 control = 128,
51 dataserver = 256,
52 email = 512,
53 http_response = 1024,
54 land_collision = 2048,
55 land_collision_end = 4096,
56 land_collision_start = 8192,
57 at_target = 16384,
58 listen = 32768,
59 money = 65536,
60 moving_end = 131072,
61 moving_start = 262144,
62 not_at_rot_target = 524288,
63 not_at_target = 1048576,
64 remote_data = 8388608,
65 run_time_permissions = 268435456,
66 state_entry = 1073741824,
67 state_exit = 2,
68 timer = 4,
69 touch = 8,
70 touch_end = 536870912,
71 touch_start = 2097152,
72 object_rez = 4194304
73 }
74
75 struct scriptPosTarget
76 {
77 public Vector3 targetPos;
78 public float tolerance;
79 }
80
81 public delegate void PrimCountTaintedDelegate();
82
83 /// <summary>
84 /// A scene object group is conceptually an object in the scene. The object is constituted of SceneObjectParts
85 /// (often known as prims), one of which is considered the root part.
86 /// </summary>
87 public partial class SceneObjectGroup : EntityBase
88 {
89 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
90
91 /// <summary>
92 /// Signal whether the non-inventory attributes of any prims in the group have changed
93 /// since the group's last persistent backup
94 /// </summary>
95 private bool m_hasGroupChanged = false;
96 private long timeFirstChanged;
97 private long timeLastChanged;
98
99 public bool HasGroupChanged
100 {
101 set
102 {
103 if (value)
104 {
105 timeLastChanged = DateTime.Now.Ticks;
106 if (!m_hasGroupChanged)
107 timeFirstChanged = DateTime.Now.Ticks;
108 }
109 m_hasGroupChanged = value;
110 }
111
112 get { return m_hasGroupChanged; }
113 }
114
115 private bool isTimeToPersist()
116 {
117 if (IsSelected || IsDeleted || IsAttachment)
118 return false;
119 if (!m_hasGroupChanged)
120 return false;
121 if (m_scene.ShuttingDown)
122 return true;
123 long currentTime = DateTime.Now.Ticks;
124 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter)
125 return true;
126 return false;
127 }
128
129 /// <value>
130 /// Is this scene object acting as an attachment?
131 ///
132 /// We return false if the group has already been deleted.
133 ///
134 /// TODO: At the moment set must be done on the part itself. There may be a case for doing it here since I
135 /// presume either all or no parts in a linkset can be part of an attachment (in which
136 /// case the value would get proprogated down into all the descendent parts).
137 /// </value>
138 public bool IsAttachment
139 {
140 get
141 {
142 if (!IsDeleted)
143 return m_rootPart.IsAttachment;
144
145 return false;
146 }
147 }
148
149 public float scriptScore = 0f;
150
151 private Vector3 lastPhysGroupPos;
152 private Quaternion lastPhysGroupRot;
153
154 private bool m_isBackedUp = false;
155
156 /// <summary>
157 /// The constituent parts of this group
158 /// </summary>
159 protected Dictionary<UUID, SceneObjectPart> m_parts = new Dictionary<UUID, SceneObjectPart>();
160
161 protected ulong m_regionHandle;
162 protected SceneObjectPart m_rootPart;
163 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
164
165 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
166
167 private bool m_scriptListens_atTarget = false;
168 private bool m_scriptListens_notAtTarget = false;
169
170 #region Properties
171
172 /// <summary>
173 /// The name of an object grouping is always the same as its root part
174 /// </summary>
175 public override string Name
176 {
177 get {
178 if (RootPart == null)
179 return "";
180 return RootPart.Name;
181 }
182 set { RootPart.Name = value; }
183 }
184
185 /// <summary>
186 /// Added because the Parcel code seems to use it
187 /// but not sure a object should have this
188 /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
189 /// think really there should be a list (or whatever) in each scenepresence
190 /// saying what prim(s) that user has selected.
191 /// </summary>
192 protected bool m_isSelected = false;
193
194 /// <summary>
195 /// Number of prims in this group
196 /// </summary>
197 public int PrimCount
198 {
199 get { return m_parts.Count; }
200 }
201
202 public Quaternion GroupRotation
203 {
204 get { return m_rootPart.RotationOffset; }
205 }
206
207 public UUID GroupID
208 {
209 get { return m_rootPart.GroupID; }
210 set { m_rootPart.GroupID = value; }
211 }
212
213 public Dictionary<UUID, SceneObjectPart> Children
214 {
215 get { return m_parts; }
216 set { m_parts = value; }
217 }
218
219 /// <value>
220 /// The root part of this scene object
221 /// </value>
222 public SceneObjectPart RootPart
223 {
224 get { return m_rootPart; }
225 }
226
227 public ulong RegionHandle
228 {
229 get { return m_regionHandle; }
230 set
231 {
232 m_regionHandle = value;
233 lock (m_parts)
234 {
235 foreach (SceneObjectPart part in m_parts.Values)
236 {
237 part.RegionHandle = m_regionHandle;
238 }
239 }
240 }
241 }
242
243 /// <summary>
244 /// The absolute position of this scene object in the scene
245 /// </summary>
246 public override Vector3 AbsolutePosition
247 {
248 get
249 {
250 if (m_rootPart == null)
251 {
252 throw new NullReferenceException(
253 string.Format("[SCENE OBJECT GROUP]: Object {0} has no root part.", m_uuid));
254 }
255
256 return m_rootPart.GroupPosition;
257 }
258 set
259 {
260 Vector3 val = value;
261
262 if ((val.X > 257f || val.X < -1f || val.Y > 257f || val.Y < -1f) && !IsAttachment)
263 {
264 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
265 }
266
267 lock (m_parts)
268 {
269 foreach (SceneObjectPart part in m_parts.Values)
270 {
271 part.GroupPosition = val;
272 }
273 }
274
275 //if (m_rootPart.PhysActor != null)
276 //{
277 //m_rootPart.PhysActor.Position =
278 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
279 //m_rootPart.GroupPosition.Z);
280 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
281 //}
282 }
283 }
284
285 public override uint LocalId
286 {
287 get
288 {
289 if (m_rootPart == null)
290 {
291 m_log.Error("[SCENE OBJECT GROUP]: Unable to find the rootpart for a LocalId Request!");
292 return 0;
293 }
294
295 return m_rootPart.LocalId;
296 }
297 set { m_rootPart.LocalId = value; }
298 }
299
300 public override UUID UUID
301 {
302 get {
303 if (m_rootPart == null)
304 {
305 m_log.Error("Got a null rootpart while requesting UUID. Called from: ", new Exception());
306 return UUID.Zero;
307 }
308 else return m_rootPart.UUID;
309 }
310 set { m_rootPart.UUID = value; }
311 }
312
313 public UUID OwnerID
314 {
315 get
316 {
317 if (m_rootPart == null)
318 return UUID.Zero;
319
320 return m_rootPart.OwnerID;
321 }
322 set { m_rootPart.OwnerID = value; }
323 }
324
325 public Color Color
326 {
327 get { return m_rootPart.Color; }
328 set { m_rootPart.Color = value; }
329 }
330
331 public string Text
332 {
333 get {
334 string returnstr = m_rootPart.Text;
335 if (returnstr.Length > 255)
336 {
337 returnstr = returnstr.Substring(0, 255);
338 }
339 return returnstr;
340 }
341 set { m_rootPart.Text = value; }
342 }
343
344 protected virtual bool InSceneBackup
345 {
346 get { return true; }
347 }
348
349 public bool IsSelected
350 {
351 get { return m_isSelected; }
352 set
353 {
354 m_isSelected = value;
355 // Tell physics engine that group is selected
356 if (m_rootPart != null && m_rootPart.PhysActor != null)
357 {
358 m_rootPart.PhysActor.Selected = value;
359 // Pass it on to the children.
360 foreach (SceneObjectPart child in Children.Values)
361 {
362 if (child.PhysActor != null)
363 {
364 child.PhysActor.Selected = value;
365 }
366 }
367 }
368 }
369 }
370
371 // The UUID for the Region this Object is in.
372 public UUID RegionUUID
373 {
374 get
375 {
376 if (m_scene != null)
377 {
378 return m_scene.RegionInfo.RegionID;
379 }
380 return UUID.Zero;
381 }
382 }
383
384 #endregion
385
386 #region Constructors
387
388 /// <summary>
389 /// Constructor
390 /// </summary>
391 public SceneObjectGroup()
392 {
393 }
394
395 /// <summary>
396 /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
397 /// The original SceneObjectPart will be used rather than a copy, preserving
398 /// its existing localID and UUID.
399 /// </summary>
400 public SceneObjectGroup(SceneObjectPart part)
401 {
402 SetRootPart(part);
403 }
404
405 public SceneObjectGroup(string xmlData, bool isOriginalXmlFormat)
406 : this(UUID.Zero, xmlData, isOriginalXmlFormat)
407 {
408 }
409
410 /// <summary>
411 /// Create an object using serialized data in OpenSim's original xml format.
412 /// </summary>
413 /// <param name="fromUserInventoryItemID">
414 /// If applicable, the user inventory item id from which this object was rezzed. If not applicable then this
415 /// should be UUID.Zero
416 /// </param>
417 /// <param name="xmlData"></param>
418 /// <param name="isOriginalXmlFormat">
419 /// This parameter only exists to separate the two different xml constructors. In the future, versions should
420 /// be specified within the xml itself.
421 /// </param>
422 public SceneObjectGroup(UUID fromUserInventoryItemID, string xmlData, bool isOriginalXmlFormat)
423 {
424 if (!isOriginalXmlFormat)
425 throw new Exception("This constructor must specify the xml is in OpenSim's original format");
426
427 //m_log.DebugFormat("[SOG]: Starting deserialization of SOG");
428 int time = System.Environment.TickCount;
429
430 // libomv.types changes UUID to Guid
431 xmlData = xmlData.Replace("<UUID>", "<Guid>");
432 xmlData = xmlData.Replace("</UUID>", "</Guid>");
433
434 // Handle Nested <UUID><UUID> property
435 xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>");
436 xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>");
437 StringReader sr = new StringReader(xmlData);
438 XmlTextReader reader = new XmlTextReader(sr);
439
440 try
441 {
442 reader.Read();
443 reader.ReadStartElement("SceneObjectGroup");
444 reader.ReadStartElement("RootPart");
445 SetRootPart(SceneObjectPart.FromXml(fromUserInventoryItemID, reader));
446
447 reader.ReadEndElement();
448
449 while (reader.Read())
450 {
451 switch (reader.NodeType)
452 {
453 case XmlNodeType.Element:
454 if (reader.Name == "Part")
455 {
456 reader.Read();
457 SceneObjectPart part = SceneObjectPart.FromXml(reader);
458
459 // We reset the link number in order to make sure that the persisted linkset order is
460 int linkNum = part.LinkNum;
461 AddPart(part);
462 part.LinkNum = linkNum;
463
464 part.TrimPermissions();
465 part.StoreUndoState();
466 }
467 break;
468
469 case XmlNodeType.EndElement:
470 break;
471 }
472 }
473 }
474 catch (XmlException e)
475 {
476 m_log.ErrorFormat("[SCENE]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData);
477 }
478
479 reader.Close();
480 sr.Close();
481 m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
482 }
483
484 /// <summary>
485 /// Create an object using serialized data in OpenSim's xml2 format.
486 /// </summary>
487 public SceneObjectGroup(string xmlData)
488 {
489 SetFromXml(xmlData);
490 }
491
492 protected void SetFromXml(string xmlData)
493 {
494 //m_log.DebugFormat("[SOG]: Starting deserialization of SOG");
495 //int time = System.Environment.TickCount;
496
497 // libomv.types changes UUID to Guid
498 xmlData = xmlData.Replace("<UUID>", "<Guid>");
499 xmlData = xmlData.Replace("</UUID>", "</Guid>");
500
501 // Handle Nested <UUID><UUID> property
502 xmlData = xmlData.Replace("<Guid><Guid>", "<UUID><Guid>");
503 xmlData = xmlData.Replace("</Guid></Guid>", "</Guid></UUID>");
504
505 StringReader sr = new StringReader(xmlData);
506 XmlTextReader reader = new XmlTextReader(sr);
507 reader.Read();
508
509 reader.ReadStartElement("SceneObjectGroup");
510 SetRootPart(CreatePartFromXml(reader));
511
512 reader.Read();
513 bool more = true;
514
515 while (more)
516 {
517 switch (reader.NodeType)
518 {
519 case XmlNodeType.Element:
520 if (reader.Name == "SceneObjectPart")
521 {
522 SceneObjectPart part = CreatePartFromXml(reader);
523 AddPart(part);
524 part.StoreUndoState();
525 }
526 else
527 {
528 Console.WriteLine("found unexpected element: " + reader.Name);
529 reader.Read();
530 }
531 break;
532 case XmlNodeType.EndElement:
533 reader.Read();
534 break;
535 }
536 more = !reader.EOF;
537 }
538
539 reader.Close();
540 sr.Close();
541
542 //m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
543 }
544
545 protected virtual SceneObjectPart CreatePartFromXml(XmlTextReader reader)
546 {
547 SceneObjectPart part = SceneObjectPart.FromXml(reader);
548 return part;
549 }
550
551 /// <summary>
552 /// Constructor. This object is added to the scene later via AttachToScene()
553 /// </summary>
554 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
555 {
556 Vector3 rootOffset = new Vector3(0, 0, 0);
557 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, rootOffset));
558 }
559
560 /// <summary>
561 /// Constructor.
562 /// </summary>
563 public SceneObjectGroup(UUID ownerID, Vector3 pos, PrimitiveBaseShape shape)
564 : this(ownerID, pos, Quaternion.Identity, shape)
565 {
566 }
567
568 public void SetFromAssetID(UUID AssetId)
569 {
570 lock (m_parts)
571 {
572 foreach (SceneObjectPart part in m_parts.Values)
573 {
574 part.FromAssetID = AssetId;
575 }
576 }
577 }
578
579 public UUID GetFromAssetID()
580 {
581 if (m_rootPart != null)
582 {
583 return m_rootPart.FromAssetID;
584 }
585 return UUID.Zero;
586 }
587
588 /// <summary>
589 /// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes.
590 /// </summary>
591 public void AttachToBackup()
592 {
593 if (InSceneBackup)
594 {
595 //m_log.DebugFormat(
596 // "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
597
598 if (!m_isBackedUp)
599 m_scene.EventManager.OnBackup += ProcessBackup;
600
601 m_isBackedUp = true;
602 }
603 }
604
605 /// <summary>
606 /// Attach this object to a scene. It will also now appear to agents.
607 /// </summary>
608 /// <param name="scene"></param>
609 public void AttachToScene(Scene scene)
610 {
611 m_scene = scene;
612 RegionHandle = m_scene.RegionInfo.RegionHandle;
613
614 if (m_rootPart.Shape.PCode != 9 || m_rootPart.Shape.State == 0)
615 m_rootPart.ParentID = 0;
616 if (m_rootPart.LocalId==0)
617 m_rootPart.LocalId = m_scene.AllocateLocalId();
618
619 // No need to lock here since the object isn't yet in a scene
620 foreach (SceneObjectPart part in m_parts.Values)
621 {
622 if (Object.ReferenceEquals(part, m_rootPart))
623 continue;
624 if (part.LocalId==0)
625 part.LocalId = m_scene.AllocateLocalId();
626 part.ParentID = m_rootPart.LocalId;
627 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
628 }
629
630 ApplyPhysics(m_scene.m_physicalPrim);
631
632 ScheduleGroupForFullUpdate();
633 }
634
635 public Vector3 GroupScale()
636 {
637 Vector3 minScale = new Vector3(Constants.RegionSize,Constants.RegionSize,Constants.RegionSize);
638 Vector3 maxScale = new Vector3(0f,0f,0f);
639 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
640
641 lock (m_parts)
642 {
643 foreach (SceneObjectPart part in m_parts.Values)
644 {
645 Vector3 partscale = part.Scale;
646 Vector3 partoffset = part.OffsetPosition;
647
648 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
649 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.X + partoffset.Y : minScale.Y;
650 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.X + partoffset.Z : minScale.Z;
651
652 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
653 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
654 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
655 }
656 }
657 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
658 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
659 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
660 return finalScale;
661
662 }
663 public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
664 {
665 // We got a request from the inner_scene to raytrace along the Ray hRay
666 // We're going to check all of the prim in this group for intersection with the ray
667 // If we get a result, we're going to find the closest result to the origin of the ray
668 // and send back the intersection information back to the innerscene.
669
670 EntityIntersection returnresult = new EntityIntersection();
671
672 lock (m_parts)
673 {
674 foreach (SceneObjectPart part in m_parts.Values)
675 {
676 // Temporary commented to stop compiler warning
677 //Vector3 partPosition =
678 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
679 Quaternion parentrotation = GroupRotation;
680
681 // Telling the prim to raytrace.
682 //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
683
684 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation,frontFacesOnly, faceCenters);
685
686 // This may need to be updated to the maximum draw distance possible..
687 // We might (and probably will) be checking for prim creation from other sims
688 // when the camera crosses the border.
689 float idist = Constants.RegionSize;
690
691
692 if (inter.HitTF)
693 {
694 // We need to find the closest prim to return to the testcaller along the ray
695 if (inter.distance < idist)
696 {
697 returnresult.HitTF = true;
698 returnresult.ipoint = inter.ipoint;
699 returnresult.obj = part;
700 returnresult.normal = inter.normal;
701 returnresult.distance = inter.distance;
702 }
703 }
704 }
705 }
706 return returnresult;
707 }
708
709 #endregion
710
711
712 public string ToXmlString()
713 {
714 using (StringWriter sw = new StringWriter())
715 {
716 using (XmlTextWriter writer = new XmlTextWriter(sw))
717 {
718 ToXml(writer);
719 }
720
721 return sw.ToString();
722 }
723 }
724
725 public void ToXml(XmlTextWriter writer)
726 {
727 m_log.DebugFormat("[SOG]: Starting serialization of {0}", Name);
728 int time = System.Environment.TickCount;
729
730 writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
731 writer.WriteStartElement(String.Empty, "RootPart", String.Empty);
732 m_rootPart.ToXml(writer);
733 writer.WriteEndElement();
734 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
735
736 lock (m_parts)
737 {
738 foreach (SceneObjectPart part in m_parts.Values)
739 {
740 if (part.UUID != m_rootPart.UUID)
741 {
742 writer.WriteStartElement(String.Empty, "Part", String.Empty);
743 part.ToXml(writer);
744 writer.WriteEndElement();
745 }
746 }
747 }
748
749 writer.WriteEndElement();
750 writer.WriteEndElement();
751
752 m_log.DebugFormat("[SOG]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
753
754 }
755
756 public string ToXmlString2()
757 {
758 using (StringWriter sw = new StringWriter())
759 {
760 using (XmlTextWriter writer = new XmlTextWriter(sw))
761 {
762 ToXml2(writer);
763 }
764
765 return sw.ToString();
766 }
767 }
768
769 public void ToXml2(XmlTextWriter writer)
770 {
771 m_log.DebugFormat("[SOG]: Starting serialization of SOG {0} to XML2", Name);
772 int time = System.Environment.TickCount;
773
774 writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
775 m_rootPart.ToXml(writer);
776 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
777
778 lock (m_parts)
779 {
780 foreach (SceneObjectPart part in m_parts.Values)
781 {
782 if (part.UUID != m_rootPart.UUID)
783 {
784 part.ToXml(writer);
785 }
786 }
787 }
788
789 writer.WriteEndElement();
790 writer.WriteEndElement();
791 m_log.DebugFormat("[SOG]: Finished serialization of SOG {0} to XML2, {1}ms", Name, System.Environment.TickCount - time);
792 }
793
794 /// <summary>
795 /// Attach this scene object to the given avatar.
796 /// </summary>
797 /// <param name="agentID"></param>
798 /// <param name="attachmentpoint"></param>
799 /// <param name="AttachOffset"></param>
800 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
801 {
802 ScenePresence avatar = m_scene.GetScenePresence(agentID);
803 if (avatar != null)
804 {
805 // don't attach attachments to child agents
806 if (avatar.IsChildAgent) return;
807
808 DetachFromBackup();
809
810 // Remove from database and parcel prim count
811 //
812 m_scene.DeleteFromStorage(UUID);
813 m_scene.EventManager.TriggerParcelPrimCountTainted();
814
815 m_rootPart.AttachedAvatar = agentID;
816
817 if (m_rootPart.PhysActor != null)
818 {
819 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
820 m_rootPart.PhysActor = null;
821 }
822
823 AbsolutePosition = AttachOffset;
824 m_rootPart.AttachedPos = AttachOffset;
825 m_rootPart.IsAttachment = true;
826
827 m_rootPart.SetParentLocalId(avatar.LocalId);
828 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
829
830 avatar.AddAttachment(this);
831
832 if (!silent)
833 {
834 // Killing it here will cause the client to deselect it
835 // It then reappears on the avatar, deselected
836 // through the full update below
837 //
838 if (IsSelected)
839 {
840 m_scene.SendKillObject(m_rootPart.LocalId);
841 }
842
843 IsSelected = false; // fudge....
844 ScheduleGroupForFullUpdate();
845 }
846 }
847 }
848
849 public byte GetAttachmentPoint()
850 {
851 if (m_rootPart != null)
852 {
853 return m_rootPart.Shape.State;
854 }
855 return (byte)0;
856 }
857
858 public void ClearPartAttachmentData()
859 {
860 SetAttachmentPoint((Byte)0);
861 }
862
863 public void DetachToGround()
864 {
865 ScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar);
866 if (avatar == null)
867 return;
868
869 avatar.RemoveAttachment(this);
870
871 Vector3 detachedpos = new Vector3(127f,127f,127f);
872 if (avatar == null)
873 return;
874
875 detachedpos = avatar.AbsolutePosition;
876
877 AbsolutePosition = detachedpos;
878 m_rootPart.AttachedAvatar = UUID.Zero;
879 m_rootPart.SetParentLocalId(0);
880 SetAttachmentPoint((byte)0);
881 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
882 HasGroupChanged = true;
883 RootPart.Rezzed = DateTime.Now;
884 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
885 AttachToBackup();
886 m_scene.EventManager.TriggerParcelPrimCountTainted();
887 m_rootPart.ScheduleFullUpdate();
888 m_rootPart.ClearUndoState();
889 }
890
891 public void DetachToInventoryPrep()
892 {
893 ScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar);
894 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
895 if (avatar != null)
896 {
897 //detachedpos = avatar.AbsolutePosition;
898 avatar.RemoveAttachment(this);
899 }
900
901 m_rootPart.AttachedAvatar = UUID.Zero;
902 m_rootPart.SetParentLocalId(0);
903 //m_rootPart.SetAttachmentPoint((byte)0);
904 m_rootPart.IsAttachment = false;
905 AbsolutePosition = m_rootPart.AttachedPos;
906 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
907 //AttachToBackup();
908 //m_rootPart.ScheduleFullUpdate();
909
910 }
911 /// <summary>
912 ///
913 /// </summary>
914 /// <param name="part"></param>
915 private void SetPartAsNonRoot(SceneObjectPart part)
916 {
917 part.ParentID = m_rootPart.LocalId;
918 part.ClearUndoState();
919 }
920
921 public override void UpdateMovement()
922 {
923 lock (m_parts)
924 {
925 foreach (SceneObjectPart part in m_parts.Values)
926 {
927 part.UpdateMovement();
928 }
929 }
930 }
931
932 public float GetTimeDilation()
933 {
934 return m_scene.TimeDilation;
935 }
936
937 /// <summary>
938 /// Added as a way for the storage provider to reset the scene,
939 /// most likely a better way to do this sort of thing but for now...
940 /// </summary>
941 /// <param name="scene"></param>
942 public void SetScene(Scene scene)
943 {
944 m_scene = scene;
945 }
946
947 /// <summary>
948 /// Set a part to act as the root part for this scene object
949 /// </summary>
950 /// <param name="part"></param>
951 public void SetRootPart(SceneObjectPart part)
952 {
953 part.SetParent(this);
954 m_rootPart = part;
955 if (!IsAttachment)
956 part.ParentID = 0;
957 part.LinkNum = 0;
958
959 // No locking required since the SOG should not be in the scene yet - one can't change root parts after
960 // the scene object has been attached to the scene
961 m_parts.Add(m_rootPart.UUID, m_rootPart);
962 }
963
964 /// <summary>
965 /// Add a new part to this scene object. The part must already be correctly configured.
966 /// </summary>
967 /// <param name="part"></param>
968 public void AddPart(SceneObjectPart part)
969 {
970 lock (m_parts)
971 {
972 part.SetParent(this);
973 m_parts.Add(part.UUID, part);
974
975 part.LinkNum = m_parts.Count;
976
977 if (part.LinkNum == 2 && RootPart != null)
978 RootPart.LinkNum = 1;
979 }
980 }
981
982 /// <summary>
983 /// Make sure that every non root part has the proper parent root part local id
984 /// </summary>
985 private void UpdateParentIDs()
986 {
987 lock (m_parts)
988 {
989 foreach (SceneObjectPart part in m_parts.Values)
990 {
991 if (part.UUID != m_rootPart.UUID)
992 {
993 part.ParentID = m_rootPart.LocalId;
994 }
995 }
996 }
997 }
998
999 public void RegenerateFullIDs()
1000 {
1001 lock (m_parts)
1002 {
1003 foreach (SceneObjectPart part in m_parts.Values)
1004 {
1005 part.UUID = UUID.Random();
1006
1007 }
1008 }
1009 }
1010 // helper provided for parts.
1011 public int GetSceneMaxUndo()
1012 {
1013 if (m_scene != null)
1014 return m_scene.MaxUndoCount;
1015 return 5;
1016 }
1017
1018 // justincc: I don't believe this hack is needed any longer, especially since the physics
1019 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1020 // this method was preventing proper reload of scene objects.
1021 // dahlia: I had to uncomment it, without it meshing was failing on some prims and objects
1022 // at region startup
1023 public void ResetChildPrimPhysicsPositions()
1024 {
1025 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1026 }
1027
1028 public UUID GetPartsFullID(uint localID)
1029 {
1030 SceneObjectPart part = GetChildPart(localID);
1031 if (part != null)
1032 {
1033 return part.UUID;
1034 }
1035 return UUID.Zero;
1036 }
1037
1038 public void ObjectGrabHandler(uint localId, Vector3 offsetPos, IClientAPI remoteClient)
1039 {
1040 if (m_rootPart.LocalId == localId)
1041 {
1042 OnGrabGroup(offsetPos, remoteClient);
1043 }
1044 else
1045 {
1046 SceneObjectPart part = GetChildPart(localId);
1047 OnGrabPart(part, offsetPos, remoteClient);
1048
1049 }
1050 }
1051
1052 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1053 {
1054 part.StoreUndoState();
1055 part.OnGrab(offsetPos, remoteClient);
1056 }
1057
1058 public virtual void OnGrabGroup(Vector3 offsetPos, IClientAPI remoteClient)
1059 {
1060 m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
1061 }
1062
1063 /// <summary>
1064 /// Delete this group from its scene and tell all the scene presences about that deletion.
1065 /// </summary>
1066 /// <param name="silent">Broadcast deletions to all clients.</param>
1067 public void DeleteGroup(bool silent)
1068 {
1069 // We need to keep track of this state in case this group is still queued for backup.
1070 m_isDeleted = true;
1071
1072 DetachFromBackup();
1073
1074 lock (m_parts)
1075 {
1076 foreach (SceneObjectPart part in m_parts.Values)
1077 {
1078// part.Inventory.RemoveScriptInstances();
1079
1080 List<ScenePresence> avatars = Scene.GetScenePresences();
1081 for (int i = 0; i < avatars.Count; i++)
1082 {
1083 if (avatars[i].ParentID == LocalId)
1084 {
1085 avatars[i].StandUp();
1086 }
1087
1088 if (!silent)
1089 {
1090 if (m_rootPart != null && part == m_rootPart)
1091 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1092 }
1093 }
1094 }
1095 }
1096 }
1097
1098 public void AddScriptLPS(int count)
1099 {
1100 if (scriptScore + count >= float.MaxValue - count)
1101 scriptScore = 0;
1102
1103 scriptScore += (float)count;
1104 SceneGraph d = m_scene.m_sceneGraph;
1105 d.AddToScriptLPS(count);
1106 }
1107
1108 public void AddActiveScriptCount(int count)
1109 {
1110 SceneGraph d = m_scene.m_sceneGraph;
1111 d.AddActiveScripts(count);
1112 }
1113
1114 public void aggregateScriptEvents()
1115 {
1116 uint objectflagupdate=(uint)RootPart.GetEffectiveObjectFlags();
1117
1118 scriptEvents aggregateScriptEvents=0;
1119
1120 lock (m_parts)
1121 {
1122 foreach (SceneObjectPart part in m_parts.Values)
1123 {
1124 if (part == null)
1125 continue;
1126 if (part != RootPart)
1127 part.ObjectFlags = objectflagupdate;
1128 aggregateScriptEvents |= part.AggregateScriptEvents;
1129 }
1130 }
1131
1132 if ((aggregateScriptEvents & scriptEvents.at_target) != 0)
1133 {
1134 m_scriptListens_atTarget = true;
1135 }
1136 else
1137 {
1138 m_scriptListens_atTarget = false;
1139 }
1140
1141 if ((aggregateScriptEvents & scriptEvents.not_at_target) != 0)
1142 {
1143 m_scriptListens_notAtTarget = true;
1144 }
1145 else
1146 {
1147 m_scriptListens_notAtTarget = false;
1148 }
1149
1150 if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
1151 {
1152 }
1153 else
1154 {
1155 lock (m_targets)
1156 m_targets.Clear();
1157 }
1158
1159 ScheduleGroupForFullUpdate();
1160 }
1161
1162 public override void SetText(string text, Vector3 color, double alpha)
1163 {
1164 Color = Color.FromArgb(0xff - (int) (alpha * 0xff),
1165 (int) (color.X * 0xff),
1166 (int) (color.Y * 0xff),
1167 (int) (color.Z * 0xff));
1168 Text = text;
1169
1170 HasGroupChanged = true;
1171 m_rootPart.ScheduleFullUpdate();
1172 }
1173
1174 /// <summary>
1175 /// Apply physics to this group
1176 /// </summary>
1177 /// <param name="m_physicalPrim"></param>
1178 public void ApplyPhysics(bool m_physicalPrim)
1179 {
1180 lock (m_parts)
1181 {
1182 if (m_parts.Count > 1)
1183 {
1184 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1185 foreach (SceneObjectPart part in m_parts.Values)
1186 {
1187 if (part.LocalId != m_rootPart.LocalId)
1188 {
1189 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1190 }
1191 }
1192
1193 // Hack to get the physics scene geometries in the right spot
1194 ResetChildPrimPhysicsPositions();
1195 }
1196 else
1197 {
1198 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1199 }
1200 }
1201 }
1202
1203 public void SetOwnerId(UUID userId)
1204 {
1205 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; });
1206 }
1207
1208 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1209 {
1210 lock (m_parts)
1211 {
1212 foreach (SceneObjectPart part in m_parts.Values)
1213 {
1214 whatToDo(part);
1215 }
1216 }
1217 }
1218
1219 #region Events
1220
1221 /// <summary>
1222 /// Processes backup.
1223 /// </summary>
1224 /// <param name="datastore"></param>
1225 public void ProcessBackup(IRegionDataStore datastore, bool forcedBackup)
1226 {
1227 if (!m_isBackedUp)
1228 return;
1229
1230 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1231 // any exception propogate upwards.
1232
1233 if (IsDeleted || UUID == UUID.Zero)
1234 return;
1235
1236 try
1237 {
1238 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart
1239 {
1240 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1241 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
1242
1243 if (parcel != null && parcel.landData != null &&
1244 parcel.landData.OtherCleanTime != 0)
1245 {
1246 if (parcel.landData.OwnerID != OwnerID &&
1247 (parcel.landData.GroupID != GroupID ||
1248 parcel.landData.GroupID == UUID.Zero))
1249 {
1250 if ((DateTime.Now - RootPart.Rezzed).TotalMinutes >
1251 parcel.landData.OtherCleanTime)
1252 {
1253 DetachFromBackup();
1254 m_log.InfoFormat("[SCENE]: Returning object {0} due to parcel auto return", RootPart.UUID.ToString());
1255 m_scene.AddReturn(OwnerID, Name, AbsolutePosition, "parcel auto return");
1256 m_scene.DeRezObject(null, RootPart.LocalId,
1257 RootPart.GroupID, DeRezAction.Return, UUID.Zero);
1258
1259 return;
1260 }
1261 }
1262 }
1263 }
1264
1265 if (HasGroupChanged)
1266 {
1267 // don't backup while it's selected or you're asking for changes mid stream.
1268 if ((isTimeToPersist()) || (forcedBackup))
1269 {
1270 m_log.DebugFormat(
1271 "[SCENE]: Storing {0}, {1} in {2}",
1272 Name, UUID, m_scene.RegionInfo.RegionName);
1273
1274 SceneObjectGroup backup_group = Copy(OwnerID, GroupID, false);
1275 backup_group.RootPart.Velocity = RootPart.Velocity;
1276 backup_group.RootPart.Acceleration = RootPart.Acceleration;
1277 backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity;
1278 backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
1279 HasGroupChanged = false;
1280
1281 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1282
1283 backup_group.ForEachPart(delegate(SceneObjectPart part)
1284 {
1285 part.Inventory.ProcessInventoryBackup(datastore);
1286 });
1287
1288 backup_group = null;
1289 }
1290 // else
1291 // {
1292 // m_log.DebugFormat(
1293 // "[SCENE]: Did not update persistence of object {0} {1}, selected = {2}",
1294 // Name, UUID, IsSelected);
1295 // }
1296 }
1297 }
1298 catch (Exception e)
1299 {
1300 m_log.ErrorFormat(
1301 "[SCENE]: Storing of {0}, {1} in {2} failed with exception {3}\n\t{4}",
1302 Name, UUID, m_scene.RegionInfo.RegionName, e, e.StackTrace);
1303 }
1304 }
1305
1306 #endregion
1307
1308 #region Client Updating
1309
1310 public void SendFullUpdateToClient(IClientAPI remoteClient)
1311 {
1312 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1313
1314 lock (m_parts)
1315 {
1316 foreach (SceneObjectPart part in m_parts.Values)
1317 {
1318 if (part != RootPart)
1319 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1320 }
1321 }
1322 }
1323
1324 /// <summary>
1325 /// Send a full update to the client for the given part
1326 /// </summary>
1327 /// <param name="remoteClient"></param>
1328 /// <param name="part"></param>
1329 internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags)
1330 {
1331 if (m_rootPart != null && m_rootPart.UUID == part.UUID)
1332 {
1333 if (IsAttachment)
1334 {
1335 part.SendFullUpdateToClient(remoteClient, m_rootPart.AttachedPos, clientFlags);
1336 }
1337 else
1338 {
1339 part.SendFullUpdateToClient(remoteClient, AbsolutePosition, clientFlags);
1340 }
1341 }
1342 else
1343 {
1344 part.SendFullUpdateToClient(remoteClient, clientFlags);
1345 }
1346 }
1347
1348 #endregion
1349
1350 #region Copying
1351
1352 /// <summary>
1353 /// Duplicates this object, including operations such as physics set up and attaching to the backup event.
1354 /// </summary>
1355 /// <returns></returns>
1356 public SceneObjectGroup Copy(UUID cAgentID, UUID cGroupID, bool userExposed)
1357 {
1358 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1359 dupe.m_isBackedUp = false;
1360 dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
1361 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1362
1363 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1364 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1365
1366 if (userExposed)
1367 dupe.m_rootPart.TrimPermissions();
1368
1369 /// may need to create a new Physics actor.
1370 if (dupe.RootPart.PhysActor != null && userExposed)
1371 {
1372 PrimitiveBaseShape pbs = dupe.RootPart.Shape;
1373
1374 dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
1375 dupe.RootPart.Name,
1376 pbs,
1377 new PhysicsVector(dupe.RootPart.AbsolutePosition.X, dupe.RootPart.AbsolutePosition.Y, dupe.RootPart.AbsolutePosition.Z),
1378 new PhysicsVector(dupe.RootPart.Scale.X, dupe.RootPart.Scale.Y, dupe.RootPart.Scale.Z),
1379 dupe.RootPart.RotationOffset,
1380 dupe.RootPart.PhysActor.IsPhysical);
1381
1382 dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
1383 dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
1384 }
1385
1386 // Now we've made a copy that replaces this one, we need to
1387 // switch the owner to the person who did the copying
1388 // Second Life copies an object and duplicates the first one in it's place
1389 // So, we have to make a copy of this one, set it in it's place then set the owner on this one
1390 if (userExposed)
1391 {
1392 SetRootPartOwner(m_rootPart, cAgentID, cGroupID);
1393 m_rootPart.ScheduleFullUpdate();
1394 }
1395
1396 List<SceneObjectPart> partList;
1397
1398 lock (m_parts)
1399 {
1400 partList = new List<SceneObjectPart>(m_parts.Values);
1401 }
1402
1403 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1404 {
1405 return p1.LinkNum.CompareTo(p2.LinkNum);
1406 }
1407 );
1408
1409 foreach (SceneObjectPart part in partList)
1410 {
1411 if (part.UUID != m_rootPart.UUID)
1412 {
1413 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1414
1415 newPart.LinkNum = part.LinkNum;
1416
1417 if (userExposed)
1418 {
1419 SetPartOwner(newPart, cAgentID, cGroupID);
1420 newPart.ScheduleFullUpdate();
1421 }
1422 }
1423 }
1424
1425 if (userExposed)
1426 {
1427 dupe.UpdateParentIDs();
1428 dupe.HasGroupChanged = true;
1429 dupe.AttachToBackup();
1430
1431 ScheduleGroupForFullUpdate();
1432 }
1433
1434 return dupe;
1435 }
1436
1437 /// <summary>
1438 ///
1439 /// </summary>
1440 /// <param name="part"></param>
1441 /// <param name="cAgentID"></param>
1442 /// <param name="cGroupID"></param>
1443 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1444 {
1445 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed));
1446 }
1447
1448 public void ScriptSetPhysicsStatus(bool UsePhysics)
1449 {
1450 bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
1451 bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
1452 bool IsVolumeDetect = RootPart.VolumeDetectActive;
1453 UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1454 }
1455
1456 public void ScriptSetTemporaryStatus(bool TemporaryStatus)
1457 {
1458 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1459 bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
1460 bool IsVolumeDetect = RootPart.VolumeDetectActive;
1461 UpdatePrimFlags(RootPart.LocalId, UsePhysics, TemporaryStatus, IsPhantom, IsVolumeDetect);
1462 }
1463
1464 public void ScriptSetPhantomStatus(bool PhantomStatus)
1465 {
1466 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1467 bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
1468 bool IsVolumeDetect = RootPart.VolumeDetectActive;
1469 UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, PhantomStatus, IsVolumeDetect);
1470 }
1471
1472 public void ScriptSetVolumeDetect(bool VDStatus)
1473 {
1474 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1475 bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
1476 bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
1477 UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, VDStatus);
1478
1479 /*
1480 ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore
1481
1482 if (PhysActor != null) // Should always be the case now
1483 {
1484 PhysActor.SetVolumeDetect(param);
1485 }
1486 if (param != 0)
1487 AddFlag(PrimFlags.Phantom);
1488
1489 ScheduleFullUpdate();
1490 */
1491 }
1492
1493 public void applyImpulse(PhysicsVector impulse)
1494 {
1495 // We check if rootpart is null here because scripts don't delete if you delete the host.
1496 // This means that unfortunately, we can pass a null physics actor to Simulate!
1497 // Make sure we don't do that!
1498 SceneObjectPart rootpart = m_rootPart;
1499 if (rootpart != null)
1500 {
1501 if (rootpart.PhysActor != null)
1502 {
1503 if (IsAttachment)
1504 {
1505 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1506 if (avatar != null)
1507 {
1508 avatar.PushForce(impulse);
1509 }
1510 }
1511 else
1512 {
1513 rootpart.PhysActor.AddForce(impulse,true);
1514 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
1515 }
1516 }
1517 }
1518 }
1519
1520 public void applyAngularImpulse(PhysicsVector impulse)
1521 {
1522 // We check if rootpart is null here because scripts don't delete if you delete the host.
1523 // This means that unfortunately, we can pass a null physics actor to Simulate!
1524 // Make sure we don't do that!
1525 SceneObjectPart rootpart = m_rootPart;
1526 if (rootpart != null)
1527 {
1528 if (rootpart.PhysActor != null)
1529 {
1530 if (!IsAttachment)
1531 {
1532 rootpart.PhysActor.AddAngularForce(impulse, true);
1533 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
1534 }
1535 }
1536 }
1537 }
1538
1539 public void setAngularImpulse(PhysicsVector impulse)
1540 {
1541 // We check if rootpart is null here because scripts don't delete if you delete the host.
1542 // This means that unfortunately, we can pass a null physics actor to Simulate!
1543 // Make sure we don't do that!
1544 SceneObjectPart rootpart = m_rootPart;
1545 if (rootpart != null)
1546 {
1547 if (rootpart.PhysActor != null)
1548 {
1549 if (!IsAttachment)
1550 {
1551 rootpart.PhysActor.Torque = impulse;
1552 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
1553 }
1554 }
1555 }
1556 }
1557
1558 public Vector3 GetTorque()
1559 {
1560 // We check if rootpart is null here because scripts don't delete if you delete the host.
1561 // This means that unfortunately, we can pass a null physics actor to Simulate!
1562 // Make sure we don't do that!
1563 SceneObjectPart rootpart = m_rootPart;
1564 if (rootpart != null)
1565 {
1566 if (rootpart.PhysActor != null)
1567 {
1568 if (!IsAttachment)
1569 {
1570 PhysicsVector torque = rootpart.PhysActor.Torque;
1571 return new Vector3(torque.X, torque.Y, torque.Z);
1572 }
1573 }
1574 }
1575 return Vector3.Zero;
1576 }
1577
1578 public void moveToTarget(Vector3 target, float tau)
1579 {
1580 SceneObjectPart rootpart = m_rootPart;
1581 if (rootpart != null)
1582 {
1583 if (rootpart.PhysActor != null)
1584 {
1585 rootpart.PhysActor.PIDTarget = new PhysicsVector(target.X, target.Y, target.Z);
1586 rootpart.PhysActor.PIDTau = tau;
1587 rootpart.PhysActor.PIDActive = true;
1588 }
1589 }
1590 }
1591
1592 public void stopMoveToTarget()
1593 {
1594 SceneObjectPart rootpart = m_rootPart;
1595 if (rootpart != null)
1596 {
1597 if (rootpart.PhysActor != null)
1598 {
1599 rootpart.PhysActor.PIDActive = false;
1600 }
1601 }
1602 }
1603
1604 /// <summary>
1605 /// Set the owner of the root part.
1606 /// </summary>
1607 /// <param name="part"></param>
1608 /// <param name="cAgentID"></param>
1609 /// <param name="cGroupID"></param>
1610 public void SetRootPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID)
1611 {
1612 part.LastOwnerID = part.OwnerID;
1613 part.OwnerID = cAgentID;
1614 part.GroupID = cGroupID;
1615
1616 if (part.OwnerID != cAgentID)
1617 {
1618 // Apply Next Owner Permissions if we're not bypassing permissions
1619 if (!m_scene.Permissions.BypassPermissions())
1620 ApplyNextOwnerPermissions();
1621 }
1622
1623 part.ScheduleFullUpdate();
1624 }
1625
1626 /// <summary>
1627 /// Make a copy of the given part.
1628 /// </summary>
1629 /// <param name="part"></param>
1630 /// <param name="cAgentID"></param>
1631 /// <param name="cGroupID"></param>
1632 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1633 {
1634 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1635 newPart.SetParent(this);
1636
1637 lock (m_parts)
1638 {
1639 m_parts.Add(newPart.UUID, newPart);
1640 }
1641
1642 SetPartAsNonRoot(newPart);
1643
1644 return newPart;
1645 }
1646
1647 /// <summary>
1648 /// Reset the UUIDs for all the prims that make up this group.
1649 ///
1650 /// This is called by methods which want to add a new group to an existing scene, in order
1651 /// to ensure that there are no clashes with groups already present.
1652 /// </summary>
1653 public void ResetIDs()
1654 {
1655 // As this is only ever called for prims which are not currently part of the scene (and hence
1656 // not accessible by clients), there should be no need to lock
1657 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
1658 m_parts.Clear();
1659 foreach (SceneObjectPart part in partsList)
1660 {
1661 part.ResetIDs(part.LinkNum); // Don't change link nums
1662 m_parts.Add(part.UUID, part);
1663 }
1664 }
1665
1666 /// <summary>
1667 ///
1668 /// </summary>
1669 /// <param name="part"></param>
1670 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
1671 {
1672
1673 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.ObjectOwner, RootPart.GroupID, RootPart.BaseMask,
1674 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
1675 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
1676 RootPart.CreatorID, RootPart.Name, RootPart.Description);
1677 }
1678
1679 public void SetPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID)
1680 {
1681 part.OwnerID = cAgentID;
1682 part.GroupID = cGroupID;
1683 }
1684
1685 #endregion
1686
1687 #region Scheduling
1688
1689 public override void Update()
1690 {
1691 // Check that the group was not deleted before the scheduled update
1692 // FIXME: This is merely a temporary measure to reduce the incidence of failure when
1693 // an object has been deleted from a scene before update was processed.
1694 // A more fundamental overhaul of the update mechanism is required to eliminate all
1695 // the race conditions.
1696 if (m_isDeleted)
1697 return;
1698
1699 // This is what happens when an orphanced link set child prim's
1700 // group was queued when it was linked
1701 //
1702 if (m_rootPart == null)
1703 return;
1704
1705 lock (m_parts)
1706 {
1707 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1708
1709 //if (IsAttachment)
1710 //{
1711 //foreach (SceneObjectPart part in m_parts.Values)
1712 //{
1713 //part.SendScheduledUpdates();
1714 //}
1715 //return;
1716 //}
1717
1718 if ((Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02) && UsePhysics)
1719 {
1720 m_rootPart.UpdateFlag = 1;
1721 lastPhysGroupPos = AbsolutePosition;
1722 }
1723 //foreach (SceneObjectPart part in m_parts.Values)
1724 //{
1725 //if (part.UpdateFlag == 0) part.UpdateFlag = 1;
1726 //}
1727
1728 checkAtTargets();
1729
1730 if (((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
1731 || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
1732 || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1)
1733 || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1))
1734 && UsePhysics)
1735 {
1736 m_rootPart.UpdateFlag = 1;
1737
1738 lastPhysGroupRot = GroupRotation;
1739 }
1740
1741 foreach (SceneObjectPart part in m_parts.Values)
1742 {
1743 part.SendScheduledUpdates();
1744 }
1745 }
1746 }
1747
1748 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1749 {
1750 RootPart.AddFullUpdateToAvatar(presence);
1751
1752 lock (m_parts)
1753 {
1754 foreach (SceneObjectPart part in m_parts.Values)
1755 {
1756 if (part != RootPart)
1757 part.AddFullUpdateToAvatar(presence);
1758 }
1759 }
1760 }
1761
1762 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1763 {
1764 lock (m_parts)
1765 {
1766 foreach (SceneObjectPart part in m_parts.Values)
1767 {
1768 part.AddTerseUpdateToAvatar(presence);
1769 }
1770 }
1771 }
1772
1773 /// <summary>
1774 /// Schedule a full update for this scene object
1775 /// </summary>
1776 public void ScheduleGroupForFullUpdate()
1777 {
1778 checkAtTargets();
1779 RootPart.ScheduleFullUpdate();
1780
1781 lock (m_parts)
1782 {
1783 foreach (SceneObjectPart part in m_parts.Values)
1784 {
1785 if (part != RootPart)
1786 part.ScheduleFullUpdate();
1787 }
1788 }
1789 }
1790
1791 /// <summary>
1792 /// Schedule a terse update for this scene object
1793 /// </summary>
1794 public void ScheduleGroupForTerseUpdate()
1795 {
1796 lock (m_parts)
1797 {
1798 foreach (SceneObjectPart part in m_parts.Values)
1799 {
1800 part.ScheduleTerseUpdate();
1801 }
1802 }
1803 }
1804
1805 /// <summary>
1806 /// Immediately send a full update for this scene object.
1807 /// </summary>
1808 public void SendGroupFullUpdate()
1809 {
1810 if (IsDeleted)
1811 return;
1812
1813 RootPart.SendFullUpdateToAllClients();
1814
1815 lock (m_parts)
1816 {
1817 foreach (SceneObjectPart part in m_parts.Values)
1818 {
1819 if (part != RootPart)
1820 part.SendFullUpdateToAllClients();
1821 }
1822 }
1823 }
1824
1825 /// <summary>
1826 /// Immediately send an update for this scene object's root prim only.
1827 /// This is for updates regarding the object as a whole, and none of its parts in particular.
1828 /// Note: this may not be cused by opensim (it probably should) but it's used by
1829 /// external modules.
1830 /// </summary>
1831 public void SendGroupRootUpdate()
1832 {
1833 if (IsDeleted)
1834 return;
1835
1836 RootPart.SendFullUpdateToAllClients();
1837 }
1838
1839 public void QueueForUpdateCheck()
1840 {
1841 if (m_scene == null) // Need to check here as it's null during object creation
1842 return;
1843 m_scene.m_sceneGraph.AddToUpdateList(this);
1844 }
1845
1846 /// <summary>
1847 /// Immediately send a terse update for this scene object.
1848 /// </summary>
1849 public void SendGroupTerseUpdate()
1850 {
1851 if (IsDeleted)
1852 return;
1853
1854 lock (m_parts)
1855 {
1856 foreach (SceneObjectPart part in m_parts.Values)
1857 {
1858 part.SendTerseUpdateToAllClients();
1859 }
1860 }
1861 }
1862
1863 #endregion
1864
1865 #region SceneGroupPart Methods
1866
1867 /// <summary>
1868 /// Get the child part by LinkNum
1869 /// </summary>
1870 /// <param name="linknum"></param>
1871 /// <returns>null if no child part with that linknum or child part</returns>
1872 public SceneObjectPart GetLinkNumPart(int linknum)
1873 {
1874 lock (m_parts)
1875 {
1876 foreach (SceneObjectPart part in m_parts.Values)
1877 {
1878 if (part.LinkNum == linknum)
1879 {
1880 return part;
1881 }
1882 }
1883 }
1884
1885 return null;
1886 }
1887
1888 /// <summary>
1889 /// Get a child part with a given UUID
1890 /// </summary>
1891 /// <param name="primID"></param>
1892 /// <returns>null if a child part with the primID was not found</returns>
1893 public SceneObjectPart GetChildPart(UUID primID)
1894 {
1895 SceneObjectPart childPart = null;
1896 if (m_parts.ContainsKey(primID))
1897 {
1898 childPart = m_parts[primID];
1899 }
1900 return childPart;
1901 }
1902
1903 /// <summary>
1904 /// Get a child part with a given local ID
1905 /// </summary>
1906 /// <param name="localID"></param>
1907 /// <returns>null if a child part with the local ID was not found</returns>
1908 public SceneObjectPart GetChildPart(uint localID)
1909 {
1910 //m_log.DebugFormat("Entered looking for {0}", localID);
1911 lock (m_parts)
1912 {
1913 foreach (SceneObjectPart part in m_parts.Values)
1914 {
1915 //m_log.DebugFormat("Found {0}", part.LocalId);
1916 if (part.LocalId == localID)
1917 {
1918 return part;
1919 }
1920 }
1921 }
1922
1923 return null;
1924 }
1925
1926 /// <summary>
1927 /// Does this group contain the child prim
1928 /// should be able to remove these methods once we have a entity index in scene
1929 /// </summary>
1930 /// <param name="primID"></param>
1931 /// <returns></returns>
1932 public bool HasChildPrim(UUID primID)
1933 {
1934 if (m_parts.ContainsKey(primID))
1935 {
1936 return true;
1937 }
1938
1939 return false;
1940 }
1941
1942 /// <summary>
1943 /// Does this group contain the child prim
1944 /// should be able to remove these methods once we have a entity index in scene
1945 /// </summary>
1946 /// <param name="localID"></param>
1947 /// <returns></returns>
1948 public bool HasChildPrim(uint localID)
1949 {
1950 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
1951 lock (m_parts)
1952 {
1953 foreach (SceneObjectPart part in m_parts.Values)
1954 {
1955 //m_log.DebugFormat("Found {0}", part.LocalId);
1956 if (part.LocalId == localID)
1957 {
1958 return true;
1959 }
1960 }
1961 }
1962
1963 return false;
1964 }
1965
1966 #endregion
1967
1968 #region Packet Handlers
1969
1970 /// <summary>
1971 /// Link the prims in a given group to this group
1972 /// </summary>
1973 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1974 public void LinkToGroup(SceneObjectGroup objectGroup)
1975 {
1976 if (objectGroup.RootPart.UpdateFlag > 0)
1977 {
1978 // I've never actually seen this happen, though I think it's theoretically possible
1979 m_log.WarnFormat(
1980 "[SCENE OBJECT GROUP]: Aborted linking {0}, {1} to {2}, {3} as it has yet to finish delinking",
1981 objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
1982
1983 return;
1984 }
1985
1986// m_log.DebugFormat(
1987// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1988// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
1989
1990 SceneObjectPart linkPart = objectGroup.m_rootPart;
1991
1992 Vector3 oldGroupPosition = linkPart.GroupPosition;
1993 Quaternion oldRootRotation = linkPart.RotationOffset;
1994
1995 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
1996 linkPart.GroupPosition = AbsolutePosition;
1997 Vector3 axPos = linkPart.OffsetPosition;
1998
1999 Quaternion parentRot = m_rootPart.RotationOffset;
2000 axPos *= Quaternion.Inverse(parentRot);
2001
2002 linkPart.OffsetPosition = axPos;
2003 Quaternion oldRot = linkPart.RotationOffset;
2004 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
2005 linkPart.RotationOffset = newRot;
2006
2007 linkPart.ParentID = m_rootPart.LocalId;
2008 if (m_rootPart.LinkNum == 0)
2009 m_rootPart.LinkNum = 1;
2010
2011 lock (m_parts)
2012 {
2013 m_parts.Add(linkPart.UUID, linkPart);
2014
2015 // Insert in terms of link numbers, the new links
2016 // before the current ones (with the exception of
2017 // the root prim. Shuffle the old ones up
2018 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2019 {
2020 if (kvp.Value.LinkNum != 1)
2021 {
2022 // Don't update root prim link number
2023 kvp.Value.LinkNum += objectGroup.PrimCount;
2024 }
2025 }
2026
2027 linkPart.LinkNum = 2;
2028
2029 linkPart.SetParent(this);
2030 linkPart.AddFlag(PrimFlags.CreateSelected);
2031
2032 //if (linkPart.PhysActor != null)
2033 //{
2034 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2035
2036 //linkPart.PhysActor = null;
2037 //}
2038
2039 //TODO: rest of parts
2040 int linkNum = 3;
2041 foreach (SceneObjectPart part in objectGroup.Children.Values)
2042 {
2043 if (part.UUID != objectGroup.m_rootPart.UUID)
2044 {
2045 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2046 }
2047 part.ClearUndoState();
2048 }
2049 }
2050
2051 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2052 objectGroup.m_isDeleted = true;
2053
2054 lock (objectGroup.m_parts)
2055 {
2056 objectGroup.m_parts.Clear();
2057 }
2058
2059 // Can't do this yet since backup still makes use of the root part without any synchronization
2060// objectGroup.m_rootPart = null;
2061
2062 AttachToBackup();
2063 HasGroupChanged = true;
2064 ScheduleGroupForFullUpdate();
2065 }
2066
2067 /// <summary>
2068 /// Delink the given prim from this group. The delinked prim is established as
2069 /// an independent SceneObjectGroup.
2070 /// </summary>
2071 /// <param name="partID"></param>
2072 public void DelinkFromGroup(uint partID)
2073 {
2074 DelinkFromGroup(partID, true);
2075 }
2076
2077 /// <summary>
2078 /// Delink the given prim from this group. The delinked prim is established as
2079 /// an independent SceneObjectGroup.
2080 /// </summary>
2081 /// <param name="partID"></param>
2082 /// <param name="sendEvents"></param>
2083 public void DelinkFromGroup(uint partID, bool sendEvents)
2084 {
2085 SceneObjectPart linkPart = GetChildPart(partID);
2086
2087 if (null != linkPart)
2088 {
2089 linkPart.ClearUndoState();
2090// m_log.DebugFormat(
2091// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2092// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2093
2094 Quaternion worldRot = linkPart.GetWorldRotation();
2095
2096 // Remove the part from this object
2097 lock (m_parts)
2098 {
2099 m_parts.Remove(linkPart.UUID);
2100 }
2101
2102 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2103 RootPart.LinkNum = 0;
2104 else
2105 {
2106 foreach (SceneObjectPart p in m_parts.Values)
2107 {
2108 if (p.LinkNum > linkPart.LinkNum)
2109 p.LinkNum--;
2110 }
2111 }
2112
2113 linkPart.ParentID = 0;
2114 linkPart.LinkNum = 0;
2115
2116 if (linkPart.PhysActor != null)
2117 {
2118 m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2119 }
2120
2121 // We need to reset the child part's position
2122 // ready for life as a separate object after being a part of another object
2123 Quaternion parentRot = m_rootPart.RotationOffset;
2124
2125 Vector3 axPos = linkPart.OffsetPosition;
2126
2127 axPos *= parentRot;
2128 linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z);
2129 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2130 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2131
2132 linkPart.RotationOffset = worldRot;
2133
2134 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2135
2136 m_scene.AddNewSceneObject(objectGroup, true);
2137
2138 if (sendEvents)
2139 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2140
2141 linkPart.Rezzed = RootPart.Rezzed;
2142
2143 HasGroupChanged = true;
2144 ScheduleGroupForFullUpdate();
2145 }
2146 else
2147 {
2148 m_log.InfoFormat("[SCENE OBJECT GROUP]: " +
2149 "DelinkFromGroup(): Child prim {0} not found in object {1}, {2}",
2150 partID, LocalId, UUID);
2151 }
2152 }
2153
2154 /// <summary>
2155 /// Stop this object from being persisted over server restarts.
2156 /// </summary>
2157 /// <param name="objectGroup"></param>
2158 public void DetachFromBackup()
2159 {
2160 if (m_isBackedUp)
2161 m_scene.EventManager.OnBackup -= ProcessBackup;
2162
2163 m_isBackedUp = false;
2164 }
2165
2166 private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
2167 {
2168
2169 Quaternion parentRot = oldGroupRotation;
2170 Quaternion oldRot = part.RotationOffset;
2171 Quaternion worldRot = parentRot * oldRot;
2172
2173 parentRot = oldGroupRotation;
2174
2175 Vector3 axPos = part.OffsetPosition;
2176
2177 axPos *= parentRot;
2178 part.OffsetPosition = axPos;
2179 part.GroupPosition = oldGroupPosition + part.OffsetPosition;
2180 part.OffsetPosition = Vector3.Zero;
2181 part.RotationOffset = worldRot;
2182
2183 part.SetParent(this);
2184 part.ParentID = m_rootPart.LocalId;
2185
2186 // Caller locks m_parts for us
2187 m_parts.Add(part.UUID, part);
2188
2189 part.LinkNum = linkNum;
2190
2191
2192 part.OffsetPosition = part.GroupPosition - AbsolutePosition;
2193
2194 Quaternion rootRotation = m_rootPart.RotationOffset;
2195
2196 Vector3 pos = part.OffsetPosition;
2197 pos *= Quaternion.Inverse(rootRotation);
2198 part.OffsetPosition = pos;
2199
2200 parentRot = m_rootPart.RotationOffset;
2201 oldRot = part.RotationOffset;
2202 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
2203 part.RotationOffset = newRot;
2204 }
2205
2206 /// <summary>
2207 /// If object is physical, apply force to move it around
2208 /// If object is not physical, just put it at the resulting location
2209 /// </summary>
2210 /// <param name="offset">Always seems to be 0,0,0, so ignoring</param>
2211 /// <param name="pos">New position. We do the math here to turn it into a force</param>
2212 /// <param name="remoteClient"></param>
2213 public void GrabMovement(Vector3 offset, Vector3 pos, IClientAPI remoteClient)
2214 {
2215 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2216 {
2217 if (m_rootPart.PhysActor != null)
2218 {
2219 if (m_rootPart.PhysActor.IsPhysical)
2220 {
2221 Vector3 llmoveforce = pos - AbsolutePosition;
2222 PhysicsVector grabforce = new PhysicsVector(llmoveforce.X, llmoveforce.Y, llmoveforce.Z);
2223 grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass;
2224 m_rootPart.PhysActor.AddForce(grabforce,true);
2225 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2226 }
2227 else
2228 {
2229 //NonPhysicalGrabMovement(pos);
2230 }
2231 }
2232 else
2233 {
2234 //NonPhysicalGrabMovement(pos);
2235 }
2236 }
2237 }
2238
2239 public void NonPhysicalGrabMovement(Vector3 pos)
2240 {
2241 AbsolutePosition = pos;
2242 m_rootPart.SendTerseUpdateToAllClients();
2243 }
2244
2245 /// <summary>
2246 /// Return metadata about a prim (name, description, sale price, etc.)
2247 /// </summary>
2248 /// <param name="client"></param>
2249 public void GetProperties(IClientAPI client)
2250 {
2251 m_rootPart.GetProperties(client);
2252 }
2253
2254 /// <summary>
2255 /// Set the name of a prim
2256 /// </summary>
2257 /// <param name="name"></param>
2258 /// <param name="localID"></param>
2259 public void SetPartName(string name, uint localID)
2260 {
2261 SceneObjectPart part = GetChildPart(localID);
2262 if (part != null)
2263 {
2264 part.Name = name;
2265 }
2266 }
2267
2268 public void SetPartDescription(string des, uint localID)
2269 {
2270 SceneObjectPart part = GetChildPart(localID);
2271 if (part != null)
2272 {
2273 part.Description = des;
2274 }
2275 }
2276
2277 public void SetPartText(string text, uint localID)
2278 {
2279 SceneObjectPart part = GetChildPart(localID);
2280 if (part != null)
2281 {
2282 part.SetText(text);
2283 }
2284 }
2285
2286 public void SetPartText(string text, UUID partID)
2287 {
2288 SceneObjectPart part = GetChildPart(partID);
2289 if (part != null)
2290 {
2291 part.SetText(text);
2292 }
2293 }
2294
2295 public string GetPartName(uint localID)
2296 {
2297 SceneObjectPart part = GetChildPart(localID);
2298 if (part != null)
2299 {
2300 return part.Name;
2301 }
2302 return String.Empty;
2303 }
2304
2305 public string GetPartDescription(uint localID)
2306 {
2307 SceneObjectPart part = GetChildPart(localID);
2308 if (part != null)
2309 {
2310 return part.Description;
2311 }
2312 return String.Empty;
2313 }
2314
2315 /// <summary>
2316 /// Update prim flags for this group.
2317 /// </summary>
2318 /// <param name="localID"></param>
2319 /// <param name="type"></param>
2320 /// <param name="inUse"></param>
2321 /// <param name="data"></param>
2322 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect)
2323 {
2324 SceneObjectPart selectionPart = GetChildPart(localID);
2325
2326 if (IsTemporary)
2327 {
2328 DetachFromBackup();
2329 // Remove from database and parcel prim count
2330 //
2331 m_scene.DeleteFromStorage(UUID);
2332 m_scene.EventManager.TriggerParcelPrimCountTainted();
2333 }
2334
2335 if (selectionPart != null)
2336 {
2337 lock (m_parts)
2338 {
2339 foreach (SceneObjectPart part in m_parts.Values)
2340 {
2341 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2342 {
2343 UsePhysics = false; // Reset physics
2344 break;
2345 }
2346 }
2347
2348 foreach (SceneObjectPart part in m_parts.Values)
2349 {
2350 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2351 }
2352 }
2353 }
2354 }
2355
2356 public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
2357 {
2358 SceneObjectPart part = GetChildPart(localID);
2359 if (part != null)
2360 {
2361 part.UpdateExtraParam(type, inUse, data);
2362 }
2363 }
2364
2365 /// <summary>
2366 /// Get the parts of this scene object
2367 /// </summary>
2368 /// <returns></returns>
2369 public SceneObjectPart[] GetParts()
2370 {
2371 int numParts = Children.Count;
2372 SceneObjectPart[] partArray = new SceneObjectPart[numParts];
2373 Children.Values.CopyTo(partArray, 0);
2374 return partArray;
2375 }
2376
2377 /// <summary>
2378 /// Update the texture entry for this part
2379 /// </summary>
2380 /// <param name="localID"></param>
2381 /// <param name="textureEntry"></param>
2382 public void UpdateTextureEntry(uint localID, byte[] textureEntry)
2383 {
2384 SceneObjectPart part = GetChildPart(localID);
2385 if (part != null)
2386 {
2387 part.UpdateTextureEntry(textureEntry);
2388 }
2389 }
2390
2391 public void UpdatePermissions(UUID AgentID, byte field, uint localID,
2392 uint mask, byte addRemTF)
2393 {
2394 foreach (SceneObjectPart part in m_parts.Values)
2395 part.UpdatePermissions(AgentID, field, localID, mask,
2396 addRemTF);
2397
2398 HasGroupChanged = true;
2399 }
2400
2401 #endregion
2402
2403 #region Shape
2404
2405 /// <summary>
2406 ///
2407 /// </summary>
2408 /// <param name="shapeBlock"></param>
2409 public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID)
2410 {
2411 SceneObjectPart part = GetChildPart(localID);
2412 if (part != null)
2413 {
2414 part.UpdateShape(shapeBlock);
2415
2416 if (part.PhysActor != null)
2417 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2418 }
2419 }
2420
2421 #endregion
2422
2423 #region Resize
2424
2425 /// <summary>
2426 /// Resize the given part
2427 /// </summary>
2428 /// <param name="scale"></param>
2429 /// <param name="localID"></param>
2430 public void Resize(Vector3 scale, uint localID)
2431 {
2432 if (scale.X > m_scene.m_maxNonphys)
2433 scale.X = m_scene.m_maxNonphys;
2434 if (scale.Y > m_scene.m_maxNonphys)
2435 scale.Y = m_scene.m_maxNonphys;
2436 if (scale.Z > m_scene.m_maxNonphys)
2437 scale.Z = m_scene.m_maxNonphys;
2438
2439 SceneObjectPart part = GetChildPart(localID);
2440 if (part != null)
2441 {
2442 part.Resize(scale);
2443 if (part.PhysActor != null)
2444 {
2445 if (part.PhysActor.IsPhysical)
2446 {
2447 if (scale.X > m_scene.m_maxPhys)
2448 scale.X = m_scene.m_maxPhys;
2449 if (scale.Y > m_scene.m_maxPhys)
2450 scale.Y = m_scene.m_maxPhys;
2451 if (scale.Z > m_scene.m_maxPhys)
2452 scale.Z = m_scene.m_maxPhys;
2453 }
2454 part.PhysActor.Size =
2455 new PhysicsVector(scale.X, scale.Y, scale.Z);
2456 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2457 }
2458 //if (part.UUID != m_rootPart.UUID)
2459
2460 HasGroupChanged = true;
2461 ScheduleGroupForFullUpdate();
2462
2463 //if (part.UUID == m_rootPart.UUID)
2464 //{
2465 //if (m_rootPart.PhysActor != null)
2466 //{
2467 //m_rootPart.PhysActor.Size =
2468 //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
2469 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2470 //}
2471 //}
2472 }
2473 }
2474
2475 public void GroupResize(Vector3 scale, uint localID)
2476 {
2477 SceneObjectPart part = GetChildPart(localID);
2478 if (part != null)
2479 {
2480 if (scale.X > m_scene.m_maxNonphys)
2481 scale.X = m_scene.m_maxNonphys;
2482 if (scale.Y > m_scene.m_maxNonphys)
2483 scale.Y = m_scene.m_maxNonphys;
2484 if (scale.Z > m_scene.m_maxNonphys)
2485 scale.Z = m_scene.m_maxNonphys;
2486 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2487 {
2488 if (scale.X > m_scene.m_maxPhys)
2489 scale.X = m_scene.m_maxPhys;
2490 if (scale.Y > m_scene.m_maxPhys)
2491 scale.Y = m_scene.m_maxPhys;
2492 if (scale.Z > m_scene.m_maxPhys)
2493 scale.Z = m_scene.m_maxPhys;
2494 }
2495 float x = (scale.X / part.Scale.X);
2496 float y = (scale.Y / part.Scale.Y);
2497 float z = (scale.Z / part.Scale.Z);
2498
2499 lock (m_parts)
2500 {
2501 if (x > 1.0f || y > 1.0f || z > 1.0f)
2502 {
2503 foreach (SceneObjectPart obPart in m_parts.Values)
2504 {
2505 if (obPart.UUID != m_rootPart.UUID)
2506 {
2507 Vector3 oldSize = new Vector3(obPart.Scale);
2508
2509 float f = 1.0f;
2510 float a = 1.0f;
2511
2512 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2513 {
2514 if (oldSize.X*x > m_scene.m_maxPhys)
2515 {
2516 f = m_scene.m_maxPhys / oldSize.X;
2517 a = f / x;
2518 x *= a;
2519 y *= a;
2520 z *= a;
2521 }
2522 if (oldSize.Y*y > m_scene.m_maxPhys)
2523 {
2524 f = m_scene.m_maxPhys / oldSize.Y;
2525 a = f / y;
2526 x *= a;
2527 y *= a;
2528 z *= a;
2529 }
2530 if (oldSize.Z*z > m_scene.m_maxPhys)
2531 {
2532 f = m_scene.m_maxPhys / oldSize.Z;
2533 a = f / z;
2534 x *= a;
2535 y *= a;
2536 z *= a;
2537 }
2538 }
2539 else
2540 {
2541 if (oldSize.X*x > m_scene.m_maxNonphys)
2542 {
2543 f = m_scene.m_maxNonphys / oldSize.X;
2544 a = f / x;
2545 x *= a;
2546 y *= a;
2547 z *= a;
2548 }
2549 if (oldSize.Y*y > m_scene.m_maxNonphys)
2550 {
2551 f = m_scene.m_maxNonphys / oldSize.Y;
2552 a = f / y;
2553 x *= a;
2554 y *= a;
2555 z *= a;
2556 }
2557 if (oldSize.Z*z > m_scene.m_maxNonphys)
2558 {
2559 f = m_scene.m_maxNonphys / oldSize.Z;
2560 a = f / z;
2561 x *= a;
2562 y *= a;
2563 z *= a;
2564 }
2565 }
2566 }
2567 }
2568 }
2569 }
2570
2571 Vector3 prevScale = part.Scale;
2572 prevScale.X *= x;
2573 prevScale.Y *= y;
2574 prevScale.Z *= z;
2575 part.Resize(prevScale);
2576
2577 lock (m_parts)
2578 {
2579 foreach (SceneObjectPart obPart in m_parts.Values)
2580 {
2581 if (obPart.UUID != m_rootPart.UUID)
2582 {
2583 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2584 currentpos.X *= x;
2585 currentpos.Y *= y;
2586 currentpos.Z *= z;
2587 Vector3 newSize = new Vector3(obPart.Scale);
2588 newSize.X *= x;
2589 newSize.Y *= y;
2590 newSize.Z *= z;
2591 obPart.Resize(newSize);
2592 obPart.UpdateOffSet(currentpos);
2593 }
2594 }
2595 }
2596
2597 if (part.PhysActor != null)
2598 {
2599 part.PhysActor.Size =
2600 new PhysicsVector(prevScale.X, prevScale.Y, prevScale.Z);
2601 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2602 }
2603
2604 HasGroupChanged = true;
2605 ScheduleGroupForTerseUpdate();
2606 }
2607 }
2608
2609 #endregion
2610
2611 #region Position
2612
2613 /// <summary>
2614 /// Move this scene object
2615 /// </summary>
2616 /// <param name="pos"></param>
2617 public void UpdateGroupPosition(Vector3 pos)
2618 {
2619 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2620 {
2621 if (IsAttachment)
2622 {
2623 m_rootPart.AttachedPos = pos;
2624 }
2625
2626 AbsolutePosition = pos;
2627
2628 HasGroupChanged = true;
2629 }
2630
2631 //we need to do a terse update even if the move wasn't allowed
2632 // so that the position is reset in the client (the object snaps back)
2633 ScheduleGroupForTerseUpdate();
2634 }
2635
2636 /// <summary>
2637 /// Update the position of a single part of this scene object
2638 /// </summary>
2639 /// <param name="pos"></param>
2640 /// <param name="localID"></param>
2641 public void UpdateSinglePosition(Vector3 pos, uint localID)
2642 {
2643 SceneObjectPart part = GetChildPart(localID);
2644
2645 if (part != null)
2646 {
2647 if (part.UUID == m_rootPart.UUID)
2648 {
2649 UpdateRootPosition(pos);
2650 }
2651 else
2652 {
2653 part.UpdateOffSet(pos);
2654 }
2655
2656 HasGroupChanged = true;
2657 }
2658 }
2659
2660 /// <summary>
2661 ///
2662 /// </summary>
2663 /// <param name="pos"></param>
2664 private void UpdateRootPosition(Vector3 pos)
2665 {
2666 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2667 Vector3 oldPos =
2668 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
2669 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y,
2670 AbsolutePosition.Z + m_rootPart.OffsetPosition.Z);
2671 Vector3 diff = oldPos - newPos;
2672 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
2673 Quaternion partRotation = m_rootPart.RotationOffset;
2674 axDiff *= Quaternion.Inverse(partRotation);
2675 diff = axDiff;
2676
2677 lock (m_parts)
2678 {
2679 foreach (SceneObjectPart obPart in m_parts.Values)
2680 {
2681 if (obPart.UUID != m_rootPart.UUID)
2682 {
2683 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2684 }
2685 }
2686 }
2687
2688 AbsolutePosition = newPos;
2689
2690 HasGroupChanged = true;
2691 ScheduleGroupForTerseUpdate();
2692 }
2693
2694 public void OffsetForNewRegion(Vector3 offset)
2695 {
2696 m_rootPart.GroupPosition = offset;
2697 }
2698
2699 #endregion
2700
2701 #region Rotation
2702
2703 /// <summary>
2704 ///
2705 /// </summary>
2706 /// <param name="rot"></param>
2707 public void UpdateGroupRotation(Quaternion rot)
2708 {
2709 m_rootPart.UpdateRotation(rot);
2710 if (m_rootPart.PhysActor != null)
2711 {
2712 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
2713 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2714 }
2715
2716 HasGroupChanged = true;
2717 ScheduleGroupForTerseUpdate();
2718 }
2719
2720 /// <summary>
2721 ///
2722 /// </summary>
2723 /// <param name="pos"></param>
2724 /// <param name="rot"></param>
2725 public void UpdateGroupRotation(Vector3 pos, Quaternion rot)
2726 {
2727 m_rootPart.UpdateRotation(rot);
2728 if (m_rootPart.PhysActor != null)
2729 {
2730 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
2731 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2732 }
2733 AbsolutePosition = pos;
2734
2735 HasGroupChanged = true;
2736 ScheduleGroupForTerseUpdate();
2737 }
2738
2739 /// <summary>
2740 ///
2741 /// </summary>
2742 /// <param name="rot"></param>
2743 /// <param name="localID"></param>
2744 public void UpdateSingleRotation(Quaternion rot, uint localID)
2745 {
2746 SceneObjectPart part = GetChildPart(localID);
2747 if (part != null)
2748 {
2749 if (part.UUID == m_rootPart.UUID)
2750 {
2751 UpdateRootRotation(rot);
2752 }
2753 else
2754 {
2755 part.UpdateRotation(rot);
2756 }
2757 }
2758 }
2759
2760 /// <summary>
2761 ///
2762 /// </summary>
2763 /// <param name="rot"></param>
2764 private void UpdateRootRotation(Quaternion rot)
2765 {
2766 Quaternion axRot = rot;
2767 Quaternion oldParentRot = m_rootPart.RotationOffset;
2768
2769 m_rootPart.UpdateRotation(rot);
2770 if (m_rootPart.PhysActor != null)
2771 {
2772 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
2773 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2774 }
2775
2776 lock (m_parts)
2777 {
2778 foreach (SceneObjectPart prim in m_parts.Values)
2779 {
2780 if (prim.UUID != m_rootPart.UUID)
2781 {
2782 Vector3 axPos = prim.OffsetPosition;
2783 axPos *= oldParentRot;
2784 axPos *= Quaternion.Inverse(axRot);
2785 prim.OffsetPosition = axPos;
2786 Quaternion primsRot = prim.RotationOffset;
2787 Quaternion newRot = primsRot * oldParentRot;
2788 newRot *= Quaternion.Inverse(axRot);
2789 prim.RotationOffset = newRot;
2790 prim.ScheduleTerseUpdate();
2791 }
2792 }
2793 }
2794
2795 m_rootPart.ScheduleTerseUpdate();
2796 }
2797
2798 #endregion
2799
2800 internal void SetAxisRotation(int axis, int rotate10)
2801 {
2802 bool setX = false;
2803 bool setY = false;
2804 bool setZ = false;
2805
2806 int xaxis = 2;
2807 int yaxis = 4;
2808 int zaxis = 8;
2809
2810 if (m_rootPart != null)
2811 {
2812 setX = ((axis & xaxis) != 0) ? true : false;
2813 setY = ((axis & yaxis) != 0) ? true : false;
2814 setZ = ((axis & zaxis) != 0) ? true : false;
2815
2816 float setval = (rotate10 > 0) ? 1f : 0f;
2817
2818 if (setX)
2819 m_rootPart.RotationAxis.X = setval;
2820 if (setY)
2821 m_rootPart.RotationAxis.Y = setval;
2822 if (setZ)
2823 m_rootPart.RotationAxis.Z = setval;
2824
2825 if (setX || setY || setZ)
2826 {
2827 m_rootPart.SetPhysicsAxisRotation();
2828 }
2829
2830 }
2831 }
2832
2833 public int registerTargetWaypoint(Vector3 target, float tolerance)
2834 {
2835 scriptPosTarget waypoint = new scriptPosTarget();
2836 waypoint.targetPos = target;
2837 waypoint.tolerance = tolerance;
2838 uint handle = m_scene.AllocateLocalId();
2839 lock (m_targets)
2840 {
2841 m_targets.Add(handle, waypoint);
2842 }
2843 return (int)handle;
2844 }
2845
2846 public void unregisterTargetWaypoint(int handle)
2847 {
2848 lock (m_targets)
2849 {
2850 if (m_targets.ContainsKey((uint)handle))
2851 m_targets.Remove((uint)handle);
2852 }
2853 }
2854
2855 private void checkAtTargets()
2856 {
2857 if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
2858 {
2859 if (m_targets.Count > 0)
2860 {
2861 bool at_target = false;
2862 //Vector3 targetPos;
2863 //uint targetHandle;
2864 Dictionary<uint, scriptPosTarget> atTargets = new Dictionary<uint, scriptPosTarget>();
2865 lock (m_targets)
2866 {
2867 foreach (uint idx in m_targets.Keys)
2868 {
2869 scriptPosTarget target = m_targets[idx];
2870 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
2871 {
2872 // trigger at_target
2873 if (m_scriptListens_atTarget)
2874 {
2875 // Reusing att.tolerance to hold the index of the target in the targets dictionary
2876 // to avoid deadlocking the sim.
2877 at_target = true;
2878 scriptPosTarget att = new scriptPosTarget();
2879 att.targetPos = target.targetPos;
2880 att.tolerance = (float)idx;
2881 atTargets.Add(idx, att);
2882 }
2883 }
2884 }
2885 }
2886 if (atTargets.Count > 0)
2887 {
2888 uint[] localids = new uint[0];
2889 lock (m_parts)
2890 {
2891 localids = new uint[m_parts.Count];
2892 int cntr = 0;
2893 foreach (SceneObjectPart part in m_parts.Values)
2894 {
2895 localids[cntr] = part.LocalId;
2896 cntr++;
2897 }
2898 }
2899 for (int ctr = 0; ctr < localids.Length; ctr++)
2900 {
2901 foreach (uint target in atTargets.Keys)
2902 {
2903 scriptPosTarget att = atTargets[target];
2904 // Reusing att.tolerance to hold the index of the target in the targets dictionary
2905 // to avoid deadlocking the sim.
2906 m_scene.TriggerAtTargetEvent(localids[ctr], (uint)att.tolerance, att.targetPos, m_rootPart.GroupPosition);
2907
2908
2909 }
2910 }
2911 return;
2912 }
2913 if (m_scriptListens_notAtTarget && !at_target)
2914 {
2915 //trigger not_at_target
2916 uint[] localids = new uint[0];
2917 lock (m_parts)
2918 {
2919 localids = new uint[m_parts.Count];
2920 int cntr = 0;
2921 foreach (SceneObjectPart part in m_parts.Values)
2922 {
2923 localids[cntr] = part.LocalId;
2924 cntr++;
2925 }
2926 }
2927 for (int ctr = 0; ctr < localids.Length; ctr++)
2928 {
2929 m_scene.TriggerNotAtTargetEvent(localids[ctr]);
2930 }
2931 }
2932 }
2933 }
2934 }
2935
2936 public float GetMass()
2937 {
2938 float retmass = 0f;
2939 lock (m_parts)
2940 {
2941 foreach (SceneObjectPart part in m_parts.Values)
2942 {
2943 retmass += part.GetMass();
2944 }
2945 }
2946 return retmass;
2947 }
2948
2949 public void CheckSculptAndLoad()
2950 {
2951 lock (m_parts)
2952 {
2953 if (!IsDeleted)
2954 {
2955 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == 0)
2956 {
2957 foreach (SceneObjectPart part in m_parts.Values)
2958 {
2959 if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero)
2960 {
2961 m_scene.AssetCache.GetAsset(part.Shape.SculptTexture, part.SculptTextureCallback, true);
2962 }
2963 }
2964 }
2965 }
2966 }
2967 }
2968
2969 /// <summary>
2970 /// Set the user group to which this scene object belongs.
2971 /// </summary>
2972 /// <param name="GroupID"></param>
2973 /// <param name="client"></param>
2974 public void SetGroup(UUID GroupID, IClientAPI client)
2975 {
2976 lock (m_parts)
2977 {
2978 foreach (SceneObjectPart part in m_parts.Values)
2979 {
2980 part.SetGroup(GroupID, client);
2981 part.Inventory.ChangeInventoryGroup(GroupID);
2982 }
2983
2984 HasGroupChanged = true;
2985 }
2986
2987 ScheduleGroupForFullUpdate();
2988 }
2989
2990 public void TriggerScriptChangedEvent(Changed val)
2991 {
2992 foreach (SceneObjectPart part in Children.Values)
2993 {
2994 part.TriggerScriptChangedEvent(val);
2995 }
2996 }
2997
2998 public override string ToString()
2999 {
3000 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
3001 }
3002
3003 public void SetAttachmentPoint(byte point)
3004 {
3005 lock (m_parts)
3006 {
3007 foreach (SceneObjectPart part in m_parts.Values)
3008 part.SetAttachmentPoint(point);
3009 }
3010 }
3011 }
3012}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
deleted file mode 100644
index 256d6f8..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ /dev/null
@@ -1,3826 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Reflection;
32using System.Runtime.Serialization;
33using System.Security.Permissions;
34using System.Xml;
35using System.Xml.Serialization;
36using log4net;
37using OpenMetaverse;
38using OpenMetaverse.Packets;
39using OpenSim.Framework;
40using OpenSim.Region.Environment.Interfaces;
41using OpenSim.Region.Environment.Scenes.Scripting;
42using OpenSim.Region.Physics.Manager;
43
44namespace OpenSim.Region.Environment.Scenes
45{
46 #region Enumerations
47
48 [Flags]
49 public enum Changed : uint
50 {
51 INVENTORY = 1,
52 COLOR = 2,
53 SHAPE = 4,
54 SCALE = 8,
55 TEXTURE = 16,
56 LINK = 32,
57 ALLOWED_DROP = 64,
58 OWNER = 128,
59 REGION_RESTART = 256,
60 REGION = 512,
61 TELEPORT = 1024
62 }
63
64 // I don't really know where to put this except here.
65 // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants
66 [Flags]
67 public enum ExtraParamType
68 {
69 Something1 = 1,
70 Something2 = 2,
71 Something3 = 4,
72 Something4 = 8,
73 Flexible = 16,
74 Light = 32,
75 Sculpt = 48,
76 Something5 = 64,
77 Something6 = 128
78 }
79
80 [Flags]
81 public enum TextureAnimFlags : byte
82 {
83 NONE = 0x00,
84 ANIM_ON = 0x01,
85 LOOP = 0x02,
86 REVERSE = 0x04,
87 PING_PONG = 0x08,
88 SMOOTH = 0x10,
89 ROTATE = 0x20,
90 SCALE = 0x40
91 }
92
93 #endregion Enumerations
94
95 [Serializable]
96 public class SceneObjectPart : IScriptHost, ISerializable
97 {
98 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
99
100 // use only one serializer to give the runtime a chance to optimize it (it won't do that if you
101 // use a new instance every time)
102 private static XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart));
103
104 #region Fields
105
106 [XmlIgnore]
107 public bool AllowedDrop = false;
108
109 [XmlIgnore]
110 public bool DIE_AT_EDGE = false;
111
112 // TODO: This needs to be persisted in next XML version update!
113 [XmlIgnore]
114 public int[] PayPrice = {-2,-2,-2,-2,-2};
115 [XmlIgnore]
116 public PhysicsActor PhysActor = null;
117
118 //Xantor 20080528 Sound stuff:
119 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet.
120 // Not a big problem as long as the script that sets it remains in the prim on startup.
121 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script)
122 [XmlIgnore]
123 public UUID Sound;
124
125 [XmlIgnore]
126 public byte SoundFlags;
127
128 [XmlIgnore]
129 public double SoundGain;
130
131 [XmlIgnore]
132 public double SoundRadius;
133
134 [XmlIgnore]
135 public uint TimeStampFull = 0;
136
137 [XmlIgnore]
138 public uint TimeStampLastActivity = 0; // Will be used for AutoReturn
139
140 [XmlIgnore]
141 public uint TimeStampTerse = 0;
142
143 [XmlIgnore]
144 public UUID FromAssetID = UUID.Zero;
145
146 /// <value>
147 /// The UUID of the user inventory item from which this object was rezzed if this is a root part.
148 /// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item.
149 /// </value>
150 private UUID m_fromUserInventoryItemID = UUID.Zero;
151
152 [XmlIgnore]
153 public UUID FromUserInventoryItemID
154 {
155 get { return m_fromUserInventoryItemID; }
156 }
157
158 [XmlIgnore]
159 public bool IsAttachment = false;
160
161 [XmlIgnore]
162 public scriptEvents AggregateScriptEvents = 0;
163
164 [XmlIgnore]
165 public UUID AttachedAvatar = UUID.Zero;
166
167 [XmlIgnore]
168 public Vector3 AttachedPos = Vector3.Zero;
169
170 [XmlIgnore]
171 public uint AttachmentPoint = (byte)0;
172
173 [XmlIgnore]
174 public PhysicsVector RotationAxis = new PhysicsVector(1f,1f,1f);
175
176 [XmlIgnore]
177 public bool VolumeDetectActive = false; // XmlIgnore set to avoid problems with persistance until I come to care for this
178 // Certainly this must be a persistant setting finally
179
180 /// <summary>
181 /// This part's inventory
182 /// </summary>
183 [XmlIgnore]
184 public IEntityInventory Inventory
185 {
186 get { return m_inventory; }
187 }
188 protected SceneObjectPartInventory m_inventory;
189
190 [XmlIgnore]
191 public bool Undoing = false;
192
193 [XmlIgnore]
194 private PrimFlags LocalFlags = 0;
195 private byte[] m_TextureAnimation;
196 private byte m_clickAction = 0;
197 private Color m_color = Color.Black;
198 private string m_description = String.Empty;
199 private readonly List<uint> m_lastColliders = new List<uint>();
200 // private PhysicsVector m_lastRotationalVelocity = PhysicsVector.Zero;
201 private int m_linkNum = 0;
202 [XmlIgnore]
203 private int m_scriptAccessPin = 0;
204 [XmlIgnore]
205 private readonly Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
206 private string m_sitName = String.Empty;
207 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
208 private Vector3 m_sitTargetPosition = Vector3.Zero;
209 private string m_sitAnimation = "SIT";
210 private string m_text = String.Empty;
211 private string m_touchName = String.Empty;
212 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
213 private UUID _creatorID;
214
215 /// <summary>
216 /// Only used internally to schedule client updates.
217 /// 0 - no update is scheduled
218 /// 1 - terse update scheduled
219 /// 2 - full update scheduled
220 ///
221 /// TODO - This should be an enumeration
222 /// </summary>
223 private byte m_updateFlag;
224
225 protected Vector3 m_acceleration;
226 protected Vector3 m_angularVelocity;
227
228 //unkown if this will be kept, added as a way of removing the group position from the group class
229 protected Vector3 m_groupPosition;
230 protected uint m_localId;
231 protected Material m_material = (Material)3; // Wood
232 protected string m_name;
233 protected Vector3 m_offsetPosition;
234
235 // FIXME, TODO, ERROR: 'ParentGroup' can't be in here, move it out.
236 protected SceneObjectGroup m_parentGroup;
237 protected byte[] m_particleSystem = new byte[0];
238 protected ulong m_regionHandle;
239 protected Quaternion m_rotationOffset;
240 protected PrimitiveBaseShape m_shape = null;
241 protected UUID m_uuid;
242 protected Vector3 m_velocity;
243
244 // TODO: Those have to be changed into persistent properties at some later point,
245 // or sit-camera on vehicles will break on sim-crossing.
246 private Vector3 m_cameraEyeOffset = new Vector3(0.0f, 0.0f, 0.0f);
247 private Vector3 m_cameraAtOffset = new Vector3(0.0f, 0.0f, 0.0f);
248 private bool m_forceMouselook = false;
249
250 // TODO: Collision sound should have default.
251 private UUID m_collisionSound = UUID.Zero;
252 private float m_collisionSoundVolume = 0.0f;
253
254 #endregion Fields
255
256 #region Constructors
257
258 /// <summary>
259 /// No arg constructor called by region restore db code
260 /// </summary>
261 public SceneObjectPart()
262 {
263 // It's not necessary to persist this
264 m_TextureAnimation = new byte[0];
265 m_particleSystem = new byte[0];
266 Rezzed = DateTime.Now;
267
268 m_inventory = new SceneObjectPartInventory(this);
269 }
270
271 /// <summary>
272 /// Create a completely new SceneObjectPart (prim). This will need to be added separately to a SceneObjectGroup
273 /// </summary>
274 /// <param name="ownerID"></param>
275 /// <param name="shape"></param>
276 /// <param name="position"></param>
277 /// <param name="rotationOffset"></param>
278 /// <param name="offsetPosition"></param>
279 public SceneObjectPart(
280 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
281 Quaternion rotationOffset, Vector3 offsetPosition)
282 {
283 m_name = "Primitive";
284
285 Rezzed = DateTime.Now;
286 _creationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
287 _ownerID = ownerID;
288 _creatorID = _ownerID;
289 _lastOwnerID = UUID.Zero;
290 UUID = UUID.Random();
291 Shape = shape;
292 // Todo: Add More Object Parameter from above!
293 _ownershipCost = 0;
294 _objectSaleType = (byte) 0;
295 _salePrice = 0;
296 _category = (uint) 0;
297 _lastOwnerID = _creatorID;
298 // End Todo: ///
299 GroupPosition = groupPosition;
300 OffsetPosition = offsetPosition;
301 RotationOffset = rotationOffset;
302 Velocity = new Vector3(0, 0, 0);
303 AngularVelocity = new Vector3(0, 0, 0);
304 Acceleration = new Vector3(0, 0, 0);
305 m_TextureAnimation = new byte[0];
306 m_particleSystem = new byte[0];
307
308 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
309 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
310 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
311
312 _flags = 0;
313 _flags |= PrimFlags.CreateSelected;
314
315 TrimPermissions();
316 //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo());
317
318 m_inventory = new SceneObjectPartInventory(this);
319 }
320
321 protected SceneObjectPart(SerializationInfo info, StreamingContext context)
322 {
323 //System.Console.WriteLine("SceneObjectPart Deserialize BGN");
324 m_TextureAnimation = new byte[0];
325 m_particleSystem = new byte[0];
326 if (info == null)
327 {
328 throw new ArgumentNullException("info");
329 }
330
331 /*
332 m_queue = (Queue<SceneObjectPart>)info.GetValue("m_queue", typeof(Queue<SceneObjectPart>));
333 m_ids = (List<UUID>)info.GetValue("m_ids", typeof(List<UUID>));
334 */
335
336 //System.Console.WriteLine("SceneObjectPart Deserialize END");
337 Rezzed = DateTime.Now;
338
339 m_inventory = new SceneObjectPartInventory(this);
340 }
341
342 #endregion Constructors
343
344 #region XML Schema
345
346 private UUID _lastOwnerID;
347 private UUID _ownerID;
348 private UUID _groupID;
349 private int _ownershipCost;
350 private byte _objectSaleType;
351 private int _salePrice;
352 private uint _category;
353 private Int32 _creationDate;
354 private uint _parentID = 0;
355 private UUID m_sitTargetAvatar = UUID.Zero;
356 private uint _baseMask = (uint)PermissionMask.All;
357 private uint _ownerMask = (uint)PermissionMask.All;
358 private uint _groupMask = (uint)PermissionMask.None;
359 private uint _everyoneMask = (uint)PermissionMask.None;
360 private uint _nextOwnerMask = (uint)PermissionMask.All;
361 private PrimFlags _flags = 0;
362 private DateTime m_expires;
363 private DateTime m_rezzed;
364
365 public UUID CreatorID
366 {
367 get
368 {
369 return _creatorID;
370 }
371 set
372 {
373 _creatorID = value;
374 }
375 }
376
377 /// <summary>
378 /// Exposing this is not particularly good, but it's one of the least evils at the moment to see
379 /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim.
380 /// </summary>
381 public UUID FolderID
382 {
383 get { return UUID; }
384 set { } // Don't allow assignment, or legacy prims wil b0rk
385 }
386
387 /// <value>
388 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
389 /// </value>
390 public uint InventorySerial
391 {
392 get { return m_inventory.Serial; }
393 set { m_inventory.Serial = value; }
394 }
395
396 /// <value>
397 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
398 /// </value>
399 public TaskInventoryDictionary TaskInventory
400 {
401 get { return m_inventory.Items; }
402 set { m_inventory.Items = value; }
403 }
404
405 public uint ObjectFlags
406 {
407 get { return (uint)_flags; }
408 set { _flags = (PrimFlags)value; }
409 }
410
411 public UUID UUID
412 {
413 get { return m_uuid; }
414 set { m_uuid = value; }
415 }
416
417 public uint LocalId
418 {
419 get { return m_localId; }
420 set { m_localId = value; }
421 }
422
423 public virtual string Name
424 {
425 get { return m_name; }
426 set
427 {
428 m_name = value;
429 if (PhysActor != null)
430 {
431 PhysActor.SOPName = value;
432 }
433 }
434 }
435
436 public byte Material
437 {
438 get { return (byte) m_material; }
439 set { m_material = (Material)value; }
440 }
441
442 public ulong RegionHandle
443 {
444 get { return m_regionHandle; }
445 set { m_regionHandle = value; }
446 }
447
448 public int ScriptAccessPin
449 {
450 get { return m_scriptAccessPin; }
451 set { m_scriptAccessPin = (int)value; }
452 }
453
454 [XmlIgnore]
455 public Byte[] TextureAnimation
456 {
457 get { return m_TextureAnimation; }
458 set { m_TextureAnimation = value; }
459 }
460
461 [XmlIgnore]
462 public Byte[] ParticleSystem
463 {
464 get { return m_particleSystem; }
465 set { m_particleSystem = value; }
466 }
467
468 [XmlIgnore]
469 public DateTime Expires
470 {
471 get { return m_expires; }
472 set { m_expires = value; }
473 }
474
475 [XmlIgnore]
476 public DateTime Rezzed
477 {
478 get { return m_rezzed; }
479 set { m_rezzed = value; }
480 }
481
482 /// <summary>
483 /// The position of the entire group that this prim belongs to.
484 /// </summary>
485 public Vector3 GroupPosition
486 {
487 get
488 {
489 // If this is a linkset, we don't want the physics engine mucking up our group position here.
490 if (PhysActor != null && _parentID == 0)
491 {
492 m_groupPosition.X = PhysActor.Position.X;
493 m_groupPosition.Y = PhysActor.Position.Y;
494 m_groupPosition.Z = PhysActor.Position.Z;
495 }
496
497 if (IsAttachment)
498 {
499 ScenePresence sp = m_parentGroup.Scene.GetScenePresence(AttachedAvatar);
500 if (sp != null)
501 {
502 return sp.AbsolutePosition;
503 }
504 }
505
506 return m_groupPosition;
507 }
508 set
509 {
510 StoreUndoState();
511
512 m_groupPosition = value;
513
514 if (PhysActor != null)
515 {
516 try
517 {
518 // Root prim actually goes at Position
519 if (_parentID == 0)
520 {
521 PhysActor.Position = new PhysicsVector(value.X, value.Y, value.Z);
522 }
523 else
524 {
525 // To move the child prim in respect to the group position and rotation we have to calculate
526 Vector3 resultingposition = GetWorldPosition();
527 PhysActor.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z);
528 Quaternion resultingrot = GetWorldRotation();
529 PhysActor.Orientation = resultingrot;
530 }
531
532 // Tell the physics engines that this prim changed.
533 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
534 }
535 catch (Exception e)
536 {
537 Console.WriteLine("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
538 }
539 }
540
541 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
542 if (m_sitTargetAvatar != UUID.Zero)
543 {
544 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
545 {
546 ScenePresence avatar;
547 if (m_parentGroup.Scene.TryGetAvatar(m_sitTargetAvatar, out avatar))
548 {
549 avatar.ParentPosition = GetWorldPosition();
550 }
551 }
552 }
553 }
554 }
555
556 public Vector3 OffsetPosition
557 {
558 get { return m_offsetPosition; }
559 set
560 {
561 StoreUndoState();
562 m_offsetPosition = value;
563
564 if (ParentGroup != null && !ParentGroup.IsDeleted)
565 {
566 if (_parentID != 0 && PhysActor != null)
567 {
568 Vector3 resultingposition = GetWorldPosition();
569 PhysActor.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z);
570 Quaternion resultingrot = GetWorldRotation();
571 PhysActor.Orientation = resultingrot;
572
573 // Tell the physics engines that this prim changed.
574 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
575 }
576 }
577 }
578 }
579
580 public Quaternion RotationOffset
581 {
582 get
583 {
584 // We don't want the physics engine mucking up the rotations in a linkset
585 if ((_parentID == 0) && (Shape.PCode != 9 || Shape.State == 0) && (PhysActor != null))
586 {
587 if (PhysActor.Orientation.X != 0 || PhysActor.Orientation.Y != 0
588 || PhysActor.Orientation.Z != 0 || PhysActor.Orientation.W != 0)
589 {
590 m_rotationOffset = PhysActor.Orientation;
591 }
592 }
593 return m_rotationOffset;
594 }
595 set
596 {
597 StoreUndoState();
598 m_rotationOffset = value;
599
600 if (PhysActor != null)
601 {
602 try
603 {
604 // Root prim gets value directly
605 if (_parentID == 0)
606 {
607 PhysActor.Orientation = value;
608 //m_log.Info("[PART]: RO1:" + PhysActor.Orientation.ToString());
609 }
610 else
611 {
612 // Child prim we have to calculate it's world rotationwel
613 Quaternion resultingrotation = GetWorldRotation();
614 PhysActor.Orientation = resultingrotation;
615 //m_log.Info("[PART]: RO2:" + PhysActor.Orientation.ToString());
616 }
617 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
618 //}
619 }
620 catch (Exception ex)
621 {
622 Console.WriteLine("[SCENEOBJECTPART]: ROTATIONOFFSET" + ex.Message);
623 }
624 }
625
626 }
627 }
628
629 /// <summary></summary>
630 public Vector3 Velocity
631 {
632 get
633 {
634 //if (PhysActor.Velocity.X != 0 || PhysActor.Velocity.Y != 0
635 //|| PhysActor.Velocity.Z != 0)
636 //{
637 if (PhysActor != null)
638 {
639 if (PhysActor.IsPhysical)
640 {
641 m_velocity.X = PhysActor.Velocity.X;
642 m_velocity.Y = PhysActor.Velocity.Y;
643 m_velocity.Z = PhysActor.Velocity.Z;
644 }
645 }
646
647 return m_velocity;
648 }
649
650 set
651 {
652 m_velocity = value;
653 if (PhysActor != null)
654 {
655 if (PhysActor.IsPhysical)
656 {
657 PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z);
658 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
659 }
660 }
661 }
662 }
663
664 public Vector3 RotationalVelocity
665 {
666 get { return AngularVelocity; }
667 set { AngularVelocity = value; }
668 }
669
670 /// <summary></summary>
671 public Vector3 AngularVelocity
672 {
673 get
674 {
675 if ((PhysActor != null) && PhysActor.IsPhysical)
676 {
677 m_angularVelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(), 0);
678 }
679 return m_angularVelocity;
680 }
681 set { m_angularVelocity = value; }
682 }
683
684 /// <summary></summary>
685 public Vector3 Acceleration
686 {
687 get { return m_acceleration; }
688 set { m_acceleration = value; }
689 }
690
691 public string Description
692 {
693 get { return m_description; }
694 set
695 {
696 m_description = value;
697 if (PhysActor != null)
698 {
699 PhysActor.SOPDescription = value;
700 }
701 }
702 }
703
704 public Color Color
705 {
706 get { return m_color; }
707 set
708 {
709 m_color = value;
710 TriggerScriptChangedEvent(Changed.COLOR);
711
712 /* ScheduleFullUpdate() need not be called b/c after
713 * setting the color, the text will be set, so then
714 * ScheduleFullUpdate() will be called. */
715 //ScheduleFullUpdate();
716 }
717 }
718
719 public string Text
720 {
721 get
722 {
723 string returnstr = m_text;
724 if (returnstr.Length > 255)
725 {
726 returnstr = returnstr.Substring(0, 254);
727 }
728 return returnstr;
729 }
730 set
731 {
732 m_text = value;
733 }
734 }
735
736
737 public string SitName
738 {
739 get { return m_sitName; }
740 set { m_sitName = value; }
741 }
742
743 public string TouchName
744 {
745 get { return m_touchName; }
746 set { m_touchName = value; }
747 }
748
749 public int LinkNum
750 {
751 get { return m_linkNum; }
752 set { m_linkNum = value; }
753 }
754
755 public byte ClickAction
756 {
757 get { return m_clickAction; }
758 set
759 {
760 m_clickAction = value;
761 }
762 }
763
764 public PrimitiveBaseShape Shape
765 {
766 get { return m_shape; }
767 set
768 {
769 bool shape_changed = false;
770 // TODO: this should really be restricted to the right
771 // set of attributes on shape change. For instance,
772 // changing the lighting on a shape shouldn't cause
773 // this.
774 if (m_shape != null)
775 shape_changed = true;
776
777 m_shape = value;
778
779 if (shape_changed)
780 TriggerScriptChangedEvent(Changed.SHAPE);
781 }
782 }
783
784 public Vector3 Scale
785 {
786 get { return m_shape.Scale; }
787 set
788 {
789 StoreUndoState();
790if (m_shape != null) {
791 m_shape.Scale = value;
792
793 if (PhysActor != null && m_parentGroup != null)
794 {
795 if (m_parentGroup.Scene != null)
796 {
797 if (m_parentGroup.Scene.PhysicsScene != null)
798 {
799 PhysActor.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z);
800 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
801 }
802 }
803 }
804}
805 TriggerScriptChangedEvent(Changed.SCALE);
806 }
807 }
808 public byte UpdateFlag
809 {
810 get { return m_updateFlag; }
811 set { m_updateFlag = value; }
812 }
813
814 #endregion
815
816//---------------
817#region Public Properties with only Get
818
819 public Vector3 AbsolutePosition
820 {
821 get {
822 if (IsAttachment)
823 return GroupPosition;
824
825 return m_offsetPosition + m_groupPosition; }
826 }
827
828 public UUID ObjectCreator
829 {
830 get { return _creatorID; }
831 }
832
833 public UUID ObjectOwner
834 {
835 get { return _ownerID; }
836 }
837
838 public SceneObjectGroup ParentGroup
839 {
840 get { return m_parentGroup; }
841 }
842
843 public scriptEvents ScriptEvents
844 {
845 get { return AggregateScriptEvents; }
846 }
847
848
849 public Quaternion SitTargetOrientation
850 {
851 get { return m_sitTargetOrientation; }
852 set { m_sitTargetOrientation = value; }
853 }
854
855
856 public Vector3 SitTargetPosition
857 {
858 get { return m_sitTargetPosition; }
859 set { m_sitTargetPosition = value; }
860 }
861
862 // This sort of sucks, but I'm adding these in to make some of
863 // the mappings more consistant.
864 public Vector3 SitTargetPositionLL
865 {
866 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); }
867 set { m_sitTargetPosition = value; }
868 }
869
870 public Quaternion SitTargetOrientationLL
871 {
872 get
873 {
874 return new Quaternion(
875 m_sitTargetOrientation.X,
876 m_sitTargetOrientation.Y,
877 m_sitTargetOrientation.Z,
878 m_sitTargetOrientation.W
879 );
880 }
881
882 set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); }
883 }
884
885 public bool Stopped
886 {
887 get {
888 double threshold = 0.02;
889 return (Math.Abs(Velocity.X) < threshold &&
890 Math.Abs(Velocity.Y) < threshold &&
891 Math.Abs(Velocity.Z) < threshold &&
892 Math.Abs(AngularVelocity.X) < threshold &&
893 Math.Abs(AngularVelocity.Y) < threshold &&
894 Math.Abs(AngularVelocity.Z) < threshold);
895 }
896 }
897
898 public uint ParentID
899 {
900 get { return _parentID; }
901 set { _parentID = value; }
902 }
903
904 public int CreationDate
905 {
906 get { return _creationDate; }
907 set { _creationDate = value; }
908 }
909
910 public uint Category
911 {
912 get { return _category; }
913 set { _category = value; }
914 }
915
916 public int SalePrice
917 {
918 get { return _salePrice; }
919 set { _salePrice = value; }
920 }
921
922 public byte ObjectSaleType
923 {
924 get { return _objectSaleType; }
925 set { _objectSaleType = value; }
926 }
927
928 public int OwnershipCost
929 {
930 get { return _ownershipCost; }
931 set { _ownershipCost = value; }
932 }
933
934 public UUID GroupID
935 {
936 get { return _groupID; }
937 set { _groupID = value; }
938 }
939
940 public UUID OwnerID
941 {
942 get { return _ownerID; }
943 set { _ownerID = value; }
944 }
945
946 public UUID LastOwnerID
947 {
948 get { return _lastOwnerID; }
949 set { _lastOwnerID = value; }
950 }
951
952 public uint BaseMask
953 {
954 get { return _baseMask; }
955 set { _baseMask = value; }
956 }
957
958 public uint OwnerMask
959 {
960 get { return _ownerMask; }
961 set { _ownerMask = value; }
962 }
963
964 public uint GroupMask
965 {
966 get { return _groupMask; }
967 set { _groupMask = value; }
968 }
969
970 public uint EveryoneMask
971 {
972 get { return _everyoneMask; }
973 set { _everyoneMask = value; }
974 }
975
976 public uint NextOwnerMask
977 {
978 get { return _nextOwnerMask; }
979 set { _nextOwnerMask = value; }
980 }
981
982 public PrimFlags Flags
983 {
984 get { return _flags; }
985 set { _flags = value; }
986 }
987
988 [XmlIgnore]
989 public UUID SitTargetAvatar
990 {
991 get { return m_sitTargetAvatar; }
992 set { m_sitTargetAvatar = value; }
993 }
994
995 [XmlIgnore]
996 public virtual UUID RegionID
997 {
998 get
999 {
1000 if (ParentGroup != null && ParentGroup.Scene != null)
1001 return ParentGroup.Scene.RegionInfo.RegionID;
1002 else
1003 return UUID.Zero;
1004 }
1005 set {} // read only
1006 }
1007
1008 private UUID _parentUUID = UUID.Zero;
1009 [XmlIgnore]
1010 public UUID ParentUUID
1011 {
1012 get
1013 {
1014 if (ParentGroup != null)
1015 {
1016 _parentUUID = ParentGroup.UUID;
1017 }
1018 return _parentUUID;
1019 }
1020 set { _parentUUID = value; }
1021 }
1022
1023 [XmlIgnore]
1024 public string SitAnimation
1025 {
1026 get { return m_sitAnimation; }
1027 set { m_sitAnimation = value; }
1028 }
1029
1030 public UUID CollisionSound
1031 {
1032 get { return m_collisionSound; }
1033 set
1034 {
1035 m_collisionSound = value;
1036 aggregateScriptEvents();
1037 }
1038 }
1039
1040 public float CollisionSoundVolume
1041 {
1042 get { return m_collisionSoundVolume; }
1043 set { m_collisionSoundVolume = value; }
1044 }
1045
1046 #endregion Public Properties with only Get
1047
1048
1049
1050 #region Private Methods
1051
1052 private uint ApplyMask(uint val, bool set, uint mask)
1053 {
1054 if (set)
1055 {
1056 return val |= mask;
1057 }
1058 else
1059 {
1060 return val &= ~mask;
1061 }
1062 }
1063
1064 /// <summary>
1065 /// Clear all pending updates of parts to clients
1066 /// </summary>
1067 private void ClearUpdateSchedule()
1068 {
1069 m_updateFlag = 0;
1070 }
1071
1072 private void SendObjectPropertiesToClient(UUID AgentID)
1073 {
1074 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
1075 for (int i = 0; i < avatars.Count; i++)
1076 {
1077 // Ugly reference :(
1078 if (avatars[i].UUID == AgentID)
1079 {
1080 m_parentGroup.GetProperties(avatars[i].ControllingClient);
1081 }
1082 }
1083 }
1084
1085 private void handleTimerAccounting(uint localID, double interval)
1086 {
1087 if (localID == LocalId)
1088 {
1089
1090 float sec = (float)interval;
1091 if (m_parentGroup != null)
1092 {
1093 if (sec == 0)
1094 {
1095 if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001)
1096 m_parentGroup.scriptScore = 0;
1097
1098 m_parentGroup.scriptScore += 0.001f;
1099 return;
1100 }
1101
1102 if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec))
1103 m_parentGroup.scriptScore = 0;
1104 m_parentGroup.scriptScore += (0.001f / sec);
1105 }
1106
1107 }
1108 }
1109
1110 #endregion Private Methods
1111
1112 #region Public Methods
1113
1114 public void ResetExpire()
1115 {
1116 Expires = DateTime.Now + new TimeSpan(600000000);
1117 }
1118
1119 public void AddFlag(PrimFlags flag)
1120 {
1121 // PrimFlags prevflag = Flags;
1122 if ((ObjectFlags & (uint) flag) == 0)
1123 {
1124 //Console.WriteLine("Adding flag: " + ((PrimFlags) flag).ToString());
1125 _flags |= flag;
1126
1127 if (flag == PrimFlags.TemporaryOnRez)
1128 ResetExpire();
1129 }
1130 // System.Console.WriteLine("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
1131 }
1132
1133 /// <summary>
1134 /// Tell all scene presences that they should send updates for this part to their clients
1135 /// </summary>
1136 public void AddFullUpdateToAllAvatars()
1137 {
1138 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
1139 for (int i = 0; i < avatars.Count; i++)
1140 {
1141 avatars[i].QueuePartForUpdate(this);
1142 }
1143 }
1144
1145 public void AddFullUpdateToAvatar(ScenePresence presence)
1146 {
1147 presence.QueuePartForUpdate(this);
1148 }
1149
1150 public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
1151 {
1152 m_particleSystem = pSystem.GetBytes();
1153 }
1154
1155 public void RemoveParticleSystem()
1156 {
1157 m_particleSystem = new byte[0];
1158 }
1159
1160 /// Terse updates
1161 public void AddTerseUpdateToAllAvatars()
1162 {
1163 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
1164 for (int i = 0; i < avatars.Count; i++)
1165 {
1166 avatars[i].QueuePartForUpdate(this);
1167 }
1168 }
1169
1170 public void AddTerseUpdateToAvatar(ScenePresence presence)
1171 {
1172 presence.QueuePartForUpdate(this);
1173 }
1174
1175 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
1176 {
1177 byte[] data = new byte[16];
1178 int pos = 0;
1179
1180 // The flags don't like conversion from uint to byte, so we have to do
1181 // it the crappy way. See the above function :(
1182
1183 data[pos] = ConvertScriptUintToByte((uint)pTexAnim.Flags); pos++;
1184 data[pos] = (byte)pTexAnim.Face; pos++;
1185 data[pos] = (byte)pTexAnim.SizeX; pos++;
1186 data[pos] = (byte)pTexAnim.SizeY; pos++;
1187
1188 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1189 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1190 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1191
1192 m_TextureAnimation = data;
1193 }
1194
1195 public void AdjustSoundGain(double volume)
1196 {
1197 if (volume > 1)
1198 volume = 1;
1199 if (volume < 0)
1200 volume = 0;
1201
1202 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
1203 foreach (ScenePresence p in avatarts)
1204 {
1205 p.ControllingClient.SendAttachedSoundGainChange(UUID, (float)volume);
1206 }
1207 }
1208
1209 /// <summary>
1210 /// hook to the physics scene to apply impulse
1211 /// This is sent up to the group, which then finds the root prim
1212 /// and applies the force on the root prim of the group
1213 /// </summary>
1214 /// <param name="impulsei">Vector force</param>
1215 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1216 public void ApplyImpulse(Vector3 impulsei, bool localGlobalTF)
1217 {
1218 PhysicsVector impulse = new PhysicsVector(impulsei.X, impulsei.Y, impulsei.Z);
1219
1220 if (localGlobalTF)
1221 {
1222 Quaternion grot = GetWorldRotation();
1223 Quaternion AXgrot = grot;
1224 Vector3 AXimpulsei = impulsei;
1225 Vector3 newimpulse = AXimpulsei * AXgrot;
1226 impulse = new PhysicsVector(newimpulse.X, newimpulse.Y, newimpulse.Z);
1227 }
1228
1229 if (m_parentGroup != null)
1230 {
1231 m_parentGroup.applyImpulse(impulse);
1232 }
1233 }
1234
1235
1236 /// <summary>
1237 /// hook to the physics scene to apply angular impulse
1238 /// This is sent up to the group, which then finds the root prim
1239 /// and applies the force on the root prim of the group
1240 /// </summary>
1241 /// <param name="impulsei">Vector force</param>
1242 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1243 public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF)
1244 {
1245 PhysicsVector impulse = new PhysicsVector(impulsei.X, impulsei.Y, impulsei.Z);
1246
1247 if (localGlobalTF)
1248 {
1249 Quaternion grot = GetWorldRotation();
1250 Quaternion AXgrot = grot;
1251 Vector3 AXimpulsei = impulsei;
1252 Vector3 newimpulse = AXimpulsei * AXgrot;
1253 impulse = new PhysicsVector(newimpulse.X, newimpulse.Y, newimpulse.Z);
1254 }
1255
1256 if (m_parentGroup != null)
1257 {
1258 m_parentGroup.applyAngularImpulse(impulse);
1259 }
1260 }
1261
1262 /// <summary>
1263 /// hook to the physics scene to apply angular impulse
1264 /// This is sent up to the group, which then finds the root prim
1265 /// and applies the force on the root prim of the group
1266 /// </summary>
1267 /// <param name="impulsei">Vector force</param>
1268 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1269 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF)
1270 {
1271 PhysicsVector impulse = new PhysicsVector(impulsei.X, impulsei.Y, impulsei.Z);
1272
1273 if (localGlobalTF)
1274 {
1275 Quaternion grot = GetWorldRotation();
1276 Quaternion AXgrot = grot;
1277 Vector3 AXimpulsei = impulsei;
1278 Vector3 newimpulse = AXimpulsei * AXgrot;
1279 impulse = new PhysicsVector(newimpulse.X, newimpulse.Y, newimpulse.Z);
1280 }
1281
1282 if (m_parentGroup != null)
1283 {
1284 m_parentGroup.setAngularImpulse(impulse);
1285 }
1286 }
1287
1288 public Vector3 GetTorque()
1289 {
1290 if (m_parentGroup != null)
1291 {
1292 m_parentGroup.GetTorque();
1293 }
1294 return Vector3.Zero;
1295 }
1296
1297 /// <summary>
1298 /// Apply physics to this part.
1299 /// </summary>
1300 /// <param name="rootObjectFlags"></param>
1301 /// <param name="m_physicalPrim"></param>
1302 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool m_physicalPrim)
1303 {
1304 bool isPhysical = (((rootObjectFlags & (uint) PrimFlags.Physics) != 0) && m_physicalPrim);
1305 bool isPhantom = ((rootObjectFlags & (uint) PrimFlags.Phantom) != 0);
1306
1307 if (IsJoint())
1308 {
1309 DoPhysicsPropertyUpdate(isPhysical, true);
1310 }
1311 else
1312 {
1313 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored
1314 if (VolumeDetectActive)
1315 isPhantom = false;
1316
1317 // Added clarification.. since A rigid body is an object that you can kick around, etc.
1318 bool RigidBody = isPhysical && !isPhantom;
1319
1320 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
1321 if (!isPhantom && !IsAttachment)
1322 {
1323 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1324 Name,
1325 Shape,
1326 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z),
1327 new PhysicsVector(Scale.X, Scale.Y, Scale.Z),
1328 RotationOffset,
1329 RigidBody);
1330
1331 // Basic Physics returns null.. joy joy joy.
1332 if (PhysActor != null)
1333 {
1334 PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info
1335 PhysActor.SOPDescription = this.Description;
1336 PhysActor.LocalID = LocalId;
1337 DoPhysicsPropertyUpdate(RigidBody, true);
1338 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1339 }
1340 }
1341 }
1342 }
1343
1344 public void ClearUndoState()
1345 {
1346 lock (m_undo)
1347 {
1348 m_undo.Clear();
1349 }
1350 StoreUndoState();
1351 }
1352
1353 public byte ConvertScriptUintToByte(uint indata)
1354 {
1355 byte outdata = (byte)TextureAnimFlags.NONE;
1356 if ((indata & 1) != 0) outdata |= (byte)TextureAnimFlags.ANIM_ON;
1357 if ((indata & 2) != 0) outdata |= (byte)TextureAnimFlags.LOOP;
1358 if ((indata & 4) != 0) outdata |= (byte)TextureAnimFlags.REVERSE;
1359 if ((indata & 8) != 0) outdata |= (byte)TextureAnimFlags.PING_PONG;
1360 if ((indata & 16) != 0) outdata |= (byte)TextureAnimFlags.SMOOTH;
1361 if ((indata & 32) != 0) outdata |= (byte)TextureAnimFlags.ROTATE;
1362 if ((indata & 64) != 0) outdata |= (byte)TextureAnimFlags.SCALE;
1363 return outdata;
1364 }
1365
1366 /// <summary>
1367 /// Duplicates this part.
1368 /// </summary>
1369 /// <returns></returns>
1370 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1371 {
1372 SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone();
1373 dupe.m_shape = m_shape.Copy();
1374 dupe.m_regionHandle = m_regionHandle;
1375 if (userExposed)
1376 dupe.UUID = UUID.Random();
1377
1378 //memberwiseclone means it also clones the physics actor reference
1379 // This will make physical prim 'bounce' if not set to null.
1380 if (!userExposed)
1381 dupe.PhysActor = null;
1382
1383 dupe._ownerID = AgentID;
1384 dupe._groupID = GroupID;
1385 dupe.GroupPosition = GroupPosition;
1386 dupe.OffsetPosition = OffsetPosition;
1387 dupe.RotationOffset = RotationOffset;
1388 dupe.Velocity = new Vector3(0, 0, 0);
1389 dupe.Acceleration = new Vector3(0, 0, 0);
1390 dupe.AngularVelocity = new Vector3(0, 0, 0);
1391 dupe.ObjectFlags = ObjectFlags;
1392
1393 dupe._ownershipCost = _ownershipCost;
1394 dupe._objectSaleType = _objectSaleType;
1395 dupe._salePrice = _salePrice;
1396 dupe._category = _category;
1397 dupe.m_rezzed = m_rezzed;
1398
1399 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1400 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1401
1402 if (userExposed)
1403 {
1404 dupe.ResetIDs(linkNum);
1405 dupe.m_inventory.HasInventoryChanged = true;
1406 }
1407 else
1408 {
1409 dupe.m_inventory.HasInventoryChanged = m_inventory.HasInventoryChanged;
1410 }
1411
1412 // Move afterwards ResetIDs as it clears the localID
1413 dupe.LocalId = localID;
1414 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1415 dupe._lastOwnerID = ObjectOwner;
1416
1417 byte[] extraP = new byte[Shape.ExtraParams.Length];
1418 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1419 dupe.Shape.ExtraParams = extraP;
1420
1421 if (userExposed)
1422 {
1423 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
1424 {
1425 m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true);
1426 }
1427 bool UsePhysics = ((dupe.ObjectFlags & (uint)PrimFlags.Physics) != 0);
1428 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1429 }
1430
1431 return dupe;
1432 }
1433
1434 public static SceneObjectPart Create()
1435 {
1436 SceneObjectPart part = new SceneObjectPart();
1437 part.UUID = UUID.Random();
1438
1439 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1440 part.Shape = shape;
1441
1442 part.Name = "Primitive";
1443 part._ownerID = UUID.Random();
1444
1445 return part;
1446 }
1447
1448 public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew)
1449 {
1450 if (IsJoint())
1451 {
1452 if (UsePhysics)
1453 {
1454 // by turning a joint proxy object physical, we cause creation of a joint in the ODE scene.
1455 // note that, as a special case, joints have no bodies or geoms in the physics scene, even though they are physical.
1456
1457 PhysicsJointType jointType;
1458 if (IsHingeJoint())
1459 {
1460 jointType = PhysicsJointType.Hinge;
1461 }
1462 else if (IsBallJoint())
1463 {
1464 jointType = PhysicsJointType.Ball;
1465 }
1466 else
1467 {
1468 jointType = PhysicsJointType.Ball;
1469 }
1470
1471 List<string> bodyNames = new List<string>();
1472 string RawParams = Description;
1473 string[] jointParams = RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
1474 string trackedBodyName = null;
1475 if (jointParams.Length >= 2)
1476 {
1477 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1478 {
1479 string bodyName = jointParams[iBodyName];
1480 bodyNames.Add(bodyName);
1481 if (bodyName != "NULL")
1482 {
1483 if (trackedBodyName == null)
1484 {
1485 trackedBodyName = bodyName;
1486 }
1487 }
1488 }
1489 }
1490
1491 SceneObjectPart trackedBody = m_parentGroup.Scene.GetSceneObjectPart(trackedBodyName); // FIXME: causes a sequential lookup
1492 Quaternion localRotation = Quaternion.Identity;
1493 if (trackedBody != null)
1494 {
1495 localRotation = Quaternion.Inverse(trackedBody.RotationOffset) * this.RotationOffset;
1496 }
1497 else
1498 {
1499 // error, output it below
1500 }
1501
1502 PhysicsJoint joint;
1503
1504 joint = m_parentGroup.Scene.PhysicsScene.RequestJointCreation(Name, jointType,
1505 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z),
1506 this.RotationOffset,
1507 Description,
1508 bodyNames,
1509 trackedBodyName,
1510 localRotation);
1511
1512 if (trackedBody == null)
1513 {
1514 ParentGroup.Scene.jointErrorMessage(joint, "warning: tracked body name not found! joint location will not be updated properly. joint: " + Name);
1515 }
1516
1517 }
1518 else
1519 {
1520 if (isNew)
1521 {
1522 // if the joint proxy is new, and it is not physical, do nothing. There is no joint in ODE to
1523 // delete, and if we try to delete it, due to asynchronous processing, the deletion request
1524 // will get processed later at an indeterminate time, which could cancel a later-arriving
1525 // joint creation request.
1526 }
1527 else
1528 {
1529 // here we turn off the joint object, so remove the joint from the physics scene
1530 m_parentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed?
1531
1532 // make sure client isn't interpolating the joint proxy object
1533 Velocity = new Vector3(0, 0, 0);
1534 RotationalVelocity = new Vector3(0, 0, 0);
1535 Acceleration = new Vector3(0, 0, 0);
1536 }
1537 }
1538 }
1539 else
1540 {
1541 if (PhysActor != null)
1542 {
1543 if (UsePhysics != PhysActor.IsPhysical || isNew)
1544 {
1545 if (PhysActor.IsPhysical) // implies UsePhysics==false for this block
1546 {
1547 if (!isNew)
1548 ParentGroup.Scene.RemovePhysicalPrim(1);
1549
1550 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1551 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
1552 PhysActor.delink();
1553
1554 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew))
1555 {
1556 // destroy all joints connected to this now deactivated body
1557 m_parentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor);
1558 }
1559
1560 // stop client-side interpolation of all joint proxy objects that have just been deleted
1561 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback,
1562 // which stops client-side interpolation of deactivated joint proxy objects.
1563 }
1564
1565 if (!UsePhysics && !isNew)
1566 {
1567 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1568 // prim still has velocity and continues to interpolate its position along the old
1569 // velocity-vector.
1570 Velocity = new Vector3(0, 0, 0);
1571 Acceleration = new Vector3(0, 0, 0);
1572 AngularVelocity = new Vector3(0, 0, 0);
1573 //RotationalVelocity = new Vector3(0, 0, 0);
1574 }
1575
1576 PhysActor.IsPhysical = UsePhysics;
1577
1578
1579 // If we're not what we're supposed to be in the physics scene, recreate ourselves.
1580 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
1581 /// that's not wholesome. Had to make Scene public
1582 //PhysActor = null;
1583
1584 if ((ObjectFlags & (uint)PrimFlags.Phantom) == 0)
1585 {
1586 if (UsePhysics)
1587 {
1588 ParentGroup.Scene.AddPhysicalPrim(1);
1589
1590 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1591 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1592 if (_parentID != 0 && _parentID != LocalId)
1593 {
1594 if (ParentGroup.RootPart.PhysActor != null)
1595 {
1596 PhysActor.link(ParentGroup.RootPart.PhysActor);
1597 }
1598 }
1599 }
1600 }
1601 }
1602 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1603 }
1604 }
1605 }
1606
1607 /// <summary>
1608 /// Restore this part from the serialized xml representation.
1609 /// </summary>
1610 /// <param name="xmlReader"></param>
1611 /// <returns></returns>
1612 public static SceneObjectPart FromXml(XmlReader xmlReader)
1613 {
1614 return FromXml(UUID.Zero, xmlReader);
1615 }
1616
1617 /// <summary>
1618 /// Restore this part from the serialized xml representation.
1619 /// </summary>
1620 /// <param name="fromUserInventoryItemId">The inventory id from which this part came, if applicable</param>
1621 /// <param name="xmlReader"></param>
1622 /// <returns></returns>
1623 public static SceneObjectPart FromXml(UUID fromUserInventoryItemId, XmlReader xmlReader)
1624 {
1625 SceneObjectPart part = (SceneObjectPart)serializer.Deserialize(xmlReader);
1626 part.m_fromUserInventoryItemID = fromUserInventoryItemId;
1627
1628 // for tempOnRez objects, we have to fix the Expire date.
1629 if ((part.Flags & PrimFlags.TemporaryOnRez) != 0) part.ResetExpire();
1630
1631 return part;
1632 }
1633
1634 public UUID GetAvatarOnSitTarget()
1635 {
1636 return m_sitTargetAvatar;
1637 }
1638
1639 public bool GetDieAtEdge()
1640 {
1641 if (m_parentGroup == null)
1642 return false;
1643 if (m_parentGroup.IsDeleted)
1644 return false;
1645
1646 return m_parentGroup.RootPart.DIE_AT_EDGE;
1647 }
1648
1649 public double GetDistanceTo(Vector3 a, Vector3 b)
1650 {
1651 float dx = a.X - b.X;
1652 float dy = a.Y - b.Y;
1653 float dz = a.Z - b.Z;
1654 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
1655 }
1656
1657 public uint GetEffectiveObjectFlags()
1658 {
1659 PrimFlags f = _flags;
1660 if (m_parentGroup == null || m_parentGroup.RootPart == this)
1661 f &= ~(PrimFlags.Touch | PrimFlags.Money);
1662
1663 return (uint)_flags | (uint)LocalFlags;
1664 }
1665
1666 public Vector3 GetGeometricCenter()
1667 {
1668 if (PhysActor != null)
1669 {
1670 return new Vector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z);
1671 }
1672 else
1673 {
1674 return new Vector3(0, 0, 0);
1675 }
1676 }
1677
1678 public float GetMass()
1679 {
1680 if (PhysActor != null)
1681 {
1682 return PhysActor.Mass;
1683 }
1684 else
1685 {
1686 return 0;
1687 }
1688 }
1689
1690 public PhysicsVector GetForce()
1691 {
1692 if (PhysActor != null)
1693 return PhysActor.Force;
1694 else
1695 return new PhysicsVector();
1696 }
1697
1698 [SecurityPermission(SecurityAction.LinkDemand,
1699 Flags = SecurityPermissionFlag.SerializationFormatter)]
1700 public virtual void GetObjectData(
1701 SerializationInfo info, StreamingContext context)
1702 {
1703 if (info == null)
1704 {
1705 throw new ArgumentNullException("info");
1706 }
1707
1708 info.AddValue("m_inventoryFileName", Inventory.GetInventoryFileName());
1709 info.AddValue("m_folderID", UUID);
1710 info.AddValue("PhysActor", PhysActor);
1711
1712 Dictionary<Guid, TaskInventoryItem> TaskInventory_work = new Dictionary<Guid, TaskInventoryItem>();
1713
1714 foreach (UUID id in TaskInventory.Keys)
1715 {
1716 TaskInventory_work.Add(id.Guid, TaskInventory[id]);
1717 }
1718
1719 info.AddValue("TaskInventory", TaskInventory_work);
1720
1721 info.AddValue("LastOwnerID", _lastOwnerID.Guid);
1722 info.AddValue("OwnerID", _ownerID.Guid);
1723 info.AddValue("GroupID", _groupID.Guid);
1724
1725 info.AddValue("OwnershipCost", _ownershipCost);
1726 info.AddValue("ObjectSaleType", _objectSaleType);
1727 info.AddValue("SalePrice", _salePrice);
1728 info.AddValue("Category", _category);
1729
1730 info.AddValue("CreationDate", _creationDate);
1731 info.AddValue("ParentID", _parentID);
1732
1733 info.AddValue("OwnerMask", _ownerMask);
1734 info.AddValue("NextOwnerMask", _nextOwnerMask);
1735 info.AddValue("GroupMask", _groupMask);
1736 info.AddValue("EveryoneMask", _everyoneMask);
1737 info.AddValue("BaseMask", _baseMask);
1738
1739 info.AddValue("m_particleSystem", m_particleSystem);
1740
1741 info.AddValue("TimeStampFull", TimeStampFull);
1742 info.AddValue("TimeStampTerse", TimeStampTerse);
1743 info.AddValue("TimeStampLastActivity", TimeStampLastActivity);
1744
1745 info.AddValue("m_updateFlag", m_updateFlag);
1746 info.AddValue("CreatorID", _creatorID.Guid);
1747
1748 info.AddValue("m_inventorySerial", m_inventory.Serial);
1749 info.AddValue("m_uuid", m_uuid.Guid);
1750 info.AddValue("m_localID", m_localId);
1751 info.AddValue("m_name", m_name);
1752 info.AddValue("m_flags", _flags);
1753 info.AddValue("m_material", m_material);
1754 info.AddValue("m_regionHandle", m_regionHandle);
1755
1756 info.AddValue("m_groupPosition.X", m_groupPosition.X);
1757 info.AddValue("m_groupPosition.Y", m_groupPosition.Y);
1758 info.AddValue("m_groupPosition.Z", m_groupPosition.Z);
1759
1760 info.AddValue("m_offsetPosition.X", m_offsetPosition.X);
1761 info.AddValue("m_offsetPosition.Y", m_offsetPosition.Y);
1762 info.AddValue("m_offsetPosition.Z", m_offsetPosition.Z);
1763
1764 info.AddValue("m_rotationOffset.W", m_rotationOffset.W);
1765 info.AddValue("m_rotationOffset.X", m_rotationOffset.X);
1766 info.AddValue("m_rotationOffset.Y", m_rotationOffset.Y);
1767 info.AddValue("m_rotationOffset.Z", m_rotationOffset.Z);
1768
1769 info.AddValue("m_velocity.X", m_velocity.X);
1770 info.AddValue("m_velocity.Y", m_velocity.Y);
1771 info.AddValue("m_velocity.Z", m_velocity.Z);
1772
1773 info.AddValue("m_rotationalvelocity.X", RotationalVelocity.X);
1774 info.AddValue("m_rotationalvelocity.Y", RotationalVelocity.Y);
1775 info.AddValue("m_rotationalvelocity.Z", RotationalVelocity.Z);
1776
1777 info.AddValue("m_angularVelocity.X", m_angularVelocity.X);
1778 info.AddValue("m_angularVelocity.Y", m_angularVelocity.Y);
1779 info.AddValue("m_angularVelocity.Z", m_angularVelocity.Z);
1780
1781 info.AddValue("m_acceleration.X", m_acceleration.X);
1782 info.AddValue("m_acceleration.Y", m_acceleration.Y);
1783 info.AddValue("m_acceleration.Z", m_acceleration.Z);
1784
1785 info.AddValue("m_description", m_description);
1786 info.AddValue("m_color", m_color);
1787 info.AddValue("m_text", m_text);
1788 info.AddValue("m_sitName", m_sitName);
1789 info.AddValue("m_touchName", m_touchName);
1790 info.AddValue("m_clickAction", m_clickAction);
1791 info.AddValue("m_shape", m_shape);
1792 info.AddValue("m_parentGroup", m_parentGroup);
1793 info.AddValue("PayPrice", PayPrice);
1794 }
1795
1796 public void GetProperties(IClientAPI client)
1797 {
1798 client.SendObjectPropertiesReply(
1799 m_fromUserInventoryItemID, (ulong)_creationDate, _creatorID, UUID.Zero, UUID.Zero,
1800 _groupID, (short)InventorySerial, _lastOwnerID, UUID, _ownerID,
1801 ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description,
1802 ParentGroup.RootPart._ownerMask, ParentGroup.RootPart._nextOwnerMask, ParentGroup.RootPart._groupMask, ParentGroup.RootPart._everyoneMask,
1803 ParentGroup.RootPart._baseMask,
1804 ParentGroup.RootPart.ObjectSaleType,
1805 ParentGroup.RootPart.SalePrice);
1806 }
1807
1808 public UUID GetRootPartUUID()
1809 {
1810 if (m_parentGroup != null)
1811 {
1812 return m_parentGroup.UUID;
1813 }
1814 return UUID.Zero;
1815 }
1816
1817 /// <summary>
1818 /// Method for a prim to get it's world position from the group.
1819 /// Remember, the Group Position simply gives the position of the group itself
1820 /// </summary>
1821 /// <returns>A Linked Child Prim objects position in world</returns>
1822 public Vector3 GetWorldPosition()
1823 {
1824 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1825
1826 Vector3 axPos = OffsetPosition;
1827
1828 axPos *= parentRot;
1829 Vector3 translationOffsetPosition = axPos;
1830 return GroupPosition + translationOffsetPosition;
1831 }
1832
1833 /// <summary>
1834 /// Gets the rotation of this prim offset by the group rotation
1835 /// </summary>
1836 /// <returns></returns>
1837 public Quaternion GetWorldRotation()
1838 {
1839 Quaternion newRot;
1840
1841 if (this.LinkNum == 0)
1842 {
1843 newRot = RotationOffset;
1844 }
1845 else
1846 {
1847 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1848 Quaternion oldRot = RotationOffset;
1849 newRot = parentRot * oldRot;
1850 }
1851
1852 return newRot;
1853 }
1854
1855 public void MoveToTarget(Vector3 target, float tau)
1856 {
1857 if (tau > 0)
1858 {
1859 m_parentGroup.moveToTarget(target, tau);
1860 }
1861 else
1862 {
1863 StopMoveToTarget();
1864 }
1865 }
1866
1867 public virtual void OnGrab(Vector3 offsetPos, IClientAPI remoteClient)
1868 {
1869 }
1870
1871 public void PhysicsCollision(EventArgs e)
1872 {
1873 // single threaded here
1874 if (e == null)
1875 {
1876 return;
1877 }
1878
1879 CollisionEventUpdate a = (CollisionEventUpdate)e;
1880 Dictionary<uint, float> collissionswith = a.m_objCollisionList;
1881 List<uint> thisHitColliders = new List<uint>();
1882 List<uint> endedColliders = new List<uint>();
1883 List<uint> startedColliders = new List<uint>();
1884
1885 // calculate things that started colliding this time
1886 // and build up list of colliders this time
1887 foreach (uint localid in collissionswith.Keys)
1888 {
1889 if (localid != 0)
1890 {
1891 thisHitColliders.Add(localid);
1892 if (!m_lastColliders.Contains(localid))
1893 {
1894 startedColliders.Add(localid);
1895 }
1896
1897 //m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
1898 }
1899 }
1900
1901 // calculate things that ended colliding
1902 foreach (uint localID in m_lastColliders)
1903 {
1904 if (!thisHitColliders.Contains(localID))
1905 {
1906 endedColliders.Add(localID);
1907 }
1908 }
1909
1910 //add the items that started colliding this time to the last colliders list.
1911 foreach (uint localID in startedColliders)
1912 {
1913 m_lastColliders.Add(localID);
1914 }
1915 // remove things that ended colliding from the last colliders list
1916 foreach (uint localID in endedColliders)
1917 {
1918 m_lastColliders.Remove(localID);
1919 }
1920 if (m_parentGroup == null)
1921 return;
1922 if (m_parentGroup.IsDeleted)
1923 return;
1924
1925 // play the sound.
1926 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f)
1927 {
1928 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0);
1929 }
1930
1931 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0)
1932 {
1933 // do event notification
1934 if (startedColliders.Count > 0)
1935 {
1936 ColliderArgs StartCollidingMessage = new ColliderArgs();
1937 List<DetectedObject> colliding = new List<DetectedObject>();
1938 foreach (uint localId in startedColliders)
1939 {
1940 // always running this check because if the user deletes the object it would return a null reference.
1941 if (m_parentGroup == null)
1942 return;
1943 if (m_parentGroup.Scene == null)
1944 return;
1945 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
1946 if (obj != null)
1947 {
1948 DetectedObject detobj = new DetectedObject();
1949 detobj.keyUUID = obj.UUID;
1950 detobj.nameStr = obj.Name;
1951 detobj.ownerUUID = obj._ownerID;
1952 detobj.posVector = obj.AbsolutePosition;
1953 detobj.rotQuat = obj.GetWorldRotation();
1954 detobj.velVector = obj.Velocity;
1955 detobj.colliderType = 0;
1956 detobj.groupUUID = obj._groupID;
1957 colliding.Add(detobj);
1958 }
1959 else
1960 {
1961 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
1962 if (avlist != null)
1963 {
1964 foreach (ScenePresence av in avlist)
1965 {
1966 if (av.LocalId == localId)
1967 {
1968 DetectedObject detobj = new DetectedObject();
1969 detobj.keyUUID = av.UUID;
1970 detobj.nameStr = av.ControllingClient.Name;
1971 detobj.ownerUUID = av.UUID;
1972 detobj.posVector = av.AbsolutePosition;
1973 detobj.rotQuat = av.Rotation;
1974 detobj.velVector = av.Velocity;
1975 detobj.colliderType = 0;
1976 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
1977 colliding.Add(detobj);
1978 }
1979 }
1980 }
1981 }
1982 }
1983 if (colliding.Count > 0)
1984 {
1985 StartCollidingMessage.Colliders = colliding;
1986 // always running this check because if the user deletes the object it would return a null reference.
1987 if (m_parentGroup == null)
1988 return;
1989 if (m_parentGroup.Scene == null)
1990 return;
1991 m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, StartCollidingMessage);
1992 }
1993 }
1994 }
1995 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
1996 {
1997 if (m_lastColliders.Count > 0)
1998 {
1999 ColliderArgs CollidingMessage = new ColliderArgs();
2000 List<DetectedObject> colliding = new List<DetectedObject>();
2001 foreach (uint localId in m_lastColliders)
2002 {
2003 // always running this check because if the user deletes the object it would return a null reference.
2004 if (localId == 0)
2005 continue;
2006
2007 if (m_parentGroup == null)
2008 return;
2009 if (m_parentGroup.Scene == null)
2010 return;
2011 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
2012 if (obj != null)
2013 {
2014 DetectedObject detobj = new DetectedObject();
2015 detobj.keyUUID = obj.UUID;
2016 detobj.nameStr = obj.Name;
2017 detobj.ownerUUID = obj._ownerID;
2018 detobj.posVector = obj.AbsolutePosition;
2019 detobj.rotQuat = obj.GetWorldRotation();
2020 detobj.velVector = obj.Velocity;
2021 detobj.colliderType = 0;
2022 detobj.groupUUID = obj._groupID;
2023 colliding.Add(detobj);
2024 }
2025 else
2026 {
2027 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
2028 if (avlist != null)
2029 {
2030 foreach (ScenePresence av in avlist)
2031 {
2032 if (av.LocalId == localId)
2033 {
2034 DetectedObject detobj = new DetectedObject();
2035 detobj.keyUUID = av.UUID;
2036 detobj.nameStr = av.Name;
2037 detobj.ownerUUID = av.UUID;
2038 detobj.posVector = av.AbsolutePosition;
2039 detobj.rotQuat = av.Rotation;
2040 detobj.velVector = av.Velocity;
2041 detobj.colliderType = 0;
2042 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2043 colliding.Add(detobj);
2044 }
2045 }
2046
2047 }
2048 }
2049 }
2050 if (colliding.Count > 0)
2051 {
2052 CollidingMessage.Colliders = colliding;
2053 // always running this check because if the user deletes the object it would return a null reference.
2054 if (m_parentGroup == null)
2055 return;
2056 if (m_parentGroup.Scene == null)
2057 return;
2058 m_parentGroup.Scene.EventManager.TriggerScriptColliding(LocalId, CollidingMessage);
2059 }
2060
2061 }
2062 }
2063 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0)
2064 {
2065 if (endedColliders.Count > 0)
2066 {
2067 ColliderArgs EndCollidingMessage = new ColliderArgs();
2068 List<DetectedObject> colliding = new List<DetectedObject>();
2069 foreach (uint localId in endedColliders)
2070 {
2071 if (localId == 0)
2072 continue;
2073
2074 // always running this check because if the user deletes the object it would return a null reference.
2075 if (m_parentGroup == null)
2076 return;
2077 if (m_parentGroup.Scene == null)
2078 return;
2079 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
2080 if (obj != null)
2081 {
2082 DetectedObject detobj = new DetectedObject();
2083 detobj.keyUUID = obj.UUID;
2084 detobj.nameStr = obj.Name;
2085 detobj.ownerUUID = obj._ownerID;
2086 detobj.posVector = obj.AbsolutePosition;
2087 detobj.rotQuat = obj.GetWorldRotation();
2088 detobj.velVector = obj.Velocity;
2089 detobj.colliderType = 0;
2090 detobj.groupUUID = obj._groupID;
2091 colliding.Add(detobj);
2092 }
2093 else
2094 {
2095 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
2096 if (avlist != null)
2097 {
2098 foreach (ScenePresence av in avlist)
2099 {
2100 if (av.LocalId == localId)
2101 {
2102 DetectedObject detobj = new DetectedObject();
2103 detobj.keyUUID = av.UUID;
2104 detobj.nameStr = av.Name;
2105 detobj.ownerUUID = av.UUID;
2106 detobj.posVector = av.AbsolutePosition;
2107 detobj.rotQuat = av.Rotation;
2108 detobj.velVector = av.Velocity;
2109 detobj.colliderType = 0;
2110 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2111 colliding.Add(detobj);
2112 }
2113 }
2114
2115 }
2116 }
2117 }
2118 if (colliding.Count > 0)
2119 {
2120 EndCollidingMessage.Colliders = colliding;
2121 // always running this check because if the user deletes the object it would return a null reference.
2122 if (m_parentGroup == null)
2123 return;
2124 if (m_parentGroup.Scene == null)
2125 return;
2126 m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(LocalId, EndCollidingMessage);
2127 }
2128
2129 }
2130 }
2131 }
2132
2133 public void PhysicsOutOfBounds(PhysicsVector pos)
2134 {
2135 m_log.Info("[PHYSICS]: Physical Object went out of bounds.");
2136 RemFlag(PrimFlags.Physics);
2137 DoPhysicsPropertyUpdate(false, true);
2138 //m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2139 }
2140
2141 public void PhysicsRequestingTerseUpdate()
2142 {
2143 if (PhysActor != null)
2144 {
2145 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0);
2146 if (newpos.X > 257f || newpos.X < -1f || newpos.Y > 257f || newpos.Y < -1f)
2147 {
2148 m_parentGroup.AbsolutePosition = newpos;
2149 return;
2150 }
2151 }
2152 ScheduleTerseUpdate();
2153
2154 //SendTerseUpdateToAllClients();
2155 }
2156
2157 public void PreloadSound(string sound)
2158 {
2159 // UUID ownerID = OwnerID;
2160 UUID objectID = UUID;
2161 UUID soundID = UUID.Zero;
2162
2163 if (!UUID.TryParse(sound, out soundID))
2164 {
2165 //Trys to fetch sound id from prim's inventory.
2166 //Prim's inventory doesn't support non script items yet
2167 SceneObjectPart op = this;
2168 foreach (KeyValuePair<UUID, TaskInventoryItem> item in op.TaskInventory)
2169 {
2170 if (item.Value.Name == sound)
2171 {
2172 soundID = item.Value.ItemID;
2173 break;
2174 }
2175 }
2176 }
2177
2178 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
2179 foreach (ScenePresence p in avatarts)
2180 {
2181 // TODO: some filtering by distance of avatar
2182
2183 p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
2184 }
2185 }
2186
2187 public void RemFlag(PrimFlags flag)
2188 {
2189 // PrimFlags prevflag = Flags;
2190 if ((ObjectFlags & (uint) flag) != 0)
2191 {
2192 //Console.WriteLine("Removing flag: " + ((PrimFlags)flag).ToString());
2193 _flags &= ~flag;
2194 }
2195 //System.Console.WriteLine("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
2196 //ScheduleFullUpdate();
2197 }
2198
2199 public void RemoveScriptEvents(UUID scriptid)
2200 {
2201 lock (m_scriptEvents)
2202 {
2203 if (m_scriptEvents.ContainsKey(scriptid))
2204 {
2205 scriptEvents oldparts = scriptEvents.None;
2206 oldparts = (scriptEvents) m_scriptEvents[scriptid];
2207
2208 // remove values from aggregated script events
2209 AggregateScriptEvents &= ~oldparts;
2210 m_scriptEvents.Remove(scriptid);
2211 aggregateScriptEvents();
2212 }
2213 }
2214 }
2215
2216 /// <summary>
2217 /// Reset UUIDs for this part. This involves generate this part's own UUID and
2218 /// generating new UUIDs for all the items in the inventory.
2219 /// </summary>
2220 /// <param name="linkNum">Link number for the part</param>
2221 public void ResetIDs(int linkNum)
2222 {
2223 UUID = UUID.Random();
2224 LinkNum = linkNum;
2225 LocalId = 0;
2226 Inventory.ResetInventoryIDs();
2227 }
2228
2229 /// <summary>
2230 /// Resize this part.
2231 /// </summary>
2232 /// <param name="scale"></param>
2233 public void Resize(Vector3 scale)
2234 {
2235 StoreUndoState();
2236 m_shape.Scale = scale;
2237
2238 ParentGroup.HasGroupChanged = true;
2239 ScheduleFullUpdate();
2240 }
2241
2242 /// <summary>
2243 /// Schedules this prim for a full update
2244 /// </summary>
2245 public void ScheduleFullUpdate()
2246 {
2247 if (m_parentGroup != null)
2248 {
2249 m_parentGroup.QueueForUpdateCheck();
2250 }
2251
2252 int timeNow = Util.UnixTimeSinceEpoch();
2253
2254 // If multiple updates are scheduled on the same second, we still need to perform all of them
2255 // So we'll force the issue by bumping up the timestamp so that later processing sees these need
2256 // to be performed.
2257 if (timeNow <= TimeStampFull)
2258 {
2259 TimeStampFull += 1;
2260 }
2261 else
2262 {
2263 TimeStampFull = (uint)timeNow;
2264 }
2265
2266 m_updateFlag = 2;
2267
2268 // m_log.DebugFormat(
2269 // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
2270 // UUID, Name, TimeStampFull);
2271 }
2272
2273 /// <summary>
2274 /// Schedule a terse update for this prim. Terse updates only send position,
2275 /// rotation, velocity, rotational velocity and shape information.
2276 /// </summary>
2277 public void ScheduleTerseUpdate()
2278 {
2279 if (m_updateFlag < 1)
2280 {
2281 if (m_parentGroup != null)
2282 {
2283 m_parentGroup.HasGroupChanged = true;
2284 m_parentGroup.QueueForUpdateCheck();
2285 }
2286 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
2287 m_updateFlag = 1;
2288
2289 // m_log.DebugFormat(
2290 // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
2291 // UUID, Name, TimeStampTerse);
2292 }
2293 }
2294
2295 public void ScriptSetPhantomStatus(bool Phantom)
2296 {
2297 if (m_parentGroup != null)
2298 {
2299 m_parentGroup.ScriptSetPhantomStatus(Phantom);
2300 }
2301 }
2302
2303 public void ScriptSetTemporaryStatus(bool Temporary)
2304 {
2305 if (m_parentGroup != null)
2306 {
2307 m_parentGroup.ScriptSetTemporaryStatus(Temporary);
2308 }
2309 }
2310
2311 public void ScriptSetPhysicsStatus(bool UsePhysics)
2312 {
2313 if (m_parentGroup == null)
2314 DoPhysicsPropertyUpdate(UsePhysics, false);
2315 else
2316 m_parentGroup.ScriptSetPhysicsStatus(UsePhysics);
2317 }
2318
2319 public void ScriptSetVolumeDetect(bool SetVD)
2320 {
2321
2322 if (m_parentGroup != null)
2323 {
2324 m_parentGroup.ScriptSetVolumeDetect(SetVD);
2325 }
2326 }
2327
2328
2329 public void SculptTextureCallback(UUID textureID, AssetBase texture)
2330 {
2331 if (m_shape.SculptEntry)
2332 {
2333 if (texture != null)
2334 {
2335 m_shape.SculptData = texture.Data;
2336 if (PhysActor != null)
2337 {
2338 // Tricks physics engine into thinking we've changed the part shape.
2339 PrimitiveBaseShape m_newshape = m_shape.Copy();
2340 PhysActor.Shape = m_newshape;
2341 m_shape = m_newshape;
2342
2343 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2344 }
2345 }
2346 }
2347 }
2348
2349 /// <summary>
2350 ///
2351 /// </summary>
2352 /// <param name="remoteClient"></param>
2353 public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
2354 {
2355 m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags);
2356 }
2357
2358 /// <summary>
2359 ///
2360 /// </summary>
2361 public void SendFullUpdateToAllClients()
2362 {
2363 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2364 for (int i = 0; i < avatars.Count; i++)
2365 {
2366 // Ugly reference :(
2367 m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this,
2368 avatars[i].GenerateClientFlags(UUID));
2369 }
2370 }
2371
2372 public void SendFullUpdateToAllClientsExcept(UUID agentID)
2373 {
2374 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2375 for (int i = 0; i < avatars.Count; i++)
2376 {
2377 // Ugly reference :(
2378 if (avatars[i].UUID != agentID)
2379 {
2380 m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this,
2381 avatars[i].GenerateClientFlags(UUID));
2382 }
2383 }
2384 }
2385
2386 /// <summary>
2387 /// Sends a full update to the client
2388 /// </summary>
2389 /// <param name="remoteClient"></param>
2390 /// <param name="clientFlags"></param>
2391 public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags)
2392 {
2393 Vector3 lPos;
2394 lPos = OffsetPosition;
2395 SendFullUpdateToClient(remoteClient, lPos, clientflags);
2396 }
2397
2398 /// <summary>
2399 /// Sends a full update to the client
2400 /// </summary>
2401 /// <param name="remoteClient"></param>
2402 /// <param name="lPos"></param>
2403 /// <param name="clientFlags"></param>
2404 public void SendFullUpdateToClient(IClientAPI remoteClient, Vector3 lPos, uint clientFlags)
2405 {
2406 // Suppress full updates during attachment editing
2407 //
2408 if (ParentGroup.IsSelected && IsAttachment)
2409 return;
2410
2411 if (ParentGroup.IsDeleted)
2412 return;
2413
2414 clientFlags &= ~(uint) PrimFlags.CreateSelected;
2415
2416 if (remoteClient.AgentId == _ownerID)
2417 {
2418 if ((uint) (_flags & PrimFlags.CreateSelected) != 0)
2419 {
2420 clientFlags |= (uint) PrimFlags.CreateSelected;
2421 _flags &= ~PrimFlags.CreateSelected;
2422 }
2423 }
2424 //bool isattachment = IsAttachment;
2425 //if (LocalId != ParentGroup.RootPart.LocalId)
2426 //isattachment = ParentGroup.RootPart.IsAttachment;
2427
2428 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A};
2429 remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape,
2430 lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, _ownerID,
2431 m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment,
2432 AttachmentPoint,FromAssetID, Sound, SoundGain, SoundFlags, SoundRadius);
2433 }
2434
2435 /// <summary>
2436 /// Tell all the prims which have had updates scheduled
2437 /// </summary>
2438 public void SendScheduledUpdates()
2439 {
2440 if (m_updateFlag == 1) //some change has been made so update the clients
2441 {
2442 AddTerseUpdateToAllAvatars();
2443 ClearUpdateSchedule();
2444
2445 // This causes the Scene to 'poll' physical objects every couple of frames
2446 // bad, so it's been replaced by an event driven method.
2447 //if ((ObjectFlags & (uint)PrimFlags.Physics) != 0)
2448 //{
2449 // Only send the constant terse updates on physical objects!
2450 //ScheduleTerseUpdate();
2451 //}
2452 }
2453 else
2454 {
2455 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2456 {
2457 AddFullUpdateToAllAvatars();
2458 ClearUpdateSchedule();
2459 }
2460 }
2461 }
2462
2463 /// <summary>
2464 /// Trigger or play an attached sound in this part's inventory.
2465 /// </summary>
2466 /// <param name="sound"></param>
2467 /// <param name="volume"></param>
2468 /// <param name="triggered"></param>
2469 /// <param name="flags"></param>
2470 public void SendSound(string sound, double volume, bool triggered, byte flags)
2471 {
2472 if (volume > 1)
2473 volume = 1;
2474 if (volume < 0)
2475 volume = 0;
2476
2477 UUID ownerID = _ownerID;
2478 UUID objectID = UUID;
2479 UUID parentID = GetRootPartUUID();
2480 UUID soundID = UUID.Zero;
2481 Vector3 position = AbsolutePosition; // region local
2482 ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle;
2483
2484 if (!UUID.TryParse(sound, out soundID))
2485 {
2486 // search sound file from inventory
2487 SceneObjectPart op = this;
2488 foreach (KeyValuePair<UUID, TaskInventoryItem> item in op.TaskInventory)
2489 {
2490 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2491 {
2492 soundID = item.Value.ItemID;
2493 break;
2494 }
2495 }
2496 }
2497
2498 if (soundID == UUID.Zero)
2499 return;
2500
2501 ISoundModule soundModule = m_parentGroup.Scene.RequestModuleInterface<ISoundModule>();
2502 if (soundModule != null)
2503 {
2504 if (triggered)
2505 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle);
2506 else
2507 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags);
2508 }
2509 }
2510
2511 /// <summary>
2512 /// Send a terse update to all clients
2513 /// </summary>
2514 public void SendTerseUpdateToAllClients()
2515 {
2516 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2517 for (int i = 0; i < avatars.Count; i++)
2518 {
2519 SendTerseUpdateToClient(avatars[i].ControllingClient);
2520 }
2521 }
2522
2523 public void SetAttachmentPoint(uint AttachmentPoint)
2524 {
2525 this.AttachmentPoint = AttachmentPoint;
2526
2527 if (AttachmentPoint != 0)
2528 {
2529 IsAttachment = true;
2530 }
2531 else
2532 {
2533 IsAttachment = false;
2534 }
2535
2536 // save the attachment point.
2537 //if (AttachmentPoint != 0)
2538 //{
2539 m_shape.State = (byte)AttachmentPoint;
2540 //}
2541 }
2542
2543 public void SetAvatarOnSitTarget(UUID avatarID)
2544 {
2545 m_sitTargetAvatar = avatarID;
2546 if (ParentGroup != null)
2547 ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2548 }
2549
2550 public void SetAxisRotation(int axis, int rotate)
2551 {
2552 if (m_parentGroup != null)
2553 {
2554 m_parentGroup.SetAxisRotation(axis, rotate);
2555 }
2556 }
2557
2558 public void SetBuoyancy(float fvalue)
2559 {
2560 if (PhysActor != null)
2561 {
2562 PhysActor.Buoyancy = fvalue;
2563 }
2564 }
2565
2566 public void SetDieAtEdge(bool p)
2567 {
2568 if (m_parentGroup == null)
2569 return;
2570 if (m_parentGroup.IsDeleted)
2571 return;
2572
2573 m_parentGroup.RootPart.DIE_AT_EDGE = p;
2574 }
2575
2576 public void SetFloatOnWater(int floatYN)
2577 {
2578 if (PhysActor != null)
2579 {
2580 if (floatYN == 1)
2581 {
2582 PhysActor.FloatOnWater = true;
2583 }
2584 else
2585 {
2586 PhysActor.FloatOnWater = false;
2587 }
2588 }
2589 }
2590
2591 public void SetForce(PhysicsVector force)
2592 {
2593 if (PhysActor != null)
2594 {
2595 PhysActor.Force = force;
2596 }
2597 }
2598
2599 public void SetVehicleType(int type)
2600 {
2601 if (PhysActor != null)
2602 {
2603 PhysActor.VehicleType = type;
2604 }
2605 }
2606
2607 public void SetVehicleFloatParam(int param, float value)
2608 {
2609 if (PhysActor != null)
2610 {
2611 PhysActor.VehicleFloatParam(param, value);
2612 }
2613 }
2614
2615 public void SetVehicleVectorParam(int param, PhysicsVector value)
2616 {
2617 if (PhysActor != null)
2618 {
2619 PhysActor.VehicleVectorParam(param, value);
2620 }
2621 }
2622
2623 public void SetVehicleRotationParam(int param, Quaternion rotation)
2624 {
2625 if (PhysActor != null)
2626 {
2627 PhysActor.VehicleRotationParam(param, rotation);
2628 }
2629 }
2630
2631 public void SetGroup(UUID groupID, IClientAPI client)
2632 {
2633 _groupID = groupID;
2634 if (client != null)
2635 GetProperties(client);
2636 m_updateFlag = 2;
2637 }
2638
2639 /// <summary>
2640 ///
2641 /// </summary>
2642 public void SetParent(SceneObjectGroup parent)
2643 {
2644 m_parentGroup = parent;
2645 }
2646
2647 // Use this for attachments! LocalID should be avatar's localid
2648 public void SetParentLocalId(uint localID)
2649 {
2650 _parentID = localID;
2651 }
2652
2653 public void SetPhysicsAxisRotation()
2654 {
2655 if (PhysActor != null)
2656 {
2657 PhysActor.LockAngularMotion(RotationAxis);
2658 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2659 }
2660 }
2661
2662 public void SetScriptEvents(UUID scriptid, int events)
2663 {
2664 // scriptEvents oldparts;
2665 lock (m_scriptEvents)
2666 {
2667 if (m_scriptEvents.ContainsKey(scriptid))
2668 {
2669 // oldparts = m_scriptEvents[scriptid];
2670
2671 // remove values from aggregated script events
2672 if (m_scriptEvents[scriptid] == (scriptEvents) events)
2673 return;
2674 m_scriptEvents[scriptid] = (scriptEvents) events;
2675 }
2676 else
2677 {
2678 m_scriptEvents.Add(scriptid, (scriptEvents) events);
2679 }
2680 }
2681 aggregateScriptEvents();
2682 }
2683
2684 /// <summary>
2685 /// Set the text displayed for this part.
2686 /// </summary>
2687 /// <param name="text"></param>
2688 public void SetText(string text)
2689 {
2690 Text = text;
2691
2692 ParentGroup.HasGroupChanged = true;
2693 ScheduleFullUpdate();
2694 }
2695
2696 /// <summary>
2697 /// Set the text displayed for this part.
2698 /// </summary>
2699 /// <param name="text"></param>
2700 /// <param name="color"></param>
2701 /// <param name="alpha"></param>
2702 public void SetText(string text, Vector3 color, double alpha)
2703 {
2704 Color = Color.FromArgb(0xff - (int) (alpha*0xff),
2705 (int) (color.X*0xff),
2706 (int) (color.Y*0xff),
2707 (int) (color.Z*0xff));
2708 SetText(text);
2709 }
2710
2711 public void StopMoveToTarget()
2712 {
2713 m_parentGroup.stopMoveToTarget();
2714
2715 m_parentGroup.ScheduleGroupForTerseUpdate();
2716 //m_parentGroup.ScheduleGroupForFullUpdate();
2717 }
2718
2719 public void StoreUndoState()
2720 {
2721 if (!Undoing)
2722 {
2723 if (m_parentGroup != null)
2724 {
2725 lock (m_undo)
2726 {
2727 if (m_undo.Count > 0)
2728 {
2729 UndoState last = m_undo.Peek();
2730 if (last != null)
2731 {
2732 if (last.Compare(this))
2733 return;
2734 }
2735 }
2736
2737 if (m_parentGroup.GetSceneMaxUndo() > 0)
2738 {
2739 UndoState nUndo = new UndoState(this);
2740
2741 m_undo.Push(nUndo);
2742 }
2743
2744 }
2745 }
2746 }
2747 }
2748
2749 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
2750 {
2751 // In this case we're using a sphere with a radius of the largest dimention of the prim
2752 // TODO: Change to take shape into account
2753
2754
2755 EntityIntersection returnresult = new EntityIntersection();
2756 Vector3 vAbsolutePosition = AbsolutePosition;
2757 Vector3 vScale = Scale;
2758 Vector3 rOrigin = iray.Origin;
2759 Vector3 rDirection = iray.Direction;
2760
2761 //rDirection = rDirection.Normalize();
2762 // Buidling the first part of the Quadratic equation
2763 Vector3 r2ndDirection = rDirection*rDirection;
2764 float itestPart1 = r2ndDirection.X + r2ndDirection.Y + r2ndDirection.Z;
2765
2766 // Buidling the second part of the Quadratic equation
2767 Vector3 tmVal2 = rOrigin - vAbsolutePosition;
2768 Vector3 r2Direction = rDirection*2.0f;
2769 Vector3 tmVal3 = r2Direction*tmVal2;
2770
2771 float itestPart2 = tmVal3.X + tmVal3.Y + tmVal3.Z;
2772
2773 // Buidling the third part of the Quadratic equation
2774 Vector3 tmVal4 = rOrigin*rOrigin;
2775 Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition;
2776
2777 Vector3 tmVal6 = vAbsolutePosition*rOrigin;
2778
2779
2780 // Set Radius to the largest dimention of the prim
2781 float radius = 0f;
2782 if (vScale.X > radius)
2783 radius = vScale.X;
2784 if (vScale.Y > radius)
2785 radius = vScale.Y;
2786 if (vScale.Z > radius)
2787 radius = vScale.Z;
2788
2789 // the second part of this is the default prim size
2790 // once we factor in the aabb of the prim we're adding we can
2791 // change this to;
2792 // radius = (radius / 2) - 0.01f;
2793 //
2794 radius = (radius / 2) + (0.5f / 2) - 0.1f;
2795
2796 //radius = radius;
2797
2798 float itestPart3 = tmVal4.X + tmVal4.Y + tmVal4.Z + tmVal5.X + tmVal5.Y + tmVal5.Z -
2799 (2.0f*(tmVal6.X + tmVal6.Y + tmVal6.Z + (radius*radius)));
2800
2801 // Yuk Quadradrics.. Solve first
2802 float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3);
2803 if (rootsqr < 0.0f)
2804 {
2805 // No intersection
2806 return returnresult;
2807 }
2808 float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f);
2809
2810 if (root < 0.0f)
2811 {
2812 // perform second quadratic root solution
2813 root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f);
2814
2815 // is there any intersection?
2816 if (root < 0.0f)
2817 {
2818 // nope, no intersection
2819 return returnresult;
2820 }
2821 }
2822
2823 // We got an intersection. putting together an EntityIntersection object with the
2824 // intersection information
2825 Vector3 ipoint =
2826 new Vector3(iray.Origin.X + (iray.Direction.X*root), iray.Origin.Y + (iray.Direction.Y*root),
2827 iray.Origin.Z + (iray.Direction.Z*root));
2828
2829 returnresult.HitTF = true;
2830 returnresult.ipoint = ipoint;
2831
2832 // Normal is calculated by the difference and then normalizing the result
2833 Vector3 normalpart = ipoint - vAbsolutePosition;
2834 returnresult.normal = normalpart / normalpart.Length();
2835
2836 // It's funny how the Vector3 object has a Distance function, but the Axiom.Math object doesn't.
2837 // I can write a function to do it.. but I like the fact that this one is Static.
2838
2839 Vector3 distanceConvert1 = new Vector3(iray.Origin.X, iray.Origin.Y, iray.Origin.Z);
2840 Vector3 distanceConvert2 = new Vector3(ipoint.X, ipoint.Y, ipoint.Z);
2841 float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2);
2842
2843 returnresult.distance = distance;
2844
2845 return returnresult;
2846 }
2847
2848 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters)
2849 {
2850 // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes
2851 // This breaks down into the ray---> plane equation.
2852 // TODO: Change to take shape into account
2853 Vector3[] vertexes = new Vector3[8];
2854
2855 // float[] distance = new float[6];
2856 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
2857 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
2858 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
2859 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
2860
2861 Vector3[] normals = new Vector3[6]; // Normal for Facei
2862 Vector3[] AAfacenormals = new Vector3[6]; // Axis Aligned face normals
2863
2864 AAfacenormals[0] = new Vector3(1, 0, 0);
2865 AAfacenormals[1] = new Vector3(0, 1, 0);
2866 AAfacenormals[2] = new Vector3(-1, 0, 0);
2867 AAfacenormals[3] = new Vector3(0, -1, 0);
2868 AAfacenormals[4] = new Vector3(0, 0, 1);
2869 AAfacenormals[5] = new Vector3(0, 0, -1);
2870
2871 Vector3 AmBa = new Vector3(0, 0, 0); // Vertex A - Vertex B
2872 Vector3 AmBb = new Vector3(0, 0, 0); // Vertex B - Vertex C
2873 Vector3 cross = new Vector3();
2874
2875 Vector3 pos = GetWorldPosition();
2876 Quaternion rot = GetWorldRotation();
2877
2878 // Variables prefixed with AX are Axiom.Math copies of the LL variety.
2879
2880 Quaternion AXrot = rot;
2881 AXrot.Normalize();
2882
2883 Vector3 AXpos = pos;
2884
2885 // tScale is the offset to derive the vertex based on the scale.
2886 // it's different for each vertex because we've got to rotate it
2887 // to get the world position of the vertex to produce the Oriented Bounding Box
2888
2889 Vector3 tScale = Vector3.Zero;
2890
2891 Vector3 AXscale = new Vector3(m_shape.Scale.X * 0.5f, m_shape.Scale.Y * 0.5f, m_shape.Scale.Z * 0.5f);
2892
2893 //Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale));
2894 //Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1));
2895
2896 // rScale is the rotated offset to find a vertex based on the scale and the world rotation.
2897 Vector3 rScale = new Vector3();
2898
2899 // Get Vertexes for Faces Stick them into ABCD for each Face
2900 // Form: Face<vertex>[face] that corresponds to the below diagram
2901 #region ABCD Face Vertex Map Comment Diagram
2902 // A _________ B
2903 // | |
2904 // | 4 top |
2905 // |_________|
2906 // C D
2907
2908 // A _________ B
2909 // | Back |
2910 // | 3 |
2911 // |_________|
2912 // C D
2913
2914 // A _________ B B _________ A
2915 // | Left | | Right |
2916 // | 0 | | 2 |
2917 // |_________| |_________|
2918 // C D D C
2919
2920 // A _________ B
2921 // | Front |
2922 // | 1 |
2923 // |_________|
2924 // C D
2925
2926 // C _________ D
2927 // | |
2928 // | 5 bot |
2929 // |_________|
2930 // A B
2931 #endregion
2932
2933 #region Plane Decomposition of Oriented Bounding Box
2934 tScale = new Vector3(AXscale.X, -AXscale.Y, AXscale.Z);
2935 rScale = tScale * AXrot;
2936 vertexes[0] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
2937 // vertexes[0].X = pos.X + vertexes[0].X;
2938 //vertexes[0].Y = pos.Y + vertexes[0].Y;
2939 //vertexes[0].Z = pos.Z + vertexes[0].Z;
2940
2941 FaceA[0] = vertexes[0];
2942 FaceB[3] = vertexes[0];
2943 FaceA[4] = vertexes[0];
2944
2945 tScale = AXscale;
2946 rScale = tScale * AXrot;
2947 vertexes[1] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
2948
2949 // vertexes[1].X = pos.X + vertexes[1].X;
2950 // vertexes[1].Y = pos.Y + vertexes[1].Y;
2951 //vertexes[1].Z = pos.Z + vertexes[1].Z;
2952
2953 FaceB[0] = vertexes[1];
2954 FaceA[1] = vertexes[1];
2955 FaceC[4] = vertexes[1];
2956
2957 tScale = new Vector3(AXscale.X, -AXscale.Y, -AXscale.Z);
2958 rScale = tScale * AXrot;
2959
2960 vertexes[2] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
2961
2962 //vertexes[2].X = pos.X + vertexes[2].X;
2963 //vertexes[2].Y = pos.Y + vertexes[2].Y;
2964 //vertexes[2].Z = pos.Z + vertexes[2].Z;
2965
2966 FaceC[0] = vertexes[2];
2967 FaceD[3] = vertexes[2];
2968 FaceC[5] = vertexes[2];
2969
2970 tScale = new Vector3(AXscale.X, AXscale.Y, -AXscale.Z);
2971 rScale = tScale * AXrot;
2972 vertexes[3] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
2973
2974 //vertexes[3].X = pos.X + vertexes[3].X;
2975 // vertexes[3].Y = pos.Y + vertexes[3].Y;
2976 // vertexes[3].Z = pos.Z + vertexes[3].Z;
2977
2978 FaceD[0] = vertexes[3];
2979 FaceC[1] = vertexes[3];
2980 FaceA[5] = vertexes[3];
2981
2982 tScale = new Vector3(-AXscale.X, AXscale.Y, AXscale.Z);
2983 rScale = tScale * AXrot;
2984 vertexes[4] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
2985
2986 // vertexes[4].X = pos.X + vertexes[4].X;
2987 // vertexes[4].Y = pos.Y + vertexes[4].Y;
2988 // vertexes[4].Z = pos.Z + vertexes[4].Z;
2989
2990 FaceB[1] = vertexes[4];
2991 FaceA[2] = vertexes[4];
2992 FaceD[4] = vertexes[4];
2993
2994 tScale = new Vector3(-AXscale.X, AXscale.Y, -AXscale.Z);
2995 rScale = tScale * AXrot;
2996 vertexes[5] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
2997
2998 // vertexes[5].X = pos.X + vertexes[5].X;
2999 // vertexes[5].Y = pos.Y + vertexes[5].Y;
3000 // vertexes[5].Z = pos.Z + vertexes[5].Z;
3001
3002 FaceD[1] = vertexes[5];
3003 FaceC[2] = vertexes[5];
3004 FaceB[5] = vertexes[5];
3005
3006 tScale = new Vector3(-AXscale.X, -AXscale.Y, AXscale.Z);
3007 rScale = tScale * AXrot;
3008 vertexes[6] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
3009
3010 // vertexes[6].X = pos.X + vertexes[6].X;
3011 // vertexes[6].Y = pos.Y + vertexes[6].Y;
3012 // vertexes[6].Z = pos.Z + vertexes[6].Z;
3013
3014 FaceB[2] = vertexes[6];
3015 FaceA[3] = vertexes[6];
3016 FaceB[4] = vertexes[6];
3017
3018 tScale = new Vector3(-AXscale.X, -AXscale.Y, -AXscale.Z);
3019 rScale = tScale * AXrot;
3020 vertexes[7] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
3021
3022 // vertexes[7].X = pos.X + vertexes[7].X;
3023 // vertexes[7].Y = pos.Y + vertexes[7].Y;
3024 // vertexes[7].Z = pos.Z + vertexes[7].Z;
3025
3026 FaceD[2] = vertexes[7];
3027 FaceC[3] = vertexes[7];
3028 FaceD[5] = vertexes[7];
3029 #endregion
3030
3031 // Get our plane normals
3032 for (int i = 0; i < 6; i++)
3033 {
3034 //m_log.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]);
3035
3036 // Our Plane direction
3037 AmBa = FaceA[i] - FaceB[i];
3038 AmBb = FaceB[i] - FaceC[i];
3039
3040 cross = Vector3.Cross(AmBb, AmBa);
3041
3042 // normalize the cross product to get the normal.
3043 normals[i] = cross / cross.Length();
3044
3045 //m_log.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString());
3046 //distance[i] = (normals[i].X * AmBa.X + normals[i].Y * AmBa.Y + normals[i].Z * AmBa.Z) * -1;
3047 }
3048
3049 EntityIntersection returnresult = new EntityIntersection();
3050
3051 returnresult.distance = 1024;
3052 float c = 0;
3053 float a = 0;
3054 float d = 0;
3055 Vector3 q = new Vector3();
3056
3057 #region OBB Version 2 Experiment
3058 //float fmin = 999999;
3059 //float fmax = -999999;
3060 //float s = 0;
3061
3062 //for (int i=0;i<6;i++)
3063 //{
3064 //s = iray.Direction.Dot(normals[i]);
3065 //d = normals[i].Dot(FaceB[i]);
3066
3067 //if (s == 0)
3068 //{
3069 //if (iray.Origin.Dot(normals[i]) > d)
3070 //{
3071 //return returnresult;
3072 //}
3073 // else
3074 //{
3075 //continue;
3076 //}
3077 //}
3078 //a = (d - iray.Origin.Dot(normals[i])) / s;
3079 //if (iray.Direction.Dot(normals[i]) < 0)
3080 //{
3081 //if (a > fmax)
3082 //{
3083 //if (a > fmin)
3084 //{
3085 //return returnresult;
3086 //}
3087 //fmax = a;
3088 //}
3089
3090 //}
3091 //else
3092 //{
3093 //if (a < fmin)
3094 //{
3095 //if (a < 0 || a < fmax)
3096 //{
3097 //return returnresult;
3098 //}
3099 //fmin = a;
3100 //}
3101 //}
3102 //}
3103 //if (fmax > 0)
3104 // a= fmax;
3105 //else
3106 // a=fmin;
3107
3108 //q = iray.Origin + a * iray.Direction;
3109 #endregion
3110
3111 // Loop over faces (6 of them)
3112 for (int i = 0; i < 6; i++)
3113 {
3114 AmBa = FaceA[i] - FaceB[i];
3115 AmBb = FaceB[i] - FaceC[i];
3116 d = Vector3.Dot(normals[i], FaceB[i]);
3117
3118 //if (faceCenters)
3119 //{
3120 // c = normals[i].Dot(normals[i]);
3121 //}
3122 //else
3123 //{
3124 c = Vector3.Dot(iray.Direction, normals[i]);
3125 //}
3126 if (c == 0)
3127 continue;
3128
3129 a = (d - Vector3.Dot(iray.Origin, normals[i])) / c;
3130
3131 if (a < 0)
3132 continue;
3133
3134 // If the normal is pointing outside the object
3135 if (Vector3.Dot(iray.Direction, normals[i]) < 0 || !frontFacesOnly)
3136 {
3137 //if (faceCenters)
3138 //{ //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f;
3139 // q = iray.Origin + a * normals[i];
3140 //}
3141 //else
3142 //{
3143 q = iray.Origin + iray.Direction * a;
3144 //}
3145
3146 float distance2 = (float)GetDistanceTo(q, AXpos);
3147 // Is this the closest hit to the object's origin?
3148 //if (faceCenters)
3149 //{
3150 // distance2 = (float)GetDistanceTo(q, iray.Origin);
3151 //}
3152
3153 if (distance2 < returnresult.distance)
3154 {
3155 returnresult.distance = distance2;
3156 returnresult.HitTF = true;
3157 returnresult.ipoint = q;
3158 //m_log.Info("[FACE]:" + i.ToString());
3159 //m_log.Info("[POINT]: " + q.ToString());
3160 //m_log.Info("[DIST]: " + distance2.ToString());
3161 if (faceCenters)
3162 {
3163 returnresult.normal = AAfacenormals[i] * AXrot;
3164
3165 Vector3 scaleComponent = AAfacenormals[i];
3166 float ScaleOffset = 0.5f;
3167 if (scaleComponent.X != 0) ScaleOffset = AXscale.X;
3168 if (scaleComponent.Y != 0) ScaleOffset = AXscale.Y;
3169 if (scaleComponent.Z != 0) ScaleOffset = AXscale.Z;
3170 ScaleOffset = Math.Abs(ScaleOffset);
3171 Vector3 offset = returnresult.normal * ScaleOffset;
3172 returnresult.ipoint = AXpos + offset;
3173
3174 ///pos = (intersectionpoint + offset);
3175 }
3176 else
3177 {
3178 returnresult.normal = normals[i];
3179 }
3180 returnresult.AAfaceNormal = AAfacenormals[i];
3181 }
3182 }
3183 }
3184 return returnresult;
3185 }
3186
3187 /// <summary>
3188 /// Serialize this part to xml.
3189 /// </summary>
3190 /// <param name="xmlWriter"></param>
3191 public void ToXml(XmlWriter xmlWriter)
3192 {
3193 serializer.Serialize(xmlWriter, this);
3194 }
3195
3196 public void TriggerScriptChangedEvent(Changed val)
3197 {
3198 if (m_parentGroup != null)
3199 {
3200 if (m_parentGroup.Scene != null)
3201 m_parentGroup.Scene.TriggerObjectChanged(LocalId, (uint)val);
3202 }
3203 }
3204
3205 public void TrimPermissions()
3206 {
3207 _baseMask &= (uint)PermissionMask.All;
3208 _ownerMask &= (uint)PermissionMask.All;
3209 _groupMask &= (uint)PermissionMask.All;
3210 _everyoneMask &= (uint)PermissionMask.All;
3211 _nextOwnerMask &= (uint)PermissionMask.All;
3212 }
3213
3214 public void Undo()
3215 {
3216 lock (m_undo)
3217 {
3218 if (m_undo.Count > 0)
3219 {
3220 UndoState goback = m_undo.Pop();
3221 if (goback != null)
3222 goback.PlaybackState(this);
3223 }
3224 }
3225 }
3226
3227 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
3228 {
3229 m_shape.ReadInUpdateExtraParam(type, inUse, data);
3230
3231 if (type == 0x30)
3232 {
3233 if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
3234 {
3235 //AssetBase tx = m_parentGroup.Scene.getase
3236 m_parentGroup.Scene.AssetCache.GetAsset(m_shape.SculptTexture, SculptTextureCallback, true);
3237 }
3238 }
3239
3240 ParentGroup.HasGroupChanged = true;
3241 ScheduleFullUpdate();
3242 }
3243
3244 public void UpdateGroupPosition(Vector3 pos)
3245 {
3246 if ((pos.X != GroupPosition.X) ||
3247 (pos.Y != GroupPosition.Y) ||
3248 (pos.Z != GroupPosition.Z))
3249 {
3250 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3251 GroupPosition = newPos;
3252 ScheduleTerseUpdate();
3253 }
3254 }
3255
3256 public virtual void UpdateMovement()
3257 {
3258 }
3259
3260 /// <summary>
3261 ///
3262 /// </summary>
3263 /// <param name="pos"></param>
3264 public void UpdateOffSet(Vector3 pos)
3265 {
3266 if ((pos.X != OffsetPosition.X) ||
3267 (pos.Y != OffsetPosition.Y) ||
3268 (pos.Z != OffsetPosition.Z))
3269 {
3270 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3271 OffsetPosition = newPos;
3272 ScheduleTerseUpdate();
3273 }
3274 }
3275
3276 public void UpdatePermissions(UUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
3277 {
3278 bool set = addRemTF == 1;
3279 bool god = m_parentGroup.Scene.Permissions.IsGod(AgentID);
3280
3281 uint baseMask = _baseMask;
3282 if (god)
3283 baseMask = 0x7ffffff0;
3284
3285 // Are we the owner?
3286 if ((AgentID == _ownerID) || god)
3287 {
3288 switch (field)
3289 {
3290 case 1:
3291 if (god)
3292 {
3293 _baseMask = ApplyMask(_baseMask, set, mask);
3294 Inventory.ApplyGodPermissions(_baseMask);
3295 }
3296
3297 break;
3298 case 2:
3299 _ownerMask = ApplyMask(_ownerMask, set, mask) &
3300 baseMask;
3301 break;
3302 case 4:
3303 _groupMask = ApplyMask(_groupMask, set, mask) &
3304 baseMask;
3305 break;
3306 case 8:
3307 _everyoneMask = ApplyMask(_everyoneMask, set, mask) &
3308 baseMask;
3309 break;
3310 case 16:
3311 _nextOwnerMask = ApplyMask(_nextOwnerMask, set, mask) &
3312 baseMask;
3313 break;
3314 }
3315 SendFullUpdateToAllClients();
3316
3317 SendObjectPropertiesToClient(AgentID);
3318
3319 }
3320 }
3321
3322 public bool IsHingeJoint()
3323 {
3324 // For now, we use the NINJA naming scheme for identifying joints.
3325 // In the future, we can support other joint specification schemes such as a
3326 // custom checkbox in the viewer GUI.
3327 if (m_parentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
3328 {
3329 string hingeString = "hingejoint";
3330 return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString);
3331 }
3332 else
3333 {
3334 return false;
3335 }
3336 }
3337
3338 public bool IsBallJoint()
3339 {
3340 // For now, we use the NINJA naming scheme for identifying joints.
3341 // In the future, we can support other joint specification schemes such as a
3342 // custom checkbox in the viewer GUI.
3343 if (m_parentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
3344 {
3345 string ballString = "balljoint";
3346 return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString);
3347 }
3348 else
3349 {
3350 return false;
3351 }
3352 }
3353
3354 public bool IsJoint()
3355 {
3356 // For now, we use the NINJA naming scheme for identifying joints.
3357 // In the future, we can support other joint specification schemes such as a
3358 // custom checkbox in the viewer GUI.
3359 if (m_parentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
3360 {
3361 return IsHingeJoint() || IsBallJoint();
3362 }
3363 else
3364 {
3365 return false;
3366 }
3367 }
3368
3369 public void UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVD)
3370 {
3371 bool wasUsingPhysics = ((ObjectFlags & (uint) PrimFlags.Physics) != 0);
3372 bool wasTemporary = ((ObjectFlags & (uint)PrimFlags.TemporaryOnRez) != 0);
3373 bool wasPhantom = ((ObjectFlags & (uint)PrimFlags.Phantom) != 0);
3374 bool wasVD = VolumeDetectActive;
3375
3376 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == IsTemporary) && (wasPhantom == IsPhantom) && (IsVD==wasVD) )
3377 {
3378 return;
3379 }
3380
3381 // Special cases for VD. VD can only be called from a script
3382 // and can't be combined with changes to other states. So we can rely
3383 // that...
3384 // ... if VD is changed, all others are not.
3385 // ... if one of the others is changed, VD is not.
3386 if (IsVD) // VD is active, special logic applies
3387 {
3388 // State machine logic for VolumeDetect
3389 // More logic below
3390 bool phanReset = (IsPhantom != wasPhantom) && !IsPhantom;
3391
3392 if (phanReset) // Phantom changes from on to off switch VD off too
3393 {
3394 IsVD = false; // Switch it of for the course of this routine
3395 VolumeDetectActive = false; // and also permanently
3396 if (PhysActor != null)
3397 PhysActor.SetVolumeDetect(0); // Let physics know about it too
3398 }
3399 else
3400 {
3401 IsPhantom = false;
3402 // If volumedetect is active we don't want phantom to be applied.
3403 // If this is a new call to VD out of the state "phantom"
3404 // this will also cause the prim to be visible to physics
3405 }
3406
3407 }
3408
3409 if (UsePhysics && IsJoint())
3410 {
3411 IsPhantom = true;
3412 }
3413
3414 if (UsePhysics)
3415 {
3416 AddFlag(PrimFlags.Physics);
3417 if (!wasUsingPhysics)
3418 {
3419 DoPhysicsPropertyUpdate(UsePhysics, false);
3420 if (m_parentGroup != null)
3421 {
3422 if (!m_parentGroup.IsDeleted)
3423 {
3424 if (LocalId == m_parentGroup.RootPart.LocalId)
3425 {
3426 m_parentGroup.CheckSculptAndLoad();
3427 }
3428 }
3429 }
3430 }
3431 }
3432 else
3433 {
3434 RemFlag(PrimFlags.Physics);
3435 if (wasUsingPhysics)
3436 {
3437 DoPhysicsPropertyUpdate(UsePhysics, false);
3438 }
3439 }
3440
3441
3442 if (IsPhantom || IsAttachment) // note: this may have been changed above in the case of joints
3443 {
3444 AddFlag(PrimFlags.Phantom);
3445 if (PhysActor != null)
3446 {
3447 m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
3448 /// that's not wholesome. Had to make Scene public
3449 PhysActor = null;
3450 }
3451 }
3452 else // Not phantom
3453 {
3454 RemFlag(PrimFlags.Phantom);
3455
3456 if (PhysActor == null)
3457 {
3458 // It's not phantom anymore. So make sure the physics engine get's knowledge of it
3459 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
3460 Name,
3461 Shape,
3462 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z),
3463 new PhysicsVector(Scale.X, Scale.Y, Scale.Z),
3464 RotationOffset,
3465 UsePhysics);
3466
3467 if (PhysActor != null)
3468 {
3469 PhysActor.LocalID = LocalId;
3470 DoPhysicsPropertyUpdate(UsePhysics, true);
3471 if (m_parentGroup != null)
3472 {
3473 if (!m_parentGroup.IsDeleted)
3474 {
3475 if (LocalId == m_parentGroup.RootPart.LocalId)
3476 {
3477 m_parentGroup.CheckSculptAndLoad();
3478 }
3479 }
3480 }
3481 if (
3482 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
3483 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3484 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3485 (CollisionSound != UUID.Zero)
3486 )
3487 {
3488 PhysActor.OnCollisionUpdate += PhysicsCollision;
3489 PhysActor.SubscribeEvents(1000);
3490 }
3491 }
3492 }
3493 else // it already has a physical representation
3494 {
3495 PhysActor.IsPhysical = UsePhysics;
3496
3497 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
3498 if (m_parentGroup != null)
3499 {
3500 if (!m_parentGroup.IsDeleted)
3501 {
3502 if (LocalId == m_parentGroup.RootPart.LocalId)
3503 {
3504 m_parentGroup.CheckSculptAndLoad();
3505 }
3506 }
3507 }
3508 }
3509 }
3510
3511 if (IsVD)
3512 {
3513 // If the above logic worked (this is urgent candidate to unit tests!)
3514 // we now have a physicsactor.
3515 // Defensive programming calls for a check here.
3516 // Better would be throwing an exception that could be catched by a unit test as the internal
3517 // logic should make sure, this Physactor is always here.
3518 if (this.PhysActor != null)
3519 {
3520 PhysActor.SetVolumeDetect(1);
3521 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
3522 this.VolumeDetectActive = true;
3523 }
3524
3525 }
3526 else
3527 { // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
3528 // (mumbles, well, at least if you have infinte CPU powers :-) )
3529 if (this.PhysActor != null)
3530 {
3531 PhysActor.SetVolumeDetect(0);
3532 }
3533 this.VolumeDetectActive = false;
3534 }
3535
3536
3537 if (IsTemporary)
3538 {
3539 AddFlag(PrimFlags.TemporaryOnRez);
3540 }
3541 else
3542 {
3543 RemFlag(PrimFlags.TemporaryOnRez);
3544 }
3545 // System.Console.WriteLine("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
3546
3547 ParentGroup.HasGroupChanged = true;
3548 ScheduleFullUpdate();
3549 }
3550
3551 public void UpdateRotation(Quaternion rot)
3552 {
3553 if ((rot.X != RotationOffset.X) ||
3554 (rot.Y != RotationOffset.Y) ||
3555 (rot.Z != RotationOffset.Z) ||
3556 (rot.W != RotationOffset.W))
3557 {
3558 //StoreUndoState();
3559 RotationOffset = rot;
3560 ParentGroup.HasGroupChanged = true;
3561 ScheduleTerseUpdate();
3562 }
3563 }
3564
3565 /// <summary>
3566 /// Update the shape of this part.
3567 /// </summary>
3568 /// <param name="shapeBlock"></param>
3569 public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock)
3570 {
3571 m_shape.PathBegin = shapeBlock.PathBegin;
3572 m_shape.PathEnd = shapeBlock.PathEnd;
3573 m_shape.PathScaleX = shapeBlock.PathScaleX;
3574 m_shape.PathScaleY = shapeBlock.PathScaleY;
3575 m_shape.PathShearX = shapeBlock.PathShearX;
3576 m_shape.PathShearY = shapeBlock.PathShearY;
3577 m_shape.PathSkew = shapeBlock.PathSkew;
3578 m_shape.ProfileBegin = shapeBlock.ProfileBegin;
3579 m_shape.ProfileEnd = shapeBlock.ProfileEnd;
3580 m_shape.PathCurve = shapeBlock.PathCurve;
3581 m_shape.ProfileCurve = shapeBlock.ProfileCurve;
3582 m_shape.ProfileHollow = shapeBlock.ProfileHollow;
3583 m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset;
3584 m_shape.PathRevolutions = shapeBlock.PathRevolutions;
3585 m_shape.PathTaperX = shapeBlock.PathTaperX;
3586 m_shape.PathTaperY = shapeBlock.PathTaperY;
3587 m_shape.PathTwist = shapeBlock.PathTwist;
3588 m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
3589 if (PhysActor != null)
3590 {
3591 PhysActor.Shape = m_shape;
3592 }
3593
3594 // This is what makes vehicle trailers work
3595 // A script in a child prim re-issues
3596 // llSetPrimitiveParams(PRIM_TYPE) every few seconds. That
3597 // prevents autoreturn. This is not well known. It also works
3598 // in SL.
3599 //
3600 if (ParentGroup.RootPart != this)
3601 ParentGroup.RootPart.Rezzed = DateTime.Now;
3602
3603 ParentGroup.HasGroupChanged = true;
3604 ScheduleFullUpdate();
3605 }
3606
3607 // Added to handle bug in libsecondlife's TextureEntry.ToBytes()
3608 // not handling RGBA properly. Cycles through, and "fixes" the color
3609 // info
3610 public void UpdateTexture(Primitive.TextureEntry tex)
3611 {
3612 //Color4 tmpcolor;
3613 //for (uint i = 0; i < 32; i++)
3614 //{
3615 // if (tex.FaceTextures[i] != null)
3616 // {
3617 // tmpcolor = tex.GetFace((uint) i).RGBA;
3618 // tmpcolor.A = tmpcolor.A*255;
3619 // tmpcolor.R = tmpcolor.R*255;
3620 // tmpcolor.G = tmpcolor.G*255;
3621 // tmpcolor.B = tmpcolor.B*255;
3622 // tex.FaceTextures[i].RGBA = tmpcolor;
3623 // }
3624 //}
3625 //tmpcolor = tex.DefaultTexture.RGBA;
3626 //tmpcolor.A = tmpcolor.A*255;
3627 //tmpcolor.R = tmpcolor.R*255;
3628 //tmpcolor.G = tmpcolor.G*255;
3629 //tmpcolor.B = tmpcolor.B*255;
3630 //tex.DefaultTexture.RGBA = tmpcolor;
3631 UpdateTextureEntry(tex.ToBytes());
3632 }
3633
3634 /// <summary>
3635 /// Update the texture entry for this part.
3636 /// </summary>
3637 /// <param name="textureEntry"></param>
3638 public void UpdateTextureEntry(byte[] textureEntry)
3639 {
3640 m_shape.TextureEntry = textureEntry;
3641 TriggerScriptChangedEvent(Changed.TEXTURE);
3642
3643 ParentGroup.HasGroupChanged = true;
3644 ParentGroup.ScheduleGroupForFullUpdate();
3645 }
3646
3647 public void aggregateScriptEvents()
3648 {
3649 AggregateScriptEvents = 0;
3650
3651 // Aggregate script events
3652 lock (m_scriptEvents)
3653 {
3654 foreach (scriptEvents s in m_scriptEvents.Values)
3655 {
3656 AggregateScriptEvents |= s;
3657 }
3658 }
3659
3660 uint objectflagupdate = 0;
3661
3662 if (
3663 ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
3664 ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
3665 ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
3666 )
3667 {
3668 objectflagupdate |= (uint) PrimFlags.Touch;
3669 }
3670
3671 if ((AggregateScriptEvents & scriptEvents.money) != 0)
3672 {
3673 objectflagupdate |= (uint) PrimFlags.Money;
3674 }
3675
3676 if (AllowedDrop)
3677 {
3678 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
3679 }
3680
3681 if (
3682 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
3683 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3684 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3685 (CollisionSound != UUID.Zero)
3686 )
3687 {
3688 // subscribe to physics updates.
3689 if (PhysActor != null)
3690 {
3691 PhysActor.OnCollisionUpdate += PhysicsCollision;
3692 PhysActor.SubscribeEvents(1000);
3693
3694 }
3695 }
3696 else
3697 {
3698 if (PhysActor != null)
3699 {
3700 PhysActor.UnSubscribeEvents();
3701 PhysActor.OnCollisionUpdate -= PhysicsCollision;
3702 }
3703 }
3704
3705 if (m_parentGroup == null)
3706 {
3707 ScheduleFullUpdate();
3708 return;
3709 }
3710
3711 if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
3712 {
3713 m_parentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
3714 }
3715 else
3716 {
3717 m_parentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
3718 }
3719
3720 LocalFlags=(PrimFlags)objectflagupdate;
3721
3722 if (m_parentGroup != null && m_parentGroup.RootPart == this)
3723 m_parentGroup.aggregateScriptEvents();
3724 else
3725 ScheduleFullUpdate();
3726 }
3727
3728 public int registerTargetWaypoint(Vector3 target, float tolerance)
3729 {
3730 if (m_parentGroup != null)
3731 {
3732 return m_parentGroup.registerTargetWaypoint(target, tolerance);
3733 }
3734 return 0;
3735 }
3736
3737 public void unregisterTargetWaypoint(int handle)
3738 {
3739 if (m_parentGroup != null)
3740 {
3741 m_parentGroup.unregisterTargetWaypoint(handle);
3742 }
3743 }
3744
3745 public void SetCameraAtOffset(Vector3 v)
3746 {
3747 m_cameraAtOffset = v;
3748 }
3749
3750 public void SetCameraEyeOffset(Vector3 v)
3751 {
3752 m_cameraEyeOffset = v;
3753 }
3754
3755 public void SetForceMouselook(bool force)
3756 {
3757 m_forceMouselook = force;
3758 }
3759
3760 public Vector3 GetCameraAtOffset()
3761 {
3762 return m_cameraAtOffset;
3763 }
3764
3765 public Vector3 GetCameraEyeOffset()
3766 {
3767 return m_cameraEyeOffset;
3768 }
3769
3770 public bool GetForceMouselook()
3771 {
3772 return m_forceMouselook;
3773 }
3774
3775 public override string ToString()
3776 {
3777 return String.Format("{0} {1} (parent {2}))", Name, UUID, ParentGroup);
3778 }
3779
3780 #endregion Public Methods
3781
3782 public void SendTerseUpdateToClient(IClientAPI remoteClient)
3783 {
3784 if (ParentGroup == null || ParentGroup.IsDeleted)
3785 return;
3786
3787 Vector3 lPos = OffsetPosition;
3788
3789 byte state = Shape.State;
3790 if (IsAttachment)
3791 {
3792 if (ParentGroup.RootPart != this)
3793 return;
3794
3795 lPos = ParentGroup.RootPart.AttachedPos;
3796 state = (byte)AttachmentPoint;
3797 }
3798 else
3799 {
3800 if (ParentGroup.RootPart == this)
3801 lPos = AbsolutePosition;
3802 }
3803
3804 remoteClient.SendPrimTerseUpdate(m_regionHandle,
3805 (ushort)(m_parentGroup.GetTimeDilation() *
3806 (float)ushort.MaxValue), LocalId, lPos,
3807 RotationOffset, Velocity,
3808 RotationalVelocity, state, FromAssetID,
3809 OwnerID, (int)AttachmentPoint);
3810 }
3811
3812 public void AddScriptLPS(int count)
3813 {
3814 m_parentGroup.AddScriptLPS(count);
3815 }
3816
3817 public void ApplyNextOwnerPermissions()
3818 {
3819 _baseMask &= _nextOwnerMask;
3820 _ownerMask &= _nextOwnerMask;
3821 _everyoneMask &= _nextOwnerMask;
3822
3823 Inventory.ApplyNextOwnerPermissions();
3824 }
3825 }
3826}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs
deleted file mode 100644
index 8137a53..0000000
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs
+++ /dev/null
@@ -1,892 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenMetaverse;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications.Cache;
35using OpenSim.Region.Interfaces;
36using OpenSim.Region.Environment.Interfaces;
37using OpenSim.Region.Environment.Scenes.Scripting;
38
39namespace OpenSim.Region.Environment.Scenes
40{
41 public class SceneObjectPartInventory : IEntityInventory
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private string m_inventoryFileName = String.Empty;
46 private int m_inventoryFileNameSerial = 0;
47
48 /// <value>
49 /// The part to which the inventory belongs.
50 /// </value>
51 private SceneObjectPart m_part;
52
53 /// <summary>
54 /// Serial count for inventory file , used to tell if inventory has changed
55 /// no need for this to be part of Database backup
56 /// </summary>
57 protected uint m_inventorySerial = 0;
58
59 /// <summary>
60 /// Holds in memory prim inventory
61 /// </summary>
62 protected TaskInventoryDictionary m_items = new TaskInventoryDictionary();
63
64 /// <summary>
65 /// Tracks whether inventory has changed since the last persistent backup
66 /// </summary>
67 internal bool HasInventoryChanged;
68
69 /// <value>
70 /// Inventory serial number
71 /// </value>
72 protected internal uint Serial
73 {
74 get { return m_inventorySerial; }
75 set { m_inventorySerial = value; }
76 }
77
78 /// <value>
79 /// Raw inventory data
80 /// </value>
81 protected internal TaskInventoryDictionary Items
82 {
83 get { return m_items; }
84 set
85 {
86 m_items = value;
87 m_inventorySerial++;
88 }
89 }
90
91 /// <summary>
92 /// Constructor
93 /// </summary>
94 /// <param name="part">
95 /// A <see cref="SceneObjectPart"/>
96 /// </param>
97 public SceneObjectPartInventory(SceneObjectPart part)
98 {
99 m_part = part;
100 }
101
102 /// <summary>
103 /// Force the task inventory of this prim to persist at the next update sweep
104 /// </summary>
105 public void ForceInventoryPersistence()
106 {
107 HasInventoryChanged = true;
108 }
109
110 /// <summary>
111 /// Reset UUIDs for all the items in the prim's inventory. This involves either generating
112 /// new ones or setting existing UUIDs to the correct parent UUIDs.
113 ///
114 /// If this method is called and there are inventory items, then we regard the inventory as having changed.
115 /// </summary>
116 /// <param name="linkNum">Link number for the part</param>
117 public void ResetInventoryIDs()
118 {
119 lock (Items)
120 {
121 if (0 == Items.Count)
122 return;
123
124 HasInventoryChanged = true;
125 m_part.ParentGroup.HasGroupChanged = true;
126 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
127 Items.Clear();
128
129 foreach (TaskInventoryItem item in items)
130 {
131 item.ResetIDs(m_part.UUID);
132 Items.Add(item.ItemID, item);
133 }
134 }
135 }
136
137 /// <summary>
138 /// Change every item in this inventory to a new owner.
139 /// </summary>
140 /// <param name="ownerId"></param>
141 public void ChangeInventoryOwner(UUID ownerId)
142 {
143 lock (Items)
144 {
145 if (0 == Items.Count)
146 {
147 return;
148 }
149
150 HasInventoryChanged = true;
151 m_part.ParentGroup.HasGroupChanged = true;
152 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
153 foreach (TaskInventoryItem item in items)
154 {
155 if (ownerId != item.OwnerID)
156 {
157 item.LastOwnerID = item.OwnerID;
158 item.OwnerID = ownerId;
159 }
160 }
161 }
162 }
163
164 /// <summary>
165 /// Change every item in this inventory to a new group.
166 /// </summary>
167 /// <param name="groupID"></param>
168 public void ChangeInventoryGroup(UUID groupID)
169 {
170 lock (Items)
171 {
172 if (0 == Items.Count)
173 {
174 return;
175 }
176
177 HasInventoryChanged = true;
178 m_part.ParentGroup.HasGroupChanged = true;
179 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
180 foreach (TaskInventoryItem item in items)
181 {
182 if (groupID != item.GroupID)
183 {
184 item.GroupID = groupID;
185 }
186 }
187 }
188 }
189
190 /// <summary>
191 /// Start all the scripts contained in this prim's inventory
192 /// </summary>
193 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
194 {
195 lock (m_items)
196 {
197 foreach (TaskInventoryItem item in Items.Values)
198 {
199 if ((int)InventoryType.LSL == item.InvType)
200 {
201 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
202 }
203 }
204 }
205 }
206
207 /// <summary>
208 /// Stop all the scripts in this prim.
209 /// </summary>
210 public void RemoveScriptInstances()
211 {
212 lock (Items)
213 {
214 foreach (TaskInventoryItem item in Items.Values)
215 {
216 if ((int)InventoryType.LSL == item.InvType)
217 {
218 RemoveScriptInstance(item.ItemID);
219 m_part.RemoveScriptEvents(item.ItemID);
220 }
221 }
222 }
223 }
224
225 /// <summary>
226 /// Start a script which is in this prim's inventory.
227 /// </summary>
228 /// <param name="item"></param>
229 /// <returns></returns>
230 public void CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource)
231 {
232 // m_log.InfoFormat(
233 // "[PRIM INVENTORY]: " +
234 // "Starting script {0}, {1} in prim {2}, {3}",
235 // item.Name, item.ItemID, Name, UUID);
236
237 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
238 return;
239
240 m_part.AddFlag(PrimFlags.Scripted);
241
242 if (!m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts)
243 {
244 if (stateSource == 1 && // Prim crossing
245 m_part.ParentGroup.Scene.m_trustBinaries)
246 {
247 m_items[item.ItemID].PermsMask = 0;
248 m_items[item.ItemID].PermsGranter = UUID.Zero;
249 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
250 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
251 m_part.ParentGroup.AddActiveScriptCount(1);
252 m_part.ScheduleFullUpdate();
253 return;
254 }
255 AssetCache cache = m_part.ParentGroup.Scene.AssetCache;
256
257 cache.GetAsset(item.AssetID, delegate(UUID assetID, AssetBase asset)
258 {
259 if (null == asset)
260 {
261 m_log.ErrorFormat(
262 "[PRIM INVENTORY]: " +
263 "Couldn't start script {0}, {1} since asset ID {2} could not be found",
264 item.Name, item.ItemID, item.AssetID);
265 }
266 else
267 {
268 m_items[item.ItemID].PermsMask = 0;
269 m_items[item.ItemID].PermsGranter = UUID.Zero;
270 string script = Utils.BytesToString(asset.Data);
271 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
272 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
273 m_part.ParentGroup.AddActiveScriptCount(1);
274 m_part.ScheduleFullUpdate();
275 }
276 }, false);
277 }
278 }
279
280 /// <summary>
281 /// Start a script which is in this prim's inventory.
282 /// </summary>
283 /// <param name="itemId">
284 /// A <see cref="UUID"/>
285 /// </param>
286 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
287 {
288 lock (m_items)
289 {
290 if (m_items.ContainsKey(itemId))
291 {
292 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
293 }
294 else
295 {
296 m_log.ErrorFormat(
297 "[PRIM INVENTORY]: " +
298 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
299 itemId, m_part.Name, m_part.UUID);
300 }
301 }
302 }
303
304 /// <summary>
305 /// Stop a script which is in this prim's inventory.
306 /// </summary>
307 /// <param name="itemId"></param>
308 public void RemoveScriptInstance(UUID itemId)
309 {
310 if (m_items.ContainsKey(itemId))
311 {
312 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId);
313 m_part.ParentGroup.AddActiveScriptCount(-1);
314 }
315 else
316 {
317 m_log.ErrorFormat(
318 "[PRIM INVENTORY]: " +
319 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2}",
320 itemId, m_part.Name, m_part.UUID);
321 }
322 }
323
324 /// <summary>
325 /// Check if the inventory holds an item with a given name.
326 /// This method assumes that the task inventory is already locked.
327 /// </summary>
328 /// <param name="name"></param>
329 /// <returns></returns>
330 private bool InventoryContainsName(string name)
331 {
332 foreach (TaskInventoryItem item in Items.Values)
333 {
334 if (item.Name == name)
335 return true;
336 }
337 return false;
338 }
339
340 /// <summary>
341 /// For a given item name, return that name if it is available. Otherwise, return the next available
342 /// similar name (which is currently the original name with the next available numeric suffix).
343 /// </summary>
344 /// <param name="name"></param>
345 /// <returns></returns>
346 private string FindAvailableInventoryName(string name)
347 {
348 if (!InventoryContainsName(name))
349 return name;
350
351 int suffix=1;
352 while (suffix < 256)
353 {
354 string tryName=String.Format("{0} {1}", name, suffix);
355 if (!InventoryContainsName(tryName))
356 return tryName;
357 suffix++;
358 }
359 return String.Empty;
360 }
361
362 /// <summary>
363 /// Add an item to this prim's inventory. If an item with the same name already exists, then an alternative
364 /// name is chosen.
365 /// </summary>
366 /// <param name="item"></param>
367 public void AddInventoryItem(TaskInventoryItem item, bool allowedDrop)
368 {
369 AddInventoryItem(item.Name, item, allowedDrop);
370 }
371
372 /// <summary>
373 /// Add an item to this prim's inventory. If an item with the same name already exists, it is replaced.
374 /// </summary>
375 /// <param name="item"></param>
376 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
377 {
378 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
379 foreach (TaskInventoryItem i in il)
380 {
381 if (i.Name == item.Name)
382 {
383 if (i.InvType == (int)InventoryType.LSL)
384 RemoveScriptInstance(i.ItemID);
385
386 RemoveInventoryItem(i.ItemID);
387 break;
388 }
389 }
390
391 AddInventoryItem(item.Name, item, allowedDrop);
392 }
393
394 /// <summary>
395 /// Add an item to this prim's inventory.
396 /// </summary>
397 /// <param name="name">The name that the new item should have.</param>
398 /// <param name="item">
399 /// The item itself. The name within this structure is ignored in favour of the name
400 /// given in this method's arguments
401 /// </param>
402 /// <param name="allowedDrop">
403 /// Item was only added to inventory because AllowedDrop is set
404 /// </param>
405 protected void AddInventoryItem(string name, TaskInventoryItem item, bool allowedDrop)
406 {
407 name = FindAvailableInventoryName(name);
408 if (name == String.Empty)
409 return;
410
411 item.ParentID = m_part.UUID;
412 item.ParentPartID = m_part.UUID;
413 item.Name = name;
414
415 lock (m_items)
416 {
417 m_items.Add(item.ItemID, item);
418
419 if (allowedDrop)
420 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
421 else
422 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
423 }
424
425 m_inventorySerial++;
426 //m_inventorySerial += 2;
427 HasInventoryChanged = true;
428 m_part.ParentGroup.HasGroupChanged = true;
429 }
430
431 /// <summary>
432 /// Restore a whole collection of items to the prim's inventory at once.
433 /// We assume that the items already have all their fields correctly filled out.
434 /// The items are not flagged for persistence to the database, since they are being restored
435 /// from persistence rather than being newly added.
436 /// </summary>
437 /// <param name="items"></param>
438 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
439 {
440 lock (m_items)
441 {
442 foreach (TaskInventoryItem item in items)
443 {
444 m_items.Add(item.ItemID, item);
445 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
446 }
447 }
448
449 m_inventorySerial++;
450 }
451
452 /// <summary>
453 /// Returns an existing inventory item. Returns the original, so any changes will be live.
454 /// </summary>
455 /// <param name="itemID"></param>
456 /// <returns>null if the item does not exist</returns>
457 public TaskInventoryItem GetInventoryItem(UUID itemId)
458 {
459 TaskInventoryItem item;
460 m_items.TryGetValue(itemId, out item);
461
462 return item;
463 }
464
465 /// <summary>
466 /// Update an existing inventory item.
467 /// </summary>
468 /// <param name="item">The updated item. An item with the same id must already exist
469 /// in this prim's inventory.</param>
470 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
471 public bool UpdateInventoryItem(TaskInventoryItem item)
472 {
473 lock (m_items)
474 {
475 if (m_items.ContainsKey(item.ItemID))
476 {
477 item.ParentID = m_part.UUID;
478 item.ParentPartID = m_part.UUID;
479 item.Flags = m_items[item.ItemID].Flags;
480 if (item.AssetID == UUID.Zero)
481 {
482 item.AssetID = m_items[item.ItemID].AssetID;
483 }
484 else if ((InventoryType)item.Type == InventoryType.Notecard)
485 {
486 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
487
488 if (presence != null)
489 {
490 presence.ControllingClient.SendAgentAlertMessage(
491 "Notecard saved", false);
492 }
493 }
494
495 m_items[item.ItemID] = item;
496 m_inventorySerial++;
497 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
498
499 HasInventoryChanged = true;
500 m_part.ParentGroup.HasGroupChanged = true;
501
502 return true;
503 }
504 else
505 {
506 m_log.ErrorFormat(
507 "[PRIM INVENTORY]: " +
508 "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
509 item.ItemID, m_part.Name, m_part.UUID);
510 }
511 }
512
513 return false;
514 }
515
516 /// <summary>
517 /// Remove an item from this prim's inventory
518 /// </summary>
519 /// <param name="itemID"></param>
520 /// <returns>Numeric asset type of the item removed. Returns -1 if the item did not exist
521 /// in this prim's inventory.</returns>
522 public int RemoveInventoryItem(UUID itemID)
523 {
524 lock (m_items)
525 {
526 if (m_items.ContainsKey(itemID))
527 {
528 int type = m_items[itemID].InvType;
529 if (type == 10) // Script
530 {
531 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
532 }
533 m_items.Remove(itemID);
534 m_inventorySerial++;
535 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
536
537 HasInventoryChanged = true;
538 m_part.ParentGroup.HasGroupChanged = true;
539
540 int scriptcount = 0;
541 lock (m_items)
542 {
543 foreach (TaskInventoryItem item in m_items.Values)
544 {
545 if (item.Type == 10)
546 {
547 scriptcount++;
548 }
549 }
550 }
551
552 if (scriptcount <= 0)
553 {
554 m_part.RemFlag(PrimFlags.Scripted);
555 }
556
557 m_part.ScheduleFullUpdate();
558
559 return type;
560 }
561 else
562 {
563 m_log.ErrorFormat(
564 "[PRIM INVENTORY]: " +
565 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
566 itemID, m_part.Name, m_part.UUID);
567 }
568 }
569
570 return -1;
571 }
572
573 public string GetInventoryFileName()
574 {
575 if (m_inventoryFileName == String.Empty)
576 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
577 if (m_inventoryFileNameSerial < m_inventorySerial)
578 {
579 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
580 }
581 return m_inventoryFileName;
582 }
583
584 /// <summary>
585 /// Return the name with which a client can request a xfer of this prim's inventory metadata
586 /// </summary>
587 /// <param name="client"></param>
588 /// <param name="localID"></param>
589 public bool GetInventoryFileName(IClientAPI client, uint localID)
590 {
591// m_log.DebugFormat(
592// "[PRIM INVENTORY]: Received request from client {0} for inventory file name of {1}, {2}",
593// client.AgentId, Name, UUID);
594
595 if (m_inventorySerial > 0)
596 {
597 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
598 Utils.StringToBytes(GetInventoryFileName()));
599 return true;
600 }
601 else
602 {
603 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
604 return false;
605 }
606 }
607
608 /// <summary>
609 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
610 /// </summary>
611 /// <param name="xferManager"></param>
612 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
613 {
614 byte[] fileData = new byte[0];
615
616 // Confusingly, the folder item has to be the object id, while the 'parent id' has to be zero. This matches
617 // what appears to happen in the Second Life protocol. If this isn't the case. then various functionality
618 // isn't available (such as drag from prim inventory to agent inventory)
619 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
620
621 lock (m_items)
622 {
623 foreach (TaskInventoryItem item in m_items.Values)
624 {
625 UUID ownerID = item.OwnerID;
626 uint everyoneMask = 0;
627 uint baseMask = item.BasePermissions;
628 uint ownerMask = item.CurrentPermissions;
629
630 invString.AddItemStart();
631 invString.AddNameValueLine("item_id", item.ItemID.ToString());
632 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
633
634 invString.AddPermissionsStart();
635
636 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
637 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
638 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0));
639 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
640 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
641
642 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
643 invString.AddNameValueLine("owner_id", ownerID.ToString());
644
645 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
646
647 invString.AddNameValueLine("group_id", item.GroupID.ToString());
648 invString.AddSectionEnd();
649
650 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
651 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
652 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
653 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
654
655 invString.AddSaleStart();
656 invString.AddNameValueLine("sale_type", "not");
657 invString.AddNameValueLine("sale_price", "0");
658 invString.AddSectionEnd();
659
660 invString.AddNameValueLine("name", item.Name + "|");
661 invString.AddNameValueLine("desc", item.Description + "|");
662
663 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
664 invString.AddSectionEnd();
665 }
666 }
667
668 fileData = Utils.StringToBytes(invString.BuildString);
669
670 //Console.WriteLine(Utils.BytesToString(fileData));
671 //m_log.Debug("[PRIM INVENTORY]: RequestInventoryFile fileData: " + Utils.BytesToString(fileData));
672
673 if (fileData.Length > 2)
674 {
675 xferManager.AddNewFile(m_inventoryFileName, fileData);
676 }
677 }
678
679 /// <summary>
680 /// Process inventory backup
681 /// </summary>
682 /// <param name="datastore"></param>
683 public void ProcessInventoryBackup(IRegionDataStore datastore)
684 {
685 if (HasInventoryChanged)
686 {
687 lock (Items)
688 {
689 datastore.StorePrimInventory(m_part.UUID, Items.Values);
690 }
691
692 HasInventoryChanged = false;
693 }
694 }
695
696 public class InventoryStringBuilder
697 {
698 public string BuildString = String.Empty;
699
700 public InventoryStringBuilder(UUID folderID, UUID parentID)
701 {
702 BuildString += "\tinv_object\t0\n\t{\n";
703 AddNameValueLine("obj_id", folderID.ToString());
704 AddNameValueLine("parent_id", parentID.ToString());
705 AddNameValueLine("type", "category");
706 AddNameValueLine("name", "Contents|");
707 AddSectionEnd();
708 }
709
710 public void AddItemStart()
711 {
712 BuildString += "\tinv_item\t0\n";
713 AddSectionStart();
714 }
715
716 public void AddPermissionsStart()
717 {
718 BuildString += "\tpermissions 0\n";
719 AddSectionStart();
720 }
721
722 public void AddSaleStart()
723 {
724 BuildString += "\tsale_info\t0\n";
725 AddSectionStart();
726 }
727
728 protected void AddSectionStart()
729 {
730 BuildString += "\t{\n";
731 }
732
733 public void AddSectionEnd()
734 {
735 BuildString += "\t}\n";
736 }
737
738 public void AddLine(string addLine)
739 {
740 BuildString += addLine;
741 }
742
743 public void AddNameValueLine(string name, string value)
744 {
745 BuildString += "\t\t";
746 BuildString += name + "\t";
747 BuildString += value + "\n";
748 }
749
750 public void Close()
751 {
752 }
753 }
754
755 public uint MaskEffectivePermissions()
756 {
757 uint mask=0x7fffffff;
758
759 foreach (TaskInventoryItem item in m_items.Values)
760 {
761 if (item.InvType != 6)
762 {
763 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
764 mask &= ~((uint)PermissionMask.Copy >> 13);
765 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
766 mask &= ~((uint)PermissionMask.Transfer >> 13);
767 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
768 mask &= ~((uint)PermissionMask.Modify >> 13);
769 }
770 else
771 {
772 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
773 mask &= ~((uint)PermissionMask.Copy >> 13);
774 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
775 mask &= ~((uint)PermissionMask.Transfer >> 13);
776 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
777 mask &= ~((uint)PermissionMask.Modify >> 13);
778 }
779
780 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
781 mask &= ~(uint)PermissionMask.Copy;
782 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
783 mask &= ~(uint)PermissionMask.Transfer;
784 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
785 mask &= ~(uint)PermissionMask.Modify;
786 }
787 return mask;
788 }
789
790 public void ApplyNextOwnerPermissions()
791 {
792 foreach (TaskInventoryItem item in m_items.Values)
793 {
794 if (item.InvType == 6 && (item.CurrentPermissions & 7) != 0)
795 {
796 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
797 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
798 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
799 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
800 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
801 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
802 item.CurrentPermissions |= 8;
803 }
804 item.CurrentPermissions &= item.NextPermissions;
805 item.BasePermissions &= item.NextPermissions;
806 item.EveryonePermissions &= item.NextPermissions;
807 }
808
809 m_part.TriggerScriptChangedEvent(Changed.OWNER);
810 }
811
812 public void ApplyGodPermissions(uint perms)
813 {
814 foreach (TaskInventoryItem item in m_items.Values)
815 {
816 item.CurrentPermissions = perms;
817 item.BasePermissions = perms;
818 }
819 }
820
821 public bool ContainsScripts()
822 {
823 foreach (TaskInventoryItem item in m_items.Values)
824 {
825 if (item.InvType == 10)
826 {
827 return true;
828 }
829 }
830 return false;
831 }
832
833 public List<UUID> GetInventoryList()
834 {
835 List<UUID> ret = new List<UUID>();
836
837 foreach (TaskInventoryItem item in m_items.Values)
838 ret.Add(item.ItemID);
839
840 return ret;
841 }
842
843 public string[] GetScriptAssemblies()
844 {
845 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
846
847 List<string> ret = new List<string>();
848
849 foreach (TaskInventoryItem item in m_items.Values)
850 {
851 if (item.InvType == 10)
852 {
853 foreach (IScriptModule e in engines)
854 {
855 string n = e.GetAssemblyName(item.ItemID);
856 if (n != "")
857 {
858 if (!ret.Contains(n))
859 ret.Add(n);
860 break;
861 }
862 }
863 }
864 }
865 return ret.ToArray();
866 }
867
868 public Dictionary<UUID, string> GetScriptStates()
869 {
870 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
871 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
872
873 foreach (TaskInventoryItem item in m_items.Values)
874 {
875 if (item.InvType == 10)
876 {
877 foreach (IScriptModule e in engines)
878 {
879 string n = e.GetXMLState(item.ItemID);
880 if (n != "")
881 {
882 if (!ret.ContainsKey(item.ItemID))
883 ret[item.ItemID] = n;
884 break;
885 }
886 }
887 }
888 }
889 return ret;
890 }
891 }
892}
diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
deleted file mode 100644
index ed455f4..0000000
--- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs
+++ /dev/null
@@ -1,3651 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.Serialization;
32using System.Security.Permissions;
33using OpenMetaverse;
34using OpenMetaverse.Packets;
35using log4net;
36using OpenSim.Framework;
37using OpenSim.Framework.Client;
38using OpenSim.Framework.Communications.Cache;
39using OpenSim.Region.Environment.Interfaces;
40using OpenSim.Region.Environment.Types;
41using OpenSim.Region.Interfaces;
42using OpenSim.Region.Physics.Manager;
43using OSD = OpenMetaverse.StructuredData.OSD;
44
45namespace OpenSim.Region.Environment.Scenes
46{
47 enum ScriptControlled : uint
48 {
49 CONTROL_ZERO = 0,
50 CONTROL_FWD = 1,
51 CONTROL_BACK = 2,
52 CONTROL_LEFT = 4,
53 CONTROL_RIGHT = 8,
54 CONTROL_UP = 16,
55 CONTROL_DOWN = 32,
56 CONTROL_ROT_LEFT = 256,
57 CONTROL_ROT_RIGHT = 512,
58 CONTROL_LBUTTON = 268435456,
59 CONTROL_ML_LBUTTON = 1073741824
60 }
61
62 struct ScriptControllers
63 {
64 public UUID itemID;
65 public uint objID;
66 public ScriptControlled ignoreControls;
67 public ScriptControlled eventControls;
68 }
69
70 [Serializable]
71 public class ScenePresence : EntityBase, ISerializable
72 {
73// ~ScenePresence()
74// {
75// System.Console.WriteLine("[ScenePresence] Destructor called");
76// }
77
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
80 public static byte[] DefaultTexture;
81
82 public UUID currentParcelUUID = UUID.Zero;
83 private AnimationSet m_animations = new AnimationSet();
84 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
85 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
86 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
87 private bool MouseDown = false;
88 private SceneObjectGroup proxyObjectGroup = null;
89 //private SceneObjectPart proxyObjectPart = null;
90
91 public Vector3 lastKnownAllowedPosition = new Vector3();
92 public bool sentMessageAboutRestrictedParcelFlyingDown = false;
93
94 private bool m_updateflag = false;
95 private byte m_movementflag = 0;
96 private readonly List<NewForce> m_forcesList = new List<NewForce>();
97 private short m_updateCount = 0;
98 private uint m_requestedSitTargetID = 0;
99 private UUID m_requestedSitTargetUUID = UUID.Zero;
100
101 private bool m_startAnimationSet = false;
102
103 private Vector3 m_requestedSitOffset = new Vector3();
104
105 private Vector3 m_LastFinitePos = new Vector3();
106
107 private float m_sitAvatarHeight = 2.0f;
108
109 // experimentally determined "fudge factor" to make sit-target positions
110 // the same as in SecondLife. Fudge factor was tested for 36 different
111 // test cases including prims of type box, sphere, cylinder, and torus,
112 // with varying parameters for sit target location, prim size, prim
113 // rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
114 // issue #1716
115 private static readonly Vector3 m_sitTargetCorrectionOffset = new Vector3(0.1f, 0.0f, 0.3f);
116 private float m_godlevel = 0;
117
118 private bool m_invulnerable = true;
119
120 private Vector3 m_LastChildAgentUpdatePosition = new Vector3();
121
122 private int m_perfMonMS = 0;
123
124 private bool m_setAlwaysRun = false;
125
126 private Quaternion m_bodyRot= Quaternion.Identity;
127
128 public bool IsRestrictedToRegion = false;
129
130 public string JID = string.Empty;
131
132 // Agent moves with a PID controller causing a force to be exerted.
133 private bool m_newForce = false;
134 private bool m_newCoarseLocations = true;
135 private float m_health = 100f;
136
137 private Vector3 m_lastVelocity = Vector3.Zero;
138
139 // Default AV Height
140 private float m_avHeight = 127.0f;
141
142 protected RegionInfo m_regionInfo;
143 protected ulong crossingFromRegion = 0;
144
145 private readonly Vector3[] Dir_Vectors = new Vector3[6];
146
147 /// <value>
148 /// The avatar position last sent to clients
149 /// </value>
150 private Vector3 lastPhysPos = Vector3.Zero;
151
152 /// <value>
153 /// The avatar body rotation last sent to clients
154 /// </value>
155 private Quaternion lastPhysRot = Quaternion.Identity;
156
157 // Position of agent's camera in world (region cordinates)
158 protected Vector3 m_CameraCenter = Vector3.Zero;
159
160 // Use these three vectors to figure out what the agent is looking at
161 // Convert it to a Matrix and/or Quaternion
162 protected Vector3 m_CameraAtAxis = Vector3.Zero;
163 protected Vector3 m_CameraLeftAxis = Vector3.Zero;
164 protected Vector3 m_CameraUpAxis = Vector3.Zero;
165 private uint m_AgentControlFlags = 0;
166 private Quaternion m_headrotation = Quaternion.Identity;
167 private byte m_state = 0;
168
169 //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
170 private Vector3 movementvector = Vector3.Zero;
171
172 private bool m_autopilotMoving = false;
173 private Vector3 m_autoPilotTarget = Vector3.Zero;
174 private bool m_sitAtAutoTarget = false;
175
176 private string m_nextSitAnimation = String.Empty;
177
178 //PauPaw:Proper PID Controler for autopilot************
179 private bool m_moveToPositionInProgress = false;
180 private Vector3 m_moveToPositionTarget = Vector3.Zero;
181 //private int m_moveToPositionStateStatus = 0;
182 //*****************************************************
183
184 // Agent's Draw distance.
185 protected float m_DrawDistance = 0f;
186
187 protected AvatarAppearance m_appearance;
188
189 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
190
191 // neighbouring regions we have enabled a child agent in
192 // holds the seed cap for the child agent in that region
193 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
194
195 /// <summary>
196 /// Implemented Control Flags
197 /// </summary>
198 private enum Dir_ControlFlags
199 {
200 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
201 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
202 DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
203 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
204 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
205 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
206 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
207 }
208
209 /// <summary>
210 /// Position at which a significant movement was made
211 /// </summary>
212 private Vector3 posLastSignificantMove = new Vector3();
213
214 private UpdateQueue m_partsUpdateQueue = new UpdateQueue();
215 private Queue<SceneObjectGroup> m_pendingObjects = null;
216
217 private Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
218
219 // For teleports and crossings callbacks
220 string m_callbackURI;
221 ulong m_rootRegionHandle;
222
223 #region Properties
224
225 /// <summary>
226 /// Physical scene representation of this Avatar.
227 /// </summary>
228 public PhysicsActor PhysicsActor
229 {
230 set { m_physicsActor = value; }
231 get { return m_physicsActor; }
232 }
233
234 public byte MovementFlag
235 {
236 set { m_movementflag = value; }
237 get { return m_movementflag; }
238 }
239
240 public bool Updated
241 {
242 set { m_updateflag = value; }
243 get { return m_updateflag; }
244 }
245
246 public bool Invulnerable
247 {
248 set { m_invulnerable = value; }
249 get { return m_invulnerable; }
250 }
251
252 public float GodLevel
253 {
254 get { return m_godlevel; }
255 }
256
257 private readonly ulong m_regionHandle;
258
259 public ulong RegionHandle
260 {
261 get { return m_regionHandle; }
262 }
263
264 public Vector3 CameraPosition
265 {
266 get { return m_CameraCenter; }
267 }
268
269 public Quaternion CameraRotation
270 {
271 get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
272 }
273
274 public Vector3 Lookat
275 {
276 get
277 {
278 Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
279
280 if (a == Vector3.Zero)
281 return a;
282
283 return Util.GetNormalizedVector(a);
284 }
285 }
286
287 private readonly string m_firstname;
288
289 public string Firstname
290 {
291 get { return m_firstname; }
292 }
293
294 private readonly string m_lastname;
295
296 public string Lastname
297 {
298 get { return m_lastname; }
299 }
300
301 private string m_grouptitle;
302
303 public string Grouptitle
304 {
305 get { return m_grouptitle; }
306 set { m_grouptitle = value; }
307 }
308
309 public float DrawDistance
310 {
311 get { return m_DrawDistance; }
312 }
313
314 protected bool m_allowMovement = true;
315
316 public bool AllowMovement
317 {
318 get { return m_allowMovement; }
319 set { m_allowMovement = value; }
320 }
321
322 public bool SetAlwaysRun
323 {
324 get
325 {
326 if (PhysicsActor != null)
327 {
328 return PhysicsActor.SetAlwaysRun;
329 }
330 else
331 {
332 return m_setAlwaysRun;
333 }
334 }
335 set
336 {
337 m_setAlwaysRun = value;
338 if (PhysicsActor != null)
339 {
340 PhysicsActor.SetAlwaysRun = value;
341 }
342 }
343 }
344
345 public byte State
346 {
347 get { return m_state; }
348 set { m_state = value; }
349 }
350
351 public uint AgentControlFlags
352 {
353 get { return m_AgentControlFlags; }
354 set { m_AgentControlFlags = value; }
355 }
356
357 /// <summary>
358 /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
359 /// </summary>
360 private IClientAPI m_controllingClient;
361
362 protected PhysicsActor m_physicsActor;
363
364 /// <value>
365 /// The client controlling this presence
366 /// </value>
367 public IClientAPI ControllingClient
368 {
369 get { return m_controllingClient; }
370 }
371
372 public IClientCore ClientView
373 {
374 get { return (IClientCore) m_controllingClient; }
375 }
376
377 protected Vector3 m_parentPosition = new Vector3();
378 public Vector3 ParentPosition
379 {
380 get { return m_parentPosition; }
381 set { m_parentPosition = value; }
382 }
383
384 /// <summary>
385 /// Absolute position of this avatar in 'region cordinates'
386 /// </summary>
387 public override Vector3 AbsolutePosition
388 {
389 get
390 {
391 if (m_physicsActor != null)
392 {
393 m_pos.X = m_physicsActor.Position.X;
394 m_pos.Y = m_physicsActor.Position.Y;
395 m_pos.Z = m_physicsActor.Position.Z;
396 }
397
398 return m_parentPosition + m_pos;
399 }
400 set
401 {
402 if (m_physicsActor != null)
403 {
404 try
405 {
406 lock (m_scene.SyncRoot)
407 {
408 m_physicsActor.Position = new PhysicsVector(value.X, value.Y, value.Z);
409 }
410 }
411 catch (Exception e)
412 {
413 Console.WriteLine("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
414 }
415 }
416
417 m_pos = value;
418 m_parentPosition = new Vector3(0, 0, 0);
419 }
420 }
421
422 /// <summary>
423 /// Current velocity of the avatar.
424 /// </summary>
425 public override Vector3 Velocity
426 {
427 get
428 {
429 if (m_physicsActor != null)
430 {
431 m_velocity.X = m_physicsActor.Velocity.X;
432 m_velocity.Y = m_physicsActor.Velocity.Y;
433 m_velocity.Z = m_physicsActor.Velocity.Z;
434 }
435
436 return m_velocity;
437 }
438 set
439 {
440 //m_log.DebugFormat("In {0} setting velocity of {1} to {2}", m_scene.RegionInfo.RegionName, Name, value);
441
442 if (m_physicsActor != null)
443 {
444 try
445 {
446 lock (m_scene.SyncRoot)
447 {
448 m_physicsActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z);
449 }
450 }
451 catch (Exception e)
452 {
453 Console.WriteLine("[SCENEPRESENCE]: VELOCITY " + e.Message);
454 }
455 }
456
457 m_velocity = value;
458 }
459 }
460
461 /// <summary>
462 /// If this is true, agent doesn't have a representation in this scene.
463 /// this is an agent 'looking into' this scene from a nearby scene(region)
464 ///
465 /// if False, this agent has a representation in this scene
466 /// </summary>
467 private bool m_isChildAgent = true;
468
469 public bool IsChildAgent
470 {
471 get { return m_isChildAgent; }
472 set { m_isChildAgent = value; }
473 }
474
475 private uint m_parentID = 0;
476
477 public uint ParentID
478 {
479 get { return m_parentID; }
480 set { m_parentID = value; }
481 }
482 public float Health
483 {
484 get { return m_health; }
485 set { m_health = value; }
486 }
487
488 /// <summary>
489 /// These are the region handles known by the avatar.
490 /// </summary>
491 public List<ulong> KnownChildRegionHandles
492 {
493 get
494 {
495 if (m_knownChildRegions.Count == 0)
496 return new List<ulong>();
497 else
498 return new List<ulong>(m_knownChildRegions.Keys);
499 }
500 }
501
502 public Dictionary<ulong, string> KnownRegions
503 {
504 get { return m_knownChildRegions; }
505 set
506 {
507 m_knownChildRegions = value;
508 }
509 }
510
511 public void AdjustKnownSeeds()
512 {
513 Dictionary<ulong, string> seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
514 List<ulong> old = new List<ulong>();
515 foreach (ulong handle in seeds.Keys)
516 {
517 uint x, y;
518 Utils.LongToUInts(handle, out x, out y);
519 x = x / Constants.RegionSize;
520 y = y / Constants.RegionSize;
521 if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
522 {
523 old.Add(handle);
524 }
525 }
526 DropOldNeighbours(old);
527 Scene.CapsModule.SetChildrenSeed(UUID, seeds);
528 KnownRegions = seeds;
529 //Console.WriteLine(" ++++++++++AFTER+++++++++++++ ");
530 //DumpKnownRegions();
531 }
532
533 public void DumpKnownRegions()
534 {
535 Console.WriteLine("================ KnownRegions {0} ================", Scene.RegionInfo.RegionName);
536 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
537 {
538 uint x, y;
539 Utils.LongToUInts(kvp.Key, out x, out y);
540 x = x / Constants.RegionSize;
541 y = y / Constants.RegionSize;
542 Console.WriteLine(" >> {0}, {1}: {2}", x, y, kvp.Value);
543 }
544 }
545
546 public AnimationSet Animations
547 {
548 get { return m_animations; }
549 }
550
551 #endregion
552
553 #region Constructor(s)
554
555 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo)
556 {
557 m_regionHandle = reginfo.RegionHandle;
558 m_controllingClient = client;
559 m_firstname = m_controllingClient.FirstName;
560 m_lastname = m_controllingClient.LastName;
561 m_name = String.Format("{0} {1}", m_firstname, m_lastname);
562
563 m_scene = world;
564 m_uuid = client.AgentId;
565 m_regionInfo = reginfo;
566 m_localId = m_scene.AllocateLocalId();
567
568 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
569 if (gm != null)
570 m_grouptitle = gm.GetGroupTitle(m_uuid);
571
572 AbsolutePosition = m_controllingClient.StartPos;
573 AdjustKnownSeeds();
574
575 TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here...
576
577 // we created a new ScenePresence (a new child agent) in a fresh region.
578 // Request info about all the (root) agents in this region
579 // Note: This won't send data *to* other clients in that region (children don't send)
580 SendInitialFullUpdateToAllClients();
581
582 RegisterToEvents();
583 SetDirectionVectors();
584
585 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
586 if (userInfo != null)
587 userInfo.OnItemReceived += ItemReceived;
588 }
589
590 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
591 AvatarWearable[] wearables)
592 : this(client, world, reginfo)
593 {
594 m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
595 }
596
597 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
598 : this(client, world, reginfo)
599 {
600 m_appearance = appearance;
601 }
602
603 public void RegisterToEvents()
604 {
605 m_controllingClient.OnRequestWearables += SendWearables;
606 m_controllingClient.OnSetAppearance += SetAppearance;
607 m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
608 m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
609 m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
610 m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
611 m_controllingClient.OnAgentSit += HandleAgentSit;
612 m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
613 m_controllingClient.OnStartAnim += HandleStartAnim;
614 m_controllingClient.OnStopAnim += HandleStopAnim;
615 m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
616 m_controllingClient.OnAutoPilotGo += DoAutoPilot;
617 m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
618
619 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
620 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
621 }
622
623 private void SetDirectionVectors()
624 {
625 Dir_Vectors[0] = new Vector3(1, 0, 0); //FORWARD
626 Dir_Vectors[1] = new Vector3(-1, 0, 0); //BACK
627 Dir_Vectors[2] = new Vector3(0, 1, 0); //LEFT
628 Dir_Vectors[3] = new Vector3(0, -1, 0); //RIGHT
629 Dir_Vectors[4] = new Vector3(0, 0, 1); //UP
630 Dir_Vectors[5] = new Vector3(0, 0, -1); //DOWN
631 Dir_Vectors[5] = new Vector3(0, 0, -0.5f); //DOWN_Nudge
632 }
633
634 #endregion
635
636 /// <summary>
637 /// Add the part to the queue of parts for which we need to send an update to the client
638 /// </summary>
639 /// <param name="part"></param>
640 public void QueuePartForUpdate(SceneObjectPart part)
641 {
642 //if (InterestList.Contains(part.ParentGroup))
643 //{
644 lock (m_partsUpdateQueue)
645 {
646 m_partsUpdateQueue.Enqueue(part);
647 }
648 // }
649 }
650
651 public uint GenerateClientFlags(UUID ObjectID)
652 {
653 return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
654 }
655
656 /// <summary>
657 /// Send updates to the client about prims which have been placed on the update queue. We don't
658 /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
659 /// timestamp has already been sent.
660 /// </summary>
661 public void SendPrimUpdates()
662 {
663 // if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode)
664 //{
665 // this.UpdateQuadTreeNode();
666 //this.RefreshQuadObject();
667 //}
668 m_perfMonMS = System.Environment.TickCount;
669
670 if (m_pendingObjects == null)
671 {
672 if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor)
673 {
674 m_pendingObjects = new Queue<SceneObjectGroup>();
675
676 List<EntityBase> ents = new List<EntityBase>(m_scene.Entities);
677 if (!m_isChildAgent) // Proximity sort makes no sense for
678 { // Child agents
679 ents.Sort(delegate(EntityBase a, EntityBase b)
680 {
681 return Vector3.Distance(AbsolutePosition, a.AbsolutePosition).CompareTo(Vector3.Distance(AbsolutePosition, b.AbsolutePosition));
682 });
683 }
684
685 foreach (EntityBase e in ents)
686 {
687 if (e is SceneObjectGroup)
688 m_pendingObjects.Enqueue((SceneObjectGroup)e);
689 }
690 }
691 }
692
693 while (m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < 60)
694 {
695 SceneObjectGroup g = m_pendingObjects.Dequeue();
696
697 // This is where we should check for draw distance
698 // do culling and stuff. Problem with that is that until
699 // we recheck in movement, that won't work right.
700 // So it's not implemented now.
701 //
702
703 // Don't even queue if we have sent this one
704 //
705 if (!m_updateTimes.ContainsKey(g.UUID))
706 g.ScheduleFullUpdateToAvatar(this);
707 }
708
709 int updateCount = 0;
710
711 while (m_partsUpdateQueue.Count > 0)
712 {
713 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
714
715 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
716 continue;
717
718 if (m_updateTimes.ContainsKey(part.UUID))
719 {
720 ScenePartUpdate update = m_updateTimes[part.UUID];
721
722 // We deal with the possibility that two updates occur at
723 // the same unix time at the update point itself.
724
725 if ((update.LastFullUpdateTime < part.TimeStampFull) ||
726 part.IsAttachment)
727 {
728// m_log.DebugFormat(
729// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
730// part.Name, part.UUID, part.TimeStampFull);
731
732 part.SendFullUpdate(ControllingClient,
733 GenerateClientFlags(part.UUID));
734
735 // We'll update to the part's timestamp rather than
736 // the current time to avoid the race condition
737 // whereby the next tick occurs while we are doing
738 // this update. If this happened, then subsequent
739 // updates which occurred on the same tick or the
740 // next tick of the last update would be ignored.
741
742 update.LastFullUpdateTime = part.TimeStampFull;
743
744 updateCount++;
745 }
746 else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
747 {
748// m_log.DebugFormat(
749// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
750// part.Name, part.UUID, part.TimeStampTerse);
751
752 part.SendTerseUpdateToClient(ControllingClient);
753
754 update.LastTerseUpdateTime = part.TimeStampTerse;
755 updateCount++;
756 }
757 }
758 else
759 {
760 //never been sent to client before so do full update
761 ScenePartUpdate update = new ScenePartUpdate();
762 update.FullID = part.UUID;
763 update.LastFullUpdateTime = part.TimeStampFull;
764 m_updateTimes.Add(part.UUID, update);
765
766 // Attachment handling
767 //
768 if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0)
769 {
770 if (part != part.ParentGroup.RootPart)
771 continue;
772
773 part.ParentGroup.SendFullUpdateToClient(ControllingClient);
774 continue;
775 }
776
777 part.SendFullUpdate(ControllingClient,
778 GenerateClientFlags(part.UUID));
779 updateCount++;
780 }
781
782 if (updateCount > 60)
783 break;
784 }
785
786 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
787 }
788
789 #region Status Methods
790
791 /// <summary>
792 /// This turns a child agent, into a root agent
793 /// This is called when an agent teleports into a region, or if an
794 /// agent crosses into this region from a neighbor over the border
795 /// </summary>
796 public void MakeRootAgent(Vector3 pos, bool isFlying)
797 {
798 m_log.DebugFormat(
799 "[SCENE]: Upgrading child to root agent for {0} in {1}",
800 Name, m_scene.RegionInfo.RegionName);
801
802 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
803
804 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
805 if (gm != null)
806 m_grouptitle = gm.GetGroupTitle(m_uuid);
807
808 m_scene.SetRootAgentScene(m_uuid);
809
810 // Moved this from SendInitialData to ensure that m_appearance is initialized
811 // before the inventory is processed in MakeRootAgent. This fixes a race condition
812 // related to the handling of attachments
813 m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
814
815 if (pos.X < 0 || pos.X > Constants.RegionSize || pos.Y < 0 || pos.Y > Constants.RegionSize || pos.Z < 0)
816 {
817 Vector3 emergencyPos = new Vector3(128, 128, 128);
818
819 m_log.WarnFormat(
820 "[SCENE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
821 pos, Name, UUID, emergencyPos);
822
823 pos = emergencyPos;
824 }
825
826 m_isChildAgent = false;
827
828 float localAVHeight = 1.56f;
829 if (m_avHeight != 127.0f)
830 {
831 localAVHeight = m_avHeight;
832 }
833
834 float posZLimit = (float)m_scene.GetLandHeight((int)pos.X, (int)pos.Y);
835 float newPosZ = posZLimit + localAVHeight / 2;
836 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
837 {
838 pos.Z = newPosZ;
839 }
840 AbsolutePosition = pos;
841
842 AddToPhysicalScene();
843 m_physicsActor.Flying = isFlying;
844
845 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
846 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
847 // elsewhere anyway
848 //SendAnimPack();
849
850 m_scene.SwapRootAgentCount(false);
851 m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(m_uuid);
852 m_scene.CapsModule.AddCapsHandler(m_uuid);
853
854 // On the next prim update, all objects will be sent
855 //
856 m_pendingObjects = null;
857
858 m_scene.EventManager.TriggerOnMakeRootAgent(this);
859 }
860
861 /// <summary>
862 /// This turns a root agent into a child agent
863 /// when an agent departs this region for a neighbor, this gets called.
864 ///
865 /// It doesn't get called for a teleport. Reason being, an agent that
866 /// teleports out may not end up anywhere near this region
867 /// </summary>
868 public void MakeChildAgent()
869 {
870 m_animations.Clear();
871
872// m_log.DebugFormat(
873// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
874// Name, UUID, m_scene.RegionInfo.RegionName);
875
876 // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
877 // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
878 //Velocity = new Vector3(0, 0, 0);
879
880 m_isChildAgent = true;
881 m_scene.SwapRootAgentCount(true);
882 RemoveFromPhysicalScene();
883 m_scene.EventManager.TriggerOnMakeChildAgent(this);
884 }
885
886 /// <summary>
887 /// Removes physics plugin scene representation of this agent if it exists.
888 /// </summary>
889 private void RemoveFromPhysicalScene()
890 {
891 if (PhysicsActor != null)
892 {
893 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
894 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
895 m_physicsActor.UnSubscribeEvents();
896 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
897 PhysicsActor = null;
898 }
899 }
900
901 /// <summary>
902 ///
903 /// </summary>
904 /// <param name="pos"></param>
905 public void Teleport(Vector3 pos)
906 {
907 RemoveFromPhysicalScene();
908 Velocity = new Vector3(0, 0, 0);
909 AbsolutePosition = pos;
910 AddToPhysicalScene();
911 SendTerseUpdateToAllClients();
912 }
913
914 /// <summary>
915 ///
916 /// </summary>
917 public void StopMovement()
918 {
919 }
920
921 public void StopFlying()
922 {
923 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
924 // and send a full object update.
925 // There's no message to send the client to tell it to stop flying
926
927 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
928 // when the avatar stands up
929
930 if (m_avHeight != 127.0f)
931 {
932 AbsolutePosition = AbsolutePosition + new Vector3(0, 0, (m_avHeight / 6f));
933 }
934 else
935 {
936 AbsolutePosition = AbsolutePosition + new Vector3(0, 0, (1.56f / 6f));
937 }
938 TrySetMovementAnimation("LAND");
939 SendFullUpdateToAllClients();
940 }
941
942 public void AddNeighbourRegion(ulong regionHandle, string cap)
943 {
944 lock (m_knownChildRegions)
945 {
946 if (!m_knownChildRegions.ContainsKey(regionHandle))
947 {
948 uint x, y;
949 Utils.LongToUInts(regionHandle, out x, out y);
950 m_knownChildRegions.Add(regionHandle, cap);
951 }
952 }
953 }
954
955 public void RemoveNeighbourRegion(ulong regionHandle)
956 {
957 lock (m_knownChildRegions)
958 {
959 if (m_knownChildRegions.ContainsKey(regionHandle))
960 {
961 m_knownChildRegions.Remove(regionHandle);
962 //Console.WriteLine(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
963 }
964 }
965 }
966
967 public void DropOldNeighbours(List<ulong> oldRegions)
968 {
969 foreach (ulong handle in oldRegions)
970 {
971 RemoveNeighbourRegion(handle);
972 Scene.CapsModule.DropChildSeed(UUID, handle);
973 }
974 }
975
976 public List<ulong> GetKnownRegionList()
977 {
978 return new List<ulong>(m_knownChildRegions.Keys);
979 }
980
981 #endregion
982
983 #region Event Handlers
984
985 /// <summary>
986 /// Sets avatar height in the phyiscs plugin
987 /// </summary>
988 internal void SetHeight(float height)
989 {
990 m_avHeight = height;
991 if (PhysicsActor != null)
992 {
993 PhysicsVector SetSize = new PhysicsVector(0.45f, 0.6f, m_avHeight);
994 PhysicsActor.Size = SetSize;
995 }
996 }
997
998 /// <summary>
999 /// Complete Avatar's movement into the region
1000 /// </summary>
1001 public void CompleteMovement()
1002 {
1003 Vector3 look = Velocity;
1004 if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
1005 {
1006 look = new Vector3(0.99f, 0.042f, 0);
1007 }
1008
1009 m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
1010
1011 if (m_isChildAgent)
1012 {
1013 m_isChildAgent = false;
1014
1015 MakeRootAgent(AbsolutePosition, false);
1016
1017 if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
1018 {
1019 m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
1020 Scene.SendReleaseAgent(m_rootRegionHandle, UUID, m_callbackURI);
1021 m_callbackURI = null;
1022 }
1023
1024 //m_log.DebugFormat("Completed movement");
1025 }
1026 }
1027
1028 /// <summary>
1029 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1030 /// </summary>
1031 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1032 {
1033 //if (m_isChildAgent)
1034 //{
1035 // // Console.WriteLine("DEBUG: HandleAgentUpdate: child agent");
1036 // return;
1037 //}
1038
1039 // Must check for standing up even when PhysicsActor is null,
1040 // since sitting currently removes avatar from physical scene
1041 //m_log.Debug("agentPos:" + AbsolutePosition.ToString());
1042
1043 // This is irritating. Really.
1044 if (!AbsolutePosition.IsFinite())
1045 {
1046 RemoveFromPhysicalScene();
1047 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999902");
1048
1049 m_pos = m_LastFinitePos;
1050 if (!m_pos.IsFinite())
1051 {
1052 m_pos.X = 127f;
1053 m_pos.Y = 127f;
1054 m_pos.Z = 127f;
1055 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999903");
1056 }
1057
1058 AddToPhysicalScene();
1059 }
1060 else
1061 {
1062 m_LastFinitePos = m_pos;
1063 }
1064 //m_physicsActor.AddForce(new PhysicsVector(999999999, 99999999, 999999999999999), true);
1065
1066
1067 //ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
1068 //if (land != null)
1069 //{
1070 //if (land.landData.landingType == (byte)1 && land.landData.userLocation != Vector3.Zero)
1071 //{
1072 // agent.startpos = land.landData.userLocation;
1073 //}
1074 //}
1075
1076 m_perfMonMS = System.Environment.TickCount;
1077
1078 uint flags = agentData.ControlFlags;
1079 Quaternion bodyRotation = agentData.BodyRotation;
1080
1081 // Camera location in world. We'll need to raytrace
1082 // from this location from time to time.
1083 m_CameraCenter = agentData.CameraCenter;
1084
1085 // Use these three vectors to figure out what the agent is looking at
1086 // Convert it to a Matrix and/or Quaternion
1087 m_CameraAtAxis = agentData.CameraAtAxis;
1088 m_CameraLeftAxis = agentData.CameraLeftAxis;
1089 m_CameraUpAxis = agentData.CameraUpAxis;
1090
1091 // The Agent's Draw distance setting
1092 m_DrawDistance = agentData.Far;
1093
1094 if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1095 {
1096 StandUp();
1097 }
1098 lock (scriptedcontrols)
1099 {
1100 if (scriptedcontrols.Count > 0)
1101 {
1102 SendControlToScripts(flags);
1103 flags = this.RemoveIgnoredControls(flags, IgnoredControls);
1104
1105 }
1106 }
1107
1108 if (PhysicsActor == null)
1109 {
1110 return;
1111 }
1112
1113 if (m_autopilotMoving)
1114 CheckAtSitTarget();
1115
1116 if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1117 {
1118 // TODO: This doesn't prevent the user from walking yet.
1119 // Setting parent ID would fix this, if we knew what value
1120 // to use. Or we could add a m_isSitting variable.
1121
1122 TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1123 }
1124 // In the future, these values might need to go global.
1125 // Here's where you get them.
1126
1127 m_AgentControlFlags = flags;
1128 m_headrotation = agentData.HeadRotation;
1129 m_state = agentData.State;
1130
1131 if (m_allowMovement)
1132 {
1133 int i = 0;
1134 bool update_movementflag = false;
1135 bool update_rotation = false;
1136 bool DCFlagKeyPressed = false;
1137 Vector3 agent_control_v3 = new Vector3(0, 0, 0);
1138 Quaternion q = bodyRotation;
1139 if (PhysicsActor != null)
1140 {
1141 bool oldflying = PhysicsActor.Flying;
1142
1143 PhysicsActor.Flying = ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1144
1145 if (PhysicsActor.Flying != oldflying)
1146 {
1147 update_movementflag = true;
1148 }
1149 }
1150
1151 if (q != m_bodyRot)
1152 {
1153 m_bodyRot = q;
1154 update_rotation = true;
1155 }
1156
1157 if (m_parentID == 0)
1158 {
1159 bool bAllowUpdateMoveToPosition = false;
1160 bool bResetMoveToPosition = false;
1161 foreach (Dir_ControlFlags DCF in Enum.GetValues(typeof (Dir_ControlFlags)))
1162 {
1163 if ((flags & (uint) DCF) != 0)
1164 {
1165 bResetMoveToPosition = true;
1166 DCFlagKeyPressed = true;
1167 try
1168 {
1169 agent_control_v3 += Dir_Vectors[i];
1170 }
1171 catch (IndexOutOfRangeException)
1172 {
1173 // Why did I get this?
1174 }
1175
1176 if ((m_movementflag & (uint) DCF) == 0)
1177 {
1178 m_movementflag += (byte) (uint) DCF;
1179 update_movementflag = true;
1180 }
1181 }
1182 else
1183 {
1184 if ((m_movementflag & (uint) DCF) != 0)
1185 {
1186 m_movementflag -= (byte) (uint) DCF;
1187 update_movementflag = true;
1188 }
1189 else
1190 {
1191 bAllowUpdateMoveToPosition = true;
1192 }
1193 }
1194 i++;
1195 }
1196
1197 //Paupaw:Do Proper PID for Autopilot here
1198 if (bResetMoveToPosition)
1199 {
1200 m_moveToPositionTarget = Vector3.Zero;
1201 m_moveToPositionInProgress = false;
1202 update_movementflag = true;
1203 bAllowUpdateMoveToPosition = false;
1204 }
1205
1206 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1207 {
1208 //Check the error term of the current position in relation to the target position
1209 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 1.5)
1210 {
1211 // we are close enough to the target
1212 m_moveToPositionTarget = Vector3.Zero;
1213 m_moveToPositionInProgress = false;
1214 update_movementflag = true;
1215 }
1216 else
1217 {
1218 try
1219 {
1220 // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
1221 // This movement vector gets added to the velocity through AddNewMovement().
1222 // Theoretically we might need a more complex PID approach here if other
1223 // unknown forces are acting on the avatar and we need to adaptively respond
1224 // to such forces, but the following simple approach seems to works fine.
1225 Vector3 LocalVectorToTarget3D =
1226 (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1227 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1228 // Ignore z component of vector
1229 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1230 LocalVectorToTarget2D.Normalize();
1231 agent_control_v3 += LocalVectorToTarget2D;
1232
1233 // update avatar movement flags. the avatar coordinate system is as follows:
1234 //
1235 // +X (forward)
1236 //
1237 // ^
1238 // |
1239 // |
1240 // |
1241 // |
1242 // (left) +Y <--------o--------> -Y
1243 // avatar
1244 // |
1245 // |
1246 // |
1247 // |
1248 // v
1249 // -X
1250 //
1251
1252 // based on the above avatar coordinate system, classify the movement into
1253 // one of left/right/back/forward.
1254 if (LocalVectorToTarget2D.Y > 0)//MoveLeft
1255 {
1256 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
1257 update_movementflag = true;
1258 }
1259 else if (LocalVectorToTarget2D.Y < 0) //MoveRight
1260 {
1261 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
1262 update_movementflag = true;
1263 }
1264 if (LocalVectorToTarget2D.X < 0) //MoveBack
1265 {
1266 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
1267 update_movementflag = true;
1268 }
1269 else if (LocalVectorToTarget2D.X > 0) //Move Forward
1270 {
1271 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
1272 update_movementflag = true;
1273 }
1274 }
1275 catch (Exception)
1276 {
1277
1278 //Avoid system crash, can be slower but...
1279 }
1280
1281 }
1282 }
1283 }
1284
1285 // Cause the avatar to stop flying if it's colliding
1286 // with something with the down arrow pressed.
1287
1288 // Only do this if we're flying
1289 if (m_physicsActor != null && m_physicsActor.Flying)
1290 {
1291 // Are the landing controls requirements filled?
1292 bool controlland = (((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1293 ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1294
1295 // Are the collision requirements fulfilled?
1296 bool colliding = (m_physicsActor.IsColliding == true);
1297
1298 if (m_physicsActor.Flying && colliding && controlland)
1299 {
1300 StopFlying();
1301 }
1302 }
1303
1304 if (update_movementflag || (update_rotation && DCFlagKeyPressed))
1305 {
1306// m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
1307// m_log.DebugFormat(
1308// "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1309
1310 AddNewMovement(agent_control_v3, q);
1311
1312 if (update_movementflag)
1313 UpdateMovementAnimations();
1314 }
1315 }
1316
1317 m_scene.EventManager.TriggerOnClientMovement(this);
1318
1319 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
1320 }
1321
1322 public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client)
1323 {
1324 m_autopilotMoving = true;
1325 m_autoPilotTarget = Pos;
1326 m_sitAtAutoTarget = false;
1327 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1328 //proxy.PCode = (byte)PCode.ParticleSystem;
1329
1330 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1331 proxyObjectGroup.AttachToScene(m_scene);
1332
1333 // Commented out this code since it could never have executed, but might still be informative.
1334// if (proxyObjectGroup != null)
1335// {
1336 proxyObjectGroup.SendGroupFullUpdate();
1337 remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
1338 m_scene.DeleteSceneObject(proxyObjectGroup, false);
1339// }
1340// else
1341// {
1342// m_autopilotMoving = false;
1343// m_autoPilotTarget = Vector3.Zero;
1344// ControllingClient.SendAlertMessage("Autopilot cancelled");
1345// }
1346 }
1347
1348 public void DoMoveToPosition(Object sender, string method, List<String> args)
1349 {
1350 try
1351 {
1352 float locx = 0f;
1353 float locy = 0f;
1354 float locz = 0f;
1355 uint regionX = 0;
1356 uint regionY = 0;
1357 try
1358 {
1359 Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
1360 locx = Convert.ToSingle(args[0]) - (float)regionX;
1361 locy = Convert.ToSingle(args[1]) - (float)regionY;
1362 locz = Convert.ToSingle(args[2]);
1363 }
1364 catch (InvalidCastException)
1365 {
1366 m_log.Error("[CLIENT]: Invalid autopilot request");
1367 return;
1368 }
1369 m_moveToPositionInProgress = true;
1370 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1371 }
1372 catch (Exception ex)
1373 {
1374 //Why did I get this error?
1375 Console.WriteLine("[SCENEPRESENCE]: DoMoveToPosition" + ex.ToString());
1376 }
1377 }
1378
1379 private void CheckAtSitTarget()
1380 {
1381 //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString());
1382 if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5)
1383 {
1384 if (m_sitAtAutoTarget)
1385 {
1386 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID);
1387 if (part != null)
1388 {
1389 AbsolutePosition = part.AbsolutePosition;
1390 Velocity = new Vector3(0, 0, 0);
1391 SendFullUpdateToAllClients();
1392
1393 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID);
1394 }
1395 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1396 m_requestedSitTargetUUID = UUID.Zero;
1397 }
1398 else
1399 {
1400 //ControllingClient.SendAlertMessage("Autopilot cancelled");
1401 //SendTerseUpdateToAllClients();
1402 //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1403 //proxy.PCode = (byte)PCode.ParticleSystem;
1404 ////uint nextUUID = m_scene.NextLocalId;
1405
1406 //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy);
1407 //if (proxyObjectGroup != null)
1408 //{
1409 //proxyObjectGroup.SendGroupFullUpdate();
1410 //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
1411 //m_scene.DeleteSceneObject(proxyObjectGroup);
1412 //}
1413 }
1414
1415 m_autoPilotTarget = Vector3.Zero;
1416 m_autopilotMoving = false;
1417 }
1418 }
1419 /// <summary>
1420 /// Perform the logic necessary to stand the client up. This method also executes
1421 /// the stand animation.
1422 /// </summary>
1423 public void StandUp()
1424 {
1425 if (m_parentID != 0)
1426 {
1427 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1428 if (part != null)
1429 {
1430 TaskInventoryDictionary taskIDict = part.TaskInventory;
1431 if (taskIDict != null)
1432 {
1433 lock (taskIDict)
1434 {
1435 foreach (UUID taskID in taskIDict.Keys)
1436 {
1437 UnRegisterControlEventsToScript(LocalId, taskID);
1438 taskIDict[taskID].PermsMask &= ~(
1439 2048 | //PERMISSION_CONTROL_CAMERA
1440 4); // PERMISSION_TAKE_CONTROLS
1441 }
1442 }
1443
1444 }
1445 // Reset sit target.
1446 if (part.GetAvatarOnSitTarget() == UUID)
1447 part.SetAvatarOnSitTarget(UUID.Zero);
1448
1449 m_parentPosition = part.GetWorldPosition();
1450 }
1451
1452 if (m_physicsActor == null)
1453 {
1454 AddToPhysicalScene();
1455 }
1456
1457 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
1458 m_parentPosition = new Vector3();
1459
1460 m_parentID = 0;
1461 SendFullUpdateToAllClients();
1462 m_requestedSitTargetID = 0;
1463 if (m_physicsActor != null)
1464 {
1465 SetHeight(m_avHeight);
1466 }
1467 }
1468
1469 TrySetMovementAnimation("STAND");
1470 }
1471
1472 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
1473 {
1474 SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
1475 if (targetPart == null)
1476 return null;
1477
1478 // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
1479 // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
1480
1481 // Get our own copy of the part array, and sort into the order we want to test
1482 SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
1483 Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
1484 {
1485 // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
1486 int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
1487 int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
1488 return linkNum1 - linkNum2;
1489 }
1490 );
1491
1492 //look for prims with explicit sit targets that are available
1493 foreach (SceneObjectPart part in partArray)
1494 {
1495 // Is a sit target available?
1496 Vector3 avSitOffSet = part.SitTargetPosition;
1497 Quaternion avSitOrientation = part.SitTargetOrientation;
1498 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1499
1500 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1501 bool SitTargetisSet =
1502 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1503 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1504
1505 if (SitTargetisSet && SitTargetUnOccupied)
1506 {
1507 //switch the target to this prim
1508 return part;
1509 }
1510 }
1511
1512 // no explicit sit target found - use original target
1513 return targetPart;
1514 }
1515
1516 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset)
1517 {
1518 bool autopilot = true;
1519 Vector3 pos = new Vector3();
1520 Quaternion sitOrientation = Quaternion.Identity;
1521 Vector3 cameraEyeOffset = Vector3.Zero;
1522 Vector3 cameraAtOffset = Vector3.Zero;
1523 bool forceMouselook = false;
1524
1525 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1526 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1527 if (part != null)
1528 {
1529 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1530 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1531
1532 // Is a sit target available?
1533 Vector3 avSitOffSet = part.SitTargetPosition;
1534 Quaternion avSitOrientation = part.SitTargetOrientation;
1535 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1536
1537 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1538 bool SitTargetisSet =
1539 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f &&
1540 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f));
1541
1542 if (SitTargetisSet && SitTargetUnOccupied)
1543 {
1544 part.SetAvatarOnSitTarget(UUID);
1545 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
1546 sitOrientation = avSitOrientation;
1547 autopilot = false;
1548 }
1549
1550 pos = part.AbsolutePosition + offset;
1551 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
1552 //{
1553 // offset = pos;
1554 //autopilot = false;
1555 //}
1556 if (m_physicsActor != null)
1557 {
1558 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1559 // We can remove the physicsActor until they stand up.
1560 m_sitAvatarHeight = m_physicsActor.Size.Z;
1561
1562 if (autopilot)
1563 {
1564 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5)
1565 {
1566 autopilot = false;
1567
1568 RemoveFromPhysicalScene();
1569 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1570 }
1571 }
1572 else
1573 {
1574 RemoveFromPhysicalScene();
1575 }
1576 }
1577
1578 cameraAtOffset = part.GetCameraAtOffset();
1579 cameraEyeOffset = part.GetCameraEyeOffset();
1580 forceMouselook = part.GetForceMouselook();
1581 }
1582
1583 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1584 m_requestedSitTargetUUID = targetID;
1585 // This calls HandleAgentSit twice, once from here, and the client calls
1586 // HandleAgentSit itself after it gets to the location
1587 // It doesn't get to the location until we've moved them there though
1588 // which happens in HandleAgentSit :P
1589 m_autopilotMoving = autopilot;
1590 m_autoPilotTarget = pos;
1591 m_sitAtAutoTarget = autopilot;
1592 if (!autopilot)
1593 HandleAgentSit(remoteClient, UUID);
1594 }
1595
1596 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
1597 {
1598 if (m_parentID != 0)
1599 {
1600 StandUp();
1601 }
1602 m_nextSitAnimation = "SIT";
1603
1604 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1605 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1606
1607 if (part != null)
1608 {
1609 if (!String.IsNullOrEmpty(part.SitAnimation))
1610 {
1611 m_nextSitAnimation = part.SitAnimation;
1612 }
1613 m_requestedSitTargetID = part.LocalId;
1614 m_requestedSitOffset = offset;
1615 }
1616 else
1617 {
1618
1619 m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
1620 }
1621 SendSitResponse(remoteClient, targetID, offset);
1622 }
1623
1624 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation)
1625 {
1626 if (m_parentID != 0)
1627 {
1628 StandUp();
1629 }
1630 if (!String.IsNullOrEmpty(sitAnimation))
1631 {
1632 m_nextSitAnimation = sitAnimation;
1633 }
1634 else
1635 {
1636 m_nextSitAnimation = "SIT";
1637 }
1638
1639 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1640 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1641 if (part != null)
1642 {
1643 m_requestedSitTargetID = part.LocalId;
1644 m_requestedSitOffset = offset;
1645 }
1646 else
1647 {
1648 m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
1649 }
1650 SendSitResponse(remoteClient, targetID, offset);
1651 }
1652
1653 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
1654 {
1655 if (!String.IsNullOrEmpty(m_nextSitAnimation))
1656 {
1657 HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
1658 }
1659 else
1660 {
1661 HandleAgentSit(remoteClient, agentID, "SIT");
1662 }
1663 }
1664
1665 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
1666 {
1667 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1668
1669 if (m_sitAtAutoTarget || !m_autopilotMoving)
1670 {
1671 if (part != null)
1672 {
1673 if (part.GetAvatarOnSitTarget() == UUID)
1674 {
1675 Vector3 sitTargetPos = part.SitTargetPosition;
1676 Quaternion sitTargetOrient = part.SitTargetOrientation;
1677
1678 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
1679 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
1680
1681 //Quaternion result = (sitTargetOrient * vq) * nq;
1682
1683 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
1684 m_pos += m_sitTargetCorrectionOffset;
1685 m_bodyRot = sitTargetOrient;
1686 //Rotation = sitTargetOrient;
1687 m_parentPosition = part.AbsolutePosition;
1688
1689 //SendTerseUpdateToAllClients();
1690 }
1691 else
1692 {
1693 m_pos -= part.AbsolutePosition;
1694 m_parentPosition = part.AbsolutePosition;
1695 }
1696 }
1697 else
1698 {
1699 return;
1700 }
1701 }
1702 m_parentID = m_requestedSitTargetID;
1703
1704 Velocity = new Vector3(0, 0, 0);
1705 RemoveFromPhysicalScene();
1706
1707 TrySetMovementAnimation(sitAnimation);
1708 SendFullUpdateToAllClients();
1709 // This may seem stupid, but Our Full updates don't send avatar rotation :P
1710 // So we're also sending a terse update (which has avatar rotation)
1711 // [Update] We do now.
1712 //SendTerseUpdateToAllClients();
1713 }
1714
1715 /// <summary>
1716 /// Event handler for the 'Always run' setting on the client
1717 /// Tells the physics plugin to increase speed of movement.
1718 /// </summary>
1719 public void HandleSetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun)
1720 {
1721 m_setAlwaysRun = SetAlwaysRun;
1722 if (PhysicsActor != null)
1723 {
1724 PhysicsActor.SetAlwaysRun = SetAlwaysRun;
1725 }
1726 }
1727
1728 public void AddAnimation(UUID animID)
1729 {
1730 if (m_isChildAgent)
1731 return;
1732
1733 if (m_animations.Add(animID, m_controllingClient.NextAnimationSequenceNumber))
1734 {
1735 SendAnimPack();
1736 }
1737 }
1738
1739 public void AddAnimation(string name)
1740 {
1741 if (m_isChildAgent)
1742 return;
1743
1744 UUID animID = m_controllingClient.GetDefaultAnimation(name);
1745 if (animID == UUID.Zero)
1746 return;
1747
1748 AddAnimation(animID);
1749 }
1750
1751 public void RemoveAnimation(UUID animID)
1752 {
1753 if (m_isChildAgent)
1754 return;
1755
1756 if (m_animations.Remove(animID))
1757 {
1758 SendAnimPack();
1759 }
1760 }
1761
1762 public void RemoveAnimation(string name)
1763 {
1764 if (m_isChildAgent)
1765 return;
1766
1767 UUID animID = m_controllingClient.GetDefaultAnimation(name);
1768 if (animID == UUID.Zero)
1769 return;
1770
1771 RemoveAnimation(animID);
1772 }
1773
1774 public UUID[] GetAnimationArray()
1775 {
1776 UUID[] animIDs;
1777 int[] sequenceNums;
1778 m_animations.GetArrays( out animIDs, out sequenceNums );
1779 return animIDs;
1780 }
1781
1782 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
1783 {
1784 AddAnimation(animID);
1785 }
1786
1787 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
1788 {
1789 RemoveAnimation(animID);
1790 }
1791
1792 /// <summary>
1793 /// The movement animation is reserved for "main" animations
1794 /// that are mutually exclusive, e.g. flying and sitting.
1795 /// </summary>
1796 protected void TrySetMovementAnimation(string anim)
1797 {
1798 //m_log.DebugFormat("Updating movement animation to {0}", anim);
1799
1800 if (m_animations.TrySetDefaultAnimation(anim, m_controllingClient.NextAnimationSequenceNumber))
1801 {
1802 SendAnimPack();
1803 }
1804 }
1805
1806 /// <summary>
1807 /// This method determines the proper movement related animation
1808 /// </summary>
1809 public string GetMovementAnimation()
1810 {
1811 if (m_movementflag != 0)
1812 {
1813 // We are moving
1814 if (PhysicsActor != null && PhysicsActor.Flying)
1815 {
1816 return "FLY";
1817 }
1818 else if (PhysicsActor != null && (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 &&
1819 PhysicsActor.IsColliding)
1820 {
1821 if ((m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 ||
1822 (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0)
1823 {
1824 return "CROUCHWALK";
1825 }
1826 else
1827 {
1828 return "CROUCH";
1829 }
1830 }
1831 else if (PhysicsActor != null && !PhysicsActor.IsColliding && PhysicsActor.Velocity.Z < -2)
1832 {
1833 return "FALLDOWN";
1834 }
1835 else if (PhysicsActor != null && !PhysicsActor.IsColliding && Velocity.Z > 1e-6 &&
1836 (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0)
1837 {
1838 return "JUMP";
1839 }
1840 else if (m_setAlwaysRun)
1841 {
1842 return "RUN";
1843 }
1844 else
1845 {
1846 return "WALK";
1847 }
1848 }
1849 else
1850 {
1851 // We are not moving
1852 if (PhysicsActor != null && !PhysicsActor.IsColliding && PhysicsActor.Velocity.Z < -2 && !PhysicsActor.Flying)
1853 {
1854 return "FALLDOWN";
1855 }
1856 else if (PhysicsActor != null && !PhysicsActor.IsColliding && Velocity.Z > 6 && !PhysicsActor.Flying)
1857 {
1858 // HACK: We check if Velocity.Z > 6 for this animation in order to avoid false positives during normal movement.
1859 // TODO: set this animation only when on the ground and UP_POS is received?
1860
1861 // This is the standing jump
1862 return "JUMP";
1863 }
1864 else if (PhysicsActor != null && PhysicsActor.Flying)
1865 {
1866 return "HOVER";
1867 }
1868 else
1869 {
1870 return "STAND";
1871 }
1872 }
1873 }
1874
1875 /// <summary>
1876 /// Update the movement animation of this avatar according to its current state
1877 /// </summary>
1878 protected void UpdateMovementAnimations()
1879 {
1880 string animation = GetMovementAnimation();
1881 TrySetMovementAnimation(animation);
1882 }
1883
1884 /// <summary>
1885 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
1886 /// </summary>
1887 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
1888 /// <param name="rotation">The direction in which this avatar should now face.
1889 public void AddNewMovement(Vector3 vec, Quaternion rotation)
1890 {
1891 if (m_isChildAgent)
1892 {
1893 Console.WriteLine("DEBUG: AddNewMovement: child agent");
1894 return;
1895 }
1896
1897 m_perfMonMS = System.Environment.TickCount;
1898
1899 m_rotation = rotation;
1900 NewForce newVelocity = new NewForce();
1901 Vector3 direc = vec * rotation;
1902 direc.Normalize();
1903
1904 direc *= 0.03f * 128f;
1905 if (m_physicsActor.Flying)
1906 {
1907 direc *= 4;
1908 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1909 //bool colliding = (m_physicsActor.IsColliding==true);
1910 //if (controlland)
1911 // m_log.Info("[AGENT]: landCommand");
1912 //if (colliding)
1913 // m_log.Info("[AGENT]: colliding");
1914 //if (m_physicsActor.Flying && colliding && controlland)
1915 //{
1916 // StopFlying();
1917 // m_log.Info("[AGENT]: Stop FLying");
1918 //}
1919 }
1920 else
1921 {
1922 if (!m_physicsActor.Flying && m_physicsActor.IsColliding)
1923 {
1924 if (direc.Z > 2.0f)
1925 {
1926 direc.Z *= 3;
1927
1928 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
1929 TrySetMovementAnimation("PREJUMP");
1930 TrySetMovementAnimation("JUMP");
1931 }
1932 }
1933 }
1934
1935 newVelocity.X = direc.X;
1936 newVelocity.Y = direc.Y;
1937 newVelocity.Z = direc.Z;
1938 m_forcesList.Add(newVelocity);
1939
1940 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
1941 }
1942
1943 #endregion
1944
1945 #region Overridden Methods
1946
1947 public override void Update()
1948 {
1949 SendPrimUpdates();
1950
1951 if (m_newCoarseLocations)
1952 {
1953 SendCoarseLocations();
1954 m_newCoarseLocations = false;
1955 }
1956
1957 if (m_isChildAgent == false)
1958 {
1959 if (m_newForce) // user movement 'forces' (ie commands to move)
1960 {
1961 SendTerseUpdateToAllClients();
1962 m_updateCount = 0;
1963 }
1964 else if (m_movementflag != 0) // scripted movement (?)
1965 {
1966 m_updateCount++;
1967 if (m_updateCount > 3)
1968 {
1969 SendTerseUpdateToAllClients();
1970 m_updateCount = 0;
1971 }
1972 }
1973 else if ((Util.GetDistanceTo(lastPhysPos, AbsolutePosition) > 0.02)
1974 || (Util.GetDistanceTo(m_lastVelocity, m_velocity) > 0.02)
1975 || lastPhysRot != m_bodyRot)
1976 {
1977 // Send Terse Update to all clients updates lastPhysPos and m_lastVelocity
1978 // doing the above assures us that we know what we sent the clients last
1979 SendTerseUpdateToAllClients();
1980 m_updateCount = 0;
1981 }
1982
1983 // followed suggestion from mic bowman. reversed the two lines below.
1984 CheckForBorderCrossing();
1985 CheckForSignificantMovement(); // sends update to the modules.
1986 }
1987 }
1988
1989 #endregion
1990
1991 #region Update Client(s)
1992
1993 /// <summary>
1994 /// Sends a location update to the client connected to this scenePresence
1995 /// </summary>
1996 /// <param name="remoteClient"></param>
1997 public void SendTerseUpdateToClient(IClientAPI remoteClient)
1998 {
1999 m_perfMonMS = System.Environment.TickCount;
2000
2001 Vector3 pos = m_pos;
2002 Vector3 vel = Velocity;
2003 Quaternion rot = m_bodyRot;
2004 pos.Z -= m_appearance.HipOffset;
2005 remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * (float)ushort.MaxValue), LocalId, new Vector3(pos.X, pos.Y, pos.Z),
2006 new Vector3(vel.X, vel.Y, vel.Z), rot);
2007
2008 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2009 m_scene.AddAgentUpdates(1);
2010 }
2011
2012 /// <summary>
2013 /// Send a location/velocity/accelleration update to all agents in scene
2014 /// </summary>
2015 public void SendTerseUpdateToAllClients()
2016 {
2017 m_perfMonMS = System.Environment.TickCount;
2018
2019 m_scene.Broadcast(SendTerseUpdateToClient);
2020
2021 m_lastVelocity = m_velocity;
2022 lastPhysPos = AbsolutePosition;
2023 lastPhysRot = m_bodyRot;
2024
2025 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2026
2027 }
2028
2029 public void SendCoarseLocations()
2030 {
2031 m_perfMonMS = System.Environment.TickCount;
2032
2033 List<Vector3> CoarseLocations = new List<Vector3>();
2034 List<ScenePresence> avatars = m_scene.GetAvatars();
2035 for (int i = 0; i < avatars.Count; i++)
2036 {
2037 if (avatars[i] != this)
2038 {
2039 if (avatars[i].ParentID != 0)
2040 {
2041 // sitting avatar
2042 SceneObjectPart sop = m_scene.GetSceneObjectPart(avatars[i].ParentID);
2043 if (sop != null)
2044 {
2045 CoarseLocations.Add(sop.AbsolutePosition + avatars[i].m_pos);
2046 }
2047 else
2048 {
2049 // we can't find the parent.. ! arg!
2050 CoarseLocations.Add(avatars[i].m_pos);
2051 }
2052 }
2053 else
2054 {
2055 CoarseLocations.Add(avatars[i].m_pos);
2056 }
2057 }
2058 }
2059
2060 m_controllingClient.SendCoarseLocationUpdate(CoarseLocations);
2061
2062 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2063 }
2064
2065 public void CoarseLocationChange()
2066 {
2067 m_newCoarseLocations = true;
2068 }
2069
2070 /// <summary>
2071 /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar)
2072 /// </summary>
2073 /// <param name="remoteAvatar"></param>
2074 public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
2075 {
2076 // 2 stage check is needed.
2077 if (remoteAvatar == null)
2078 return;
2079 IClientAPI cl=remoteAvatar.ControllingClient;
2080 if (cl == null)
2081 return;
2082 if (m_appearance.Texture == null)
2083 return;
2084
2085 // Note: because Quaternion is a struct, it can't be null
2086 Quaternion rot = m_bodyRot;
2087
2088 Vector3 pos = m_pos;
2089 pos.Z -= m_appearance.HipOffset;
2090
2091 remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid,
2092 LocalId, m_pos, m_appearance.Texture.ToBytes(),
2093 m_parentID, rot);
2094 m_scene.AddAgentUpdates(1);
2095 }
2096
2097 /// <summary>
2098 /// Tell *ALL* agents about this agent
2099 /// </summary>
2100 public void SendInitialFullUpdateToAllClients()
2101 {
2102 m_perfMonMS = System.Environment.TickCount;
2103
2104 List<ScenePresence> avatars = m_scene.GetScenePresences();
2105 foreach (ScenePresence avatar in avatars)
2106 {
2107 // only send if this is the root (children are only "listening posts" in a foreign region)
2108 if (!IsChildAgent)
2109 {
2110 SendFullUpdateToOtherClient(avatar);
2111 }
2112
2113 if (avatar.LocalId != LocalId)
2114 {
2115 if (!avatar.IsChildAgent)
2116 {
2117 avatar.SendFullUpdateToOtherClient(this);
2118 avatar.SendAppearanceToOtherAgent(this);
2119 avatar.SendAnimPackToClient(this.ControllingClient);
2120 }
2121 }
2122 }
2123 m_scene.AddAgentUpdates(avatars.Count);
2124 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2125 }
2126
2127 public void SendFullUpdateToAllClients()
2128 {
2129 m_perfMonMS = System.Environment.TickCount;
2130
2131 // only send update from root agents to other clients; children are only "listening posts"
2132 List<ScenePresence> avatars = m_scene.GetAvatars();
2133 foreach (ScenePresence avatar in avatars)
2134 {
2135 SendFullUpdateToOtherClient(avatar);
2136
2137 }
2138 m_scene.AddAgentUpdates(avatars.Count);
2139 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2140
2141 SendAnimPack();
2142 }
2143
2144 /// <summary>
2145 /// Do everything required once a client completes its movement into a region
2146 /// </summary>
2147 public void SendInitialData()
2148 {
2149 // Moved this into CompleteMovement to ensure that m_appearance is initialized before
2150 // the inventory arrives
2151 // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
2152
2153 // Note: because Quaternion is a struct, it can't be null
2154 Quaternion rot = m_bodyRot;
2155
2156 Vector3 pos = m_pos;
2157 pos.Z -= m_appearance.HipOffset;
2158
2159 m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
2160 m_pos, m_appearance.Texture.ToBytes(), m_parentID, rot);
2161
2162 if (!m_isChildAgent)
2163 {
2164 m_scene.InformClientOfNeighbours(this);
2165 }
2166
2167 SendInitialFullUpdateToAllClients();
2168 SendAppearanceToAllOtherAgents();
2169 }
2170
2171 /// <summary>
2172 /// Tell the client for this scene presence what items it should be wearing now
2173 /// </summary>
2174 /// <param name="client"></param>
2175 public void SendWearables()
2176 {
2177 ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
2178 }
2179
2180 /// <summary>
2181 ///
2182 /// </summary>
2183 public void SendAppearanceToAllOtherAgents()
2184 {
2185 m_perfMonMS = System.Environment.TickCount;
2186
2187 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
2188 {
2189 if (scenePresence.UUID != UUID)
2190 {
2191 SendAppearanceToOtherAgent(scenePresence);
2192 }
2193 });
2194
2195 m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
2196 }
2197
2198 /// <summary>
2199 /// Send appearance data to an agent that isn't this one.
2200 /// </summary>
2201 /// <param name="avatar"></param>
2202 public void SendAppearanceToOtherAgent(ScenePresence avatar)
2203 {
2204 avatar.ControllingClient.SendAppearance(
2205 m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.ToBytes());
2206 }
2207
2208 /// <summary>
2209 /// Set appearance data (textureentry and slider settings) received from the client
2210 /// </summary>
2211 /// <param name="texture"></param>
2212 /// <param name="visualParam"></param>
2213 public void SetAppearance(byte[] texture, List<byte> visualParam)
2214 {
2215 if (m_physicsActor != null)
2216 {
2217 // This may seem like it's redundant, remove the avatar from the physics scene
2218 // just to add it back again, but it saves us from having to update
2219 // 3 variables 10 times a second.
2220 m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
2221 AddToPhysicalScene();
2222 }
2223 m_appearance.SetAppearance(texture, visualParam);
2224 SetHeight(m_appearance.AvatarHeight);
2225 m_scene.CommsManager.AvatarService.UpdateUserAppearance(m_controllingClient.AgentId, m_appearance);
2226
2227 SendAppearanceToAllOtherAgents();
2228 //SendWearables();
2229 if (!m_startAnimationSet)
2230 {
2231 UpdateMovementAnimations();
2232 m_startAnimationSet = true;
2233 }
2234 }
2235
2236 public void SetWearable(int wearableId, AvatarWearable wearable)
2237 {
2238 m_appearance.SetWearable(wearableId, wearable);
2239 m_scene.CommsManager.AvatarService.UpdateUserAppearance(m_controllingClient.AgentId, m_appearance);
2240 m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
2241 }
2242
2243 // Because appearance setting is in a module, we actually need
2244 // to give it access to our appearance directly, otherwise we
2245 // get a synchronization issue.
2246 public AvatarAppearance Appearance
2247 {
2248 get { return m_appearance; }
2249 set { m_appearance = value; }
2250 }
2251
2252 /// <summary>
2253 ///
2254 /// </summary>
2255 /// <param name="animations"></param>
2256 /// <param name="seqs"></param>
2257 public void SendAnimPack(UUID[] animations, int[] seqs)
2258 {
2259 if (m_isChildAgent)
2260 return;
2261
2262 m_scene.Broadcast(
2263 delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId); });
2264 }
2265
2266 public void SendAnimPackToClient(IClientAPI client)
2267 {
2268 if (m_isChildAgent)
2269 return;
2270 UUID[] animIDs;
2271 int[] sequenceNums;
2272
2273 m_animations.GetArrays(out animIDs, out sequenceNums);
2274
2275 client.SendAnimations(animIDs, sequenceNums, m_controllingClient.AgentId);
2276 }
2277
2278 /// <summary>
2279 /// Send animation information about this avatar to all clients.
2280 /// </summary>
2281 public void SendAnimPack()
2282 {
2283 //m_log.Debug("Sending animation pack");
2284
2285 if (m_isChildAgent)
2286 return;
2287
2288 UUID[] animIDs;
2289 int[] sequenceNums;
2290
2291 m_animations.GetArrays(out animIDs, out sequenceNums);
2292
2293 SendAnimPack(animIDs, sequenceNums);
2294 }
2295
2296 #endregion
2297
2298 #region Significant Movement Method
2299
2300 /// <summary>
2301 /// This checks for a significant movement and sends a courselocationchange update
2302 /// </summary>
2303 protected void CheckForSignificantMovement()
2304 {
2305 if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > 0.5)
2306 {
2307 posLastSignificantMove = AbsolutePosition;
2308 m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient);
2309 m_scene.NotifyMyCoarseLocationChange();
2310 }
2311
2312 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
2313 if (Util.GetDistanceTo(AbsolutePosition,m_LastChildAgentUpdatePosition) > 32)
2314 {
2315 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
2316 cadu.ActiveGroupID = UUID.Zero.Guid;
2317 cadu.AgentID = UUID.Guid;
2318 cadu.alwaysrun = m_setAlwaysRun;
2319 cadu.AVHeight = m_avHeight;
2320 sLLVector3 tempCameraCenter = new sLLVector3(new Vector3(m_CameraCenter.X, m_CameraCenter.Y, m_CameraCenter.Z));
2321 cadu.cameraPosition = tempCameraCenter;
2322 cadu.drawdistance = m_DrawDistance;
2323 if (m_scene.Permissions.IsGod(new UUID(cadu.AgentID)))
2324 cadu.godlevel = m_godlevel;
2325 cadu.GroupAccess = 0;
2326 cadu.Position = new sLLVector3(AbsolutePosition);
2327 cadu.regionHandle = m_scene.RegionInfo.RegionHandle;
2328 float multiplier = 1;
2329 int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
2330 if (innacurateNeighbors != 0)
2331 {
2332 multiplier = 1f / (float)innacurateNeighbors;
2333 }
2334 if (multiplier <= 0f)
2335 {
2336 multiplier = 0.25f;
2337 }
2338
2339 //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
2340 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
2341 cadu.Velocity = new sLLVector3(Velocity);
2342
2343 AgentPosition agentpos = new AgentPosition();
2344 agentpos.CopyFrom(cadu);
2345
2346 m_scene.SendOutChildAgentUpdates(agentpos, this);
2347
2348 m_LastChildAgentUpdatePosition.X = AbsolutePosition.X;
2349 m_LastChildAgentUpdatePosition.Y = AbsolutePosition.Y;
2350 m_LastChildAgentUpdatePosition.Z = AbsolutePosition.Z;
2351 }
2352 }
2353
2354 #endregion
2355
2356 #region Border Crossing Methods
2357
2358 /// <summary>
2359 /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion
2360 /// </summary>
2361 protected void CheckForBorderCrossing()
2362 {
2363 if (IsChildAgent)
2364 return;
2365
2366 Vector3 pos2 = AbsolutePosition;
2367 Vector3 vel = Velocity;
2368
2369 float timeStep = 0.1f;
2370 pos2.X = pos2.X + (vel.X*timeStep);
2371 pos2.Y = pos2.Y + (vel.Y*timeStep);
2372 pos2.Z = pos2.Z + (vel.Z*timeStep);
2373
2374 if ((pos2.X < 0) || (pos2.X > Constants.RegionSize))
2375 {
2376 CrossToNewRegion();
2377 }
2378
2379 if ((pos2.Y < 0) || (pos2.Y > Constants.RegionSize))
2380 {
2381 CrossToNewRegion();
2382 }
2383 }
2384
2385 /// <summary>
2386 /// Moves the agent outside the region bounds
2387 /// Tells neighbor region that we're crossing to it
2388 /// If the neighbor accepts, remove the agent's viewable avatar from this scene
2389 /// set them to a child agent.
2390 /// </summary>
2391 protected void CrossToNewRegion()
2392 {
2393 Vector3 pos = AbsolutePosition;
2394 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
2395 uint neighbourx = m_regionInfo.RegionLocX;
2396 uint neighboury = m_regionInfo.RegionLocY;
2397
2398 // distance to edge that will trigger crossing
2399 const float boundaryDistance = 1.7f;
2400
2401 // distance into new region to place avatar
2402 const float enterDistance = 0.1f;
2403
2404 if (pos.X < boundaryDistance)
2405 {
2406 neighbourx--;
2407 newpos.X = Constants.RegionSize - enterDistance;
2408 }
2409 else if (pos.X > Constants.RegionSize - boundaryDistance)
2410 {
2411 neighbourx++;
2412 newpos.X = enterDistance;
2413 }
2414
2415 if (pos.Y < boundaryDistance)
2416 {
2417 neighboury--;
2418 newpos.Y = Constants.RegionSize - enterDistance;
2419 }
2420 else if (pos.Y > Constants.RegionSize - boundaryDistance)
2421 {
2422 neighboury++;
2423 newpos.Y = enterDistance;
2424 }
2425
2426 Vector3 vel = m_velocity;
2427 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
2428 SimpleRegionInfo neighbourRegion = m_scene.RequestNeighbouringRegionInfo(neighbourHandle);
2429 if (neighbourRegion != null && ValidateAttachments())
2430 {
2431 // When the neighbour is informed of the border crossing, it will set up CAPS handlers for the avatar
2432 // This means we need to remove the current caps handler here and possibly compensate later,
2433 // in case both scenes are being hosted on the same region server. Messy
2434 //m_scene.RemoveCapsHandler(UUID);
2435 newpos = newpos + (vel);
2436
2437 CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(UUID);
2438 if (userInfo != null)
2439 {
2440 userInfo.DropInventory();
2441 }
2442 else
2443 {
2444 m_log.WarnFormat("[SCENE PRESENCE]: No cached user info found for {0} {1} on leaving region", Name, UUID);
2445 }
2446
2447 bool crossingSuccessful =
2448 m_scene.InformNeighbourOfCrossing(neighbourHandle, m_controllingClient.AgentId, newpos,
2449 m_physicsActor.Flying);
2450 if (crossingSuccessful)
2451 {
2452 // Next, let's close the child agent connections that are too far away.
2453 CloseChildAgents(neighbourx, neighboury);
2454
2455 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
2456 m_controllingClient.RequestClientInfo();
2457
2458 //Console.WriteLine("BEFORE CROSS");
2459 //Scene.DumpChildrenSeeds(UUID);
2460 //DumpKnownRegions();
2461 string agentcaps;
2462 if (!m_knownChildRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
2463 {
2464 m_log.ErrorFormat("[SCENE PRESENCE]: No CAPS information for region handle {0}, exiting CrossToNewRegion.",
2465 neighbourRegion.RegionHandle);
2466 return;
2467 }
2468 // TODO Should construct this behind a method
2469 string capsPath =
2470 "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
2471 + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
2472
2473 m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, m_uuid);
2474
2475 IEventQueue eq = m_scene.RequestModuleInterface<IEventQueue>();
2476 if (eq != null)
2477 {
2478 OSD Item = EventQueueHelper.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint,
2479 capsPath, UUID, ControllingClient.SessionId);
2480 eq.Enqueue(Item, UUID);
2481 }
2482 else
2483 {
2484 m_controllingClient.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint,
2485 capsPath);
2486 }
2487
2488 MakeChildAgent();
2489 // now we have a child agent in this region. Request all interesting data about other (root) agents
2490 SendInitialFullUpdateToAllClients();
2491
2492 CrossAttachmentsIntoNewRegion(neighbourHandle, true);
2493
2494 // m_scene.SendKillObject(m_localId);
2495
2496 m_scene.NotifyMyCoarseLocationChange();
2497 // the user may change their profile information in other region,
2498 // so the userinfo in UserProfileCache is not reliable any more, delete it
2499 if (m_scene.NeedSceneCacheClear(UUID))
2500 {
2501 m_scene.CommsManager.UserProfileCacheService.RemoveUser(UUID);
2502 m_log.DebugFormat(
2503 "[SCENE PRESENCE]: User {0} is going to another region, profile cache removed", UUID);
2504 }
2505 }
2506 else
2507 {
2508 // Restore the user structures that we needed to delete before asking the receiving region to complete the crossing
2509 m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(UUID);
2510 m_scene.CapsModule.AddCapsHandler(UUID);
2511 }
2512 }
2513
2514 //Console.WriteLine("AFTER CROSS");
2515 //Scene.DumpChildrenSeeds(UUID);
2516 //DumpKnownRegions();
2517 }
2518
2519 /// <summary>
2520 /// Computes which child agents to close when the scene presence moves to another region.
2521 /// Removes those regions from m_knownRegions.
2522 /// </summary>
2523 /// <param name="newRegionX">The new region's x on the map</param>
2524 /// <param name="newRegionY">The new region's y on the map</param>
2525 /// <returns></returns>
2526 public void CloseChildAgents(uint newRegionX, uint newRegionY)
2527 {
2528 List<ulong> byebyeRegions = new List<ulong>();
2529 m_log.DebugFormat(
2530 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
2531 m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName);
2532 //DumpKnownRegions();
2533
2534 lock (m_knownChildRegions)
2535 {
2536 foreach (ulong handle in m_knownChildRegions.Keys)
2537 {
2538 // Don't close the agent on this region yet
2539 if (handle != Scene.RegionInfo.RegionHandle)
2540 {
2541 uint x, y;
2542 Utils.LongToUInts(handle, out x, out y);
2543 x = x / Constants.RegionSize;
2544 y = y / Constants.RegionSize;
2545
2546 //Console.WriteLine("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
2547 //Console.WriteLine("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
2548 if (Util.IsOutsideView(x, newRegionX, y, newRegionY))
2549 {
2550 byebyeRegions.Add(handle);
2551 }
2552 }
2553 }
2554 }
2555
2556 if (byebyeRegions.Count > 0)
2557 {
2558 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
2559 m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions);
2560 }
2561
2562 foreach (ulong handle in byebyeRegions)
2563 {
2564 RemoveNeighbourRegion(handle);
2565 }
2566
2567 }
2568
2569 #endregion
2570
2571 /// <summary>
2572 /// This allows the Sim owner the abiility to kick users from their sim currently.
2573 /// It tells the client that the agent has permission to do so.
2574 /// </summary>
2575 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
2576 {
2577 if (godStatus)
2578 {
2579 // For now, assign god level 200 to anyone
2580 // who is granted god powers, but has no god level set.
2581 //
2582 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
2583 if (profile.UserProfile.GodLevel > 0)
2584 m_godlevel = profile.UserProfile.GodLevel;
2585 else
2586 m_godlevel = 200;
2587 }
2588 else
2589 {
2590 m_godlevel = 0;
2591 }
2592
2593 ControllingClient.SendAdminResponse(token, (uint)m_godlevel);
2594 }
2595
2596 #region Child Agent Updates
2597
2598 public void ChildAgentDataUpdate(AgentData cAgentData)
2599 {
2600 //Console.WriteLine(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
2601 if (!IsChildAgent)
2602 return;
2603
2604 CopyFrom(cAgentData);
2605 }
2606
2607 /// <summary>
2608 /// This updates important decision making data about a child agent
2609 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
2610 /// </summary>
2611 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
2612 {
2613 if (!IsChildAgent)
2614 return;
2615
2616 //Console.WriteLine(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
2617 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
2618 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
2619
2620 m_DrawDistance = cAgentData.Far;
2621 if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!!
2622 m_pos = new Vector3(cAgentData.Position.X + shiftx, cAgentData.Position.Y + shifty, cAgentData.Position.Z);
2623
2624 // It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region
2625 m_CameraCenter = cAgentData.Center;
2626
2627 m_avHeight = cAgentData.Size.Z;
2628 //SetHeight(cAgentData.AVHeight);
2629
2630 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
2631 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
2632
2633 // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
2634 if (m_scene.m_seeIntoRegionFromNeighbor)
2635 m_pendingObjects = null;
2636
2637 //cAgentData.AVHeight;
2638 //cAgentData.regionHandle;
2639 //m_velocity = cAgentData.Velocity;
2640 }
2641
2642 public void CopyTo(AgentData cAgent)
2643 {
2644 cAgent.AgentID = UUID;
2645 cAgent.RegionHandle = m_scene.RegionInfo.RegionHandle;
2646
2647 cAgent.Position = m_pos;
2648 cAgent.Velocity = m_velocity;
2649 cAgent.Center = m_CameraCenter;
2650 cAgent.Size = new Vector3(0, 0, m_avHeight);
2651 cAgent.AtAxis = m_CameraAtAxis;
2652 cAgent.LeftAxis = m_CameraLeftAxis;
2653 cAgent.UpAxis = m_CameraUpAxis;
2654
2655 cAgent.Far = m_DrawDistance;
2656
2657 // Throttles
2658 float multiplier = 1;
2659 int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
2660 if (innacurateNeighbors != 0)
2661 {
2662 multiplier = 1f / (float)innacurateNeighbors;
2663 }
2664 if (multiplier <= 0f)
2665 {
2666 multiplier = 0.25f;
2667 }
2668 //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
2669 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
2670
2671 cAgent.HeadRotation = m_headrotation;
2672 cAgent.BodyRotation = m_bodyRot;
2673 cAgent.ControlFlags = m_AgentControlFlags;
2674 if ((m_physicsActor != null) && (m_physicsActor.Flying))
2675 {
2676 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
2677 }
2678
2679 if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
2680 cAgent.GodLevel = (byte)m_godlevel;
2681 else
2682 cAgent.GodLevel = (byte) 0;
2683
2684 cAgent.AlwaysRun = m_setAlwaysRun;
2685
2686 //cAgent.AgentTextures = ???
2687 //cAgent.GroupID = ??
2688 // Groups???
2689
2690 // Animations???
2691
2692 cAgent.VisualParams = m_appearance.VisualParams;
2693 }
2694
2695 public void CopyFrom(AgentData cAgent)
2696 {
2697 m_rootRegionHandle= cAgent.RegionHandle;
2698 m_callbackURI = cAgent.CallbackURI;
2699
2700 m_pos = cAgent.Position;
2701 m_velocity = cAgent.Velocity;
2702 m_CameraCenter = cAgent.Center;
2703 m_avHeight = cAgent.Size.Z;
2704 m_CameraAtAxis = cAgent.AtAxis;
2705 m_CameraLeftAxis = cAgent.LeftAxis;
2706 m_CameraUpAxis = cAgent.UpAxis;
2707
2708 m_DrawDistance = cAgent.Far;
2709
2710 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
2711 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
2712
2713 m_headrotation = cAgent.HeadRotation;
2714 m_bodyRot = cAgent.BodyRotation;
2715 m_AgentControlFlags = cAgent.ControlFlags; // We need more flags!
2716 if (m_physicsActor != null)
2717 {
2718 m_physicsActor.Flying = ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
2719 }
2720 if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
2721 m_godlevel = cAgent.GodLevel;
2722 m_setAlwaysRun = cAgent.AlwaysRun;
2723
2724 //cAgent.AgentTextures = ???
2725
2726 //cAgent.GroupID = ??
2727 //Groups???
2728
2729 // Animations???
2730
2731 m_appearance.VisualParams = cAgent.VisualParams;
2732 }
2733
2734 #endregion Child Agent Updates
2735
2736 /// <summary>
2737 /// Handles part of the PID controller function for moving an avatar.
2738 /// </summary>
2739 public override void UpdateMovement()
2740 {
2741 m_newForce = false;
2742 lock (m_forcesList)
2743 {
2744 if (m_forcesList.Count > 0)
2745 {
2746 for (int i = 0; i < m_forcesList.Count; i++)
2747 {
2748 NewForce force = m_forcesList[i];
2749
2750 m_updateflag = true;
2751 try
2752 {
2753 movementvector.X = force.X;
2754 movementvector.Y = force.Y;
2755 movementvector.Z = force.Z;
2756 Velocity = movementvector;
2757 }
2758 catch (NullReferenceException)
2759 {
2760 // Under extreme load, this returns a NullReference Exception that we can ignore.
2761 // Ignoring this causes no movement to be sent to the physics engine...
2762 // which when the scene is moving at 1 frame every 10 seconds, it doesn't really matter!
2763 }
2764 m_newForce = true;
2765 }
2766 for (int i = 0; i < m_forcesList.Count; i++)
2767 {
2768 m_forcesList.RemoveAt(0);
2769 }
2770 }
2771 }
2772 }
2773
2774 static ScenePresence()
2775 {
2776 Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture();
2777 DefaultTexture = textu.ToBytes();
2778 }
2779
2780 [Serializable]
2781 public class NewForce
2782 {
2783 public float X;
2784 public float Y;
2785 public float Z;
2786
2787 public NewForce()
2788 {
2789 }
2790 }
2791
2792 [Serializable]
2793 public class ScenePartUpdate : ISerializable
2794 {
2795 public UUID FullID;
2796 public uint LastFullUpdateTime;
2797 public uint LastTerseUpdateTime;
2798
2799 public ScenePartUpdate()
2800 {
2801 FullID = UUID.Zero;
2802 LastFullUpdateTime = 0;
2803 LastTerseUpdateTime = 0;
2804 }
2805
2806 protected ScenePartUpdate(SerializationInfo info, StreamingContext context)
2807 {
2808 //System.Console.WriteLine("ScenePartUpdate Deserialize BGN");
2809
2810 if (info == null)
2811 {
2812 throw new ArgumentNullException("info");
2813 }
2814
2815 FullID = new UUID((Guid)info.GetValue("FullID", typeof(Guid)));
2816 LastFullUpdateTime = (uint)info.GetValue("LastFullUpdateTime", typeof(uint));
2817 LastTerseUpdateTime = (uint)info.GetValue("LastTerseUpdateTime", typeof(uint));
2818
2819 //System.Console.WriteLine("ScenePartUpdate Deserialize END");
2820 }
2821
2822 [SecurityPermission(SecurityAction.LinkDemand,
2823 Flags = SecurityPermissionFlag.SerializationFormatter)]
2824 public virtual void GetObjectData(
2825 SerializationInfo info, StreamingContext context)
2826 {
2827 if (info == null)
2828 {
2829 throw new ArgumentNullException("info");
2830 }
2831
2832 info.AddValue("FullID", FullID.Guid);
2833 info.AddValue("LastFullUpdateTime", LastFullUpdateTime);
2834 info.AddValue("LastTerseUpdateTime", LastTerseUpdateTime);
2835 }
2836 }
2837
2838 public override void SetText(string text, Vector3 color, double alpha)
2839 {
2840 throw new Exception("Can't set Text on avatar.");
2841 }
2842
2843 /// <summary>
2844 /// Adds a physical representation of the avatar to the Physics plugin
2845 /// </summary>
2846 public void AddToPhysicalScene()
2847 {
2848 PhysicsScene scene = m_scene.PhysicsScene;
2849
2850 PhysicsVector pVec =
2851 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y,
2852 AbsolutePosition.Z);
2853
2854 if (m_avHeight == 127.0f)
2855 {
2856 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new PhysicsVector(0, 0, 1.56f));
2857 }
2858 else
2859 {
2860 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new PhysicsVector(0, 0, m_avHeight));
2861 }
2862
2863 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
2864 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
2865 m_physicsActor.SubscribeEvents(1000);
2866 m_physicsActor.LocalID = LocalId;
2867 }
2868
2869 // Event called by the physics plugin to tell the avatar about a collision.
2870 private void PhysicsCollisionUpdate(EventArgs e)
2871 {
2872 if (e == null)
2873 return;
2874 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
2875 Dictionary<uint, float> coldata = collisionData.m_objCollisionList;
2876 float starthealth = Health;
2877 uint killerObj = 0;
2878 foreach (uint localid in coldata.Keys)
2879 {
2880 if (coldata[localid] <= 0.10f || m_invulnerable)
2881 continue;
2882 //if (localid == 0)
2883 //continue;
2884
2885 Health -= coldata[localid] * 5;
2886
2887 if (Health <= 0)
2888 {
2889 if (localid != 0)
2890 killerObj = localid;
2891 }
2892 //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
2893 }
2894 //Health = 100;
2895 if (!m_invulnerable)
2896 {
2897 if (starthealth != Health)
2898 {
2899 ControllingClient.SendHealth(Health);
2900 }
2901 if (m_health <= 0)
2902 m_scene.EventManager.TriggerAvatarKill(killerObj, this);
2903 }
2904
2905 if (Velocity.X > 0 || Velocity.Y > 0)
2906 UpdateMovementAnimations();
2907 }
2908
2909 public void setHealthWithUpdate(float health)
2910 {
2911 Health = health;
2912 ControllingClient.SendHealth(Health);
2913 }
2914
2915 public void Close()
2916 {
2917 lock (m_attachments)
2918 {
2919 // Delete attachments from scene
2920 // Don't try to save, as this thread won't live long
2921 // enough to complete the save. This would cause no copy
2922 // attachments to poof!
2923 //
2924 foreach (SceneObjectGroup grp in m_attachments)
2925 {
2926 m_scene.DeleteSceneObject(grp, false);
2927 }
2928 m_attachments.Clear();
2929 }
2930 lock (m_knownChildRegions)
2931 {
2932 m_knownChildRegions.Clear();
2933 }
2934 lock (m_updateTimes)
2935 {
2936 m_updateTimes.Clear();
2937 }
2938 lock (m_partsUpdateQueue)
2939 {
2940 m_partsUpdateQueue.Clear();
2941 }
2942
2943 RemoveFromPhysicalScene();
2944 GC.Collect();
2945 }
2946
2947 public ScenePresence()
2948 {
2949/* JB
2950 if (Animations == null)
2951 {
2952 Animations = new AvatarAnimations();
2953 Animations.LoadAnims();
2954 }
2955*/
2956 if (DefaultTexture == null)
2957 {
2958 Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture();
2959 DefaultTexture = textu.ToBytes();
2960 }
2961 }
2962
2963 public void AddAttachment(SceneObjectGroup gobj)
2964 {
2965 lock (m_attachments)
2966 {
2967 m_attachments.Add(gobj);
2968 }
2969 }
2970
2971 public bool HasAttachments()
2972 {
2973 return m_attachments.Count > 0;
2974 }
2975
2976 public bool HasScriptedAttachments()
2977 {
2978 lock (m_attachments)
2979 {
2980 foreach (SceneObjectGroup gobj in m_attachments)
2981 {
2982 if (gobj != null)
2983 {
2984 if (gobj.RootPart.Inventory.ContainsScripts())
2985 return true;
2986 }
2987 }
2988 }
2989 return false;
2990 }
2991
2992 public void RemoveAttachment(SceneObjectGroup gobj)
2993 {
2994 lock (m_attachments)
2995 {
2996 if (m_attachments.Contains(gobj))
2997 {
2998 m_attachments.Remove(gobj);
2999 }
3000 }
3001 }
3002
3003 public bool ValidateAttachments()
3004 {
3005 lock (m_attachments)
3006 {
3007 // Validate
3008 foreach (SceneObjectGroup gobj in m_attachments)
3009 {
3010 if (gobj == null)
3011 return false;
3012
3013 if (gobj.IsDeleted)
3014 return false;
3015 }
3016 }
3017 return true;
3018 }
3019
3020 public bool CrossAttachmentsIntoNewRegion(ulong regionHandle, bool silent)
3021 {
3022 lock (m_attachments)
3023 {
3024 // Validate
3025 foreach (SceneObjectGroup gobj in m_attachments)
3026 {
3027 if (gobj == null || gobj.IsDeleted)
3028 return false;
3029 }
3030
3031 foreach (SceneObjectGroup gobj in m_attachments)
3032 {
3033 // If the prim group is null then something must have happened to it!
3034 if (gobj != null && gobj.RootPart != null)
3035 {
3036 // Set the parent localID to 0 so it transfers over properly.
3037 gobj.RootPart.SetParentLocalId(0);
3038 gobj.RootPart.IsAttachment = false;
3039 gobj.AbsolutePosition = gobj.RootPart.AttachedPos;
3040 gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
3041 m_log.DebugFormat("[ATTACHMENT]: Sending attachment {0} to region {1}", gobj.UUID, regionHandle);
3042 m_scene.CrossPrimGroupIntoNewRegion(regionHandle, gobj, silent);
3043 }
3044 }
3045 m_attachments.Clear();
3046
3047 return true;
3048 }
3049 }
3050
3051 public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
3052 {
3053 m_controllingClient = client;
3054 m_regionInfo = region;
3055 m_scene = scene;
3056
3057 RegisterToEvents();
3058
3059 /*
3060 AbsolutePosition = client.StartPos;
3061
3062 Animations = new AvatarAnimations();
3063 Animations.LoadAnims();
3064
3065 m_animations = new List<UUID>();
3066 m_animations.Add(Animations.AnimsUUID["STAND"]);
3067 m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
3068
3069 SetDirectionVectors();
3070 */
3071 }
3072
3073 protected ScenePresence(SerializationInfo info, StreamingContext context)
3074 : base (info, context)
3075 {
3076 //System.Console.WriteLine("ScenePresence Deserialize BGN");
3077
3078 if (info == null)
3079 {
3080 throw new ArgumentNullException("info");
3081 }
3082/* JB
3083 if (Animations == null)
3084 {
3085 Animations = new AvatarAnimations();
3086 Animations.LoadAnims();
3087 }
3088*/
3089 if (DefaultTexture == null)
3090 {
3091 Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture();
3092 DefaultTexture = textu.ToBytes();
3093 }
3094
3095 m_animations = (AnimationSet)info.GetValue("m_animations", typeof(AnimationSet));
3096 m_updateflag = (bool)info.GetValue("m_updateflag", typeof(bool));
3097 m_movementflag = (byte)info.GetValue("m_movementflag", typeof(byte));
3098 m_forcesList = (List<NewForce>)info.GetValue("m_forcesList", typeof(List<NewForce>));
3099 m_updateCount = (short)info.GetValue("m_updateCount", typeof(short));
3100 m_requestedSitTargetID = (uint)info.GetValue("m_requestedSitTargetID", typeof(uint));
3101
3102 m_requestedSitOffset
3103 = new Vector3(
3104 (float)info.GetValue("m_requestedSitOffset.X", typeof(float)),
3105 (float)info.GetValue("m_requestedSitOffset.Y", typeof(float)),
3106 (float)info.GetValue("m_requestedSitOffset.Z", typeof(float)));
3107
3108 m_sitAvatarHeight = (float)info.GetValue("m_sitAvatarHeight", typeof(float));
3109 m_godlevel = (float)info.GetValue("m_godlevel", typeof(float));
3110 m_setAlwaysRun = (bool)info.GetValue("m_setAlwaysRun", typeof(bool));
3111
3112 m_bodyRot
3113 = new Quaternion(
3114 (float)info.GetValue("m_bodyRot.X", typeof(float)),
3115 (float)info.GetValue("m_bodyRot.Y", typeof(float)),
3116 (float)info.GetValue("m_bodyRot.Z", typeof(float)),
3117 (float)info.GetValue("m_bodyRot.W", typeof(float)));
3118
3119 IsRestrictedToRegion = (bool)info.GetValue("IsRestrictedToRegion", typeof(bool));
3120 m_newForce = (bool)info.GetValue("m_newForce", typeof(bool));
3121 //m_newAvatar = (bool)info.GetValue("m_newAvatar", typeof(bool));
3122 m_newCoarseLocations = (bool)info.GetValue("m_newCoarseLocations", typeof(bool));
3123 m_avHeight = (float)info.GetValue("m_avHeight", typeof(float));
3124 crossingFromRegion = (ulong)info.GetValue("crossingFromRegion", typeof(ulong));
3125
3126 List<float[]> Dir_Vectors_work = (List<float[]>)info.GetValue("Dir_Vectors", typeof(List<float[]>));
3127 List<Vector3> Dir_Vectors_work2 = new List<Vector3>();
3128
3129 foreach (float[] f3 in Dir_Vectors_work)
3130 {
3131 Dir_Vectors_work2.Add(new Vector3(f3[0], f3[1], f3[2]));
3132 }
3133
3134 Dir_Vectors = Dir_Vectors_work2.ToArray();
3135
3136 lastPhysPos
3137 = new Vector3(
3138 (float)info.GetValue("lastPhysPos.X", typeof(float)),
3139 (float)info.GetValue("lastPhysPos.Y", typeof(float)),
3140 (float)info.GetValue("lastPhysPos.Z", typeof(float)));
3141
3142 // Possibly we should store lastPhysRot. But there may well be not much point since rotation changes
3143 // wouldn't carry us across borders anyway
3144
3145 m_CameraCenter
3146 = new Vector3(
3147 (float)info.GetValue("m_CameraCenter.X", typeof(float)),
3148 (float)info.GetValue("m_CameraCenter.Y", typeof(float)),
3149 (float)info.GetValue("m_CameraCenter.Z", typeof(float)));
3150
3151 m_CameraAtAxis
3152 = new Vector3(
3153 (float)info.GetValue("m_CameraAtAxis.X", typeof(float)),
3154 (float)info.GetValue("m_CameraAtAxis.Y", typeof(float)),
3155 (float)info.GetValue("m_CameraAtAxis.Z", typeof(float)));
3156
3157 m_CameraLeftAxis
3158 = new Vector3(
3159 (float)info.GetValue("m_CameraLeftAxis.X", typeof(float)),
3160 (float)info.GetValue("m_CameraLeftAxis.Y", typeof(float)),
3161 (float)info.GetValue("m_CameraLeftAxis.Z", typeof(float)));
3162
3163 m_CameraUpAxis
3164 = new Vector3(
3165 (float)info.GetValue("m_CameraUpAxis.X", typeof(float)),
3166 (float)info.GetValue("m_CameraUpAxis.Y", typeof(float)),
3167 (float)info.GetValue("m_CameraUpAxis.Z", typeof(float)));
3168
3169 m_DrawDistance = (float)info.GetValue("m_DrawDistance", typeof(float));
3170 m_appearance = (AvatarAppearance)info.GetValue("m_appearance", typeof(AvatarAppearance));
3171
3172 m_knownChildRegions = (Dictionary<ulong, string>)info.GetValue("m_knownChildRegions", typeof(Dictionary<ulong, string>));
3173
3174 posLastSignificantMove
3175 = new Vector3(
3176 (float)info.GetValue("posLastSignificantMove.X", typeof(float)),
3177 (float)info.GetValue("posLastSignificantMove.Y", typeof(float)),
3178 (float)info.GetValue("posLastSignificantMove.Z", typeof(float)));
3179
3180 // m_partsUpdateQueue = (UpdateQueue)info.GetValue("m_partsUpdateQueue", typeof(UpdateQueue));
3181
3182 /*
3183 Dictionary<Guid, ScenePartUpdate> updateTimes_work
3184 = (Dictionary<Guid, ScenePartUpdate>)info.GetValue("m_updateTimes", typeof(Dictionary<Guid, ScenePartUpdate>));
3185
3186 foreach (Guid id in updateTimes_work.Keys)
3187 {
3188 m_updateTimes.Add(new UUID(id), updateTimes_work[id]);
3189 }
3190 */
3191 m_regionHandle = (ulong)info.GetValue("m_regionHandle", typeof(ulong));
3192 m_firstname = (string)info.GetValue("m_firstname", typeof(string));
3193 m_lastname = (string)info.GetValue("m_lastname", typeof(string));
3194 m_allowMovement = (bool)info.GetValue("m_allowMovement", typeof(bool));
3195 m_parentPosition = new Vector3((float)info.GetValue("m_parentPosition.X", typeof(float)),
3196 (float)info.GetValue("m_parentPosition.Y", typeof(float)),
3197 (float)info.GetValue("m_parentPosition.Z", typeof(float)));
3198
3199 m_isChildAgent = (bool)info.GetValue("m_isChildAgent", typeof(bool));
3200 m_parentID = (uint)info.GetValue("m_parentID", typeof(uint));
3201
3202// for OpenSim_v0.5
3203 currentParcelUUID = new UUID((Guid)info.GetValue("currentParcelUUID", typeof(Guid)));
3204
3205 lastKnownAllowedPosition
3206 = new Vector3(
3207 (float)info.GetValue("lastKnownAllowedPosition.X", typeof(float)),
3208 (float)info.GetValue("lastKnownAllowedPosition.Y", typeof(float)),
3209 (float)info.GetValue("lastKnownAllowedPosition.Z", typeof(float)));
3210
3211 sentMessageAboutRestrictedParcelFlyingDown = (bool)info.GetValue("sentMessageAboutRestrictedParcelFlyingDown", typeof(bool));
3212
3213 m_LastChildAgentUpdatePosition
3214 = new Vector3(
3215 (float)info.GetValue("m_LastChildAgentUpdatePosition.X", typeof(float)),
3216 (float)info.GetValue("m_LastChildAgentUpdatePosition.Y", typeof(float)),
3217 (float)info.GetValue("m_LastChildAgentUpdatePosition.Z", typeof(float)));
3218
3219 m_perfMonMS = (int)info.GetValue("m_perfMonMS", typeof(int));
3220 m_AgentControlFlags = (uint)info.GetValue("m_AgentControlFlags", typeof(uint));
3221
3222 m_headrotation
3223 = new Quaternion(
3224 (float)info.GetValue("m_headrotation.X", typeof(float)),
3225 (float)info.GetValue("m_headrotation.Y", typeof(float)),
3226 (float)info.GetValue("m_headrotation.Z", typeof(float)),
3227 (float)info.GetValue("m_headrotation.W", typeof(float)));
3228
3229 m_state = (byte)info.GetValue("m_state", typeof(byte));
3230
3231 //System.Console.WriteLine("ScenePresence Deserialize END");
3232 }
3233
3234 [SecurityPermission(SecurityAction.LinkDemand,
3235 Flags = SecurityPermissionFlag.SerializationFormatter)]
3236 public override void GetObjectData(
3237 SerializationInfo info, StreamingContext context)
3238 {
3239 if (info == null)
3240 {
3241 throw new ArgumentNullException("info");
3242 }
3243
3244 base.GetObjectData(info, context);
3245
3246 info.AddValue("m_animations", m_animations);
3247 info.AddValue("m_updateflag", m_updateflag);
3248 info.AddValue("m_movementflag", m_movementflag);
3249 info.AddValue("m_forcesList", m_forcesList);
3250 info.AddValue("m_updateCount", m_updateCount);
3251 info.AddValue("m_requestedSitTargetID", m_requestedSitTargetID);
3252
3253 // Vector3
3254 info.AddValue("m_requestedSitOffset.X", m_requestedSitOffset.X);
3255 info.AddValue("m_requestedSitOffset.Y", m_requestedSitOffset.Y);
3256 info.AddValue("m_requestedSitOffset.Z", m_requestedSitOffset.Z);
3257
3258 info.AddValue("m_sitAvatarHeight", m_sitAvatarHeight);
3259 info.AddValue("m_godlevel", m_godlevel);
3260 info.AddValue("m_setAlwaysRun", m_setAlwaysRun);
3261
3262 // Quaternion
3263 info.AddValue("m_bodyRot.X", m_bodyRot.X);
3264 info.AddValue("m_bodyRot.Y", m_bodyRot.Y);
3265 info.AddValue("m_bodyRot.Z", m_bodyRot.Z);
3266 info.AddValue("m_bodyRot.W", m_bodyRot.W);
3267
3268 info.AddValue("IsRestrictedToRegion", IsRestrictedToRegion);
3269 info.AddValue("m_newForce", m_newForce);
3270 //info.AddValue("m_newAvatar", m_newAvatar);
3271 info.AddValue("m_newCoarseLocations", m_newCoarseLocations);
3272 info.AddValue("m_gotAPrimitivesInScene", false);
3273 info.AddValue("m_avHeight", m_avHeight);
3274
3275 // info.AddValue("m_regionInfo", m_regionInfo);
3276
3277 info.AddValue("crossingFromRegion", crossingFromRegion);
3278
3279 List<float[]> Dir_Vectors_work = new List<float[]>();
3280
3281 foreach (Vector3 v3 in Dir_Vectors)
3282 {
3283 Dir_Vectors_work.Add(new float[] { v3.X, v3.Y, v3.Z });
3284 }
3285
3286 info.AddValue("Dir_Vectors", Dir_Vectors_work);
3287
3288 // Vector3
3289 info.AddValue("lastPhysPos.X", lastPhysPos.X);
3290 info.AddValue("lastPhysPos.Y", lastPhysPos.Y);
3291 info.AddValue("lastPhysPos.Z", lastPhysPos.Z);
3292
3293 // Possibly we should retrieve lastPhysRot. But there may well be not much point since rotation changes
3294 // wouldn't carry us across borders anyway
3295
3296 // Vector3
3297 info.AddValue("m_CameraCenter.X", m_CameraCenter.X);
3298 info.AddValue("m_CameraCenter.Y", m_CameraCenter.Y);
3299 info.AddValue("m_CameraCenter.Z", m_CameraCenter.Z);
3300
3301 // Vector3
3302 info.AddValue("m_CameraAtAxis.X", m_CameraAtAxis.X);
3303 info.AddValue("m_CameraAtAxis.Y", m_CameraAtAxis.Y);
3304 info.AddValue("m_CameraAtAxis.Z", m_CameraAtAxis.Z);
3305
3306 // Vector3
3307 info.AddValue("m_CameraLeftAxis.X", m_CameraLeftAxis.X);
3308 info.AddValue("m_CameraLeftAxis.Y", m_CameraLeftAxis.Y);
3309 info.AddValue("m_CameraLeftAxis.Z", m_CameraLeftAxis.Z);
3310
3311 // Vector3
3312 info.AddValue("m_CameraUpAxis.X", m_CameraUpAxis.X);
3313 info.AddValue("m_CameraUpAxis.Y", m_CameraUpAxis.Y);
3314 info.AddValue("m_CameraUpAxis.Z", m_CameraUpAxis.Z);
3315
3316 info.AddValue("m_DrawDistance", m_DrawDistance);
3317 info.AddValue("m_appearance", m_appearance);
3318 info.AddValue("m_knownChildRegions", m_knownChildRegions);
3319
3320 // Vector3
3321 info.AddValue("posLastSignificantMove.X", posLastSignificantMove.X);
3322 info.AddValue("posLastSignificantMove.Y", posLastSignificantMove.Y);
3323 info.AddValue("posLastSignificantMove.Z", posLastSignificantMove.Z);
3324
3325 //info.AddValue("m_partsUpdateQueue", m_partsUpdateQueue);
3326
3327 /*
3328 Dictionary<Guid, ScenePartUpdate> updateTimes_work = new Dictionary<Guid, ScenePartUpdate>();
3329
3330 foreach (UUID id in m_updateTimes.Keys)
3331 {
3332 updateTimes_work.Add(id.UUID, m_updateTimes[id]);
3333 }
3334
3335 info.AddValue("m_updateTimes", updateTimes_work);
3336 */
3337
3338 info.AddValue("m_regionHandle", m_regionHandle);
3339 info.AddValue("m_firstname", m_firstname);
3340 info.AddValue("m_lastname", m_lastname);
3341 info.AddValue("m_allowMovement", m_allowMovement);
3342 //info.AddValue("m_physicsActor", m_physicsActor);
3343 info.AddValue("m_parentPosition.X", m_parentPosition.X);
3344 info.AddValue("m_parentPosition.Y", m_parentPosition.Y);
3345 info.AddValue("m_parentPosition.Z", m_parentPosition.Z);
3346 info.AddValue("m_isChildAgent", m_isChildAgent);
3347 info.AddValue("m_parentID", m_parentID);
3348
3349// for OpenSim_v0.5
3350 info.AddValue("currentParcelUUID", currentParcelUUID.Guid);
3351
3352 info.AddValue("lastKnownAllowedPosition.X", lastKnownAllowedPosition.X);
3353 info.AddValue("lastKnownAllowedPosition.Y", lastKnownAllowedPosition.Y);
3354 info.AddValue("lastKnownAllowedPosition.Z", lastKnownAllowedPosition.Z);
3355
3356 info.AddValue("sentMessageAboutRestrictedParcelFlyingDown", sentMessageAboutRestrictedParcelFlyingDown);
3357
3358 info.AddValue("m_LastChildAgentUpdatePosition.X", m_LastChildAgentUpdatePosition.X);
3359 info.AddValue("m_LastChildAgentUpdatePosition.Y", m_LastChildAgentUpdatePosition.Y);
3360 info.AddValue("m_LastChildAgentUpdatePosition.Z", m_LastChildAgentUpdatePosition.Z);
3361
3362 info.AddValue("m_perfMonMS", m_perfMonMS);
3363 info.AddValue("m_AgentControlFlags", m_AgentControlFlags);
3364
3365 info.AddValue("m_headrotation.W", m_headrotation.W);
3366 info.AddValue("m_headrotation.X", m_headrotation.X);
3367 info.AddValue("m_headrotation.Y", m_headrotation.Y);
3368 info.AddValue("m_headrotation.Z", m_headrotation.Z);
3369
3370 info.AddValue("m_state", m_state);
3371
3372 List<Guid> knownPrimUUID_work = new List<Guid>();
3373
3374 info.AddValue("m_knownPrimUUID", knownPrimUUID_work);
3375 }
3376
3377 internal void PushForce(PhysicsVector impulse)
3378 {
3379 if (PhysicsActor != null)
3380 {
3381 PhysicsActor.AddForce(impulse,true);
3382 }
3383 }
3384
3385 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
3386 {
3387 ScriptControllers obj = new ScriptControllers();
3388 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3389 obj.eventControls = ScriptControlled.CONTROL_ZERO;
3390
3391 obj.itemID = Script_item_UUID;
3392 obj.objID = Obj_localID;
3393 if (pass_on == 0 && accept == 0)
3394 {
3395 IgnoredControls |= (ScriptControlled)controls;
3396 obj.ignoreControls = (ScriptControlled)controls;
3397 }
3398
3399 if (pass_on == 0 && accept == 1)
3400 {
3401 IgnoredControls |= (ScriptControlled)controls;
3402 obj.ignoreControls = (ScriptControlled)controls;
3403 obj.eventControls = (ScriptControlled)controls;
3404 }
3405 if (pass_on == 1 && accept == 1)
3406 {
3407 IgnoredControls = ScriptControlled.CONTROL_ZERO;
3408 obj.eventControls = (ScriptControlled)controls;
3409 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3410 }
3411
3412 lock (scriptedcontrols)
3413 {
3414 if (pass_on == 1 && accept == 0)
3415 {
3416 IgnoredControls &= ~(ScriptControlled)controls;
3417 if (scriptedcontrols.ContainsKey(Script_item_UUID))
3418 scriptedcontrols.Remove(Script_item_UUID);
3419
3420 }
3421 else
3422 {
3423
3424 if (scriptedcontrols.ContainsKey(Script_item_UUID))
3425 {
3426 scriptedcontrols[Script_item_UUID] = obj;
3427 }
3428 else
3429 {
3430 scriptedcontrols.Add(Script_item_UUID, obj);
3431 }
3432 }
3433 }
3434 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
3435 }
3436
3437 public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
3438 {
3439 IgnoredControls = ScriptControlled.CONTROL_ZERO;
3440 lock (scriptedcontrols)
3441 {
3442 scriptedcontrols.Clear();
3443 }
3444 ControllingClient.SendTakeControls(int.MaxValue, false, false);
3445 }
3446
3447 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
3448 {
3449 lock (scriptedcontrols)
3450 {
3451 if (scriptedcontrols.ContainsKey(Script_item_UUID))
3452 {
3453 ScriptControllers takecontrolls = scriptedcontrols[Script_item_UUID];
3454 ScriptControlled sctc = takecontrolls.eventControls;
3455 ControllingClient.SendTakeControls((int)sctc, false, false);
3456 ControllingClient.SendTakeControls((int)sctc, true, false);
3457
3458 scriptedcontrols.Remove(Script_item_UUID);
3459 IgnoredControls = ScriptControlled.CONTROL_ZERO;
3460 foreach (ScriptControllers scData in scriptedcontrols.Values)
3461 {
3462 IgnoredControls |= scData.ignoreControls;
3463 }
3464 }
3465
3466 }
3467 }
3468
3469 internal void SendControlToScripts(uint flags)
3470 {
3471
3472 ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
3473
3474 if (MouseDown)
3475 {
3476 allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
3477 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
3478 {
3479 allflags = ScriptControlled.CONTROL_ZERO;
3480 MouseDown = true;
3481 }
3482 }
3483
3484 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
3485 {
3486 allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
3487 MouseDown = true;
3488 }
3489 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
3490 {
3491 allflags |= ScriptControlled.CONTROL_LBUTTON;
3492 MouseDown = true;
3493 }
3494
3495 // find all activated controls, whether the scripts are interested in them or not
3496 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
3497 {
3498 allflags |= ScriptControlled.CONTROL_FWD;
3499 }
3500 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
3501 {
3502 allflags |= ScriptControlled.CONTROL_BACK;
3503 }
3504 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
3505 {
3506 allflags |= ScriptControlled.CONTROL_UP;
3507 }
3508 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
3509 {
3510 allflags |= ScriptControlled.CONTROL_DOWN;
3511 }
3512 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
3513 {
3514 allflags |= ScriptControlled.CONTROL_LEFT;
3515 }
3516 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
3517 {
3518 allflags |= ScriptControlled.CONTROL_RIGHT;
3519 }
3520 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
3521 {
3522 allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
3523 }
3524 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
3525 {
3526 allflags |= ScriptControlled.CONTROL_ROT_LEFT;
3527 }
3528 // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
3529 if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
3530 {
3531 lock (scriptedcontrols)
3532 {
3533 foreach (UUID scriptUUID in scriptedcontrols.Keys)
3534 {
3535 ScriptControllers scriptControlData = scriptedcontrols[scriptUUID];
3536 ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
3537 ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
3538 ScriptControlled localChange = localHeld ^ localLast; // the changed bits
3539 if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
3540 {
3541 // only send if still pressed or just changed
3542 m_scene.EventManager.TriggerControlEvent(scriptControlData.objID, scriptUUID, UUID, (uint)localHeld, (uint)localChange);
3543 }
3544 }
3545 }
3546 }
3547
3548 LastCommands = allflags;
3549 }
3550
3551 internal uint RemoveIgnoredControls(uint flags, ScriptControlled Ignored)
3552 {
3553 if (Ignored == ScriptControlled.CONTROL_ZERO)
3554 return flags;
3555 if ((Ignored & ScriptControlled.CONTROL_BACK) != 0)
3556 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
3557 if ((Ignored & ScriptControlled.CONTROL_FWD) != 0)
3558 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
3559 if ((Ignored & ScriptControlled.CONTROL_DOWN) != 0)
3560 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
3561 if ((Ignored & ScriptControlled.CONTROL_UP) != 0)
3562 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
3563 if ((Ignored & ScriptControlled.CONTROL_LEFT) != 0)
3564 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
3565 if ((Ignored & ScriptControlled.CONTROL_RIGHT) != 0)
3566 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
3567 if ((Ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
3568 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
3569 if ((Ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
3570 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
3571 if ((Ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
3572 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
3573 if ((Ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
3574 flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
3575 //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
3576 //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
3577 //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
3578 //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
3579 //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
3580 //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
3581 //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
3582 return flags;
3583 }
3584
3585 private void ItemReceived(UUID itemID)
3586 {
3587 if (IsChildAgent)
3588 return;
3589
3590 if (null == m_appearance)
3591 {
3592 m_log.Warn("[ATTACHMENT] Appearance has not been initialized");
3593 return;
3594 }
3595
3596 int attachpoint = m_appearance.GetAttachpoint(itemID);
3597 if (attachpoint == 0)
3598 return;
3599
3600 UUID asset = m_appearance.GetAttachedAsset(attachpoint);
3601 if (UUID.Zero == asset) // We have just logged in
3602 {
3603 try
3604 {
3605 // Rez from inventory
3606 asset = m_scene.RezSingleAttachment(ControllingClient,
3607 itemID, (uint)attachpoint);
3608 // Corner case: We are not yet a Scene Entity
3609 // Setting attachment info in RezSingleAttachment will fail
3610 // Set it here
3611 //
3612 m_appearance.SetAttachment((int)attachpoint, itemID,
3613 asset);
3614 m_log.InfoFormat("[ATTACHMENT] Rezzed attachment {0}, inworld asset {1}",
3615 itemID.ToString(), asset);
3616
3617 }
3618 catch (Exception e)
3619 {
3620 m_log.ErrorFormat("[ATTACHMENT] Unable to rez attachment: {0}", e.ToString());
3621 }
3622
3623 return;
3624 }
3625
3626 SceneObjectPart att = m_scene.GetSceneObjectPart(asset);
3627
3628
3629 // If this is null, then the asset has not yet appeared in world
3630 // so we revisit this when it does
3631 //
3632 if (att != null && att.UUID != asset) // Yes. It's really needed
3633 {
3634 m_log.DebugFormat("[ATTACHMENT]: Attach from in world: ItemID {0}, Asset ID {1}, Attachment inworld: {2}", itemID.ToString(), asset.ToString(), att.UUID.ToString());
3635
3636 // This will throw if crossing katty-korner
3637 // So catch it here to avoid the noid
3638 //
3639 try
3640 {
3641 // Attach from world, if not already attached
3642 if (att.ParentGroup != null && !att.IsAttachment)
3643 m_scene.AttachObject(ControllingClient, att.ParentGroup.LocalId, (uint)0, Quaternion.Identity, att.ParentGroup.AbsolutePosition, false);
3644 }
3645 catch (NullReferenceException)
3646 {
3647 }
3648 }
3649 }
3650 }
3651}
diff --git a/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs b/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs
deleted file mode 100644
index 152825f..0000000
--- a/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 OpenMetaverse;
29
30namespace OpenSim.Region.Environment.Scenes.Scripting
31{
32 public interface IScriptHost
33 {
34 string Name { get; set; }
35 string Description { get; set; }
36
37 UUID UUID { get; }
38 UUID ObjectOwner { get; }
39 UUID ObjectCreator { get; }
40 Vector3 AbsolutePosition { get; }
41
42 string SitName { get; set; }
43 string TouchName { get; set; }
44 void SetText(string text, Vector3 color, double alpha);
45 }
46}
diff --git a/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs b/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs
deleted file mode 100644
index 37f5d43..0000000
--- a/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs
+++ /dev/null
@@ -1,86 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30
31namespace OpenSim.Region.Environment.Scenes.Scripting
32{
33 public class NullScriptHost : IScriptHost
34 {
35 private Vector3 m_pos = new Vector3(128, 128, 30);
36
37 public string Name
38 {
39 get { return "Object"; }
40 set { }
41 }
42
43 public string SitName
44 {
45 get { return String.Empty; }
46 set { }
47 }
48
49 public string TouchName
50 {
51 get { return String.Empty; }
52 set { }
53 }
54
55 public string Description
56 {
57 get { return String.Empty; }
58 set { }
59 }
60
61 public UUID UUID
62 {
63 get { return UUID.Zero; }
64 }
65
66 public UUID ObjectOwner
67 {
68 get { return UUID.Zero; }
69 }
70
71 public UUID ObjectCreator
72 {
73 get { return UUID.Zero; }
74 }
75
76 public Vector3 AbsolutePosition
77 {
78 get { return m_pos; }
79 }
80
81 public void SetText(string text, Vector3 color, double alpha)
82 {
83 Console.WriteLine("Tried to SetText [{0}] on NullScriptHost", text);
84 }
85 }
86}
diff --git a/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs b/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs
deleted file mode 100644
index b1ee519..0000000
--- a/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28//TODO: WHERE TO PLACE THIS?
29
30namespace OpenSim.Region.Environment.Scenes.Scripting
31{
32 public interface ScriptEngineInterface
33 {
34 void InitializeEngine(Scene Sceneworld);
35 void Shutdown();
36// void StartScript(string ScriptID, IScriptHost ObjectID);
37 }
38}
diff --git a/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs b/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs
deleted file mode 100644
index 6216e2c..0000000
--- a/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs
+++ /dev/null
@@ -1,119 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Original code: Tedd Hansen */
29using System;
30using System.IO;
31using System.Reflection;
32using log4net;
33
34namespace OpenSim.Region.Environment.Scenes.Scripting
35{
36 public class ScriptEngineLoader
37 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 public ScriptEngineInterface LoadScriptEngine(string EngineName)
41 {
42 ScriptEngineInterface ret = null;
43 try
44 {
45 ret =
46 LoadAndInitAssembly(
47 Path.Combine("ScriptEngines", "OpenSim.Region.ScriptEngine." + EngineName + ".dll"),
48 "OpenSim.Region.ScriptEngine." + EngineName + ".ScriptEngine");
49 }
50 catch (Exception e)
51 {
52 m_log.Error("[ScriptEngine]: " +
53 "Error loading assembly \"" + EngineName + "\": " + e.Message + ", " +
54 e.StackTrace.ToString());
55 }
56 return ret;
57 }
58
59 /// <summary>
60 /// Does actual loading and initialization of script Assembly
61 /// </summary>
62 /// <param name="FreeAppDomain">AppDomain to load script into</param>
63 /// <param name="FileName">FileName of script assembly (.dll)</param>
64 /// <returns></returns>
65 private ScriptEngineInterface LoadAndInitAssembly(string FileName, string NameSpace)
66 {
67 //Common.SendToDebug("Loading ScriptEngine Assembly " + FileName);
68 // Load .Net Assembly (.dll)
69 // Initialize and return it
70
71 // TODO: Add error handling
72
73 Assembly a;
74 //try
75 //{
76
77
78 // Load to default appdomain (temporary)
79 a = Assembly.LoadFrom(FileName);
80 // Load to specified appdomain
81 // TODO: Insert security
82 //a = FreeAppDomain.Load(FileName);
83 //}
84 //catch (Exception e)
85 //{
86 // m_log.Error("[ScriptEngine]: Error loading assembly \String.Empty + FileName + "\": " + e.ToString());
87 //}
88
89
90 //Console.WriteLine("Loading: " + FileName);
91 //foreach (Type _t in a.GetTypes())
92 //{
93 // Console.WriteLine("Type: " + _t.ToString());
94 //}
95
96 Type t;
97 //try
98 //{
99 t = a.GetType(NameSpace, true);
100 //}
101 //catch (Exception e)
102 //{
103 // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString());
104 //}
105
106 ScriptEngineInterface ret;
107 //try
108 //{
109 ret = (ScriptEngineInterface) Activator.CreateInstance(t);
110 //}
111 //catch (Exception e)
112 //{
113 // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString());
114 //}
115
116 return ret;
117 }
118 }
119}
diff --git a/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs b/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs
deleted file mode 100644
index efda140..0000000
--- a/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs
+++ /dev/null
@@ -1,450 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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;
29//using System.Collections.Generic;
30using System.Timers;
31using OpenMetaverse.Packets;
32using OpenSim.Framework;
33using OpenSim.Framework.Statistics;
34using OpenSim.Region.Environment.Interfaces;
35
36namespace OpenSim.Region.Environment.Scenes
37{
38 public class SimStatsReporter
39 {
40 public delegate void SendStatResult(SimStats stats);
41
42 public delegate void YourStatsAreWrong();
43
44 public event SendStatResult OnSendStatsResult;
45
46 public event YourStatsAreWrong OnStatsIncorrect;
47
48 private SendStatResult handlerSendStatResult = null;
49
50 private YourStatsAreWrong handlerStatsIncorrect = null;
51
52 private enum Stats : uint
53 {
54 TimeDilation = 0,
55 SimFPS = 1,
56 PhysicsFPS = 2,
57 AgentUpdates = 3,
58 FrameMS = 4,
59 NetMS = 5,
60 OtherMS = 6,
61 PhysicsMS = 7,
62 AgentMS = 8,
63 ImageMS = 9,
64 ScriptMS = 10,
65 TotalPrim = 11,
66 ActivePrim = 12,
67 Agents = 13,
68 ChildAgents = 14,
69 ActiveScripts = 15,
70 ScriptLinesPerSecond = 16,
71 InPacketsPerSecond = 17,
72 OutPacketsPerSecond = 18,
73 PendingDownloads = 19,
74 PendingUploads = 20,
75 UnAckedBytes = 24,
76 }
77
78 // Sending a stats update every 3 seconds
79 private int statsUpdatesEveryMS = 3000;
80 private float statsUpdateFactor = 0;
81 private float m_timeDilation = 0;
82 private int m_fps = 0;
83 // saved last reported value so there is something available for llGetRegionFPS
84 private float lastReportedSimFPS = 0;
85 private float m_pfps = 0;
86 private int m_agentUpdates = 0;
87
88 private int m_frameMS = 0;
89 private int m_netMS = 0;
90 private int m_agentMS = 0;
91 private int m_physicsMS = 0;
92 private int m_imageMS = 0;
93 private int m_otherMS = 0;
94
95//Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed.
96//Ckrinke private int m_scriptMS = 0;
97
98 private int m_rootAgents = 0;
99 private int m_childAgents = 0;
100 private int m_numPrim = 0;
101 private int m_inPacketsPerSecond = 0;
102 private int m_outPacketsPerSecond = 0;
103 private int m_activePrim = 0;
104 private int m_unAckedBytes = 0;
105 private int m_pendingDownloads = 0;
106 private int m_pendingUploads = 0;
107 private int m_activeScripts = 0;
108 private int m_scriptLinesPerSecond = 0;
109
110 private int objectCapacity = 45000;
111
112 private Scene m_scene;
113
114 private RegionInfo ReportingRegion;
115
116 private Timer m_report = new Timer();
117
118
119 public SimStatsReporter(Scene scene)
120 {
121 statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000);
122 m_scene = scene;
123 ReportingRegion = scene.RegionInfo;
124
125 m_report.AutoReset = true;
126 m_report.Interval = statsUpdatesEveryMS;
127 m_report.Elapsed += new ElapsedEventHandler(statsHeartBeat);
128 m_report.Enabled = true;
129
130 if (StatsManager.SimExtraStats != null)
131 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
132 }
133
134 public void SetUpdateMS(int ms)
135 {
136 statsUpdatesEveryMS = ms;
137 statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000);
138 m_report.Interval = statsUpdatesEveryMS;
139 }
140
141 private void statsHeartBeat(object sender, EventArgs e)
142 {
143 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21];
144 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
145
146 // Know what's not thread safe in Mono... modifying timers.
147 // System.Console.WriteLine("Firing Stats Heart Beat");
148 lock (m_report)
149 {
150 uint regionFlags = 0;
151
152 try
153 {
154 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
155 regionFlags = estateModule != null ? estateModule.GetRegionFlags() : (uint) 0;
156 }
157 catch (Exception)
158 {
159 // leave region flags at 0
160 }
161
162#region various statistic googly moogly
163
164 // Our FPS is actually 10fps, so multiplying by 5 to get the amount that people expect there
165 // 0-50 is pretty close to 0-45
166 float simfps = (int) ((m_fps * 5));
167 // save the reported value so there is something available for llGetRegionFPS
168 lastReportedSimFPS = (float)simfps / statsUpdateFactor;
169
170 //if (simfps > 45)
171 //simfps = simfps - (simfps - 45);
172 //if (simfps < 0)
173 //simfps = 0;
174
175 //
176 float physfps = ((m_pfps / 1000));
177
178 //if (physfps > 600)
179 //physfps = physfps - (physfps - 600);
180
181 if (physfps < 0)
182 physfps = 0;
183
184#endregion
185
186 //Our time dilation is 0.91 when we're running a full speed,
187 // therefore to make sure we get an appropriate range,
188 // we have to factor in our error. (0.10f * statsUpdateFactor)
189 // multiplies the fix for the error times the amount of times it'll occur a second
190 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
191 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
192
193 for (int i = 0; i<21;i++)
194 {
195 sb[i] = new SimStatsPacket.StatBlock();
196 }
197
198 sb[0].StatID = (uint) Stats.TimeDilation;
199 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor));
200
201 sb[1].StatID = (uint) Stats.SimFPS;
202 sb[1].StatValue = simfps/statsUpdateFactor;
203
204 sb[2].StatID = (uint) Stats.PhysicsFPS;
205 sb[2].StatValue = physfps / statsUpdateFactor;
206
207 sb[3].StatID = (uint) Stats.AgentUpdates;
208 sb[3].StatValue = (m_agentUpdates / statsUpdateFactor);
209
210 sb[4].StatID = (uint) Stats.Agents;
211 sb[4].StatValue = m_rootAgents;
212
213 sb[5].StatID = (uint) Stats.ChildAgents;
214 sb[5].StatValue = m_childAgents;
215
216 sb[6].StatID = (uint) Stats.TotalPrim;
217 sb[6].StatValue = m_numPrim;
218
219 sb[7].StatID = (uint) Stats.ActivePrim;
220 sb[7].StatValue = m_activePrim;
221
222 sb[8].StatID = (uint)Stats.FrameMS;
223 sb[8].StatValue = m_frameMS / statsUpdateFactor;
224
225 sb[9].StatID = (uint)Stats.NetMS;
226 sb[9].StatValue = m_netMS / statsUpdateFactor;
227
228 sb[10].StatID = (uint)Stats.PhysicsMS;
229 sb[10].StatValue = m_physicsMS / statsUpdateFactor;
230
231 sb[11].StatID = (uint)Stats.ImageMS ;
232 sb[11].StatValue = m_imageMS / statsUpdateFactor;
233
234 sb[12].StatID = (uint)Stats.OtherMS;
235 sb[12].StatValue = m_otherMS / statsUpdateFactor;
236
237 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
238 sb[13].StatValue = (m_inPacketsPerSecond);
239
240 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
241 sb[14].StatValue = (m_outPacketsPerSecond / statsUpdateFactor);
242
243 sb[15].StatID = (uint)Stats.UnAckedBytes;
244 sb[15].StatValue = m_unAckedBytes;
245
246 sb[16].StatID = (uint)Stats.AgentMS;
247 sb[16].StatValue = m_agentMS / statsUpdateFactor;
248
249 sb[17].StatID = (uint)Stats.PendingDownloads;
250 sb[17].StatValue = m_pendingDownloads;
251
252 sb[18].StatID = (uint)Stats.PendingUploads;
253 sb[18].StatValue = m_pendingUploads;
254
255 sb[19].StatID = (uint)Stats.ActiveScripts;
256 sb[19].StatValue = m_activeScripts;
257
258 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond;
259 sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor;
260
261 SimStats simStats
262 = new SimStats(
263 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)objectCapacity, rb, sb, m_scene.RegionInfo.originRegionID);
264
265 handlerSendStatResult = OnSendStatsResult;
266 if (handlerSendStatResult != null)
267 {
268 handlerSendStatResult(simStats);
269 }
270 resetvalues();
271 }
272 }
273
274 private void resetvalues()
275 {
276 m_timeDilation = 0;
277 m_fps = 0;
278 m_pfps = 0;
279 m_agentUpdates = 0;
280 m_inPacketsPerSecond = 0;
281 m_outPacketsPerSecond = 0;
282 m_unAckedBytes = 0;
283 m_scriptLinesPerSecond = 0;
284
285 m_frameMS = 0;
286 m_agentMS = 0;
287 m_netMS = 0;
288 m_physicsMS = 0;
289 m_imageMS = 0;
290 m_otherMS = 0;
291
292//Ckrinke This variable is not used, so comment to remove compiler warning until it is used.
293//Ckrinke m_scriptMS = 0;
294 }
295
296 # region methods called from Scene
297 // The majority of these functions are additive
298 // so that you can easily change the amount of
299 // seconds in between sim stats updates
300
301 public void AddTimeDilation(float td)
302 {
303 //float tdsetting = td;
304 //if (tdsetting > 1.0f)
305 //tdsetting = (tdsetting - (tdsetting - 0.91f));
306
307 //if (tdsetting < 0)
308 //tdsetting = 0.0f;
309 m_timeDilation = td;
310 }
311
312 public void SetRootAgents(int rootAgents)
313 {
314 m_rootAgents = rootAgents;
315 CheckStatSanity();
316
317 }
318
319 internal void CheckStatSanity()
320 {
321 if (m_rootAgents < 0 || m_childAgents < 0)
322 {
323 handlerStatsIncorrect = OnStatsIncorrect;
324 if (handlerStatsIncorrect != null)
325 {
326 handlerStatsIncorrect();
327 }
328 }
329 if (m_rootAgents == 0 && m_childAgents == 0)
330 {
331 m_unAckedBytes = 0;
332 }
333 }
334
335 public void SetChildAgents(int childAgents)
336 {
337 m_childAgents = childAgents;
338 CheckStatSanity();
339 }
340
341 public void SetObjects(int objects)
342 {
343 m_numPrim = objects;
344 }
345
346 public void SetActiveObjects(int objects)
347 {
348 m_activePrim = objects;
349 }
350
351 public void AddFPS(int frames)
352 {
353 m_fps += frames;
354 }
355
356 public void AddPhysicsFPS(float frames)
357 {
358 m_pfps += frames;
359 }
360
361 public void AddAgentUpdates(int numUpdates)
362 {
363 m_agentUpdates += numUpdates;
364 }
365
366 public void AddInPackets(int numPackets)
367 {
368 m_inPacketsPerSecond += numPackets;
369 }
370
371 public void AddOutPackets(int numPackets)
372 {
373 m_outPacketsPerSecond += numPackets;
374 }
375
376 public void AddunAckedBytes(int numBytes)
377 {
378 m_unAckedBytes += numBytes;
379 if (m_unAckedBytes < 0) m_unAckedBytes = 0;
380 }
381
382 public void addFrameMS(int ms)
383 {
384 m_frameMS += ms;
385 }
386 public void addNetMS(int ms)
387 {
388 m_netMS += ms;
389 }
390 public void addAgentMS(int ms)
391 {
392 m_agentMS += ms;
393 }
394 public void addPhysicsMS(int ms)
395 {
396 m_physicsMS += ms;
397 }
398 public void addImageMS(int ms)
399 {
400 m_imageMS += ms;
401 }
402 public void addOtherMS(int ms)
403 {
404 m_otherMS += ms;
405 }
406
407// private static readonly log4net.ILog m_log
408// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
409
410 public void addPendingDownload(int count)
411 {
412 m_pendingDownloads += count;
413 if (m_pendingDownloads < 0) m_pendingDownloads = 0;
414 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
415 }
416
417 public void addScriptLines(int count)
418 {
419 m_scriptLinesPerSecond += count;
420 }
421
422 public void SetActiveScripts(int count)
423 {
424 m_activeScripts = count;
425 }
426
427 public void SetObjectCapacity(int objects)
428 {
429 objectCapacity = objects;
430 }
431
432 /// <summary>
433 /// This is for llGetRegionFPS
434 /// </summary>
435 public float getLastReportedSimFPS()
436 {
437 return lastReportedSimFPS;
438 }
439
440 public void AddPacketsFromClientStats(int inPackets, int outPackets, int unAckedBytes)
441 {
442 AddInPackets(inPackets);
443 AddOutPackets(outPackets);
444 AddunAckedBytes(unAckedBytes);
445
446 }
447
448 #endregion
449 }
450}
diff --git a/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs
deleted file mode 100644
index 0155966..0000000
--- a/OpenSim/Region/Environment/Scenes/Tests/EntityManagerTests.cs
+++ /dev/null
@@ -1,176 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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.Threading;
30using System.Text;
31using System.Collections.Generic;
32using Nini.Config;
33using NUnit.Framework;
34using NUnit.Framework.SyntaxHelpers;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications;
38using OpenSim.Region.Environment.Scenes;
39using OpenSim.Tests.Common.Setup;
40
41namespace OpenSim.Region.Environment.Scenes.Tests
42{
43 [TestFixture]
44 public class EntityManagerTests
45 {
46 static public Random random;
47 SceneObjectGroup found;
48 Scene scene = SceneSetupHelpers.SetupScene();
49
50 [Test]
51 public void T010_AddObjects()
52 {
53 random = new Random();
54 SceneObjectGroup found;
55 EntityManager entman = new EntityManager();
56 SceneObjectGroup sog = NewSOG();
57 UUID obj1 = sog.UUID;
58 uint li1 = sog.LocalId;
59 entman.Add(sog);
60 sog = NewSOG();
61 UUID obj2 = sog.UUID;
62 uint li2 = sog.LocalId;
63 entman.Add(sog);
64
65 found = (SceneObjectGroup)entman[obj1];
66 Assert.That(found.UUID ,Is.EqualTo(obj1) );
67 found = (SceneObjectGroup)entman[li1];
68 Assert.That(found.UUID ,Is.EqualTo(obj1) );
69 found = (SceneObjectGroup)entman[obj2];
70 Assert.That(found.UUID ,Is.EqualTo(obj2) );
71 found = (SceneObjectGroup)entman[li2];
72 Assert.That(found.UUID ,Is.EqualTo(obj2) );
73
74 entman.Remove(obj1);
75 entman.Remove(li2);
76
77 Assert.That(entman.ContainsKey(obj1), Is.False);
78 Assert.That(entman.ContainsKey(li1), Is.False);
79 Assert.That(entman.ContainsKey(obj2), Is.False);
80 Assert.That(entman.ContainsKey(li2), Is.False);
81 }
82
83 [Test]
84 public void T011_ThreadAddRemoveTest()
85 {
86 // This test adds and removes with mutiple threads, attempting to break the
87 // uuid and localid dictionary coherence.
88 EntityManager entman = new EntityManager();
89 SceneObjectGroup sog = NewSOG();
90 for (int j=0; j<20; j++)
91 {
92 List<Thread> trdlist = new List<Thread>();
93
94 for (int i=0; i<4; i++)
95 {
96 // Adds scene object
97 NewTestThreads test = new NewTestThreads(entman,sog);
98 Thread start = new Thread(new ThreadStart(test.TestAddSceneObject));
99 start.Start();
100 trdlist.Add(start);
101
102 // Removes it
103 test = new NewTestThreads(entman,sog);
104 start = new Thread(new ThreadStart(test.TestRemoveSceneObject));
105 start.Start();
106 trdlist.Add(start);
107 }
108 foreach (Thread thread in trdlist)
109 {
110 thread.Join();
111 }
112 if (entman.ContainsKey(sog.UUID) || entman.ContainsKey(sog.LocalId)) {
113 found = (SceneObjectGroup)entman[sog.UUID];
114 Assert.That(found.UUID,Is.EqualTo(sog.UUID));
115 found = (SceneObjectGroup)entman[sog.LocalId];
116 Assert.That(found.UUID,Is.EqualTo(sog.UUID));
117 }
118 }
119 }
120
121 private SceneObjectGroup NewSOG()
122 {
123 SceneObjectGroup sog = new SceneObjectGroup();
124 SceneObjectPart sop = new SceneObjectPart(UUID.Random(), PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero);
125 sop.Name = RandomName();
126 sop.Description = sop.Name;
127 sop.Text = RandomName();
128 sop.SitName = RandomName();
129 sop.TouchName = RandomName();
130 sop.ObjectFlags |= (uint)PrimFlags.Phantom;
131
132 sog.SetRootPart(sop);
133
134 scene.AddNewSceneObject(sog, false);
135
136 return sog;
137 }
138
139 private static string RandomName()
140 {
141 StringBuilder name = new StringBuilder();
142 int size = random.Next(40,80);
143 char ch ;
144 for (int i=0; i<size; i++)
145 {
146 ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))) ;
147 name.Append(ch);
148 }
149 return name.ToString();
150 }
151 }
152
153 public class NewTestThreads
154 {
155 private EntityManager entman;
156 private SceneObjectGroup sog;
157 private Random random;
158
159 public NewTestThreads(EntityManager entman, SceneObjectGroup sog)
160 {
161 this.entman = entman;
162 this.sog = sog;
163 this.random = new Random();
164 }
165 public void TestAddSceneObject()
166 {
167 Thread.Sleep(random.Next(0,50));
168 entman.Add(sog);
169 }
170 public void TestRemoveSceneObject()
171 {
172 Thread.Sleep(random.Next(0,50));
173 entman.Remove(sog.UUID);
174 }
175 }
176} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Environment/Scenes/Tests/SceneObjectBasicTests.cs
deleted file mode 100644
index d063eae..0000000
--- a/OpenSim/Region/Environment/Scenes/Tests/SceneObjectBasicTests.cs
+++ /dev/null
@@ -1,139 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 NUnit.Framework;
30using NUnit.Framework.SyntaxHelpers;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34using OpenSim.Framework.Communications.Cache;
35using OpenSim.Region.Communications.Local;
36using OpenSim.Region.Environment.Scenes;
37using OpenSim.Tests.Common.Mock;
38using OpenSim.Tests.Common.Setup;
39
40namespace OpenSim.Region.Environment.Scenes.Tests
41{
42 /// <summary>
43 /// Basic scene object tests (create, read and delete but not update).
44 /// </summary>
45 [TestFixture]
46 public class SceneObjectTests
47 {
48 /// <summary>
49 /// Test adding an object to a scene.
50 /// </summary>
51 [Test]
52 public void TestAddSceneObject()
53 {
54 Scene scene = SceneSetupHelpers.SetupScene();
55 SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene);
56 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
57
58 //System.Console.WriteLine("retrievedPart : {0}", retrievedPart);
59 // If the parts have the same UUID then we will consider them as one and the same
60 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID));
61 }
62
63 /// <summary>
64 /// Test deleting an object from a scene.
65 /// </summary>
66 [Test]
67 public void TestDeleteSceneObject()
68 {
69 TestScene scene = SceneSetupHelpers.SetupScene();
70 SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene);
71 scene.DeleteSceneObject(part.ParentGroup, false);
72
73 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
74 Assert.That(retrievedPart, Is.Null);
75 }
76
77 /// <summary>
78 /// Test deleting an object asynchronously
79 /// </summary>
80 [Test]
81 public void TestDeleteSceneObjectAsync()
82 {
83 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
84
85 TestScene scene = SceneSetupHelpers.SetupScene();
86
87 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
88 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
89 sogd.Enabled = false;
90
91 SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene);
92
93 IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId);
94 scene.DeRezObject(client, part.LocalId, UUID.Zero, DeRezAction.Delete, UUID.Zero);
95
96 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
97 Assert.That(retrievedPart, Is.Not.Null);
98
99 sogd.InventoryDeQueueAndDelete();
100 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId);
101 Assert.That(retrievedPart2, Is.Null);
102 }
103
104 /// <summary>
105 /// Test deleting an object asynchronously to user inventory.
106 /// </summary>
107 [Test]
108 public void TestDeleteSceneObjectAsyncToUserInventory()
109 {
110 //log4net.Config.XmlConfigurator.Configure();
111
112 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
113 string myObjectName = "Fred";
114
115 TestScene scene = SceneSetupHelpers.SetupScene();
116 SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene, myObjectName);
117
118 Assert.That(
119 scene.CommsManager.UserAdminService.AddUser(
120 "Bob", "Hoskins", "test", "test@test.com", 1000, 1000, agentId),
121 Is.EqualTo(agentId));
122
123 IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId);
124
125 CachedUserInfo userInfo = scene.CommsManager.UserProfileCacheService.GetUserDetails(agentId);
126 Assert.That(userInfo, Is.Not.Null);
127 Assert.That(userInfo.RootFolder, Is.Not.Null);
128
129 SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
130
131 // Check that we now have the taken part in our inventory
132 Assert.That(myObjectName, Is.EqualTo(userInfo.RootFolder.FindItemByPath(myObjectName).Name));
133
134 // Check that the taken part has actually disappeared
135 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
136 Assert.That(retrievedPart, Is.Null);
137 }
138 }
139} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Environment/Scenes/Tests/SceneObjectLinkingTests.cs
deleted file mode 100644
index 30b0987..0000000
--- a/OpenSim/Region/Environment/Scenes/Tests/SceneObjectLinkingTests.cs
+++ /dev/null
@@ -1,249 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 NUnit.Framework;
30using NUnit.Framework.SyntaxHelpers;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34using OpenSim.Framework.Communications.Cache;
35using OpenSim.Region.Communications.Local;
36using OpenSim.Region.Environment.Scenes;
37using OpenSim.Tests.Common.Mock;
38using OpenSim.Tests.Common.Setup;
39
40namespace OpenSim.Region.Environment.Scenes.Tests
41{
42 /// <summary>
43 /// Linking tests
44 /// </summary>
45 [TestFixture]
46 public class SceneObjectLinkingTests
47 {
48 [Test]
49 public void TestLinkDelink2SceneObjects()
50 {
51 bool debugtest = false;
52
53 Scene scene = SceneSetupHelpers.SetupScene();
54 SceneObjectPart part1 = SceneSetupHelpers.AddSceneObject(scene);
55 SceneObjectGroup grp1 = part1.ParentGroup;
56 SceneObjectPart part2 = SceneSetupHelpers.AddSceneObject(scene);
57 SceneObjectGroup grp2 = part2.ParentGroup;
58
59 grp1.AbsolutePosition = new Vector3(10, 10, 10);
60 grp2.AbsolutePosition = Vector3.Zero;
61
62 // <90,0,0>
63 grp1.Rotation = (Quaternion.CreateFromEulers(90 * Utils.DEG_TO_RAD, 0, 0));
64
65 // <180,0,0>
66 grp2.UpdateGroupRotation(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0));
67
68 // Required for linking
69 grp1.RootPart.UpdateFlag = 0;
70 grp2.RootPart.UpdateFlag = 0;
71
72 // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated.
73 grp1.LinkToGroup(grp2);
74
75 // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since
76 // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed.
77 Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link.");
78 Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained children after delink.");
79 Assert.That(grp1.Children.Count == 2);
80
81 if (debugtest)
82 {
83 System.Console.WriteLine("parts: {0}", grp1.Children.Count);
84 System.Console.WriteLine("Group1: Pos:{0}, Rot:{1}", grp1.AbsolutePosition, grp1.Rotation);
85 System.Console.WriteLine("Group1: Prim1: OffsetPosition:{0}, OffsetRotation:{1}", part1.OffsetPosition, part1.RotationOffset);
86 System.Console.WriteLine("Group1: Prim2: OffsetPosition:{0}, OffsetRotation:{1}", part2.OffsetPosition, part2.RotationOffset);
87 }
88
89 // root part should have no offset position or rotation
90 Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity);
91
92 // offset position should be root part position - part2.absolute position.
93 Assert.That(part2.OffsetPosition == new Vector3(-10, -10, -10));
94
95 float roll = 0;
96 float pitch = 0;
97 float yaw = 0;
98
99 // There's a euler anomoly at 180, 0, 0 so expect 180 to turn into -180.
100 part1.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
101 Vector3 rotEuler1 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG);
102
103 if (debugtest)
104 System.Console.WriteLine(rotEuler1);
105
106 part2.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
107 Vector3 rotEuler2 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG);
108
109 if (debugtest)
110 System.Console.WriteLine(rotEuler2);
111
112 Assert.That(rotEuler2.ApproxEquals(new Vector3(-180, 0, 0), 0.001f) || rotEuler2.ApproxEquals(new Vector3(180, 0, 0), 0.001f));
113
114 // Delink part 2
115 grp1.DelinkFromGroup(part2.LocalId);
116
117 if (debugtest)
118 System.Console.WriteLine("Group2: Prim2: OffsetPosition:{0}, OffsetRotation:{1}", part2.AbsolutePosition, part2.RotationOffset);
119
120 Assert.That(grp1.Children.Count, Is.EqualTo(1), "Group 1 still contained part2 after delink.");
121 Assert.That(part2.AbsolutePosition == Vector3.Zero);
122 }
123
124 [Test]
125 public void TestLinkDelink2groups4SceneObjects()
126 {
127 bool debugtest = false;
128
129 Scene scene = SceneSetupHelpers.SetupScene();
130 SceneObjectPart part1 = SceneSetupHelpers.AddSceneObject(scene);
131 SceneObjectGroup grp1 = part1.ParentGroup;
132 SceneObjectPart part2 = SceneSetupHelpers.AddSceneObject(scene);
133 SceneObjectGroup grp2 = part2.ParentGroup;
134 SceneObjectPart part3 = SceneSetupHelpers.AddSceneObject(scene);
135 SceneObjectGroup grp3 = part3.ParentGroup;
136 SceneObjectPart part4 = SceneSetupHelpers.AddSceneObject(scene);
137 SceneObjectGroup grp4 = part4.ParentGroup;
138
139 grp1.AbsolutePosition = new Vector3(10, 10, 10);
140 grp2.AbsolutePosition = Vector3.Zero;
141 grp3.AbsolutePosition = new Vector3(20, 20, 20);
142 grp4.AbsolutePosition = new Vector3(40, 40, 40);
143
144 // <90,0,0>
145 grp1.Rotation = (Quaternion.CreateFromEulers(90 * Utils.DEG_TO_RAD, 0, 0));
146
147 // <180,0,0>
148 grp2.UpdateGroupRotation(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0));
149
150 // <270,0,0>
151 grp3.Rotation = (Quaternion.CreateFromEulers(270 * Utils.DEG_TO_RAD, 0, 0));
152
153 // <0,90,0>
154 grp4.UpdateGroupRotation(Quaternion.CreateFromEulers(0, 90 * Utils.DEG_TO_RAD, 0));
155
156 // Required for linking
157 grp1.RootPart.UpdateFlag = 0;
158 grp2.RootPart.UpdateFlag = 0;
159 grp3.RootPart.UpdateFlag = 0;
160 grp4.RootPart.UpdateFlag = 0;
161
162 // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated.
163 grp1.LinkToGroup(grp2);
164
165 // Link grp4 to grp3.
166 grp3.LinkToGroup(grp4);
167
168 // At this point we should have 4 parts total in two groups.
169 Assert.That(grp1.Children.Count == 2);
170 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link.");
171 Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained parts after delink.");
172 Assert.That(grp3.Children.Count == 2);
173 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link.");
174 Assert.That(grp4.Children.Count, Is.EqualTo(0), "Group 4 still contained parts after delink.");
175
176 if (debugtest)
177 {
178 System.Console.WriteLine("--------After Link-------");
179 System.Console.WriteLine("Group1: parts: {0}", grp1.Children.Count);
180 System.Console.WriteLine("Group1: Pos:{0}, Rot:{1}", grp1.AbsolutePosition, grp1.Rotation);
181 System.Console.WriteLine("Group1: Prim1: OffsetPosition:{0}, OffsetRotation:{1}", part1.OffsetPosition, part1.RotationOffset);
182 System.Console.WriteLine("Group1: Prim2: OffsetPosition:{0}, OffsetRotation:{1}", part2.OffsetPosition, part2.RotationOffset);
183
184 System.Console.WriteLine("Group3: parts: {0}", grp3.Children.Count);
185 System.Console.WriteLine("Group3: Pos:{0}, Rot:{1}", grp3.AbsolutePosition, grp3.Rotation);
186 System.Console.WriteLine("Group3: Prim1: OffsetPosition:{0}, OffsetRotation:{1}", part3.OffsetPosition, part3.RotationOffset);
187 System.Console.WriteLine("Group3: Prim2: OffsetPosition:{0}, OffsetRotation:{1}", part4.OffsetPosition, part4.RotationOffset);
188 }
189
190 // Required for linking
191 grp1.RootPart.UpdateFlag = 0;
192 grp3.RootPart.UpdateFlag = 0;
193
194 // root part should have no offset position or rotation
195 Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity);
196
197 // offset position should be root part position - part2.absolute position.
198 Assert.That(part2.OffsetPosition == new Vector3(-10, -10, -10));
199
200 float roll = 0;
201 float pitch = 0;
202 float yaw = 0;
203
204 // There's a euler anomoly at 180, 0, 0 so expect 180 to turn into -180.
205 part1.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
206 Vector3 rotEuler1 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG);
207
208 if (debugtest)
209 System.Console.WriteLine(rotEuler1);
210
211 part2.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
212 Vector3 rotEuler2 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG);
213
214 if (debugtest)
215 System.Console.WriteLine(rotEuler2);
216
217 Assert.That(rotEuler2.ApproxEquals(new Vector3(-180, 0, 0), 0.001f) || rotEuler2.ApproxEquals(new Vector3(180, 0, 0), 0.001f));
218
219 // Now we're linking the first group to the third group. This will make the first group child parts of the third one.
220 grp3.LinkToGroup(grp1);
221
222 // Delink parts 2 and 3
223 grp3.DelinkFromGroup(part2.LocalId);
224 grp3.DelinkFromGroup(part3.LocalId);
225
226 if (debugtest)
227 {
228 System.Console.WriteLine("--------After De-Link-------");
229 System.Console.WriteLine("Group1: parts: {0}", grp1.Children.Count);
230 System.Console.WriteLine("Group1: Pos:{0}, Rot:{1}", grp1.AbsolutePosition, grp1.Rotation);
231 System.Console.WriteLine("Group1: Prim1: OffsetPosition:{0}, OffsetRotation:{1}", part1.OffsetPosition, part1.RotationOffset);
232 System.Console.WriteLine("NoGroup: Prim2: AbsolutePosition:{0}, OffsetRotation:{1}", part2.AbsolutePosition, part2.RotationOffset);
233
234 System.Console.WriteLine("Group3: parts: {0}", grp3.Children.Count);
235 System.Console.WriteLine("Group3: Pos:{0}, Rot:{1}", grp3.AbsolutePosition, grp3.Rotation);
236 System.Console.WriteLine("Group3: Prim1: OffsetPosition:{0}, OffsetRotation:{1}", part3.OffsetPosition, part3.RotationOffset);
237 System.Console.WriteLine("Group3: Prim2: OffsetPosition:{0}, OffsetRotation:{1}", part4.OffsetPosition, part4.RotationOffset);
238 }
239
240 Assert.That(part2.AbsolutePosition == Vector3.Zero);
241 Assert.That(part4.OffsetPosition == new Vector3(20, 20, 20));
242 Quaternion compareQuaternion = new Quaternion(0, 0.7071068f, 0, 0.7071068f);
243 Assert.That((part4.RotationOffset.X - compareQuaternion.X < 0.00003)
244 && (part4.RotationOffset.Y - compareQuaternion.Y < 0.00003)
245 && (part4.RotationOffset.Z - compareQuaternion.Z < 0.00003)
246 && (part4.RotationOffset.W - compareQuaternion.W < 0.00003));
247 }
248 }
249}
diff --git a/OpenSim/Region/Environment/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Environment/Scenes/Tests/ScenePresenceTests.cs
deleted file mode 100644
index d66c365..0000000
--- a/OpenSim/Region/Environment/Scenes/Tests/ScenePresenceTests.cs
+++ /dev/null
@@ -1,292 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 Nini.Config;
29using System;
30using System.Collections.Generic;
31using System.Text;
32using NUnit.Framework;
33using NUnit.Framework.SyntaxHelpers;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications;
37using OpenSim.Region.Environment.Scenes;
38using OpenSim.Region.Environment.Interfaces;
39using OpenSim.Region.Environment.Modules.Communications.Local;
40using OpenSim.Region.Environment.Modules.World.Serialiser;
41using OpenSim.Tests.Common.Mock;
42using OpenSim.Tests.Common.Setup;
43
44namespace OpenSim.Region.Environment.Scenes.Tests
45{
46 /// <summary>
47 /// Scene presence tests
48 /// </summary>
49 [TestFixture]
50 public class ScenePresenceTests
51 {
52 public Scene scene, scene2, scene3;
53 public UUID agent1, agent2, agent3;
54 public static Random random;
55 public ulong region1,region2,region3;
56 public CommunicationsManager cm;
57 public AgentCircuitData acd1;
58 public SceneObjectGroup sog1, sog2, sog3;
59 public TestClient testclient;
60
61 [TestFixtureSetUp]
62 public void Init()
63 {
64 cm = new TestCommunicationsManager();
65 scene = SceneSetupHelpers.SetupScene("Neighbour x", UUID.Random(), 1000, 1000, cm);
66 scene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000, cm);
67 scene3 = SceneSetupHelpers.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000, cm);
68
69 agent1 = UUID.Random();
70 agent2 = UUID.Random();
71 agent3 = UUID.Random();
72 random = new Random();
73 sog1 = NewSOG(UUID.Random(), scene, agent1);
74 sog2 = NewSOG(UUID.Random(), scene, agent1);
75 sog3 = NewSOG(UUID.Random(), scene, agent1);
76
77 //ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
78 region1 = scene.RegionInfo.RegionHandle;
79 region2 = scene2.RegionInfo.RegionHandle;
80 region3 = scene3.RegionInfo.RegionHandle;
81 }
82
83 /// <summary>
84 /// Test adding a root agent to a scene. Doesn't yet actually complete crossing the agent into the scene.
85 /// </summary>
86 [Test]
87 public void T010_TestAddRootAgent()
88 {
89 string firstName = "testfirstname";
90
91 AgentCircuitData agent = new AgentCircuitData();
92 agent.AgentID = agent1;
93 agent.firstname = firstName;
94 agent.lastname = "testlastname";
95 agent.SessionID = UUID.Zero;
96 agent.SecureSessionID = UUID.Zero;
97 agent.circuitcode = 123;
98 agent.BaseFolder = UUID.Zero;
99 agent.InventoryFolder = UUID.Zero;
100 agent.startpos = Vector3.Zero;
101 agent.CapsPath = GetRandomCapsObjectPath();
102
103 scene.NewUserConnection(agent);
104 testclient = new TestClient(agent, scene);
105 scene.AddNewClient(testclient);
106
107 ScenePresence presence = scene.GetScenePresence(agent1);
108
109 Assert.That(presence, Is.Not.Null, "presence is null");
110 Assert.That(presence.Firstname, Is.EqualTo(firstName), "First name not same");
111 acd1 = agent;
112 }
113
114 /// <summary>
115 /// Test removing an uncrossed root agent from a scene.
116 /// </summary>
117 [Test]
118 public void T011_TestRemoveRootAgent()
119 {
120 scene.RemoveClient(agent1);
121
122 ScenePresence presence = scene.GetScenePresence(agent1);
123
124 Assert.That(presence, Is.Null, "presence is not null");
125 }
126
127 [Test]
128 public void T012_TestAddNeighbourRegion()
129 {
130 SceneSetupHelpers.AddRootAgent(scene,agent1);
131
132 ScenePresence presence = scene.GetScenePresence(agent1);
133
134 string cap = presence.ControllingClient.RequestClientInfo().CapsPath;
135
136 presence.AddNeighbourRegion(region2, cap);
137 presence.AddNeighbourRegion(region3, cap);
138
139 List<ulong> neighbours = presence.GetKnownRegionList();
140
141 Assert.That(neighbours.Count, Is.EqualTo(2));
142 }
143
144 [Test]
145 public void T013_TestRemoveNeighbourRegion()
146 {
147 ScenePresence presence = scene.GetScenePresence(agent1);
148 presence.RemoveNeighbourRegion(region3);
149
150 List<ulong> neighbours = presence.GetKnownRegionList();
151 Assert.That(neighbours.Count,Is.EqualTo(1));
152 /*
153 presence.MakeChildAgent;
154 presence.MakeRootAgent;
155 CompleteAvatarMovement
156 */
157 }
158
159 [Test]
160 public void T020_TestMakeRootAgent()
161 {
162 ScenePresence presence = scene.GetScenePresence(agent1);
163 Assert.That(presence.IsChildAgent, Is.False, "Starts out as a root agent");
164
165 presence.MakeChildAgent();
166 Assert.That(presence.IsChildAgent, Is.True, "Did not change to child agent after MakeChildAgent");
167
168 // Accepts 0 but rejects Constants.RegionSize
169 Vector3 pos = new Vector3(0,Constants.RegionSize-1,0);
170 presence.MakeRootAgent(pos,true);
171 Assert.That(presence.IsChildAgent, Is.False, "Did not go back to root agent");
172 Assert.That(presence.AbsolutePosition, Is.EqualTo(pos), "Position is not the same one entered");
173 }
174
175 [Test]
176 public void T021_TestCrossToNewRegion()
177 {
178 // Adding child agent to region 1001
179 scene2.NewUserConnection(acd1);
180 scene2.AddNewClient(testclient);
181
182 ScenePresence presence = scene.GetScenePresence(agent1);
183 ScenePresence presence2 = scene2.GetScenePresence(agent1);
184
185 // Adding neighbour region caps info to presence2
186 string cap = presence.ControllingClient.RequestClientInfo().CapsPath;
187 presence2.AddNeighbourRegion(region1, cap);
188
189 Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region.");
190 Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region.");
191
192 // Cross to x+1
193 presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100);
194 scene.RegisterRegionWithGrid();
195 scene2.RegisterRegionWithGrid();
196 presence.Update();
197
198 Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected.");
199 Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent.");
200
201 // Cross Back
202 presence2.AbsolutePosition = new Vector3(-1, 3, 100);
203 presence2.Update();
204
205 Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected.");
206 Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again.");
207 }
208
209 [Test]
210 public void T030_TestAddAttachments()
211 {
212 ScenePresence presence = scene.GetScenePresence(agent1);
213
214 presence.AddAttachment(sog1);
215 presence.AddAttachment(sog2);
216 presence.AddAttachment(sog3);
217
218 Assert.That(presence.HasAttachments(), Is.True);
219 Assert.That(presence.ValidateAttachments(), Is.True);
220 }
221
222 [Test]
223 public void T031_RemoveAttachments()
224 {
225 ScenePresence presence = scene.GetScenePresence(agent1);
226 presence.RemoveAttachment(sog1);
227 presence.RemoveAttachment(sog2);
228 presence.RemoveAttachment(sog3);
229 Assert.That(presence.HasAttachments(), Is.False);
230 }
231
232 [Test]
233 public void T032_CrossAttachments()
234 {
235 ScenePresence presence = scene.GetScenePresence(agent1);
236 ScenePresence presence2 = scene2.GetScenePresence(agent1);
237 presence2.AddAttachment(sog1);
238 presence2.AddAttachment(sog2);
239
240 IRegionModule serialiser = new SerialiserModule();
241 SceneSetupHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser);
242 SceneSetupHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser);
243
244 Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross");
245
246 Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful");
247 Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted");
248 Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects");
249 }
250
251 public static string GetRandomCapsObjectPath()
252 {
253 UUID caps = UUID.Random();
254 string capsPath = caps.ToString();
255 capsPath = capsPath.Remove(capsPath.Length - 4, 4);
256 return capsPath;
257 }
258
259 private SceneObjectGroup NewSOG(UUID uuid, Scene scene, UUID agent)
260 {
261 SceneObjectPart sop = new SceneObjectPart();
262 sop.Name = RandomName();
263 sop.Description = RandomName();
264 sop.Text = RandomName();
265 sop.SitName = RandomName();
266 sop.TouchName = RandomName();
267 sop.UUID = uuid;
268 sop.Shape = PrimitiveBaseShape.Default;
269 sop.Shape.State = 1;
270 sop.OwnerID = agent;
271
272 SceneObjectGroup sog = new SceneObjectGroup();
273 sog.SetScene(scene);
274 sog.SetRootPart(sop);
275
276 return sog;
277 }
278
279 private static string RandomName()
280 {
281 StringBuilder name = new StringBuilder();
282 int size = random.Next(5,12);
283 char ch ;
284 for (int i=0; i<size; i++)
285 {
286 ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))) ;
287 name.Append(ch);
288 }
289 return name.ToString();
290 }
291 }
292}
diff --git a/OpenSim/Region/Environment/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Environment/Scenes/Tests/StandaloneTeleportTests.cs
deleted file mode 100644
index 221d97f..0000000
--- a/OpenSim/Region/Environment/Scenes/Tests/StandaloneTeleportTests.cs
+++ /dev/null
@@ -1,105 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 Nini.Config;
29using NUnit.Framework;
30using NUnit.Framework.SyntaxHelpers;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34using OpenSim.Region.Environment;
35using OpenSim.Region.Environment.Interfaces;
36using OpenSim.Region.Environment.Modules.Communications.REST;
37using OpenSim.Tests.Common.Mock;
38using OpenSim.Tests.Common.Setup;
39
40namespace OpenSim.Region.Environment.Scenes.Tests
41{
42 /// <summary>
43 /// Teleport tests in a standalone OpenSim
44 /// </summary>
45 [TestFixture]
46 public class StandaloneTeleportTests
47 {
48 /// <summary>
49 /// Test a teleport between two regions that are not neighbours and do not share any neighbours in common.
50 /// </summary>
51 /// Does not yet do what is says on the tin.
52 [Test]
53 public void TestSimpleNotNeighboursTeleport()
54 {
55 //log4net.Config.XmlConfigurator.Configure();
56
57 UUID sceneAId = UUID.Parse("00000000-0000-0000-0000-000000000100");
58 UUID sceneBId = UUID.Parse("00000000-0000-0000-0000-000000000200");
59 CommunicationsManager cm = new TestCommunicationsManager();
60
61 // shared module
62 IRegionModule interregionComms = new RESTInterregionComms();
63
64 Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000, cm);
65 SceneSetupHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms);
66 sceneA.RegisterRegionWithGrid();
67
68 Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010, cm);
69 SceneSetupHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms);
70 sceneB.RegisterRegionWithGrid();
71
72 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000041");
73 TestClient client = SceneSetupHelpers.AddRootAgent(sceneA, agentId);
74
75 ICapabilitiesModule sceneACapsModule = sceneA.RequestModuleInterface<ICapabilitiesModule>();
76
77 Assert.That(
78 sceneACapsModule.GetCapsPath(agentId),
79 Is.EqualTo(client.CapsSeedUrl),
80 "Incorrect caps object path set up in sceneA");
81
82 // FIXME: This is a hack to get the test working - really the normal OpenSim mechanisms should be used.
83 client.TeleportTargetScene = sceneB;
84 client.Teleport(sceneB.RegionInfo.RegionHandle, new Vector3(100, 100, 100), new Vector3(40, 40, 40));
85
86 Assert.That(sceneB.GetScenePresence(agentId), Is.Not.Null, "Client does not have an agent in sceneB");
87 Assert.That(sceneA.GetScenePresence(agentId), Is.Null, "Client still had an agent in sceneA");
88
89 ICapabilitiesModule sceneBCapsModule = sceneB.RequestModuleInterface<ICapabilitiesModule>();
90
91 // Temporary assertion - caps url construction should at least be doable through a method.
92 Assert.That(
93 "http://" + sceneB.RegionInfo.ExternalHostName + ":" + sceneB.RegionInfo.HttpPort + "/CAPS/" + sceneBCapsModule.GetCapsPath(agentId) + "0000/",
94 Is.EqualTo(client.CapsSeedUrl),
95 "Incorrect caps object path set up in sceneB");
96
97 // This assertion will currently fail since we don't remove the caps paths when no longer needed
98 //Assert.That(sceneACapsModule.GetCapsPath(agentId), Is.Null, "sceneA still had a caps object path");
99
100 // TODO: Check that more of everything is as it should be
101
102 // TODO: test what happens if we try to teleport to a region that doesn't exist
103 }
104 }
105} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Scenes/UndoState.cs b/OpenSim/Region/Environment/Scenes/UndoState.cs
deleted file mode 100644
index d828d8d..0000000
--- a/OpenSim/Region/Environment/Scenes/UndoState.cs
+++ /dev/null
@@ -1,116 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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 OpenMetaverse;
29
30namespace OpenSim.Region.Environment.Scenes
31{
32 public class UndoState
33 {
34 public Vector3 Position = Vector3.Zero;
35 public Vector3 Scale = Vector3.Zero;
36 public Quaternion Rotation = Quaternion.Identity;
37
38 public UndoState(Vector3 pos, Quaternion rot, Vector3 scale)
39 {
40 Position = pos;
41 Rotation = rot;
42 Scale = scale;
43 }
44
45 public UndoState(SceneObjectPart part)
46 {
47 if (part != null)
48 {
49 if (part.ParentID == 0)
50 {
51 Position = part.AbsolutePosition;
52 Rotation = part.RotationOffset;
53
54 }
55 else
56 {
57 Position = part.GroupPosition;
58 Rotation = part.RotationOffset;
59 Scale = part.Shape.Scale;
60
61 }
62 }
63 }
64
65 public bool Compare(SceneObjectPart part)
66 {
67 if (part != null)
68 {
69 if (part.ParentID == 0)
70 {
71 if (Position == part.AbsolutePosition && Rotation == part.RotationOffset)
72 return true;
73 else
74 return false;
75 }
76 else
77 {
78 if (Position == part.GroupPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale)
79 return true;
80 else
81 return false;
82
83 }
84 }
85 return false;
86 }
87
88 public void PlaybackState(SceneObjectPart part)
89 {
90 if (part != null)
91 {
92 part.Undoing = true;
93
94 if (part.ParentID == 0)
95 {
96 part.ParentGroup.AbsolutePosition = Position;
97 part.UpdateRotation(Rotation);
98 part.ParentGroup.ScheduleGroupForTerseUpdate();
99 }
100 else
101 {
102 part.OffsetPosition = Position;
103 part.UpdateRotation(Rotation);
104 part.Resize(Scale);
105 part.ScheduleTerseUpdate();
106 }
107 part.Undoing = false;
108
109 }
110 }
111
112 public UndoState()
113 {
114 }
115 }
116}