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 RecipeGate v1.0.0
RecipeGate.dll
Decompiled 18 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("RecipeGate")] [assembly: AssemblyProduct("RecipeGate")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("2.3.0.0")] namespace RecipeGate; public static class CacheNucleo { private const int Magica = 843269970; public const int Formato = 2; public const int MaxArquivo = 262144; private const int MaxTexto = 128; public static byte[] Montar(string versao, string assinatura, int quantas, byte[] bruto, int maxBruto, int maxComprimido) { if (string.IsNullOrEmpty(versao) || string.IsNullOrEmpty(assinatura) || quantas <= 0 || bruto == null || bruto.Length == 0 || bruto.Length > maxBruto) { throw new InvalidDataException("dados de cache invalidos"); } byte[] array = RedeNucleo.Comprimir(bruto); if (array.Length == 0 || array.Length > maxComprimido) { throw new InvalidDataException("cache comprimido excede o limite"); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8); binaryWriter.Write(843269970); binaryWriter.Write(2); EscreverTexto(binaryWriter, versao); EscreverTexto(binaryWriter, assinatura); binaryWriter.Write(quantas); binaryWriter.Write(bruto.Length); byte[] array2 = RedeNucleo.Hash(bruto); binaryWriter.Write(array2.Length); binaryWriter.Write(array2); binaryWriter.Write(array.Length); binaryWriter.Write(array); binaryWriter.Flush(); if (memoryStream.Length > 262144) { throw new InvalidDataException("arquivo de cache excede o limite"); } return memoryStream.ToArray(); } public static bool TentarLer(byte[] arquivo, string versaoEsperada, string assinaturaEsperada, int maxBruto, int maxComprimido, out int quantas, out byte[] bruto) { quantas = 0; bruto = null; if (arquivo == null || arquivo.Length == 0 || arquivo.Length > 262144 || string.IsNullOrEmpty(versaoEsperada) || string.IsNullOrEmpty(assinaturaEsperada)) { return false; } try { using MemoryStream memoryStream = new MemoryStream(arquivo, writable: false); using BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8); if (binaryReader.ReadInt32() != 843269970 || binaryReader.ReadInt32() != 2) { return false; } string text = LerTexto(binaryReader); string text2 = LerTexto(binaryReader); int num = binaryReader.ReadInt32(); int num2 = binaryReader.ReadInt32(); int num3 = binaryReader.ReadInt32(); if (text != versaoEsperada || text2 != assinaturaEsperada || num <= 0 || num > 100000 || num2 <= 0 || num2 > maxBruto || num3 != 32) { return false; } byte[] a = LerExato(binaryReader, num3); int num4 = binaryReader.ReadInt32(); if (num4 <= 0 || num4 > maxComprimido || num4 > memoryStream.Length - memoryStream.Position) { return false; } byte[] comprimido = LerExato(binaryReader, num4); if (memoryStream.Position != memoryStream.Length) { return false; } byte[] array = RedeNucleo.Descomprimir(comprimido, num2, maxBruto); if (!RedeNucleo.Iguais(a, RedeNucleo.Hash(array))) { return false; } quantas = num; bruto = array; return true; } catch { quantas = 0; bruto = null; return false; } } private static void EscreverTexto(BinaryWriter writer, string valor) { byte[] bytes = Encoding.UTF8.GetBytes(valor); if (bytes.Length == 0 || bytes.Length > 128) { throw new InvalidDataException("cabecalho de cache invalido"); } writer.Write(bytes.Length); writer.Write(bytes); } private static string LerTexto(BinaryReader reader) { int num = reader.ReadInt32(); if (num <= 0 || num > 128) { throw new InvalidDataException("cabecalho de cache invalido"); } return Encoding.UTF8.GetString(LerExato(reader, num)); } private static byte[] LerExato(BinaryReader reader, int tamanho) { byte[] array = reader.ReadBytes(tamanho); if (array.Length != tamanho) { throw new EndOfStreamException(); } return array; } } internal static class DumpSpawns { private class Bicho { public string Prefab; public List<string> Biomas = new List<string>(); public List<string> Chaves = new List<string>(); public List<string> Drops = new List<string>(); public int MenorTier = 99; public int MaiorTier = -1; } private static bool _feito; private static readonly Biome[] TierBiomes = (Biome[])(object)new Biome[8] { (Biome)1, (Biome)8, (Biome)2, (Biome)4, (Biome)16, (Biome)512, (Biome)32, (Biome)64 }; private static readonly string[] Nomes = new string[8] { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands", "DeepNorth" }; internal static void Escrever(SpawnSystem sistema) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (_feito || (Object)(object)sistema == (Object)null || sistema.m_spawnLists == null) { return; } _feito = true; Dictionary<string, Bicho> dictionary = new Dictionary<string, Bicho>(StringComparer.OrdinalIgnoreCase); int num = 0; for (int i = 0; i < sistema.m_spawnLists.Count; i++) { SpawnSystemList val = sistema.m_spawnLists[i]; if ((Object)(object)val == (Object)null || val.m_spawners == null) { continue; } for (int j = 0; j < val.m_spawners.Count; j++) { SpawnData val2 = val.m_spawners[j]; if (val2 == null || (Object)(object)val2.m_prefab == (Object)null) { continue; } num++; string prefabName = Utils.GetPrefabName(val2.m_prefab); if (!dictionary.TryGetValue(prefabName, out var value)) { value = new Bicho(); value.Prefab = prefabName; value.Drops = Drops(val2.m_prefab); dictionary[prefabName] = value; } string text = ((!val2.m_enabled) ? " [desativado]" : "") + (val2.m_devDisabled ? " [devDisabled]" : ""); for (int k = 0; k < TierBiomes.Length; k++) { if ((val2.m_biome & TierBiomes[k]) == 0) { continue; } string item = Nomes[k] + text; if (!value.Biomas.Contains(item)) { value.Biomas.Add(item); } if (val2.m_enabled && !val2.m_devDisabled) { if (k < value.MenorTier) { value.MenorTier = k; } if (k > value.MaiorTier) { value.MaiorTier = k; } } } if (!string.IsNullOrEmpty(val2.m_requiredGlobalKey)) { string requiredGlobalKey = val2.m_requiredGlobalKey; if (!value.Chaves.Contains(requiredGlobalKey)) { value.Chaves.Add(requiredGlobalKey); } } } } Salvar(dictionary, num); } private static string Ingredientes(ObjectDB db, GameObject produto) { if (db.m_recipes == null) { return "-"; } for (int i = 0; i < db.m_recipes.Count; i++) { Recipe val = db.m_recipes[i]; if ((Object)(object)val == (Object)null || (Object)(object)val.m_item == (Object)null || (Object)(object)((Component)val.m_item).gameObject != (Object)(object)produto) { continue; } if (val.m_resources == null) { return "-"; } List<string> list = new List<string>(); for (int j = 0; j < val.m_resources.Length; j++) { Requirement val2 = val.m_resources[j]; if (val2 != null && (Object)(object)val2.m_resItem != (Object)null) { list.Add(Utils.GetPrefabName(((Component)val2.m_resItem).gameObject)); } } if (list.Count <= 0) { return "-"; } return string.Join(" + ", list.ToArray()); } return "-"; } private static void DaTabela(List<string> saida, DropTable t) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (t != null && t.m_drops != null) { for (int i = 0; i < t.m_drops.Count; i++) { Junta(saida, t.m_drops[i].m_item); } } } private static void Junta(List<string> saida, GameObject item) { if (!((Object)(object)item == (Object)null)) { string prefabName = Utils.GetPrefabName(item); if (!string.IsNullOrEmpty(prefabName) && !saida.Contains(prefabName)) { saida.Add(prefabName); } } } private static List<string> Drops(GameObject prefab) { List<string> list = new List<string>(); CharacterDrop component = prefab.GetComponent<CharacterDrop>(); if ((Object)(object)component == (Object)null || component.m_drops == null) { return list; } for (int i = 0; i < component.m_drops.Count; i++) { Drop val = component.m_drops[i]; if (val != null && !((Object)(object)val.m_prefab == (Object)null)) { string prefabName = Utils.GetPrefabName(val.m_prefab); if (!list.Contains(prefabName)) { list.Add(prefabName); } } } return list; } private static void Salvar(Dictionary<string, Bicho> bichos, int entradas) { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# RecipeGate - lista de spawn lida do jogo"); stringBuilder.AppendLine("# gerado em " + DateTime.Now.ToString("yyyy-MM-dd HH:mm")); stringBuilder.AppendLine("# fonte: SpawnSystem.m_spawnLists (a mesma que o UpdateSpawning percorre)"); stringBuilder.AppendLine("#"); stringBuilder.AppendLine("# " + bichos.Count + " criaturas em " + entradas + " entradas de spawn"); stringBuilder.AppendLine(); List<Bicho> list = new List<Bicho>(bichos.Values); list.Sort((Bicho a, Bicho b) => (a.MenorTier == b.MenorTier) ? string.Compare(a.Prefab, b.Prefab, StringComparison.OrdinalIgnoreCase) : (a.MenorTier - b.MenorTier)); stringBuilder.AppendLine("## criaturas em mais de um tier (a regra do menor pode enganar aqui)"); stringBuilder.AppendLine(); int num = 0; for (int num2 = 0; num2 < list.Count; num2++) { Bicho bicho = list[num2]; if (bicho.MaiorTier > bicho.MenorTier && bicho.MaiorTier >= 0) { num++; stringBuilder.AppendLine(" " + bicho.Prefab.PadRight(24) + Nomes[bicho.MenorTier] + " .. " + Nomes[bicho.MaiorTier]); stringBuilder.AppendLine(" biomas: " + string.Join(", ", bicho.Biomas.ToArray())); if (bicho.Chaves.Count > 0) { stringBuilder.AppendLine(" exige chave: " + string.Join(", ", bicho.Chaves.ToArray())); } if (bicho.Drops.Count > 0) { stringBuilder.AppendLine(" larga: " + string.Join(", ", bicho.Drops.ToArray())); } } } if (num == 0) { stringBuilder.AppendLine(" (nenhuma)"); } stringBuilder.AppendLine(); stringBuilder.AppendLine("## todas as criaturas"); stringBuilder.AppendLine(); for (int num3 = 0; num3 < list.Count; num3++) { Bicho bicho2 = list[num3]; string text = ((bicho2.MenorTier < Nomes.Length) ? Nomes[bicho2.MenorTier] : "-"); stringBuilder.AppendLine(" " + bicho2.Prefab.PadRight(24) + text); stringBuilder.AppendLine(" biomas: " + string.Join(", ", bicho2.Biomas.ToArray())); if (bicho2.Chaves.Count > 0) { stringBuilder.AppendLine(" exige chave: " + string.Join(", ", bicho2.Chaves.ToArray())); } if (bicho2.Drops.Count > 0) { stringBuilder.AppendLine(" larga: " + string.Join(", ", bicho2.Drops.ToArray())); } } string text2 = RecipeGatePlugin.CaminhoDeRelatorio("spawns.txt"); File.WriteAllText(text2, stringBuilder.ToString()); RecipeGatePlugin.Log.LogInfo((object)("dump de spawn escrito em " + text2 + " (" + bichos.Count + " criaturas, " + num + " atravessando tier).")); } catch (Exception ex) { RecipeGatePlugin.Log.LogError((object)("nao consegui escrever o dump: " + ex.Message)); } } } [HarmonyPatch(typeof(SpawnSystem), "Awake")] internal static class SpawnSystemAwakeDumpPatch { private static void Postfix(SpawnSystem __instance) { try { if (RecipeGatePlugin.DumpSpawn.Value) { DumpSpawns.Escrever(__instance); } } catch (Exception ex) { RecipeGatePlugin.Log.LogError((object)("falha no dump de spawn: " + ex)); } } } public static class MapaWireNucleo { public const int MaxCaracteres = 4194304; public const int MaxEntradas = 100000; public static bool TentarLer(string texto, int contagemEsperada, out Dictionary<string, Resultado> mapa) { mapa = null; if (string.IsNullOrEmpty(texto) || texto.Length > 4194304) { return false; } Dictionary<string, Resultado> dictionary = new Dictionary<string, Resultado>(StringComparer.OrdinalIgnoreCase); string[] array = texto.Split(new char[1] { '\n' }); if (array.Length > 100001) { return false; } for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd(new char[1] { '\r' }); if (text.Length != 0) { string[] array2 = text.Split(new char[1] { '\t' }); if (array2.Length != 4 || array2[0].Length == 0 || array2[0].Length > 256 || array2[2].Length > 256 || array2[3].Length > 512) { return false; } if (!int.TryParse(array2[1], out var result) || result < 0 || result >= MapaNucleo.ChavePorTier.Length || dictionary.ContainsKey(array2[0])) { return false; } dictionary[array2[0]] = new Resultado(result, array2[2], array2[3]); } } if (dictionary.Count == 0 || dictionary.Count > 100000 || (contagemEsperada >= 0 && dictionary.Count != contagemEsperada)) { return false; } mapa = dictionary; return true; } } internal static class Mapa { private const int MaxMapaCache = 4194304; private const int MaxComprimidoCache = 245760; internal static Dictionary<string, Resultado> Derivado; internal static bool Pronto; private static readonly Biome[] TierBiomes = (Biome[])(object)new Biome[8] { (Biome)1, (Biome)8, (Biome)2, (Biome)4, (Biome)16, (Biome)512, (Biome)32, (Biome)64 }; private static SpawnSystem _sistema; private static string _assinaturaAtual; private static List<string> _marcosAnteriores; private static readonly List<string> Tempos = new List<string>(); private static readonly Dictionary<int, int> TierDoTema = new Dictionary<int, int>(); private static string[] _ignorar; private static readonly List<Fonte> Pisos = new List<Fonte>(); internal static int Desativados; private static Dictionary<string, string> _como; private static string _mecanismo; private static int TierDoBioma(Biome mask) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < TierBiomes.Length; i++) { if ((mask & TierBiomes[i]) != 0) { return i; } } return 0; } private static string Nome(GameObject go) { if (!((Object)(object)go == (Object)null)) { return Utils.GetPrefabName(go); } return null; } internal static void RefazerSePreciso() { if (!((Object)(object)_sistema == (Object)null) && (ListaMudou() || !string.Equals(_assinaturaAtual, Assinatura(_sistema), StringComparison.Ordinal))) { RecipeGatePlugin.Detalhe("os dados ou configs mudaram; invalidando o cache e refazendo o mapa."); Construir(_sistema); } } internal static void Esquecer() { Derivado = null; Pronto = false; _sistema = null; _assinaturaAtual = null; _ignorar = null; } internal static void Construir(SpawnSystem sistema) { _sistema = sistema; float realtimeSinceStartup = Time.realtimeSinceStartup; string assinatura = (_assinaturaAtual = Assinatura(sistema)); if (LerDoCache(assinatura)) { Pronto = Derivado != null && Derivado.Count > 0; RecipeGatePlugin.Log.LogInfo((object)("mapa pronto: " + Derivado.Count + " materiais (cache).")); RecipeGatePlugin.Detalhe("mapa lido do cache em " + ((Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f).ToString("0") + "ms; nada mudou nos dados do jogo."); Rede.PublicarMapaAtualizado(); return; } List<Fonte> fontes = new List<Fonte>(); List<Receita> receitas = new List<Receita>(); List<Ferramenta> ferramentas = new List<Ferramenta>(); List<Extensao> extensoes = new List<Extensao>(); Pisos.Clear(); Tempos.Clear(); Desativados = 0; _ignorar = null; Tenta("vegetacao", delegate { DoChao(fontes); }); Tenta("criaturas", delegate { DasCriaturas(fontes, sistema); }); Tenta("localizacoes", delegate { DosLocais(fontes); }); Tenta("bosses", delegate { DosBosses(fontes); }); Tenta("salas", delegate { DasSalas(fontes); }); Tenta("peixes", delegate { DosPeixes(fontes); }); Tenta("receitas", delegate { DasReceitas(receitas, ferramentas, extensoes); }); fontes.AddRange(Pisos); float realtimeSinceStartup2 = Time.realtimeSinceStartup; Derivado = MapaNucleo.Resolver(fontes, receitas, ferramentas, extensoes, 20); Tempos.Add("resolver " + ((Time.realtimeSinceStartup - realtimeSinceStartup2) * 1000f).ToString("0") + "ms"); Pronto = Derivado != null && Derivado.Count > 0; RecipeGatePlugin.Log.LogInfo((object)("mapa pronto: " + Derivado.Count + " materiais em " + (Time.realtimeSinceStartup - realtimeSinceStartup).ToString("0.0") + "s.")); RecipeGatePlugin.Detalhe("mapa derivado de " + fontes.Count + " fontes, " + receitas.Count + " receitas e " + extensoes.Count + " melhorias de estacao (" + Desativados + " colheitas ignoradas por filho desativado)."); RecipeGatePlugin.Detalhe("tempo por etapa: " + string.Join(", ", Tempos.ToArray())); Explicar(fontes, receitas); string text = MapaNucleo.Conferir(Derivado, RecipeGatePlugin.TabelaDoWap(), RecipeGatePlugin.ChaveDoMaterial); if (!string.IsNullOrEmpty(text)) { RecipeGatePlugin.Detalhe(text); } GravarCache(assinatura); Despejar(receitas, ferramentas); if (RecipeGatePlugin.GerarRelatorio.Value) { Escrever(); } Rede.PublicarMapaAtualizado(); } private static void Despejar(List<Receita> receitas, List<Ferramenta> ferramentas) { if (!RecipeGatePlugin.DumpSpawn.Value) { return; } try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# RecipeGate - receitas, como a formula as viu"); stringBuilder.AppendLine("# formato: produto | estacao nivel N | ingrediente + ingrediente"); stringBuilder.AppendLine(); List<string> list = new List<string>(); for (int i = 0; i < receitas.Count; i++) { Receita receita = receitas[i]; if (receita != null && !string.IsNullOrEmpty(receita.Produto)) { string text = (string.IsNullOrEmpty(receita.Estacao) ? "-" : receita.Estacao); if (receita.NivelEstacao > 1) { text = text + " nivel " + receita.NivelEstacao; } list.Add(" " + receita.Produto + " | " + text + " | " + string.Join(" + ", receita.Ingredientes.ToArray())); } } list.Sort(StringComparer.OrdinalIgnoreCase); for (int j = 0; j < list.Count; j++) { stringBuilder.AppendLine(list[j]); } File.WriteAllText(RecipeGatePlugin.CaminhoDeRelatorio("receitas.txt"), stringBuilder.ToString()); stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# RecipeGate - ferramentas: nivel e que dano fazem"); stringBuilder.AppendLine(); list.Clear(); for (int k = 0; k < ferramentas.Count; k++) { Ferramenta ferramenta = ferramentas[k]; if (ferramenta != null) { list.Add(" " + ferramenta.Prefab.PadRight(26) + " nivel " + ferramenta.Nivel + (ferramenta.Corta ? " corta" : "") + (ferramenta.Escava ? " escava" : "") + ((!ferramenta.Corta && !ferramenta.Escava) ? " (nao serve de ferramenta)" : "")); } } list.Sort(StringComparer.OrdinalIgnoreCase); for (int l = 0; l < list.Count; l++) { stringBuilder.AppendLine(list[l]); } File.WriteAllText(RecipeGatePlugin.CaminhoDeRelatorio("ferramentas.txt"), stringBuilder.ToString()); } catch (Exception ex) { RecipeGatePlugin.Log.LogWarning((object)("despejo: " + ex.Message)); } } private static string CaminhoDoCache() { return Path.Combine(RecipeGatePlugin.DiretorioDoCache(), "map-v2.cache"); } private static string Assinatura(SpawnSystem sistema) { //IL_059a: Unknown result type (might be due to invalid IL or missing references) //IL_05a4: Expected I4, but got Unknown //IL_0699: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Expected I4, but got Unknown ulong h = 14695981039346656037uL; List<string> list = new List<string>(); h = Mistura(h, VersaoDoJogo()); h = Mistura(h, "2.3.0"); try { h = Mistura(h, typeof(Mapa).Module.ModuleVersionId.ToString()); } catch { } List<string> list2 = new List<string>(); foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { list2.Add(pluginInfo.Key + "@" + ((pluginInfo.Value != null && pluginInfo.Value.Metadata != null) ? pluginInfo.Value.Metadata.Version.ToString() : "?")); } list2.Sort(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < list2.Count; i++) { h = Mistura(h, list2[i]); } list.Add("mods:" + h.ToString("x16")); ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance != (Object)null && instance.m_items != null) { h = Mistura(h, "itens" + instance.m_items.Count); for (int j = 0; j < instance.m_items.Count; j++) { if ((Object)(object)instance.m_items[j] != (Object)null) { h = Mistura(h, ((Object)instance.m_items[j]).name); } } } list.Add("itens:" + h.ToString("x16")); ZNetScene instance2 = ZNetScene.instance; if ((Object)(object)instance2 != (Object)null && instance2.m_prefabs != null) { h = Mistura(h, "prefabs" + instance2.m_prefabs.Count); for (int k = 0; k < instance2.m_prefabs.Count; k++) { if ((Object)(object)instance2.m_prefabs[k] != (Object)null) { h = Mistura(h, ((Object)instance2.m_prefabs[k]).name); } } } list.Add("prefabs:" + h.ToString("x16")); if ((Object)(object)instance != (Object)null && instance.m_recipes != null) { h = Mistura(h, "receitas" + instance.m_recipes.Count); for (int l = 0; l < instance.m_recipes.Count; l++) { Recipe val = instance.m_recipes[l]; if ((Object)(object)val == (Object)null || (Object)(object)val.m_item == (Object)null) { continue; } h = Mistura(h, ((Object)val.m_item).name + "|" + val.m_enabled + "|" + val.m_minStationLevel + "|" + val.m_requireOnlyOneIngredient + "|" + (((Object)(object)val.m_craftingStation == (Object)null) ? "" : ((Object)val.m_craftingStation).name)); if (val.m_resources == null) { continue; } for (int m = 0; m < val.m_resources.Length; m++) { Requirement val2 = val.m_resources[m]; if (val2 != null && (Object)(object)val2.m_resItem != (Object)null) { h = Mistura(h, ((Object)val2.m_resItem).name); } } } } list.Add("receitas:" + h.ToString("x16")); if ((Object)(object)instance != (Object)null && instance.m_items != null) { for (int n = 0; n < instance.m_items.Count; n++) { GameObject val3 = instance.m_items[n]; if (!((Object)(object)val3 == (Object)null)) { ItemDrop component = val3.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_toolTier > 0) { h = Mistura(h, "tool:" + ((Object)val3).name + ":" + component.m_itemData.m_shared.m_toolTier); } } } } list.Add("ferramentas:" + h.ToString("x16")); ZoneSystem instance3 = ZoneSystem.instance; if ((Object)(object)instance3 != (Object)null && instance3.m_locations != null) { h = Mistura(h, "locais" + instance3.m_locations.Count); for (int num = 0; num < instance3.m_locations.Count; num++) { ZoneLocation val4 = instance3.m_locations[num]; if (val4 != null) { h = Mistura(h, val4.m_prefabName + "|" + val4.m_quantity + "|" + (int)val4.m_biome + "|" + val4.m_enable); } } } list.Add("locais:" + h.ToString("x16")); if ((Object)(object)sistema != (Object)null && sistema.m_spawnLists != null) { for (int num2 = 0; num2 < sistema.m_spawnLists.Count; num2++) { SpawnSystemList val5 = sistema.m_spawnLists[num2]; if ((Object)(object)val5 == (Object)null || val5.m_spawners == null) { continue; } for (int num3 = 0; num3 < val5.m_spawners.Count; num3++) { SpawnData val6 = val5.m_spawners[num3]; if (val6 != null && !((Object)(object)val6.m_prefab == (Object)null)) { h = Mistura(h, ((Object)val6.m_prefab).name + "|" + (int)val6.m_biome + "|" + val6.m_enabled + "|" + val6.m_requiredGlobalKey); } } } } list.Add("spawns:" + h.ToString("x16")); string[] array = ListaDeIgnorados(); for (int num4 = 0; num4 < array.Length; num4++) { h = Mistura(h, "ign:" + array[num4]); } list.Add("ignorados:" + h.ToString("x16")); h = MisturaConfiguracoes(h); list.Add("configs:" + h.ToString("x16")); ConferirMarcos(list); return h.ToString("x16"); } private static void ConferirMarcos(List<string> marcos) { List<string> marcosAnteriores = _marcosAnteriores; _marcosAnteriores = marcos; if (marcosAnteriores == null) { return; } List<string> list = new List<string>(); for (int i = 0; i < marcos.Count && i < marcosAnteriores.Count; i++) { if (!(marcos[i] == marcosAnteriores[i])) { string item = marcos[i].Substring(0, marcos[i].IndexOf(':')); list.Add(item); } } if (list.Count != 0) { RecipeGatePlugin.Detalhe("assinatura mudou a partir de '" + list[0] + "' (arrastou: " + string.Join(", ", list.ToArray()) + ")."); } } private static ulong MisturaConfiguracoes(ulong h) { try { string[] files = Directory.GetFiles(Paths.ConfigPath, "*", SearchOption.AllDirectories); Array.Sort(files, (IComparer<string>?)StringComparer.OrdinalIgnoreCase); for (int i = 0; i < files.Length; i++) { string extension = Path.GetExtension(files[i]); if (extension.Equals(".cfg", StringComparison.OrdinalIgnoreCase) || extension.Equals(".yml", StringComparison.OrdinalIgnoreCase) || extension.Equals(".yaml", StringComparison.OrdinalIgnoreCase)) { FileInfo fileInfo = new FileInfo(files[i]); string text = files[i].Substring(Paths.ConfigPath.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); h = Mistura(h, "cfg:" + text.Replace(Path.DirectorySeparatorChar, '/')); h = Mistura(h, fileInfo.Length.ToString()); } } } catch (Exception ex) { RecipeGatePlugin.Log.LogWarning((object)("nao consegui conferir a data das configs; o cache pode ficar conservador (" + ex.Message + ").")); } return h; } private static string VersaoDoJogo() { try { Type type = AccessTools.TypeByName("Version"); if (type == null) { return "?"; } MethodInfo methodInfo = AccessTools.Method(type, "GetVersionString", (Type[])null, (Type[])null); if (methodInfo == null) { return "?"; } object obj = methodInfo.Invoke(null, null); return (obj == null) ? "?" : obj.ToString(); } catch { return "?"; } } private static ulong Mistura(ulong h, string texto) { if (texto == null) { texto = ""; } for (int i = 0; i < texto.Length; i++) { h ^= texto[i]; h *= 1099511628211L; } return h; } internal static string EmTexto() { if (Derivado == null) { return ""; } StringBuilder stringBuilder = new StringBuilder(Derivado.Count * 48); foreach (KeyValuePair<string, Resultado> item in Derivado) { stringBuilder.Append(item.Key).Append('\t').Append(item.Value.Tier) .Append('\t') .Append(item.Value.Origem ?? "") .Append('\t') .Append(item.Value.Onde ?? "") .Append('\n'); } return stringBuilder.ToString(); } internal static bool DeTexto(string texto) { return DeTexto(texto, -1); } internal static bool DeTexto(string texto, int contagemEsperada) { if (!MapaWireNucleo.TentarLer(texto, contagemEsperada, out var mapa)) { return false; } Derivado = mapa; Pronto = true; return true; } private static bool LerDoCache(string assinatura) { string text = CaminhoDoCache(); if (LerArquivoDoCache(text, assinatura)) { return true; } string caminho = text + ".bak"; if (LerArquivoDoCache(caminho, assinatura)) { RecipeGatePlugin.Detalhe("cache principal invalido; copia de recuperacao aceita."); return true; } return false; } private static bool LerArquivoDoCache(string caminho, string assinatura) { try { FileInfo fileInfo = new FileInfo(caminho); if (!fileInfo.Exists || fileInfo.Length <= 0 || fileInfo.Length > 262144) { return false; } if (!CacheNucleo.TentarLer(File.ReadAllBytes(caminho), "2.3.0", assinatura, 4194304, 245760, out var quantas, out var bruto)) { return false; } if (!DeTexto(Encoding.UTF8.GetString(bruto), quantas) || Derivado == null || Derivado.Count != quantas) { Derivado = null; Pronto = false; return false; } _ignorar = ListaDeIgnorados(); return true; } catch (Exception ex) { RecipeGatePlugin.Detalhe("cache ignorado: " + ex.Message); return false; } } private static void GravarCache(string assinatura) { string text = null; try { if (Derivado == null || Derivado.Count == 0) { return; } string text2 = CaminhoDoCache(); Directory.CreateDirectory(Path.GetDirectoryName(text2)); byte[] bytes = Encoding.UTF8.GetBytes(EmTexto()); byte[] array = CacheNucleo.Montar("2.3.0", assinatura, Derivado.Count, bytes, 4194304, 245760); text = text2 + ".tmp-" + Process.GetCurrentProcess().Id + "-" + Guid.NewGuid().ToString("N"); using (FileStream fileStream = new FileStream(text, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { fileStream.Write(array, 0, array.Length); fileStream.Flush(flushToDisk: true); } if (File.Exists(text2)) { try { File.Replace(text, text2, text2 + ".bak", ignoreMetadataErrors: true); text = null; return; } catch (PlatformNotSupportedException) { File.Copy(text2, text2 + ".bak", overwrite: true); File.Copy(text, text2, overwrite: true); return; } catch (IOException) { File.Copy(text2, text2 + ".bak", overwrite: true); File.Copy(text, text2, overwrite: true); return; } } File.Move(text, text2); text = null; } catch (Exception ex3) { RecipeGatePlugin.Log.LogWarning((object)("cache nao gravado: " + ex3.Message)); } finally { if (!string.IsNullOrEmpty(text) && File.Exists(text)) { try { File.Delete(text); } catch { } } } } private static void Tenta(string oQue, Action acao) { float realtimeSinceStartup = Time.realtimeSinceStartup; try { acao(); } catch (Exception ex) { RecipeGatePlugin.Log.LogWarning((object)(oQue + ": " + ex.Message)); } Tempos.Add(oQue + " " + ((Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f).ToString("0") + "ms"); } private static void DoChao(List<Fonte> fontes) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null || instance.m_vegetation == null) { return; } for (int i = 0; i < instance.m_vegetation.Count; i++) { ZoneVegetation val = instance.m_vegetation[i]; if (val == null || !val.m_enable || (Object)(object)val.m_prefab == (Object)null) { continue; } int num = TierDoBioma(val.m_biome); if (num >= 0) { List<string> list = new List<string>(); List<string> list2 = new List<string>(); Varrer(val.m_prefab, list, list2, null, 0); int tipo; int ferramenta = NivelDeFerramenta(val.m_prefab, 0, out tipo); string onde = Nome(val.m_prefab); for (int j = 0; j < list.Count; j++) { Fonte fonte = new Fonte(list[j], num, ferramenta, "chao", onde, fraca: false); fonte.TipoFerramenta = tipo; fontes.Add(fonte); } for (int k = 0; k < list2.Count; k++) { Fonte fonte2 = new Fonte(list2[k], num, ferramenta, "chao", onde, fraca: true); fonte2.TipoFerramenta = tipo; fontes.Add(fonte2); } } } } private static void DasCriaturas(List<Fonte> fontes, SpawnSystem sys) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sys == (Object)null || sys.m_spawnLists == null) { return; } for (int i = 0; i < sys.m_spawnLists.Count; i++) { SpawnSystemList val = sys.m_spawnLists[i]; if ((Object)(object)val == (Object)null || val.m_spawners == null) { continue; } for (int j = 0; j < val.m_spawners.Count; j++) { SpawnData val2 = val.m_spawners[j]; if (val2 == null || (Object)(object)val2.m_prefab == (Object)null || !val2.m_enabled || val2.m_devDisabled) { continue; } int num = TierDoBioma(val2.m_biome); if (num >= 0) { int num2 = MapaNucleo.TierDaChave(val2.m_requiredGlobalKey); if (num2 > num) { num = num2; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); Varrer(val2.m_prefab, list, list2, null, 0); string onde = Nome(val2.m_prefab); for (int k = 0; k < list.Count; k++) { fontes.Add(new Fonte(list[k], num, 0, "bicho", onde, fraca: false)); } for (int l = 0; l < list2.Count; l++) { fontes.Add(new Fonte(list2[l], num, 0, "bicho", onde, fraca: true)); } } } } } private static void DosBosses(List<Fonte> fontes) { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return; } int num = 0; for (int i = 0; i < instance.m_prefabs.Count; i++) { GameObject val = instance.m_prefabs[i]; if ((Object)(object)val == (Object)null) { continue; } Character component = val.GetComponent<Character>(); if ((Object)(object)component == (Object)null || !component.IsBoss()) { continue; } string defeatSetGlobalKey = component.m_defeatSetGlobalKey; if (string.IsNullOrEmpty(defeatSetGlobalKey)) { continue; } int num2 = MapaNucleo.TierDaChave(defeatSetGlobalKey); if (num2 <= 0) { continue; } CharacterDrop component2 = val.GetComponent<CharacterDrop>(); if ((Object)(object)component2 == (Object)null || component2.m_drops == null) { continue; } num++; string onde = Nome(val) + " (" + defeatSetGlobalKey + ")"; for (int j = 0; j < component2.m_drops.Count; j++) { Drop val2 = component2.m_drops[j]; if (val2 != null && !((Object)(object)val2.m_prefab == (Object)null)) { fontes.Add(new Fonte(Nome(val2.m_prefab), num2, 0, "boss", onde, fraca: false, piso: true)); } } } if (num > 0) { RecipeGatePlugin.Detalhe(num + " bosses lidos pela chave de derrota."); } } private static void DosLocais(List<Fonte> fontes) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected I4, but got Unknown ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null || instance.m_locations == null) { return; } for (int i = 0; i < instance.m_locations.Count; i++) { ZoneLocation val = instance.m_locations[i]; if (val == null || !val.m_enable || val.m_quantity <= 0 || Ignorada(val.m_prefabName)) { continue; } int num = TierDoBioma(val.m_biome); if (num < 0) { continue; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); bool flag = false; try { if (!val.m_prefab.IsLoaded) { val.m_prefab.Load(); flag = true; } GameObject asset = val.m_prefab.Asset; if ((Object)(object)asset != (Object)null) { Varrer(asset, list, list2, null, 0); Location component = asset.GetComponent<Location>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_interiorPrefab != (Object)null) { Varrer(component.m_interiorPrefab, list, list2, null, 0); } DungeonGenerator[] componentsInChildren = asset.GetComponentsInChildren<DungeonGenerator>(true); for (int j = 0; j < componentsInChildren.Length; j++) { int num2 = (int)componentsInChildren[j].m_themes; for (int k = 0; k < 32; k++) { int num3 = 1 << k; if ((num2 & num3) != 0 && (!TierDoTema.TryGetValue(num3, out var value) || value > num)) { TierDoTema[num3] = num; } } } } } catch (Exception ex) { RecipeGatePlugin.Log.LogDebug((object)(val.m_prefabName + ": " + ex.Message)); } finally { if (flag) { try { val.m_prefab.Release(); } catch { } } } for (int l = 0; l < list.Count; l++) { fontes.Add(new Fonte(list[l], num, 0, "local", val.m_prefabName, fraca: false)); } for (int m = 0; m < list2.Count; m++) { fontes.Add(new Fonte(list2[m], num, 0, "local", val.m_prefabName, fraca: true)); } } } private static void DasSalas(List<Fonte> fontes) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected I4, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) DungeonDB instance = DungeonDB.instance; if ((Object)(object)instance == (Object)null || instance.m_roomLists == null || TierDoTema.Count == 0) { return; } int num = 0; for (int i = 0; i < instance.m_roomLists.Count; i++) { GameObject val = instance.m_roomLists[i]; if ((Object)(object)val == (Object)null) { continue; } RoomList component = val.GetComponent<RoomList>(); if ((Object)(object)component == (Object)null || component.m_rooms == null) { continue; } for (int j = 0; j < component.m_rooms.Count; j++) { RoomData val2 = component.m_rooms[j]; if (val2 == null || !val2.m_enabled || !TierDoTema.TryGetValue((int)val2.m_theme, out var value)) { continue; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); bool flag = false; try { if (!val2.m_prefab.IsLoaded) { val2.m_prefab.Load(); flag = true; } GameObject asset = val2.m_prefab.Asset; if ((Object)(object)asset == (Object)null) { continue; } Varrer(asset, list, list2, null, 0); num++; goto IL_013e; } catch (Exception ex) { RecipeGatePlugin.Log.LogDebug((object)("sala: " + ex.Message)); goto IL_013e; } finally { if (flag) { try { val2.m_prefab.Release(); } catch { } } } IL_013e: string onde = "sala " + val2.m_theme; for (int k = 0; k < list.Count; k++) { fontes.Add(new Fonte(list[k], value, 0, "sala", onde, fraca: false)); } for (int l = 0; l < list2.Count; l++) { fontes.Add(new Fonte(list2[l], value, 0, "sala", onde, fraca: true)); } } } RecipeGatePlugin.Detalhe(num + " salas de masmorra lidas, em " + TierDoTema.Count + " temas."); } internal static string[] ListaDeIgnorados() { List<string> list = new List<string>(); string[] array = (RecipeGatePlugin.IgnorarLocais.Value ?? "").Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { list.Add(text); } } return list.ToArray(); } internal static bool ListaMudou() { if (!Pronto || _ignorar == null) { return false; } string[] array = ListaDeIgnorados(); if (array.Length != _ignorar.Length) { return true; } for (int i = 0; i < array.Length; i++) { if (!string.Equals(array[i], _ignorar[i], StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static bool Ignorada(string nome) { if (string.IsNullOrEmpty(nome)) { return false; } if (_ignorar == null) { _ignorar = ListaDeIgnorados(); } for (int i = 0; i < _ignorar.Length; i++) { if (nome.StartsWith(_ignorar[i], StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static void PisoDeChave(string item, int tier, string onde) { Pisos.Add(new Fonte(item, tier, 0, "loja", onde, fraca: false, piso: true)); } private static bool EstaAtivo(Component c, GameObject raiz) { if ((Object)(object)c == (Object)null) { return false; } Transform val = c.transform; while ((Object)(object)val != (Object)null) { if (!((Component)val).gameObject.activeSelf) { return false; } if ((Object)(object)raiz != (Object)null && (Object)(object)((Component)val).gameObject == (Object)(object)raiz) { break; } val = val.parent; } return true; } private static void Varrer(GameObject raiz, List<string> natural, List<string> bau, HashSet<int> vistos, int nivel) { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)raiz == (Object)null || nivel > 3) { return; } if (vistos == null) { vistos = new HashSet<int>(); } if (!vistos.Add(((Object)raiz).GetInstanceID())) { return; } Pickable[] componentsInChildren = raiz.GetComponentsInChildren<Pickable>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (!EstaAtivo((Component)(object)componentsInChildren[i], raiz)) { Desativados++; continue; } _mecanismo = "Pickable"; Junta(natural, componentsInChildren[i].m_itemPrefab); DaTabela(natural, componentsInChildren[i].m_extraDrops); } PickableItem[] componentsInChildren2 = raiz.GetComponentsInChildren<PickableItem>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if (!EstaAtivo((Component)(object)componentsInChildren2[j], raiz)) { Desativados++; continue; } _mecanismo = "PickableItem"; if ((Object)(object)componentsInChildren2[j].m_itemPrefab != (Object)null) { Junta(natural, ((Component)componentsInChildren2[j].m_itemPrefab).gameObject); } if (componentsInChildren2[j].m_randomItemPrefabs == null) { continue; } for (int k = 0; k < componentsInChildren2[j].m_randomItemPrefabs.Length; k++) { RandomItem val = componentsInChildren2[j].m_randomItemPrefabs[k]; if ((Object)(object)val.m_itemPrefab != (Object)null) { Junta(natural, ((Component)val.m_itemPrefab).gameObject); } } } _mecanismo = "MineRock5 (mineravel)"; MineRock5[] componentsInChildren3 = raiz.GetComponentsInChildren<MineRock5>(true); for (int l = 0; l < componentsInChildren3.Length; l++) { DaTabela(natural, componentsInChildren3[l].m_dropItems); } _mecanismo = "MineRock (mineravel)"; MineRock[] componentsInChildren4 = raiz.GetComponentsInChildren<MineRock>(true); for (int m = 0; m < componentsInChildren4.Length; m++) { DaTabela(natural, componentsInChildren4[m].m_dropItems); } _mecanismo = "TreeBase (arvore)"; TreeBase[] componentsInChildren5 = raiz.GetComponentsInChildren<TreeBase>(true); for (int n = 0; n < componentsInChildren5.Length; n++) { DaTabela(natural, componentsInChildren5[n].m_dropWhenDestroyed); string mecanismo = _mecanismo; _mecanismo = "cadeia: arvore vira tronco " + Nome(componentsInChildren5[n].m_logPrefab); Varrer(componentsInChildren5[n].m_logPrefab, natural, bau, vistos, nivel + 1); Varrer(componentsInChildren5[n].m_stubPrefab, natural, bau, vistos, nivel + 1); _mecanismo = mecanismo; } _mecanismo = "TreeLog (tronco)"; TreeLog[] componentsInChildren6 = raiz.GetComponentsInChildren<TreeLog>(true); for (int num = 0; num < componentsInChildren6.Length; num++) { DaTabela(natural, componentsInChildren6[num].m_dropWhenDestroyed); string mecanismo2 = _mecanismo; _mecanismo = "cadeia: tronco parte em " + Nome(componentsInChildren6[num].m_subLogPrefab); Varrer(componentsInChildren6[num].m_subLogPrefab, natural, bau, vistos, nivel + 1); _mecanismo = mecanismo2; } _mecanismo = "DropOnDestroyed"; DropOnDestroyed[] componentsInChildren7 = raiz.GetComponentsInChildren<DropOnDestroyed>(true); for (int num2 = 0; num2 < componentsInChildren7.Length; num2++) { DaTabela(natural, componentsInChildren7[num2].m_dropWhenDestroyed); } _mecanismo = "CharacterDrop (larga ao morrer)"; CharacterDrop[] componentsInChildren8 = raiz.GetComponentsInChildren<CharacterDrop>(true); for (int num3 = 0; num3 < componentsInChildren8.Length; num3++) { if (componentsInChildren8[num3].m_drops == null) { continue; } for (int num4 = 0; num4 < componentsInChildren8[num3].m_drops.Count; num4++) { Drop val2 = componentsInChildren8[num3].m_drops[num4]; if (val2 != null) { Junta(natural, val2.m_prefab); } } } _mecanismo = "Container (bau)"; Container[] componentsInChildren9 = raiz.GetComponentsInChildren<Container>(true); for (int num5 = 0; num5 < componentsInChildren9.Length; num5++) { DaTabela(bau, componentsInChildren9[num5].m_defaultItems); } _mecanismo = "CreatureSpawner"; CreatureSpawner[] componentsInChildren10 = raiz.GetComponentsInChildren<CreatureSpawner>(true); for (int num6 = 0; num6 < componentsInChildren10.Length; num6++) { Varrer(componentsInChildren10[num6].m_creaturePrefab, natural, bau, vistos, nivel + 1); } _mecanismo = "SpawnArea (ninho)"; SpawnArea[] componentsInChildren11 = raiz.GetComponentsInChildren<SpawnArea>(true); for (int num7 = 0; num7 < componentsInChildren11.Length; num7++) { if (componentsInChildren11[num7].m_prefabs == null) { continue; } for (int num8 = 0; num8 < componentsInChildren11[num7].m_prefabs.Count; num8++) { SpawnData val3 = componentsInChildren11[num7].m_prefabs[num8]; if (val3 != null) { Varrer(val3.m_prefab, natural, bau, vistos, nivel + 1); } } } _mecanismo = "WispSpawner"; WispSpawner[] componentsInChildren12 = raiz.GetComponentsInChildren<WispSpawner>(true); for (int num9 = 0; num9 < componentsInChildren12.Length; num9++) { Varrer(componentsInChildren12[num9].m_wispPrefab, natural, bau, vistos, nivel + 1); } _mecanismo = "TriggerSpawner"; TriggerSpawner[] componentsInChildren13 = raiz.GetComponentsInChildren<TriggerSpawner>(true); for (int num10 = 0; num10 < componentsInChildren13.Length; num10++) { if (componentsInChildren13[num10].m_creaturePrefabs != null) { for (int num11 = 0; num11 < componentsInChildren13[num10].m_creaturePrefabs.Length; num11++) { Varrer(componentsInChildren13[num10].m_creaturePrefabs[num11], natural, bau, vistos, nivel + 1); } } } _mecanismo = "Trader (loja)"; Trader[] componentsInChildren14 = raiz.GetComponentsInChildren<Trader>(true); for (int num12 = 0; num12 < componentsInChildren14.Length; num12++) { if (componentsInChildren14[num12].m_items == null) { continue; } for (int num13 = 0; num13 < componentsInChildren14[num12].m_items.Count; num13++) { TradeItem val4 = componentsInChildren14[num12].m_items[num13]; if (val4 == null || (Object)(object)val4.m_prefab == (Object)null) { continue; } string text = Nome(((Component)val4.m_prefab).gameObject); if (!string.IsNullOrEmpty(text)) { int num14 = MapaNucleo.TierDaChave(val4.m_requiredGlobalKey); if (num14 > 0) { PisoDeChave(text, num14, "loja: " + Nome(raiz)); } else { Junta(natural, ((Component)val4.m_prefab).gameObject); } } } } _mecanismo = "Beehive"; Beehive[] componentsInChildren15 = raiz.GetComponentsInChildren<Beehive>(true); for (int num15 = 0; num15 < componentsInChildren15.Length; num15++) { if ((Object)(object)componentsInChildren15[num15].m_honeyItem != (Object)null) { Junta(natural, ((Component)componentsInChildren15[num15].m_honeyItem).gameObject); } } _mecanismo = "SapCollector"; SapCollector[] componentsInChildren16 = raiz.GetComponentsInChildren<SapCollector>(true); for (int num16 = 0; num16 < componentsInChildren16.Length; num16++) { if ((Object)(object)componentsInChildren16[num16].m_spawnItem != (Object)null) { Junta(natural, ((Component)componentsInChildren16[num16].m_spawnItem).gameObject); } } Destructible[] componentsInChildren17 = raiz.GetComponentsInChildren<Destructible>(true); for (int num17 = 0; num17 < componentsInChildren17.Length; num17++) { string mecanismo3 = _mecanismo; _mecanismo = "cadeia: destruido vira " + Nome(componentsInChildren17[num17].m_spawnWhenDestroyed); Varrer(componentsInChildren17[num17].m_spawnWhenDestroyed, natural, bau, vistos, nivel + 1); _mecanismo = mecanismo3; } } private static int NivelDeFerramenta(GameObject go, int nivel) { int tipo; return NivelDeFerramenta(go, nivel, out tipo); } private static int NivelDeFerramenta(GameObject go, int nivel, out int tipo) { if ((Object)(object)go == (Object)null || nivel > 3) { tipo = 0; return 0; } int maior = 0; int tipoMaior = 0; bool flag = false; bool flag2 = false; Action<int, int> action = delegate(int exigido, int deQueTipo) { if (exigido > maior) { maior = exigido; tipoMaior = deQueTipo; } }; TreeBase[] componentsInChildren = go.GetComponentsInChildren<TreeBase>(true); if (componentsInChildren.Length > 0) { flag = true; } for (int num = 0; num < componentsInChildren.Length; num++) { action(componentsInChildren[num].m_minToolTier, 1); action(NivelDeFerramenta(componentsInChildren[num].m_logPrefab, nivel + 1, out var tipo2), tipo2); action(NivelDeFerramenta(componentsInChildren[num].m_stubPrefab, nivel + 1, out tipo2), tipo2); } TreeLog[] componentsInChildren2 = go.GetComponentsInChildren<TreeLog>(true); if (componentsInChildren2.Length > 0) { flag = true; } for (int num2 = 0; num2 < componentsInChildren2.Length; num2++) { action(componentsInChildren2[num2].m_minToolTier, 1); action(NivelDeFerramenta(componentsInChildren2[num2].m_subLogPrefab, nivel + 1, out var tipo3), tipo3); } MineRock5[] componentsInChildren3 = go.GetComponentsInChildren<MineRock5>(true); if (componentsInChildren3.Length > 0) { flag2 = true; } for (int num3 = 0; num3 < componentsInChildren3.Length; num3++) { action(componentsInChildren3[num3].m_minToolTier, 2); } MineRock[] componentsInChildren4 = go.GetComponentsInChildren<MineRock>(true); if (componentsInChildren4.Length > 0) { flag2 = true; } for (int num4 = 0; num4 < componentsInChildren4.Length; num4++) { action(componentsInChildren4[num4].m_minToolTier, 2); } Destructible[] componentsInChildren5 = go.GetComponentsInChildren<Destructible>(true); for (int num5 = 0; num5 < componentsInChildren5.Length; num5++) { action(componentsInChildren5[num5].m_minToolTier, 2); action(NivelDeFerramenta(componentsInChildren5[num5].m_spawnWhenDestroyed, nivel + 1, out var tipo4), tipo4); } if (maior == 0 && tipoMaior == 0) { if (flag2) { tipoMaior = 2; } else if (flag) { tipoMaior = 1; } } tipo = tipoMaior; return maior; } private static void DaTabela(List<string> saida, DropTable t) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (t != null && t.m_drops != null) { for (int i = 0; i < t.m_drops.Count; i++) { Junta(saida, t.m_drops[i].m_item); } } } private static void Junta(List<string> saida, GameObject item) { string text = Nome(item); if (!string.IsNullOrEmpty(text)) { if (_como != null && !_como.ContainsKey(text)) { _como[text] = _mecanismo; } if (!saida.Contains(text)) { saida.Add(text); } } } private static void DosPeixes(List<Fonte> fontes) { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return; } for (int i = 0; i < instance.m_prefabs.Count; i++) { GameObject val = instance.m_prefabs[i]; if ((Object)(object)val == (Object)null) { continue; } Fish component = val.GetComponent<Fish>(); if (!((Object)(object)component == (Object)null)) { string onde = "peixe: " + Nome(val); if ((Object)(object)val.GetComponent<ItemDrop>() != (Object)null) { fontes.Add(new Fonte(Nome(val), 0, 0, "mar", onde, fraca: false)); } if ((Object)(object)component.m_pickupItem != (Object)null) { fontes.Add(new Fonte(Nome(component.m_pickupItem), 0, 0, "mar", onde, fraca: false)); } } } } private static void DasReceitas(List<Receita> receitas, List<Ferramenta> ferramentas, List<Extensao> extensoes) { DaBancada(receitas); DasFerramentas(ferramentas); ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return; } for (int i = 0; i < instance.m_prefabs.Count; i++) { GameObject val = instance.m_prefabs[i]; if (!((Object)(object)val == (Object)null)) { DoQueProduzSozinho(receitas, val); DaCriacao(receitas, val); DasConversoes(receitas, val); DoPlantio(receitas, val); DaConstrucao(receitas, extensoes, val); } } } private static void DaBancada(List<Receita> receitas) { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_recipes == null) { return; } for (int i = 0; i < instance.m_recipes.Count; i++) { Recipe val = instance.m_recipes[i]; if ((Object)(object)val == (Object)null || !val.m_enabled || (Object)(object)val.m_item == (Object)null || val.m_resources == null) { continue; } Receita receita = new Receita(); receita.Produto = Nome(((Component)val.m_item).gameObject); receita.Estacao = (((Object)(object)val.m_craftingStation == (Object)null) ? null : Nome(((Component)val.m_craftingStation).gameObject)); receita.NivelEstacao = ((val.m_minStationLevel < 1) ? 1 : val.m_minStationLevel); receita.QualquerUm = val.m_requireOnlyOneIngredient; for (int j = 0; j < val.m_resources.Length; j++) { Requirement val2 = val.m_resources[j]; if (val2 != null && (Object)(object)val2.m_resItem != (Object)null) { receita.Ingredientes.Add(Nome(((Component)val2.m_resItem).gameObject)); } } if (receita.Ingredientes.Count > 0) { receitas.Add(receita); } } } private static void DasFerramentas(List<Ferramenta> ferramentas) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null) { return; } for (int i = 0; i < instance.m_items.Count; i++) { GameObject val = instance.m_items[i]; if (!((Object)(object)val == (Object)null)) { ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_toolTier > 0) { DamageTypes damages = component.m_itemData.m_shared.m_damages; ferramentas.Add(new Ferramenta(Nome(val), component.m_itemData.m_shared.m_toolTier, damages.m_chop > 0f, damages.m_pickaxe > 0f)); } } } } private static void DoQueProduzSozinho(List<Receita> receitas, GameObject go) { string text = Nome(go); SapCollector component = go.GetComponent<SapCollector>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_spawnItem != (Object)null) { receitas.Add(new Receita(Nome(((Component)component.m_spawnItem).gameObject), null, text)); } Beehive component2 = go.GetComponent<Beehive>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_honeyItem != (Object)null) { receitas.Add(new Receita(Nome(((Component)component2.m_honeyItem).gameObject), null, text)); } WispSpawner component3 = go.GetComponent<WispSpawner>(); if ((Object)(object)component3 != (Object)null && (Object)(object)component3.m_wispPrefab != (Object)null) { RendeComoReceita(receitas, component3.m_wispPrefab, text); } CreatureSpawner component4 = go.GetComponent<CreatureSpawner>(); if ((Object)(object)component4 != (Object)null && (Object)(object)component4.m_creaturePrefab != (Object)null && (Object)(object)go.GetComponent<Piece>() != (Object)null) { RendeComoReceita(receitas, component4.m_creaturePrefab, text); } } private static void DaCriacao(List<Receita> receitas, GameObject go) { EggGrow component = go.GetComponent<EggGrow>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_grownPrefab != (Object)null) { receitas.Add(new Receita(Nome(component.m_grownPrefab), null, Nome(go))); DropsComoReceita(receitas, component.m_grownPrefab); } Growup component2 = go.GetComponent<Growup>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_grownPrefab != (Object)null) { receitas.Add(new Receita(Nome(component2.m_grownPrefab), null, Nome(go))); DropsComoReceita(receitas, component2.m_grownPrefab); } } private static void DasConversoes(List<Receita> receitas, GameObject go) { string estacao = Nome(go); Smelter component = go.GetComponent<Smelter>(); if ((Object)(object)component != (Object)null && component.m_conversion != null) { for (int i = 0; i < component.m_conversion.Count; i++) { ItemConversion val = component.m_conversion[i]; if (val != null && !((Object)(object)val.m_from == (Object)null) && !((Object)(object)val.m_to == (Object)null)) { receitas.Add(new Receita(Nome(((Component)val.m_to).gameObject), estacao, Nome(((Component)val.m_from).gameObject))); } } } CookingStation component2 = go.GetComponent<CookingStation>(); if ((Object)(object)component2 != (Object)null && component2.m_conversion != null) { for (int j = 0; j < component2.m_conversion.Count; j++) { ItemConversion val2 = component2.m_conversion[j]; if (val2 != null && !((Object)(object)val2.m_from == (Object)null) && !((Object)(object)val2.m_to == (Object)null)) { receitas.Add(new Receita(Nome(((Component)val2.m_to).gameObject), estacao, Nome(((Component)val2.m_from).gameObject))); } } } Fermenter component3 = go.GetComponent<Fermenter>(); if (!((Object)(object)component3 != (Object)null) || component3.m_conversion == null) { return; } for (int k = 0; k < component3.m_conversion.Count; k++) { ItemConversion val3 = component3.m_conversion[k]; if (val3 != null && !((Object)(object)val3.m_from == (Object)null) && !((Object)(object)val3.m_to == (Object)null)) { receitas.Add(new Receita(Nome(((Component)val3.m_to).gameObject), estacao, Nome(((Component)val3.m_from).gameObject))); } } } private static void DoPlantio(List<Receita> receitas, GameObject go) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) Plant component = go.GetComponent<Plant>(); if ((Object)(object)component == (Object)null || component.m_grownPrefabs == null) { return; } Piece component2 = go.GetComponent<Piece>(); if ((Object)(object)component2 == (Object)null || component2.m_resources == null) { return; } List<string> list = new List<string>(); for (int i = 0; i < component2.m_resources.Length; i++) { Requirement val = component2.m_resources[i]; if (val != null && (Object)(object)val.m_resItem != (Object)null) { list.Add(Nome(((Component)val.m_resItem).gameObject)); } } if (list.Count == 0) { return; } for (int j = 0; j < component.m_grownPrefabs.Length; j++) { GameObject val2 = component.m_grownPrefabs[j]; if (!((Object)(object)val2 == (Object)null)) { List<string> list2 = new List<string>(); List<string> bau = new List<string>(); Varrer(val2, list2, bau, null, 0); for (int k = 0; k < list2.Count; k++) { Receita receita = new Receita(); receita.Produto = list2[k]; receita.Ingredientes = new List<string>(list); receita.Piso = TierDoBioma(component.m_biome); receitas.Add(receita); } } } } private static void DaConstrucao(List<Receita> receitas, List<Extensao> extensoes, GameObject go) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) string text = Nome(go); StationExtension component = go.GetComponent<StationExtension>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_craftingStation != (Object)null) { extensoes.Add(new Extensao(Nome(((Component)component.m_craftingStation).gameObject), text)); } Piece component2 = go.GetComponent<Piece>(); if ((Object)(object)component2 == (Object)null || component2.m_resources == null || component2.m_resources.Length == 0) { return; } Receita receita = new Receita(); receita.Produto = text; receita.Estacao = (((Object)(object)component2.m_craftingStation == (Object)null) ? null : Nome(((Component)component2.m_craftingStation).gameObject)); receita.Piso = TierDoBioma(component2.m_onlyInBiome); for (int i = 0; i < component2.m_resources.Length; i++) { Requirement val = component2.m_resources[i]; if (val != null && (Object)(object)val.m_resItem != (Object)null) { receita.Ingredientes.Add(Nome(((Component)val.m_resItem).gameObject)); } } if (receita.Ingredientes.Count > 0) { receitas.Add(receita); } } private static void RendeComoReceita(List<Receita> receitas, GameObject rende, string fonte) { if ((Object)(object)rende == (Object)null || string.IsNullOrEmpty(fonte)) { return; } List<string> list = new List<string>(); List<string> bau = new List<string>(); Varrer(rende, list, bau, null, 0); for (int i = 0; i < list.Count; i++) { if (!string.Equals(list[i], fonte, StringComparison.OrdinalIgnoreCase)) { receitas.Add(new Receita(list[i], null, fonte)); } } } private static void DropsComoReceita(List<Receita> receitas, GameObject criatura) { if ((Object)(object)criatura == (Object)null) { return; } CharacterDrop component = criatura.GetComponent<CharacterDrop>(); if ((Object)(object)component == (Object)null || component.m_drops == null) { return; } string text = Nome(criatura); if (string.IsNullOrEmpty(text)) { return; } for (int i = 0; i < component.m_drops.Count; i++) { Drop val = component.m_drops[i]; if (val != null && !((Object)(object)val.m_prefab == (Object)null)) { string text2 = Nome(val.m_prefab); if (!string.IsNullOrEmpty(text2)) { receitas.Add(new Receita(text2, null, text)); } } } } private static void Explicar(List<Fonte> fontes, List<Receita> receitas) { string value = RecipeGatePlugin.Explicar.Value; if (string.IsNullOrEmpty(value)) { return; } string[] array = value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } RecipeGatePlugin.Log.LogInfo((object)("--- " + text + " ---")); if (Derivado != null && Derivado.TryGetValue(text, out var value2)) { RecipeGatePlugin.Log.LogInfo((object)(" VENCEU tier " + value2.Tier + " " + value2.Origem + ": " + value2.Onde + (value2.Fraca ? " [FRACO]" : " [forte]"))); } for (int j = 0; j < fontes.Count; j++) { Fonte fonte = fontes[j]; if (fonte != null && string.Equals(fonte.Prefab, text, StringComparison.OrdinalIgnoreCase)) { RecipeGatePlugin.Log.LogInfo((object)(" fonte tier " + fonte.Tier + " " + fonte.Origem + ": " + fonte.Onde + (fonte.Fraca ? " (bau)" : "") + (fonte.Piso ? " (piso)" : "") + ((fonte.Ferramenta > 0) ? (" ferramenta " + fonte.Ferramenta) : ""))); } } QuemProduz(text); for (int k = 0; k < receitas.Count; k++) { Receita receita = receitas[k]; if (receita != null) { bool flag = string.Equals(receita.Produto, text, StringComparison.OrdinalIgnoreCase); bool flag2 = receita.Ingredientes.Contains(text); if (flag || flag2) { RecipeGatePlugin.Log.LogInfo((object)(" " + (flag ? "sai de" : "entra em") + " " + receita.Produto + " = " + string.Join(" + ", receita.Ingredientes.ToArray()) + (string.IsNullOrEmpty(receita.Estacao) ? "" : (" @" + receita.Estacao)) + ((receita.NivelEstacao > 1) ? (" nv" + receita.NivelEstacao) : "") + (receita.QualquerUm ? " (basta um)" : "") + ((receita.Piso > 0) ? (" (so em " + MapaNucleo.NomeDoTier(receita.Piso) + ")") : ""))); } } } } } private static void QuemProduz(string alvo) { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return; } int num = 0; for (int i = 0; i < instance.m_prefabs.Count; i++) { GameObject val = instance.m_prefabs[i]; if ((Object)(object)val == (Object)null) { continue; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); _como = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); _mecanismo = "?"; try { Varrer(val, list, list2, null, 0); } catch { _como = null; continue; } bool flag = list.Contains(alvo); bool flag2 = list2.Contains(alvo); if (!_como.TryGetValue(alvo, out var value)) { value = "?"; } _como = null; if (flag || flag2) { num++; if (num <= 20) { RecipeGatePlugin.Log.LogInfo((object)(" produz " + Nome(val) + " por " + value + ((flag2 && !flag) ? " (dentro de bau)" : ""))); } } } if (num == 0) { RecipeGatePlugin.Log.LogInfo((object)" NINGUEM produz isto em prefab nenhum do jogo."); } else if (num > 20) { RecipeGatePlugin.Log.LogInfo((object)(" ... e mais " + (num - 20) + " prefabs.")); } } internal static void Escrever() { try { if (Derivado == null) { return; } List<string> list = new List<string>(Derivado.Keys); list.Sort(StringComparer.OrdinalIgnoreCase); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# RecipeGate - mapa derivado dos dados do jogo"); stringBuilder.AppendLine("# " + DateTime.Now.ToString("yyyy-MM-dd HH:mm") + " | " + Derivado.Count + " materiais"); stringBuilder.AppendLine("#"); stringBuilder.AppendLine("# tier = MENOR entre as formas de obter, cada uma valendo"); stringBuilder.AppendLine("# MAX(bioma, ferramenta ou estacao exigida)"); stringBuilder.AppendLine("# bau conta so quando nao ha nenhuma outra origem"); stringBuilder.AppendLine(); for (int i = 0; i < MapaNucleo.Biomas.Length; i++) { List<string> list2 = new List<string>(); for (int j = 0; j < list.Count; j++) { if (Derivado[list[j]].Tier == i) { list2.Add(list[j]); } } if (list2.Count != 0) { string text = MapaNucleo.ChaveDoTier(i); stringBuilder.AppendLine("## " + MapaNucleo.NomeDoTier(i) + " (" + ((text == null) ? "livre" : ("exige " + text)) + ") " + list2.Count + " materiais"); stringBuilder.AppendLine(); for (int k = 0; k < list2.Count; k++) { Resultado resultado = Derivado[list2[k]]; stringBuilder.AppendLine(" " + list2[k] + " | " + resultado.Origem + ": " + resultado.Onde); } stringBuilder.AppendLine(); } } stringBuilder.AppendLine(MapaNucleo.Conferir(Derivado, RecipeGatePlugin.TabelaDoWap(), RecipeGatePlugin.ChaveDoMaterial)); File.WriteAllText(RecipeGatePlugin.CaminhoDeRelatorio("mapa.txt"), stringBuilder.ToString()); RecipeGatePlugin.Detalhe("relatorio do mapa escrito na pasta de relatorios."); } catch (Exception ex) { RecipeGatePlugin.Log.LogError((object)("falha ao escrever o relatorio: " + ex.Message)); } } } public class Fonte { public string Prefab; public int Tier; public int Ferramenta; public int TipoFerramenta; public string Origem; public string Onde; public bool Fraca; public bool Piso; public Fonte() { } public Fonte(string prefab, int tier, int ferramenta, string origem, string onde, bool fraca) { Prefab = prefab; Tier = tier; Ferramenta = ferramenta; Origem = origem; Onde = onde; Fraca = fraca; } public Fonte(string prefab, int tier, int ferramenta, string origem, string onde, bool fraca, bool piso) : this(prefab, tier, ferramenta, origem, onde, fraca) { Piso = piso; } } public class Receita { public string Produto; public List<string> Ingredientes = new List<string>(); public string Estacao; public bool QualquerUm; public int Piso; public int NivelEstacao; public Receita() { } public Receita(string produto, string estacao, params string[] ing) { Produto = produto; Estacao = estacao; NivelEstacao = 1; Ingredientes = new List<string>(ing); } } public class Extensao { public string Estacao; public string Prefab; public Extensao() { } public Extensao(string estacao, string prefab) { Estacao = estacao; Prefab = prefab; } } public static class Tipo { public const int Qualquer = 0; public const int Corte = 1; public const int Escavacao = 2; } public class Ferramenta { public string Prefab; public int Nivel; public bool Corta; public bool Escava; public Ferramenta() { } public Ferramenta(string prefab, int nivel) { Prefab = prefab; Nivel = nivel; Corta = true; Escava = true; } public Ferramenta(string prefab, int nivel, bool corta, bool escava) { Prefab = prefab; Nivel = nivel; Corta = corta; Escava = escava; } } public class Resultado { public int Tier; public string Origem; public string Onde; public bool Fraca; public Resultado(int t, string o, string onde) { Tier = t; Origem = o; Onde = onde; } public Resultado(int t, string o, string onde, bool fraca) : this(t, o, onde) { Fraca = fraca; } } public static class MapaNucleo { public static readonly string[] Biomas = new string[8] { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands", "DeepNorth" }; public static readonly string[] ChavePorTier = new string[8] { null, "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader" }; private static Dictionary<string, Resultado> _piso; public static string NomeDoTier(int t) { if (t < 0 || t >= Biomas.Length) { return "?"; } return Biomas[t]; } public static string ChaveDoTier(int t) { if (t < 0 || t >= ChavePorTier.Length) { return null; } return ChavePorTier[t]; } public static int TierDaChave(string chave) { if (string.IsNullOrEmpty(chave)) { return 0; } for (int i = 1; i < ChavePorTier.Length; i++) { if (string.Equals(ChavePorTier[i], chave, StringComparison.OrdinalIgnoreCase)) { return i; } } return 0; } public static Dictionary<string, Resultado> Resolver(List<Fonte> fontes, List<Receita> receitas, List<Ferramenta> ferramentas, int maxVoltas) { return Resolver(fontes, receitas, ferramentas, null, maxVoltas); } public static Dictionary<string, Resultado> Resolver(List<Fonte> fontes, List<Receita> receitas, List<Ferramenta> ferramentas, List<Extensao> extensoes, int maxVoltas) { if (extensoes == null) { extensoes = new List<Extensao>(); } _piso = new Dictionary<string, Resultado>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < fontes.Count; i++) { Fonte fonte = fontes[i]; if (fonte != null && fonte.Piso && !string.IsNullOrEmpty(fonte.Prefab) && (!_piso.TryGetValue(fonte.Prefab, out var value) || value.Tier < fonte.Tier)) { _piso[fonte.Prefab] = new Resultado(fonte.Tier, fonte.Origem, fonte.Onde); } } Dictionary<string, Resultado> dictionary = new Dictionary<string, Resultado>(StringComparer.OrdinalIgnoreCase); if (fontes == null) { fontes = new List<Fonte>(); } if (receitas == null) { receitas = new List<Receita>(); } if (ferramentas == null) { ferramentas = new List<Ferramenta>(); } HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); for (int j = 0; j < receitas.Count; j++) { if (receitas[j] != null && !string.IsNullOrEmpty(receitas[j].Produto)) { hashSet.Add(receitas[j].Produto); } } for (int k = 0; k < maxVoltas; k++) { Dictionary<string, Resultado> dictionary2 = new Dictionary<string, Resultado>(StringComparer.OrdinalIgnoreCase); for (int l = 0; l < fontes.Count; l++) { Fonte fonte2 = fontes[l]; if (fonte2 != null && !string.IsNullOrEmpty(fonte2.Prefab) && fonte2.Tier >= 0 && (!fonte2.Fraca || !hashSet.Contains(fonte2.Prefab))) { int num = CustoFerramenta(fonte2.Ferramenta, fonte2.TipoFerramenta, ferramentas, dictionary); if (num >= 0) { int t = Math.Max(fonte2.Tier, num); Melhor(dictionary2, fonte2.Prefab, t, fonte2.Fraca ? "bau" : fonte2.Origem, fonte2.Onde, fonte2.Fraca); } } } for (int m = 0; m < 10; m++) { bool flag = false; for (int n = 0; n < receitas.Count; n++) { Receita receita = receitas[n]; if (receita == null || string.IsNullOrEmpty(receita.Produto) || SeAlimentaDeSi(receita)) { continue; } int num2 = 0; bool flag2 = true; if (receita.QualquerUm) { num2 = -1; for (int num3 = 0; num3 < receita.Ingredientes.Count; num3++) { int num4 = TierDe(receita.Ingredientes[num3], dictionary2, dictionary); if (num4 >= 0 && (num2 < 0 || num4 < num2)) { num2 = num4; } } if (num2 < 0) { flag2 = false; } } else { for (int num5 = 0; num5 < receita.Ingredientes.Count; num5++) { int num6 = TierDe(receita.Ingredientes[num5], dictionary2, dictionary); if (num6 < 0) { flag2 = false; break; } if (num6 > num2) { num2 = num6; } } } if (!flag2) { continue; } if (receita.Piso > num2) { num2 = receita.Piso; } if (!string.IsNullOrEmpty(receita.Estacao)) { int num7 = TierDe(receita.Estacao, dictionary2, dictionary); if (num7 < 0) { continue; } if (num7 > num2) { num2 = num7; } int num8 = CustoDoNivel(receita.Estacao, receita.NivelEstacao, extensoes, dictionary2, dictionary); if (num8 > num2) { num2 = num8; } } bool flag3 = EhFraca(receita.Estacao, dictionary2, dictionary); for (int num9 = 0; num9 < receita.Ingredientes.Count; num9++) { if (flag3) { break; } if (EhFraca(receita.Ingredientes[num9], dictionary2, dictionary)) { flag3 = true; } } if (Melhor(dictionary2, receita.Produto, num2, "receita", Descrever(receita), flag3)) { flag = true; } } if (!flag) { break; } } for (int num10 = 0; num10 < 10; num10++) { bool flag4 = false; for (int num11 = 0; num11 < receitas.Count; num11++) { Receita receita2 = receitas[num11]; if (receita2 == null || string.IsNullOrEmpty(receita2.Produto) || SeAlimentaDeSi(receita2) || dictionary2.ContainsKey(receita2.Produto)) { continue; } int num12 = 0; bool flag5 = false; for (int num13 = 0; num13 < receita2.Ingredientes.Count; num13++) { int num14 = TierDe(receita2.Ingredientes[num13], dictionary2, dictionary); if (num14 < 0) { continue; } if (receita2.QualquerUm) { if (!flag5 || num14 < num12) { num12 = num14; } } else if (num14 > num12) { num12 = num14; } flag5 = true; } if (!string.IsNullOrEmpty(receita2.Estacao)) { int num15 = TierDe(receita2.Estacao, dictionary2, dictionary); if (num15 >= 0) { flag5 = true; if (num15 > num12) { num12 = num15; } int num16 = CustoDoNivel(receita2.Estacao, receita2.NivelEstacao, extensoes, dictionary2, dictionary); if (num16 > num12) { num12 = num16; } } } if (!flag5) { continue; } if (receita2.Piso > num12) { num12 = receita2.Piso; } bool flag6 = EhFraca(receita2.Estacao, dictionary2, dictionary); for (int num17 = 0; num17 < receita2.Ingredientes.Count; num17++) { if (flag6) { break; } if (EhFraca(receita2.Ingredientes[num17], dictionary2, dictionary)) { flag6 = true; } } if (Melhor(dictionary2, receita2.Produto, num12, "receita", Descrever(receita2) + " [parcial]", flag6)) { flag4 = true; } } if (!flag4) { break; } } for (int num18 = 0; num18 < fontes.Count; num18++) { Fonte fonte3 = fontes[num18]; if (fonte3 != null && fonte3.Fraca && !string.IsNullOrEmpty(fonte3.Prefab) && fonte3.Tier >= 0 && !dictionary2.ContainsKey(fonte3.Prefab)) { int num19 = CustoFerramenta(fonte3.Ferramenta, fonte3.TipoFerramenta, ferramentas, dictionary); if (num19 >= 0) { int t2 = Math.Max(fonte3.Tier, num19); Melhor(dictionary2, fonte3.Prefab, t2, "bau", fonte3.Onde, fraca: true); } } } for (int num20 = 0; num20 < fontes.Count; num20++) { Fonte fonte4 = fontes[num20]; if (fonte4 != null && fonte4.Piso && !string.IsNullOrEmpty(fonte4.Prefab) && (!dictionary2.TryGetValue(fonte4.Prefab, out var value2) || value2.Tier < fonte4.Tier)) { dictionary2[fonte4.Prefab] = new Resultado(fonte4.Tier, "boss", fonte4.Onde); } } if (Igual(dictionary2, dictionary)) { dictionary = dictionary2; break; } dictionary = dictionary2; } return dictionary; } private static int CustoDoNivel(string estacao, int nivel, List<Extensao> extensoes, Dictionary<string, Resultado> a, Dictionary<string, Resultado> b) { if (nivel <= 1 || extensoes.Count == 0) { return 0; } List<int> list = new List<int>(); for (int i = 0; i < extensoes.Count; i++) { Extensao extensao = extensoes[i]; if (extensao != null && string.Equals(extensao.Estacao, estacao, StringComparison.OrdinalIgnoreCase)) { int num = TierDe(extensao.Prefab, a, b); if (num >= 0) { list.Add(num); } } } if (list.Count == 0) { return 0; } list.Sort(); int num2 = nivel - 1; if (num2 > list.Count) { num2 = list.Count; } return list[num2 - 1]; } private static bool SeAlimentaDeSi(Receita r) { for (int i = 0; i < r.Ingredientes.Count; i++) { if (string.Equals(r.Ingredientes[i], r.Produto, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static string Descrever(Receita r) { string text = string.Join(" + ", r.Ingredientes.ToArray()); if (!string.IsNullOrEmpty(r.Estacao)) { text = text + " @" + r.Estacao; if (r.NivelEstacao > 1) { text = text + " nv" + r.NivelEstacao; } } if (r.Piso > 0) { text = text + " so em " + NomeDoTier(r.Piso); } return text; } private static bool EhFraca(string nome, Dictionary<string, Resultado> a, Dictionary<string, Resultado> b) { if (string.IsNullOrEmpty(nome)) { return false; } if (a != null && a.TryGetValue(nome, out var value)) { return value.Fraca; } if (b != null && b.TryGetValue(nome, out value)) { return value.Fraca; } return false; } private static int TierDe(string nome, Dictionary<string, Resultado> a, Dictionary<string, Resultado> b) { if (a != null && a.TryGetValue(nome, out var value)) { return value.Tier; } if (b != null && b.TryGetValue(nome, out value)) { return value.Tier; } return -1; } private static bool Melhor(Dictionary<string, Resultado> mapa, string prefab, int t, string origem, string onde) { return Melhor(mapa, prefab, t, origem, onde, fraca: false); } private static bool Melhor(Dictionary<string, Resultado> mapa, string prefab, int t, string origem, string onde, bool fraca) { if (_piso != null && _piso.TryGetValue(prefab, out var value) && value.Tier > t) { t = value.Tier; origem = value.Origem; onde = value.Onde; } if (mapa.TryGetValue(prefab, out var value2) && value2.Tier <= t) { if (value2.Fraca && !fraca && value2.Tier == t) { mapa[prefab] = new Resultado(t, origem, onde, fraca: false); return true; } return false; } mapa[prefab] = new Resultado(t, origem, onde, fraca); return true; } private static int CustoFerramenta(int nivel, int tipo, List<Ferramenta> ferramentas, Dictionary<string, Resultado> tier) { if (ferramentas == null) { return 0; } if (nivel <= 0 && tipo == 0) { return 0; } int num = int.MaxValue; for (int i = 0; i < ferramentas.Count; i++) { Ferramenta ferramenta = ferramentas[i]; if (ferramenta != null && ferramenta.Nivel >= nivel && (tipo != 1 || ferramenta.Corta) && (tipo != 2 || ferramenta.Escava) && tier != null && tier.TryGetValue(ferramenta.Prefab, out var value) && !value.Fraca && value.Tier < num) { num = value.Tier; } } if (num != int.MaxValue) { return num; } return -1; } private static bool Igual(Dictionary<string, Resultado> a, Dictionary<string, Resultado> b) { if (a.Count != b.Count) { return false; } foreach (KeyValuePair<string, Resultado> item in a) { if (!b.TryGetValue(item.Key, out var value)) { return false; } if (value.Tier != item.Value.Tier) { return false; } } return true; } public static string Conferir(Dictionary<string, Resultado> derivado, Dictionary<string, string> wap) { return Conferir(derivado, wap, null); } public static string Conferir(Dictionary<string, Resultado> derivado, Dictionary<string, string> wap, Func<string, string> efetiva) { StringBuilder stringBuilder = new StringBuilder(); if (derivado == null || wap == null) { return ""; } List<string> list = new List<string>(); List<string> list2 = new List<string>(); List<string> list3 = new List<string>(); foreach (KeyValuePair<string, string> item in wap) { if (!derivado.TryGetValue(item.Key, out var value)) { list3.Add(item.Key); continue; } string text = ChaveDoTier(value.Tier); bool flag = false; if (efetiva != null) { string text2 = efetiva(item.Key); if (text2 != text) { text = text2; flag = true; } } if (text == item.Value) { list.Add(item.Key); continue; } list2.Add(item.Key + ": derivado=" + (text ?? "livre") + " wap=" + item.Value + " (" + (flag ? "na mao" : (value.Origem + ": " + value.Onde)) + ")"); } stringBuilder.AppendLine("conferencia com o WAP: " + list.Count + " iguais, " + list2.Count + " diferentes, " + list3.Count + " sem origem derivada"); for (int i = 0; i < list2.Count; i++) { stringBuilder.AppendLine(" " + list2[i]); } if (list3.Count > 0) { stringBuilder.AppendLine(" sem origem: " + string.Join(", ", list3.ToArray())); } return stringBuilder.ToString(); } } public static class Nucleo { public const char Separador = ','; public static List<string> LerPendentes(string bruto) { List<string> list = new List<string>(); if (string.IsNullOrEmpty(bruto)) { return list; } string[] array = bruto.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0 && !list.Contains(text)) { list.Add(text); } } return list; } public static string GravarPendentes(List<string> lista) { if (lista == null || lista.Count == 0) { return null; } return string.Join(','.ToString(), lista.ToArray()); } public static bool Adicionar(List<string> lista, string prefab) { if (lista == null || string.IsNullOrEmpty(prefab)) { return false; } if (lista.Contains(prefab)) { return false; } lista.Add(prefab); return true; } public static bool DeveSegurar(string prefab, Func<string, string> chaveDe, Func<string, bool> temChave, out string chave) { chave = null; if (string.IsNullOrEmpty(prefab) || chaveDe == null || temChave == null) { return false; } chave = chaveDe(prefab); if (string.IsNullOrEmpty(chave)) { return false; } return !temChave(chave); } public static void Separar(List<string> pendentes, Func<string, string> chaveDe, Func<string, bool> temChave, out List<string> liberar, out List<string> restantes) { liberar = new List<string>(); restantes = new List<string>(); if (pendentes == null) { return; } for (int i = 0; i < pendentes.Count; i++) { string text = pendentes[i]; if (DeveSegurar(text, chaveDe, temChave, out var _)) { restantes.Add(text); } else { liberar.Add(text); } } } public static List<string> EmChavesGlobais(string bruto, bool par) { List<string> list = new List<string>(); List<string> list2 = LerPendentes(bruto); for (int i = 0; i < list2.Count; i++) { string text = list2[i].Trim(); if (text.Length == 0) { continue; } if (par) { int num = text.IndexOf('='); if (num <= 0 || num == text.Length - 1) { continue; } string text2 = text.Substring(0, num).Trim(); string text3 = text.Substring(num + 1).Trim(); if (text2.Length == 0 || text3.Length == 0) { continue; } text = text2 + "-" + text3; } text = text.ToLowerInvariant(); if (text.IndexOf(' ') < 0 && !list.Contains(text)) { list.Add(text); } } return list; } public static string EmParDeIgual(string chave) { if (string.IsNullOrEmpty(chave)) { return chave; } int num = chave.LastIndexOf('-'); if (num <= 0 || num == chave.Length - 1) { return chave; } return chave.Substring(0, num) + "=" + chave.Substring(num + 1); } public static bool ReceitaPossivel(List<string> ingredientes, bool bastaUm, Func<string, bool> conhece) { if (ingredientes == null || ingredientes.Count == 0 || conhece == null) { return false; } bool result = false; for (int i = 0; i < ingredientes.Count; i++) { string text = ingredientes[i]; if (string.IsNullOrEmpty(text)) { continue; } bool flag = conhece(text); if (bastaUm) { if (flag) { result = true; } } else if (!flag) { return false; } } if (!bastaUm) { return true; } return result; } } [BepInPlugin("raaotium.recipegate", "RecipeGate", "2.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class RecipeGatePlugin : BaseUnityPlugin { public const string GUID = "raaotium.recipegate"; public const string NAME = "RecipeGate"; public const string VERSION = "2.3.0"; internal const string WapGuid = "com.orianaventure.mod.WorldAdvancementProgression"; internal const string JotunnGuid = "com.jotunn.jotunn"; private const string WapKeyManager = "VentureValheim.Progression.KeyManager"; internal const string PendingKey = "recipegate_pending"; internal const string EnforceKey = "recipegate_on"; internal const string OvrPrefix = "recipegate_ovr-"; internal const string LocPrefix = "recipegate_loc-"; internal static RecipeGatePlugin Instancia; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> Verbose; internal static ConfigEntry<string> Overrides; internal static ConfigEntry<bool> DumpSpawn; internal static ConfigEntry<string> Explicar; internal static ConfigEntry<bool> GerarRelatorio; internal static ConfigEntry<string> IgnorarLocais; private static bool _wapChecked; private static object _keyManager; private static FieldInfo _bossItems; private static FieldInfo _materials; private static FieldInfo _foods; private Harmony _harmony; private FileSystemWatcher _watcher; private bool _travaPendente; private float _proximaTentativa; private float _proximaReafirmacao; private static volatile bool _recarregar; private static string _manuaisBruto; private static Dictionary<string, string> _manuais; private static int _frameDasChaves = -1; private static readonly Dictionary<string, bool> _chavesDoFrame = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); private static bool _estavaLigado = true; private static bool _mapaEstavaPronto; private static SpawnSystem _spawnGuardado; private static float _limiteDeEspera; private static bool _socorroFeito; private static StringBuilder _rastro; internal static string DiretorioDoCache() { return Path.Combine(Paths.BepInExRootPath, "cache", "raaotium.recipegate"); } internal static string CaminhoDeRelatorio(string nome) { string text = Path.Combine(Paths.ConfigPath, "raaotium.recipegate", "reports"); Directory.CreateDirectory(text); return Path.Combine(text, nome); } private static void PrepararArquivosGerados() { try { string path = DiretorioDoCache(); Directory.CreateDirectory(path); string path2 = Path.Combine(Paths.ConfigPath, "recipegate_cache.txt"); if (File.Exists(path2)) { File.Delete(path2); } string[] files = Directory.GetFiles(path, "map-v2.cache.tmp-*"); for (int i = 0; i < files.Length; i++) { File.Delete(files[i]); } string[] array = new string[5] { "spawns", "receitas", "ferramentas", "mapa", "simulacao" }; for (int j = 0; j < array.Length; j++) { string text = Path.Combine(Paths.ConfigPath, "recipegate_" + array[j] + ".txt"); if (File.Exists(text)) { string text2 = CaminhoDeRelatorio(array[j] + ".txt"); if (File.Exists(text2)) { File.Delete(text); } else { File.Move(text, text2); } } } } catch (Exception ex) { Log.LogDebug((object)("organizacao dos arquivos gerados: " + ex.Message)); } } internal static List<string> ChavesDoServidor(string prefixo) { List<string> list = new List<string>(); ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return list; } List<string> globalKeys; try { globalKeys = instance.GetGlobalKeys(); } catch { return list; } if (globalKeys == null) { return list; } for (int i = 0; i < globalKeys.Count; i++) { string text = globalKeys[i]; if (!string.IsNullOrEmpty(text) && text.StartsWith(prefixo, StringComparison.OrdinalIgnoreCase)) { string text2 = text.Substring(prefixo.Length).Trim(); if (text2.Length > 0) { list.Add(text2); } } } list.Sort(StringComparer.OrdinalIgnoreCase); return list; } internal static bool Forcado() { if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { return Rede.Recebido; } ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance != (Object)null) { return instance.GetGlobalKey("recipegate_on"); } return false; } private void Awake() { //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown Instancia = this; Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Geral", "Ativo", true, "Desligue para as receitas voltarem ao normal do jogo. Em multiplayer esta opcao e autoritativa no servidor e chega aos clientes pelo canal seguro do RecipeGate."); Verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Geral", "Log detalhado", false, "Registra no log cada decisao da trava e cada recalculo do mapa."); Overrides = ((BaseUnityPlugin)this).Config.Bind<string>("Mapa", "Materiais na mao", "DvergrKeyFragment=defeated_goblinking", "Prefab=chave, separado por virgula. Ganha de tudo. Serve para material que nenhuma tabela conhece. Em multiplayer vale exclusivamente a configuracao autenticada do servidor."); IgnorarLocais = ((BaseUnityPlugin)this).Config.Bind<string>("Mapa", "Ignorar localizacoes", "Dev", "Prefixos de nome de localizacao a ignorar ao montar o mapa, separados por virgula. Em multiplayer somente o servidor monta o mapa."); GerarRelatorio = ((BaseUnityPlugin)this).Config.Bind<bool>("Mapa", "Gerar relatorio", false, "Escreve BepInEx/config/raaotium.recipegate/reports/mapa.txt com o mapa derivado inteiro e a conferencia contra a tabela do WAP."); DumpSpawn = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostico", "Gerar dump de spawn", false, "Escreve arquivos de leitura em BepInEx/config/raaotium.recipegate/reports. Nao muda nada. Ligue, entre uma vez, desligue."); Explicar = ((BaseUnityPlugin)this).Config.Bind<string>("Diagnostico", "Explicar materiais", "", "Lista separada por virgula. Para cada material citado, o log mostra TODAS as fontes e receitas que falam dele, nao so a origem vencedora. Serve pra entender por que um item caiu no tier em que caiu. Ex: ChickenEgg,Chicken"); PrepararArquivosGerados(); try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; _watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath)); _watcher.Changed += delegate { _recarregar = true; }; _watcher.IncludeSubdirectories = false; _watcher.NotifyFilter = NotifyFilters.LastWrite; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("sem recarga automatica do cfg: " + ex.Message)); } Rede.Registrar(); _harmony = new Harmony("raaotium.recipegate"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"RecipeGate 2.3.0 carregado — sync direto e falha fechada."); } private void OnDestroy() { if (_watcher != null) { _watcher.Dispose(); _watcher = null; } Rede.Esquecer(); if (_harmony != null) { _harmony.UnpatchSelf(); } } private void Update() { Rede.Atualizar(); if (_travaPendente && Time.realtimeSinceStartup >= _proximaTentativa) { _proximaTentativa = Time.realtimeSinceStartup + 5f; if (PublicarTrava()) { _travaPendente = false; } } if (Mapa.Pronto != _mapaEstavaPronto) { _mapaEstavaPronto = Mapa.Pronto; if (Ligado() && (Object)(object)Player.m_localPlayer != (Object)null) { Trava.AtualizarReceitas(Player.m_localPlayer); } } if (_recarregar) { _recarregar = false; try { ((BaseUnityPlugin)this).Config.Reload(); Mapa.RefazerSePreciso(); Detalhe("cfg relido em tempo real."); _proximaReafirmacao = 0f; } catch (Exception ex) { Log.LogWarning((object)("falha ao reler o cfg: " + ex.Message)); } } SocorroSeOMapaNaoVeio(); bool flag = Ligado(); if (flag != _estavaLigado) { _estavaLigado = flag; Log.LogWarning((object)("RecipeGate " + (flag ? "LIGADO" : "DESLIGADO") + " em tempo real.")); } if (IsServer() && Time.realtimeSinceStartup >= _proximaReafirmacao) { _proximaReafirmacao = Time.realtimeSinceStartup + 30f; PublicarTrava(); } } internal void PedirTrava() { _travaPendente = true; _proximaTentativa = 0f; } private static bool WapPronto() { if (_wapChecked) { return _keyManager != null; } _wapChecked = true; try { Type type = AccessTools.TypeByName("VentureValheim.Progression.KeyManager"); if (type == null) { Detalhe("World Advancement Progression nao encontrado; sem conferencia, mas o mapa derivado basta."); return false; } PropertyInfo propertyInfo = AccessTools.Property(type, "Instance"); _keyManager = ((propertyInfo != null) ? propertyInfo.GetValue(null, null) : null); _bossItems = AccessTools.Field(type, "BossItemKeysList"); _materials = AccessTools.Field(type, "MaterialKeysList"); _foods = AccessTools.Field(type, "FoodKeysList"); if (_keyManager == null || _materials == null) { Log.LogWarning((object)"o WAP esta aqui mas com formato diferente do esperado; RecipeGate fica sem a conferencia, mas o mapa derivado basta."); _keyManager = null; return false; } Detalhe("WAP encontrado; as tabelas dele entram so como conferencia do mapa derivado."); return true; } catch (Exception ex) { Log.LogError((object)("falha ao encaixar no WAP (" + ex.Message + "); RecipeGate inerte.")); _keyManager = null; return false; } } private static Dictionary<string, string> Tabela(FieldInfo campo) { if (campo == null || _keyManager == null) { return null; } return campo.GetValue(_keyManager) as Dictionary<string, string>; } private static Dictionary<string, string> Manuais() { string text = (((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) ? Rede.OverridesServidor : Overrides.Value); text = text ?? ""; if (_manuais != null && text == _manuaisBruto) { return _manuais; } _manuaisBruto = text; _manuais = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); List<string> list = Nucleo.LerPendentes(text); for (int i = 0; i < list.Count; i++) { string text2 = list[i]; int num = text2.IndexOf('='); if (num <= 0) { Log.LogWarning((object)("ignorando '" + text2 + "': use 'Prefab=chave'")); continue; } string text3 = text2.Substring(0, num).Trim(); string text4 = text2.Substring(num + 1).Trim(); if (text3.Length > 0 && text4.Length > 0) { _manuais[text3] = text4; } } if (_manuais.Count > 0) { Detalhe(_manuais.Count + " material(is) mapeados na mao."); } return _manuais; } internal static Dictionary<string, string> TabelaDoWap() { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (!WapPronto()) { return dictionary; } FieldInfo[] array = new FieldInfo[3] { _bossItems, _materials, _foods }; for (int i = 0; i < array.Length; i++) { Dictionary<string, string> dictionary2 = Tabela(array[i]); if (dictionary2 == null) { continue; } foreach (KeyValuePair<string, string> item in dictionary2) { dictionary[item.Key] = item.Value; } } return dictionary; } internal static string ChaveDoMaterial(string prefab) { if (string.IsNullOrEmpty(prefab)) { return null; } if (Manuais().TryGetValue(prefab, out var value)) { return value; } if (!Mapa.Pronto || Mapa.Derivado == null) { return null; } if (!Mapa.Derivado.TryGetValue(prefab, out var value2)) { return null; } return MapaNucleo.ChaveDoTier(value2.Tier); } internal static bool TemChave(string chave) { if (string.IsNullOrEmpty(chave)) { return true; } int frameCount = Time.frameCount; if (frameCount != _frameDasChaves) { _chavesDoFrame.Clear(); _frameDasChaves = frameCount; } if (_chavesDoFrame.TryGetValue(chave, out var value)) { return value; } try { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return false; } bool globalKey = instance.GetGlobalKey(chave); _chavesDoFrame[chave] = globalKey; return globalKey; } catch (Exception ex) { Log.LogWarning((object)("nao consegui ler a chave '" + chave + "' (" + ex.Message + "); segurando por precaucao.")); return false; } } internal static bool Ligado() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return Enabled.Value; } if (instance.IsServer()) { return Enabled.Value; } if (!Rede.Recebido) { return true; } return Rede.ServidorLigado; } internal static void MigrarEspera(Player player) { if ((Object)(object)player == (Object)null || player.m_customData == null || !player.m_customData.TryGetValue("recipegate_pending", out var value)) { return; } List<string> list = Nucleo.LerPendentes(value); player.m_customData.Remove("recipegate_pending"); ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || list.Count == 0) { return; } int num = 0; for (int i = 0; i < list.Count; i++) { try { GameObject itemPrefab = instance.GetItemPrefab(list[i]); ItemDrop val = (((Object)(object)itemPrefab == (Object)null) ? null : itemPrefab.GetComponent<ItemDrop>()); if (!((Object)(object)val == (Object)null)) { player.AddKnownItem(val.m_itemData); num++; } } catch { } } Log.LogWarning((object)("migracao da geracao 1: " + num + " material(is) da lista de espera voltaram a ser conhecidos. Quem tranca agora e a receita.")); } internal static void GuardarSpawnSystem(SpawnSystem s) { _spawnGuardado = s; _limiteDeEspera = Time.realtimeSinceStartup + 30f; } internal static bool EsperandoPacote() { return (Object)(object)_spawnGuardado != (Object)null; } internal static void EsquecerMundo() { Mapa.Esquecer(); Red