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 00d1fd8..864f33e 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 |
@@ -548,26 +677,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
548 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) | 677 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) |
549 | { | 678 | { |
550 | IInventoryService invService = m_scene.InventoryService; | 679 | IInventoryService invService = m_scene.InventoryService; |
551 | 680 | bool resetwearable = false; | |
552 | if (invService.GetRootFolder(userID) != null) | 681 | if (invService.GetRootFolder(userID) != null) |
553 | { | 682 | { |
554 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | 683 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) |
555 | { | 684 | { |
556 | for (int j = 0; j < appearance.Wearables[i].Count; j++) | 685 | for (int j = 0; j < appearance.Wearables[i].Count; j++) |
557 | { | 686 | { |
687 | // Check if the default wearables are not set | ||
558 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) | 688 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) |
689 | { | ||
690 | switch ((WearableType) i) | ||
691 | { | ||
692 | case WearableType.Eyes: | ||
693 | case WearableType.Hair: | ||
694 | case WearableType.Shape: | ||
695 | case WearableType.Skin: | ||
696 | //case WearableType.Underpants: | ||
697 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
698 | resetwearable = true; | ||
699 | m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); | ||
700 | resetwearable = true; | ||
701 | break; | ||
702 | |||
703 | } | ||
559 | continue; | 704 | continue; |
705 | } | ||
560 | 706 | ||
561 | // Ignore ruth's assets | 707 | // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 |
562 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 708 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
709 | { | ||
710 | switch ((WearableType)i) | ||
711 | { | ||
712 | case WearableType.Eyes: | ||
713 | case WearableType.Hair: | ||
714 | case WearableType.Shape: | ||
715 | case WearableType.Skin: | ||
716 | //case WearableType.Underpants: | ||
717 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
718 | |||
719 | m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); | ||
720 | resetwearable = true; | ||
721 | break; | ||
722 | |||
723 | } | ||
563 | continue; | 724 | continue; |
564 | 725 | } | |
726 | |||
565 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 727 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
566 | baseItem = invService.GetItem(baseItem); | 728 | baseItem = invService.GetItem(baseItem); |
567 | 729 | ||
568 | if (baseItem != null) | 730 | if (baseItem != null) |
569 | { | 731 | { |
570 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); | 732 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); |
733 | int unmodifiedWearableIndexForClosure = i; | ||
734 | m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, | ||
735 | delegate(string x, object y, AssetBase z) | ||
736 | { | ||
737 | if (z == null) | ||
738 | { | ||
739 | TryAndRepairBrokenWearable( | ||
740 | (WearableType)unmodifiedWearableIndexForClosure, invService, | ||
741 | userID, appearance); | ||
742 | } | ||
743 | }); | ||
571 | } | 744 | } |
572 | else | 745 | else |
573 | { | 746 | { |
@@ -575,17 +748,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
575 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", | 748 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", |
576 | appearance.Wearables[i][j].ItemID, (WearableType)i); | 749 | appearance.Wearables[i][j].ItemID, (WearableType)i); |
577 | 750 | ||
578 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); | 751 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); |
752 | resetwearable = true; | ||
753 | |||
579 | } | 754 | } |
580 | } | 755 | } |
581 | } | 756 | } |
757 | |||
758 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
759 | if (appearance.Wearables[(int) WearableType.Eyes] == null) | ||
760 | { | ||
761 | m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); | ||
762 | |||
763 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
764 | resetwearable = true; | ||
765 | } | ||
766 | else | ||
767 | { | ||
768 | if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) | ||
769 | { | ||
770 | m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", | ||
771 | appearance.Wearables[(int) WearableType.Eyes][0].ItemID, | ||
772 | appearance.Wearables[(int) WearableType.Eyes][0].AssetID); | ||
773 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
774 | resetwearable = true; | ||
775 | |||
776 | } | ||
777 | |||
778 | } | ||
779 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
780 | if (appearance.Wearables[(int)WearableType.Shape] == null) | ||
781 | { | ||
782 | m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); | ||
783 | |||
784 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
785 | resetwearable = true; | ||
786 | } | ||
787 | else | ||
788 | { | ||
789 | if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) | ||
790 | { | ||
791 | m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", | ||
792 | appearance.Wearables[(int)WearableType.Shape][0].ItemID, | ||
793 | appearance.Wearables[(int)WearableType.Shape][0].AssetID); | ||
794 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
795 | resetwearable = true; | ||
796 | |||
797 | } | ||
798 | |||
799 | } | ||
800 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
801 | if (appearance.Wearables[(int)WearableType.Hair] == null) | ||
802 | { | ||
803 | m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); | ||
804 | |||
805 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
806 | resetwearable = true; | ||
807 | } | ||
808 | else | ||
809 | { | ||
810 | if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) | ||
811 | { | ||
812 | m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", | ||
813 | appearance.Wearables[(int)WearableType.Hair][0].ItemID, | ||
814 | appearance.Wearables[(int)WearableType.Hair][0].AssetID); | ||
815 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
816 | resetwearable = true; | ||
817 | |||
818 | } | ||
819 | |||
820 | } | ||
821 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
822 | if (appearance.Wearables[(int)WearableType.Skin] == null) | ||
823 | { | ||
824 | m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); | ||
825 | |||
826 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
827 | resetwearable = true; | ||
828 | } | ||
829 | else | ||
830 | { | ||
831 | if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) | ||
832 | { | ||
833 | m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", | ||
834 | appearance.Wearables[(int)WearableType.Skin][0].ItemID, | ||
835 | appearance.Wearables[(int)WearableType.Skin][0].AssetID); | ||
836 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
837 | resetwearable = true; | ||
838 | |||
839 | } | ||
840 | |||
841 | } | ||
842 | if (resetwearable) | ||
843 | { | ||
844 | ScenePresence presence = null; | ||
845 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
846 | { | ||
847 | presence.ControllingClient.SendWearables(presence.Appearance.Wearables, | ||
848 | presence.Appearance.Serial++); | ||
849 | } | ||
850 | } | ||
851 | |||
582 | } | 852 | } |
583 | else | 853 | else |
584 | { | 854 | { |
585 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); | 855 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); |
586 | } | 856 | } |
587 | } | 857 | } |
858 | private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) | ||
859 | { | ||
860 | UUID defaultwearable = GetDefaultItem(type); | ||
861 | if (defaultwearable != UUID.Zero) | ||
862 | { | ||
863 | UUID newInvItem = UUID.Random(); | ||
864 | InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) | ||
865 | { | ||
866 | AssetID = | ||
867 | defaultwearable, | ||
868 | AssetType | ||
869 | = | ||
870 | (int) | ||
871 | AssetType | ||
872 | .Bodypart, | ||
873 | CreatorId | ||
874 | = | ||
875 | userID | ||
876 | .ToString | ||
877 | (), | ||
878 | //InvType = (int)InventoryType.Wearable, | ||
879 | |||
880 | Description | ||
881 | = | ||
882 | "Failed Wearable Replacement", | ||
883 | Folder = | ||
884 | invService | ||
885 | .GetFolderForType | ||
886 | (userID, | ||
887 | AssetType | ||
888 | .Bodypart) | ||
889 | .ID, | ||
890 | Flags = (uint) type, | ||
891 | Name = Enum.GetName(typeof (WearableType), type), | ||
892 | BasePermissions = (uint) PermissionMask.Copy, | ||
893 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
894 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
895 | GroupPermissions = (uint) PermissionMask.Copy, | ||
896 | NextPermissions = (uint) PermissionMask.Copy | ||
897 | }; | ||
898 | invService.AddItem(itembase); | ||
899 | UUID LinkInvItem = UUID.Random(); | ||
900 | itembase = new InventoryItemBase(LinkInvItem, userID) | ||
901 | { | ||
902 | AssetID = | ||
903 | newInvItem, | ||
904 | AssetType | ||
905 | = | ||
906 | (int) | ||
907 | AssetType | ||
908 | .Link, | ||
909 | CreatorId | ||
910 | = | ||
911 | userID | ||
912 | .ToString | ||
913 | (), | ||
914 | InvType = (int) InventoryType.Wearable, | ||
915 | |||
916 | Description | ||
917 | = | ||
918 | "Failed Wearable Replacement", | ||
919 | Folder = | ||
920 | invService | ||
921 | .GetFolderForType | ||
922 | (userID, | ||
923 | AssetType | ||
924 | .CurrentOutfitFolder) | ||
925 | .ID, | ||
926 | Flags = (uint) type, | ||
927 | Name = Enum.GetName(typeof (WearableType), type), | ||
928 | BasePermissions = (uint) PermissionMask.Copy, | ||
929 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
930 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
931 | GroupPermissions = (uint) PermissionMask.Copy, | ||
932 | NextPermissions = (uint) PermissionMask.Copy | ||
933 | }; | ||
934 | invService.AddItem(itembase); | ||
935 | appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); | ||
936 | ScenePresence presence = null; | ||
937 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
938 | { | ||
939 | m_scene.SendInventoryUpdate(presence.ControllingClient, | ||
940 | invService.GetFolderForType(userID, | ||
941 | AssetType | ||
942 | .CurrentOutfitFolder), | ||
943 | false, true); | ||
944 | } | ||
945 | } | ||
946 | } | ||
947 | private UUID GetDefaultItem(WearableType wearable) | ||
948 | { | ||
949 | // These are ruth | ||
950 | UUID ret = UUID.Zero; | ||
951 | switch (wearable) | ||
952 | { | ||
953 | case WearableType.Eyes: | ||
954 | ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); | ||
955 | break; | ||
956 | case WearableType.Hair: | ||
957 | ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); | ||
958 | break; | ||
959 | case WearableType.Pants: | ||
960 | ret = new UUID("00000000-38f9-1111-024e-222222111120"); | ||
961 | break; | ||
962 | case WearableType.Shape: | ||
963 | ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); | ||
964 | break; | ||
965 | case WearableType.Shirt: | ||
966 | ret = new UUID("00000000-38f9-1111-024e-222222111110"); | ||
967 | break; | ||
968 | case WearableType.Skin: | ||
969 | ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); | ||
970 | break; | ||
971 | case WearableType.Undershirt: | ||
972 | ret = new UUID("16499ebb-3208-ec27-2def-481881728f47"); | ||
973 | break; | ||
974 | case WearableType.Underpants: | ||
975 | ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d"); | ||
976 | break; | ||
977 | } | ||
588 | 978 | ||
979 | return ret; | ||
980 | } | ||
589 | #endregion | 981 | #endregion |
590 | 982 | ||
591 | #region Client Event Handlers | 983 | #region Client Event Handlers |
@@ -595,12 +987,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
595 | /// <param name="client"></param> | 987 | /// <param name="client"></param> |
596 | private void Client_OnRequestWearables(IClientAPI client) | 988 | private void Client_OnRequestWearables(IClientAPI client) |
597 | { | 989 | { |
598 | // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); | 990 | Util.FireAndForget(delegate(object x) |
599 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 991 | { |
600 | if (sp != null) | 992 | Thread.Sleep(4000); |
601 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | 993 | |
602 | else | 994 | // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); |
603 | m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); | 995 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
996 | if (sp != null) | ||
997 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | ||
998 | else | ||
999 | m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); | ||
1000 | }); | ||
604 | } | 1001 | } |
605 | 1002 | ||
606 | /// <summary> | 1003 | /// <summary> |
@@ -609,12 +1006,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
609 | /// <param name="client"></param> | 1006 | /// <param name="client"></param> |
610 | /// <param name="texture"></param> | 1007 | /// <param name="texture"></param> |
611 | /// <param name="visualParam"></param> | 1008 | /// <param name="visualParam"></param> |
612 | private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) | 1009 | private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) |
613 | { | 1010 | { |
614 | // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); | 1011 | // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); |
615 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 1012 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
616 | if (sp != null) | 1013 | if (sp != null) |
617 | SetAppearance(sp, textureEntry, visualParams); | 1014 | SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems); |
618 | else | 1015 | else |
619 | m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); | 1016 | m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); |
620 | } | 1017 | } |
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 | ||