aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs')
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs171
1 files changed, 171 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs b/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs
new file mode 100644
index 0000000..2661522
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs
@@ -0,0 +1,171 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Reflection;
31using System.Text;
32using System.Collections.Generic;
33using System.Threading;
34
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim;
38using OpenSim.Region;
39using OpenSim.Region.Framework;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Framework;
43using OpenSim.Services.Interfaces;
44//using OpenSim.Framework.Capabilities;
45using Nini.Config;
46using log4net;
47using OSDMap = OpenMetaverse.StructuredData.OSDMap;
48using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
49
50namespace OpenSim.Region.OptionalModules.ViewerSupport
51{
52 public class SimulatorFeaturesHelper
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private IEntityTransferModule m_TransferModule;
57 private Scene m_scene;
58
59 private struct RegionSend {
60 public UUID region;
61 public bool send;
62 };
63 // Using a static cache so that we don't have to perform the time-consuming tests
64 // in ShouldSend on Extra SimFeatures that go on the same response but come from
65 // different modules.
66 // This cached is indexed on the agentID and maps to a list of regions
67 private static ExpiringCache<UUID, List<RegionSend>> m_Cache = new ExpiringCache<UUID, List<RegionSend>>();
68 private const double TIMEOUT = 1.0; // time in cache
69
70 public SimulatorFeaturesHelper(Scene scene, IEntityTransferModule et)
71 {
72 m_scene = scene;
73 m_TransferModule = et;
74 }
75
76 public bool ShouldSend(UUID agentID)
77 {
78 List<RegionSend> rsendlist;
79 RegionSend rsend;
80 if (m_Cache.TryGetValue(agentID, out rsendlist))
81 {
82 rsend = rsendlist.Find(r => r.region == m_scene.RegionInfo.RegionID);
83 if (rsend.region != UUID.Zero) // Found it
84 {
85 return rsend.send;
86 }
87 }
88
89 // Relatively complex logic for deciding whether to send the extra SimFeature or not.
90 // This is because the viewer calls this cap to all sims that it knows about,
91 // including the departing sims and non-neighbors (those that are cached).
92 rsend.region = m_scene.RegionInfo.RegionID;
93 rsend.send = false;
94 IClientAPI client = null;
95 int counter = 200;
96
97 // Let's wait a little to see if we get a client here
98 while (!m_scene.TryGetClient(agentID, out client) && counter-- > 0)
99 Thread.Sleep(50);
100
101 if (client != null)
102 {
103 ScenePresence sp = WaitGetScenePresence(agentID);
104
105 if (sp != null)
106 {
107 // On the receiving region, the call to this cap may arrive before
108 // the agent is root. Make sure we only proceed from here when the agent
109 // has been made root
110 counter = 200;
111 while ((sp.IsInTransit || sp.IsChildAgent) && counter-- > 0)
112 {
113 Thread.Sleep(50);
114 }
115
116 // The viewer calls this cap on the departing sims too. Make sure
117 // that we only proceed after the agent is not in transit anymore.
118 // The agent must be root and not going anywhere
119 if (!sp.IsChildAgent && !m_TransferModule.IsInTransit(agentID))
120 rsend.send = true;
121
122 }
123 }
124 //else
125 // m_log.DebugFormat("[XXX]: client is null");
126
127
128 if (rsendlist == null)
129 {
130 rsendlist = new List<RegionSend>();
131 m_Cache.AddOrUpdate(agentID, rsendlist, TIMEOUT);
132 }
133 rsendlist.Add(rsend);
134
135 return rsend.send;
136 }
137
138 public int UserLevel(UUID agentID)
139 {
140 int level = 0;
141 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
142 if (account != null)
143 level = account.UserLevel;
144
145 return level;
146 }
147
148 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
149 {
150 int ntimes = 20;
151 ScenePresence sp = null;
152 while ((sp = m_scene.GetScenePresence(agentID)) == null && (ntimes-- > 0))
153 Thread.Sleep(1000);
154
155 if (sp == null)
156 m_log.WarnFormat(
157 "[XXX]: Did not find presence with id {0} in {1} before timeout",
158 agentID, m_scene.RegionInfo.RegionName);
159 else
160 {
161 ntimes = 10;
162 while (sp.IsInTransit && (ntimes-- > 0))
163 Thread.Sleep(1000);
164 }
165
166 return sp;
167 }
168
169 }
170
171}