aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs616
1 files changed, 402 insertions, 214 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index cfb082b..4abac43 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures); 77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures);
78 78
79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
80 } 80 }
81 81
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
166 } 166 }
167 167
168 /// <summary> 168 /// <summary>
169 /// Set appearance data (texture asset IDs and slider settings) 169 /// Set appearance data (texture asset IDs and slider settings)
170 /// </summary> 170 /// </summary>
171 /// <param name="sp"></param> 171 /// <param name="sp"></param>
172 /// <param name="texture"></param> 172 /// <param name="texture"></param>
@@ -188,29 +188,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
188 // Process the visual params, this may change height as well 188 // Process the visual params, this may change height as well
189 if (visualParams != null) 189 if (visualParams != null)
190 { 190 {
191 // string[] visualParamsStrings = new string[visualParams.Length];
192 // for (int i = 0; i < visualParams.Length; i++)
193 // visualParamsStrings[i] = visualParams[i].ToString();
194 // m_log.DebugFormat(
195 // "[AVFACTORY]: Setting visual params for {0} to {1}",
196 // client.Name, string.Join(", ", visualParamsStrings));
197/*
198 float oldHeight = sp.Appearance.AvatarHeight;
199 changed = sp.Appearance.SetVisualParams(visualParams);
200
201 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
202 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
203 */
204// float oldoff = sp.Appearance.AvatarFeetOffset;
205// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
206 changed = sp.Appearance.SetVisualParams(visualParams); 191 changed = sp.Appearance.SetVisualParams(visualParams);
207// float off = sp.Appearance.AvatarFeetOffset;
208// Vector3 box = sp.Appearance.AvatarBoxSize;
209// if(oldoff != off || oldbox != box)
210// ((ScenePresence)sp).SetSize(box,off);
211
212 } 192 }
213 193
214 // Process the baked texture array 194 // Process the baked texture array
215 if (textureEntry != null) 195 if (textureEntry != null)
216 { 196 {
@@ -222,9 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
222 202
223// WriteBakedTexturesReport(sp, m_log.DebugFormat); 203// WriteBakedTexturesReport(sp, m_log.DebugFormat);
224 204
225 // If bake textures are missing and this is not an NPC, request a rebake from client 205 UpdateBakedTextureCache(sp, cacheItems);
226 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
227 RequestRebake(sp, true);
228 206
229 // This appears to be set only in the final stage of the appearance 207 // This appears to be set only in the final stage of the appearance
230 // update transaction. In theory, we should be able to do an immediate 208 // update transaction. In theory, we should be able to do an immediate
@@ -251,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
251 private void SendAppearance(ScenePresence sp) 229 private void SendAppearance(ScenePresence sp)
252 { 230 {
253 // Send the appearance to everyone in the scene 231 // Send the appearance to everyone in the scene
254 sp.SendAppearanceToAllOtherClients(); 232 sp.SendAppearanceToAllOtherAgents();
255 233
256 // Send animations back to the avatar as well 234 // Send animations back to the avatar as well
257 sp.Animator.SendAnimPack(); 235 sp.Animator.SendAnimPack();
@@ -289,7 +267,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
289 WearableCacheItem[] items = sp.Appearance.WearableCacheItems; 267 WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
290 //foreach (WearableCacheItem item in items) 268 //foreach (WearableCacheItem item in items)
291 //{ 269 //{
292 270
293 //} 271 //}
294 return items; 272 return items;
295 } 273 }
@@ -310,23 +288,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
310 if (bakedTextures.Count == 0) 288 if (bakedTextures.Count == 0)
311 return false; 289 return false;
312 290
291 IAssetCache cache = sp.Scene.RequestModuleInterface<IAssetCache>();
292 if(cache == null)
293 return true; // no baked local caching so nothing to do
294
313 foreach (BakeType bakeType in bakedTextures.Keys) 295 foreach (BakeType bakeType in bakedTextures.Keys)
314 { 296 {
315 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType]; 297 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
316 298
317 if (bakedTextureFace == null) 299 if (bakedTextureFace == null)
318 {
319 // This can happen legitimately, since some baked textures might not exist
320 //m_log.WarnFormat(
321 // "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
322 // bakeType, sp.Name, m_scene.RegionInfo.RegionName);
323 continue; 300 continue;
324 }
325 301
326 AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString()); 302 AssetBase asset;
303 cache.Get(bakedTextureFace.TextureID.ToString(), out asset);
327 304
328 if (asset != null) 305 if (asset != null && asset.Local)
329 { 306 {
307 // cache does not update asset contents
308 cache.Expire(bakedTextureFace.TextureID.ToString());
309
330 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars 310 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars
331 asset.ID = asset.FullID.ToString(); 311 asset.ID = asset.FullID.ToString();
332 312
@@ -334,7 +314,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
334 asset.Local = false; 314 asset.Local = false;
335 m_scene.AssetService.Store(asset); 315 m_scene.AssetService.Store(asset);
336 } 316 }
337 else 317
318 if (asset == null)
338 { 319 {
339 m_log.WarnFormat( 320 m_log.WarnFormat(
340 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently", 321 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
@@ -377,116 +358,366 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 } 358 }
378 } 359 }
379 360
380 public bool ValidateBakedTextureCache(IScenePresence sp) 361 // called on textures update
362 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
381 { 363 {
382 bool defonly = true; // are we only using default textures 364 if(cacheItems == null)
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 365 return false;
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 366
385 WearableCacheItem[] wearableCache = null; 367 // npcs dont have baked cache
386 368 if (((ScenePresence)sp).IsNPC)
387 // Cache wearable data for teleport. 369 return true;
388 // Only makes sense if there's a bake module and a cache module 370
389 if (bakedModule != null && cache != null) 371 // uploaded baked textures will be in assets local cache
372 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
373 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
374
375 int validDirtyBakes = 0;
376 int hits = 0;
377
378 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
379 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
380
381 if (wearableCache == null)
382 {
383 wearableCache = WearableCacheItem.GetDefaultCacheItem();
384 }
385
386 List<UUID> missing = new List<UUID>();
387
388 bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero);
389 bool haveNewSkirt = false;
390
391 // Process received baked textures
392 for (int i = 0; i < cacheItems.Length; i++)
390 { 393 {
391 try 394 int idx = (int)cacheItems[i].TextureIndex;
395 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
396
397 // No face
398 if (face == null)
392 { 399 {
393 wearableCache = bakedModule.Get(sp.UUID); 400 // for some reason viewer is cleaning this
401 if(idx != 19) // skirt is optional
402 {
403 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
404 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
405 }
406 wearableCache[idx].CacheId = UUID.Zero;
407 wearableCache[idx].TextureID = UUID.Zero;
408 wearableCache[idx].TextureAsset = null;
409 continue;
394 } 410 }
395 catch (Exception) 411 else
396 { 412 {
413 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
414 {
415 wearableCache[idx].CacheId = UUID.Zero;
416 wearableCache[idx].TextureID = UUID.Zero;
417 wearableCache[idx].TextureAsset = null;
418 continue;
419 }
397 420
398 } 421 if(idx == 19)
399 if (wearableCache != null) 422 haveNewSkirt = true;
400 { 423/*
401 for (int i = 0; i < wearableCache.Length; i++) 424 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
402 { 425 {
403 cache.Cache(wearableCache[i].TextureAsset); 426 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
427 {
428 wearableCache[idx].CacheId = cacheItems[i].CacheId;
429 validDirtyBakes++;
430
431 //assuming this can only happen if asset is in cache
432 }
433 hits++;
434 continue;
435 }
436*/
437 wearableCache[idx].TextureAsset = null;
438 if (cache != null)
439 {
440 AssetBase asb = null;
441 cache.Get(face.TextureID.ToString(), out asb);
442 wearableCache[idx].TextureAsset = asb;
443 }
444
445 if (wearableCache[idx].TextureAsset != null)
446 {
447 if ( wearableCache[idx].TextureID != face.TextureID ||
448 wearableCache[idx].CacheId != cacheItems[i].CacheId)
449 validDirtyBakes++;
450
451 wearableCache[idx].TextureID = face.TextureID;
452 wearableCache[idx].CacheId = cacheItems[i].CacheId;
453 hits++;
454 }
455 else
456 {
457 wearableCache[idx].CacheId = UUID.Zero;
458 wearableCache[idx].TextureID = UUID.Zero;
459 wearableCache[idx].TextureAsset = null;
460 missing.Add(face.TextureID);
461 continue;
404 } 462 }
405 } 463 }
406 } 464 }
407 /* 465
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 466 // handle optional skirt case
409 if (invService.GetRootFolder(userID) != null) 467 if(!haveNewSkirt && haveSkirt)
468 {
469 wearableCache[19].CacheId = UUID.Zero;
470 wearableCache[19].TextureID = UUID.Zero;
471 wearableCache[19].TextureAsset = null;
472 validDirtyBakes++;
473 }
474
475 sp.Appearance.WearableCacheItems = wearableCache;
476
477 if (missing.Count > 0)
410 { 478 {
411 WearableCacheItem[] wearableCache = null; 479 foreach (UUID id in missing)
412 if (bakedModule != null) 480 sp.ControllingClient.SendRebakeAvatarTextures(id);
481 }
482
483 if (validDirtyBakes > 0 && hits == cacheItems.Length)
484 {
485 // if we got a full set of baked textures save all in BakedTextureModule
486 if (m_BakedTextureModule != null)
413 { 487 {
414 try 488 m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
489 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
490
491 m_BakedTextureModule.Store(sp.UUID, wearableCache);
492 }
493 }
494 else
495 m_log.DebugFormat("[UpdateBakedCache] cache hits: {0} changed entries: {1} rebakes {2}",
496 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
497
498 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
499 {
500 int j = AvatarAppearance.BAKE_INDICES[iter];
501 sp.Appearance.WearableCacheItems[j].TextureAsset = null;
502// m_log.Debug("[UpdateBCache] {" + iter + "/" +
503// sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
504// sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
505// sp.Appearance.WearableCacheItems[j].TextureID);
506 }
507
508 return (hits == cacheItems.Length);
509 }
510
511 // called when we get a new root avatar
512 public bool ValidateBakedTextureCache(IScenePresence sp)
513 {
514 int hits = 0;
515
516 if (((ScenePresence)sp).IsNPC)
517 return true;
518
519 lock (m_setAppearanceLock)
520 {
521 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
522 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
523 WearableCacheItem[] bakedModuleCache = null;
524
525 if (cache == null)
526 return false;
527
528 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
529
530 // big debug
531 //m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
532/*
533 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
534 {
535 int j = AvatarAppearance.BAKE_INDICES[iter];
536 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
537 if (wearableCache == null)
538 {
539 if (face != null)
540 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
541 else
542 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
543 }
544 else
545 {
546 if (face != null)
547 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
548 "}: cc-" +
549 wearableCache[j].CacheId + ", ct-" +
550 wearableCache[j].TextureID
551 );
552 else
553 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
554 "}: cc-" +
555 wearableCache[j].CacheId + ", ct-" +
556 wearableCache[j].TextureID
557 );
558 }
559 }
560*/
561
562 bool wearableCacheValid = false;
563 if (wearableCache == null)
564 {
565 wearableCache = WearableCacheItem.GetDefaultCacheItem();
566 }
567 else
568 {
569 // we may have received a full cache
570 // check same coerence and store
571 wearableCacheValid = true;
572 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
415 { 573 {
416 wearableCache = bakedModule.Get(userID); 574 int idx = AvatarAppearance.BAKE_INDICES[i];
417 appearance.WearableCacheItems = wearableCache; 575 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
418 appearance.WearableCacheItemsDirty = false; 576 if (face != null)
419 foreach (WearableCacheItem item in wearableCache)
420 { 577 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; 578 if (face.TextureID == wearableCache[idx].TextureID &&
579 face.TextureID != UUID.Zero)
580 {
581 if (wearableCache[idx].TextureAsset != null)
582 {
583 hits++;
584 wearableCache[idx].TextureAsset.Temporary = true;
585 wearableCache[idx].TextureAsset.Local = true;
586 cache.Cache(wearableCache[idx].TextureAsset);
587 wearableCache[idx].TextureAsset = null;
588 continue;
589 }
590
591 if (cache.Check((wearableCache[idx].TextureID).ToString()))
592 {
593 hits++;
594 continue;
595 }
596 }
597 wearableCacheValid = false;
422 } 598 }
423 } 599 }
424 catch (Exception) 600
601 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
602 if (wearableCacheValid)
425 { 603 {
426 604 //m_log.Debug("[ValidateBakedCache] have valid local cache");
427 } 605 }
606 else
607 wearableCache[19].TextureAsset = null; // clear optional skirt
428 } 608 }
429 */
430 609
431 // Process the texture entry 610 bool checkExternal = false;
432 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
433 {
434 int idx = AvatarAppearance.BAKE_INDICES[i];
435 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
436 611
437 // No face, so lets check our baked service cache, teleport or login. 612 if (!wearableCacheValid)
438 if (face == null)
439 { 613 {
440 if (wearableCache != null) 614 hits = 0;
615 // only use external bake module on login condition check
616// ScenePresence ssp = null;
617// if (sp is ScenePresence)
441 { 618 {
442 // If we find the an appearance item, set it as the textureentry and the face 619// ssp = (ScenePresence)sp;
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 620// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
444 if (searchitem != null) 621// bakedModule != null;
445 { 622
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); 623 // or do it anytime we dont have the cache
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; 624 checkExternal = bakedModule != null;
448 face = sp.Appearance.Texture.FaceTextures[idx]; 625 }
449 } 626 }
450 else 627
628 if (checkExternal)
629 {
630 bool gotbacked = false;
631
632 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
633 try
634 {
635 bakedModuleCache = bakedModule.Get(sp.UUID);
636 }
637 catch (Exception e)
638 {
639 m_log.ErrorFormat(e.ToString());
640 bakedModuleCache = null;
641 }
642
643 if (bakedModuleCache != null)
644 {
645 //m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
646
647 for (int i = 0; i < bakedModuleCache.Length; i++)
451 { 648 {
452 // if there is no texture entry and no baked cache, skip it 649 int j = (int)bakedModuleCache[i].TextureIndex;
453 continue; 650
651 if (bakedModuleCache[i].TextureAsset != null)
652 {
653 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
654 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
655 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
656 bakedModuleCache[i].TextureAsset.Temporary = true;
657 bakedModuleCache[i].TextureAsset.Local = true;
658 cache.Cache(bakedModuleCache[i].TextureAsset);
659 }
454 } 660 }
661 gotbacked = true;
455 } 662 }
456 else 663
664 if (gotbacked)
457 { 665 {
458 //No texture entry face and no cache. Skip this face. 666 // force the ones we got
459 continue; 667 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
668 {
669 int idx = AvatarAppearance.BAKE_INDICES[i];
670 if(wearableCache[idx].TextureAsset == null)
671 {
672 if(idx == 19)
673 {
674 sp.Appearance.Texture.FaceTextures[idx] = null;
675 hits++;
676 }
677 continue;
678 }
679
680 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
681
682 if (face == null)
683 {
684 face = sp.Appearance.Texture.CreateFace((uint)idx);
685 sp.Appearance.Texture.FaceTextures[idx] = face;
686 }
687
688 face.TextureID = wearableCache[idx].TextureID;
689 hits++;
690 wearableCache[idx].TextureAsset = null;
691 }
460 } 692 }
461 } 693 }
462
463// m_log.DebugFormat(
464// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
465// face.TextureID, idx, client.Name, client.AgentId);
466 694
467 // if the texture is one of the "defaults" then skip it 695 sp.Appearance.WearableCacheItems = wearableCache;
468 // this should probably be more intelligent (skirt texture doesnt matter
469 // if the avatar isnt wearing a skirt) but if any of the main baked
470 // textures is default then the rest should be as well
471 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
472 continue;
473
474 defonly = false; // found a non-default texture reference
475 696
476 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
477 return false;
478 } 697 }
479 698
480// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 699 // debug
481 700 //m_log.DebugFormat("[ValidateBakedCache]: Completed texture check for {0} {1} with {2} hits", sp.Name, sp.UUID, hits);
482 // If we only found default textures, then the appearance is not cached 701/*
483 return (defonly ? false : true); 702 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
703 {
704 int j = AvatarAppearance.BAKE_INDICES[iter];
705 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
706 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
707 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
708 sp.Appearance.WearableCacheItems[j].TextureID);
709 }
710*/
711 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
484 } 712 }
485 713
486 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 714 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
487 { 715 {
716 if (((ScenePresence)sp).IsNPC)
717 return 0;
718
488 int texturesRebaked = 0; 719 int texturesRebaked = 0;
489// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 720 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
490 721
491 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 722 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
492 { 723 {
@@ -497,31 +728,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
497 if (face == null) 728 if (face == null)
498 continue; 729 continue;
499 730
500// m_log.DebugFormat(
501// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
502// face.TextureID, idx, client.Name, client.AgentId);
503
504 // if the texture is one of the "defaults" then skip it
505 // this should probably be more intelligent (skirt texture doesnt matter
506 // if the avatar isnt wearing a skirt) but if any of the main baked
507 // textures is default then the rest should be as well
508 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) 731 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
509 continue; 732 continue;
510 733
511 if (missingTexturesOnly) 734 if (missingTexturesOnly)
512 { 735 {
513 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 736 if (cache != null && cache.Check(face.TextureID.ToString()))
514 { 737 {
515 continue; 738 continue;
516 } 739 }
517 else 740 else
518 { 741 {
519 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
520 // grid asset service (which means that they are not available to the new region and so have
521 // to be re-requested from the client).
522 //
523 // The only available core OpenSimulator behaviour right now
524 // is not to store these textures, temporarily or otherwise.
525 m_log.DebugFormat( 742 m_log.DebugFormat(
526 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 743 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
527 face.TextureID, idx, sp.Name); 744 face.TextureID, idx, sp.Name);
@@ -605,7 +822,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
605 foreach (KeyValuePair<UUID, long> kvp in saves) 822 foreach (KeyValuePair<UUID, long> kvp in saves)
606 { 823 {
607 // We have to load the key and value into local parameters to avoid a race condition if we loop 824 // We have to load the key and value into local parameters to avoid a race condition if we loop
608 // around and load kvp with a different value before FireAndForget has launched its thread. 825 // around and load kvp with a different value before FireAndForget has launched its thread.
609 UUID avatarID = kvp.Key; 826 UUID avatarID = kvp.Key;
610 long sendTime = kvp.Value; 827 long sendTime = kvp.Value;
611 828
@@ -658,13 +875,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
658 875
659 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 876 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
660 877
661 // Trigger this here because it's the final step in the set/queue/save process for appearance setting. 878 // Trigger this here because it's the final step in the set/queue/save process for appearance setting.
662 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes). 879 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes).
663 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp); 880 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
664 } 881 }
665 882
666 /// <summary> 883 /// <summary>
667 /// For a given set of appearance items, check whether the items are valid and add their asset IDs to 884 /// For a given set of appearance items, check whether the items are valid and add their asset IDs to
668 /// appearance data. 885 /// appearance data.
669 /// </summary> 886 /// </summary>
670 /// <param name='userID'></param> 887 /// <param name='userID'></param>
@@ -675,25 +892,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
675 892
676 if (invService.GetRootFolder(userID) != null) 893 if (invService.GetRootFolder(userID) != null)
677 { 894 {
678 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 895 for (int i = 0; i < appearance.Wearables.Length; i++)
679 { 896 {
680 for (int j = 0; j < appearance.Wearables[i].Count; j++) 897 for (int j = 0; j < appearance.Wearables[i].Count; j++)
681 { 898 {
682 if (appearance.Wearables[i][j].ItemID == UUID.Zero) 899 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
683 { 900 {
684 m_log.WarnFormat( 901 m_log.WarnFormat(
685 "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.", 902 "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.",
686 i, j, userID); 903 i, j, userID);
687 904
688 continue; 905 continue;
689 } 906 }
690 907
691 // Ignore ruth's assets 908 // Ignore ruth's assets
692 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 909 if (i < AvatarWearable.DefaultWearables.Length)
693 continue; 910 {
911 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
912 continue;
913 }
694 914
695 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 915 InventoryItemBase baseItem = invService.GetItem(userID, appearance.Wearables[i][j].ItemID);
696 baseItem = invService.GetItem(baseItem);
697 916
698 if (baseItem != null) 917 if (baseItem != null)
699 { 918 {
@@ -754,7 +973,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
754// case WearableType.Skin: 973// case WearableType.Skin:
755// //case WearableType.Underpants: 974// //case WearableType.Underpants:
756// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); 975// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
757// 976//
758// m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); 977// m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
759// resetwearable = true; 978// resetwearable = true;
760// break; 979// break;
@@ -762,7 +981,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
762// } 981// }
763// continue; 982// continue;
764// } 983// }
765// 984//
766// InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 985// InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
767// baseItem = invService.GetItem(baseItem); 986// baseItem = invService.GetItem(baseItem);
768// 987//
@@ -789,7 +1008,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
789// 1008//
790// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); 1009// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
791// resetwearable = true; 1010// resetwearable = true;
792// 1011//
793// } 1012// }
794// } 1013// }
795// } 1014// }
@@ -798,7 +1017,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
798// if (appearance.Wearables[(int) WearableType.Eyes] == null) 1017// if (appearance.Wearables[(int) WearableType.Eyes] == null)
799// { 1018// {
800// m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); 1019// m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
801// 1020//
802// TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); 1021// TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
803// resetwearable = true; 1022// resetwearable = true;
804// } 1023// }
@@ -902,85 +1121,45 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
902 { 1121 {
903 UUID newInvItem = UUID.Random(); 1122 UUID newInvItem = UUID.Random();
904 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) 1123 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
905 { 1124 {
906 AssetID = 1125 AssetID = defaultwearable,
907 defaultwearable, 1126 AssetType = (int)FolderType.BodyPart,
908 AssetType 1127 CreatorId = userID.ToString(),
909 = 1128 //InvType = (int)InventoryType.Wearable,
910 (int) 1129 Description = "Failed Wearable Replacement",
911 FolderType 1130 Folder = invService.GetFolderForType(userID, FolderType.BodyPart).ID,
912 .BodyPart, 1131 Flags = (uint) type, Name = Enum.GetName(typeof (WearableType), type),
913 CreatorId 1132 BasePermissions = (uint) PermissionMask.Copy,
914 = 1133 CurrentPermissions = (uint) PermissionMask.Copy,
915 userID 1134 EveryOnePermissions = (uint) PermissionMask.Copy,
916 .ToString 1135 GroupPermissions = (uint) PermissionMask.Copy,
917 (), 1136 NextPermissions = (uint) PermissionMask.Copy
918 //InvType = (int)InventoryType.Wearable, 1137 };
919
920 Description
921 =
922 "Failed Wearable Replacement",
923 Folder =
924 invService
925 .GetFolderForType
926 (userID,
927 FolderType
928 .BodyPart)
929 .ID,
930 Flags = (uint) type,
931 Name = Enum.GetName(typeof (WearableType), type),
932 BasePermissions = (uint) PermissionMask.Copy,
933 CurrentPermissions = (uint) PermissionMask.Copy,
934 EveryOnePermissions = (uint) PermissionMask.Copy,
935 GroupPermissions = (uint) PermissionMask.Copy,
936 NextPermissions = (uint) PermissionMask.Copy
937 };
938 invService.AddItem(itembase); 1138 invService.AddItem(itembase);
939 UUID LinkInvItem = UUID.Random(); 1139 UUID LinkInvItem = UUID.Random();
940 itembase = new InventoryItemBase(LinkInvItem, userID) 1140 itembase = new InventoryItemBase(LinkInvItem, userID)
941 { 1141 {
942 AssetID = 1142 AssetID = newInvItem,
943 newInvItem, 1143 AssetType = (int)AssetType.Link,
944 AssetType 1144 CreatorId = userID.ToString(),
945 = 1145 InvType = (int) InventoryType.Wearable,
946 (int) 1146 Description = "Failed Wearable Replacement",
947 AssetType 1147 Folder = invService.GetFolderForType(userID, FolderType.CurrentOutfit).ID,
948 .Link, 1148 Flags = (uint) type,
949 CreatorId 1149 Name = Enum.GetName(typeof (WearableType), type),
950 = 1150 BasePermissions = (uint) PermissionMask.Copy,
951 userID 1151 CurrentPermissions = (uint) PermissionMask.Copy,
952 .ToString 1152 EveryOnePermissions = (uint) PermissionMask.Copy,
953 (), 1153 GroupPermissions = (uint) PermissionMask.Copy,
954 InvType = (int) InventoryType.Wearable, 1154 NextPermissions = (uint) PermissionMask.Copy
955 1155 };
956 Description
957 =
958 "Failed Wearable Replacement",
959 Folder =
960 invService
961 .GetFolderForType
962 (userID,
963 FolderType
964 .CurrentOutfit)
965 .ID,
966 Flags = (uint) type,
967 Name = Enum.GetName(typeof (WearableType), type),
968 BasePermissions = (uint) PermissionMask.Copy,
969 CurrentPermissions = (uint) PermissionMask.Copy,
970 EveryOnePermissions = (uint) PermissionMask.Copy,
971 GroupPermissions = (uint) PermissionMask.Copy,
972 NextPermissions = (uint) PermissionMask.Copy
973 };
974 invService.AddItem(itembase); 1156 invService.AddItem(itembase);
975 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); 1157 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
976 ScenePresence presence = null; 1158 ScenePresence presence = null;
977 if (m_scene.TryGetScenePresence(userID, out presence)) 1159 if (m_scene.TryGetScenePresence(userID, out presence))
978 { 1160 {
979 m_scene.SendInventoryUpdate(presence.ControllingClient, 1161 m_scene.SendInventoryUpdate(presence.ControllingClient,
980 invService.GetFolderForType(userID, 1162 invService.GetFolderForType(userID, FolderType.CurrentOutfit), false, true);
981 FolderType
982 .CurrentOutfit),
983 false, true);
984 } 1163 }
985 } 1164 }
986 } 1165 }
@@ -1040,7 +1219,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1040 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); 1219 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
1041 }, null, "AvatarFactoryModule.OnClientRequestWearables"); 1220 }, null, "AvatarFactoryModule.OnClientRequestWearables");
1042 } 1221 }
1043 1222
1044 /// <summary> 1223 /// <summary>
1045 /// Set appearance data (texture asset IDs and slider settings) received from a client 1224 /// Set appearance data (texture asset IDs and slider settings) received from a client
1046 /// </summary> 1225 /// </summary>
@@ -1080,8 +1259,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1080 1259
1081 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 1260 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
1082 { 1261 {
1083 if (wear.Type < AvatarWearable.MAX_WEARABLES) 1262 // If the wearable type is larger than the current array, expand it
1084 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); 1263 if (avatAppearance.Wearables.Length <= wear.Type)
1264 {
1265 int currentLength = avatAppearance.Wearables.Length;
1266 AvatarWearable[] wears = avatAppearance.Wearables;
1267 Array.Resize(ref wears, wear.Type + 1);
1268 for (int i = currentLength ; i <= wear.Type ; i++)
1269 wears[i] = new AvatarWearable();
1270 avatAppearance.Wearables = wears;
1271 }
1272 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero);
1085 } 1273 }
1086 1274
1087 avatAppearance.GetAssetsFrom(sp.Appearance); 1275 avatAppearance.GetAssetsFrom(sp.Appearance);
@@ -1117,12 +1305,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1117 { 1305 {
1118 UUID texture = UUID.Zero; 1306 UUID texture = UUID.Zero;
1119 int index = request.BakedTextureIndex; 1307 int index = request.BakedTextureIndex;
1120 1308
1121 if (m_reusetextures) 1309 if (m_reusetextures)
1122 { 1310 {
1123 // this is the most insanely dumb way to do this... however it seems to 1311 // this is the most insanely dumb way to do this... however it seems to
1124 // actually work. if the appearance has been reset because wearables have 1312 // actually work. if the appearance has been reset because wearables have
1125 // changed then the texture entries are zero'd out until the bakes are 1313 // changed then the texture entries are zero'd out until the bakes are
1126 // uploaded. on login, if the textures exist in the cache (eg if you logged 1314 // uploaded. on login, if the textures exist in the cache (eg if you logged
1127 // into the simulator recently, then the appearance will pull those and send 1315 // into the simulator recently, then the appearance will pull those and send
1128 // them back in the packet and you won't have to rebake. if the textures aren't 1316 // them back in the packet and you won't have to rebake. if the textures aren't
@@ -1138,7 +1326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1138 1326
1139 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index); 1327 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1140 } 1328 }
1141 1329
1142 CachedTextureResponseArg response = new CachedTextureResponseArg(); 1330 CachedTextureResponseArg response = new CachedTextureResponseArg();
1143 response.BakedTextureIndex = index; 1331 response.BakedTextureIndex = index;
1144 response.BakedTextureID = texture; 1332 response.BakedTextureID = texture;
@@ -1146,7 +1334,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1146 1334
1147 cachedTextureResponse.Add(response); 1335 cachedTextureResponse.Add(response);
1148 } 1336 }
1149 1337
1150 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial); 1338 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1151 // The serial number appears to be used to match requests and responses 1339 // The serial number appears to be used to match requests and responses
1152 // in the texture transaction. We just send back the serial number 1340 // in the texture transaction. We just send back the serial number