private static void SetupRecipes() // Sets up recipes, what were you expecting? { _loadProgressText.Invoke("tConfig Wrapper: Adding Recipes"); // Ah yes, more reflection _loadProgress.Invoke(0f); int progressCount = 0; bool initialized = (bool)Assembly.GetAssembly(typeof(Mod)).GetType("Terraria.ModLoader.MapLoader").GetField("initialized", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); // Check if the map is already initialized foreach (var iniFileSection in recipeDict) // Load every recipe in the recipe dict { progressCount++; // Count the number of recipes, still broken somehow :( string modName = iniFileSection.Key.Split(':')[0]; ModRecipe recipe = null; if (initialized) // Only make the recipe if the maps have already been initialized. The checks for initialized are because this method is run in GetTileMapEntires() to see what tiles are used in recipes and need to have a name in their map entry { recipe = new ModRecipe(Mod); } foreach (var element in iniFileSection.Value.elements) // ini recipe loading, code is barely readable enough. { string[] splitElement = element.Content.Split('='); string key = splitElement[0]; string value = splitElement[1]; switch (key) { case "Amount" when initialized: { int id; string[] splitKey = iniFileSection.Key.Split(':'); string itemName = splitKey.Length == 1 ? splitKey[0] : splitKey[1]; if ((id = ItemID.FromLegacyName(itemName, 4)) != 0) { recipe?.SetResult(id, int.Parse(value)); } else { recipe?.SetResult(Mod, iniFileSection.Key, int.Parse(value)); } break; } case "needWater" when initialized: recipe.needWater = bool.Parse(value); break; case "Items" when initialized: { foreach (string recipeItem in value.Split(',')) { var recipeItemInfo = recipeItem.Split(null, 2); int amount = int.Parse(recipeItemInfo[0]); int itemID = Mod.ItemType($"{modName}:{recipeItemInfo[1].RemoveIllegalCharacters()}"); if (itemID == 0) { itemID = ItemID.FromLegacyName(recipeItemInfo[1], 4); } var numberIngredients = recipe?.requiredItem.Count(i => i != null & i.type != ItemID.None); if (numberIngredients < 14) { recipe?.AddIngredient(itemID, amount); } else { Mod.Logger.Debug($"The following item has exceeded the max ingredient limit! -> {iniFileSection.Key}"); tConfigWrapper.ReportErrors = true; } } break; } case "Tiles": { // Does stuff to check for modtiles and vanilla tiles that have changed their name since 1.1.2 foreach (string recipeTile in value.Split(',')) { string recipeTileIR = recipeTile.RemoveIllegalCharacters(); int tileInt = Mod.TileType($"{modName}:{recipeTileIR}"); var tileModTile = Mod.GetTile($"{modName}:{recipeTileIR}"); if (!TileID.Search.ContainsName(recipeTileIR) && !CheckIDConversion(recipeTileIR) && tileInt == 0 && tileModTile == null) // Would love to replace this with Utilities.StringToContent() but this one is special and needs to add stuff to a dictionary so I can't { if (initialized) { Mod.Logger.Debug($"TileID {modName}:{recipeTileIR} does not exist"); // We will have to manually convert anything that breaks lmao tConfigWrapper.ReportErrors = true; } } else if (CheckIDConversion(recipeTileIR) || TileID.Search.ContainsName(recipeTileIR)) { string converted = ConvertIDTo13(recipeTileIR); if (initialized) { recipe?.AddTile(TileID.Search.GetId(converted)); } } else if (tileInt != 0) { if (initialized) { recipe?.AddTile(tileModTile); Mod.Logger.Debug($"{modName}:{recipeTileIR} added to recipe through mod.TileType!"); } //else { // tileMapData[tileModTile] = (true, tileMapData[tileModTile].Item2); // I do this because either I can't just change Item1 directly to true OR because I am very not smart and couldn't figure out how to set it individually. //} } } break; } } } if (recipe?.createItem != null && recipe?.createItem.type != ItemID.None && initialized) { recipe?.AddRecipe(); } if (initialized) { _loadProgress.Invoke(progressCount / recipeDict.Count); } } }
protected override void HandleFile(string file) { MemoryStream iniStream = fileStreams[file]; IniFileReader reader = new IniFileReader(iniStream); IniFile iniFile = IniFile.FromStream(reader); object info = new ItemInfo(); List <string> toolTipList = new List <string>(); // Get the mod name string itemName = Path.GetFileNameWithoutExtension(file); string internalName = $"{modName}:{itemName.RemoveIllegalCharacters()}"; // TODO: If the item is from Terraria, make it a GlobalItem if (ItemID.FromLegacyName(itemName, 4) != 0) { internalName = itemName; } bool logItemAndModName = false; string createWall = null; string createTile = null; string shoot = null; foreach (IniFileSection section in iniFile.sections) { foreach (IniFileElement element in section.elements) { switch (section.Name) { case "Stats": { var splitElement = element.Content.Split('='); var statField = typeof(ItemInfo).GetField(splitElement[0]); switch (splitElement[0]) { // Set the tooltip, has to be done manually since the toolTip field doesn't exist in 1.3 case "toolTip": case "toolTip1": case "toolTip2": case "toolTip3": case "toolTip4": case "toolTip5": case "toolTip6": case "toolTip7": { toolTipList.Add(splitElement[1]); continue; } case "useSound": { var soundStyleId = int.Parse(splitElement[1]); var soundStyle = new LegacySoundStyle(2, soundStyleId); // All items use the second sound ID statField = typeof(ItemInfo).GetField("UseSound"); statField.SetValue(info, soundStyle); continue; } case "createTileName": { createTile = $"{modName}:{splitElement[1]}"; continue; } case "projectile": { shoot = $"{modName}:{splitElement[1]}"; continue; } case "createWallName": { createWall = $"{modName}:{splitElement[1]}"; continue; } case "type": continue; default: { if (statField == null) { Mod.Logger.Debug($"Item field not found or invalid field! -> {splitElement[0]}"); logItemAndModName = true; tConfigWrapper.ReportErrors = true; continue; } break; } } // Convert the value to an object of type statField.FieldType TypeConverter converter = TypeDescriptor.GetConverter(statField.FieldType); object realValue = converter.ConvertFromString(splitElement[1]); statField.SetValue(info, realValue); break; } case "Recipe": { if (!LoadStep.recipeDict.ContainsKey(internalName)) { LoadStep.recipeDict.TryAdd(internalName, section); } break; } } } } if (logItemAndModName) { Mod.Logger.Debug($"{internalName}"); //Logs the item and mod name if "Field not found or invalid field". Mod and item name show up below the other log line } string toolTip = string.Join("\n", toolTipList); // Check if a texture for the .ini file exists string texturePath = Path.ChangeExtension(file, "png"); Texture2D itemTexture = null; if (!Main.dedServ && fileStreams.TryGetValue(texturePath, out MemoryStream textureStream)) { itemTexture = Texture2D.FromStream(Main.instance.GraphicsDevice, textureStream); // Load a Texture2D from the stream } int id = ItemID.FromLegacyName(itemName, 4); if (id != 0) { if (!LoadStep.globalItemInfos.ContainsKey(id)) { LoadStep.globalItemInfos.TryAdd(id, (ItemInfo)info); } else { LoadStep.globalItemInfos[id] = (ItemInfo)info; } reader.Dispose(); return; } _itemsToLoad.Add(internalName, new BaseItem((ItemInfo)info, internalName, itemName, createTile, shoot, createWall, toolTip, itemTexture)); reader.Dispose(); }