aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs279
1 files changed, 80 insertions, 199 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 9433cf6..30e9f95 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -25,142 +25,47 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28/*
29using System; 28using System;
30using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31
31using System.Threading; 32using System.Threading;
32using OpenMetaverse; 33using OpenMetaverse;
34using log4net;
33using Nini.Config; 35using Nini.Config;
36using OpenSim.Data.Base;
34using OpenSim.Framework; 37using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache; 38using OpenSim.Framework.Communications.Cache;
36using OpenSim.Data.MySQLMapper;
37using OpenSim.Region.Environment.Interfaces; 39using OpenSim.Region.Environment.Interfaces;
38using OpenSim.Region.Environment.Scenes; 40using OpenSim.Region.Environment.Scenes;
39using OpenSim.Data.Base;
40 41
41namespace OpenSim.Region.Environment.Modules 42namespace OpenSim.Region.Environment.Modules.Avatar.AvatarFactory
42{ 43{
43 public class AvatarFactoryModule : IAvatarFactory 44 public class AvatarFactoryModule : IAvatarFactory, IRegionModule
44 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private Scene m_scene = null; 47 private Scene m_scene = null;
46 private readonly Dictionary<UUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<UUID, AvatarAppearance>(); 48 private static readonly AvatarAppearance def = new 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<UUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<UUID, EventWaitHandle>();
55 private object m_syncLock = new object();
56 49
57 public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance) 50 public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance)
58 { 51 {
59 52 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(avatarId);
60 //should only let one thread at a time do this part 53 //if ((profile != null) && (profile.RootFolder != null))
61 EventWaitHandle waitHandle = null; 54 if (profile != null)
62 bool fetchInProgress = false;
63 lock (m_syncLock)
64 { 55 {
65 appearance = CheckCache(avatarId); 56 appearance = m_scene.CommsManager.AvatarService.GetUserAppearance(avatarId);
66 if (appearance != null) 57 if (appearance != null)
67 { 58 {
59 //SetAppearanceAssets(profile, ref appearance);
60 m_log.InfoFormat("[APPEARANCE] found : {0}", appearance.ToString());
68 return true; 61 return true;
69 } 62 }
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 } 63 }
86 64
87 if (fetchInProgress) 65 appearance = CreateDefault(avatarId);
88 { 66 m_log.InfoFormat("[APPEARANCE] appearance not found for {0}, creating default", avatarId.ToString());
89 waitHandle.WaitOne(); 67 return false;
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 68
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 } 69 }
165 70
166 private AvatarAppearance CreateDefault(UUID avatarId) 71 private AvatarAppearance CreateDefault(UUID avatarId)
@@ -174,37 +79,6 @@ namespace OpenSim.Region.Environment.Modules
174 return appearance; 79 return appearance;
175 } 80 }
176 81
177 private AvatarAppearance CheckDatabase(UUID 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(UUID 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) 82 public void Initialise(Scene scene, IConfigSource source)
209 { 83 {
210 scene.RegisterModuleInterface<IAvatarFactory>(this); 84 scene.RegisterModuleInterface<IAvatarFactory>(this);
@@ -215,23 +89,6 @@ namespace OpenSim.Region.Environment.Modules
215 m_scene = scene; 89 m_scene = scene;
216 } 90 }
217 91
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 } 92 }
236 93
237 public void PostInitialise() 94 public void PostInitialise()
@@ -262,59 +119,78 @@ namespace OpenSim.Region.Environment.Modules
262 // client.OnAvatarNowWearing -= AvatarIsWearing; 119 // client.OnAvatarNowWearing -= AvatarIsWearing;
263 } 120 }
264 121
265 public void AvatarIsWearing(Object sender, AvatarWearingArgs e) 122
123 public void SetAppearanceAssets(CachedUserInfo profile, ref AvatarAppearance appearance)
266 { 124 {
267 IClientAPI clientView = (IClientAPI)sender; 125 if (profile.RootFolder != null)
268 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
269 if (profile != null)
270 { 126 {
271 if (profile.RootFolder != null) 127 for (int i = 0; i < 13; i++)
272 { 128 {
273 if (m_avatarsAppearance.ContainsKey(clientView.AgentId)) 129 if (appearance.Wearables[i].ItemID == UUID.Zero)
274 { 130 {
275 AvatarAppearance avatAppearance = null; 131 appearance.Wearables[i].AssetID = UUID.Zero;
276 lock (m_avatarsAppearance) 132 }
133 else
134 {
135 // UUID assetId;
136
137 InventoryItemBase baseItem = profile.RootFolder.FindItem(appearance.Wearables[i].ItemID);
138
139 if (baseItem != null)
277 { 140 {
278 avatAppearance = m_avatarsAppearance[clientView.AgentId]; 141 appearance.Wearables[i].AssetID = baseItem.AssetID;
279 } 142 }
280 143 else
281 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
282 { 144 {
283 if (wear.Type < 13) 145 m_log.ErrorFormat("[APPEARANCE] Can't find inventory item {0}, setting to default", appearance.Wearables[i].ItemID);
284 { 146 appearance.Wearables[i].AssetID = def.Wearables[i].AssetID;
285 if (wear.ItemID == UUID.Zero)
286 {
287 avatAppearance.Wearables[wear.Type].ItemID = UUID.Zero;
288 avatAppearance.Wearables[wear.Type].AssetID = UUID.Zero;
289
290 UpdateDatabase(clientView.AgentId, avatAppearance);
291 }
292 else
293 {
294 UUID assetId;
295
296 InventoryItemBase baseItem = profile.RootFolder.FindItem(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 } 147 }
308 } 148 }
309 } 149 }
310 } 150 }
151 else
152 {
153 m_log.Error("[APPEARANCE] you have no inventory, appearance stuff isn't going to work");
154 }
311 } 155 }
312 156
313 public void UpdateDatabase(UUID userID, AvatarAppearance avatAppearance) 157 public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
314 { 158 {
315 if (m_enablePersist) 159 IClientAPI clientView = (IClientAPI)sender;
160 ScenePresence avatar = m_scene.GetScenePresence(clientView.AgentId);
161 if (avatar == null) {
162 m_log.Info("Avatar is child agent, ignoring AvatarIsWearing event");
163 return;
164 }
165
166 CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
167
168 AvatarAppearance avatAppearance = null;
169 if (!TryGetAvatarAppearance(clientView.AgentId, out avatAppearance)) {
170 m_log.Info("We didn't seem to find the appearance, falling back to ScenePresense");
171 avatAppearance = avatar.Appearance;
172 }
173 m_log.Info("Calling Avatar is Wearing");
174 if (profile != null)
316 { 175 {
317 m_appearanceMapper.Update(userID.Guid, avatAppearance); 176 if (profile.RootFolder != null)
177 {
178 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
179 {
180 if (wear.Type < 13)
181 {
182 avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
183 }
184 }
185 SetAppearanceAssets(profile, ref avatAppearance);
186
187 m_scene.CommsManager.AvatarService.UpdateUserAppearance(clientView.AgentId, avatAppearance);
188 avatar.Appearance = avatAppearance;
189 }
190 else
191 {
192 m_log.Error("Root Profile is null, we can't set the appearance");
193 }
318 } 194 }
319 } 195 }
320 196
@@ -324,6 +200,11 @@ namespace OpenSim.Region.Environment.Modules
324 wearables = AvatarWearable.DefaultWearables; 200 wearables = AvatarWearable.DefaultWearables;
325 } 201 }
326 202
203 public void UpdateDatabase(UUID user, AvatarAppearance appearance)
204 {
205 m_scene.CommsManager.AvatarService.UpdateUserAppearance(user, appearance);
206 }
207
327 private static byte[] GetDefaultVisualParams() 208 private static byte[] GetDefaultVisualParams()
328 { 209 {
329 byte[] visualParams; 210 byte[] visualParams;
@@ -335,4 +216,4 @@ namespace OpenSim.Region.Environment.Modules
335 return visualParams; 216 return visualParams;
336 } 217 }
337 } 218 }
338}*/ 219}