diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/AvatarFactory')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 463 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | 4 |
2 files changed, 432 insertions, 35 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index ff5bf9f..51fe1ea 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -140,9 +140,24 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
140 | /// <param name="sp"></param> | 140 | /// <param name="sp"></param> |
141 | /// <param name="texture"></param> | 141 | /// <param name="texture"></param> |
142 | /// <param name="visualParam"></param> | 142 | /// <param name="visualParam"></param> |
143 | public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) | 143 | public void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems) |
144 | { | 144 | { |
145 | SetAppearance(sp, appearance.Texture, appearance.VisualParams); | 145 | SetAppearance(sp, appearance.Texture, appearance.VisualParams, cacheItems); |
146 | } | ||
147 | |||
148 | |||
149 | public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) | ||
150 | { | ||
151 | float oldoff = sp.Appearance.AvatarFeetOffset; | ||
152 | Vector3 oldbox = sp.Appearance.AvatarBoxSize; | ||
153 | |||
154 | SetAppearance(sp, textureEntry, visualParams, cacheItems); | ||
155 | sp.Appearance.SetSize(avSize); | ||
156 | |||
157 | float off = sp.Appearance.AvatarFeetOffset; | ||
158 | Vector3 box = sp.Appearance.AvatarBoxSize; | ||
159 | if (oldoff != off || oldbox != box) | ||
160 | ((ScenePresence)sp).SetSize(box, off); | ||
146 | } | 161 | } |
147 | 162 | ||
148 | /// <summary> | 163 | /// <summary> |
@@ -151,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
151 | /// <param name="sp"></param> | 166 | /// <param name="sp"></param> |
152 | /// <param name="texture"></param> | 167 | /// <param name="texture"></param> |
153 | /// <param name="visualParam"></param> | 168 | /// <param name="visualParam"></param> |
154 | public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) | 169 | public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems) |
155 | { | 170 | { |
156 | // m_log.DebugFormat( | 171 | // m_log.DebugFormat( |
157 | // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", | 172 | // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", |
@@ -174,18 +189,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
174 | // m_log.DebugFormat( | 189 | // m_log.DebugFormat( |
175 | // "[AVFACTORY]: Setting visual params for {0} to {1}", | 190 | // "[AVFACTORY]: Setting visual params for {0} to {1}", |
176 | // client.Name, string.Join(", ", visualParamsStrings)); | 191 | // client.Name, string.Join(", ", visualParamsStrings)); |
177 | 192 | /* | |
178 | float oldHeight = sp.Appearance.AvatarHeight; | 193 | float oldHeight = sp.Appearance.AvatarHeight; |
179 | changed = sp.Appearance.SetVisualParams(visualParams); | 194 | changed = sp.Appearance.SetVisualParams(visualParams); |
180 | 195 | ||
181 | if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) | 196 | if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) |
182 | ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); | 197 | ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); |
183 | } | 198 | */ |
199 | // float oldoff = sp.Appearance.AvatarFeetOffset; | ||
200 | // Vector3 oldbox = sp.Appearance.AvatarBoxSize; | ||
201 | changed = sp.Appearance.SetVisualParams(visualParams); | ||
202 | // float off = sp.Appearance.AvatarFeetOffset; | ||
203 | // Vector3 box = sp.Appearance.AvatarBoxSize; | ||
204 | // if(oldoff != off || oldbox != box) | ||
205 | // ((ScenePresence)sp).SetSize(box,off); | ||
184 | 206 | ||
207 | } | ||
208 | |||
185 | // Process the baked texture array | 209 | // Process the baked texture array |
186 | if (textureEntry != null) | 210 | if (textureEntry != null) |
187 | { | 211 | { |
188 | // m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); | 212 | m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); |
189 | 213 | ||
190 | // WriteBakedTexturesReport(sp, m_log.DebugFormat); | 214 | // WriteBakedTexturesReport(sp, m_log.DebugFormat); |
191 | 215 | ||
@@ -254,6 +278,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
254 | return GetBakedTextureFaces(sp); | 278 | return GetBakedTextureFaces(sp); |
255 | } | 279 | } |
256 | 280 | ||
281 | public WearableCacheItem[] GetCachedItems(UUID agentId) | ||
282 | { | ||
283 | ScenePresence sp = m_scene.GetScenePresence(agentId); | ||
284 | WearableCacheItem[] items = sp.Appearance.WearableCacheItems; | ||
285 | //foreach (WearableCacheItem item in items) | ||
286 | //{ | ||
287 | |||
288 | //} | ||
289 | return items; | ||
290 | } | ||
291 | |||
257 | public bool SaveBakedTextures(UUID agentId) | 292 | public bool SaveBakedTextures(UUID agentId) |
258 | { | 293 | { |
259 | ScenePresence sp = m_scene.GetScenePresence(agentId); | 294 | ScenePresence sp = m_scene.GetScenePresence(agentId); |
@@ -340,6 +375,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
340 | public bool ValidateBakedTextureCache(IScenePresence sp) | 375 | public bool ValidateBakedTextureCache(IScenePresence sp) |
341 | { | 376 | { |
342 | bool defonly = true; // are we only using default textures | 377 | bool defonly = true; // are we only using default textures |
378 | IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); | ||
379 | IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); | ||
380 | WearableCacheItem[] wearableCache = null; | ||
381 | |||
382 | // Cache wearable data for teleport. | ||
383 | // Only makes sense if there's a bake module and a cache module | ||
384 | if (bakedModule != null && cache != null) | ||
385 | { | ||
386 | try | ||
387 | { | ||
388 | wearableCache = bakedModule.Get(sp.UUID); | ||
389 | } | ||
390 | catch (Exception) | ||
391 | { | ||
392 | |||
393 | } | ||
394 | if (wearableCache != null) | ||
395 | { | ||
396 | for (int i = 0; i < wearableCache.Length; i++) | ||
397 | { | ||
398 | cache.Cache(wearableCache[i].TextureAsset); | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | /* | ||
403 | IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); | ||
404 | if (invService.GetRootFolder(userID) != null) | ||
405 | { | ||
406 | WearableCacheItem[] wearableCache = null; | ||
407 | if (bakedModule != null) | ||
408 | { | ||
409 | try | ||
410 | { | ||
411 | wearableCache = bakedModule.Get(userID); | ||
412 | appearance.WearableCacheItems = wearableCache; | ||
413 | appearance.WearableCacheItemsDirty = false; | ||
414 | foreach (WearableCacheItem item in wearableCache) | ||
415 | { | ||
416 | appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; | ||
417 | } | ||
418 | } | ||
419 | catch (Exception) | ||
420 | { | ||
421 | |||
422 | } | ||
423 | } | ||
424 | */ | ||
343 | 425 | ||
344 | // Process the texture entry | 426 | // Process the texture entry |
345 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) | 427 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) |
@@ -347,9 +429,32 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
347 | int idx = AvatarAppearance.BAKE_INDICES[i]; | 429 | int idx = AvatarAppearance.BAKE_INDICES[i]; |
348 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; | 430 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; |
349 | 431 | ||
350 | // if there is no texture entry, skip it | 432 | // No face, so lets check our baked service cache, teleport or login. |
351 | if (face == null) | 433 | if (face == null) |
352 | continue; | 434 | { |
435 | if (wearableCache != null) | ||
436 | { | ||
437 | // If we find the an appearance item, set it as the textureentry and the face | ||
438 | WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); | ||
439 | if (searchitem != null) | ||
440 | { | ||
441 | sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); | ||
442 | sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; | ||
443 | face = sp.Appearance.Texture.FaceTextures[idx]; | ||
444 | } | ||
445 | else | ||
446 | { | ||
447 | // if there is no texture entry and no baked cache, skip it | ||
448 | continue; | ||
449 | } | ||
450 | } | ||
451 | else | ||
452 | { | ||
453 | //No texture entry face and no cache. Skip this face. | ||
454 | continue; | ||
455 | } | ||
456 | } | ||
457 | |||
353 | 458 | ||
354 | // m_log.DebugFormat( | 459 | // m_log.DebugFormat( |
355 | // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", | 460 | // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", |
@@ -364,8 +469,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
364 | 469 | ||
365 | defonly = false; // found a non-default texture reference | 470 | defonly = false; // found a non-default texture reference |
366 | 471 | ||
367 | if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) | 472 | if (cache != null) |
368 | return false; | 473 | { |
474 | if (!cache.Check(face.TextureID.ToString())) | ||
475 | return false; | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) | ||
480 | return false; | ||
481 | } | ||
369 | } | 482 | } |
370 | 483 | ||
371 | // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); | 484 | // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); |
@@ -377,6 +490,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
377 | public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) | 490 | public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) |
378 | { | 491 | { |
379 | int texturesRebaked = 0; | 492 | int texturesRebaked = 0; |
493 | IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); | ||
380 | 494 | ||
381 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) | 495 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) |
382 | { | 496 | { |
@@ -400,21 +514,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
400 | 514 | ||
401 | if (missingTexturesOnly) | 515 | if (missingTexturesOnly) |
402 | { | 516 | { |
403 | if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) | 517 | if (cache != null) |
404 | { | 518 | { |
405 | continue; | 519 | if (cache.Check(face.TextureID.ToString())) |
520 | continue; | ||
521 | else | ||
522 | { | ||
523 | m_log.DebugFormat( | ||
524 | "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", | ||
525 | face.TextureID, idx, sp.Name); | ||
526 | } | ||
406 | } | 527 | } |
407 | else | 528 | else |
408 | { | 529 | { |
409 | // On inter-simulator teleports, this occurs if baked textures are not being stored by the | 530 | if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) |
410 | // grid asset service (which means that they are not available to the new region and so have | 531 | { |
411 | // to be re-requested from the client). | 532 | continue; |
412 | // | 533 | } |
413 | // The only available core OpenSimulator behaviour right now | 534 | |
414 | // is not to store these textures, temporarily or otherwise. | 535 | else |
415 | m_log.DebugFormat( | 536 | { |
416 | "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", | 537 | // On inter-simulator teleports, this occurs if baked textures are not being stored by the |
417 | face.TextureID, idx, sp.Name); | 538 | // grid asset service (which means that they are not available to the new region and so have |
539 | // to be re-requested from the client). | ||
540 | // | ||
541 | // The only available core OpenSimulator behaviour right now | ||
542 | // is not to store these textures, temporarily or otherwise. | ||
543 | m_log.DebugFormat( | ||
544 | "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", | ||
545 | face.TextureID, idx, sp.Name); | ||
546 | } | ||
418 | } | 547 | } |
419 | } | 548 | } |
420 | else | 549 | else |
@@ -556,26 +685,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
556 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) | 685 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) |
557 | { | 686 | { |
558 | IInventoryService invService = m_scene.InventoryService; | 687 | IInventoryService invService = m_scene.InventoryService; |
559 | 688 | bool resetwearable = false; | |
560 | if (invService.GetRootFolder(userID) != null) | 689 | if (invService.GetRootFolder(userID) != null) |
561 | { | 690 | { |
562 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | 691 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) |
563 | { | 692 | { |
564 | for (int j = 0; j < appearance.Wearables[i].Count; j++) | 693 | for (int j = 0; j < appearance.Wearables[i].Count; j++) |
565 | { | 694 | { |
695 | // Check if the default wearables are not set | ||
566 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) | 696 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) |
697 | { | ||
698 | switch ((WearableType) i) | ||
699 | { | ||
700 | case WearableType.Eyes: | ||
701 | case WearableType.Hair: | ||
702 | case WearableType.Shape: | ||
703 | case WearableType.Skin: | ||
704 | //case WearableType.Underpants: | ||
705 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
706 | resetwearable = true; | ||
707 | m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); | ||
708 | resetwearable = true; | ||
709 | break; | ||
710 | |||
711 | } | ||
567 | continue; | 712 | continue; |
713 | } | ||
568 | 714 | ||
569 | // Ignore ruth's assets | 715 | // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 |
570 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 716 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
717 | { | ||
718 | switch ((WearableType)i) | ||
719 | { | ||
720 | case WearableType.Eyes: | ||
721 | case WearableType.Hair: | ||
722 | case WearableType.Shape: | ||
723 | case WearableType.Skin: | ||
724 | //case WearableType.Underpants: | ||
725 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
726 | |||
727 | m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); | ||
728 | resetwearable = true; | ||
729 | break; | ||
730 | |||
731 | } | ||
571 | continue; | 732 | continue; |
572 | 733 | } | |
734 | |||
573 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 735 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
574 | baseItem = invService.GetItem(baseItem); | 736 | baseItem = invService.GetItem(baseItem); |
575 | 737 | ||
576 | if (baseItem != null) | 738 | if (baseItem != null) |
577 | { | 739 | { |
578 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); | 740 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); |
741 | int unmodifiedWearableIndexForClosure = i; | ||
742 | m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, | ||
743 | delegate(string x, object y, AssetBase z) | ||
744 | { | ||
745 | if (z == null) | ||
746 | { | ||
747 | TryAndRepairBrokenWearable( | ||
748 | (WearableType)unmodifiedWearableIndexForClosure, invService, | ||
749 | userID, appearance); | ||
750 | } | ||
751 | }); | ||
579 | } | 752 | } |
580 | else | 753 | else |
581 | { | 754 | { |
@@ -583,17 +756,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
583 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", | 756 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", |
584 | appearance.Wearables[i][j].ItemID, (WearableType)i); | 757 | appearance.Wearables[i][j].ItemID, (WearableType)i); |
585 | 758 | ||
586 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); | 759 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); |
760 | resetwearable = true; | ||
761 | |||
587 | } | 762 | } |
588 | } | 763 | } |
589 | } | 764 | } |
765 | |||
766 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
767 | if (appearance.Wearables[(int) WearableType.Eyes] == null) | ||
768 | { | ||
769 | m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); | ||
770 | |||
771 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
772 | resetwearable = true; | ||
773 | } | ||
774 | else | ||
775 | { | ||
776 | if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) | ||
777 | { | ||
778 | m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", | ||
779 | appearance.Wearables[(int) WearableType.Eyes][0].ItemID, | ||
780 | appearance.Wearables[(int) WearableType.Eyes][0].AssetID); | ||
781 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
782 | resetwearable = true; | ||
783 | |||
784 | } | ||
785 | |||
786 | } | ||
787 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
788 | if (appearance.Wearables[(int)WearableType.Shape] == null) | ||
789 | { | ||
790 | m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); | ||
791 | |||
792 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
793 | resetwearable = true; | ||
794 | } | ||
795 | else | ||
796 | { | ||
797 | if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) | ||
798 | { | ||
799 | m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", | ||
800 | appearance.Wearables[(int)WearableType.Shape][0].ItemID, | ||
801 | appearance.Wearables[(int)WearableType.Shape][0].AssetID); | ||
802 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
803 | resetwearable = true; | ||
804 | |||
805 | } | ||
806 | |||
807 | } | ||
808 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
809 | if (appearance.Wearables[(int)WearableType.Hair] == null) | ||
810 | { | ||
811 | m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); | ||
812 | |||
813 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
814 | resetwearable = true; | ||
815 | } | ||
816 | else | ||
817 | { | ||
818 | if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) | ||
819 | { | ||
820 | m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", | ||
821 | appearance.Wearables[(int)WearableType.Hair][0].ItemID, | ||
822 | appearance.Wearables[(int)WearableType.Hair][0].AssetID); | ||
823 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
824 | resetwearable = true; | ||
825 | |||
826 | } | ||
827 | |||
828 | } | ||
829 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
830 | if (appearance.Wearables[(int)WearableType.Skin] == null) | ||
831 | { | ||
832 | m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); | ||
833 | |||
834 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
835 | resetwearable = true; | ||
836 | } | ||
837 | else | ||
838 | { | ||
839 | if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) | ||
840 | { | ||
841 | m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", | ||
842 | appearance.Wearables[(int)WearableType.Skin][0].ItemID, | ||
843 | appearance.Wearables[(int)WearableType.Skin][0].AssetID); | ||
844 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
845 | resetwearable = true; | ||
846 | |||
847 | } | ||
848 | |||
849 | } | ||
850 | if (resetwearable) | ||
851 | { | ||
852 | ScenePresence presence = null; | ||
853 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
854 | { | ||
855 | presence.ControllingClient.SendWearables(presence.Appearance.Wearables, | ||
856 | presence.Appearance.Serial++); | ||
857 | } | ||
858 | } | ||
859 | |||
590 | } | 860 | } |
591 | else | 861 | else |
592 | { | 862 | { |
593 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); | 863 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); |
594 | } | 864 | } |
595 | } | 865 | } |
866 | private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) | ||
867 | { | ||
868 | UUID defaultwearable = GetDefaultItem(type); | ||
869 | if (defaultwearable != UUID.Zero) | ||
870 | { | ||
871 | UUID newInvItem = UUID.Random(); | ||
872 | InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) | ||
873 | { | ||
874 | AssetID = | ||
875 | defaultwearable, | ||
876 | AssetType | ||
877 | = | ||
878 | (int) | ||
879 | AssetType | ||
880 | .Bodypart, | ||
881 | CreatorId | ||
882 | = | ||
883 | userID | ||
884 | .ToString | ||
885 | (), | ||
886 | //InvType = (int)InventoryType.Wearable, | ||
887 | |||
888 | Description | ||
889 | = | ||
890 | "Failed Wearable Replacement", | ||
891 | Folder = | ||
892 | invService | ||
893 | .GetFolderForType | ||
894 | (userID, | ||
895 | AssetType | ||
896 | .Bodypart) | ||
897 | .ID, | ||
898 | Flags = (uint) type, | ||
899 | Name = Enum.GetName(typeof (WearableType), type), | ||
900 | BasePermissions = (uint) PermissionMask.Copy, | ||
901 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
902 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
903 | GroupPermissions = (uint) PermissionMask.Copy, | ||
904 | NextPermissions = (uint) PermissionMask.Copy | ||
905 | }; | ||
906 | invService.AddItem(itembase); | ||
907 | UUID LinkInvItem = UUID.Random(); | ||
908 | itembase = new InventoryItemBase(LinkInvItem, userID) | ||
909 | { | ||
910 | AssetID = | ||
911 | newInvItem, | ||
912 | AssetType | ||
913 | = | ||
914 | (int) | ||
915 | AssetType | ||
916 | .Link, | ||
917 | CreatorId | ||
918 | = | ||
919 | userID | ||
920 | .ToString | ||
921 | (), | ||
922 | InvType = (int) InventoryType.Wearable, | ||
923 | |||
924 | Description | ||
925 | = | ||
926 | "Failed Wearable Replacement", | ||
927 | Folder = | ||
928 | invService | ||
929 | .GetFolderForType | ||
930 | (userID, | ||
931 | AssetType | ||
932 | .CurrentOutfitFolder) | ||
933 | .ID, | ||
934 | Flags = (uint) type, | ||
935 | Name = Enum.GetName(typeof (WearableType), type), | ||
936 | BasePermissions = (uint) PermissionMask.Copy, | ||
937 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
938 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
939 | GroupPermissions = (uint) PermissionMask.Copy, | ||
940 | NextPermissions = (uint) PermissionMask.Copy | ||
941 | }; | ||
942 | invService.AddItem(itembase); | ||
943 | appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); | ||
944 | ScenePresence presence = null; | ||
945 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
946 | { | ||
947 | m_scene.SendInventoryUpdate(presence.ControllingClient, | ||
948 | invService.GetFolderForType(userID, | ||
949 | AssetType | ||
950 | .CurrentOutfitFolder), | ||
951 | false, true); | ||
952 | } | ||
953 | } | ||
954 | } | ||
955 | private UUID GetDefaultItem(WearableType wearable) | ||
956 | { | ||
957 | // These are ruth | ||
958 | UUID ret = UUID.Zero; | ||
959 | switch (wearable) | ||
960 | { | ||
961 | case WearableType.Eyes: | ||
962 | ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); | ||
963 | break; | ||
964 | case WearableType.Hair: | ||
965 | ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); | ||
966 | break; | ||
967 | case WearableType.Pants: | ||
968 | ret = new UUID("00000000-38f9-1111-024e-222222111120"); | ||
969 | break; | ||
970 | case WearableType.Shape: | ||
971 | ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); | ||
972 | break; | ||
973 | case WearableType.Shirt: | ||
974 | ret = new UUID("00000000-38f9-1111-024e-222222111110"); | ||
975 | break; | ||
976 | case WearableType.Skin: | ||
977 | ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); | ||
978 | break; | ||
979 | case WearableType.Undershirt: | ||
980 | ret = new UUID("16499ebb-3208-ec27-2def-481881728f47"); | ||
981 | break; | ||
982 | case WearableType.Underpants: | ||
983 | ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d"); | ||
984 | break; | ||
985 | } | ||
596 | 986 | ||
987 | return ret; | ||
988 | } | ||
597 | #endregion | 989 | #endregion |
598 | 990 | ||
599 | #region Client Event Handlers | 991 | #region Client Event Handlers |
@@ -603,12 +995,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
603 | /// <param name="client"></param> | 995 | /// <param name="client"></param> |
604 | private void Client_OnRequestWearables(IClientAPI client) | 996 | private void Client_OnRequestWearables(IClientAPI client) |
605 | { | 997 | { |
606 | // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); | 998 | Util.FireAndForget(delegate(object x) |
607 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 999 | { |
608 | if (sp != null) | 1000 | Thread.Sleep(4000); |
609 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | 1001 | |
610 | else | 1002 | // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); |
611 | m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); | 1003 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
1004 | if (sp != null) | ||
1005 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | ||
1006 | else | ||
1007 | m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); | ||
1008 | }); | ||
612 | } | 1009 | } |
613 | 1010 | ||
614 | /// <summary> | 1011 | /// <summary> |
@@ -617,12 +1014,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
617 | /// <param name="client"></param> | 1014 | /// <param name="client"></param> |
618 | /// <param name="texture"></param> | 1015 | /// <param name="texture"></param> |
619 | /// <param name="visualParam"></param> | 1016 | /// <param name="visualParam"></param> |
620 | private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) | 1017 | private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) |
621 | { | 1018 | { |
622 | // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); | 1019 | // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); |
623 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 1020 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
624 | if (sp != null) | 1021 | if (sp != null) |
625 | SetAppearance(sp, textureEntry, visualParams); | 1022 | SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems); |
626 | else | 1023 | else |
627 | m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); | 1024 | m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); |
628 | } | 1025 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index 1830d41..f090e15 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | |||
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
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.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); | 64 | afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams, new WearableCacheItem[0]); |
65 | 65 | ||
66 | // TODO: Check baked texture | 66 | // TODO: Check baked texture |
67 | Assert.AreEqual(visualParams, sp.Appearance.VisualParams); | 67 | Assert.AreEqual(visualParams, sp.Appearance.VisualParams); |
@@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
102 | Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); | 102 | Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); |
103 | eyesFace.TextureID = eyesTextureId; | 103 | eyesFace.TextureID = eyesTextureId; |
104 | 104 | ||
105 | afm.SetAppearance(sp, bakedTextureEntry, visualParams); | 105 | afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]); |
106 | afm.SaveBakedTextures(userId); | 106 | afm.SaveBakedTextures(userId); |
107 | // Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); | 107 | // Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); |
108 | 108 | ||