aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorDan Lake2011-10-19 14:41:44 -0700
committerDan Lake2011-10-19 14:41:44 -0700
commitda794f34a56f7c88904315ae538de8f3790e6891 (patch)
treeec15f9ad1a941441ab2c0cd24f50b7636bba7bce /OpenSim/Region
parentAdd "scripts stop" and "scripts start" console commands. (diff)
downloadopensim-SC_OLD-da794f34a56f7c88904315ae538de8f3790e6891.zip
opensim-SC_OLD-da794f34a56f7c88904315ae538de8f3790e6891.tar.gz
opensim-SC_OLD-da794f34a56f7c88904315ae538de8f3790e6891.tar.bz2
opensim-SC_OLD-da794f34a56f7c88904315ae538de8f3790e6891.tar.xz
Renamed and rearranged AvatarFactoryModule to eliminate redundant lookups of scene presence by client ID.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs616
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs (renamed from OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs)9
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs12
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs2
9 files changed, 319 insertions, 344 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index d4e1736..0c7c690 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -42,7 +42,7 @@ using OpenSim.Services.Interfaces;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 43namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
44{ 44{
45 public class AvatarFactoryModule : IAvatarFactory, IRegionModule 45 public class AvatarFactoryModule : IAvatarFactoryModule, IRegionModule
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private Scene m_scene = null; 48 private Scene m_scene = null;
@@ -57,12 +57,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
57 57
58 private object m_setAppearanceLock = new object(); 58 private object m_setAppearanceLock = new object();
59 59
60 #region RegionModule Members 60 #region IRegionModule
61 61
62 public void Initialise(Scene scene, IConfigSource config) 62 public void Initialise(Scene scene, IConfigSource config)
63 { 63 {
64 scene.RegisterModuleInterface<IAvatarFactory>(this); 64 scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
65 scene.EventManager.OnNewClient += NewClient; 65 scene.EventManager.OnNewClient += SubscribeToClientEvents;
66 66
67 IConfig sconfig = config.Configs["Startup"]; 67 IConfig sconfig = config.Configs["Startup"];
68 if (sconfig != null) 68 if (sconfig != null)
@@ -98,44 +98,201 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
98 get { return false; } 98 get { return false; }
99 } 99 }
100 100
101 public void NewClient(IClientAPI client) 101 private void SubscribeToClientEvents(IClientAPI client)
102 { 102 {
103 client.OnRequestWearables += SendWearables; 103 client.OnRequestWearables += Client_OnRequestWearables;
104 client.OnSetAppearance += SetAppearanceFromClient; 104 client.OnSetAppearance += Client_OnSetAppearance;
105 client.OnAvatarNowWearing += AvatarIsWearing; 105 client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
106 } 106 }
107 107
108 public void RemoveClient(IClientAPI client) 108 #endregion
109 { 109
110 // client.OnAvatarNowWearing -= AvatarIsWearing; 110 #region IAvatarFactoryModule
111 } 111
112 112 /// <summary>
113 #endregion 113 /// Set appearance data (texture asset IDs and slider settings)
114 114 /// </summary>
115 /// <param name="sp"></param>
116 /// <param name="texture"></param>
117 /// <param name="visualParam"></param>
118 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
119 {
120 // m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId);
121
122 // TODO: This is probably not necessary any longer, just assume the
123 // textureEntry set implies that the appearance transaction is complete
124 bool changed = false;
125
126 // Process the texture entry transactionally, this doesn't guarantee that Appearance is
127 // going to be handled correctly but it does serialize the updates to the appearance
128 lock (m_setAppearanceLock)
129 {
130 // Process the visual params, this may change height as well
131 if (visualParams != null)
132 {
133 // string[] visualParamsStrings = new string[visualParams.Length];
134 // for (int i = 0; i < visualParams.Length; i++)
135 // visualParamsStrings[i] = visualParams[i].ToString();
136 // m_log.DebugFormat(
137 // "[AVFACTORY]: Setting visual params for {0} to {1}",
138 // client.Name, string.Join(", ", visualParamsStrings));
139
140 float oldHeight = sp.Appearance.AvatarHeight;
141 changed = sp.Appearance.SetVisualParams(visualParams);
142
143 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
144 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
145 }
146
147 // Process the baked texture array
148 if (textureEntry != null)
149 {
150 changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
151
152 m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", sp.UUID);
153 Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(sp, false); });
154
155 // This appears to be set only in the final stage of the appearance
156 // update transaction. In theory, we should be able to do an immediate
157 // appearance send and save here.
158
159 }
160 // save only if there were changes, send no matter what (doesn't hurt to send twice)
161 if (changed)
162 QueueAppearanceSave(sp.ControllingClient.AgentId);
163
164 QueueAppearanceSend(sp.ControllingClient.AgentId);
165 }
166
167 // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString());
168 }
169
170 public bool SendAppearance(UUID agentId)
171 {
172 ScenePresence sp = m_scene.GetScenePresence(agentId);
173 if (sp == null)
174 {
175 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
176 return false;
177 }
178
179 // Send the appearance to everyone in the scene
180 sp.SendAppearanceToAllOtherAgents();
181
182 // Send animations back to the avatar as well
183 sp.Animator.SendAnimPack();
184
185 return true;
186 }
187
188 public Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId)
189 {
190 ScenePresence sp = m_scene.GetScenePresence(agentId);
191
192 if (sp == null)
193 return new Dictionary<BakeType, Primitive.TextureEntryFace>();
194
195 return GetBakedTextureFaces(sp);
196 }
197
198 public bool SaveBakedTextures(UUID agentId)
199 {
200 ScenePresence sp = m_scene.GetScenePresence(agentId);
201
202 if (sp == null)
203 return false;
204
205 m_log.DebugFormat(
206 "[AV FACTORY]: Permanently saving baked textures for {0} in {1}",
207 sp.Name, m_scene.RegionInfo.RegionName);
208
209 Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp);
210
211 if (bakedTextures.Count == 0)
212 return false;
213
214 foreach (BakeType bakeType in bakedTextures.Keys)
215 {
216 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
217
218 if (bakedTextureFace == null)
219 {
220 m_log.WarnFormat(
221 "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
222 bakeType, sp.Name, m_scene.RegionInfo.RegionName);
223
224 continue;
225 }
226
227 AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString());
228
229 if (asset != null)
230 {
231 asset.Temporary = false;
232 asset.Local = false;
233 m_scene.AssetService.Store(asset);
234 }
235 else
236 {
237 m_log.WarnFormat(
238 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
239 bakedTextureFace.TextureID, bakeType, sp.Name, m_scene.RegionInfo.RegionName);
240 }
241 }
242 return true;
243 }
244
115 /// <summary> 245 /// <summary>
116 /// Check for the existence of the baked texture assets. 246 /// Check for the existence of the baked texture assets.
117 /// </summary> 247 /// </summary>
118 /// <param name="client"></param> 248 /// <param name="sp"></param>
119 public bool ValidateBakedTextureCache(IClientAPI client) 249 public bool ValidateBakedTextureCache(IScenePresence sp)
120 { 250 {
121 return ValidateBakedTextureCache(client, true); 251 return ValidateBakedTextureCache(sp, true);
122 } 252 }
123 253
254 /// <summary>
255 /// Queue up a request to send appearance, makes it possible to
256 /// accumulate changes without sending out each one separately.
257 /// </summary>
258 public void QueueAppearanceSend(UUID agentid)
259 {
260 // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
261
262 // 10000 ticks per millisecond, 1000 milliseconds per second
263 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
264 lock (m_sendqueue)
265 {
266 m_sendqueue[agentid] = timestamp;
267 m_updateTimer.Start();
268 }
269 }
270
271 public void QueueAppearanceSave(UUID agentid)
272 {
273 // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid);
274
275 // 10000 ticks per millisecond, 1000 milliseconds per second
276 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
277 lock (m_savequeue)
278 {
279 m_savequeue[agentid] = timestamp;
280 m_updateTimer.Start();
281 }
282 }
283
284 #endregion
285
286 #region AvatarFactoryModule private methods
287
124 /// <summary> 288 /// <summary>
125 /// Check for the existence of the baked texture assets. Request a rebake 289 /// Check for the existence of the baked texture assets. Request a rebake
126 /// unless checkonly is true. 290 /// unless checkonly is true.
127 /// </summary> 291 /// </summary>
128 /// <param name="client"></param> 292 /// <param name="client"></param>
129 /// <param name="checkonly"></param> 293 /// <param name="checkonly"></param>
130 private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly) 294 private bool ValidateBakedTextureCache(IScenePresence sp, bool checkonly)
131 { 295 {
132 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
133 if (sp == null)
134 {
135 m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}", client.AgentId);
136 return false;
137 }
138
139 bool defonly = true; // are we only using default textures 296 bool defonly = true; // are we only using default textures
140 297
141 // Process the texture entry 298 // Process the texture entry
@@ -161,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
161 318
162 defonly = false; // found a non-default texture reference 319 defonly = false; // found a non-default texture reference
163 320
164 if (!CheckBakedTextureAsset(client, face.TextureID, idx)) 321 if (!CheckBakedTextureAsset(sp, face.TextureID, idx))
165 { 322 {
166 // the asset didn't exist if we are only checking, then we found a bad 323 // the asset didn't exist if we are only checking, then we found a bad
167 // one and we're done otherwise, ask for a rebake 324 // one and we're done otherwise, ask for a rebake
@@ -170,109 +327,34 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
170 327
171 m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID); 328 m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID);
172 329
173 client.SendRebakeAvatarTextures(face.TextureID); 330 sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
174 } 331 }
175 } 332 }
176 333
177 m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", client.AgentId); 334 m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", sp.UUID);
178 335
179 // If we only found default textures, then the appearance is not cached 336 // If we only found default textures, then the appearance is not cached
180 return (defonly ? false : true); 337 return (defonly ? false : true);
181 } 338 }
182 339
183 /// <summary> 340 /// <summary>
184 /// Set appearance data (texture asset IDs and slider settings) received from the client
185 /// </summary>
186 /// <param name="client"></param>
187 /// <param name="texture"></param>
188 /// <param name="visualParam"></param>
189 public void SetAppearanceFromClient(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
190 {
191 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
192 if (sp == null)
193 {
194 m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}", client.AgentId);
195 return;
196 }
197
198// m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId);
199
200 // TODO: This is probably not necessary any longer, just assume the
201 // textureEntry set implies that the appearance transaction is complete
202 bool changed = false;
203
204 // Process the texture entry transactionally, this doesn't guarantee that Appearance is
205 // going to be handled correctly but it does serialize the updates to the appearance
206 lock (m_setAppearanceLock)
207 {
208 // Process the visual params, this may change height as well
209 if (visualParams != null)
210 {
211// string[] visualParamsStrings = new string[visualParams.Length];
212// for (int i = 0; i < visualParams.Length; i++)
213// visualParamsStrings[i] = visualParams[i].ToString();
214// m_log.DebugFormat(
215// "[AVFACTORY]: Setting visual params for {0} to {1}",
216// client.Name, string.Join(", ", visualParamsStrings));
217
218 float oldHeight = sp.Appearance.AvatarHeight;
219 changed = sp.Appearance.SetVisualParams(visualParams);
220
221 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
222 sp.SetHeight(sp.Appearance.AvatarHeight);
223 }
224
225 // Process the baked texture array
226 if (textureEntry != null)
227 {
228 changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
229
230 m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", client.AgentId);
231 Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client, false); });
232
233 // This appears to be set only in the final stage of the appearance
234 // update transaction. In theory, we should be able to do an immediate
235 // appearance send and save here.
236
237 }
238 // save only if there were changes, send no matter what (doesn't hurt to send twice)
239 if (changed)
240 QueueAppearanceSave(client.AgentId);
241
242 QueueAppearanceSend(client.AgentId);
243 }
244
245 // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString());
246 }
247
248 /// <summary>
249 /// Checks for the existance of a baked texture asset and 341 /// Checks for the existance of a baked texture asset and
250 /// requests the viewer rebake if the asset is not found 342 /// requests the viewer rebake if the asset is not found
251 /// </summary> 343 /// </summary>
252 /// <param name="client"></param> 344 /// <param name="sp"></param>
253 /// <param name="textureID"></param> 345 /// <param name="textureID"></param>
254 /// <param name="idx"></param> 346 /// <param name="idx"></param>
255 private bool CheckBakedTextureAsset(IClientAPI client, UUID textureID, int idx) 347 private bool CheckBakedTextureAsset(IScenePresence sp, UUID textureID, int idx)
256 { 348 {
257 if (m_scene.AssetService.Get(textureID.ToString()) == null) 349 if (m_scene.AssetService.Get(textureID.ToString()) == null)
258 { 350 {
259 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}", 351 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",
260 textureID, idx, client.Name); 352 textureID, idx, sp.Name);
261 return false; 353 return false;
262 } 354 }
263 return true; 355 return true;
264 } 356 }
265 357
266 public Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId)
267 {
268 ScenePresence sp = m_scene.GetScenePresence(agentId);
269
270 if (sp == null)
271 return new Dictionary<BakeType, Primitive.TextureEntryFace>();
272
273 return GetBakedTextureFaces(sp);
274 }
275
276 private Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(ScenePresence sp) 358 private Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(ScenePresence sp)
277 { 359 {
278 if (sp.IsChildAgent) 360 if (sp.IsChildAgent)
@@ -302,136 +384,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
302 return bakedTextures; 384 return bakedTextures;
303 } 385 }
304 386
305 public bool SaveBakedTextures(UUID agentId)
306 {
307 ScenePresence sp = m_scene.GetScenePresence(agentId);
308
309 if (sp == null)
310 return false;
311
312 m_log.DebugFormat(
313 "[AV FACTORY]: Permanently saving baked textures for {0} in {1}",
314 sp.Name, m_scene.RegionInfo.RegionName);
315
316 Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp);
317
318 if (bakedTextures.Count == 0)
319 return false;
320
321 foreach (BakeType bakeType in bakedTextures.Keys)
322 {
323 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
324
325 if (bakedTextureFace == null)
326 {
327 m_log.WarnFormat(
328 "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
329 bakeType, sp.Name, m_scene.RegionInfo.RegionName);
330
331 continue;
332 }
333
334 AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString());
335
336 if (asset != null)
337 {
338 asset.Temporary = false;
339 asset.Local = false;
340 m_scene.AssetService.Store(asset);
341 }
342 else
343 {
344 m_log.WarnFormat(
345 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
346 bakedTextureFace.TextureID, bakeType, sp.Name, m_scene.RegionInfo.RegionName);
347 }
348 }
349
350// for (int i = 0; i < faceTextures.Length; i++)
351// {
352//// m_log.DebugFormat(
353//// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
354//// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
355//
356// if (faceTextures[i] == null)
357// continue;
358//
359// AssetBase asset = m_scene.AssetService.Get(faceTextures[i].TextureID.ToString());
360//
361// if (asset != null)
362// {
363// asset.Temporary = false;
364// m_scene.AssetService.Store(asset);
365// }
366// else
367// {
368// m_log.WarnFormat(
369// "[AV FACTORY]: Baked texture {0} for {1} in {2} not found when trying to save permanently",
370// faceTextures[i].TextureID, sp.Name, m_scene.RegionInfo.RegionName);
371// }
372// }
373
374 return true;
375 }
376
377 #region UpdateAppearanceTimer
378
379 /// <summary>
380 /// Queue up a request to send appearance, makes it possible to
381 /// accumulate changes without sending out each one separately.
382 /// </summary>
383 public void QueueAppearanceSend(UUID agentid)
384 {
385 // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
386
387 // 10000 ticks per millisecond, 1000 milliseconds per second
388 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
389 lock (m_sendqueue)
390 {
391 m_sendqueue[agentid] = timestamp;
392 m_updateTimer.Start();
393 }
394 }
395
396 public void QueueAppearanceSave(UUID agentid)
397 {
398 // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid);
399
400 // 10000 ticks per millisecond, 1000 milliseconds per second
401 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
402 lock (m_savequeue)
403 {
404 m_savequeue[agentid] = timestamp;
405 m_updateTimer.Start();
406 }
407 }
408
409 private void SaveAppearance(UUID agentid)
410 {
411 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
412 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as
413 // number seperators.
414 Culture.SetCurrentCulture();
415
416 ScenePresence sp = m_scene.GetScenePresence(agentid);
417 if (sp == null)
418 {
419 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
420 return;
421 }
422
423 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
424
425 // This could take awhile since it needs to pull inventory
426 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
427 // assets and item asset id changes to complete.
428 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
429 // multiple save requests.
430 SetAppearanceAssets(sp.UUID, sp.Appearance);
431
432 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
433 }
434
435 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea) 387 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
436 { 388 {
437 long now = DateTime.Now.Ticks; 389 long now = DateTime.Now.Ticks;
@@ -464,43 +416,122 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
464 416
465 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0) 417 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
466 m_updateTimer.Stop(); 418 m_updateTimer.Stop();
467 } 419 }
468 420
469 #endregion 421 private void SaveAppearance(UUID agentid)
470 422 {
423 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
424 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as
425 // number seperators.
426 Culture.SetCurrentCulture();
427
428 ScenePresence sp = m_scene.GetScenePresence(agentid);
429 if (sp == null)
430 {
431 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
432 return;
433 }
434
435 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
436
437 // This could take awhile since it needs to pull inventory
438 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
439 // assets and item asset id changes to complete.
440 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
441 // multiple save requests.
442 SetAppearanceAssets(sp.UUID, sp.Appearance);
443
444 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
445 }
446
447 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
448 {
449 IInventoryService invService = m_scene.InventoryService;
450
451 if (invService.GetRootFolder(userID) != null)
452 {
453 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
454 {
455 for (int j = 0; j < appearance.Wearables[j].Count; j++)
456 {
457 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
458 continue;
459
460 // Ignore ruth's assets
461 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
462 continue;
463 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
464 baseItem = invService.GetItem(baseItem);
465
466 if (baseItem != null)
467 {
468 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
469 }
470 else
471 {
472 m_log.ErrorFormat(
473 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
474 appearance.Wearables[i][j].ItemID, (WearableType)i);
475
476 appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID);
477 }
478 }
479 }
480 }
481 else
482 {
483 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
484 }
485 }
486
487 #endregion
488
489 #region Client Event Handlers
471 /// <summary> 490 /// <summary>
472 /// Tell the client for this scene presence what items it should be wearing now 491 /// Tell the client for this scene presence what items it should be wearing now
473 /// </summary> 492 /// </summary>
474 public void SendWearables(IClientAPI client) 493 /// <param name="client"></param>
475 { 494 private void Client_OnRequestWearables(IClientAPI client)
495 {
496 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId);
476 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 497 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
477 if (sp == null) 498 if (sp != null)
478 { 499 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
479 m_log.WarnFormat("[AVFACTORY]: SendWearables unable to find presence for {0}", client.AgentId); 500 else
480 return; 501 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
481 } 502 }
482 503
483// m_log.DebugFormat("[AVFACTORY]: Received request for wearables of {0}", client.Name); 504 /// <summary>
484 505 /// Set appearance data (texture asset IDs and slider settings) received from a client
485 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); 506 /// </summary>
507 /// <param name="client"></param>
508 /// <param name="texture"></param>
509 /// <param name="visualParam"></param>
510 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
511 {
512 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
513 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
514 if (sp != null)
515 SetAppearance(sp, textureEntry, visualParams);
516 else
517 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
486 } 518 }
487 519
488 /// <summary> 520 /// <summary>
489 /// Update what the avatar is wearing using an item from their inventory. 521 /// Update what the avatar is wearing using an item from their inventory.
490 /// </summary> 522 /// </summary>
491 /// <param name="sender"></param> 523 /// <param name="client"></param>
492 /// <param name="e"></param> 524 /// <param name="e"></param>
493 public void AvatarIsWearing(IClientAPI client, AvatarWearingArgs e) 525 private void Client_OnAvatarNowWearing(IClientAPI client, AvatarWearingArgs e)
494 { 526 {
527 // m_log.WarnFormat("[AVFACTORY]: Client_OnAvatarNowWearing called for {0} ({1})", client.Name, client.AgentId);
495 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 528 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
496 if (sp == null) 529 if (sp == null)
497 { 530 {
498 m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing unable to find presence for {0}", client.AgentId); 531 m_log.WarnFormat("[AVFACTORY]: Client_OnAvatarNowWearing unable to find presence for {0}", client.AgentId);
499 return; 532 return;
500 } 533 }
501 534
502 // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId);
503
504 // we need to clean out the existing textures 535 // we need to clean out the existing textures
505 sp.Appearance.ResetAppearance(); 536 sp.Appearance.ResetAppearance();
506 537
@@ -527,65 +558,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
527 // of visual param and baked texture changes. When those complete, the new appearance will be sent 558 // of visual param and baked texture changes. When those complete, the new appearance will be sent
528 559
529 QueueAppearanceSave(client.AgentId); 560 QueueAppearanceSave(client.AgentId);
530 } 561 }
531 } 562 }
532 563 #endregion
533 public bool SendAppearance(UUID agentId)
534 {
535 ScenePresence sp = m_scene.GetScenePresence(agentId);
536 if (sp == null)
537 {
538 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
539 return false;
540 }
541
542 // Send the appearance to everyone in the scene
543 sp.SendAppearanceToAllOtherAgents();
544
545 // Send animations back to the avatar as well
546 sp.Animator.SendAnimPack();
547
548 return true;
549 }
550
551 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
552 {
553 IInventoryService invService = m_scene.InventoryService;
554
555 if (invService.GetRootFolder(userID) != null)
556 {
557 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
558 {
559 for (int j = 0; j < appearance.Wearables[j].Count; j++)
560 {
561 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
562 continue;
563
564 // Ignore ruth's assets
565 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
566 continue;
567 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
568 baseItem = invService.GetItem(baseItem);
569
570 if (baseItem != null)
571 {
572 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
573 }
574 else
575 {
576 m_log.ErrorFormat(
577 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
578 appearance.Wearables[i][j].ItemID, (WearableType)i);
579
580 appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID);
581 }
582 }
583 }
584 }
585 else
586 {
587 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
588 }
589 }
590 } 564 }
591} 565}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 7b2f14e..931d52f 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -55,15 +55,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 AvatarFactoryModule afm = new AvatarFactoryModule(); 55 AvatarFactoryModule afm = new AvatarFactoryModule();
56 TestScene scene = SceneHelpers.SetupScene(); 56 TestScene scene = SceneHelpers.SetupScene();
57 SceneHelpers.SetupSceneModules(scene, afm); 57 SceneHelpers.SetupSceneModules(scene, afm);
58 IClientAPI tc = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 58 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
59 59
60 byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; 60 byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT];
61 for (byte i = 0; i < visualParams.Length; i++) 61 for (byte i = 0; i < visualParams.Length; i++)
62 visualParams[i] = i; 62 visualParams[i] = i;
63 63
64 afm.SetAppearanceFromClient(tc, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); 64 afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams);
65
66 ScenePresence sp = scene.GetScenePresence(userId);
67 65
68 // TODO: Check baked texture 66 // TODO: Check baked texture
69 Assert.AreEqual(visualParams, sp.Appearance.VisualParams); 67 Assert.AreEqual(visualParams, sp.Appearance.VisualParams);
@@ -84,8 +82,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
84 82
85 AvatarFactoryModule afm = new AvatarFactoryModule(); 83 AvatarFactoryModule afm = new AvatarFactoryModule();
86 TestScene scene = SceneHelpers.SetupScene(assetCache); 84 TestScene scene = SceneHelpers.SetupScene(assetCache);
87 SceneHelpers.SetupSceneModules(scene, afm); 85 SceneHelpers.SetupSceneModules(scene, afm);
88 IClientAPI tc = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 86 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
89 87
90 // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules 88 // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules
91 AssetBase uploadedAsset; 89 AssetBase uploadedAsset;
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
104 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 102 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
105 eyesFace.TextureID = eyesTextureId; 103 eyesFace.TextureID = eyesTextureId;
106 104
107 afm.SetAppearanceFromClient(tc, bakedTextureEntry, visualParams); 105 afm.SetAppearance(sp, bakedTextureEntry, visualParams);
108 afm.SaveBakedTextures(userId); 106 afm.SaveBakedTextures(userId);
109// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 107// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
110 108
diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
index 4dbddf4..98228e4 100644
--- a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
@@ -31,8 +31,11 @@ using OpenSim.Framework;
31 31
32namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
33{ 33{
34 public interface IAvatarFactory 34 public interface IAvatarFactoryModule
35 { 35 {
36
37 void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams);
38
36 /// <summary> 39 /// <summary>
37 /// Send the appearance of an avatar to others in the scene. 40 /// Send the appearance of an avatar to others in the scene.
38 /// </summary> 41 /// </summary>
@@ -57,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces
57 /// <returns>true if a valid agent was found, false otherwise</returns> 60 /// <returns>true if a valid agent was found, false otherwise</returns>
58 bool SaveBakedTextures(UUID agentId); 61 bool SaveBakedTextures(UUID agentId);
59 62
60 bool ValidateBakedTextureCache(IClientAPI client); 63 bool ValidateBakedTextureCache(IScenePresence sp);
61 void QueueAppearanceSend(UUID agentid); 64 void QueueAppearanceSend(UUID agentid);
62 void QueueAppearanceSave(UUID agentid); 65 void QueueAppearanceSave(UUID agentid);
63 } 66 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 8a32e1d..724c635 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -135,7 +135,7 @@ namespace OpenSim.Region.Framework.Scenes
135 135
136 protected IXMLRPC m_xmlrpcModule; 136 protected IXMLRPC m_xmlrpcModule;
137 protected IWorldComm m_worldCommModule; 137 protected IWorldComm m_worldCommModule;
138 protected IAvatarFactory m_AvatarFactory; 138 protected IAvatarFactoryModule m_AvatarFactory;
139 protected IConfigSource m_config; 139 protected IConfigSource m_config;
140 protected IRegionSerialiserModule m_serialiser; 140 protected IRegionSerialiserModule m_serialiser;
141 protected IDialogModule m_dialogModule; 141 protected IDialogModule m_dialogModule;
@@ -444,7 +444,7 @@ namespace OpenSim.Region.Framework.Scenes
444 444
445 public IAttachmentsModule AttachmentsModule { get; set; } 445 public IAttachmentsModule AttachmentsModule { get; set; }
446 446
447 public IAvatarFactory AvatarFactory 447 public IAvatarFactoryModule AvatarFactory
448 { 448 {
449 get { return m_AvatarFactory; } 449 get { return m_AvatarFactory; }
450 } 450 }
@@ -1154,7 +1154,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 m_xmlrpcModule = RequestModuleInterface<IXMLRPC>(); 1154 m_xmlrpcModule = RequestModuleInterface<IXMLRPC>();
1155 m_worldCommModule = RequestModuleInterface<IWorldComm>(); 1155 m_worldCommModule = RequestModuleInterface<IWorldComm>();
1156 XferManager = RequestModuleInterface<IXfer>(); 1156 XferManager = RequestModuleInterface<IXfer>();
1157 m_AvatarFactory = RequestModuleInterface<IAvatarFactory>(); 1157 m_AvatarFactory = RequestModuleInterface<IAvatarFactoryModule>();
1158 AttachmentsModule = RequestModuleInterface<IAttachmentsModule>(); 1158 AttachmentsModule = RequestModuleInterface<IAttachmentsModule>();
1159 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>(); 1159 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>();
1160 m_dialogModule = RequestModuleInterface<IDialogModule>(); 1160 m_dialogModule = RequestModuleInterface<IDialogModule>();
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index e0fd84a..464f8f0 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2538,7 +2538,7 @@ namespace OpenSim.Region.Framework.Scenes
2538 // We have an appearance but we may not have the baked textures. Check the asset cache 2538 // We have an appearance but we may not have the baked textures. Check the asset cache
2539 // to see if all the baked textures are already here. 2539 // to see if all the baked textures are already here.
2540 if (m_scene.AvatarFactory != null) 2540 if (m_scene.AvatarFactory != null)
2541 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(ControllingClient); 2541 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
2542 2542
2543 // If we aren't using a cached appearance, then clear out the baked textures 2543 // If we aren't using a cached appearance, then clear out the baked textures
2544 if (!cachedappearance) 2544 if (!cachedappearance)
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
index 77e7acf..2cef8a9 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 53 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
54 protected IAvatarFactory m_avatarFactory; 54 protected IAvatarFactoryModule m_avatarFactory;
55 55
56 public string Name { get { return "Appearance Information Module"; } } 56 public string Name { get { return "Appearance Information Module"; } }
57 57
@@ -106,14 +106,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
106 { 106 {
107 foreach (Scene scene in m_scenes.Values) 107 foreach (Scene scene in m_scenes.Values)
108 { 108 {
109 scene.ForEachClient( 109 scene.ForEachScenePresence(
110 delegate(IClientAPI client) 110 delegate(ScenePresence sp)
111 { 111 {
112 if (client is LLClientView && !((LLClientView)client).ChildAgentStatus()) 112 if (sp.ControllingClient is LLClientView && !((LLClientView)sp.ControllingClient).ChildAgentStatus())
113 { 113 {
114 bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(client); 114 bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
115 MainConsole.Instance.OutputFormat( 115 MainConsole.Instance.OutputFormat(
116 "{0} baked appearance texture is {1}", client.Name, bakedTextureValid ? "OK" : "corrupt"); 116 "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt");
117 } 117 }
118 }); 118 });
119 } 119 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index e94ed85..10181aa 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
84 sp.Appearance = npcAppearance; 84 sp.Appearance = npcAppearance;
85 scene.AttachmentsModule.RezAttachments(sp); 85 scene.AttachmentsModule.RezAttachments(sp);
86 86
87 IAvatarFactory module = scene.RequestModuleInterface<IAvatarFactory>(); 87 IAvatarFactoryModule module = scene.RequestModuleInterface<IAvatarFactoryModule>();
88 module.SendAppearance(sp.UUID); 88 module.SendAppearance(sp.UUID);
89 89
90 return true; 90 return true;
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index be1ecd0..ce8d1db 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
106 // ScenePresence.SendInitialData() to reset our entire appearance. 106 // ScenePresence.SendInitialData() to reset our entire appearance.
107 scene.AssetService.Store(AssetHelpers.CreateAsset(originalFace8TextureId)); 107 scene.AssetService.Store(AssetHelpers.CreateAsset(originalFace8TextureId));
108 108
109 afm.SetAppearanceFromClient(sp.ControllingClient, originalTe, null); 109 afm.SetAppearance(sp, originalTe, null);
110 110
111 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>(); 111 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
112 UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance); 112 UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 49c8722..52d787d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -2405,7 +2405,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2405 2405
2406 protected LSL_Key SaveAppearanceToNotecard(ScenePresence sp, string notecard) 2406 protected LSL_Key SaveAppearanceToNotecard(ScenePresence sp, string notecard)
2407 { 2407 {
2408 IAvatarFactory appearanceModule = World.RequestModuleInterface<IAvatarFactory>(); 2408 IAvatarFactoryModule appearanceModule = World.RequestModuleInterface<IAvatarFactoryModule>();
2409 2409
2410 if (appearanceModule != null) 2410 if (appearanceModule != null)
2411 { 2411 {