diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 289 |
1 files changed, 282 insertions, 7 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 7ec2860..bc79944 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -40,6 +40,7 @@ using OpenSim.Region.Framework.Scenes; | |||
40 | using OpenSim.Services.Interfaces; | 40 | using OpenSim.Services.Interfaces; |
41 | 41 | ||
42 | using Mono.Addins; | 42 | using Mono.Addins; |
43 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
43 | 44 | ||
44 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | 45 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory |
45 | { | 46 | { |
@@ -322,6 +323,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
322 | 323 | ||
323 | if (asset != null) | 324 | if (asset != null) |
324 | { | 325 | { |
326 | // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars | ||
327 | asset.ID = asset.FullID.ToString(); | ||
328 | |||
325 | asset.Temporary = false; | 329 | asset.Temporary = false; |
326 | asset.Local = false; | 330 | asset.Local = false; |
327 | m_scene.AssetService.Store(asset); | 331 | m_scene.AssetService.Store(asset); |
@@ -358,7 +362,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
358 | 362 | ||
359 | public void QueueAppearanceSave(UUID agentid) | 363 | public void QueueAppearanceSave(UUID agentid) |
360 | { | 364 | { |
361 | // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid); | 365 | // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); |
362 | 366 | ||
363 | // 10000 ticks per millisecond, 1000 milliseconds per second | 367 | // 10000 ticks per millisecond, 1000 milliseconds per second |
364 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); | 368 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); |
@@ -655,7 +659,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
655 | return; | 659 | return; |
656 | } | 660 | } |
657 | 661 | ||
658 | // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); | 662 | // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); |
659 | 663 | ||
660 | // This could take awhile since it needs to pull inventory | 664 | // This could take awhile since it needs to pull inventory |
661 | // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape | 665 | // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape |
@@ -664,6 +668,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
664 | // multiple save requests. | 668 | // multiple save requests. |
665 | SetAppearanceAssets(sp.UUID, sp.Appearance); | 669 | SetAppearanceAssets(sp.UUID, sp.Appearance); |
666 | 670 | ||
671 | // List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | ||
672 | // foreach (AvatarAttachment att in attachments) | ||
673 | // { | ||
674 | // m_log.DebugFormat( | ||
675 | // "[AVFACTORY]: For {0} saving attachment {1} at point {2}", | ||
676 | // sp.Name, att.ItemID, att.AttachPoint); | ||
677 | // } | ||
678 | |||
667 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); | 679 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); |
668 | 680 | ||
669 | // Trigger this here because it's the final step in the set/queue/save process for appearance setting. | 681 | // Trigger this here because it's the final step in the set/queue/save process for appearance setting. |
@@ -674,26 +686,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
674 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) | 686 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) |
675 | { | 687 | { |
676 | IInventoryService invService = m_scene.InventoryService; | 688 | IInventoryService invService = m_scene.InventoryService; |
677 | 689 | bool resetwearable = false; | |
678 | if (invService.GetRootFolder(userID) != null) | 690 | if (invService.GetRootFolder(userID) != null) |
679 | { | 691 | { |
680 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | 692 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) |
681 | { | 693 | { |
682 | for (int j = 0; j < appearance.Wearables[i].Count; j++) | 694 | for (int j = 0; j < appearance.Wearables[i].Count; j++) |
683 | { | 695 | { |
696 | // Check if the default wearables are not set | ||
684 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) | 697 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) |
698 | { | ||
699 | switch ((WearableType) i) | ||
700 | { | ||
701 | case WearableType.Eyes: | ||
702 | case WearableType.Hair: | ||
703 | case WearableType.Shape: | ||
704 | case WearableType.Skin: | ||
705 | //case WearableType.Underpants: | ||
706 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
707 | resetwearable = true; | ||
708 | m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); | ||
709 | resetwearable = true; | ||
710 | break; | ||
711 | |||
712 | } | ||
685 | continue; | 713 | continue; |
714 | } | ||
686 | 715 | ||
687 | // Ignore ruth's assets | 716 | // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 |
688 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 717 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
718 | { | ||
719 | switch ((WearableType)i) | ||
720 | { | ||
721 | case WearableType.Eyes: | ||
722 | case WearableType.Hair: | ||
723 | case WearableType.Shape: | ||
724 | case WearableType.Skin: | ||
725 | //case WearableType.Underpants: | ||
726 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
727 | |||
728 | m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); | ||
729 | resetwearable = true; | ||
730 | break; | ||
731 | |||
732 | } | ||
689 | continue; | 733 | continue; |
690 | 734 | } | |
735 | |||
691 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 736 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
692 | baseItem = invService.GetItem(baseItem); | 737 | baseItem = invService.GetItem(baseItem); |
693 | 738 | ||
694 | if (baseItem != null) | 739 | if (baseItem != null) |
695 | { | 740 | { |
696 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); | 741 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); |
742 | int unmodifiedWearableIndexForClosure = i; | ||
743 | m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, | ||
744 | delegate(string x, object y, AssetBase z) | ||
745 | { | ||
746 | if (z == null) | ||
747 | { | ||
748 | TryAndRepairBrokenWearable( | ||
749 | (WearableType)unmodifiedWearableIndexForClosure, invService, | ||
750 | userID, appearance); | ||
751 | } | ||
752 | }); | ||
697 | } | 753 | } |
698 | else | 754 | else |
699 | { | 755 | { |
@@ -701,17 +757,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
701 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", | 757 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", |
702 | appearance.Wearables[i][j].ItemID, (WearableType)i); | 758 | appearance.Wearables[i][j].ItemID, (WearableType)i); |
703 | 759 | ||
704 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); | 760 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); |
761 | resetwearable = true; | ||
762 | |||
705 | } | 763 | } |
706 | } | 764 | } |
707 | } | 765 | } |
766 | |||
767 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
768 | if (appearance.Wearables[(int) WearableType.Eyes] == null) | ||
769 | { | ||
770 | m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); | ||
771 | |||
772 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
773 | resetwearable = true; | ||
774 | } | ||
775 | else | ||
776 | { | ||
777 | if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) | ||
778 | { | ||
779 | m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", | ||
780 | appearance.Wearables[(int) WearableType.Eyes][0].ItemID, | ||
781 | appearance.Wearables[(int) WearableType.Eyes][0].AssetID); | ||
782 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
783 | resetwearable = true; | ||
784 | |||
785 | } | ||
786 | |||
787 | } | ||
788 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
789 | if (appearance.Wearables[(int)WearableType.Shape] == null) | ||
790 | { | ||
791 | m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); | ||
792 | |||
793 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
794 | resetwearable = true; | ||
795 | } | ||
796 | else | ||
797 | { | ||
798 | if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) | ||
799 | { | ||
800 | m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", | ||
801 | appearance.Wearables[(int)WearableType.Shape][0].ItemID, | ||
802 | appearance.Wearables[(int)WearableType.Shape][0].AssetID); | ||
803 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
804 | resetwearable = true; | ||
805 | |||
806 | } | ||
807 | |||
808 | } | ||
809 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
810 | if (appearance.Wearables[(int)WearableType.Hair] == null) | ||
811 | { | ||
812 | m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); | ||
813 | |||
814 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
815 | resetwearable = true; | ||
816 | } | ||
817 | else | ||
818 | { | ||
819 | if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) | ||
820 | { | ||
821 | m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", | ||
822 | appearance.Wearables[(int)WearableType.Hair][0].ItemID, | ||
823 | appearance.Wearables[(int)WearableType.Hair][0].AssetID); | ||
824 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
825 | resetwearable = true; | ||
826 | |||
827 | } | ||
828 | |||
829 | } | ||
830 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
831 | if (appearance.Wearables[(int)WearableType.Skin] == null) | ||
832 | { | ||
833 | m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); | ||
834 | |||
835 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
836 | resetwearable = true; | ||
837 | } | ||
838 | else | ||
839 | { | ||
840 | if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) | ||
841 | { | ||
842 | m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", | ||
843 | appearance.Wearables[(int)WearableType.Skin][0].ItemID, | ||
844 | appearance.Wearables[(int)WearableType.Skin][0].AssetID); | ||
845 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
846 | resetwearable = true; | ||
847 | |||
848 | } | ||
849 | |||
850 | } | ||
851 | if (resetwearable) | ||
852 | { | ||
853 | ScenePresence presence = null; | ||
854 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
855 | { | ||
856 | presence.ControllingClient.SendWearables(presence.Appearance.Wearables, | ||
857 | presence.Appearance.Serial++); | ||
858 | } | ||
859 | } | ||
860 | |||
708 | } | 861 | } |
709 | else | 862 | else |
710 | { | 863 | { |
711 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); | 864 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); |
712 | } | 865 | } |
713 | } | 866 | } |
867 | private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) | ||
868 | { | ||
869 | UUID defaultwearable = GetDefaultItem(type); | ||
870 | if (defaultwearable != UUID.Zero) | ||
871 | { | ||
872 | UUID newInvItem = UUID.Random(); | ||
873 | InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) | ||
874 | { | ||
875 | AssetID = | ||
876 | defaultwearable, | ||
877 | AssetType | ||
878 | = | ||
879 | (int) | ||
880 | AssetType | ||
881 | .Bodypart, | ||
882 | CreatorId | ||
883 | = | ||
884 | userID | ||
885 | .ToString | ||
886 | (), | ||
887 | //InvType = (int)InventoryType.Wearable, | ||
888 | |||
889 | Description | ||
890 | = | ||
891 | "Failed Wearable Replacement", | ||
892 | Folder = | ||
893 | invService | ||
894 | .GetFolderForType | ||
895 | (userID, | ||
896 | AssetType | ||
897 | .Bodypart) | ||
898 | .ID, | ||
899 | Flags = (uint) type, | ||
900 | Name = Enum.GetName(typeof (WearableType), type), | ||
901 | BasePermissions = (uint) PermissionMask.Copy, | ||
902 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
903 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
904 | GroupPermissions = (uint) PermissionMask.Copy, | ||
905 | NextPermissions = (uint) PermissionMask.Copy | ||
906 | }; | ||
907 | invService.AddItem(itembase); | ||
908 | UUID LinkInvItem = UUID.Random(); | ||
909 | itembase = new InventoryItemBase(LinkInvItem, userID) | ||
910 | { | ||
911 | AssetID = | ||
912 | newInvItem, | ||
913 | AssetType | ||
914 | = | ||
915 | (int) | ||
916 | AssetType | ||
917 | .Link, | ||
918 | CreatorId | ||
919 | = | ||
920 | userID | ||
921 | .ToString | ||
922 | (), | ||
923 | InvType = (int) InventoryType.Wearable, | ||
924 | |||
925 | Description | ||
926 | = | ||
927 | "Failed Wearable Replacement", | ||
928 | Folder = | ||
929 | invService | ||
930 | .GetFolderForType | ||
931 | (userID, | ||
932 | AssetType | ||
933 | .CurrentOutfitFolder) | ||
934 | .ID, | ||
935 | Flags = (uint) type, | ||
936 | Name = Enum.GetName(typeof (WearableType), type), | ||
937 | BasePermissions = (uint) PermissionMask.Copy, | ||
938 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
939 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
940 | GroupPermissions = (uint) PermissionMask.Copy, | ||
941 | NextPermissions = (uint) PermissionMask.Copy | ||
942 | }; | ||
943 | invService.AddItem(itembase); | ||
944 | appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); | ||
945 | ScenePresence presence = null; | ||
946 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
947 | { | ||
948 | m_scene.SendInventoryUpdate(presence.ControllingClient, | ||
949 | invService.GetFolderForType(userID, | ||
950 | AssetType | ||
951 | .CurrentOutfitFolder), | ||
952 | false, true); | ||
953 | } | ||
954 | } | ||
955 | } | ||
956 | private UUID GetDefaultItem(WearableType wearable) | ||
957 | { | ||
958 | // These are ruth | ||
959 | UUID ret = UUID.Zero; | ||
960 | switch (wearable) | ||
961 | { | ||
962 | case WearableType.Eyes: | ||
963 | ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); | ||
964 | break; | ||
965 | case WearableType.Hair: | ||
966 | ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); | ||
967 | break; | ||
968 | case WearableType.Pants: | ||
969 | ret = new UUID("00000000-38f9-1111-024e-222222111120"); | ||
970 | break; | ||
971 | case WearableType.Shape: | ||
972 | ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); | ||
973 | break; | ||
974 | case WearableType.Shirt: | ||
975 | ret = new UUID("00000000-38f9-1111-024e-222222111110"); | ||
976 | break; | ||
977 | case WearableType.Skin: | ||
978 | ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); | ||
979 | break; | ||
980 | case WearableType.Undershirt: | ||
981 | ret = new UUID("16499ebb-3208-ec27-2def-481881728f47"); | ||
982 | break; | ||
983 | case WearableType.Underpants: | ||
984 | ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d"); | ||
985 | break; | ||
986 | } | ||
714 | 987 | ||
988 | return ret; | ||
989 | } | ||
715 | #endregion | 990 | #endregion |
716 | 991 | ||
717 | #region Client Event Handlers | 992 | #region Client Event Handlers |
@@ -824,7 +1099,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
824 | } | 1099 | } |
825 | 1100 | ||
826 | bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); | 1101 | bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); |
827 | outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); | 1102 | outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete"); |
828 | } | 1103 | } |
829 | } | 1104 | } |
830 | } | 1105 | } |