diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/AvatarFactory')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 414 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | 96 |
2 files changed, 325 insertions, 185 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 22f0366..1e9cfba 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
229 | private void SendAppearance(ScenePresence sp) | 229 | private void SendAppearance(ScenePresence sp) |
230 | { | 230 | { |
231 | // Send the appearance to everyone in the scene | 231 | // Send the appearance to everyone in the scene |
232 | sp.SendAppearanceToAllOtherAgents(); | 232 | sp.SendAppearanceToAllOtherClients(); |
233 | 233 | ||
234 | // Send animations back to the avatar as well | 234 | // Send animations back to the avatar as well |
235 | sp.Animator.SendAnimPack(); | 235 | sp.Animator.SendAnimPack(); |
@@ -529,6 +529,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
529 | ); | 529 | ); |
530 | } | 530 | } |
531 | } | 531 | } |
532 | <<<<<<< HEAD | ||
533 | |||
534 | // m_log.DebugFormat( | ||
535 | // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", | ||
536 | // face.TextureID, idx, client.Name, client.AgentId); | ||
537 | ======= | ||
532 | */ | 538 | */ |
533 | bool wearableCacheValid = false; | 539 | bool wearableCacheValid = false; |
534 | if (wearableCache == null) | 540 | if (wearableCache == null) |
@@ -571,9 +577,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
571 | if (wearableCacheValid) | 577 | if (wearableCacheValid) |
572 | m_log.Debug("[ValidateBakedCache] have valid local cache"); | 578 | m_log.Debug("[ValidateBakedCache] have valid local cache"); |
573 | } | 579 | } |
580 | >>>>>>> avn/ubitvar | ||
574 | 581 | ||
575 | bool checkExternal = false; | 582 | bool checkExternal = false; |
576 | 583 | ||
584 | <<<<<<< HEAD | ||
585 | if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) | ||
586 | return false; | ||
587 | } | ||
588 | ======= | ||
577 | if (!wearableCacheValid) | 589 | if (!wearableCacheValid) |
578 | { | 590 | { |
579 | // only use external bake module on login condition check | 591 | // only use external bake module on login condition check |
@@ -646,6 +658,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
646 | } | 658 | } |
647 | } | 659 | } |
648 | } | 660 | } |
661 | >>>>>>> avn/ubitvar | ||
649 | 662 | ||
650 | sp.Appearance.WearableCacheItems = wearableCache; | 663 | sp.Appearance.WearableCacheItems = wearableCache; |
651 | 664 | ||
@@ -672,7 +685,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
672 | return 0; | 685 | return 0; |
673 | 686 | ||
674 | int texturesRebaked = 0; | 687 | int texturesRebaked = 0; |
675 | IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); | 688 | // IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); |
676 | 689 | ||
677 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) | 690 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) |
678 | { | 691 | { |
@@ -688,36 +701,21 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
688 | 701 | ||
689 | if (missingTexturesOnly) | 702 | if (missingTexturesOnly) |
690 | { | 703 | { |
691 | if (cache != null) | 704 | if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) |
692 | { | 705 | { |
693 | if (cache.Check(face.TextureID.ToString())) | 706 | continue; |
694 | continue; | ||
695 | else | ||
696 | { | ||
697 | m_log.DebugFormat( | ||
698 | "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", | ||
699 | face.TextureID, idx, sp.Name); | ||
700 | } | ||
701 | } | 707 | } |
702 | else | 708 | else |
703 | { | 709 | { |
704 | if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) | 710 | // On inter-simulator teleports, this occurs if baked textures are not being stored by the |
705 | { | 711 | // grid asset service (which means that they are not available to the new region and so have |
706 | continue; | 712 | // to be re-requested from the client). |
707 | } | 713 | // |
708 | 714 | // The only available core OpenSimulator behaviour right now | |
709 | else | 715 | // is not to store these textures, temporarily or otherwise. |
710 | { | 716 | m_log.DebugFormat( |
711 | // On inter-simulator teleports, this occurs if baked textures are not being stored by the | 717 | "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", |
712 | // grid asset service (which means that they are not available to the new region and so have | 718 | face.TextureID, idx, sp.Name); |
713 | // to be re-requested from the client). | ||
714 | // | ||
715 | // The only available core OpenSimulator behaviour right now | ||
716 | // is not to store these textures, temporarily or otherwise. | ||
717 | m_log.DebugFormat( | ||
718 | "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", | ||
719 | face.TextureID, idx, sp.Name); | ||
720 | } | ||
721 | } | 719 | } |
722 | } | 720 | } |
723 | else | 721 | else |
@@ -786,7 +784,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
786 | 784 | ||
787 | if (sendTime < now) | 785 | if (sendTime < now) |
788 | { | 786 | { |
789 | Util.FireAndForget(o => SendAppearance(avatarID)); | 787 | Util.FireAndForget(o => SendAppearance(avatarID), null, "AvatarFactoryModule.SendAppearance"); |
790 | m_sendqueue.Remove(avatarID); | 788 | m_sendqueue.Remove(avatarID); |
791 | } | 789 | } |
792 | } | 790 | } |
@@ -804,7 +802,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
804 | 802 | ||
805 | if (sendTime < now) | 803 | if (sendTime < now) |
806 | { | 804 | { |
807 | Util.FireAndForget(o => SaveAppearance(avatarID)); | 805 | Util.FireAndForget(o => SaveAppearance(avatarID), null, "AvatarFactoryModule.SaveAppearance"); |
808 | m_savequeue.Remove(avatarID); | 806 | m_savequeue.Remove(avatarID); |
809 | } | 807 | } |
810 | } | 808 | } |
@@ -856,187 +854,238 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
856 | m_scene.EventManager.TriggerAvatarAppearanceChanged(sp); | 854 | m_scene.EventManager.TriggerAvatarAppearanceChanged(sp); |
857 | } | 855 | } |
858 | 856 | ||
857 | /// <summary> | ||
858 | /// For a given set of appearance items, check whether the items are valid and add their asset IDs to | ||
859 | /// appearance data. | ||
860 | /// </summary> | ||
861 | /// <param name='userID'></param> | ||
862 | /// <param name='appearance'></param> | ||
859 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) | 863 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) |
860 | { | 864 | { |
861 | IInventoryService invService = m_scene.InventoryService; | 865 | IInventoryService invService = m_scene.InventoryService; |
862 | bool resetwearable = false; | 866 | |
863 | if (invService.GetRootFolder(userID) != null) | 867 | if (invService.GetRootFolder(userID) != null) |
864 | { | 868 | { |
865 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | 869 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) |
866 | { | 870 | { |
867 | for (int j = 0; j < appearance.Wearables[i].Count; j++) | 871 | for (int j = 0; j < appearance.Wearables[i].Count; j++) |
868 | { | 872 | { |
869 | // Check if the default wearables are not set | ||
870 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) | 873 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) |
871 | { | 874 | { |
872 | switch ((WearableType) i) | 875 | m_log.WarnFormat( |
873 | { | 876 | "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.", |
874 | case WearableType.Eyes: | 877 | i, j, userID); |
875 | case WearableType.Hair: | ||
876 | case WearableType.Shape: | ||
877 | case WearableType.Skin: | ||
878 | //case WearableType.Underpants: | ||
879 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
880 | resetwearable = true; | ||
881 | m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); | ||
882 | resetwearable = true; | ||
883 | break; | ||
884 | 878 | ||
885 | } | ||
886 | continue; | 879 | continue; |
887 | } | 880 | } |
888 | 881 | ||
889 | // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 | 882 | // Ignore ruth's assets |
890 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 883 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
891 | { | ||
892 | switch ((WearableType)i) | ||
893 | { | ||
894 | case WearableType.Eyes: | ||
895 | case WearableType.Hair: | ||
896 | case WearableType.Shape: | ||
897 | case WearableType.Skin: | ||
898 | //case WearableType.Underpants: | ||
899 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
900 | |||
901 | m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); | ||
902 | resetwearable = true; | ||
903 | break; | ||
904 | |||
905 | } | ||
906 | continue; | 884 | continue; |
907 | } | 885 | |
908 | |||
909 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 886 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
910 | baseItem = invService.GetItem(baseItem); | 887 | baseItem = invService.GetItem(baseItem); |
911 | 888 | ||
912 | if (baseItem != null) | 889 | if (baseItem != null) |
913 | { | 890 | { |
914 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); | 891 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); |
915 | int unmodifiedWearableIndexForClosure = i; | ||
916 | m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, | ||
917 | delegate(string x, object y, AssetBase z) | ||
918 | { | ||
919 | if (z == null) | ||
920 | { | ||
921 | TryAndRepairBrokenWearable( | ||
922 | (WearableType)unmodifiedWearableIndexForClosure, invService, | ||
923 | userID, appearance); | ||
924 | } | ||
925 | }); | ||
926 | } | 892 | } |
927 | else | 893 | else |
928 | { | 894 | { |
929 | m_log.ErrorFormat( | 895 | m_log.WarnFormat( |
930 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", | 896 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", |
931 | appearance.Wearables[i][j].ItemID, (WearableType)i); | 897 | appearance.Wearables[i][j].ItemID, (WearableType)i); |
932 | 898 | ||
933 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | 899 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); |
934 | resetwearable = true; | ||
935 | |||
936 | } | 900 | } |
937 | } | 901 | } |
938 | } | 902 | } |
939 | |||
940 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
941 | if (appearance.Wearables[(int) WearableType.Eyes] == null) | ||
942 | { | ||
943 | m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); | ||
944 | |||
945 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
946 | resetwearable = true; | ||
947 | } | ||
948 | else | ||
949 | { | ||
950 | if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) | ||
951 | { | ||
952 | m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", | ||
953 | appearance.Wearables[(int) WearableType.Eyes][0].ItemID, | ||
954 | appearance.Wearables[(int) WearableType.Eyes][0].AssetID); | ||
955 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
956 | resetwearable = true; | ||
957 | |||
958 | } | ||
959 | |||
960 | } | ||
961 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
962 | if (appearance.Wearables[(int)WearableType.Shape] == null) | ||
963 | { | ||
964 | m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); | ||
965 | |||
966 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
967 | resetwearable = true; | ||
968 | } | ||
969 | else | ||
970 | { | ||
971 | if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) | ||
972 | { | ||
973 | m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", | ||
974 | appearance.Wearables[(int)WearableType.Shape][0].ItemID, | ||
975 | appearance.Wearables[(int)WearableType.Shape][0].AssetID); | ||
976 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
977 | resetwearable = true; | ||
978 | |||
979 | } | ||
980 | |||
981 | } | ||
982 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
983 | if (appearance.Wearables[(int)WearableType.Hair] == null) | ||
984 | { | ||
985 | m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); | ||
986 | |||
987 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
988 | resetwearable = true; | ||
989 | } | ||
990 | else | ||
991 | { | ||
992 | if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) | ||
993 | { | ||
994 | m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", | ||
995 | appearance.Wearables[(int)WearableType.Hair][0].ItemID, | ||
996 | appearance.Wearables[(int)WearableType.Hair][0].AssetID); | ||
997 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
998 | resetwearable = true; | ||
999 | |||
1000 | } | ||
1001 | |||
1002 | } | ||
1003 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
1004 | if (appearance.Wearables[(int)WearableType.Skin] == null) | ||
1005 | { | ||
1006 | m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); | ||
1007 | |||
1008 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
1009 | resetwearable = true; | ||
1010 | } | ||
1011 | else | ||
1012 | { | ||
1013 | if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) | ||
1014 | { | ||
1015 | m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", | ||
1016 | appearance.Wearables[(int)WearableType.Skin][0].ItemID, | ||
1017 | appearance.Wearables[(int)WearableType.Skin][0].AssetID); | ||
1018 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
1019 | resetwearable = true; | ||
1020 | |||
1021 | } | ||
1022 | |||
1023 | } | ||
1024 | if (resetwearable) | ||
1025 | { | ||
1026 | ScenePresence presence = null; | ||
1027 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
1028 | { | ||
1029 | presence.ControllingClient.SendWearables(presence.Appearance.Wearables, | ||
1030 | presence.Appearance.Serial++); | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | } | 903 | } |
1035 | else | 904 | else |
1036 | { | 905 | { |
1037 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); | 906 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); |
1038 | } | 907 | } |
908 | |||
909 | // IInventoryService invService = m_scene.InventoryService; | ||
910 | // bool resetwearable = false; | ||
911 | // if (invService.GetRootFolder(userID) != null) | ||
912 | // { | ||
913 | // for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | ||
914 | // { | ||
915 | // for (int j = 0; j < appearance.Wearables[i].Count; j++) | ||
916 | // { | ||
917 | // // Check if the default wearables are not set | ||
918 | // if (appearance.Wearables[i][j].ItemID == UUID.Zero) | ||
919 | // { | ||
920 | // switch ((WearableType) i) | ||
921 | // { | ||
922 | // case WearableType.Eyes: | ||
923 | // case WearableType.Hair: | ||
924 | // case WearableType.Shape: | ||
925 | // case WearableType.Skin: | ||
926 | // //case WearableType.Underpants: | ||
927 | // TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
928 | // resetwearable = true; | ||
929 | // m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); | ||
930 | // resetwearable = true; | ||
931 | // break; | ||
932 | // | ||
933 | // } | ||
934 | // continue; | ||
935 | // } | ||
936 | // | ||
937 | // // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 | ||
938 | // if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | ||
939 | // { | ||
940 | // switch ((WearableType)i) | ||
941 | // { | ||
942 | // case WearableType.Eyes: | ||
943 | // case WearableType.Hair: | ||
944 | // case WearableType.Shape: | ||
945 | // case WearableType.Skin: | ||
946 | // //case WearableType.Underpants: | ||
947 | // TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
948 | // | ||
949 | // m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); | ||
950 | // resetwearable = true; | ||
951 | // break; | ||
952 | // | ||
953 | // } | ||
954 | // continue; | ||
955 | // } | ||
956 | // | ||
957 | // InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | ||
958 | // baseItem = invService.GetItem(baseItem); | ||
959 | // | ||
960 | // if (baseItem != null) | ||
961 | // { | ||
962 | // appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); | ||
963 | // int unmodifiedWearableIndexForClosure = i; | ||
964 | // m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, | ||
965 | // delegate(string x, object y, AssetBase z) | ||
966 | // { | ||
967 | // if (z == null) | ||
968 | // { | ||
969 | // TryAndRepairBrokenWearable( | ||
970 | // (WearableType)unmodifiedWearableIndexForClosure, invService, | ||
971 | // userID, appearance); | ||
972 | // } | ||
973 | // }); | ||
974 | // } | ||
975 | // else | ||
976 | // { | ||
977 | // m_log.ErrorFormat( | ||
978 | // "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", | ||
979 | // appearance.Wearables[i][j].ItemID, (WearableType)i); | ||
980 | // | ||
981 | // TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
982 | // resetwearable = true; | ||
983 | // | ||
984 | // } | ||
985 | // } | ||
986 | // } | ||
987 | // | ||
988 | // // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
989 | // if (appearance.Wearables[(int) WearableType.Eyes] == null) | ||
990 | // { | ||
991 | // m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); | ||
992 | // | ||
993 | // TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
994 | // resetwearable = true; | ||
995 | // } | ||
996 | // else | ||
997 | // { | ||
998 | // if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) | ||
999 | // { | ||
1000 | // m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", | ||
1001 | // appearance.Wearables[(int) WearableType.Eyes][0].ItemID, | ||
1002 | // appearance.Wearables[(int) WearableType.Eyes][0].AssetID); | ||
1003 | // TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
1004 | // resetwearable = true; | ||
1005 | // | ||
1006 | // } | ||
1007 | // | ||
1008 | // } | ||
1009 | // // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
1010 | // if (appearance.Wearables[(int)WearableType.Shape] == null) | ||
1011 | // { | ||
1012 | // m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); | ||
1013 | // | ||
1014 | // TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
1015 | // resetwearable = true; | ||
1016 | // } | ||
1017 | // else | ||
1018 | // { | ||
1019 | // if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) | ||
1020 | // { | ||
1021 | // m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", | ||
1022 | // appearance.Wearables[(int)WearableType.Shape][0].ItemID, | ||
1023 | // appearance.Wearables[(int)WearableType.Shape][0].AssetID); | ||
1024 | // TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
1025 | // resetwearable = true; | ||
1026 | // | ||
1027 | // } | ||
1028 | // | ||
1029 | // } | ||
1030 | // // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
1031 | // if (appearance.Wearables[(int)WearableType.Hair] == null) | ||
1032 | // { | ||
1033 | // m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); | ||
1034 | // | ||
1035 | // TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
1036 | // resetwearable = true; | ||
1037 | // } | ||
1038 | // else | ||
1039 | // { | ||
1040 | // if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) | ||
1041 | // { | ||
1042 | // m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", | ||
1043 | // appearance.Wearables[(int)WearableType.Hair][0].ItemID, | ||
1044 | // appearance.Wearables[(int)WearableType.Hair][0].AssetID); | ||
1045 | // TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
1046 | // resetwearable = true; | ||
1047 | // | ||
1048 | // } | ||
1049 | // | ||
1050 | // } | ||
1051 | // // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
1052 | // if (appearance.Wearables[(int)WearableType.Skin] == null) | ||
1053 | // { | ||
1054 | // m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); | ||
1055 | // | ||
1056 | // TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
1057 | // resetwearable = true; | ||
1058 | // } | ||
1059 | // else | ||
1060 | // { | ||
1061 | // if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) | ||
1062 | // { | ||
1063 | // m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", | ||
1064 | // appearance.Wearables[(int)WearableType.Skin][0].ItemID, | ||
1065 | // appearance.Wearables[(int)WearableType.Skin][0].AssetID); | ||
1066 | // TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
1067 | // resetwearable = true; | ||
1068 | // | ||
1069 | // } | ||
1070 | // | ||
1071 | // } | ||
1072 | // if (resetwearable) | ||
1073 | // { | ||
1074 | // ScenePresence presence = null; | ||
1075 | // if (m_scene.TryGetScenePresence(userID, out presence)) | ||
1076 | // { | ||
1077 | // presence.ControllingClient.SendWearables(presence.Appearance.Wearables, | ||
1078 | // presence.Appearance.Serial++); | ||
1079 | // } | ||
1080 | // } | ||
1081 | // | ||
1082 | // } | ||
1083 | // else | ||
1084 | // { | ||
1085 | // m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); | ||
1086 | // } | ||
1039 | } | 1087 | } |
1088 | |||
1040 | private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) | 1089 | private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) |
1041 | { | 1090 | { |
1042 | UUID defaultwearable = GetDefaultItem(type); | 1091 | UUID defaultwearable = GetDefaultItem(type); |
@@ -1050,8 +1099,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
1050 | AssetType | 1099 | AssetType |
1051 | = | 1100 | = |
1052 | (int) | 1101 | (int) |
1053 | AssetType | 1102 | FolderType |
1054 | .Bodypart, | 1103 | .BodyPart, |
1055 | CreatorId | 1104 | CreatorId |
1056 | = | 1105 | = |
1057 | userID | 1106 | userID |
@@ -1066,8 +1115,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
1066 | invService | 1115 | invService |
1067 | .GetFolderForType | 1116 | .GetFolderForType |
1068 | (userID, | 1117 | (userID, |
1069 | AssetType | 1118 | FolderType |
1070 | .Bodypart) | 1119 | .BodyPart) |
1071 | .ID, | 1120 | .ID, |
1072 | Flags = (uint) type, | 1121 | Flags = (uint) type, |
1073 | Name = Enum.GetName(typeof (WearableType), type), | 1122 | Name = Enum.GetName(typeof (WearableType), type), |
@@ -1102,8 +1151,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
1102 | invService | 1151 | invService |
1103 | .GetFolderForType | 1152 | .GetFolderForType |
1104 | (userID, | 1153 | (userID, |
1105 | AssetType | 1154 | FolderType |
1106 | .CurrentOutfitFolder) | 1155 | .CurrentOutfit) |
1107 | .ID, | 1156 | .ID, |
1108 | Flags = (uint) type, | 1157 | Flags = (uint) type, |
1109 | Name = Enum.GetName(typeof (WearableType), type), | 1158 | Name = Enum.GetName(typeof (WearableType), type), |
@@ -1120,12 +1169,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
1120 | { | 1169 | { |
1121 | m_scene.SendInventoryUpdate(presence.ControllingClient, | 1170 | m_scene.SendInventoryUpdate(presence.ControllingClient, |
1122 | invService.GetFolderForType(userID, | 1171 | invService.GetFolderForType(userID, |
1123 | AssetType | 1172 | FolderType |
1124 | .CurrentOutfitFolder), | 1173 | .CurrentOutfit), |
1125 | false, true); | 1174 | false, true); |
1126 | } | 1175 | } |
1127 | } | 1176 | } |
1128 | } | 1177 | } |
1178 | |||
1129 | private UUID GetDefaultItem(WearableType wearable) | 1179 | private UUID GetDefaultItem(WearableType wearable) |
1130 | { | 1180 | { |
1131 | // These are ruth | 1181 | // These are ruth |
@@ -1179,7 +1229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
1179 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | 1229 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); |
1180 | else | 1230 | else |
1181 | m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); | 1231 | m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); |
1182 | }); | 1232 | }, null, "AvatarFactoryModule.OnClientRequestWearables"); |
1183 | } | 1233 | } |
1184 | 1234 | ||
1185 | /// <summary> | 1235 | /// <summary> |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index f090e15..b7ff4e0 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | |||
@@ -34,7 +34,6 @@ using OpenSim.Framework; | |||
34 | using OpenSim.Region.CoreModules.Asset; | 34 | using OpenSim.Region.CoreModules.Asset; |
35 | using OpenSim.Region.Framework.Scenes; | 35 | using OpenSim.Region.Framework.Scenes; |
36 | using OpenSim.Tests.Common; | 36 | using OpenSim.Tests.Common; |
37 | using OpenSim.Tests.Common.Mock; | ||
38 | 37 | ||
39 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | 38 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory |
40 | { | 39 | { |
@@ -48,23 +47,110 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
48 | public void TestSetAppearance() | 47 | public void TestSetAppearance() |
49 | { | 48 | { |
50 | TestHelpers.InMethod(); | 49 | TestHelpers.InMethod(); |
51 | // log4net.Config.XmlConfigurator.Configure(); | 50 | // TestHelpers.EnableLogging(); |
51 | |||
52 | UUID userId = TestHelpers.ParseTail(0x1); | ||
53 | UUID bakedTextureID = TestHelpers.ParseTail(0x2); | ||
54 | |||
55 | // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly | ||
56 | // to the AssetService, which will then store temporary and local assets permanently | ||
57 | CoreAssetCache assetCache = new CoreAssetCache(); | ||
58 | |||
59 | AvatarFactoryModule afm = new AvatarFactoryModule(); | ||
60 | TestScene scene = new SceneHelpers(assetCache).SetupScene(); | ||
61 | SceneHelpers.SetupSceneModules(scene, afm); | ||
62 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); | ||
63 | |||
64 | // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules | ||
65 | AssetBase bakedTextureAsset; | ||
66 | bakedTextureAsset | ||
67 | = new AssetBase( | ||
68 | bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString()); | ||
69 | bakedTextureAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet | ||
70 | bakedTextureAsset.Temporary = true; | ||
71 | bakedTextureAsset.Local = true; | ||
72 | scene.AssetService.Store(bakedTextureAsset); | ||
73 | |||
74 | byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; | ||
75 | for (byte i = 0; i < visualParams.Length; i++) | ||
76 | visualParams[i] = i; | ||
77 | |||
78 | Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)); | ||
79 | uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes); | ||
80 | Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); | ||
81 | |||
82 | int rebakeRequestsReceived = 0; | ||
83 | ((TestClient)sp.ControllingClient).OnReceivedSendRebakeAvatarTextures += id => rebakeRequestsReceived++; | ||
84 | |||
85 | // This is the alpha texture | ||
86 | eyesFace.TextureID = bakedTextureID; | ||
87 | afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); | ||
88 | |||
89 | Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); | ||
90 | |||
91 | AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString()); | ||
92 | Assert.That(eyesBake, Is.Not.Null); | ||
93 | Assert.That(eyesBake.Temporary, Is.True); | ||
94 | Assert.That(eyesBake.Local, Is.True); | ||
95 | } | ||
96 | |||
97 | /// <summary> | ||
98 | /// Test appearance setting where the baked texture UUID are library alpha textures. | ||
99 | /// </summary> | ||
100 | /// <remarks> | ||
101 | /// For a mesh avatar, it appears these 'baked textures' are used. So these should not trigger a request to | ||
102 | /// rebake. | ||
103 | /// </remarks> | ||
104 | [Test] | ||
105 | public void TestSetAppearanceAlphaBakedTextures() | ||
106 | { | ||
107 | TestHelpers.InMethod(); | ||
108 | // TestHelpers.EnableLogging(); | ||
52 | 109 | ||
53 | UUID userId = TestHelpers.ParseTail(0x1); | 110 | UUID userId = TestHelpers.ParseTail(0x1); |
111 | UUID alphaTextureID = new UUID("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); | ||
54 | 112 | ||
113 | // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly | ||
114 | // to the AssetService, which will then store temporary and local assets permanently | ||
115 | CoreAssetCache assetCache = new CoreAssetCache(); | ||
116 | |||
55 | AvatarFactoryModule afm = new AvatarFactoryModule(); | 117 | AvatarFactoryModule afm = new AvatarFactoryModule(); |
56 | TestScene scene = new SceneHelpers().SetupScene(); | 118 | TestScene scene = new SceneHelpers(assetCache).SetupScene(); |
57 | SceneHelpers.SetupSceneModules(scene, afm); | 119 | SceneHelpers.SetupSceneModules(scene, afm); |
58 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); | 120 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); |
59 | 121 | ||
122 | AssetBase libraryAsset; | ||
123 | libraryAsset | ||
124 | = new AssetBase( | ||
125 | alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString()); | ||
126 | libraryAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet | ||
127 | libraryAsset.Temporary = false; | ||
128 | libraryAsset.Local = false; | ||
129 | scene.AssetService.Store(libraryAsset); | ||
130 | |||
60 | byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; | 131 | byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; |
61 | for (byte i = 0; i < visualParams.Length; i++) | 132 | for (byte i = 0; i < visualParams.Length; i++) |
62 | visualParams[i] = i; | 133 | visualParams[i] = i; |
63 | 134 | ||
135 | <<<<<<< HEAD | ||
136 | Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)); | ||
137 | uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes); | ||
138 | Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); | ||
139 | |||
140 | int rebakeRequestsReceived = 0; | ||
141 | ((TestClient)sp.ControllingClient).OnReceivedSendRebakeAvatarTextures += id => rebakeRequestsReceived++; | ||
142 | |||
143 | // This is the alpha texture | ||
144 | eyesFace.TextureID = alphaTextureID; | ||
145 | afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); | ||
146 | |||
147 | Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); | ||
148 | ======= | ||
64 | afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams, new WearableCacheItem[0]); | 149 | afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams, new WearableCacheItem[0]); |
65 | 150 | ||
66 | // TODO: Check baked texture | 151 | // TODO: Check baked texture |
67 | Assert.AreEqual(visualParams, sp.Appearance.VisualParams); | 152 | Assert.AreEqual(visualParams, sp.Appearance.VisualParams); |
153 | >>>>>>> avn/ubitvar | ||
68 | } | 154 | } |
69 | 155 | ||
70 | [Test] | 156 | [Test] |
@@ -102,7 +188,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
102 | Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); | 188 | Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); |
103 | eyesFace.TextureID = eyesTextureId; | 189 | eyesFace.TextureID = eyesTextureId; |
104 | 190 | ||
191 | <<<<<<< HEAD | ||
192 | afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); | ||
193 | ======= | ||
105 | afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]); | 194 | afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]); |
195 | >>>>>>> avn/ubitvar | ||
106 | afm.SaveBakedTextures(userId); | 196 | afm.SaveBakedTextures(userId); |
107 | // Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); | 197 | // Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); |
108 | 198 | ||