Decompiled source of JSONLoader v0.6.0
JSONLoader.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using ATS_API; using ATS_API.Ascension; using ATS_API.Difficulties; using ATS_API.Goods; using ATS_API.Helpers; using ATS_API.Localization; using ATS_API.MetaRewards; using ATS_API.Recipes; using ATS_JSONLoader; using ATS_JSONLoader.Sounds; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Eremite; using Eremite.Buildings; using Eremite.Characters.Villagers; using Eremite.Controller; using Eremite.Model; using Eremite.Model.Meta; using Eremite.Model.Sound; using Eremite.Model.Trade; using HarmonyLib; using JLPlugin; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Sirenix.Utilities; using TinyJson; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("JSONLoader")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Adds new content to Against the Storm using files instead of code")] [assembly: AssemblyFileVersion("0.6.0.0")] [assembly: AssemblyInformationalVersion("0.6.0+5f8caccc3f277ff692d934ffbf7e973e83aeab19")] [assembly: AssemblyProduct("JSONLoader")] [assembly: AssemblyTitle("JSONLoader")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.6.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public class DifficultyLoader { public const string fileExtension = "_difficulty.json"; public static void LoadAll(List<string> files) { //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown for (int i = 0; i < files.Count; i++) { string text = files[i]; if (!text.EndsWith("_difficulty.json")) { continue; } ImportExportUtils.SetDebugPath(text); files.RemoveAt(i--); try { Logging.VerboseLog("Loading JSON (difficulties) " + text); DifficultyData data = text.FromFilePath<DifficultyData>(); if (data == null) { Plugin.Log.LogError((object)("Failed to load JSON (difficulties) " + text)); continue; } Logging.VerboseLog("Loaded JSON (difficulties) " + text); DifficultyData difficultyData = data; if (difficultyData.guid == null) { difficultyData.guid = (MB.Settings.difficulties.Any((DifficultyModel a) => ((Object)a).name == data.name) ? "" : "JSONLoader"); } string text2 = ((!string.IsNullOrEmpty(data.guid)) ? (data.guid + "_") : ""); string fullName = text2 + data.name; bool isNewDifficulty = false; DifficultyModel val = null; if (MB.Settings.difficulties.Any((DifficultyModel a) => ((Object)a).name == fullName)) { Logging.VerboseLog("Found existing difficulty " + fullName); val = MB.Settings.difficulties.First((DifficultyModel a) => ((Object)a).name == fullName); } else { Logging.VerboseLog("Creating new difficulty " + fullName); DifficultyBuilder val2 = new DifficultyBuilder(data.guid, data.name); val = val2.Model; isNewDifficulty = true; } Logging.VerboseLog("Applying JSON (difficulties) " + text + " to difficulty " + fullName); Apply(val, data, toModel: true, fullName, isNewDifficulty); Logging.VerboseLog("Loaded JSON difficulty " + fullName); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error loading JSON (difficulties) {text}\n{arg}"); } } } public static void Apply(DifficultyModel model, DifficultyData data, bool toModel, string modelName, bool isNewDifficulty) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0427: Unknown result type (might be due to invalid IL or missing references) ImportExportUtils.SetID(modelName); DifficultyBuilder builder = new DifficultyBuilder(model); ImportExportUtils.ApplyLocaText(ref model.displayName, ref data.displayName, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetDisplayName(a, b); }, toModel, "displayName"); ImportExportUtils.ApplyLocaText(ref model.description, ref data.description, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetDescription(a, b); }, toModel, "description"); ImportExportUtils.ApplyValueNoNull(ref model.shortName, ref data.shortName, toModel, "difficulties", "shortName"); ImportExportUtils.ApplyValueNoNull(ref model.index, ref data.index, toModel, "difficulties", "index"); ImportExportUtils.ApplyValueNoNull(ref model.ascensionIndex, ref data.ascensionIndex, toModel, "difficulties", "ascensionIndex"); ImportExportUtils.ApplyValueNoNull(ref model.sealFramentsForWin, ref data.sealFragmentsForWin, toModel, "difficulties", "sealFragmentsForWin"); ImportExportUtils.ApplyValueNoNull(ref model.isAscension, ref data.isAscension, toModel, "difficulties", "eatable"); ImportExportUtils.ApplyValueNoNull(ref model.canBePicked, ref data.canBePicked, toModel, "difficulties", "canBePicked"); ImportExportUtils.ApplyValueNoNull(ref model.isInCustomGame, ref data.isInCustomGame, toModel, "difficulties", "isInCustomGame"); ImportExportUtils.ApplyValueNoNull(ref model.blightFootprintRate, ref data.blightFootprintRate, toModel, "difficulties", "blightFootprintRate"); ImportExportUtils.ApplyValueNoNull(ref model.blightCorruptionRate, ref data.blightCorruptionRate, toModel, "difficulties", "blightCorruptionRate"); ImportExportUtils.ApplyValueNoNull(ref model.rewardsMultiplier, ref data.rewardsMultiplier, toModel, "difficulties", "rewardsMultiplier"); ImportExportUtils.ApplyValueNoNull(ref model.expMultiplier, ref data.expMultiplier, toModel, "difficulties", "expMultiplier"); ImportExportUtils.ApplyValueNoNull(ref model.scoreMultiplier, ref data.scoreMultiplier, toModel, "difficulties", "scoreMultiplier"); ImportExportUtils.ApplyValueNoNull(ref model.difficultyBudget, ref data.difficultyBudget, toModel, "difficulties", "difficultyBudget"); ImportExportUtils.ApplyValueNoNull(ref model.positiveEffects, ref data.positiveEffects, toModel, "difficulties", "positiveEffects"); ImportExportUtils.ApplyValueNoNull(ref model.negativeEffects, ref data.negativeEffects, toModel, "difficulties", "negativeEffects"); ImportExportUtils.ApplyValueNoNull(ref model.minEffectCost, ref data.minEffectCost, toModel, "difficulties", "minEffectCost"); ImportExportUtils.ApplyValueNoNull(ref model.maxEffectCost, ref data.maxEffectCost, toModel, "difficulties", "maxEffectCost"); ImportExportUtils.ApplyValueNoNull(ref model.preparationPointsPenalty, ref data.preparationPointsPenalty, toModel, "difficulties", "preparationPointsPenalty"); ImportExportUtils.ApplyValueNoNull(ref model.portRequirementsRatio, ref data.portRequirementsRatio, toModel, "difficulties", "portRequirementsRatio"); ImportExportUtils.ApplyValueNoNull(ref model.maxWildcards, ref data.maxWildcards, toModel, "difficulties", "maxWildcards"); ImportExportUtils.ApplyValueNoNull(ref model.inGameSeal, ref data.inGameSeal, toModel, "difficulties", "inGameSeal"); ImportExportUtils.ApplyValueNoNull(ref model.modifiers, ref data.modifiers, toModel, "difficulties", "modifiers"); if (toModel) { if (data.prestigeLevel.HasValue) { builder.SetPrestigeLevel(data.prestigeLevel.Value, true); } if (data.copyModifiersFromPreviousDifficulties.HasValue) { builder.CopyModifiersFromPreviousDifficulties(data.copyModifiersFromPreviousDifficulties.Value); } if (data.newModifiers != null) { for (int i = 0; i < data.newModifiers.Length; i++) { DifficultyData.NewModifier newModifier = data.newModifiers[i]; bool valueOrDefault = newModifier.isShown.GetValueOrDefault(true); bool valueOrDefault2 = newModifier.isEarlyEffect.GetValueOrDefault(); bool valueOrDefault3 = newModifier.inCustomMode.GetValueOrDefault(true); NewAscensionModifierModel modifier = builder.AddModifier(EffectTypesExtensions.ToEffectTypes(newModifier.effect), valueOrDefault, valueOrDefault2, valueOrDefault3); ImportExportUtils.ApplyLocaText(ref modifier.ShortDescription, ref newModifier.shortDescription, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) modifier.SetShortDescription(a, b); }, toModel, $"newModifiers[{i}].shortDescription"); } } } else { data.prestigeLevel = model.ascensionIndex + 1; data.copyModifiersFromPreviousDifficulties = builder.NewDifficulty.copyModifiersFromPreviousDifficulty; } if (toModel) { if (!isNewDifficulty && !string.IsNullOrEmpty(data.icon)) { ImportExportUtils.ApplyProperty(() => model.icon, delegate(Sprite a) { builder.SetIcon(a); }, ref data.icon, toModel, "difficulties", "icon"); } } else { ImportExportUtils.ApplyProperty(() => model.icon, delegate(Sprite a) { builder.SetIcon(a); }, ref data.icon, toModel, "difficulties", "icon"); } } public static void ExportAll() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) DifficultyModel[] difficulties = MB.Settings.difficulties; foreach (DifficultyModel val in difficulties) { DifficultyTypes key = DifficultyTypesExtensions.ToDifficultyTypes(((Object)val).name); DifficultyData difficultyData = new DifficultyData(); difficultyData.Initialize(); NewDifficulty value; bool flag = DifficultyManager.NewDifficultiesLookup.TryGetValue(key, out value); if (flag) { difficultyData.guid = value.guid; difficultyData.name = value.rawName; } else { difficultyData.name = ((Object)val).name; } Apply(val, difficultyData, toModel: false, ((Object)val).name, flag); string path = Path.Combine(Plugin.ExportDirectory, "difficulties", ((Object)val).name + "_difficulty.json"); if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } string contents = JSONParser.ToJSON(difficultyData); File.WriteAllText(path, contents); } } } [GenerateSchema("Difficulty", "Difficulty when starting a settlement.", "_difficulty.json")] public class DifficultyData : IInitializable { public class NewModifier : IInitializable { [SchemaShortDescription] public LocalizableField shortDescription; [SchemaEffectType(/*Could not decode attribute arguments.*/)] public string effect; [SchemaField(true, false, "When set to true will apply the effect to the difficulty.")] public bool? isEarlyEffect; [SchemaField(true, false, "When set to false will hide the effect from the list of effects in custom games.")] public bool? isShown; [SchemaField(true, false, "When set to false will hide the effect from the list of effects in custom games.")] public bool? inCustomMode; public void Initialize() { shortDescription = new LocalizableField("shortDescription"); } } [SchemaGuid] public string guid; [SchemaName] public string name; [SchemaIcon(/*Could not decode attribute arguments.*/)] public string icon; [SchemaDisplayName] public LocalizableField displayName; [SchemaDescription] public LocalizableField description; [SchemaShortName] public string shortName; [SchemaField(0, false, "Position in the list of difficulties. Starts at 0 for the first difficulty.")] public int? index; [SchemaField(1, false, "Position in the list of ascension difficulties. 0 if not prestige difficulty or first prestige in the list.")] public int? ascensionIndex; [SchemaField(5, false, "Amount of seal fragments earned when winning the game with this difficulty selected.")] public int? sealFragmentsForWin; [SchemaField(false, false, "When set to true will set this difficulty to be a prestige difficulty.")] public bool? isAscension; [SchemaField(true, false, "When set to false will hide this difficulty from the list of difficulties.")] public bool? canBePicked; [SchemaField(true, false, "When set to false will hide this difficulty from the list of difficulties in custom games.")] public bool? isInCustomGame; [SchemaField(1f)] public float? blightFootprintRate; [SchemaField(1f)] public float? blightCorruptionRate; [SchemaField(5.1f)] public float? rewardsMultiplier; [SchemaField(5.1f)] public float? expMultiplier; [SchemaField(2.1f)] public float? scoreMultiplier; [SchemaField(6)] public int? difficultyBudget; [SchemaField(1)] public int? positiveEffects; [SchemaField(4)] public int? negativeEffects; [SchemaField(-1)] public int? minEffectCost; [SchemaField(3)] public int? maxEffectCost; [SchemaField(-4)] public int? preparationPointsPenalty; [SchemaField(1)] public float? portRequirementsRatio; [SchemaField(1)] public int? maxWildcards; [SchemaField("Seal")] public string inGameSeal; [SchemaAscensionModifierType("List of effects that are applied to this difficulty.")] public string[] modifiers; [SchemaField(1, false, "Prestige level of the difficulty. Overrides everything in the Difficulty to set the prestige level.")] public int? prestigeLevel; [SchemaField(true, false, "When set to true will copy the modifiers from the lower level difficulties.")] public bool? copyModifiersFromPreviousDifficulties; [SchemaField(null, false, "List of new modifiers that are created and applied to this difficulty.")] public NewModifier[] newModifiers; public void Initialize() { displayName = new LocalizableField("displayName"); description = new LocalizableField("description"); } } public class GoodsLoader { public const string fileExtension = "_good.json"; public static void LoadAll(List<string> files) { for (int i = 0; i < files.Count; i++) { string text = files[i]; if (!text.EndsWith("_good.json")) { continue; } ImportExportUtils.SetDebugPath(text); files.RemoveAt(i--); try { Logging.VerboseLog("Loading JSON (goods) " + text); GoodsData goodsData = text.FromFilePath<GoodsData>(); if (goodsData == null) { Plugin.Log.LogError((object)("Failed to load JSON (goods) " + text)); continue; } Logging.VerboseLog("Loaded JSON (goods) " + text); GoodsData goodsData2 = goodsData; if (goodsData2.guid == null) { goodsData2.guid = (MB.Settings.ContainsGood(goodsData.name) ? "" : "JSONLoader"); } string text2 = ((!string.IsNullOrEmpty(goodsData.guid)) ? (goodsData.guid + "_") : ""); string text3 = text2 + goodsData.name; bool isNewGood = false; GoodModel val = null; if (MB.Settings.ContainsGood(text3)) { Logging.VerboseLog("Found existing good " + text3); val = MB.Settings.GetGood(text3); } else { Logging.VerboseLog("Creating new good " + text3); val = GoodsManager.New(goodsData.guid, goodsData.name, goodsData.icon).goodModel; isNewGood = true; } Logging.VerboseLog("Applying JSON (goods) " + text + " to good " + text3); Apply(val, goodsData, toModel: true, text3, isNewGood); Logging.VerboseLog("Loaded JSON good " + text3); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error loading JSON (goods) {text}\n{arg}"); } } } public static void Apply(GoodModel model, GoodsData data, bool toModel, string modelName, bool isNewGood) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Expected O, but got Unknown //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Expected O, but got Unknown ImportExportUtils.SetID(modelName); GoodsBuilder builder = new GoodsBuilder(model); ImportExportUtils.ApplyLocaText(ref model.displayName, ref data.displayName, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetDisplayName(a, b); }, toModel, "displayName"); ImportExportUtils.ApplyLocaText(ref model.description, ref data.description, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetDescription(a, b); }, toModel, "description"); ImportExportUtils.ApplyLocaText(ref model.shortDescription, ref data.shortDescription, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetShortDescription(a, b); }, toModel, "shortDescription"); ImportExportUtils.ApplyProperty(() => ((Object)model.category).name, delegate(string a) { builder.SetCategory(a); }, ref data.category, toModel, "goods", "category"); ApplyTraderSellingFields(builder, data, toModel, modelName); ApplyTraderBuyingFields(builder, data, toModel, modelName); ImportExportUtils.ApplyValueNoNull(ref model.eatable, ref data.eatable, toModel, "goods", "eatable"); ImportExportUtils.ApplyValueNoNull(ref model.order, ref data.order, toModel, "goods", "order"); ImportExportUtils.ApplyValueNoNull(ref model.burningTime, ref data.burningTime, toModel, "goods", "burningTime"); ImportExportUtils.ApplyValueNoNull(ref model.eatingFullness, ref data.eatingFullness, toModel, "goods", "eatingFullness"); ImportExportUtils.ApplyValueNoNull(ref model.canBeBurned, ref data.canBeBurned, toModel, "goods", "canBeBurned"); ImportExportUtils.ApplyValueNoNull(ref model.showStorageAmount, ref data.showStorageAmount, toModel, "goods", "showStorageAmount"); ImportExportUtils.ApplyValueNoNull(ref model.tradingBuyValue, ref data.tradingBuyValue, toModel, "goods", "tradingBuyValue"); ImportExportUtils.ApplyValueNoNull(ref model.tradingSellValue, ref data.tradingSellValue, toModel, "goods", "tradingSellValue"); ImportExportUtils.ApplyValueNoNull(ref model.isOnHUD, ref data.isOnHUD, toModel, "goods", "isOnHUD"); ImportExportUtils.ApplyValueNoNull(ref model.consoleId, ref data.consoleId, toModel, "goods", "consoleId"); ImportExportUtils.ApplyValueNoNull(ref model.tags, ref data.tags, toModel, "goods", "tags"); if (toModel) { if (!isNewGood && !string.IsNullOrEmpty(data.icon)) { ImportExportUtils.ApplyProperty(() => model.icon, delegate(Sprite a) { builder.SetIcon(a); }, ref data.icon, toModel, "goods", "icon"); } if (data.embarkGoodMetaRewards == null) { return; } List<EmbarkGoodMetaRewardModel> list = (from a in SO.Settings.metaRewards.Where(delegate(MetaRewardModel a) { EmbarkGoodMetaRewardModel val4 = (EmbarkGoodMetaRewardModel)(object)((a is EmbarkGoodMetaRewardModel) ? a : null); return val4 != null && (Object)(object)val4.good.good == (Object)(object)model; }) select (EmbarkGoodMetaRewardModel)(object)((a is EmbarkGoodMetaRewardModel) ? a : null)).ToList(); GoodMetaRewardData[] embarkGoodMetaRewards = data.embarkGoodMetaRewards; foreach (GoodMetaRewardData goodMetaRewardData in embarkGoodMetaRewards) { string expectedName = ((!string.IsNullOrEmpty(goodMetaRewardData.guid)) ? (goodMetaRewardData.guid + "_" + goodMetaRewardData.name) : goodMetaRewardData.name); EmbarkGoodMetaRewardModel val = ((IEnumerable<EmbarkGoodMetaRewardModel>)list).FirstOrDefault((Func<EmbarkGoodMetaRewardModel, bool>)((EmbarkGoodMetaRewardModel a) => ((Object)a).name == expectedName)); if ((Object)(object)val == (Object)null) { MetaRewardModel model2 = MetaRewardManager.New<EmbarkGoodMetaRewardModel>(goodMetaRewardData.guid, goodMetaRewardData.name).Model; val = (EmbarkGoodMetaRewardModel)(object)((model2 is EmbarkGoodMetaRewardModel) ? model2 : null); val.good = new GoodRef(); val.good.good = model; } else { list.Remove(val); } EmbarkGoodMetaRewardBuilder goodBuilder = new EmbarkGoodMetaRewardBuilder((MetaRewardModel)(object)val); EmbarkGoodMetaRewardModel model3 = ((MetaRewardBuilder<EmbarkGoodMetaRewardModel>)(object)goodBuilder).Model; ImportExportUtils.ApplyValue(ref model3.good.amount, ref goodMetaRewardData.goodAmount, toModel, "metaReward", "goodAmount"); ImportExportUtils.ApplyLocaText(ref model3.displayName, ref goodMetaRewardData.displayName, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) goodBuilder.SetDisplayName(a, b); }, toModel, "displayName"); ImportExportUtils.ApplyLocaText(ref model3.description, ref goodMetaRewardData.description, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) goodBuilder.SetDescription(a, b); }, toModel, "description"); ImportExportUtils.ApplyVector2Int(ref model3.costRange, ref goodMetaRewardData.minCost, ref goodMetaRewardData.maxCost, toModel, "metaReward", "costRange"); } return; } ImportExportUtils.ApplyProperty(() => model.icon, delegate(Sprite a) { builder.SetIcon(a); }, ref data.icon, toModel, "goods", "icon"); EmbarkGoodMetaRewardModel[] array = (from a in SO.Settings.metaRewards.Where(delegate(MetaRewardModel a) { EmbarkGoodMetaRewardModel val3 = (EmbarkGoodMetaRewardModel)(object)((a is EmbarkGoodMetaRewardModel) ? a : null); return val3 != null && (Object)(object)val3.good.good == (Object)(object)model; }) select (EmbarkGoodMetaRewardModel)(object)((a is EmbarkGoodMetaRewardModel) ? a : null)).ToArray(); if (array.Length == 0) { return; } data.embarkGoodMetaRewards = new GoodMetaRewardData[array.Length]; for (int j = 0; j < array.Length; j++) { EmbarkGoodMetaRewardModel val2 = array[j]; GoodMetaRewardData goodMetaRewardData2 = new GoodMetaRewardData(); goodMetaRewardData2.Initialize(); string text = ""; string a2 = ""; if (MetaRewardManager.NewMetaRewardsLookup.TryGetValue(MetaRewardTypesExtensions.ToMetaRewardTypes(((Object)val2).name), out var value)) { text = value.rawName; a2 = value.guid; } else { text = ((Object)val2).name; } ImportExportUtils.ApplyValue(ref a2, ref goodMetaRewardData2.guid, toModel, "metaReward", "guid"); ImportExportUtils.ApplyValue(ref text, ref goodMetaRewardData2.name, toModel, "metaReward", "name"); ImportExportUtils.ApplyLocaText(ref val2.displayName, ref goodMetaRewardData2.displayName, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetDisplayName(a, b); }, toModel: false, "displayName"); ImportExportUtils.ApplyLocaText(ref val2.description, ref goodMetaRewardData2.description, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) builder.SetDescription(a, b); }, toModel: false, "description"); goodMetaRewardData2.goodAmount = val2.good.amount; goodMetaRewardData2.minCost = ((Vector2Int)(ref val2.costRange)).x; goodMetaRewardData2.maxCost = ((Vector2Int)(ref val2.costRange)).y; data.embarkGoodMetaRewards[j] = goodMetaRewardData2; } } private static void ApplyTraderBuyingFields(GoodsBuilder builder, GoodsData data, bool toModel, string modelName) { TraderModel[] allTraders = MB.Settings.traders; IEnumerable<string> tradersBuyingThisGood = from a in MB.Settings.traders where a.desiredGoods.Any((GoodModel b) => ((Object)b).name == modelName) select ((Object)a).name; ImportExportUtils.ApplyProperty(() => allTraders.Length == tradersBuyingThisGood.Count(), delegate(bool a) { if (a) { builder.CanBeSoldToAllTraders(); } }, ref data.allTradersBuyThisGood, !toModel, "goods", "allTradersBuyThisGood"); ImportExportUtils.ApplyProperty(() => tradersBuyingThisGood.ToArray(), delegate(string[] a) { if (a != null) { foreach (string canBeSoldToTrader in a) { builder.SetCanBeSoldToTrader(canBeSoldToTrader); } } }, ref data.tradersBuyingThisGood, toModel, "goods", "tradersBuyingThisGood"); } private static void ApplyTraderSellingFields(GoodsBuilder model, GoodsData data, bool toModel, string modelName) { TraderModel[] allTraders = MB.Settings.traders; IEnumerable<string> tradersSellingThisGood = from a in MB.Settings.traders where a.guaranteedOfferedGoods.Any((GoodRef b) => ((Object)b.good).name == modelName) || a.offeredGoods.Any((GoodRefWeight b) => b.Value.name == modelName) select ((Object)a).name; ImportExportUtils.ApplyProperty(() => allTraders.Length == tradersSellingThisGood.Count(), delegate(bool a) { if (a) { model.SetSoldByAllTraders(); } }, ref data.allTradersSellThisGood, toModel, "goods", "allTradersSellThisGood"); ImportExportUtils.ApplyProperty(() => tradersSellingThisGood.ToArray(), delegate(string[] a) { if (a != null) { foreach (string text in a) { model.AddTraderSellingGood(text); } } }, ref data.tradersSellingThisGood, toModel, "goods", "tradersSellingThisGood"); } public static void ExportAll() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) GoodModel[] goods = MB.Settings.Goods; foreach (GoodModel val in goods) { GoodsTypes key = GoodsTypesExtensions.ToGoodsTypes(((Object)val).name); GoodsData goodsData = new GoodsData(); goodsData.Initialize(); if (GoodsManager.NewGoodsLookup.TryGetValue(key, out var value)) { goodsData.guid = value.guid; goodsData.name = value.rawName; } else { goodsData.name = ((Object)val).name; } Apply(val, goodsData, toModel: false, ((Object)val).name, isNewGood: false); string path = Path.Combine(Plugin.ExportDirectory, "goods", ((Object)val).name + "_good.json"); if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } string contents = JSONParser.ToJSON(goodsData); File.WriteAllText(path, contents); } } } [GenerateSchema("Goods", "Fuel/Eatable/Tradeable items/Amber/etc.", "_good.json")] public class GoodsData : IInitializable { [SchemaGuid] public string guid; [SchemaName] public string name; [SchemaIcon(/*Could not decode attribute arguments.*/)] public string icon; [SchemaDisplayName] public LocalizableField displayName; [SchemaDescription] public LocalizableField description; [SchemaShortDescription] public LocalizableField shortDescription; [SchemaField(false, "If set to true will allow villagers to eat it. Use eatingFullness to set how full villagers get.")] public bool? eatable; [SchemaField(0, "The order of which this will be good will be sorted in some lists.")] public int? order; [SchemaField(40f, "How long this good will burn at the hearth if canBeBurned is set to true.")] public float? burningTime; [SchemaField(1f, "How full villagers get when they eat this good if eatable is set to true.")] public float? eatingFullness; [SchemaField(false, "If set to true then this good can be burnt at the hearth. Use burningTime to set how long it will burn.")] public bool? canBeBurned; [SchemaField(true)] public bool? showStorageAmount; [SchemaField(true)] public bool? isOnHUD; [SchemaEnum<GoodsCategoriesTypes>(/*Could not decode attribute arguments.*/)] public string category; [SchemaField(null)] public string[] tags; [SchemaField("", "Identifier to be used by the console??")] public string consoleId; [SchemaField(4.5f, "How much the player will receive for selling this.")] public float? tradingBuyValue; [SchemaField(true, "If set to true then this good will be sold by all traders.")] public bool? allTradersSellThisGood; [SchemaTraderType(/*Could not decode attribute arguments.*/)] public string[] tradersSellingThisGood; [SchemaField(2.25f, "How much traders will sell this good for.")] public float? tradingSellValue; [SchemaField(true, "If set to true then the player can sell this good to all traders.")] public bool? allTradersBuyThisGood; [SchemaTraderType(/*Could not decode attribute arguments.*/)] public string[] tradersBuyingThisGood; [SchemaField(null, "Rewards the player can choose when starting a new settlement. If not included then will not affect existing meta rewards.")] public GoodMetaRewardData[] embarkGoodMetaRewards; public void Initialize() { displayName = new LocalizableField("displayName"); description = new LocalizableField("description"); shortDescription = new LocalizableField("shortDescription"); } } public class GoodMetaRewardData : IInitializable { [SchemaGuid] public string guid; [SchemaGuid] public string name; [SchemaDisplayName] public LocalizableField displayName; [SchemaDescription] public LocalizableField description; [SchemaField("How much of this good you will get when selecting this reward.")] public int goodAmount; [SchemaField("Minimum cost required to get this meta reward.")] public int minCost; [SchemaField("Maximum cost required to get this meta reward.")] public int maxCost; public void Initialize() { displayName = new LocalizableField("displayName"); description = new LocalizableField("description"); } } public static class ImportExportUtils { private static string ID; private static string DebugPath; private static string LoggingSuffix; public static void SetID(string id) { ID = id; } public static void SetDebugPath(string path) { DebugPath = path.Substring(Plugin.BepInExDirectory.Length); LoggingSuffix = ""; } public static T ParseEnum<T>(string value) where T : unmanaged, Enum { if (Enum.TryParse<T>(value, out var result)) { return result; } int num = Math.Max(value.LastIndexOf('_'), value.LastIndexOf('.')); if (num < 0) { throw new InvalidCastException("Cannot parse " + value + " as " + typeof(T).FullName); } string text = value.Substring(0, num); string text2 = value.Substring(num + 1); return GUIDManager.Get<T>(text, text2); } public static void ApplyMethod<T, Y>(Func<T> getter, Action<T> setter, ref Y serializeInfoValue, bool toModel, string category, string suffix) { if (toModel) { T a = default(T); ApplyValue(ref a, ref serializeInfoValue, toA: true, category, suffix); setter(a); } else { T a2 = getter(); ApplyValue(ref a2, ref serializeInfoValue, toA: false, category, suffix); } } public static void ApplyProperty<T, Y>(Func<T> modelGetter, Action<T> modelSetter, ref Y serializeInfoValue, bool toModel, string category, string suffix) { if (toModel) { T a = default(T); ApplyValue(ref a, ref serializeInfoValue, toA: true, category, suffix); modelSetter(a); } else { T a2 = modelGetter(); ApplyValue(ref a2, ref serializeInfoValue, toA: false, category, suffix); } } public static void ApplyProperty<T, Y>(ref T aSerializeInfoValue, Func<Y> bGetter, Action<Y> bSetter, bool toModel, string category, string suffix) { if (toModel) { Y b = bGetter(); ApplyValue(ref aSerializeInfoValue, ref b, toA: true, category, suffix); } else { Y b2 = default(Y); ApplyValue(ref aSerializeInfoValue, ref b2, toA: false, category, suffix); bSetter(b2); } } public static void ApplyValue<T, Y>(ref T a, ref Y b, bool toA, string category, string suffix) { if (toA) { ConvertValue(ref b, ref a, category, suffix); } else { ConvertValue(ref a, ref b, category, suffix); } } public static void ApplyVector2<T>(ref Vector2 a, ref T bX, ref T bY, bool toA, string category, string suffix) { if (toA) { ConvertValue(ref bX, ref a.x, category, suffix); ConvertValue(ref bY, ref a.y, category, suffix); } else { ConvertValue(ref a.x, ref bX, category, suffix); ConvertValue(ref a.y, ref bY, category, suffix); } } public static void ApplyVector2Int(ref Vector2Int a, ref int bX, ref int bY, bool toA, string category, string suffix) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (toA) { int to = ((Vector2Int)(ref a)).x; int to2 = ((Vector2Int)(ref a)).y; ConvertValue(ref bX, ref to, category, suffix); ConvertValue(ref bY, ref to2, category, suffix); a = new Vector2Int(to, to2); } else { int from = ((Vector2Int)(ref a)).x; int from2 = ((Vector2Int)(ref a)).x; ConvertValue(ref from, ref bX, category, suffix); ConvertValue(ref from2, ref bY, category, suffix); bX = from; bY = from2; } } public static void ApplyValueNoNull<T, Y>(ref T a, ref Y b, bool toA, string category, string suffix) { if (toA) { if ((object)b != GetDefault(typeof(Y))) { ConvertValue(ref b, ref a, category, suffix); return; } VerboseLog("Skipping " + category + "." + suffix + " as it is null"); } else if ((object)a != GetDefault(typeof(T))) { ConvertValue(ref a, ref b, category, suffix); } else { VerboseLog("Skipping " + category + "." + suffix + " as it is null"); } } private static void ConvertValue<FromType, ToType>(ref FromType from, ref ToType to, string category, string suffix) { //IL_076f: Unknown result type (might be due to invalid IL or missing references) //IL_0776: Expected O, but got Unknown //IL_0887: Unknown result type (might be due to invalid IL or missing references) //IL_088e: Expected O, but got Unknown //IL_09aa: Unknown result type (might be due to invalid IL or missing references) //IL_09af: Unknown result type (might be due to invalid IL or missing references) //IL_0b08: Unknown result type (might be due to invalid IL or missing references) //IL_0b0d: Unknown result type (might be due to invalid IL or missing references) //IL_0b1d: Unknown result type (might be due to invalid IL or missing references) //IL_0b32: Unknown result type (might be due to invalid IL or missing references) //IL_0b47: Unknown result type (might be due to invalid IL or missing references) //IL_0b5c: Unknown result type (might be due to invalid IL or missing references) //IL_0ab8: Unknown result type (might be due to invalid IL or missing references) //IL_0bf6: Unknown result type (might be due to invalid IL or missing references) //IL_0c62: Unknown result type (might be due to invalid IL or missing references) //IL_0c67: Unknown result type (might be due to invalid IL or missing references) //IL_0c6f: Unknown result type (might be due to invalid IL or missing references) //IL_0c7b: Unknown result type (might be due to invalid IL or missing references) //IL_0cd2: Unknown result type (might be due to invalid IL or missing references) //IL_0cd9: Expected O, but got Unknown //IL_0d27: Unknown result type (might be due to invalid IL or missing references) //IL_0d2e: Expected O, but got Unknown //IL_0f4f: Unknown result type (might be due to invalid IL or missing references) //IL_0f56: Expected O, but got Unknown //IL_10c9: Unknown result type (might be due to invalid IL or missing references) //IL_10d0: Expected O, but got Unknown //IL_122c: Unknown result type (might be due to invalid IL or missing references) //IL_1233: Expected O, but got Unknown //IL_13a1: Unknown result type (might be due to invalid IL or missing references) //IL_13a8: Expected O, but got Unknown //IL_14c3: Unknown result type (might be due to invalid IL or missing references) //IL_14ca: Expected O, but got Unknown //IL_15be: Unknown result type (might be due to invalid IL or missing references) //IL_15c5: Expected O, but got Unknown LoggingSuffix = suffix; Type typeFromHandle = typeof(FromType); Type typeFromHandle2 = typeof(ToType); try { if (typeFromHandle == typeFromHandle2) { to = (ToType)(object)from; return; } if (AreNullableTypesEqual(from, to, out var a2, out var _, out var aHasValue, out var _)) { if (aHasValue) { to = (ToType)a2; } return; } if (typeFromHandle.IsGenericType && typeFromHandle.GetGenericTypeDefinition() == typeof(List<>) && typeFromHandle2.IsGenericType && typeFromHandle2.GetGenericTypeDefinition() == typeof(List<>)) { if (from != null) { IList list = (IList)Activator.CreateInstance(typeFromHandle2); to = (ToType)list; IList list2 = (IList)(object)from; for (int i = 0; i < list2.Count; i++) { object o = list2[i]; object @default = GetDefault(typeFromHandle2.GetGenericArguments().Single()); object value = ConvertType(typeFromHandle, typeFromHandle2, o, @default, category, $"{suffix}_{i + 1}"); list.Add(value); } } return; } if (typeFromHandle.IsGenericType && typeFromHandle.GetGenericTypeDefinition() == typeof(List<>) && typeFromHandle2.IsArray) { if (from != null) { IList list3 = (IList)(object)from; int length = ((from != null) ? list3.Count : 0); Array array = Array.CreateInstance(typeFromHandle2.GetElementType(), length); to = (ToType)(object)array; for (int j = 0; j < list3.Count; j++) { object obj = list3[j]; object default2 = GetDefault(typeFromHandle2.GetElementType()); object[] array2 = new object[4] { obj, default2, category, $"{suffix}_{j + 1}" }; MethodInfo methodInfo = typeof(ImportExportUtils).GetMethod("ConvertValue", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(typeFromHandle.GetGenericArguments().Single(), typeFromHandle2.GetElementType()); methodInfo.Invoke(null, array2); array.SetValue(array2[1], j); } } return; } if (typeFromHandle.IsArray && typeFromHandle2.IsGenericType && typeFromHandle2.GetGenericTypeDefinition() == typeof(List<>)) { if (from != null) { IList list4 = (IList)Activator.CreateInstance(typeFromHandle2); to = (ToType)list4; Array array3 = (Array)(object)from; for (int k = 0; k < array3.Length; k++) { object value2 = array3.GetValue(k); object default3 = GetDefault(typeFromHandle2.GetGenericArguments().Single()); object[] array4 = new object[4] { value2, default3, category, $"{suffix}_{k + 1}" }; MethodInfo methodInfo2 = typeof(ImportExportUtils).GetMethod("ConvertValue", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(typeFromHandle.GetElementType(), typeFromHandle2.GetGenericArguments().Single()); methodInfo2.Invoke(null, array4); list4.Add(array4[1]); } } return; } if (typeFromHandle.IsArray && typeFromHandle2.IsArray) { if (from != null) { Array array5 = (Array)(object)from; int length2 = ((from != null) ? array5.Length : 0); Array array6 = Array.CreateInstance(typeFromHandle2.GetElementType(), length2); to = (ToType)(object)array6; for (int l = 0; l < array5.Length; l++) { object value3 = array5.GetValue(l); object default4 = GetDefault(typeFromHandle2.GetElementType()); object[] array7 = new object[4] { value3, default4, category, $"{suffix}_{l + 1}" }; MethodInfo methodInfo3 = typeof(ImportExportUtils).GetMethod("ConvertValue", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(typeFromHandle.GetElementType(), typeFromHandle2.GetElementType()); methodInfo3.Invoke(null, array7); array6.SetValue(array7[1], l); } } return; } if (typeFromHandle.IsEnum && typeFromHandle2 == typeof(string)) { string text = from.ToString(); if (int.TryParse(text, out var result)) { if (Enum.GetValues(typeFromHandle).Cast<int>().Contains(result)) { to = (ToType)(object)text; return; } Error($"Failed to convert enum to string! '{from}' int '{result}'"); to = (ToType)(object)text; } else { to = (ToType)(object)text; } return; } if (typeFromHandle == typeof(string) && typeFromHandle2.IsEnum) { if (!string.IsNullOrEmpty((string)(object)from)) { object obj2 = typeof(ImportExportUtils).GetMethod("ParseEnum", BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(typeFromHandle2).Invoke(null, new object[1] { from }); to = (ToType)obj2; } return; } if (typeFromHandle == typeof(string) && (typeFromHandle2 == typeof(Texture) || typeFromHandle2.IsSubclassOf(typeof(Texture)))) { string text2 = (string)(object)from; if (!string.IsNullOrEmpty(text2)) { try { to = (ToType)(object)GetTextureFromString(text2); return; } catch (FileNotFoundException) { Error("Failed to find texture " + text2 + "!"); return; } } return; } if ((typeFromHandle == typeof(Texture) || typeFromHandle.IsSubclassOf(typeof(Texture))) && typeFromHandle2 == typeof(string)) { Texture val = (Texture)(object)from; if ((Object)(object)val != (Object)null) { string path4 = Path.Combine(Plugin.ExportDirectory, category, "Assets", ID + "_" + suffix + ".png"); to = (ToType)(object)ExportTexture(val, path4); } return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(Sprite)) { string text3 = (string)(object)from; if (!string.IsNullOrEmpty(text3)) { Texture2D textureFromString = GetTextureFromString(text3); if ((Object)(object)textureFromString != (Object)null) { to = (ToType)(object)TextureHelper.ConvertTexture(textureFromString, (Vector2?)null); } } return; } if (typeFromHandle == typeof(Sprite) && typeFromHandle2 == typeof(string)) { Sprite val2 = (Sprite)(object)from; if ((Object)(object)val2 != (Object)null) { string path5 = Path.Combine(Plugin.ExportDirectory, category, "Assets", ID + "_" + suffix + ".png"); to = (ToType)(object)ExportTexture(val2.texture, path5); } return; } if (ArrayExtension.Contains<Type>(typeFromHandle.GetInterfaces(), typeof(IConvertible)) && ArrayExtension.Contains<Type>(typeFromHandle2.GetInterfaces(), typeof(IConvertible))) { IConvertible convertible = from as IConvertible; IConvertible convertible2 = to as IConvertible; if (convertible != null && convertible2 != null) { to = (ToType)Convert.ChangeType(convertible, typeFromHandle2); } return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(Color)) { string text4 = (string)(object)from; Color white = Color.white; if (text4.StartsWith("#")) { if (!ColorUtility.TryParseHtmlString(text4, ref white)) { Error("Could not convert " + text4 + " to color!"); } } else { int[] array8 = (from a in text4.Split(new char[1] { ',' }) select int.Parse(a.Trim())).ToArray(); if (array8.Length != 0) { white.r = (float)array8[0] / 255f; } if (array8.Length > 1) { white.g = (float)array8[1] / 255f; } if (array8.Length > 2) { white.b = (float)array8[2] / 255f; } if (array8.Length > 3) { white.a = (float)array8[3] / 255f; } } to = (ToType)(object)white; return; } if (typeFromHandle == typeof(Color) && typeFromHandle2 == typeof(string)) { Color val3 = (Color)(object)from; to = (ToType)(object)$"{val3.r * 255f:F0},{val3.g * 255f:F0},{val3.b * 255f:F0},{val3.a * 255f:F0}"; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(Vector2)) { string text5 = (string)(object)from; string[] array9 = text5.Split(new char[1] { ',' }); if (array9.Length == 2) { to = (ToType)(object)new Vector2(float.Parse(array9[0]), float.Parse(array9[1])); } else { Error("Could not convert " + text5 + " to Vector2!"); } return; } if (typeFromHandle == typeof(Vector2) && typeFromHandle2 == typeof(string)) { Vector2 val4 = (Vector2)(object)from; to = (ToType)(object)$"{val4.x},{val4.y}"; return; } if (typeFromHandle.IsSubclassOf(typeof(ScriptableObject)) && typeFromHandle2 == typeof(string)) { ScriptableObject val5 = (ScriptableObject)(object)from; to = (ToType)(object)((Object)val5).name; return; } if (typeFromHandle == typeof(AudioClip) && typeFromHandle2 == typeof(string)) { AudioClip val6 = (AudioClip)(object)from; if ((Object)(object)val6 != (Object)null) { string text6 = Path.Combine(Plugin.ExportDirectory, category, "Audio", ID + "_" + suffix + ".wav"); to = (ToType)(object)AudioHelpers.ExportAudioClip(val6, text6); } to = (ToType)(object)((Object)val6).name; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(AudioClip)) { string text7 = (string)(object)from; AudioClip val7 = AudioHelpers.LoadAudioClip(text7); to = (ToType)(object)val7; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(NeedModel)) { string text8 = (string)(object)from; NeedModel val8 = NeedTypesExtensions.ToNeedModel(text8); to = (ToType)(object)val8; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(ModelTag)) { string text9 = (string)(object)from; ModelTag val9 = TagTypesExtensions.ToModelTag(text9); to = (ToType)(object)val9; return; } if (typeFromHandle == typeof(LocalizableField) && typeFromHandle2 == typeof(string)) { Error("Use ApplyLocaleField when converted from LocalizableField to string!"); } else if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(LocalizableField)) { Error("Use ApplyLocaleField when converted from string to LocalizableField!"); } else { if (typeFromHandle == typeof(RacialSound) && typeFromHandle2 == typeof(RacialSounds)) { RacialSound val10 = (RacialSound)(object)from; RacialSounds racialSounds = new RacialSounds(); ApplyValue(ref val10.positiveSound, ref racialSounds.PositiveSounds, toA: false, category, suffix + "_PositiveSounds"); ApplyValue(ref val10.neutralSound, ref racialSounds.NeutralSounds, toA: false, category, suffix + "_NeutralSounds"); ApplyValue(ref val10.negativeSound, ref racialSounds.NegativeSounds, toA: false, category, suffix + "_NegativeSounds"); to = (ToType)(object)racialSounds; return; } if (typeFromHandle == typeof(RacialSounds) && typeFromHandle2 == typeof(RacialSound)) { RacialSounds racialSounds2 = (RacialSounds)(object)from; RacialSound val11 = ScriptableObject.CreateInstance<RacialSound>(); ApplyValue(ref racialSounds2.PositiveSounds, ref val11.positiveSound, toA: false, category, suffix + "_PositiveSounds"); ApplyValue(ref racialSounds2.NeutralSounds, ref val11.neutralSound, toA: false, category, suffix + "_NeutralSounds"); ApplyValue(ref racialSounds2.NegativeSounds, ref val11.negativeSound, toA: false, category, suffix + "_NegativeSounds"); to = (ToType)(object)val11; return; } if (typeFromHandle == typeof(SoundRef) && typeFromHandle2 == typeof(SoundCollection)) { SoundRef val12 = (SoundRef)(object)from; SoundCollection soundCollection = new SoundCollection(); soundCollection.Initialize(); if ((Object)(object)val12 != (Object)null && val12.sounds != null) { SoundModel[] sounds = val12.sounds; foreach (SoundModel val13 in sounds) { if (val13 != null && !((Object)(object)val13.audioClip == (Object)null)) { Sound sound = new Sound(); ApplyValue(ref sound.soundPath, ref val13.audioClip, toA: true, category, suffix + "_audioClip"); ApplyValue(ref sound.volume, ref val13.volume, toA: true, category, suffix + "_volume"); soundCollection.sounds.Add(sound); } } } to = (ToType)(object)soundCollection; return; } if (typeFromHandle == typeof(SoundCollection) && typeFromHandle2 == typeof(SoundRef)) { SoundCollection soundCollection2 = (SoundCollection)(object)from; SoundRef val14 = ScriptableObject.CreateInstance<SoundRef>(); if ((Object)(object)val14 != (Object)null) { val14.sounds = (SoundModel[])(object)new SoundModel[soundCollection2.sounds.Count]; for (int n = 0; n < soundCollection2.sounds.Count; n++) { SoundModel val15 = new SoundModel(); Sound sound2 = soundCollection2.sounds[n]; ApplyValue(ref sound2.soundPath, ref val15.audioClip, toA: false, suffix, suffix + "_audioClip"); ApplyValue(ref sound2.volume, ref val15.volume, toA: false, suffix, suffix + "_volume"); val14.sounds[n] = val15; } } to = (ToType)(object)val14; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(AscensionModifierModel)) { string path3 = (string)(object)from; AscensionModifierModel val16 = ((IEnumerable<AscensionModifierModel>)SO.Settings.ascensionModifiers).FirstOrDefault((Func<AscensionModifierModel, bool>)((AscensionModifierModel a) => ((Object)a).name == path3)); if ((Object)(object)val16 == (Object)null) { Error("Could not find AscensionModifierModel with name '" + path3 + "'!"); } to = (ToType)(object)val16; return; } if (typeFromHandle == typeof(AscensionModifierModel) && typeFromHandle2 == typeof(string)) { AscensionModifierModel val17 = (AscensionModifierModel)(object)from; to = (ToType)(object)((Object)val17).name; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(RecipeGradeModel)) { string path2 = (string)(object)from; RecipeGradeModel val18 = SO.Settings.recipes.Select((RecipeModel a) => a.grade).FirstOrDefault((Func<RecipeGradeModel, bool>)((RecipeGradeModel a) => ((Object)a).name == path2)); if ((Object)(object)val18 == (Object)null) { Error("Could not find RecipeGradeModel with name '" + path2 + "'!"); } to = (ToType)(object)val18; return; } if (typeFromHandle == typeof(RecipeGradeModel) && typeFromHandle2 == typeof(string)) { RecipeGradeModel val19 = (RecipeGradeModel)(object)from; to = (ToType)(object)((Object)val19).name; return; } if (typeFromHandle == typeof(string) && typeFromHandle2 == typeof(GoodModel)) { string path = (string)(object)from; GoodModel val20 = ((IEnumerable<GoodModel>)SO.Settings.Goods).FirstOrDefault((Func<GoodModel, bool>)((GoodModel a) => ((Object)a).name == path)); if ((Object)(object)val20 == (Object)null) { Error("Could not find GoodModel with name '" + path + "'!"); } to = (ToType)(object)val20; return; } if (typeFromHandle == typeof(GoodModel) && typeFromHandle2 == typeof(string)) { GoodModel val21 = (GoodModel)(object)from; to = (ToType)(object)((Object)val21).name; return; } } } catch (Exception e) { Error($"Failed to convert: {typeFromHandle} to {typeFromHandle2}"); Exception(e); return; } Error($"Unsupported conversion type: {typeFromHandle} to {typeFromHandle2}\n{Environment.StackTrace}"); } private static Texture2D GetTextureFromString(string path) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (path.StartsWith("base64:")) { try { string s = path.Substring("base64:".Length); byte[] array = Convert.FromBase64String(s); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)0; ImageConversion.LoadImage(val, array); return val; } catch (Exception ex) { Error("Failed to convert base64 to texture: " + path); throw ex; } } return TextureHelper.GetImageAsTexture(path, (FilterMode)0); } public static string[] FindSimilarStrings(string misspelledCardName, IEnumerable<string> collection) { return FindSimilar(misspelledCardName, collection, (string a) => a); } public static T[] FindSimilar<T>(string misspelledCardName, IEnumerable<T> allElements, Func<T, string> getter) { List<Tuple<int, T>> list = new List<Tuple<int, T>>(); string text = misspelledCardName.ToLower().Replace("-", "").Replace("_", ""); int num = Mathf.Clamp(text.Length - 1, 1, 4); foreach (T allElement in allElements) { string text2 = getter(allElement).ToLower().Replace("-", "").Replace("_", ""); if (Mathf.Abs(text.Length - text2.Length) > num) { continue; } int num2 = 0; int num3 = Mathf.Max(0, text.Length - text2.Length); int num4 = text2.Length - 1; int num5 = text.Length - 1; while (num5 >= 0 && num4 >= 0) { if (text2[num4] == text[num5]) { num2++; } else { num3++; if (num3 > num) { break; } if (num4 > 0 && text2[num4 - 1] == text[num5]) { num4--; num2++; } else if (num5 > 0 && text2[num4] == text[num5 - 1]) { num5--; num2++; } } num5--; num4--; } if (num2 > 0 && num3 < num) { list.Add(new Tuple<int, T>(num2, allElement)); } } list.Sort((Tuple<int, T> a, Tuple<int, T> b) => b.Item1 - a.Item1); return list.Select((Tuple<int, T> a) => a.Item2).ToArray(); } private static object ConvertType(Type fromType, Type toType, object o1, object o2, string category, string suffix) { object[] array = new object[4] { o1, o2, category, suffix }; MethodInfo methodInfo = typeof(ImportExportUtils).GetMethod("ConvertValue", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(fromType.GetGenericArguments().Single(), toType.GetGenericArguments().Single()); methodInfo.Invoke(null, array); return array[1]; } private static bool AreNullableTypesEqual<T, Y>(T t, Y y, out object a, out object b, out bool aHasValue, out bool bHasValue) { aHasValue = false; bHasValue = false; a = null; b = null; bool flag = typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>); bool flag2 = typeof(Y).IsGenericType && typeof(Y).GetGenericTypeDefinition() == typeof(Nullable<>); if (!flag && !flag2) { return false; } Type type = (flag ? Nullable.GetUnderlyingType(typeof(T)) : typeof(T)); Type type2 = (flag2 ? Nullable.GetUnderlyingType(typeof(Y)) : typeof(Y)); if (type == type2) { if (flag) { a = GetValueFromNullable(t, out aHasValue); } else { a = t; aHasValue = true; } if (flag2) { b = GetValueFromNullable(y, out bHasValue); } else { b = y; bHasValue = true; } return true; } Error($"Not same types {typeof(T)} {typeof(Y)}"); return false; } private static string ExportTexture(Texture texture, string path) { Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (val != null) { return ExportTexture(val, path); } Texture2D texture2 = Texture2D.CreateExternalTexture(texture.width, texture.height, (TextureFormat)4, false, false, texture.GetNativeTexturePtr()); return ExportTexture(texture2, path); } private static string ExportTexture(Texture2D texture, string path) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!((Texture)texture).isReadable) { RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)1); Graphics.Blit((Texture)(object)texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)texture).width, ((Texture)texture).height); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); texture = val; } byte[] array = ImageConversion.EncodeToPNG(texture); if (array == null) { Error("Failed to turn into bytes??"); } if (string.IsNullOrEmpty(path)) { Error("path is empty????"); } string directoryName = Path.GetDirectoryName(path); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllBytes(path, array); return Path.GetFileName(path); } public static string[] ExportTextures(IEnumerable<Texture2D> texture, string type, string fileName) { int num = 0; List<string> list = new List<string>(); foreach (Texture2D item in texture) { num++; string path = Path.Combine(Plugin.ExportDirectory, type, "Assets", $"{fileName}_{num}.png"); list.Add(ExportTexture(item, path)); } return list.ToArray(); } public static void ApplyLocaleField(string field, ref LocaText model, ref LocalizableField data, bool toModel) { if (toModel) { string modelKey = ""; ApplyLocaleField(field, data, ref modelKey); model = LocalizationManager.ToLocaText(modelKey); } } public static void ApplyLocaText(ref LocaText model, ref LocalizableField data, Action<string, SystemLanguage> setModel, bool toModel, string fieldName) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (toModel) { foreach (KeyValuePair<SystemLanguage, string> translation in data.GetTranslations()) { setModel(translation.Value, translation.Key); } return; } data = new LocalizableField(fieldName); string currentLocaCode = MB.TextsService.CurrentLocaCode; string text = model.GetText(); string value = text.Replace("\n", "\\n"); data.SetValueWithLanguageCode(currentLocaCode, value); } private static void ApplyLocaleField(string field, LocalizableField rows, ref string modelKey) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) modelKey = ID + "_" + field; VerboseLog("ApplyLocaleField " + field + " english " + modelKey); foreach (KeyValuePair<SystemLanguage, string> row in rows.rows) { SystemLanguage key = row.Key; LocalizationManager.AddString(modelKey, row.Value, key); VerboseLog($"Translation {modelKey} to {key} = {row.Value}"); } } private static object GetValueFromNullable<U>(U u, out bool hasValue) { Type typeFromHandle = typeof(U); if (u != null && (bool)typeFromHandle.GetProperty("HasValue", BindingFlags.Instance | BindingFlags.Public).GetValue(u)) { hasValue = true; return typeFromHandle.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public).GetValue(u); } hasValue = false; Type underlyingType = Nullable.GetUnderlyingType(typeFromHandle); if (underlyingType.IsValueType) { return Activator.CreateInstance(underlyingType); } return null; } private static object GetDefault(Type type) { if (type.IsValueType) { return Activator.CreateInstance(type); } return null; } private static void VerboseLog(string message) { Logging.VerboseLog("[" + DebugPath + "][" + ID + "][" + LoggingSuffix + "] " + message); } private static void VerboseWarning(string message) { if (Configs.VerboseLogging) { Logging.VerboseWarning("[" + DebugPath + "][" + ID + "][" + LoggingSuffix + "] " + message); } } private static void VerboseError(string message) { if (Configs.VerboseLogging) { Logging.VerboseError("[" + DebugPath + "][" + ID + "][" + LoggingSuffix + "] " + message); } } private static void Log(string message) { Plugin.Log.LogInfo((object)("[" + ID + "][" + LoggingSuffix + "] " + message)); } private static void Warning(string message) { if (Configs.VerboseLogging) { VerboseWarning(message); return; } Plugin.Log.LogWarning((object)("[" + ID + "][" + LoggingSuffix + "] " + message)); } private static void Error(string message) { if (Configs.VerboseLogging) { VerboseError(message); return; } Plugin.Log.LogError((object)("[" + ID + "][" + LoggingSuffix + "] " + message)); } private static void Exception(Exception e) { Plugin.Log.LogError((object)("[" + DebugPath + "][" + ID + "][" + LoggingSuffix + "] " + e.Message + "\n" + e.StackTrace)); } } public class GenerateSchemaAttribute : Attribute { private readonly string Title; private readonly string Description; private readonly string FileExtension; public GenerateSchemaAttribute(string title, string description, string fileExtension) { Title = title; Description = description; FileExtension = fileExtension; } public string GetTitle() { return Title; } public string GetDescription() { string text = Description; if (!string.IsNullOrEmpty(FileExtension)) { text = text + "\n\nFor JSONLoader to load this file into Against the Storm create a file on your computer ending with " + FileExtension + " and paste the contents of the JSON inside. Example: \"MyFile" + FileExtension + "\""; } return text; } public string GetFileExtension() { return FileExtension; } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/AscensionModifierTypes.cs", "https://hoodedhorse.com/wiki/Against_the_Storm/Difficulty")] public class SchemaAscensionModifierTypeAttribute : SchemaEnumAttribute<AscensionModifierTypes> { public SchemaAscensionModifierTypeAttribute(string description) : base((AscensionModifierTypes)21, description) { } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/BuildingPerkTypes.cs")] public class SchemaBuildingPerkTypeAttribute : SchemaEnumAttribute<BuildingPerkTypes> { public SchemaBuildingPerkTypeAttribute(string description) : base((BuildingPerkTypes)7, description) { } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/BuildingTagTypes.cs")] public class SchemaBuildingTagTypeAttribute : SchemaEnumAttribute<BuildingTagTypes> { public SchemaBuildingTagTypeAttribute(string description) : base((BuildingTagTypes)1, description) { } } public class SchemaDescriptionAttribute : SchemaLocalizedAttribute { public SchemaDescriptionAttribute() : base("Long Description describing what it does.") { } } public class SchemaDisplayNameAttribute : SchemaLocalizedAttribute { public SchemaDisplayNameAttribute() : base("Name that will appear in the game.") { } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/EffectTypes.cs", "https://hoodedhorse.com/wiki/Against_the_Storm/Perks")] public class SchemaEffectTypeAttribute : SchemaEnumAttribute<EffectTypes> { public SchemaEffectTypeAttribute(EffectTypes defaultValue, string description) : base(defaultValue, description) { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) } public class SchemaEnumAttribute<T> : SchemaFieldAttribute where T : Enum { private static readonly string[] IgnoreEnumNames = new string[3] { "None", "Unknown", "MAX" }; public SchemaEnumAttribute(T defaultValue, string description) : base(defaultValue, required: false, description) { Enum = (from a in System.Enum.GetNames(typeof(T)) where !ArrayExtension.Contains<string>(IgnoreEnumNames, a) select a).ToArray(); } public SchemaEnumAttribute(T defaultValue, bool required, string description) : base(defaultValue, required, description) { Enum = (from a in System.Enum.GetNames(typeof(T)) where !ArrayExtension.Contains<string>(IgnoreEnumNames, a) select a).ToArray(); } } public class SchemaFieldAttribute : Attribute { protected object DefaultValue; protected bool Required; protected string Description; protected string Pattern; protected int MinLength; protected string[] Enum = Array.Empty<string>(); public SchemaFieldAttribute(object defaultValue, bool required, string description) { DefaultValue = defaultValue; Required = required; Description = description; } public SchemaFieldAttribute(object defaultValue, string description) { DefaultValue = defaultValue; Required = false; Description = description; } public SchemaFieldAttribute(object defaultValue) { DefaultValue = defaultValue; Required = false; Description = ""; } public virtual object GetDefaultValue() { return DefaultValue; } public virtual bool IsRequired() { return Required; } public virtual string GetDescription() { return Description; } public virtual string GetPattern() { return Pattern; } public virtual int GetMinLength() { return MinLength; } public virtual string[] GetEnum() { return Enum; } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/GoodsTypes.cs", "https://hoodedhorse.com/wiki/Against_the_Storm/Resources")] public class SchemaGoodTypeAttribute : SchemaEnumAttribute<GoodsTypes> { public SchemaGoodTypeAttribute(string description) : base((GoodsTypes)64, description) { } } public class SchemaGuidAttribute : SchemaFieldAttribute { public SchemaGuidAttribute() : base(null, required: true, "Unique identifier for the mod that added this. Blank if it's added as part of the base game.") { Pattern = "^[a-zA-Z\\d]+$"; } } public class SchemaHelpURLAttribute : Attribute { public string URL; public SchemaHelpURLAttribute(string url) { URL = url; } public SchemaHelpURLAttribute(string urlA, string urlB) { URL = urlA + "\n" + urlB; } } public class SchemaIconAttribute : SchemaFieldAttribute { private SpriteType spriteType; public SchemaIconAttribute(SpriteType spriteType) : base("", required: false, "Name of the file containing the icon for this object. Example: MyCustomGood.png") { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) this.spriteType = spriteType; } public SchemaIconAttribute(SpriteType spriteType, string description) : base("", required: false, "Name of the file containing the icon for this object. Example: MyCustomGood.png\n" + description) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) this.spriteType = spriteType; } public override string GetDescription() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Vector2 spriteSize = TextureHelper.GetSpriteSize(spriteType); return base.GetDescription() + "\n" + $"Icon size: {(int)spriteSize.x}x{(int)spriteSize.y} pixels"; } } public class SchemaLocalizedAttribute : SchemaFieldAttribute { private const string LocalizedSubtext = "Defaults to english. To include more languages, add a new field with the language code to the end of the key. For example, 'displayName' => 'displayName_pl' for polish."; public SchemaLocalizedAttribute(string description) : base(null, description + "\nDefaults to english. To include more languages, add a new field with the language code to the end of the key. For example, 'displayName' => 'displayName_pl' for polish.") { } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/MetaRewardTypes.cs")] public class SchemaMetaRewardTypeAttribute : SchemaEnumAttribute<MetaRewardTypes> { public SchemaMetaRewardTypeAttribute(MetaRewardTypes defaultValue, string description) : base(defaultValue, description) { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) } public class SchemaNameAttribute : SchemaFieldAttribute { public SchemaNameAttribute() : base(null, required: true, "Unique identifier") { Pattern = "^[a-zA-Z\\d_]+$"; MinLength = 1; } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/NeedTypes.cs", "https://hoodedhorse.com/wiki/Against_the_Storm/Complex_Needs")] public class SchemaNeedAttribute : SchemaEnumAttribute<NeedTypes> { public SchemaNeedAttribute() : base((NeedTypes)3, "Names of each Need the villager requires. Example: Housing, Food... etc") { } } public class SchemaShortDescriptionAttribute : SchemaLocalizedAttribute { public SchemaShortDescriptionAttribute() : base("Short Description describing what it does. Typically max 1 line.") { } } public class SchemaShortNameAttribute : SchemaLocalizedAttribute { public SchemaShortNameAttribute() : base("Shorter version of the Name.") { } } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/TraderTypes.cs", "https://hoodedhorse.com/wiki/Against_the_Storm/Trading")] public class SchemaTraderTypeAttribute : SchemaEnumAttribute<TraderTypes> { public SchemaTraderTypeAttribute(TraderTypes defaultValue, string description) : base(defaultValue, description) { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) } [SchemaHelpURL("https://github.com/JamesVeug/AgainstTheStormAPI/blob/master/ATS_API/Scripts/Helpers/Enums/VillagerPerkTypes.cs")] public class SchemaVillagerPerkTypeTypeAttribute : SchemaEnumAttribute<VillagerPerkTypes> { public SchemaVillagerPerkTypeTypeAttribute(string description) : base((VillagerPerkTypes)61, description) { } } public static class JSONSchemaGenerator { public static void GenerateAndExport() { IEnumerable<Type> enumerable = from t in Assembly.GetExecutingAssembly().GetTypes() where t.GetCustomAttributes(typeof(GenerateSchemaAttribute), inherit: false).Any() select t; Plugin.Log.LogInfo((object)$"Found {enumerable.Count()} classes with the GenerateSchema attribute"); foreach (Type item in enumerable) { Plugin.Log.LogInfo((object)("Exporting schema for " + item.Name)); Dictionary<string, object> dictionary = GenerateSchemaHighLevelType(item); string contents = JsonConvert.SerializeObject((object)dictionary, (Formatting)1); string path = Path.Combine(Plugin.ExportDirectory, "Schemas", item.Name + ".json"); if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } File.WriteAllText(path, contents); } Plugin.Log.LogInfo((object)"Exported all schemas"); } private static Dictionary<string, object> GenerateSchemaHighLevelType(Type type) { Dictionary<string, object> dictionary = GenerateSchemaForType(type); Dictionary<string, object> dictionary2 = new Dictionary<string, object>(); dictionary2["$schema"] = "http://json-schema.org/draft-04/schema#"; dictionary2["id"] = "https://github.com/JamesVeug/ATS_JSONLoader"; foreach (KeyValuePair<string, object> item in dictionary) { dictionary2[item.Key] = item.Value; } return dictionary2; } private static Dictionary<string, object> GenerateSchemaForType(Type type) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); dictionary["type"] = GetFieldType(type); GenerateSchemaAttribute customAttribute = type.GetCustomAttribute<GenerateSchemaAttribute>(); if (customAttribute != null) { dictionary["title"] = customAttribute.GetTitle(); dictionary["description"] = customAttribute.GetDescription(); } FieldInfo[] array = (from a in type.GetFields() where a.GetCustomAttribute<SchemaFieldAttribute>() != null select a).ToArray(); string[] array2 = (from a in array where a.GetCustomAttribute<SchemaFieldAttribute>().IsRequired() select a.Name).ToArray(); if (array2.Length != 0) { dictionary["required"] = array2; } if (array.Length != 0) { Dictionary<string, object> dictionary3 = (Dictionary<string, object>)(dictionary["properties"] = new Dictionary<string, object>()); FieldInfo[] array3 = array; foreach (FieldInfo fieldInfo in array3) { Plugin.Log.LogInfo((object)("Generating schema for " + fieldInfo.Name)); dictionary3[fieldInfo.Name] = GenerateSchemaForField(fieldInfo); } } return dictionary; } private static Dictionary<string, object> GenerateSchemaForField(FieldInfo fieldInfo) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); Type type = fieldInfo.FieldType; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { type = Nullable.GetUnderlyingType(type); } SchemaFieldAttribute customAttribute = fieldInfo.GetCustomAttribute<SchemaFieldAttribute>(); object defaultValue = customAttribute.GetDefaultValue(); bool flag = customAttribute.GetEnum().Length != 0; if (flag || defaultValue != null) { dictionary["default"] = (flag ? defaultValue.ToString() : defaultValue); } string text = customAttribute.GetDescription(); if (TryGetAttributes<SchemaHelpURLAttribute>(customAttribute, out var t)) { text += "\n\nFor more information, see:"; SchemaHelpURLAttribute[] array = t; foreach (SchemaHelpURLAttribute schemaHelpURLAttribute in array) { text = text + "\n" + schemaHelpURLAttribute.URL; } } if (!string.IsNullOrEmpty(text)) { dictionary["description"] = text; } if (!string.IsNullOrEmpty(customAttribute.GetPattern())) { dictionary["pattern"] = customAttribute.GetPattern(); } if (customAttribute.GetMinLength() != 0) { dictionary["minLength"] = customAttribute.GetMinLength(); } AddFieldType(type, customAttribute, dictionary); return dictionary; } private static bool TryGetAttribute<T>(SchemaFieldAttribute baseAttribute, out T foundAttribute) where T : Attribute { foundAttribute = baseAttribute.GetType().GetCustomAttribute<T>(); return foundAttribute != null; } private static bool TryGetAttributes<T>(SchemaFieldAttribute baseAttribute, out T[] t) where T : Attribute { t = baseAttribute.GetType().GetCustomAttributes<T>().ToArray(); return t.Length != 0; } private static void AddFieldType(Type type, SchemaFieldAttribute fieldAttribute, Dictionary<string, object> schema) { if (type.IsArray) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); AddFieldType(type.GetElementType(), fieldAttribute, dictionary); schema["type"] = "array"; schema["items"] = dictionary; return; } if (fieldAttribute.GetEnum().Length != 0) { Type type2 = fieldAttribute.GetDefaultValue().GetType(); Dictionary<string, object> dictionary2 = new Dictionary<string, object>(); dictionary2["type"] = "string"; dictionary2["title"] = "Predefined " + type2.Name; dictionary2["enum"] = fieldAttribute.GetEnum(); Dictionary<string, object> item = CustomEnumString(type2); List<Dictionary<string, object>> list = new List<Dictionary<string, object>>(); if (fieldAttribute.GetEnum().Length <= 100) { list.Add(dictionary2); } else { Plugin.Log.LogWarning((object)("Enum for " + type.Name + " has more than 100 options, skipping predefined enum!")); } list.Add(item); schema["anyOf"] = list; return; } Dictionary<string, object> dictionary3 = GenerateSchemaForType(type); foreach (KeyValuePair<string, object> item2 in dictionary3) { schema[item2.Key] = item2.Value; } } private static Dictionary<string, object> CustomEnumString(Type type) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); dictionary["type"] = "string"; dictionary["title"] = "Mod-Added " + type.Name; return dictionary; } private static string GetFieldType(Type type) { if (type == typeof(string)) { return "string"; } if (type == typeof(int)) { return "integer"; } if (type == typeof(float)) { return "number"; } if (type == typeof(bool)) { return "boolean"; } if (type == typeof(DateTime)) { return "string"; } if (type.IsEnum) { return "string"; } if (type.IsArray) { return "array"; } if (ArrayExtension.Contains<Type>(type.GetInterfaces(), typeof(IFlexibleField))) { return "string"; } return "object"; } } public class MetaRewardLoader { public const string fileExtension = "_metaReward.json"; public static void LoadAll(List<string> files) { for (int i = 0; i < files.Count; i++) { string text = files[i]; if (!text.EndsWith("_metaReward.json")) { continue; } ImportExportUtils.SetDebugPath(text); files.RemoveAt(i--); try { Logging.VerboseLog("Loading JSON (MetaReward) " + text); MetaRewardData data = text.FromFilePath<MetaRewardData>(); if (data == null) { Plugin.Log.LogError((object)("Failed to load JSON (MetaReward) " + text)); continue; } Logging.VerboseLog("Loaded JSON (MetaReward) " + text); MetaRewardData metaRewardData = data; if (metaRewardData.guid == null) { metaRewardData.guid = (MB.Settings.metaRewards.Any((MetaRewardModel a) => ((Object)a).name == data.name) ? "" : "JSONLoader"); } string text2 = ((!string.IsNullOrEmpty(data.guid)) ? (data.guid + "_") : ""); string fullName = text2 + data.name; bool isNewMetaReward = false; object obj = null; if (MB.Settings.metaRewards.Any((MetaRewardModel a) => ((Object)a).name == fullName)) { Logging.VerboseLog("Found existing MetaReward " + fullName); MetaRewardModel val = MB.Settings.metaRewards.First((MetaRewardModel a) => ((Object)a).name == fullName); obj = CreateBuilder(data.type, val); } else { Logging.VerboseLog("Creating new MetaReward " + fullName); obj = CreateBuilder(data.type, data.guid, data.name); isNewMetaReward = true; } Logging.VerboseLog("Applying JSON (MetaReward) " + text + " to MetaReward " + fullName); Apply(data, toModel: true, fullName, isNewMetaReward, obj); Logging.VerboseLog("Loaded JSON MetaReward " + fullName); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error loading JSON (MetaReward) {text}\n{arg}"); } } } private static object CreateBuilder(string typeString, params object[] args) { if (!Enum.TryParse<MetaRewardData.MetaRewardTypes>(typeString, out var result)) { result = MetaRewardData.MetaRewardTypes.Unknown; } Type type = null; return Activator.CreateInstance(result switch { MetaRewardData.MetaRewardTypes.EmbarkGoodMetaReward => typeof(EmbarkGoodMetaRewardBuilder), MetaRewardData.MetaRewardTypes.EmbarkEffectMetaReward => typeof(EmbarkEffectMetaRewardBuilder), _ => throw new NotSupportedException("Unknown MetaRewardType: " + typeString), }, args); } public static void Apply(MetaRewardData data, bool toModel, string modelName, bool isNewMetaReward, object builder) { ImportExportUtils.SetID(modelName); Plugin.Log.LogInfo((object)("Applying MetaReward " + modelName)); if (builder == null) { return; } EmbarkGoodMetaRewardBuilder goodBuilder = (EmbarkGoodMetaRewardBuilder)((builder is EmbarkGoodMetaRewardBuilder) ? builder : null); if (goodBuilder != null) { EmbarkGoodMetaRewardModel rewardModel2 = ((MetaRewardBuilder<EmbarkGoodMetaRewardModel>)(object)goodBuilder).Model; ImportExportUtils.ApplyLocaText(ref rewardModel2.displayName, ref data.displayName, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) goodBuilder.SetDisplayName(a, b); }, toModel, "displayName"); ImportExportUtils.ApplyLocaText(ref rewardModel2.description, ref data.description, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) goodBuilder.SetDescription(a, b); }, toModel, "description"); ImportExportUtils.ApplyVector2Int(ref rewardModel2.costRange, ref data.minCost, ref data.maxCost, toModel, "metaReward", "costRange"); ImportExportUtils.ApplyProperty<GoodRef, GoodRef>(ref rewardModel2.good, delegate { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) //IL_0092: Expected O, but got Unknown ManualLogSource log2 = Plugin.Log; string[] obj4 = new string[6] { "Getting good ", modelName, " with good ", data.good, " and name ", null }; GoodModel obj5 = GoodsTypesExtensions.ToGoodModel(data.good); obj4[5] = ((obj5 != null) ? ((Object)obj5).name : null); log2.LogInfo((object)string.Concat(obj4)); return new GoodRef { good = GoodsTypesExtensions.ToGoodModel(data.good), amount = data.goodAmount }; }, delegate(GoodRef a) { ManualLogSource log = Plugin.Log; object[] obj = new object[4] { modelName, a, null, null }; object obj2; if (a == null) { obj2 = null; } else { GoodModel good = a.good; obj2 = ((good != null) ? ((Object)good).name : null); } obj[2] = obj2; obj[3] = rewardModel2.good; log.LogInfo((object)string.Format("Setting good {0} with good {1} and name {2} from {3}", obj)); MetaRewardData metaRewardData = data; object obj3; if (a == null) { obj3 = null; } else { GoodModel good2 = a.good; obj3 = ((good2 != null) ? ((Object)good2).name : null); } if (obj3 == null) { obj3 = ""; } metaRewardData.good = (string)obj3; data.goodAmount = a?.amount ?? 0; }, toModel, "metaReward", "good"); return; } EmbarkEffectMetaRewardBuilder effectBuilder = (EmbarkEffectMetaRewardBuilder)((builder is EmbarkEffectMetaRewardBuilder) ? builder : null); if (effectBuilder != null) { EmbarkEffectMetaRewardModel rewardModel = ((MetaRewardBuilder<EmbarkEffectMetaRewardModel>)(object)effectBuilder).Model; ImportExportUtils.ApplyLocaText(ref rewardModel.displayName, ref data.displayName, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) effectBuilder.SetDisplayName(a, b); }, toModel, "displayName"); ImportExportUtils.ApplyLocaText(ref rewardModel.description, ref data.description, delegate(string a, SystemLanguage b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) effectBuilder.SetDescription(a, b); }, toModel, "description"); ImportExportUtils.ApplyProperty(delegate { //IL_0017: Unknown result type (might be due to invalid IL or missing references) EffectModel effect = rewardModel.effect; return (EffectTypes)((effect != null) ? ((int)EffectTypesExtensions.ToEffectTypes(((Object)effect).name)) : 0); }, delegate(EffectTypes a) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) effectBuilder.SetEffect(a); }, ref data.effect, toModel, "metaReward", "effect"); ImportExportUtils.ApplyVector2Int(ref rewardModel.costRange, ref data.minCost, ref data.maxCost, toModel, "metaReward", "costRange"); } } public static void ExportAll() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) MetaRewardModel[] metaRewards = MB.Settings.metaRewards; foreach (MetaRewardModel val in metaRewards) { MetaRewardData.MetaRewardTypes metaRewardTypes = MetaRewardData.MetaRewardTypes.Unknown; EmbarkGoodMetaRewardModel val2 = (EmbarkGoodMetaRewardModel)(object)((val is EmbarkGoodMetaRewardModel) ? val : null); if (val2 != null) { metaRewardTypes = MetaRewardData.MetaRewardTypes.EmbarkGoodMetaReward; } else { if (!(val is EmbarkEffectMetaRewardModel)) { Plugin.Log.LogError((object)$"Unknown MetaReward type {((object)val).GetType()}"); continue; } metaRewardTypes = MetaRewardData.MetaRewardTypes.EmbarkEffectMetaReward; } MetaRewardTypes key = MetaRewardTypesExtensions.ToMetaRewardTypes(((Object)val).name); MetaRewardData metaRewardData = new MetaRewardData(); metaRewardData.Initialize(); metaRewardData.type = metaRewardTypes.ToString(); NewMetaRewardData value; bool flag = MetaRewardManager.NewMetaRewardsLookup.TryGetValue(key, out value); if (flag) { metaRewardData.guid = value.guid; metaRewardData.name = value.rawName; } else { metaRewardData.name = ((Object)val).name; } object obj = CreateBuilder(metaRewardTypes.ToString(), val); EmbarkGoodMetaRewardModel val3 = (EmbarkGoodMetaRewardModel)(object)((val is EmbarkGoodMetaRewardModel) ? val : null); if (val3 != null) { Plugin.Log.LogInfo((object)("Good model good " + (object)val3.good)); EmbarkGoodMetaRewardBuilder val4 = (EmbarkGoodMetaRewardBuilder)((obj is EmbarkGoodMetaRewardBuilder) ? obj : null); Plugin.Log.LogInfo((object)("Good builder model " + (object)((MetaRewardBuilder<EmbarkGoodMetaRewardModel>)(object)val4).Model)); Plugin.Log.LogInfo((object)("Good builder model good " + (object)((MetaRewardBuilder<EmbarkGoodMetaRewardModel>)(object)val4).Model.good)); } Apply(metaRewardData, toModel: false, ((Object)val).name, flag, obj); string path = Path.Combine(Plugin.ExportDirectory, "metaRewards", ((Object)val).name + "_metaReward.json"); if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } string contents = JSONParser.ToJSON(metaRewardData); File.WriteAllText(path, contents); } } } [GenerateSchema("MetaReward", "Rewards given to the player when embarking.", "_metaReward.json")] public class MetaRewardData : IInitializable { public enum MetaRewardTypes { Unknown, EmbarkGoodMetaReward, EmbarkEffectMetaReward } [SchemaGuid] public string guid; [SchemaName] public string name; [SchemaEnum<MetaRewardTypes>(MetaRewardTypes.EmbarkGoodMetaReward, true, "Type of meta reward")] public string type; [SchemaDisplayName] public LocalizableField displayName; [SchemaDescription] public LocalizableField description; [SchemaEffectType(/*Could not decode attribute arguments.*/)] public string effect; [SchemaGoodType("Good given when the game starts if type is EmbarkGoodMetaReward")] public string good; [SchemaField(1, false, "Amount of good given if type is EmbarkGoodMetaReward")] public int goodAmount; [SchemaField(0, false, "Minimum cost of the reward")] public int minCost; [SchemaField(0, false, "Maximum cost of the reward")] public int maxCost; public void Initialize() { displayName = new LocalizableField("displayName"); description = new LocalizableField("description"); } } public class RaceLoader { public class RaceCharacteristicData { [SchemaBuildingTagType("")] public string buildingTag; [SchemaVillagerPerkTypeType("")] public string villagerPerkEffect; [SchemaEffectType(/*Could not decode attribute arguments.*/)] public string globalEffect; [SchemaBuildingPerkType("")] public string buildingPerk; } [GenerateSchema("Races", "Also known as villagers.", "_race.json")] public class RaceData : IInitializable { [SchemaGuid] public string guid; [SchemaName] public string name; [SchemaIcon(/*Could not decode attribute arguments.*/)] public string icon; [SchemaIcon(/*Could not decode attribute arguments.*/)] public string roundIcon; [SchemaIcon(/*Could not decode attribute arguments.*/)] public string widePortrait; [SchemaField("")] public string tag; [SchemaField(true, false, "If set to true the villager will always be available in the game.")] public bool? isEssential; [SchemaField(0, false, "Order in which the villager will appear in lists. 0 is minimum")] public int? order; [SchemaField("1.8f", false, "Base speed the villager can move at")] public float? baseSpeed; [SchemaField(15f, false, "Starting resolve of the villager")] public float? initialResolve; [SchemaField(0f, false, "Minimum resolve the villager can have")] public float? minResolve; [SchemaField(50f, false, "Maximum resolve the villager can have")] public float? maxResolve; [SchemaField(0.15f, false, "Resolve increase per second when the villager is happy")] public float? resolvePositveChangePerSec; [SchemaField(0.12f, false, "Resolve decrease per second when the villager is unhappy")] public float? resolveNegativeChangePerSec; [SchemaField(0.1f, false, "Factor that determines how much faster the resolve decreases when the villager is unhappy")] public float? resolveNegativeChangeDiffFactor; [SchemaField(0.00013f, false, "How much Reputation the player gains per second when the villagers resolve meets the threshold.")] public float? reputationPerSec; [SchemaField(0.025f, false, "Maximum amount of reputation the player gains per second when the villagers resolve meets the threshold.")] public float? maxReputationFromResolvePerSec; [SchemaField("1", false, "Minimum population required to gain reputation")] public int? minPopulationToGainReputation; [SchemaField(30f, false, "Minimum and maximum resolve values for the reputation treshold")] public float? minResolveForReputationTreshold; [SchemaField(50f, false, "Minimum and maximum resolve values for the reputation treshold")] public float? maxResolveForReputationTreshold; [SchemaField(4f)] public float? reputationTresholdIncreasePerReputation; [SchemaField(0.1f)] public float? resolveToReputationRatio; [SchemaField(0.7f)] public float? populationToReputationRatio; [SchemaField(6, false, "How hunger a villager gets before it wants to leave the village.")] public int? hungerTolerance; [SchemaField(120f, false, "How often the villager needs are checked")] public float? needsInterval; [SchemaNeed] public string[] needs; [SchemaField(null, false, "Characteristics of the villager of what they like and are good at.")] public RaceCharacteristicData[] characteristics; public RacialSounds avatarClickSounds; public RacialSounds femalePickSounds; public RacialSounds malePickSounds; public RacialSounds femaleChangeProfessionSounds; public RacialSounds maleChangeProfessionSounds; [SchemaField(null, false, "All possible names a male villager can have")] public string[] maleNames; [SchemaField(null, false, "All possible names a female villager can have")] public string[] femaleNames; public void Initialize() { } } public const string fileExtension = "_race.json"; public static void LoadAll(List<string> files) { for (int i = 0; i < files.Count; i++) { string text = files[i]; if (!text.EndsWith("_race.json")) { continue; } ImportExportUtils.SetDebugPath(text); files.RemoveAt(i--); try { Logging.VerboseLog("Loading JSON (goods) " + text); RaceData raceData = text.FromFilePath<RaceData>(); if (raceData == null) { Plugin.Log.LogError((object)("Failed to load JSON (race) " + text)); continue; } Logging.VerboseLog("Loaded JSON (race) " + text); RaceData raceData2 = raceData; if (raceData2.guid == null) { raceData2.guid = (MB.Settings.ContainsRace(raceData.name) ? "" : "JSONLoader"); } string text2 = ((!string.IsNullOrEmpty(raceData.guid)) ? (raceData.guid + "_") : ""); string text3 = text2 + raceData.name; RaceModel val = null; if (MB.Settings.ContainsRace(text3)) { Logging.VerboseLog("Found existing race " + text3); val = MB.Settings.GetRace(text3); Logging.VerboseLog("Applying JSON (race) " + text + " to race " + text3); Apply(val, raceData, toModel: true, text3); Logging.VerboseLog("Loaded JSON race " + text3); } else { Plugin.Log.LogError((object)("Custom races not yet supported! for name " + text3)); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Error loading JSON (race) {text}\n{arg}"); } } } public static void Apply(RaceModel model, RaceData data, bool toModel, string modelName) { //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Expected O, but got Unknown ImportExportUtils.SetID(modelName); ImportExportUtils.ApplyValueNoNull(ref model.icon, ref data.icon, toModel, "races", "icon"); ImportExportUtils.ApplyValueNoNull(ref model.roundIcon, ref data.roundIcon, toModel, "races", "roundIcon"); ImportExportUtils.ApplyValueNoNull(ref model.widePortrait, ref data.widePortrait, toModel, "races", "widePortrait"); ImportExportUtils.ApplyValueNoNull(ref model.isEssential, ref data.isEssential, toModel, "races", "isEssential"); ImportExportUtils.ApplyValueNoNull(ref model.maleNames, ref data.maleNames, toModel, "races", "maleNames"); ImportExportUtils.ApplyValueNoNull(ref model.femaleNames, ref data.femaleNames, toModel, "races", "femaleNames"); ImportExportUtils.ApplyValueNoNull(ref model.order, ref data.order, toModel, "races", "order"); ImportExportUtils.ApplyValueNoNull(ref model.tag, ref data.tag, toModel, "races", "widePortrait"); ImportExportUtils.ApplyValueNoNull(ref model.baseSpeed, ref data.baseSpeed, toModel, "races", "baseSpeed"); ImportExportUtils.ApplyValueNoNull(ref model.initialResolve, ref data.initialResolve, toModel, "races", "initialResolve"); ImportExportUtils.ApplyValueNoNull(ref model.minResolve, ref data.minResolve, toModel, "races", "minResolve"); ImportExportUtils.ApplyValueNoNull(ref model.maxResolve, ref data.maxResolve, toModel, "races", "maxResolve"); ImportExportUtils.ApplyValueNoNull(ref model.resolvePositveChangePerSec, ref data.resolvePositveChangePerSec, toModel, "races", "resolvePositveChangePerSec"); ImportExportUtils.ApplyValueNoNull(ref model.resolveNegativeChangePerSec, ref data.resolveNegativeChangePerSec, toModel, "races", "resolveNegativeChangePerSec"); ImportExportUtils.ApplyValueNoNull(ref model.resolveNegativeChangeDiffFactor, ref data.resolveNegativeChangeDiffFactor, toModel, "races", "resolveNegativeChangeDiffFactor"); ImportExportUtils.ApplyValueNoNull(ref model.reputationPerSec, ref data.reputationPerSec, toModel, "races", "reputationPerSec"); ImportExportUtils.ApplyValueNoNull(ref model.minPopulationToGainReputation, ref data.minPopulationToGainReputation, toModel, "races", "minPopulationToGainReputation"); ImportExportUtils.ApplyValueNoNull(ref model.maxReputationFromResolvePerSec, ref data.maxReputationFromResolvePerSec, toModel, "races", "maxReputationFromResolvePerSec"); ImportExportUtils.ApplyVector2(ref model.resolveForReputationTreshold, ref data.minResolveForReputationTreshold, ref data.maxResolveForReputationTreshold, toModel, "races", "resolveForReputationTreshold"); ImportExportUtils.ApplyValueNoNull(ref model.reputationTresholdIncreasePerReputation, ref data.reputationTresholdIncreasePerReputation, toModel, "races", "reputationTresholdIncreasePerReputation"); ImportExportUtils.ApplyValueNoNull(ref model.resolveToReputationRatio, ref data.resolveToReputationRatio, toModel, "races", "resolveToReputationRatio"); ImportExportUtils.ApplyValueNoNull(ref model.populationToReputationRatio, ref data.populationToReputationRatio, toModel, "races", "populationToReputationRatio"); ImportExportUtils.ApplyValueNoNull(ref model.hungerTolerance, ref data.hungerTolerance, toModel, "races", "hungerTolerance"); ImportExportUtils.ApplyValueNoNull(ref model.needs, ref data.needs, toModel, "races", "needs"); ImportExportUtils.ApplyValueNoNull(ref model.needsInterval, ref data.needsInterval, toModel, "races", "needsInterval"); ImportExportUtils.ApplyValueNoNull(ref model.avatarClickSound, ref data.avatarClickSounds, toModel, "races", "avatarClickSounds"); ImportExportUtils.ApplyValueNoNull(ref model.femalePrefab.view.pickSound, ref data.femalePickSounds, toModel, "races", "femalePickSounds"); ImportExportUtils.ApplyValueNoNull(ref model.femalePrefab.view.professionChangeSound, ref data.femaleChangeProfessionSounds, toModel, "races", "femaleChangeProfessionSounds"); ImportExportUtils.ApplyValueNoNull(ref model.malePrefab.view.pickSound, ref data.malePickSounds, toModel, "races", "malePickSounds"); ImportExportUtils.ApplyValueNoNull(ref model.malePrefab.view.professionChangeSound, ref data.maleChangeProfessionSounds, toModel, "races", "maleChangeProfessionSounds"); if (toModel) { model.avatarClickSound.race = model; model.femalePrefab.view.pickSound.race = model; model.femalePrefab.view.professionChangeSound.race = model; model.malePrefab.view.pickSound.race = model; model.malePrefab.view.professionChangeSound.race = model; if (data.characteristics == null) { return; } model.characteristics = (RaceCharacteristicModel[])(object)new RaceCharacteristicModel[data.characteristics.Length]; for (int i = 0; i < data.characteristics.Length; i++) { RaceCharacteristicData raceCharacteristicData = data.characteristics[i]; RaceCharacteristicModel val = new RaceCharacteristicModel(); val.tag = BuildingTagTypesExtensions.ToBuildingTagModel(raceCharacteristicData.buildingTag); if (!string.IsNullOrEmpty(raceCharacteristicData.villagerPerkEffect)) { val.effect = VillagerPerkTypesExtensions.ToVillagerPerkModel(raceCharacteristicData.villagerPerkEffect); } if (!string.IsNullOrEmpty(raceCharacteristicData.globalEffect)) { val.globalEffect = EffectTypesExtensions.ToEffectModel(raceCharacteristicData.globalEffect); } if (!string.IsNullOrEmpty(raceCharacteristicData.buildingPerk)) { val.buildingPerk = BuildingPerkTypesExtensions.ToBuildingPerkModel(raceCharacteristicData.buildingPerk); } model.characteristics[i] = val; } } else { data.characteristics = new RaceCharacteristicData[model.characteristics.Length]; for (int j = 0; j < model.characteristics.Length; j++) { RaceCharacteristicModel val2 = model.characteristics[j]; RaceCharacteristicData raceCharacteristicData2 = new RaceCharacteristicData(); BuildingTagModel tag = val2.tag; raceCharacteristicData2.buildingTag = ((tag != null) ? ((Object)tag).name : null); VillagerPerkModel effect = val2.effect; raceCharacteristicData2.villagerPerkEffect = ((effect != null) ? ((Object)effect).name : null); EffectModel globalEffect = val2.globalEffect; raceCharacteristicData2.globalEffect = ((globalEffect != null) ? ((Object)globalEffect).name : null); BuildingPerkModel buildingPerk = val2.buildingPerk; raceCharacteristicData2.buildingPerk = ((buildingPerk != null) ? ((Object)buildingPerk).name : null); data.characteristics[j] = raceCharacteristicData2; } } } public static void ExportAll() { RaceModel[] races = MB.Settings.Races; foreach (RaceModel val in races) { RaceData raceData = new RaceData(); raceData.name = ((Object)val).name; raceData.Initialize(); Apply(val, raceData, toModel: false, ((Object)val).name); string path = Path.Combine(Plugin.ExportDirectory, "races", ((Object)val).name + "_race.json"); if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } string contents = JSONParser.ToJSON(raceData); File.WriteAllText(path, contents); } } } public class WorkshopRecipeLoader { public const string fileExtension = "_workshopRecipe.json"; public static void LoadAll(List<string> files) { //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Expected O, but got Unknown for (