aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs338
1 files changed, 338 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
new file mode 100644
index 0000000..3614686
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -0,0 +1,338 @@
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/*
29using System;
30using System.Collections.Generic;
31using System.Threading;
32using libsecondlife;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Data.MySQLMapper;
37using OpenSim.Region.Environment.Interfaces;
38using OpenSim.Region.Environment.Scenes;
39using OpenSim.Data.Base;
40
41namespace OpenSim.Region.Environment.Modules
42{
43 public class AvatarFactoryModule : IAvatarFactory
44 {
45 private Scene m_scene = null;
46 private readonly Dictionary<LLUUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<LLUUID, AvatarAppearance>();
47
48 private bool m_enablePersist = false;
49 private string m_connectionString;
50 private bool m_configured = false;
51 private BaseDatabaseConnector m_databaseMapper;
52 private AppearanceTableMapper m_appearanceMapper;
53
54 private Dictionary<LLUUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<LLUUID, EventWaitHandle>();
55 private object m_syncLock = new object();
56
57 public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
58 {
59
60 //should only let one thread at a time do this part
61 EventWaitHandle waitHandle = null;
62 bool fetchInProgress = false;
63 lock (m_syncLock)
64 {
65 appearance = CheckCache(avatarId);
66 if (appearance != null)
67 {
68 return true;
69 }
70
71 //not in cache so check to see if another thread is already fetching it
72 if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
73 {
74 fetchInProgress = true;
75 }
76 else
77 {
78 fetchInProgress = false;
79
80 //no thread already fetching this appearance, so add a wait handle to list
81 //for any following threads that want the same appearance
82 waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
83 m_fetchesInProgress.Add(avatarId, waitHandle);
84 }
85 }
86
87 if (fetchInProgress)
88 {
89 waitHandle.WaitOne();
90 appearance = CheckCache(avatarId);
91 if (appearance != null)
92 {
93 waitHandle = null;
94 return true;
95 }
96 else
97 {
98 waitHandle = null;
99 return false;
100 }
101 }
102 else
103 {
104 Thread.Sleep(5000);
105
106 //this is the first thread to request this appearance
107 //so let it check the db and if not found then create a default appearance
108 //and add that to the cache
109 appearance = CheckDatabase(avatarId);
110 if (appearance != null)
111 {
112 //appearance has now been added to cache so lets pulse any waiting threads
113 lock (m_syncLock)
114 {
115 m_fetchesInProgress.Remove(avatarId);
116 waitHandle.Set();
117 }
118 // waitHandle.Close();
119 waitHandle = null;
120 return true;
121 }
122
123 //not found a appearance for the user, so create a new default one
124 appearance = CreateDefault(avatarId);
125 if (appearance != null)
126 {
127 //update database
128 if (m_enablePersist)
129 {
130 m_appearanceMapper.Add(avatarId.UUID, appearance);
131 }
132
133 //add appearance to dictionary cache
134 lock (m_avatarsAppearance)
135 {
136 m_avatarsAppearance[avatarId] = appearance;
137 }
138
139 //appearance has now been added to cache so lets pulse any waiting threads
140 lock (m_syncLock)
141 {
142 m_fetchesInProgress.Remove(avatarId);
143 waitHandle.Set();
144 }
145 // waitHandle.Close();
146 waitHandle = null;
147 return true;
148 }
149 else
150 {
151 //something went wrong, so release the wait handle and remove it
152 //all waiting threads will fail to find cached appearance
153 //but its better for them to fail than wait for ever
154 lock (m_syncLock)
155 {
156 m_fetchesInProgress.Remove(avatarId);
157 waitHandle.Set();
158 }
159 //waitHandle.Close();
160 waitHandle = null;
161 return false;
162 }
163 }
164 }
165
166 private AvatarAppearance CreateDefault(LLUUID avatarId)
167 {
168 AvatarAppearance appearance = null;
169 AvatarWearable[] wearables;
170 byte[] visualParams;
171 GetDefaultAvatarAppearance(out wearables, out visualParams);
172 appearance = new AvatarAppearance(avatarId, wearables, visualParams);
173
174 return appearance;
175 }
176
177 private AvatarAppearance CheckDatabase(LLUUID avatarId)
178 {
179 AvatarAppearance appearance = null;
180 if (m_enablePersist)
181 {
182 if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance))
183 {
184 appearance.VisualParams = GetDefaultVisualParams();
185 appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry();
186 lock (m_avatarsAppearance)
187 {
188 m_avatarsAppearance[avatarId] = appearance;
189 }
190 }
191 }
192 return appearance;
193 }
194
195 private AvatarAppearance CheckCache(LLUUID avatarId)
196 {
197 AvatarAppearance appearance = null;
198 lock (m_avatarsAppearance)
199 {
200 if (m_avatarsAppearance.ContainsKey(avatarId))
201 {
202 appearance = m_avatarsAppearance[avatarId];
203 }
204 }
205 return appearance;
206 }
207
208 public void Initialise(Scene scene, IConfigSource source)
209 {
210 scene.RegisterModuleInterface<IAvatarFactory>(this);
211 scene.EventManager.OnNewClient += NewClient;
212
213 if (m_scene == null)
214 {
215 m_scene = scene;
216 }
217
218 if (!m_configured)
219 {
220 m_configured = true;
221 try
222 {
223 m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false);
224 m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", "");
225 }
226 catch (Exception)
227 {
228 }
229 if (m_enablePersist)
230 {
231 m_databaseMapper = new MySQLDatabaseMapper(m_connectionString);
232 m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance");
233 }
234 }
235 }
236
237 public void PostInitialise()
238 {
239 }
240
241 public void Close()
242 {
243 }
244
245 public string Name
246 {
247 get { return "Default Avatar Factory"; }
248 }
249
250 public bool IsSharedModule
251 {
252 get { return true; }
253 }
254
255 public void NewClient(IClientAPI client)
256 {
257 client.OnAvatarNowWearing += AvatarIsWearing;
258 }
259
260 public void RemoveClient(IClientAPI client)
261 {
262 // client.OnAvatarNowWearing -= AvatarIsWearing;
263 }
264
265 public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
266 {
267 IClientAPI clientView = (IClientAPI)sender;
268 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
269 if (profile != null)
270 {
271 if (profile.RootFolder != null)
272 {
273 if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
274 {
275 AvatarAppearance avatAppearance = null;
276 lock (m_avatarsAppearance)
277 {
278 avatAppearance = m_avatarsAppearance[clientView.AgentId];
279 }
280
281 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
282 {
283 if (wear.Type < 13)
284 {
285 if (wear.ItemID == LLUUID.Zero)
286 {
287 avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero;
288 avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero;
289
290 UpdateDatabase(clientView.AgentId, avatAppearance);
291 }
292 else
293 {
294 LLUUID assetId;
295
296 InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID);
297 if (baseItem != null)
298 {
299 assetId = baseItem.assetID;
300 avatAppearance.Wearables[wear.Type].AssetID = assetId;
301 avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
302
303 UpdateDatabase(clientView.AgentId, avatAppearance);
304 }
305 }
306 }
307 }
308 }
309 }
310 }
311 }
312
313 public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance)
314 {
315 if (m_enablePersist)
316 {
317 m_appearanceMapper.Update(userID.UUID, avatAppearance);
318 }
319 }
320
321 public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
322 {
323 visualParams = GetDefaultVisualParams();
324 wearables = AvatarWearable.DefaultWearables;
325 }
326
327 private static byte[] GetDefaultVisualParams()
328 {
329 byte[] visualParams;
330 visualParams = new byte[218];
331 for (int i = 0; i < 218; i++)
332 {
333 visualParams[i] = 100;
334 }
335 return visualParams;
336 }
337 }
338}*/