diff options
author | tylermurphy534 <tylermurphy534@gmail.com> | 2022-11-06 15:12:42 -0500 |
---|---|---|
committer | tylermurphy534 <tylermurphy534@gmail.com> | 2022-11-06 15:12:42 -0500 |
commit | eb84bb298d2b95aec7b2ae12cbf25ac64f25379a (patch) | |
tree | efd616a157df06ab661c6d56651853431ac6b08b /VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs | |
download | unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.tar.gz unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.tar.bz2 unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.zip |
move to self host
Diffstat (limited to 'VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs')
-rw-r--r-- | VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs b/VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs new file mode 100644 index 00000000..e6dfef95 --- /dev/null +++ b/VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using UnityEngine; +using System.Reflection; + +namespace VRC.SDKBase.Validation +{ + public static class ValidationUtils + { + public static void RemoveIllegalComponents(GameObject target, HashSet<Type> whitelist, bool retry = true, bool onlySceneObjects = false, bool logStripping = true) + { + List<Component> foundComponents = FindIllegalComponents(target, whitelist); + foreach(Component component in foundComponents) + { + if(component == null) + { + continue; + } + + if(onlySceneObjects && component.GetInstanceID() < 0) + { + continue; + } + + if(logStripping) + { + Core.Logger.LogWarning($"Removing {component.GetType().Name} comp from {component.gameObject.name}"); + } + + RemoveComponent(component); + } + } + + public static List<Component> FindIllegalComponents(GameObject target, HashSet<Type> whitelist) + { + List<Component> foundComponents = new List<Component>(); + Component[] allComponents = target.GetComponentsInChildren<Component>(true); + foreach(Component component in allComponents) + { + if(component == null) + { + continue; + } + + Type componentType = component.GetType(); + if(whitelist.Contains(componentType)) + { + continue; + } + + foundComponents.Add(component); + } + + return foundComponents; + } + + private static readonly Dictionary<string, Type> _typeCache = new Dictionary<string, Type>(); + private static readonly Dictionary<string, HashSet<Type>> _whitelistCache = new Dictionary<string, HashSet<Type>>(); + public static HashSet<Type> WhitelistedTypes(string whitelistName, IEnumerable<string> componentTypeWhitelist) + { + if (_whitelistCache.ContainsKey(whitelistName)) + { + return _whitelistCache[whitelistName]; + } + + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + HashSet<Type> whitelist = new HashSet<Type>(); + foreach(string whitelistedTypeName in componentTypeWhitelist) + { + Type whitelistedType = GetTypeFromName(whitelistedTypeName, assemblies); + if(whitelistedType == null) + { + continue; + } + + if(whitelist.Contains(whitelistedType)) + { + continue; + } + + whitelist.Add(whitelistedType); + } + + AddDerivedClasses(whitelist); + + _whitelistCache[whitelistName] = whitelist; + + return _whitelistCache[whitelistName]; + } + + public static HashSet<Type> WhitelistedTypes(string whitelistName, IEnumerable<Type> componentTypeWhitelist) + { + if (_whitelistCache.ContainsKey(whitelistName)) + { + return _whitelistCache[whitelistName]; + } + + HashSet<Type> whitelist = new HashSet<Type>(); + whitelist.UnionWith(componentTypeWhitelist); + + AddDerivedClasses(whitelist); + + _whitelistCache[whitelistName] = whitelist; + + return _whitelistCache[whitelistName]; + } + + private static void AddDerivedClasses(HashSet<Type> whitelist) + { + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach(Assembly assembly in assemblies) + { + foreach(Type type in assembly.GetTypes()) + { + if(whitelist.Contains(type)) + { + continue; + } + + if(!typeof(Component).IsAssignableFrom(type)) + { + continue; + } + + Type currentType = type; + while(currentType != typeof(object) && currentType != null) + { + if(whitelist.Contains(currentType)) + { + whitelist.Add(type); + break; + } + + currentType = currentType.BaseType; + } + } + } + } + + public static Type GetTypeFromName(string name, Assembly[] assemblies = null) + { + if (_typeCache.ContainsKey(name)) + { + + return _typeCache[name]; + } + + if (assemblies == null) + { + assemblies = AppDomain.CurrentDomain.GetAssemblies(); + } + + foreach (Assembly assembly in assemblies) + { + Type found = assembly.GetType(name); + if(found == null) + { + continue; + } + + _typeCache[name] = found; + return found; + } + + //This is really verbose for some SDK scenes, eg. + //If they don't have FinalIK installed +#if VRC_CLIENT && UNITY_EDITOR + Debug.LogWarningFormat("Could not find type {0}", name); +#endif + + _typeCache[name] = null; + return null; + } + + private static readonly Dictionary<Type, ImmutableArray<RequireComponent>> _requireComponentsCache = new Dictionary<Type, ImmutableArray<RequireComponent>>(); + private static void RemoveDependencies(Component rootComponent) + { + if (rootComponent == null) + { + return; + } + + Component[] components = rootComponent.GetComponents<Component>(); + if (components == null || components.Length == 0) + { + return; + } + + Type compType = rootComponent.GetType(); + foreach (var siblingComponent in components) + { + if (siblingComponent == null) + { + continue; + } + + Type siblingComponentType = siblingComponent.GetType(); + if(!_requireComponentsCache.TryGetValue(siblingComponentType, out ImmutableArray<RequireComponent> requiredComponentAttributes)) + { + requiredComponentAttributes = siblingComponentType.GetCustomAttributes(typeof(RequireComponent), true).Cast<RequireComponent>().ToImmutableArray(); + _requireComponentsCache.Add(siblingComponentType, requiredComponentAttributes); + } + + bool deleteMe = false; + foreach (RequireComponent requireComponent in requiredComponentAttributes) + { + if (requireComponent == null) + { + continue; + } + + if(requireComponent.m_Type0 != compType && requireComponent.m_Type1 != compType && requireComponent.m_Type2 != compType) + { + continue; + } + + deleteMe = true; + break; + } + + if (deleteMe && siblingComponent != rootComponent) + { + RemoveComponent(siblingComponent); + } + } + } + + public static void RemoveComponent(Component comp) + { + if (comp == null) + { + return; + } + + RemoveDependencies(comp); + +#if VRC_CLIENT + UnityEngine.Object.DestroyImmediate(comp, true); +#else + UnityEngine.Object.DestroyImmediate(comp, false); +#endif + } + + public static void RemoveComponentsOfType<T>(GameObject target) where T : Component + { + if (target == null) + return; + + foreach (T comp in target.GetComponentsInChildren<T>(true)) + { + if (comp == null || comp.gameObject == null) + continue; + + RemoveComponent(comp); + } + } + } +} |