From eb84bb298d2b95aec7b2ae12cbf25ac64f25379a Mon Sep 17 00:00:00 2001 From: tylermurphy534 Date: Sun, 6 Nov 2022 15:12:42 -0500 Subject: move to self host --- .../VRChat/Scripts/Validation/ValidationUtils.cs | 260 +++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs (limited to 'VRCSDK3AvatarsLegacy/Assets/VRCSDK/Dependencies/VRChat/Scripts/Validation/ValidationUtils.cs') 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 whitelist, bool retry = true, bool onlySceneObjects = false, bool logStripping = true) + { + List 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 FindIllegalComponents(GameObject target, HashSet whitelist) + { + List foundComponents = new List(); + Component[] allComponents = target.GetComponentsInChildren(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 _typeCache = new Dictionary(); + private static readonly Dictionary> _whitelistCache = new Dictionary>(); + public static HashSet WhitelistedTypes(string whitelistName, IEnumerable componentTypeWhitelist) + { + if (_whitelistCache.ContainsKey(whitelistName)) + { + return _whitelistCache[whitelistName]; + } + + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + HashSet whitelist = new HashSet(); + 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 WhitelistedTypes(string whitelistName, IEnumerable componentTypeWhitelist) + { + if (_whitelistCache.ContainsKey(whitelistName)) + { + return _whitelistCache[whitelistName]; + } + + HashSet whitelist = new HashSet(); + whitelist.UnionWith(componentTypeWhitelist); + + AddDerivedClasses(whitelist); + + _whitelistCache[whitelistName] = whitelist; + + return _whitelistCache[whitelistName]; + } + + private static void AddDerivedClasses(HashSet 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> _requireComponentsCache = new Dictionary>(); + private static void RemoveDependencies(Component rootComponent) + { + if (rootComponent == null) + { + return; + } + + Component[] components = rootComponent.GetComponents(); + 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 requiredComponentAttributes)) + { + requiredComponentAttributes = siblingComponentType.GetCustomAttributes(typeof(RequireComponent), true).Cast().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(GameObject target) where T : Component + { + if (target == null) + return; + + foreach (T comp in target.GetComponentsInChildren(true)) + { + if (comp == null || comp.gameObject == null) + continue; + + RemoveComponent(comp); + } + } + } +} -- cgit v1.2.3-freya