Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of balrond WeaponCrate v0.1.1
plugins/BalrondWeaponCrate.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using Balrond.Shared; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using LitJson2; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Audio; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("BalrondWeaponCrate")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BalrondWeaponCrate")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b6cf3f26-ceac-41f7-9df1-09f3f9b898b4")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.2.0")] [module: UnverifiableCode] namespace Balrond.Shared { public static class AudioRoutingService { public enum AudioRoute { SFX, Ambient, Music, Master } private enum TargetKind { Route, NamedRuntimeGroup } private sealed class AudioTarget { public TargetKind Kind; public AudioRoute Route; public string RuntimeGroupName; public string Reason; } private sealed class AudioBinding { public AudioSource Source; public AudioTarget Target; } private sealed class ProcessedNode { public GameObject Root; public readonly List<AudioBinding> AudioBindings = new List<AudioBinding>(); public readonly List<GameObject> ReferencedRoots = new List<GameObject>(); public readonly HashSet<GameObject> ReferencedRootSet = new HashSet<GameObject>(ReferenceComparer<GameObject>.Instance); } private sealed class ExplicitOverride { public bool UsesNamedGroup; public AudioRoute Route; public string RuntimeGroupName; } private sealed class RuntimeMixerCatalog { private readonly Dictionary<string, AudioMixerGroup> _groupsByName = new Dictionary<string, AudioMixerGroup>(StringComparer.OrdinalIgnoreCase); private AudioMixer _mixer; private AudioMixerGroup _master; private AudioMixerGroup _ambient; private AudioMixerGroup _music; private AudioMixerGroup _sfx; public bool IsReady => (Object)(object)_mixer != (Object)null || (Object)(object)_master != (Object)null || (Object)(object)_ambient != (Object)null || (Object)(object)_music != (Object)null; public void Rebuild(AudioMan audioMan) { _groupsByName.Clear(); _mixer = null; _master = null; _ambient = null; _music = null; _sfx = null; if ((Object)(object)audioMan == (Object)null) { return; } _master = ReadAudioManGroup(audioMan, "m_masterMixer"); _ambient = ReadAudioManGroup(audioMan, "m_ambientMixer"); _music = ReadAudioManGroup(audioMan, "m_musicMixer"); _mixer = GetMixer(_master) ?? GetMixer(_ambient) ?? GetMixer(_music); AddGroup(_master); AddGroup(_ambient); AddGroup(_music); if ((Object)(object)_mixer != (Object)null) { try { AudioMixerGroup[] array = _mixer.FindMatchingGroups(string.Empty); if (array != null) { for (int i = 0; i < array.Length; i++) { AddGroup(array[i]); } } } catch (Exception ex) { Warn("Could not enumerate runtime AudioMixer groups: " + ex.Message); } } _sfx = FindNamedGroup("SFX"); if ((Object)(object)_sfx == (Object)null) { _sfx = QueryExactGroup("SFX"); } if ((Object)(object)_sfx == (Object)null) { AudioMixerGroup val = FindNamedGroup("Effects"); if ((Object)(object)val == (Object)null) { val = QueryExactGroup("Effects"); } _sfx = val; } if ((Object)(object)_sfx == (Object)null) { _sfx = _master; WarnOnce("sfx-group-fallback", "Runtime SFX mixer group was not found. Falling back to the AudioMan master output group."); } } public AudioMixerGroup Resolve(AudioTarget target) { if (target == null) { return ResolveRoute(AudioRoute.SFX); } if (target.Kind == TargetKind.NamedRuntimeGroup) { AudioMixerGroup val = FindNamedGroup(target.RuntimeGroupName); if ((Object)(object)val == (Object)null) { val = QueryExactGroup(target.RuntimeGroupName); } if ((Object)(object)val != (Object)null) { return val; } return ResolveRoute(AudioRoute.SFX); } return ResolveRoute(target.Route); } public bool HasNamedGroup(string groupName) { if (string.IsNullOrEmpty(groupName)) { return false; } return (Object)(object)FindNamedGroup(groupName) != (Object)null || (Object)(object)QueryExactGroup(groupName) != (Object)null; } private AudioMixerGroup ResolveRoute(AudioRoute route) { return (AudioMixerGroup)(route switch { AudioRoute.Ambient => _ambient ?? _sfx ?? _master, AudioRoute.Music => _music ?? _sfx ?? _master, AudioRoute.Master => _master ?? _sfx ?? _ambient ?? _music, _ => _sfx ?? _master ?? _ambient ?? _music, }); } private AudioMixerGroup FindNamedGroup(string groupName) { if (!string.IsNullOrEmpty(groupName) && _groupsByName.TryGetValue(groupName, out var value)) { return value; } return null; } private AudioMixerGroup QueryExactGroup(string groupName) { if ((Object)(object)_mixer == (Object)null || string.IsNullOrEmpty(groupName)) { return null; } try { AudioMixerGroup[] array = _mixer.FindMatchingGroups(groupName); if (array == null) { return null; } foreach (AudioMixerGroup val in array) { AddGroup(val); if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, groupName, StringComparison.OrdinalIgnoreCase)) { return val; } } } catch (Exception ex) { WarnOnce("query-group-" + groupName, "Could not query runtime AudioMixer group '" + groupName + "': " + ex.Message); } return null; } private void AddGroup(AudioMixerGroup group) { if (!((Object)(object)group == (Object)null) && !string.IsNullOrEmpty(((Object)group).name) && !_groupsByName.ContainsKey(((Object)group).name)) { _groupsByName.Add(((Object)group).name, group); } } private static AudioMixer GetMixer(AudioMixerGroup group) { try { return ((Object)(object)group != (Object)null) ? group.audioMixer : null; } catch { return null; } } private static AudioMixerGroup ReadAudioManGroup(AudioMan audioMan, string fieldName) { try { FieldInfo field = typeof(AudioMan).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return null; } object value = field.GetValue(audioMan); AudioMixerGroup val = (AudioMixerGroup)((value is AudioMixerGroup) ? value : null); if ((Object)(object)val != (Object)null) { return val; } AudioSource val2 = (AudioSource)((value is AudioSource) ? value : null); if ((Object)(object)val2 != (Object)null) { return val2.outputAudioMixerGroup; } } catch (Exception ex) { WarnOnce("audioman-field-" + fieldName, "Could not read AudioMan." + fieldName + ": " + ex.Message); } return null; } } private sealed class ReferenceComparer<T> : IEqualityComparer<T> where T : class { public static readonly ReferenceComparer<T> Instance = new ReferenceComparer<T>(); public bool Equals(T x, T y) { return x == y; } public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); } } private const int MaxManagedDepth = 24; private const int MaxCollectionEntries = 4096; private static readonly RuntimeMixerCatalog MixerCatalog = new RuntimeMixerCatalog(); private static readonly Dictionary<string, ExplicitOverride> Overrides = new Dictionary<string, ExplicitOverride>(StringComparer.Ordinal); private static readonly Dictionary<GameObject, ProcessedNode> ProcessedNodes = new Dictionary<GameObject, ProcessedNode>(ReferenceComparer<GameObject>.Instance); private static readonly Dictionary<AudioSource, AudioBinding> SourceBindings = new Dictionary<AudioSource, AudioBinding>(ReferenceComparer<AudioSource>.Instance); private static readonly Dictionary<Type, FieldInfo[]> TraversalFields = new Dictionary<Type, FieldInfo[]>(); private static readonly HashSet<GameObject> RegisteredRootSet = new HashSet<GameObject>(ReferenceComparer<GameObject>.Instance); private static readonly List<GameObject> RegisteredRoots = new List<GameObject>(); private static readonly HashSet<GameObject> ActiveProcessing = new HashSet<GameObject>(ReferenceComparer<GameObject>.Instance); private static readonly HashSet<string> WarnedKeys = new HashSet<string>(StringComparer.Ordinal); private static Action<string> _infoLogger; private static Action<string> _warningLogger; private static Action<string> _errorLogger; public static bool DebugLogging { get; set; } public static void ConfigureLogging(Action<string> infoLogger, Action<string> warningLogger, Action<string> errorLogger) { _infoLogger = infoLogger; _warningLogger = warningLogger; _errorLogger = errorLogger; } public static void SetOverride(string gameObjectName, AudioRoute route) { if (!string.IsNullOrWhiteSpace(gameObjectName)) { Overrides[gameObjectName] = new ExplicitOverride { UsesNamedGroup = false, Route = route, RuntimeGroupName = null }; InvalidateClassificationCaches(); } } public static void SetOverrides(AudioRoute route, params string[] gameObjectNames) { if (gameObjectNames == null) { return; } bool flag = false; foreach (string text in gameObjectNames) { if (!string.IsNullOrWhiteSpace(text)) { Overrides[text] = new ExplicitOverride { UsesNamedGroup = false, Route = route, RuntimeGroupName = null }; flag = true; } } if (flag) { InvalidateClassificationCaches(); } } public static void SetMixerGroupOverride(string gameObjectName, string runtimeMixerGroupName) { if (!string.IsNullOrWhiteSpace(gameObjectName) && !string.IsNullOrWhiteSpace(runtimeMixerGroupName)) { Overrides[gameObjectName] = new ExplicitOverride { UsesNamedGroup = true, Route = AudioRoute.SFX, RuntimeGroupName = runtimeMixerGroupName }; InvalidateClassificationCaches(); } } public static void RemoveOverride(string gameObjectName) { if (!string.IsNullOrWhiteSpace(gameObjectName) && Overrides.Remove(gameObjectName)) { InvalidateClassificationCaches(); } } public static void Process(GameObject root) { if (IsUsable((Object)(object)root)) { RegisterRoot(root); if (MixerCatalog.IsReady) { ProcessRoot(root); } } } public static void Process(IEnumerable<GameObject> roots) { if (roots == null) { return; } foreach (GameObject root in roots) { if (IsUsable((Object)(object)root)) { RegisterRoot(root); } } if (!MixerCatalog.IsReady) { return; } for (int i = 0; i < RegisteredRoots.Count; i++) { GameObject val = RegisteredRoots[i]; if (IsUsable((Object)(object)val)) { ProcessRoot(val); } } } public static void OnAudioManAwake(AudioMan audioMan) { if ((Object)(object)audioMan == (Object)null) { return; } MixerCatalog.Rebuild(audioMan); if (!MixerCatalog.IsReady) { Error("AudioMan was available, but no usable runtime mixer group could be resolved."); return; } HashSet<GameObject> visited = new HashSet<GameObject>(ReferenceComparer<GameObject>.Instance); for (int i = 0; i < RegisteredRoots.Count; i++) { GameObject val = RegisteredRoots[i]; if (IsUsable((Object)(object)val)) { if (ProcessedNodes.TryGetValue(val, out var value)) { ValidateNodeGraph(value, visited); } else { ProcessRoot(val); } } } } private static void RegisterRoot(GameObject root) { if (RegisteredRootSet.Add(root)) { RegisteredRoots.Add(root); } } private static void ProcessRoot(GameObject root) { if (!MixerCatalog.IsReady || !IsUsable((Object)(object)root)) { return; } if (ProcessedNodes.TryGetValue(root, out var value)) { ValidateNodeGraph(value, new HashSet<GameObject>(ReferenceComparer<GameObject>.Instance)); } else { if (!ActiveProcessing.Add(root)) { return; } ProcessedNode processedNode = new ProcessedNode { Root = root }; ProcessedNodes[root] = processedNode; try { ScanAudioSources(root, processedNode); ScanBehaviourReferences(root, processedNode); } catch (Exception ex) { Error("Failed to process audio graph for '" + SafeName((Object)(object)root) + "': " + ex); } finally { ActiveProcessing.Remove(root); } } } private static void ScanAudioSources(GameObject root, ProcessedNode node) { AudioSource[] componentsInChildren; try { componentsInChildren = root.GetComponentsInChildren<AudioSource>(true); } catch (Exception ex) { Warn("Could not enumerate AudioSources under '" + SafeName((Object)(object)root) + "': " + ex.Message); return; } if (componentsInChildren == null) { return; } foreach (AudioSource val in componentsInChildren) { if (IsUsable((Object)(object)val)) { if (!SourceBindings.TryGetValue(val, out var value)) { value = new AudioBinding { Source = val, Target = ClassifySource(root, val) }; SourceBindings[val] = value; } if (!node.AudioBindings.Contains(value)) { node.AudioBindings.Add(value); } ApplyBinding(value, root); } } } private static void ScanBehaviourReferences(GameObject root, ProcessedNode node) { MonoBehaviour[] componentsInChildren; try { componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true); } catch (Exception ex) { Warn("Could not enumerate MonoBehaviours under '" + SafeName((Object)(object)root) + "': " + ex.Message); return; } if (componentsInChildren == null) { return; } HashSet<object> managedVisited = new HashSet<object>(ReferenceComparer<object>.Instance); foreach (MonoBehaviour val in componentsInChildren) { if (IsUsable((Object)(object)val) && !(val is ZSFX)) { TraverseManagedObject(val, root, node, managedVisited, 0, isComponentRoot: true); } } } private static void TraverseManagedObject(object value, GameObject ownerRoot, ProcessedNode node, HashSet<object> managedVisited, int depth, bool isComponentRoot) { if (value == null || depth > 24) { return; } Type type = value.GetType(); if (!type.IsValueType && !managedVisited.Add(value)) { return; } FieldInfo[] traversalFields = GetTraversalFields(type, isComponentRoot); foreach (FieldInfo fieldInfo in traversalFields) { object value2; try { value2 = fieldInfo.GetValue(value); } catch { continue; } TraverseValue(value2, ownerRoot, node, managedVisited, depth + 1); } } private static void TraverseValue(object value, GameObject ownerRoot, ProcessedNode node, HashSet<object> managedVisited, int depth) { if (value == null || depth > 24) { return; } EffectList val = (EffectList)((value is EffectList) ? value : null); if (val != null) { TraverseEffectList(val, ownerRoot, node); return; } GameObject val2 = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val2 != (Object)null) { HandleReferencedGameObject(val2, ownerRoot, node); return; } Component val3 = (Component)((value is Component) ? value : null); if ((Object)(object)val3 != (Object)null) { if (IsUsable((Object)(object)val3)) { HandleReferencedGameObject(val3.gameObject, ownerRoot, node); } return; } AudioClip val4 = (AudioClip)((value is AudioClip) ? value : null); if ((Object)(object)val4 != (Object)null) { return; } Object val5 = (Object)((value is Object) ? value : null); if (val5 != (Object)null) { ScriptableObject val6 = (ScriptableObject)((value is ScriptableObject) ? value : null); if ((Object)(object)val6 != (Object)null) { TraverseManagedObject(val6, ownerRoot, node, managedVisited, depth, isComponentRoot: false); } return; } if (value is IDictionary dictionary) { int num = 0; { foreach (DictionaryEntry item in dictionary) { TraverseValue(item.Value, ownerRoot, node, managedVisited, depth + 1); num++; if (num >= 4096) { break; } } return; } } if (value is IEnumerable enumerable && !(value is string)) { int num2 = 0; { foreach (object item2 in enumerable) { TraverseValue(item2, ownerRoot, node, managedVisited, depth + 1); num2++; if (num2 >= 4096) { break; } } return; } } Type type = value.GetType(); if (ShouldTraverseManagedType(type)) { TraverseManagedObject(value, ownerRoot, node, managedVisited, depth, isComponentRoot: false); } } private static void TraverseEffectList(EffectList effectList, GameObject ownerRoot, ProcessedNode node) { EffectData[] effectPrefabs = effectList.m_effectPrefabs; if (effectPrefabs == null) { return; } for (int i = 0; i < effectPrefabs.Length; i++) { GameObject prefab = effectPrefabs[i].m_prefab; if (IsUsable((Object)(object)prefab)) { HandleReferencedGameObject(prefab, ownerRoot, node); } } } private static void HandleReferencedGameObject(GameObject referenced, GameObject ownerRoot, ProcessedNode ownerNode) { if (IsUsable((Object)(object)referenced) && IsUsable((Object)(object)ownerRoot) && !IsInsideHierarchy(referenced, ownerRoot)) { if (ownerNode.ReferencedRootSet.Add(referenced)) { ownerNode.ReferencedRoots.Add(referenced); } ProcessRoot(referenced); } } private static bool IsInsideHierarchy(GameObject candidate, GameObject root) { if (candidate == root) { return true; } try { Transform transform = candidate.transform; Transform transform2 = root.transform; return (Object)(object)transform != (Object)null && (Object)(object)transform2 != (Object)null && transform.IsChildOf(transform2); } catch { return false; } } private static AudioTarget ClassifySource(GameObject root, AudioSource source) { AudioTarget audioTarget = FindExplicitOverride(((Component)source).gameObject, root); if (audioTarget != null) { return audioTarget; } if (HierarchyHasSfxPrefix(((Component)source).gameObject, root)) { return RouteTarget(AudioRoute.SFX, "sfx_/vfx_/fx_ GameObject name"); } if (HierarchyHasZSFX(((Component)source).gameObject, root)) { return RouteTarget(AudioRoute.SFX, "ZSFX context"); } AudioMixerGroup val = null; try { val = source.outputAudioMixerGroup; } catch { val = null; } AudioTarget audioTarget2 = ClassifyOldMixerGroup(val); if (audioTarget2 != null) { return audioTarget2; } return RouteTarget(AudioRoute.SFX, "default SFX fallback"); } private static AudioTarget FindExplicitOverride(GameObject sourceObject, GameObject root) { Transform val = null; Transform val2 = null; try { val = (((Object)(object)sourceObject != (Object)null) ? sourceObject.transform : null); val2 = (((Object)(object)root != (Object)null) ? root.transform : null); } catch { return null; } while ((Object)(object)val != (Object)null) { string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : null); if (!string.IsNullOrEmpty(text) && Overrides.TryGetValue(text, out var value)) { if (value.UsesNamedGroup) { return NamedTarget(value.RuntimeGroupName, "explicit mixer-group override on '" + text + "'"); } return RouteTarget(value.Route, "explicit route override on '" + text + "'"); } if (val == val2) { break; } val = val.parent; } return null; } private static bool HierarchyHasSfxPrefix(GameObject sourceObject, GameObject root) { Transform val = null; Transform val2 = null; try { val = (((Object)(object)sourceObject != (Object)null) ? sourceObject.transform : null); val2 = (((Object)(object)root != (Object)null) ? root.transform : null); } catch { return false; } while ((Object)(object)val != (Object)null) { string name = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : null); if (HasSfxPrefix(name)) { return true; } if (val == val2) { break; } val = val.parent; } return false; } private static bool HierarchyHasZSFX(GameObject sourceObject, GameObject root) { Transform val = null; Transform val2 = null; try { val = (((Object)(object)sourceObject != (Object)null) ? sourceObject.transform : null); val2 = (((Object)(object)root != (Object)null) ? root.transform : null); } catch { return false; } while ((Object)(object)val != (Object)null) { try { if ((Object)(object)((Component)val).GetComponent<ZSFX>() != (Object)null) { return true; } } catch { } if (val == val2) { break; } val = val.parent; } return false; } private static AudioTarget ClassifyOldMixerGroup(AudioMixerGroup oldGroup) { if ((Object)(object)oldGroup == (Object)null || string.IsNullOrEmpty(((Object)oldGroup).name)) { return null; } string name = ((Object)oldGroup).name; if (IsGenericMasterName(name)) { return null; } if (ContainsInvariant(name, "ambient")) { return RouteTarget(AudioRoute.Ambient, "old mixer-group name: " + name); } if (ContainsInvariant(name, "music")) { return RouteTarget(AudioRoute.Music, "old mixer-group name: " + name); } if (ContainsInvariant(name, "sfx") || ContainsInvariant(name, "vfx") || ContainsInvariant(name, "effect")) { return RouteTarget(AudioRoute.SFX, "old mixer-group name: " + name); } if (MixerCatalog.HasNamedGroup(name)) { return NamedTarget(name, "matching runtime mixer-group name"); } return null; } private static bool HasSfxPrefix(string name) { if (string.IsNullOrEmpty(name)) { return false; } return name.StartsWith("sfx_", StringComparison.OrdinalIgnoreCase) || name.StartsWith("vfx_", StringComparison.OrdinalIgnoreCase) || name.StartsWith("fx_", StringComparison.OrdinalIgnoreCase); } private static bool IsGenericMasterName(string name) { return string.Equals(name, "Master", StringComparison.OrdinalIgnoreCase) || string.Equals(name, "MasterAudio", StringComparison.OrdinalIgnoreCase) || string.Equals(name, "Master Mixer", StringComparison.OrdinalIgnoreCase); } private static bool ContainsInvariant(string text, string fragment) { return text != null && fragment != null && text.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0; } private static AudioTarget RouteTarget(AudioRoute route, string reason) { return new AudioTarget { Kind = TargetKind.Route, Route = route, RuntimeGroupName = null, Reason = reason }; } private static AudioTarget NamedTarget(string groupName, string reason) { return new AudioTarget { Kind = TargetKind.NamedRuntimeGroup, Route = AudioRoute.SFX, RuntimeGroupName = groupName, Reason = reason }; } private static void ApplyBinding(AudioBinding binding, GameObject semanticRoot) { if (binding == null || !IsUsable((Object)(object)binding.Source)) { return; } AudioMixerGroup val = MixerCatalog.Resolve(binding.Target); if ((Object)(object)val == (Object)null) { return; } AudioMixerGroup val2 = null; try { val2 = binding.Source.outputAudioMixerGroup; } catch { val2 = null; } if (val2 != val) { try { binding.Source.outputAudioMixerGroup = val; } catch (Exception ex) { Warn("Could not route AudioSource '" + SafeName((Object)(object)((Component)binding.Source).gameObject) + "' under '" + SafeName((Object)(object)semanticRoot) + "': " + ex.Message); return; } } if (DebugLogging) { Info("AudioSource '" + SafeName((Object)(object)((Component)binding.Source).gameObject) + "' under '" + SafeName((Object)(object)semanticRoot) + "' -> '" + ((Object)val).name + "' (" + ((binding.Target != null) ? binding.Target.Reason : "unknown") + ")."); } } private static void ValidateNodeGraph(ProcessedNode node, HashSet<GameObject> visited) { if (node == null || !IsUsable((Object)(object)node.Root) || !visited.Add(node.Root)) { return; } for (int i = 0; i < node.AudioBindings.Count; i++) { ApplyBinding(node.AudioBindings[i], node.Root); } for (int j = 0; j < node.ReferencedRoots.Count; j++) { GameObject val = node.ReferencedRoots[j]; if (IsUsable((Object)(object)val)) { if (ProcessedNodes.TryGetValue(val, out var value)) { ValidateNodeGraph(value, visited); } else { ProcessRoot(val); } } } } private static FieldInfo[] GetTraversalFields(Type type, bool isComponentRoot) { if (TraversalFields.TryGetValue(type, out var value)) { return value; } List<FieldInfo> list = new List<FieldInfo>(); Type type2 = type; while (type2 != null && type2 != typeof(object) && !(type2 == typeof(MonoBehaviour)) && !(type2 == typeof(Behaviour)) && !(type2 == typeof(Component)) && !(type2 == typeof(ScriptableObject)) && !(type2 == typeof(Object))) { FieldInfo[] array; try { array = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } catch { array = null; } if (array != null) { foreach (FieldInfo fieldInfo in array) { if (ShouldInspectField(fieldInfo)) { list.Add(fieldInfo); } } } type2 = type2.BaseType; } value = list.ToArray(); TraversalFields[type] = value; return value; } private static bool ShouldInspectField(FieldInfo field) { if (field == null || field.IsStatic || field.IsLiteral || field.IsNotSerialized) { return false; } Type fieldType = field.FieldType; if (fieldType == null) { return false; } if (typeof(EffectList).IsAssignableFrom(fieldType) || typeof(GameObject).IsAssignableFrom(fieldType) || typeof(Component).IsAssignableFrom(fieldType) || typeof(ScriptableObject).IsAssignableFrom(fieldType)) { return true; } if (fieldType.IsArray || typeof(IEnumerable).IsAssignableFrom(fieldType)) { return true; } if (fieldType == typeof(object) || fieldType.IsInterface || fieldType.IsAbstract) { return HasSerializeReferenceAttribute(field); } return ShouldTraverseManagedType(fieldType); } private static bool HasSerializeReferenceAttribute(FieldInfo field) { try { object[] customAttributes = field.GetCustomAttributes(inherit: false); if (customAttributes == null) { return false; } foreach (object obj in customAttributes) { if (obj != null) { string fullName = obj.GetType().FullName; if (string.Equals(fullName, "UnityEngine.SerializeReference", StringComparison.Ordinal)) { return true; } } } } catch { } return false; } private static bool ShouldTraverseManagedType(Type type) { if (type == null || type.IsPrimitive || type.IsEnum || type.IsPointer) { return false; } if (type == typeof(string) || type == typeof(decimal) || type == typeof(DateTime) || type == typeof(TimeSpan) || type == typeof(Guid) || type == typeof(IntPtr) || type == typeof(UIntPtr) || type == typeof(Type)) { return false; } if (typeof(Delegate).IsAssignableFrom(type)) { return false; } if (typeof(Object).IsAssignableFrom(type)) { return typeof(ScriptableObject).IsAssignableFrom(type); } string text = type.Namespace ?? string.Empty; if (text.StartsWith("System", StringComparison.Ordinal) || text.StartsWith("UnityEngine", StringComparison.Ordinal)) { return false; } return type.IsClass || type.IsValueType; } private static void InvalidateClassificationCaches() { ProcessedNodes.Clear(); SourceBindings.Clear(); ActiveProcessing.Clear(); if (!MixerCatalog.IsReady) { return; } for (int i = 0; i < RegisteredRoots.Count; i++) { GameObject val = RegisteredRoots[i]; if (IsUsable((Object)(object)val)) { ProcessRoot(val); } } } private static bool IsUsable(Object obj) { if (obj == null) { return false; } try { return obj != (Object)null; } catch { return false; } } private static string SafeName(Object obj) { if (!IsUsable(obj)) { return "<null>"; } try { return obj.name ?? "<unnamed>"; } catch { return "<unavailable>"; } } private static void Info(string message) { if (_infoLogger != null) { _infoLogger("[AudioRoutingService] " + message); } } private static void Warn(string message) { if (_warningLogger != null) { _warningLogger("[AudioRoutingService] " + message); } } private static void Error(string message) { if (_errorLogger != null) { _errorLogger("[AudioRoutingService] " + message); } } private static void WarnOnce(string key, string message) { if (WarnedKeys.Add(key)) { Warn(message); } } } } namespace BalrondWeaponCrate { internal static class WeaponCrateConfig { internal static ConfigEntry<bool> LockConfiguration; internal static ConfigEntry<bool> ShieldsAreWeapons; internal static ConfigEntry<bool> ForceCostToSelf; internal static ConfigEntry<int> CostAmount; internal static ConfigEntry<bool> RequireAttachChild; internal static ConfigEntry<string> ManualIncludeWeapons; internal static ConfigEntry<string> ManualIncludeArmors; internal static ConfigEntry<string> ManualExclude; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> AudioDebugLogging; internal static void Bind(ConfigFile config) { LockConfiguration = config.Bind<bool>("Server", "LockConfiguration", true, "Lock synchronized ZBalrondWeaponCrate settings to the server/host values."); ServerSyncBridge.AddLockingConfigEntry(LockConfiguration); ShieldsAreWeapons = BindSynced(config, "Filtering", "ShieldsAreWeapons", value: true, "Treat shields as weapon entries instead of armor entries."); RequireAttachChild = BindSynced(config, "Filtering", "RequireAttachChild", value: false, "Only expose item prefabs that contain an 'attach' child transform."); ManualIncludeWeapons = BindSynced(config, "Filtering", "ManualIncludeWeapons", string.Empty, "Comma-separated prefab IDs that should be considered for the weapon category."); ManualIncludeArmors = BindSynced(config, "Filtering", "ManualIncludeArmors", string.Empty, "Comma-separated prefab IDs that should be considered for the armor category."); ManualExclude = BindSynced(config, "Filtering", "ManualExclude", string.Empty, "Comma-separated prefab IDs to exclude from Weapon Crate build-piece generation."); ForceCostToSelf = BindSynced(config, "Costs", "ForceCostToSelf", value: true, "When enabled, generated display pieces cost copies of the displayed item itself."); CostAmount = BindSynced(config, "Costs", "CostAmount", 1, "Number of copies of the displayed item required when ForceCostToSelf is enabled."); DebugLogging = config.Bind<bool>("Diagnostics", "DebugLogging", false, "Enable additional ZBalrondWeaponCrate diagnostic logging. Local client setting; not synchronized."); AudioDebugLogging = config.Bind<bool>("Diagnostics", "AudioDebugLogging", false, "Enable detailed AudioRoutingService logging. Local client setting; not synchronized."); } private static ConfigEntry<T> BindSynced<T>(ConfigFile config, string section, string key, T value, string description) { ConfigEntry<T> val = config.Bind<T>(section, key, value, description); ServerSyncBridge.AddConfigEntry<T>(val); return val; } internal static string[] ParsePrefabList(ConfigEntry<string> entry) { if (entry == null || string.IsNullOrWhiteSpace(entry.Value)) { return new string[0]; } string[] array = entry.Value.Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); List<string> list = new List<string>(array.Length); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0 && hashSet.Add(text)) { list.Add(text); } } return list.ToArray(); } } internal static class ServerSyncBridge { private static ConfigSync sync; internal static void Initialize(string pluginGuid, string displayName, string version) { sync = new ConfigSync(pluginGuid) { DisplayName = displayName, CurrentVersion = version, MinimumRequiredVersion = version, ModRequired = true }; } internal static void AddLockingConfigEntry(ConfigEntry<bool> entry) { sync.AddLockingConfigEntry<bool>(entry); } internal static void AddConfigEntry<T>(ConfigEntry<T> entry) { SyncedConfigEntry<T> syncedConfigEntry = sync.AddConfigEntry<T>(entry); syncedConfigEntry.SynchronizedConfig = true; } internal static void Reset() { sync = null; } } public class BalrondTranslator { public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>(); public static Dictionary<string, string> getLanguage(string language) { Dictionary<string, string> result = null; try { result = translations[language]; } catch (Exception) { } return result; } } public static class ColliderSanitizer { public static void SanitizeForBuildPiece(GameObject visualRoot, bool removeAllMeshColliders, bool debugLog = false, string debugPrefix = null) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)visualRoot == (Object)null) { return; } RemoveMeshColliders(visualRoot, removeAllMeshColliders, debugLog, debugPrefix); if (!((Object)(object)visualRoot.GetComponentInChildren<Collider>(true) != (Object)null)) { Renderer componentInChildren = visualRoot.GetComponentInChildren<Renderer>(true); if (!((Object)(object)componentInChildren == (Object)null)) { AddPrimitiveColliderFromBounds(visualRoot, componentInChildren.bounds, debugLog, debugPrefix); } } } private static void RemoveMeshColliders(GameObject root, bool removeAll, bool debugLog, string debugPrefix) { MeshCollider[] componentsInChildren = root.GetComponentsInChildren<MeshCollider>(true); foreach (MeshCollider val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Mesh sharedMesh = val.sharedMesh; if (removeAll || (Object)(object)sharedMesh == (Object)null || !sharedMesh.isReadable) { Object.Destroy((Object)(object)val); if (debugLog) { string text = (((Object)(object)sharedMesh != (Object)null) ? ((Object)sharedMesh).name : "null"); Debug.Log((object)(debugPrefix + " Removed MeshCollider on " + ((Object)root).name + " (mesh=" + text + ", removeAll=" + removeAll + ")")); } } } } private static void AddPrimitiveColliderFromBounds(GameObject root, Bounds worldBounds, bool debugLog, string debugPrefix) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) Vector3 center = root.transform.InverseTransformPoint(((Bounds)(ref worldBounds)).center); Vector3 lossyScale = root.transform.lossyScale; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(SafeDiv(((Bounds)(ref worldBounds)).size.x, lossyScale.x), SafeDiv(((Bounds)(ref worldBounds)).size.y, lossyScale.y), SafeDiv(((Bounds)(ref worldBounds)).size.z, lossyScale.z)); float num = Mathf.Max(val.x, val.z); if (val.y > num * 1.6f) { CapsuleCollider val2 = root.AddComponent<CapsuleCollider>(); val2.center = center; float num2 = num * 0.5f; val2.radius = Mathf.Max(0.01f, num2); val2.height = Mathf.Max(val2.radius * 2f, val.y); val2.direction = 1; if (debugLog) { Debug.Log((object)(debugPrefix + " Added CapsuleCollider fallback on " + ((Object)root).name)); } } else { BoxCollider val3 = root.AddComponent<BoxCollider>(); val3.center = center; val3.size = val; if (debugLog) { Debug.Log((object)(debugPrefix + " Added BoxCollider fallback on " + ((Object)root).name)); } } } private static float SafeDiv(float a, float b) { if (Mathf.Abs(b) < 0.0001f) { return a; } return a / b; } } public class DatabaseAddMethods { public void AddItems(List<GameObject> items) { foreach (GameObject item in items) { AddItem(item); } } public void AddRecipes(List<Recipe> recipes) { foreach (Recipe recipe in recipes) { AddRecipe(recipe); } } public void AddStatuseffects(List<StatusEffect> statusEffects) { foreach (StatusEffect statusEffect in statusEffects) { AddStatus(statusEffect); } } private bool IsObjectDBValid() { return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null; } private void AddStatus(StatusEffect status) { if (!IsObjectDBValid()) { return; } if ((Object)(object)status != (Object)null) { if ((Object)(object)ObjectDB.instance.GetStatusEffect(status.m_nameHash) == (Object)null) { ObjectDB.instance.m_StatusEffects.Add(status); } else { Debug.Log((object)(Launch.projectName + ": " + ((Object)status).name + " - Status already in the game")); } } else { Debug.LogError((object)(Launch.projectName + ": " + ((Object)status).name + " - Status not found")); } } private void AddRecipe(Recipe recipe) { if (!IsObjectDBValid()) { return; } if ((Object)(object)recipe != (Object)null) { if ((Object)(object)ObjectDB.instance.m_recipes.Find((Recipe x) => ((Object)x).name == ((Object)recipe).name) == (Object)null) { if ((Object)(object)recipe.m_item != (Object)null) { ObjectDB.instance.m_recipes.Add(recipe); } } else { Debug.Log((object)(Launch.projectName + ": " + ((Object)recipe).name + " - Recipe with this name already in the Game")); } } else { Debug.LogError((object)(Launch.projectName + ": " + ((Object)recipe).name + " - Recipe not found")); } } private void AddItem(GameObject newPrefab) { if (!IsObjectDBValid()) { return; } ItemDrop component = newPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { if ((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)newPrefab).name) == (Object)null) { ObjectDB.instance.m_items.Add(newPrefab); Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ObjectDB.instance); dictionary[((Object)newPrefab).name.GetHashCode()] = newPrefab; } else { Debug.Log((object)(Launch.projectName + ": " + ((Object)newPrefab).name + " - ItemDrop already exist")); } } else { Debug.LogError((object)(Launch.projectName + ": " + ((Object)newPrefab).name + " - ItemDrop not found on prefab")); } } } [Serializable] public class MappedEffectList { public List<EffectInfo> pieceEffect; public List<EffectInfo> destroyedEffects; public List<EffectInfo> hitEffects; public List<EffectInfo> switchEffect; public List<EffectInfo> blockEffect; public List<EffectInfo> equipEffect; public List<EffectInfo> hitEffect; public List<EffectInfo> hitTerrainEffect; public List<EffectInfo> holdStartEffect; public List<EffectInfo> startEffect; public List<EffectInfo> trailStartEffect; public List<EffectInfo> triggerEffect; public List<EffectInfo> unequipEffect; public EffectList createEffectListFromInfo(List<EffectInfo> list) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown EffectList val = new EffectList(); List<EffectData> list2 = new List<EffectData>(); val.m_effectPrefabs = list2.ToArray(); return val; } private EffectData createEffectData(EffectInfo info) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown EffectData val = new EffectData(); val.m_inheritParentRotation = info.inheritRotation; val.m_multiplyParentVisualScale = info.multiplyScale; val.m_childTransform = info.childName; val.m_inheritParentScale = info.inheritScale; val.m_variant = info.variant; val.m_scale = info.scale; val.m_attach = info.attach; val.m_follow = info.follow; val.m_prefab = ZNetScene.instance.m_prefabs.Find((GameObject x) => ((Object)x).name == info.name); return val; } } [Serializable] public struct EffectInfo { public string name; public bool enabled; public int variant; public bool attach; public bool follow; public bool inheritRotation; public bool inheritScale; public bool multiplyScale; public bool radnomRotation; public bool scale; public string childName; public EffectInfo(string name, bool enabled = true, int variant = -1, bool attach = false, bool follow = false, bool inheritRotation = false, bool inheritScale = false, bool multiplyScale = false, bool radnomRotation = false, bool scale = false, string childName = null) { this.name = name; this.enabled = enabled; this.variant = variant; this.attach = attach; this.follow = follow; this.inheritRotation = inheritRotation; this.inheritScale = inheritScale; this.multiplyScale = multiplyScale; this.radnomRotation = radnomRotation; this.scale = scale; this.childName = childName; } } public sealed class ModResourceLoader { public AssetBundle assetBundle; public readonly List<GameObject> itemPrefabs = new List<GameObject>(); public readonly List<GameObject> otherPrefabs = new List<GameObject>(); public void loadAssets() { assetBundle = GetAssetBundleFromResources("balrondweaponcrate"); if ((Object)(object)assetBundle == (Object)null) { Debug.LogWarning((object)(Launch.projectName + " AssetBundle not found (embedded resource endswith 'balrondweaponcrate').")); return; } string basePath = "Assets/Custom/BalrondWeaponCrate/"; loadItems(basePath); loadOther(basePath); } public void AddPrefabsToZnetScene(ZNetScene zNetScene) { if (!((Object)(object)zNetScene == (Object)null)) { validateAddedPrefabs(itemPrefabs, zNetScene); validateAddedPrefabs(otherPrefabs, zNetScene); zNetScene.m_prefabs.RemoveAll((GameObject x) => (Object)(object)x == (Object)null); } } private void loadItems(string basePath) { string[] nameList = new string[1] { "WeaponCrate_bal" }; addNewPrefabToCollection(nameList, basePath, itemPrefabs, "item", requireZNetView: false); } private void loadOther(string basePath) { string mainPath = basePath + "Other/"; string[] nameList = new string[0]; addNewPrefabToCollection(nameList, mainPath, otherPrefabs, "other", requireZNetView: false); } private void validateAddedPrefabs(List<GameObject> list, ZNetScene zNetScene) { if (list == null || (Object)(object)zNetScene == (Object)null) { return; } for (int i = 0; i < list.Count; i++) { GameObject val = list[i]; if (!((Object)(object)val == (Object)null)) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name); if (zNetScene.m_namedPrefabs.ContainsKey(stableHashCode)) { Debug.LogWarning((object)("DUPLICATE: " + ((Object)val).name)); } else { zNetScene.m_prefabs.Add(val); } } } } private void addNewPrefabToCollection(string[] nameList, string mainPath, List<GameObject> prefabList, string typeName, bool requireZNetView) { if ((Object)(object)assetBundle == (Object)null || nameList == null || nameList.Length == 0) { return; } foreach (string text in nameList) { if (string.IsNullOrEmpty(text)) { continue; } GameObject val = assetBundle.LoadAsset<GameObject>(mainPath + text + ".prefab"); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("Could not find " + typeName + " with name: " + text + " at " + mainPath)); continue; } if (requireZNetView && (Object)(object)val.GetComponent<ZNetView>() == (Object)null) { Debug.LogWarning((object)("Prefab has no ZNetView (skipped): " + text)); continue; } ShaderReplacment.Replace(val); prefabList.Add(val); if (Launch.DebugLog) { Debug.Log((object)(Launch.projectName + " Loaded " + typeName + ": " + text)); } } } private static AssetBundle GetAssetBundleFromResources(string filenameSuffix) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith(filenameSuffix, StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { if (Launch.DebugLog) { Debug.LogWarning((object)(Launch.projectName + " Embedded resources: " + string.Join(", ", manifestResourceNames))); } return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } return AssetBundle.LoadFromStream(stream); } } public class ShaderReplacment { public static List<GameObject> prefabsToReplaceShader = new List<GameObject>(); public static List<Material> materialsInPrefabs = new List<Material>(); public string[] shaderlist = new string[49] { "Custom/AlphaParticle", "Custom/Blob", "Custom/Bonemass", "Custom/Clouds", "Custom/Creature", "Custom/Decal", "Custom/Distortion", "Custom/Flow", "Custom/FlowOpaque", "Custom/Grass", "Custom/GuiScroll", "Custom/Heightmap", "Custom/icon", "Custom/InteriorSide", "Custom/LitGui", "Custom/LitParticles", "Custom/mapshader", "Custom/ParticleDecal", "Custom/Piece", "Custom/Player", "Custom/Rug", "Custom/ShadowBlob", "Custom/SkyboxProcedural", "Custom/SkyObject", "Custom/StaticRock", "Custom/Tar", "Custom/Trilinearmap", "Custom/UI/BGBlur", "Custom/Vegetation", "Custom/Water", "Custom/WaterBottom", "Custom/WaterMask", "Custom/Yggdrasil", "Custom/Yggdrasil/root", "Hidden/BlitCopyHDRTonemap", "Hidden/Dof/DepthOfFieldHdr", "Hidden/Dof/DX11Dof", "Hidden/Internal-Loading", "Hidden/Internal-UIRDefaultWorld", "Hidden/SimpleClear", "Hidden/SunShaftsComposite", "Lux Lit Particles/ Bumped", "Lux Lit Particles/ Tess Bumped", "Particles/Standard Surface2", "Particles/Standard Unlit2", "Standard TwoSided", "ToonDeferredShading2017", "Unlit/DepthWrite", "Unlit/Lighting" }; public static List<Shader> shaders = new List<Shader>(); private static readonly HashSet<Shader> CachedShaders = new HashSet<Shader>(); public static bool debug = true; public static Shader findShader(string name) { Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); if (array.Length == 0) { Debug.LogWarning((object)"SHADER LIST IS EMPTY!"); return null; } if (debug) { } return shaders.Find((Shader x) => ((Object)x).name == name); } public static Shader GetShaderByName(string name) { return shaders.Find((Shader x) => ((Object)x).name == name.Trim()); } public static void debugShaderList(List<Shader> shadersRes) { foreach (Shader shadersRe in shadersRes) { Debug.LogWarning((object)("SHADER NAME IS: " + ((Object)shadersRe).name)); } debug = false; } public static void Replace(GameObject gameObject) { prefabsToReplaceShader.Add(gameObject); GetMaterialsInPrefab(gameObject); } public static void GetMaterialsInPrefab(GameObject gameObject) { Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } Material[] array2 = sharedMaterials; foreach (Material val2 in array2) { if ((Object)(object)val2 != (Object)null) { materialsInPrefabs.Add(val2); } } } } public static void getMeShaders() { AssetBundle[] array = Resources.FindObjectsOfTypeAll<AssetBundle>(); AssetBundle[] array2 = array; foreach (AssetBundle val in array2) { IEnumerable<Shader> enumerable3; try { IEnumerable<Shader> enumerable2; if (!val.isStreamedSceneAssetBundle || !Object.op_Implicit((Object)(object)val)) { IEnumerable<Shader> enumerable = val.LoadAllAssets<Shader>(); enumerable2 = enumerable; } else { enumerable2 = from shader in ((IEnumerable<string>)val.GetAllAssetNames()).Select((Func<string, Shader>)val.LoadAsset<Shader>) where (Object)(object)shader != (Object)null select shader; } enumerable3 = enumerable2; } catch (Exception) { continue; } if (enumerable3 == null) { continue; } foreach (Shader item in enumerable3) { CachedShaders.Add(item); } } } public static void runMaterialFix() { getMeShaders(); shaders.AddRange(CachedShaders); foreach (Material materialsInPrefab in materialsInPrefabs) { Shader shader = materialsInPrefab.shader; if (!((Object)(object)shader == (Object)null)) { string name = ((Object)shader).name; if (!(name == "Standard") && !name.Contains("ScrollingTex") && name.Contains("Balrond")) { setProperValue(materialsInPrefab, name); } } } } private static void setProperValue(Material material, string shaderName) { string name = shaderName.Replace("Balrond", "Custom"); name = checkNaming(name); Shader shaderByName = GetShaderByName(name); if ((Object)(object)shaderByName == (Object)null) { Debug.LogWarning((object)("Shader not found " + name)); } else { material.shader = shaderByName; } } private static string checkNaming(string name) { string result = name; if (name.Contains("Bumped")) { result = name.Replace("Custom", "Lux Lit Particles"); } if (name.Contains("Tess Bumped")) { result = name.Replace("Custom", "Lux Lit Particles"); } if (name.Contains("Standard Surface")) { result = name.Replace("Custom", "Particles"); result = result.Replace("Standard Surface2", "Standard Surface"); } if (name.Contains("Standard Unlit")) { result = name.Replace("Custom", "Particles"); result = result.Replace("Standard Unlit", "Standard Unlit2"); result = result.Replace("Standard Unlit22", "Standard Unlit2"); } return result; } } public class TableMapper { public static CraftingStation cauldron; public static CraftingStation workbench; public static CraftingStation heavyWorkbench; public static CraftingStation forge; public static CraftingStation ironworks; public static CraftingStation blackforge; public static CraftingStation stoneCutter; public static CraftingStation artisian; public static CraftingStation magetable; public static CraftingStation runeforge; public static CraftingStation tannery; public static CraftingStation fletcher; public static CraftingStation grill; public static CraftingStation alchemylab; public static CraftingStation shamantable; public static CraftingStation foodtable; public static List<GameObject> pieces = new List<GameObject>(); public static void setupTables(List<GameObject> list) { pieces = list; prepareTables(); } private static CraftingStation FindStation(List<GameObject> list, string name, string replacement = "piece_workbench") { GameObject val = list.Find((GameObject x) => ((Object)x).name == name); if ((Object)(object)val != (Object)null) { return val.GetComponent<CraftingStation>(); } if ((Object)(object)val == (Object)null) { val = list.Find((GameObject x) => ((Object)x).name == replacement); if ((Object)(object)val != (Object)null) { return val.GetComponent<CraftingStation>(); } } Debug.LogWarning((object)("TableMapper - Station not found: " + name)); return null; } private static void prepareTables() { cauldron = FindStation(pieces, "piece_cauldron"); workbench = FindStation(pieces, "piece_workbench"); heavyWorkbench = FindStation(pieces, "piece_heavy_workbench_bal"); forge = FindStation(pieces, "forge"); ironworks = FindStation(pieces, "piece_metalworks_bal", "forge"); blackforge = FindStation(pieces, "blackforge"); stoneCutter = FindStation(pieces, "piece_stonecutter"); artisian = FindStation(pieces, "piece_artisanstation"); runeforge = FindStation(pieces, "piece_runeforge_bal", "blackforge"); magetable = FindStation(pieces, "piece_magetable"); fletcher = FindStation(pieces, "piece_fletcher_bal"); shamantable = FindStation(pieces, "piece_shamantable_bal", "piece_magetable"); foodtable = FindStation(pieces, "piece_preptable"); alchemylab = FindStation(pieces, "piece_MeadCauldron"); } } public class ItemUtils { public static bool IsWeaponType(ItemType type, bool shieldsAreWeapons) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if ((int)type == 3) { return true; } if ((int)type == 14) { return true; } if ((int)type == 22) { return true; } if ((int)type == 4) { return true; } if ((int)type == 15) { return true; } if ((int)type == 5) { return shieldsAreWeapons; } return false; } public static bool IsArmorType(ItemType type, bool shieldsAreWeapons) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if ((int)type == 6) { return true; } if ((int)type == 7) { return true; } if ((int)type == 11) { return true; } if ((int)type == 17) { return true; } if ((int)type == 18) { return true; } if ((int)type == 5) { return !shieldsAreWeapons; } return false; } public static bool HasAnyIcon(ItemDrop drop) { if ((Object)(object)drop == (Object)null || drop.m_itemData == null || drop.m_itemData.m_shared == null) { return false; } try { Sprite[] icons = drop.m_itemData.m_shared.m_icons; return icons != null && icons.Length != 0 && (Object)(object)icons[0] != (Object)null; } catch { return false; } } public static Sprite SafeFirstIcon(ItemDrop drop) { try { Sprite[] icons = drop.m_itemData.m_shared.m_icons; if (icons != null && icons.Length != 0) { return icons[0]; } } catch { } return null; } public static bool HasUsableVisual(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return false; } Transform val = FindChildRecursiveByName(prefab.transform, "attach"); if ((Object)(object)val != (Object)null && !((Object)val).name.Equals("attach_skin", StringComparison.OrdinalIgnoreCase)) { return true; } MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return false; } foreach (MeshRenderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { GameObject gameObject = ((Component)val2).gameObject; if (!((Object)(object)gameObject == (Object)null) && !((Object)(object)gameObject.GetComponent<SkinnedMeshRenderer>() != (Object)null)) { return true; } } } return false; } public static Transform FindChildRecursiveByName(Transform root, string wantedName) { if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(wantedName)) { return null; } Queue<Transform> queue = new Queue<Transform>(); queue.Enqueue(root); while (queue.Count > 0) { Transform val = queue.Dequeue(); if (!((Object)(object)val == (Object)null)) { if (!string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.Equals(wantedName, StringComparison.OrdinalIgnoreCase)) { return val; } for (int i = 0; i < val.childCount; i++) { queue.Enqueue(val.GetChild(i)); } } } return null; } public static GameObject PickVisualRoot(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } Transform val = FindChildRecursiveByName(prefab.transform, "attach"); if ((Object)(object)val != (Object)null && !((Object)val).name.Equals("attach_skin", StringComparison.OrdinalIgnoreCase)) { return ((Component)val).gameObject; } MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return null; } foreach (MeshRenderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { GameObject gameObject = ((Component)val2).gameObject; if (!((Object)(object)gameObject == (Object)null) && !((Object)(object)gameObject.GetComponent<SkinnedMeshRenderer>() != (Object)null)) { return gameObject; } } } return null; } } public class JsonLoader { public string defaultPath = string.Empty; public void loadJson() { LoadTranslations(); justDefaultPath(); } public void justDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ZBalrondWeaponCrate-translation/"); defaultPath = text; } public void createDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ZBalrondWeaponCrate-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("ZBalrondWeaponCrate: Folder already exists: " + text)); } defaultPath = text; } private string[] jsonFilePath(string folderName, string extension) { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ZBalrondWeaponCrate-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("ZBalrondWeaponCrate: Folder already exists: " + text)); } string[] files = Directory.GetFiles(text, extension); Debug.Log((object)("ZBalrondWeaponCrate:" + folderName + " Json Files Found: " + files.Length)); return files; } private static void CreateFolder(string path) { try { Directory.CreateDirectory(path); Debug.Log((object)"ZBalrondWeaponCrate: Folder created successfully."); } catch (Exception ex) { Debug.Log((object)("ZBalrondWeaponCrate: Error creating folder: " + ex.Message)); } } private void LoadTranslations() { int num = 0; string[] array = jsonFilePath("Translation", "*.json"); foreach (string text in array) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string json = File.ReadAllText(text); JsonData jsonData = JsonMapper.ToObject(json); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string key in jsonData.Keys) { dictionary[key] = jsonData[key].ToString(); } if (dictionary != null) { BalrondTranslator.translations.Add(fileNameWithoutExtension, dictionary); Debug.Log((object)("ZBalrondWeaponCrate: Json Files Language: " + fileNameWithoutExtension)); num++; } else { Debug.LogError((object)("ZBalrondWeaponCrate: Loading FAILED file: " + text)); } } Debug.Log((object)("ZBalrondWeaponCrate: Translation JsonFiles Loaded: " + num)); } } [BepInPlugin("balrond.astafaraios.ZBalrondWeaponCrate", "ZBalrondWeaponCrate", "0.1.1")] public sealed class Launch : BaseUnityPlugin { [HarmonyPatch] private static class AudioMan_Initialize_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(AudioMan), "Awake", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(AudioMan), "Start", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(AudioMan), "OnEnable", (Type[])null, (Type[])null) ?? throw new MissingMethodException(typeof(AudioMan).FullName, "Awake/Start/OnEnable"); } private static void Postfix(AudioMan __instance) { AudioRoutingService.OnAudioManAwake(__instance); } } [HarmonyPatch(typeof(FejdStartup), "SetupGui")] private static class FejdStartup_SetupGUI { private static void Postfix() { bool flag = false; string selectedLanguage = Localization.instance.GetSelectedLanguage(); Dictionary<string, string> dictionary = BalrondTranslator.getLanguage("English"); if ("English" != selectedLanguage) { Dictionary<string, string> language = BalrondTranslator.getLanguage(selectedLanguage); if (language != null) { dictionary = language; } else { Debug.Log((object)"ZBalrondWeaponCrate: Did not find translation file loading English"); } } if (dictionary != null) { foreach (KeyValuePair<string, string> item in dictionary) { Localization.instance.AddWord(item.Key, item.Value); } return; } Debug.LogWarning((object)"ZBalrondWeaponCrate: No translation file found!"); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "SetupLanguage")] private static class Translation_SetupLanguage { private static void Prefix(Localization __instance, string language) { bool flag = false; Dictionary<string, string> dictionary = BalrondTranslator.getLanguage("English"); if ("English" != language) { Dictionary<string, string> language2 = BalrondTranslator.getLanguage(language); if (language2 != null) { dictionary = language2; } else { Debug.Log((object)"ZBalrondWeaponCrate: Did not find translation file loading English"); } } if (dictionary != null) { foreach (KeyValuePair<string, string> item in dictionary) { __instance.AddWord(item.Key, item.Value); } return; } Debug.LogWarning((object)"ZBalrondWeaponCrate: No translation file found!"); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "LoadCSV")] private static class Translation_LoadCSV { private static void Prefix(Localization __instance, string language) { bool flag = false; Dictionary<string, string> dictionary = BalrondTranslator.getLanguage("English"); if ("English" != language) { Dictionary<string, string> language2 = BalrondTranslator.getLanguage(language); if (language2 != null) { dictionary = language2; } else { Debug.Log((object)"ZBalrondWeaponCrate: Did not find translation file loading English"); } } if (dictionary != null) { foreach (KeyValuePair<string, string> item in dictionary) { __instance.AddWord(item.Key, item.Value); } return; } Debug.LogWarning((object)"ZBalrondWeaponCrate: No translation file found!"); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class ZNetScene_Awake_Path { private static bool ranFix; private static void Prefix(ZNetScene __instance) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) bool flag = false; if (!((Object)(object)__instance == (Object)null)) { modResourceLoader.AddPrefabsToZnetScene(__instance); if (!ranFix && !new ZNet().IsDedicated()) { ShaderReplacment.runMaterialFix(); ranFix = true; } } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDB_Awake_Path { private static void Postfix() { bool flag = false; if (IsObjectDBValid()) { databaseAddMethods.AddItems(modResourceLoader.itemPrefabs); recipeFactory.EnsureRecipes(); weaponCrateBuilder.BuildWeaponCratePieces(); } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static class Object_CopyOtherDB_Path { private static void Postfix() { bool flag = false; if (IsObjectDBValid()) { databaseAddMethods.AddItems(modResourceLoader.itemPrefabs); recipeFactory.EnsureRecipes(); weaponCrateBuilder.BuildWeaponCratePieces(); } } } private Harmony harmony; public const string PluginGUID = "balrond.astafaraios.ZBalrondWeaponCrate"; public const string PluginName = "ZBalrondWeaponCrate"; public const string PluginVersion = "0.1.1"; public static DatabaseAddMethods databaseAddMethods = new DatabaseAddMethods(); public static readonly ModResourceLoader modResourceLoader = new ModResourceLoader(); public static readonly WeaponCrateBuilder weaponCrateBuilder = new WeaponCrateBuilder(); public static readonly RecipeFactory recipeFactory = new RecipeFactory(); public static readonly JsonLoader jsonLoader = new JsonLoader(); public static readonly string projectName = "[ZBalrondWeaponCrate]"; public const bool Enabled = true; public const string WeaponCratePrefabName = "WeaponCrate_bal"; public const string TemplatePrefabName = "FierySvinstew"; public const PieceCategory WeaponCategory = (PieceCategory)7; public const PieceCategory ArmorCategory = (PieceCategory)6; public static bool DebugLog => WeaponCrateConfig.DebugLogging != null && WeaponCrateConfig.DebugLogging.Value; public static bool ShieldsAreWeapons => WeaponCrateConfig.ShieldsAreWeapons == null || WeaponCrateConfig.ShieldsAreWeapons.Value; public static bool ForceCostToSelf => WeaponCrateConfig.ForceCostToSelf == null || WeaponCrateConfig.ForceCostToSelf.Value; public static int CostAmount => (WeaponCrateConfig.CostAmount == null) ? 1 : Math.Max(1, WeaponCrateConfig.CostAmount.Value); public static bool RequireAttachChild => WeaponCrateConfig.RequireAttachChild != null && WeaponCrateConfig.RequireAttachChild.Value; public static string[] ManualIncludeWeapons => WeaponCrateConfig.ParsePrefabList(WeaponCrateConfig.ManualIncludeWeapons); public static string[] ManualIncludeArmors => WeaponCrateConfig.ParsePrefabList(WeaponCrateConfig.ManualIncludeArmors); public static string[] ManualExclude => WeaponCrateConfig.ParsePrefabList(WeaponCrateConfig.ManualExclude); private void Awake() { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown ServerSyncBridge.Initialize("balrond.astafaraios.ZBalrondWeaponCrate", "ZBalrondWeaponCrate", "0.1.1"); WeaponCrateConfig.Bind(((BaseUnityPlugin)this).Config); AudioRoutingService.ConfigureLogging(delegate(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); }, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogError((object)message); }); AudioRoutingService.DebugLogging = WeaponCrateConfig.AudioDebugLogging.Value; WeaponCrateConfig.AudioDebugLogging.SettingChanged += delegate { AudioRoutingService.DebugLogging = WeaponCrateConfig.AudioDebugLogging.Value; }; jsonLoader.loadJson(); bool flag = true; modResourceLoader.loadAssets(); AudioRoutingService.Process((IEnumerable<GameObject>)modResourceLoader.itemPrefabs); AudioRoutingService.Process((IEnumerable<GameObject>)modResourceLoader.otherPrefabs); harmony = new Harmony("balrond.astafaraios.ZBalrondWeaponCrate"); harmony.PatchAll(); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ServerSyncBridge.Reset(); } public static bool IsObjectDBValid() { return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null && ObjectDB.instance.m_items.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null; } internal static void Log(string msg) { if (DebugLog) { Debug.Log((object)(projectName + " " + msg)); } } } public static class ItemVfxApplier { public static GameObject ApplyTemplateSparkles(GameObject targetPrefab, Transform templateSparkles, bool debugLog = false, string debugPrefix = null) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)targetPrefab == (Object)null || (Object)(object)templateSparkles == (Object)null) { return null; } Transform val = ItemUtils.FindChildRecursiveByName(targetPrefab.transform, ((Object)templateSparkles).name); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } try { GameObject val2 = Object.Instantiate<GameObject>(((Component)templateSparkles).gameObject); ((Object)val2).name = ((Object)templateSparkles).name; val2.transform.SetParent(targetPrefab.transform, false); val2.transform.localPosition = templateSparkles.localPosition; val2.transform.localRotation = templateSparkles.localRotation; val2.transform.localScale = templateSparkles.localScale; return val2; } catch (Exception ex) { if (debugLog) { Debug.LogWarning((object)(debugPrefix + " Failed cloning sparkles onto " + ((Object)targetPrefab).name + ": " + ex)); } return null; } } public static void StripRootParticleSystems(GameObject targetPrefab, bool debugLog = false, string debugPrefix = null) { if ((Object)(object)targetPrefab == (Object)null) { return; } try { ParticleSystem[] components = targetPrefab.GetComponents<ParticleSystem>(); ParticleSystem[] array = components; foreach (ParticleSystem val in array) { Object.Destroy((Object)(object)val); } ParticleSystemRenderer[] components2 = targetPrefab.GetComponents<ParticleSystemRenderer>(); ParticleSystemRenderer[] array2 = components2; foreach (ParticleSystemRenderer val2 in array2) { Object.Destroy((Object)(object)val2); } } catch (Exception ex) { if (debugLog) { Debug.LogWarning((object)(debugPrefix + " Failed stripping root ParticleSystems on " + ((Object)targetPrefab).name + ": " + ex)); } } } public static GameObject ApplySparklesAndCleanRoot(GameObject targetPrefab, Transform templateSparkles, bool debugLog = false, string debugPrefix = null) { GameObject result = ApplyTemplateSparkles(targetPrefab, templateSparkles, debugLog, debugPrefix); StripRootParticleSystems(targetPrefab, debugLog, debugPrefix); return result; } } public class PieceNTearSetter { public static void CopyPieceSettings(ItemDrop drop, Piece dst, Piece src) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) dst.m_allowAltGroundPlacement = true; dst.m_allowedInDungeons = true; dst.m_allowRotatedOverlap = true; dst.m_blockingPieces = src.m_blockingPieces; dst.m_blockRadius = 0f; dst.m_notOnTiltingSurface = false; dst.m_canBeRemoved = true; dst.m_canRotate = true; if (!ItemUtils.IsArmorType(drop.m_itemData.m_shared.m_itemType, shieldsAreWeapons: true)) { dst.m_clipEverything = true; dst.m_clipGround = true; } dst.m_comfort = 0; dst.m_comfortGroup = src.m_comfortGroup; dst.m_comfortObject = src.m_comfortObject; dst.m_connectRadius = src.m_connectRadius; dst.m_craftingStation = src.m_craftingStation; dst.m_cultivatedGroundOnly = false; dst.m_groundOnly = src.m_groundOnly; dst.m_groundPiece = src.m_groundPiece; ((StaticTarget)dst).m_haveCenter = ((StaticTarget)src).m_haveCenter; dst.m_inCeilingOnly = src.m_inCeilingOnly; dst.m_isUpgrade = false; dst.m_mustBeAboveConnected = src.m_mustBeAboveConnected; dst.m_mustConnectTo = src.m_mustConnectTo; dst.m_waterPiece = src.m_waterPiece; dst.m_vegetationGroundOnly = false; dst.m_targetNonPlayerBuilt = false; dst.m_spaceRequirement = 0f; dst.m_placeEffect = src.m_placeEffect; dst.m_returnResourceHeightOffset = src.m_returnResourceHeightOffset; } public static void CopyWearNTearSettings(WearNTear dst, WearNTear src) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) dst.m_ashDamageImmune = src.m_ashDamageImmune; dst.m_ashDamageResist = src.m_ashDamageResist; dst.m_ashMaterialValue = src.m_ashMaterialValue; dst.m_ashDamageTime = src.m_ashDamageTime; dst.m_ashroof = src.m_ashroof; dst.m_autoCreateFragments = src.m_autoCreateFragments; dst.m_biome = src.m_biome; dst.m_health = src.m_health; dst.m_hitEffect = src.m_hitEffect; dst.m_hitNoise = src.m_hitNoise; dst.m_minToolTier = src.m_minToolTier; dst.m_burnable = src.m_burnable; dst.m_destroyedEffect = src.m_destroyedEffect; dst.m_switchEffect = src.m_switchEffect; dst.m_damages = src.m_damages; dst.m_destroyNoise = src.m_destroyNoise; dst.m_support = src.m_support; dst.m_staticPosition = src.m_staticPosition; dst.m_noSupportWear = src.m_noSupportWear; dst.m_noRoofWear = src.m_noRoofWear; } public static void SetSingleRequirement(Piece piece, string resPrefabName, int amount, int amountPerLevel, bool recover) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(resPrefabName); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogWarning((object)(Launch.projectName + " Cost item not found: " + resPrefabName + " (fallback Wood)")); itemPrefab = ObjectDB.instance.GetItemPrefab("Wood"); } Requirement val = new Requirement { m_resItem = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null), m_amount = amount, m_amountPerLevel = amountPerLevel, m_recover = recover }; piece.m_resources = (Requirement[])(object)new Requirement[1] { val }; } } public sealed class RecipeFactory { private const string DefaultStationPrefab = "piece_workbench"; private const int DefaultStationLevel = 1; public void EnsureRecipes() { if (Launch.IsObjectDBValid()) { EnsureWeaponCrateRecipe(); } } private void EnsureWeaponCrateRecipe() { string text = "WeaponCrate_bal"; string text2 = "Recipe_" + text; ItemDrop val = ResolveItemDrop(text, allowInjectIntoObjectDB: true); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("ZBalrondWeaponCrate: RecipeFactory - could not resolve ItemDrop for: " + text + " (not found in ObjectDB nor ZNetScene)")); return; } Recipe val2 = FindRecipeByName(text2); if ((Object)(object)val2 != (Object)null) { return; } Recipe val3 = FindRecipeByItem(val); if (!((Object)(object)val3 != (Object)null)) { Recipe val4 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val4).name = text2; val4.m_item = val; val4.m_amount = 1; val4.m_enabled = true; val4.m_craftingStation = FindStation("piece_workbench"); val4.m_minStationLevel = 1; val4.m_repairStation = val4.m_craftingStation; List<Requirement> list = new List<Requirement> { CreateReq("Wood", 10, 0, recover: true), CreateReq("BronzeNails", 2, 0, recover: true) }; list.RemoveAll((Requirement r) => r == null || (Object)(object)r.m_resItem == (Object)null); val4.m_resources = list.ToArray(); if (ObjectDB.instance.m_recipes == null) { ObjectDB.instance.m_recipes = new List<Recipe>(); } ObjectDB.instance.m_recipes.Add(val4); RefreshObjectDBLookups(ObjectDB.instance); Debug.Log((object)("ZBalrondWeaponCrate: Added recipe: " + text2 + " (station=" + (((Object)(object)val4.m_craftingStation != (Object)null) ? ((Object)val4.m_craftingStation).name : "none/hand") + ")")); } } private static ItemDrop ResolveItemDrop(string itemPrefabName, bool allowInjectIntoObjectDB) { if (string.IsNullOrEmpty(itemPrefabName)) { return null; } GameObject val = null; if ((Object)(object)ObjectDB.instance != (Object)null) { val = ObjectDB.instance.GetItemPrefab(itemPrefabName); if ((Object)(object)val == (Object)null && ObjectDB.instance.m_items != null) { val = ObjectDB.instance.m_items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == itemPrefabName); } } if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab(itemPrefabName); } if ((Object)(object)val == (Object)null) { return null; } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { return null; } if (allowInjectIntoObjectDB && (Object)(object)ObjectDB.instance != (Object)null) { if (ObjectDB.instance.m_items == null) { ObjectDB.instance.m_items = new List<GameObject>(); } bool flag = false; for (int num = 0; num < ObjectDB.instance.m_items.Count; num++) { GameObject val2 = ObjectDB.instance.m_items[num]; if ((Object)(object)val2 != (Object)null && ((Object)val2).name == ((Object)val).name) { flag = true; break; } } if (!flag) { ObjectDB.instance.m_items.Add(val); RefreshObjectDBLookups(ObjectDB.instance); if (Launch.DebugLog) { Debug.Log((object)("ZBalrondWeaponCrate: RecipeFactory - injected item prefab into ObjectDB.m_items: " + ((Object)val).name)); } } } return component; } private static CraftingStation FindStation(string stationPrefabName) { if (string.IsNullOrEmpty(stationPrefabName)) { return null; } if ((Object)(object)ZNetScene.instance == (Object)null) { return null; } GameObject prefab = ZNetScene.instance.GetPrefab(stationPrefabName); if ((Object)(object)prefab == (Object)null) { return null; } return prefab.GetComponent<CraftingStation>(); } private static Requirement CreateReq(string itemPrefabName, int amount, int amountPerLevel, bool recover) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown if (string.IsNullOrEmpty(itemPrefabName) || (Object)(object)ObjectDB.instance == (Object)null) { return null; } GameObject val = ObjectDB.instance.GetItemPrefab(itemPrefabName); if ((Object)(object)val == (Object)null && ObjectDB.instance.m_items != null) { val = ObjectDB.instance.m_items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == itemPrefabName); } if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("ZBalrondWeaponCrate: RecipeFactory - requirement item not found: " + itemPrefabName)); return null; } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { Debug.LogWarning((object)("ZBalrondWeaponCrate: RecipeFactory - requirement ItemDrop missing: " + itemPrefabName)); return null; } return new Requirement { m_resItem = component, m_amount = amount, m_amountPerLevel = amountPerLevel, m_recover = recover }; } private static Recipe FindRecipeByName(string recipeName) { if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null || string.IsNullOrEmpty(recipeName)) { return null; } for (int i = 0; i < ObjectDB.instance.m_recipes.Count; i++) { Recipe val = ObjectDB.instance.m_recipes[i]; if ((Object)(object)val != (Object)null && ((Object)val).name == recipeName) { return val; } } return null; } private static Recipe FindRecipeByItem(ItemDrop item) { if ((Object)(object)item == (Object)null || (Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null) { return null; } for (int i = 0; i < ObjectDB.instance.m_recipes.Count; i++) { Recipe val = ObjectDB.instance.m_recipes[i]; if ((Object)(object)val != (Object)null && (Object)(object)val.m_item == (Object)(object)item) { return val; } if ((Object)(object)val != (Object)null && (Object)(object)val.m_item != (Object)null && (Object)(object)((Component)val.m_item).gameObject != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null && ((Object)((Component)val.m_item).gameObject).name == ((Object)((Component)item).gameObject).name) { return val; } } return null; } private static void RefreshObjectDBLookups(ObjectDB db) { if (!((Object)(object)db == (Object)null)) { InvokeIfExists(db, "UpdateItemHashes"); InvokeIfExists(db, "UpdateRecipeHashes"); InvokeIfExists(db, "UpdateCraftingStations"); } } private static void InvokeIfExists(object target, string methodName) { try { if (target != null && !string.IsNullOrEmpty(methodName)) { MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null) && method.GetParameters().Length == 0) { method.Invoke(target, null); } } } catch (Exception ex) { if (Launch.DebugLog) { Debug.LogWarning((object)("ZBalrondWeaponCrate: RecipeFactory - failed invoking " + methodName + ": " + ex)); } } } } [HarmonyPatch] public static class WeaponCrateRotatePatch { public sealed class WeaponCratePieceMarker : MonoBehaviour { } private sealed class State { public int GhostId = -1; public int XStep = 0; public int ZStep = 0; public bool AltWasDown = false; public bool CtrlWasDown = false; } private const float StepDegrees = 30f; private static readonly int StepCount = Mathf.RoundToInt(12f); private static readonly ConditionalWeakTable<Player, State> s_state = new ConditionalWeakTable<Player, State>(); private static State Get(Player p) { return s_state.GetOrCreateValue(p); } private static bool AltDown() { return ZInput.GetKey((KeyCode)308, true) || ZInput.GetKey((KeyCode)307, true); } private static bool CtrlDown() { return ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true); } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] [HarmonyPostfix] private static void UpdatePlacementGhost_Postfix(Player __instance, bool flashGuardStone) { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((Character)__instance).InPlaceMode()) { return; } GameObject placementGhost = __instance.m_placementGhost; if (!((Object)(object)placementGhost == (Object)null) && !((Object)(object)placementGhost.GetComponent<WeaponCratePieceMarker>() == (Object)null)) { State state = Get(__instance); int instanceID = ((Object)placementGhost).GetInstanceID(); if (state.GhostId != instanceID) { state.GhostId = instanceID; state.XStep = 0; state.ZStep = 0; state.AltWasDown = false; state.CtrlWasDown = false; } bool flag = AltDown(); if (flag && !state.AltWasDown) { state.ZStep = (state.ZStep + 1) % StepCount; } state.AltWasDown = flag; bool flag2 = CtrlDown(); if (flag2 && !state.CtrlWasDown) { state.XStep = (state.XStep + 1) % StepCount; } state.CtrlWasDown = flag2; float num = (float)state.XStep * 30f; float num2 = (float)state.ZStep * 30f; if (state.XStep != 0 || state.ZStep != 0) { placementGhost.transform.rotation = placementGhost.transform.rotation * Quaternion.Euler(num, 0f, num2); } } } } public sealed class WeaponCrateBuilder { private const string SparklesChildName = "fx_ItemSparkles"; private const bool RemoveAllMeshColliders = false; public void BuildWeaponCratePieces() { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) if (!Launch.IsObjectDBValid()) { return; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || !TryGetCratePieceTable(instance, "WeaponCrate_bal", out var table) || !TryResolveTemplateAll("FierySvinstew", out var templateGo, out var templatePiece, out var templateWnt)) { return; } Transform templateSparkles = ItemUtils.FindChildRecursiveByName(templateGo.transform, "fx_ItemSparkles"); if (table.m_pieces == null) { table.m_pieces = new List<GameObject>(); } HashSet<string> exclude = ToSet(Launch.ManualExclude); HashSet<string> names = ToSet(Launch.ManualIncludeWeapons); HashSet<string> names2 = ToSet(Launch.ManualIncludeArmors); int num = 0; int num2 = 0; int skippedNoIcon = 0; int skippedNoVisual = 0; for (int i = 0; i < instance.m_items.Count; i++) { GameObject prefab = instance.m_items[i]; if (!IsCandidatePrefab(prefab, exclude, out var drop, out var isWeapon, out var _, ref skippedNoIcon, ref skippedNoVisual)) { continue; } PieceCategory category = (PieceCategory)(isWeapon ? 7 : 6); if (PrepareBuildPiece(prefab, drop, templatePiece, templateWnt, templateSparkles, category) && EnsureInPieceTable(table, prefab)) { if (isWeapon) { num++; } else { num2++; } } } num += AddManualList(instance, table, names, exclude, templatePiece, templateWnt, templateSparkles, (PieceCategory)7, ref skippedNoIcon, ref skippedNoVisual); num2 += AddManualList(instance, table, names2, exclude, templatePiece, templateWnt, templateSparkles, (PieceCategory)6, ref skippedNoIcon, ref skippedNoVisual); Debug.Log((object)(Launch.projectName + $" WeaponCrate pieces ensured. Weapons={num} Armors={num2} Skipped(NoIcon)={skippedNoIcon} Skipped(NoVisual)={skippedNoVisual}")); } private static bool PrepareBuildPiece(GameObject prefab, ItemDrop drop, Piece templatePiece, WearNTear templateWnt, Transform templateSparkles, PieceCategory category) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) GameObject val = ItemUtils.PickVisualRoot(prefab); if ((Object)(object)val == (Object)null) { return false; } if (Launch.RequireAttachChild) { Transform val2 = ItemUtils.FindChildRecursiveByName(prefab.transform, "attach"); if ((Object)(object)val2 == (Object)null) { if (Launch.DebugLog) { Debug.LogWarning((object)(Launch.projectName + " attach not present on " + ((Object)prefab).name)); } return false; } } ColliderSanitizer.SanitizeForBuildPiece(val, removeAllMeshColliders: false, Launch.DebugLog, Launch.projectName); Piece val3 = prefab.GetComponent<Piece>(); if ((Object)(object)val3 == (Object)null) { val3 = prefab.AddComponent<Piece>(); } PieceNTearSetter.CopyPieceSettings(drop, val3, templatePiece); val3.m_category = category; val3.m_icon = ItemUtils.SafeFirstIcon(drop); val3.m_name = drop.m_itemData.m_shared.m_name; val3.m_description = drop.m_itemData.m_shared.m_description; if (Launch.ForceCostToSelf) { PieceNTearSetter.SetSingleRequirement(val3, ((Object)prefab).name, Launch.CostAmount, 0, recover: true); } WearNTear val4 = prefab.GetComponent<WearNTear>(); if ((Object)(object)val4 == (Object)null) { val4 = prefab.AddComponent<WearNTear>(); } PieceNTearSetter.CopyWearNTearSettings(val4, templateWnt); val4.m_new = val; val4.m_worn = val; val4.m_broken = val; if ((Object)(object)prefab.GetComponent<WeaponCrateRotatePatch.WeaponCratePieceMarker>() == (Object)null) { prefab.AddComponent<WeaponCrateRotatePatch.WeaponCratePieceMarker>(); } GameObject val5 = ItemVfxApplier.ApplySparklesAndCleanRoot(prefab, templateSparkles, Launch.DebugLog, Launch.projectName); if ((Object)(object)val5 != (Object)null) { drop.m_pieceDisabledObj = val5; } GameObject val6 = FindEnabledObjectCandidate(prefab); if ((Object)(object)val6 != (Object)null) { drop.m_pieceEnableObj = val6; } if (Launch.DebugLog) { Debug.Log((object)(Launch.projectName + " Prepared build piece: " + ((Object)prefab).name + " visual=" + ((Object)val).name)); } return true; } private static bool IsCandidatePrefab(GameObject prefab, HashSet<string> exclude, out ItemDrop drop, out bool isWeapon, out bool isArmor, ref int skippedNoIcon, ref int skippedNoVisual) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) drop = null; isWeapon = false; isArmor = false; if ((Object)(object)prefab == (Object)null) { return false; } if (exclude != null && exclude.Contains(((Object)prefab).name)) { return false; } drop = prefab.GetComponent<ItemDrop>(); if ((Object)(object)drop == (Object)null || drop.m_itemData == null || drop.m_itemData.m_shared == null) { return false; } ItemType itemType = drop.m_itemData.m_shared.m_itemType; isWeapon = ItemUtils.IsWeaponType(itemType, Launch.ShieldsAreWeapons); isArmor = ItemUtils.IsArmorType(itemType, Launch.ShieldsAreWeapons); if (!isWeapon && !isArmor) { return false; } if (!ItemUtils.HasAnyIcon(drop)) { skippedNoIcon++; return false; } if (!ItemUtils.HasUsableVisual(prefab)) { skippedNoVisual++; return false; } return true; } private static int AddManualList(ObjectDB db, PieceTable table, HashSet<string> names, HashSet<string> exclude, Piece templatePiece, WearNTear templateWnt, Transform templateSparkles, PieceCategory category, ref int skippedNoIcon, ref int skippedNoVisual) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (names == null || names.Count == 0) { return 0; } int num = 0; foreach (string n in names) { if (!string.IsNullOrEmpty(n) && (exclude == null || !exclude.Contains(n))) { GameObject val = db.m_items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == n); ItemDrop drop; bool isWeapon; bool isArmor; if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)(Launch.projectName + " Manual include not found: " + n)); } else if (IsCandidatePrefab(val, null, out drop, out isWeapon, out isArmor, ref skippedNoIcon, ref skippedNoVisual) && PrepareBuildPiece(val, drop, templatePiece, templateWnt, templateSparkles, category) && EnsureInPieceTable(table, val)) { num++; } } } return num; } private static bool EnsureInPieceTable(PieceTable table, GameObject prefab) { for (int i = 0; i < table.m_pieces.Count; i++) { GameObject val = table.m_pieces[i]; if ((Object)(object)val != (Object)null && ((Object)val).name == ((Object)prefab).name) { return false; } } table.m_pieces.Add(prefab); return true; } private static bool TryGetCratePieceTable(ObjectDB db, string cratePrefabName, out PieceTable table) { table = null; if (string.IsNullOrEmpty(cratePrefabName)) { return false; } GameObject val = db.m_items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == cratePrefabName); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)(Launch.projectName + " Weapon crate prefab not found in ObjectDB: " + cratePrefabName)); return false; } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { Debug.LogWarning((object)(Launch.projectName + " Weapon crate ItemDrop/shared missing: " + cratePrefabName)); return false; } table = component.m_itemData.m_shared.m_buildPieces; if ((Object)(object)table == (Object)null) { Debug.LogWarning((object)(Launch.projectName + " Weapon crate has no PieceTable (m_buildPieces null): " + cratePrefabName)); return false; } if (table.m_pieces == null) { table.m_pieces = new List<GameObject>(); } return true; } private static GameObject FindEnabledObjectCandidate(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } Transform val = ItemUtils.FindChildRecursiveByName(prefab.transform, "equiped"); if ((Object)(object)val == (Object)null) { val = ItemUtils.FindChildRecursiveByName(prefab.transform, "equipped"); } if ((Object)(object)val == (Object)null) { val = ItemUtils.FindChildRecursiveByName(prefab.transform, "effects"); } return ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null; } private static GameObject FindPrefabAny(string name) { if (string.IsNullOrEmpty(name)) { return null; } if ((Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } GameObject val = ObjectDB.instance.m_items.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name); if ((Object)(object)val != (Object)null) { return val; } } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab(name); if ((Object)(object)prefab != (Object)null) { return prefab; } } return null; } private static bool TryResolveTemplateAll(string requestedName, out GameObject templateGo, out Piece templatePiece, out WearNTear templateWnt) { templateGo = null; templatePiece = null; templateWnt = null; string[] array = new string[5] { requestedName, "piece_chest_wood", "wood_wall", "wood_floor", "piece_chest" }; foreach (string text in array) { if (string.IsNullOrEmpty(text)) { continue; } GameObject val = FindPrefabAny(text); if ((Object)(object)val == (Object)null) { continue; } Piece component = val.GetComponent<Piece>(); WearNTear component2 = val.GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { templateGo = val; templatePiece = component;