using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using RecipeManager.Common;
using UnityEngine;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("RecipeManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RecipeManager")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
namespace RecipeManager
{
internal class PieceReloadCommand : ConsoleCommand
{
public override string Name => "RM_Pieces_Reload";
public override string Help => "Resynchronizes piece modifications.";
public override bool IsCheat => true;
public override void Run(string[] args)
{
PieceUpdater.RevertPieceModifications();
ValConfig.ReloadPieceFiles();
PieceUpdater.BuildPieceTracker();
PieceUpdater.PieceUpdateRunner();
}
}
internal class PiecePrintCommand : ConsoleCommand
{
public override string Name => "RM_Pieces_PrintAll";
public override string Help => "Prints all the Pieces found.";
public override void Run(string[] args)
{
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Starting to dump piece list");
}
string text = Path.Combine(Paths.ConfigPath, "RecipeManager", "AllPiecesDebug.yaml");
DataObjects.PieceModificationCollection pieceModificationCollection = new DataObjects.PieceModificationCollection();
using StreamWriter streamWriter = new StreamWriter(text);
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Gathering Pieces");
}
foreach (Piece item in (from pc in Resources.FindObjectsOfTypeAll<Piece>()
where !((Object)pc).name.EndsWith("(Clone)") && !Regex.IsMatch(((Object)pc).name.Trim(), "\\(\\d+\\)")
select pc).ToList())
{
if ((Object)(object)item == (Object)null || ((Object)item).name == null)
{
continue;
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Building Recipe " + item.m_name));
}
DataObjects.PieceModification pieceModification = new DataObjects.PieceModification();
pieceModification.action = DataObjects.PieceAction.Enable;
pieceModification.EnablePiece = ((Behaviour)item).enabled;
pieceModification.CanBeDeconstructed = item.m_canBeRemoved;
pieceModification.CultivatedGroundOnly = item.m_cultivatedGroundOnly;
pieceModification.ComfortGroup = item.m_comfortGroup;
pieceModification.ComfortAmount = item.m_comfort;
pieceModification.GroundPlacement = item.m_groundPiece;
pieceModification.SpaceRequired = item.m_spaceRequirement;
pieceModification.AllowedInDungeon = item.m_allowedInDungeons;
pieceModification.CraftingStationConnectionRadius = item.m_connectRadius;
pieceModification.MustBeAvobeConnectedStation = item.m_mustBeAboveConnected;
pieceModification.OnlyInSelectBiome = item.m_onlyInBiome;
pieceModification.PieceCategory = item.m_category;
pieceModification.PieceDescription = item.m_description;
pieceModification.PieceName = item.m_name;
pieceModification.prefab = ((Object)((Component)item).gameObject).name;
if ((Object)(object)item.m_craftingStation != (Object)null)
{
pieceModification.RequiredToPlaceCraftingStation = ((Object)item.m_craftingStation).name;
}
pieceModification.IsUpgradeForStation = item.m_isUpgrade;
List<DataObjects.SimpleRequirement> list = new List<DataObjects.SimpleRequirement>();
if (item.m_resources != null && item.m_resources.Length != 0)
{
Requirement[] resources = item.m_resources;
foreach (Requirement val in resources)
{
try
{
list.Add(new DataObjects.SimpleRequirement
{
amount = val.m_amount,
Prefab = ((Object)val.m_resItem).name
});
}
catch (Exception arg)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogWarning((object)$"Piece requirement setup error {val} \n{arg}");
}
}
}
}
pieceModification.requirements = list;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Adding " + pieceModification.prefab + " to collection."));
}
if (!pieceModificationCollection.PieceModifications.ContainsKey(pieceModification.prefab))
{
pieceModificationCollection.PieceModifications.Add(pieceModification.prefab, pieceModification);
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Piece " + pieceModification.prefab + " Added."));
}
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Serializing and printing recipes.");
}
string value = ValConfig.yamlserializer.Serialize((object)pieceModificationCollection);
streamWriter.WriteLine(value);
Logger.LogInfo((object)("Recipes dumped to file " + text));
}
}
internal class PieceUpdater
{
public static Dictionary<string, DataObjects.PieceModification> PiecesToModify = new Dictionary<string, DataObjects.PieceModification>();
public static List<DataObjects.TrackedPiece> TrackedPieces = new List<DataObjects.TrackedPiece>();
public static void InitialSychronization()
{
BuildPieceTracker();
PieceUpdateRunner();
}
public static void PieceUpdateRunner()
{
Logger.LogInfo($"Applying {TrackedPieces.Count} piece modifications");
foreach (DataObjects.TrackedPiece trackedPiece in TrackedPieces)
{
ApplyPieceModifications(trackedPiece);
}
}
public static void ApplyPieceModifications(DataObjects.TrackedPiece piece)
{
Logger.LogDebug($"Applying piece ({piece.prefab}) modification action: {piece.action}");
switch (piece.action)
{
case DataObjects.PieceAction.Disable:
DisablePiece(piece);
break;
case DataObjects.PieceAction.Modify:
ModifyPiece(piece);
break;
case DataObjects.PieceAction.Enable:
EnablePiece(piece);
break;
}
}
public static void RevertPieceModifications()
{
foreach (DataObjects.TrackedPiece trackedPiece in TrackedPieces)
{
RevertPiece(trackedPiece);
}
}
public static void EnablePiece(DataObjects.TrackedPiece piece)
{
Logger.LogDebug("Enabling " + piece.prefab);
PrefabManager.Instance.GetPrefab(piece.prefab).GetComponent<Piece>().m_enabled = true;
}
private static void RevertPiece(DataObjects.TrackedPiece tpiece)
{
PrefabManager.Instance.GetPrefab(tpiece.prefab).GetComponent<Piece>();
_ = tpiece.originalPiece;
}
private static void ModifyPiece(DataObjects.TrackedPiece piece)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Invalid comparison between Unknown and I4
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
Logger.LogDebug("Modifying " + piece.prefab);
Piece component = PrefabManager.Instance.GetPrefab(piece.prefab).GetComponent<Piece>();
if ((Object)(object)component != (Object)null)
{
if (piece.updatedRequirements != null)
{
component.m_resources = piece.updatedRequirements;
}
component.m_craftingStation = piece.RequiredToPlaceCraftingStation;
component.m_allowedInDungeons = piece.AllowedInDungeon;
component.m_canBeRemoved = piece.CanBeDeconstructed;
if ((int)piece.PieceCategory != 100)
{
component.m_category = piece.PieceCategory;
}
if (piece.ComfortAmount != -1)
{
component.m_comfort = piece.ComfortAmount;
}
if ((int)piece.ComfortGroup != 0)
{
component.m_comfortGroup = piece.ComfortGroup;
}
if (piece.CraftingStationConnectionRadius != -1f)
{
component.m_connectRadius = piece.CraftingStationConnectionRadius;
}
if (piece.PieceDescription != null)
{
component.m_description = piece.PieceDescription;
}
component.m_enabled = piece.EnablePiece;
if (piece.PieceName != null)
{
component.m_name = piece.PieceName;
}
component.m_onlyInBiome = piece.OnlyInBiome;
component.m_isUpgrade = piece.IsUpgradeForStation;
component.m_cultivatedGroundOnly = piece.CultivatedGroundOnly;
component.m_mustBeAboveConnected = piece.MustBeAvobeConnectedStation;
if (piece.SpaceRequired != -1f)
{
component.m_spaceRequirement = piece.SpaceRequired;
}
component.m_groundPiece = piece.GroundPlacement;
}
}
private static void DisablePiece(DataObjects.TrackedPiece piece)
{
Logger.LogDebug("Modifying " + piece.prefab);
PrefabManager.Instance.GetPrefab(piece.prefab).GetComponent<Piece>().m_enabled = false;
}
public static void BuildPieceTracker()
{
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Expected O, but got Unknown
//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
TrackedPieces.Clear();
foreach (KeyValuePair<string, DataObjects.PieceModification> item in PiecesToModify)
{
if (item.Key == null)
{
continue;
}
Logger.LogInfo("Constructing piece modification for " + item.Key);
DataObjects.TrackedPiece trackedPiece = new DataObjects.TrackedPiece();
trackedPiece.action = item.Value.action;
trackedPiece.prefab = item.Value.prefab;
try
{
Piece component = PrefabManager.Instance.GetPrefab(item.Value.prefab).GetComponent<Piece>();
trackedPiece.originalPiece = component;
}
catch (Exception)
{
Logger.LogWarning("Could not find entries referenced piece, this modification will be skipped. Define a prefab to modify to fix this.");
}
if (item.Value.action == DataObjects.PieceAction.Enable || item.Value.action == DataObjects.PieceAction.Disable)
{
TrackedPieces.Add(trackedPiece);
continue;
}
List<Requirement> list = new List<Requirement>();
foreach (DataObjects.SimpleRequirement requirement in item.Value.requirements)
{
try
{
ItemDrop component2 = PrefabManager.Instance.GetPrefab(requirement.Prefab).GetComponent<ItemDrop>();
list.Add(new Requirement
{
m_amount = requirement.amount,
m_resItem = component2
});
Logger.LogInfo($"Building requirement with res:{((Object)component2).name} amount:{requirement.amount}");
}
catch
{
Logger.LogWarning("Could not find an itemDrop for resource with name: " + requirement.Prefab);
}
}
trackedPiece.updatedRequirements = list.ToArray();
if (item.Value.RequiredToPlaceCraftingStation != null && item.Value.RequiredToPlaceCraftingStation != "")
{
if (item.Value.RequiredToPlaceCraftingStation.ToLower() == "none")
{
trackedPiece.RequiredToPlaceCraftingStation = null;
}
else
{
GameObject prefab = PrefabManager.Instance.GetPrefab(item.Value.RequiredToPlaceCraftingStation);
CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
if ((Object)(object)val != (Object)null)
{
trackedPiece.RequiredToPlaceCraftingStation = val;
}
else
{
Logger.LogWarning($"Could not link required crafting station, are you sure a crafting station exists with piecename: {val}");
}
}
}
else
{
trackedPiece.RequiredToPlaceCraftingStation = PrefabManager.Instance.GetPrefab(item.Value.prefab).GetComponent<Piece>().m_craftingStation;
}
trackedPiece.IsUpgradeForStation = item.Value.IsUpgradeForStation;
trackedPiece.AllowedInDungeon = item.Value.AllowedInDungeon;
trackedPiece.CanBeDeconstructed = item.Value.CanBeDeconstructed;
trackedPiece.ComfortAmount = item.Value.ComfortAmount;
trackedPiece.ComfortGroup = item.Value.ComfortGroup;
trackedPiece.CraftingStationConnectionRadius = item.Value.CraftingStationConnectionRadius;
trackedPiece.PieceDescription = item.Value.PieceDescription;
trackedPiece.PieceName = item.Value.PieceName;
trackedPiece.EnablePiece = item.Value.EnablePiece;
trackedPiece.CultivatedGroundOnly = item.Value.CultivatedGroundOnly;
trackedPiece.MustBeAvobeConnectedStation = item.Value.MustBeAvobeConnectedStation;
trackedPiece.SpaceRequired = item.Value.SpaceRequired;
trackedPiece.GroundPlacement = item.Value.GroundPlacement;
TrackedPieces.Add(trackedPiece);
}
}
public static void UpdatePieceModificationsFromList(List<DataObjects.PieceModificationCollection> lPieceMods)
{
PiecesToModify.Clear();
foreach (DataObjects.PieceModificationCollection lPieceMod in lPieceMods)
{
foreach (KeyValuePair<string, DataObjects.PieceModification> pieceModification in lPieceMod.PieceModifications)
{
PiecesToModify.Add(pieceModification.Key, pieceModification.Value);
}
}
}
public static void UpdatePieceModificationsFromRPC(string rpcRecieved)
{
Logger.LogInfo("RPC Recieved: " + rpcRecieved);
Logger.LogInfo($"RPC Data: {rpcRecieved.Length}");
}
public static void UpdatePieceModifications(DataObjects.PieceModificationCollection PieceMods)
{
PiecesToModify.Clear();
foreach (KeyValuePair<string, DataObjects.PieceModification> pieceModification in PieceMods.PieceModifications)
{
PiecesToModify.Add(pieceModification.Key, pieceModification.Value);
}
}
}
internal class RecipeReloadCommand : ConsoleCommand
{
public override string Name => "RM_Recipes_Reload";
public override string Help => "Resynchronizes recipes.";
public override bool IsCheat => true;
public override void Run(string[] args)
{
RecipeUpdater.RecipeRevert();
ValConfig.ReloadRecipeFiles();
RecipeUpdater.BuildRecipesForTracking();
RecipeUpdater.SecondaryRecipeSync();
}
}
internal class RecipeUnapplyCommand : ConsoleCommand
{
public override string Name => "RM_Recipes_Unapply";
public override string Help => "Removes recipe modifications.";
public override bool IsCheat => true;
public override void Run(string[] args)
{
RecipeUpdater.RecipeRevert();
}
}
internal class RecipePrintCommand : ConsoleCommand
{
public override string Name => "RM_Recipes_PrintAll";
public override string Help => "Prints all the recipes stored in the Object DB";
public override void Run(string[] args)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Starting to dump recipes");
}
string text = Path.Combine(Paths.ConfigPath, "RecipeManager", "ObjectDBRecipes.yaml");
DataObjects.RecipeModificationCollection recipeModificationCollection = new DataObjects.RecipeModificationCollection();
using StreamWriter streamWriter = new StreamWriter(text);
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Loading recipes from ODB");
}
foreach (Recipe item in ObjectDB.instance.m_recipes.ToList())
{
if ((Object)(object)item == (Object)null || ((Object)item).name == null)
{
continue;
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Building Recipe " + ((Object)item).name));
}
DataObjects.RecipeModification recipeModification = new DataObjects.RecipeModification();
recipeModification.recipeName = ((Object)item).name;
recipeModification.minStationLevel = (short)item.m_minStationLevel;
recipeModification.craftAmount = (short)item.m_amount;
recipeModification.action = DataObjects.Action.Enable;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Checking for empty referenced objects");
}
if ((Object)(object)item.m_craftingStation != (Object)null)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Adding crafting station");
}
recipeModification.craftedAt = ((Object)item.m_craftingStation).name;
}
if ((Object)(object)item.m_repairStation != (Object)null)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Adding repair station");
}
recipeModification.repairAt = ((Object)item.m_repairStation).name;
}
if ((Object)(object)item.m_item != (Object)null)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Adding prefab");
}
recipeModification.prefab = ((Object)item.m_item).name;
}
DataObjects.SimpleRecipe simpleRecipe = new DataObjects.SimpleRecipe();
if (item.m_resources != null && item.m_resources.Length != 0)
{
simpleRecipe.anyOneResource = item.m_requireOnlyOneIngredient;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Building resource requirements");
}
Requirement[] resources = item.m_resources;
foreach (Requirement val in resources)
{
try
{
DataObjects.Ingrediant ingrediant = new DataObjects.Ingrediant();
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Setting crafting cost");
}
ingrediant.craftCost = (short)val.m_amount;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Setting upgrade cost");
}
ingrediant.upgradeCost = (short)val.m_amountPerLevel;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Setting prefab name");
}
if ((Object)(object)val.m_resItem != (Object)null)
{
ingrediant.prefab = ((Object)val.m_resItem).name;
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Adding to ingrediants list");
}
simpleRecipe.ingredients.Add(ingrediant);
}
catch (Exception arg)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogWarning((object)$"Requirement did not contain all of the details required to set an ingrediant {val} \n{arg}");
}
}
}
}
if (simpleRecipe.ingredients != null && simpleRecipe.ingredients.Count > 0)
{
recipeModification.recipe = simpleRecipe;
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Adding " + ((Object)item).name + " to collection."));
}
if (recipeModificationCollection.RecipeModifications.ContainsKey(((Object)item).name))
{
try
{
int num = Random.Range(0, 1000);
recipeModificationCollection.RecipeModifications.Add(((Object)item).name + $"_{num}", recipeModification);
Logger.LogWarning((object)$"{((Object)item).name} was already added to the list of recipes and will be renamed {((Object)item).name}_{num}, please use unique recipe names.");
}
catch
{
Logger.LogWarning((object)(((Object)item).name + " was already added to the list of recipes and will be skipped, please use unique recipe names."));
}
}
else
{
recipeModificationCollection.RecipeModifications.Add(((Object)item).name, recipeModification);
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Recipe " + ((Object)item).name + " Added."));
}
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Serializing and printing recipes.");
}
string value = ValConfig.yamlserializer.Serialize((object)recipeModificationCollection);
streamWriter.WriteLine(value);
Logger.LogInfo((object)("Recipes dumped to file " + text));
}
}
[BepInPlugin("MidnightsFX.RecipeManager", "RecipeManager", "0.4.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class RecipeManager : BaseUnityPlugin
{
public const string PluginGUID = "MidnightsFX.RecipeManager";
public const string PluginName = "RecipeManager";
public const string PluginVersion = "0.4.3";
public ValConfig cfg;
public static ManualLogSource Log;
public void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
cfg = new ValConfig(((BaseUnityPlugin)this).Config);
ItemManager.OnItemsRegistered += RecipeUpdater.InitialRecipesAndSynchronize;
ItemManager.OnItemsRegistered += PieceUpdater.InitialSychronization;
MinimapManager.OnVanillaMapDataLoaded += RecipeUpdater.SecondaryRecipeSync;
MinimapManager.OnVanillaMapDataLoaded += PieceUpdater.PieceUpdateRunner;
CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipeReloadCommand());
CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipePrintCommand());
CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RecipeUnapplyCommand());
CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PiecePrintCommand());
CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new PieceReloadCommand());
}
}
internal class RecipeUpdater
{
public static Dictionary<string, DataObjects.RecipeModification> RecipesToModify = new Dictionary<string, DataObjects.RecipeModification>();
public static List<DataObjects.TrackedRecipe> TrackedRecipes = new List<DataObjects.TrackedRecipe>();
public static void SecondaryRecipeSync()
{
if (TrackedRecipes.Count == 0)
{
return;
}
foreach (DataObjects.TrackedRecipe trackedRecipe in TrackedRecipes)
{
if (!CheckIfRecipeWasModified(trackedRecipe))
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Tracked " + trackedRecipe.prefab + " recipe still has its original recipe in the db. Modifying."));
}
ApplyRecipeModifcations(trackedRecipe);
}
}
}
public static void RecipeRevert()
{
foreach (DataObjects.TrackedRecipe trackedRecipe in TrackedRecipes)
{
ReverseRecipeModifications(trackedRecipe);
}
}
public static void InitialRecipesAndSynchronize()
{
BuildRecipesForTracking();
RecipeUpdateRunner();
}
public static void RecipeUpdateRunner()
{
foreach (DataObjects.TrackedRecipe trackedRecipe in TrackedRecipes)
{
ApplyRecipeModifcations(trackedRecipe);
}
}
public static void ApplyRecipeModifcations(DataObjects.TrackedRecipe tracked_recipe)
{
if (ValConfig.EnableDebugMode.Value)
{
if ((Object)(object)tracked_recipe.updatedRecipe != (Object)null)
{
string text = "";
Requirement[] resources = tracked_recipe.updatedRecipe.m_resources;
foreach (Requirement val in resources)
{
text += $" {val.m_resItem},{val.m_amount},{val.m_amountPerLevel}";
}
Logger.LogInfo((object)("Applying Updated Recipe: " + ((Object)tracked_recipe.updatedRecipe).name + "\n" + $"amount:{tracked_recipe.updatedRecipe.m_amount}\n" + $"enabled:{tracked_recipe.updatedRecipe.m_enabled}\n" + $"craftingStation:{tracked_recipe.updatedRecipe.m_craftingStation}\n" + $"reqStationLevel:{tracked_recipe.updatedRecipe.m_minStationLevel}\n" + $"reqOneIngrediant:{tracked_recipe.updatedRecipe.m_requireOnlyOneIngredient}\n" + "resources:" + text));
}
if ((Object)(object)tracked_recipe.originalRecipe != (Object)null)
{
string text2 = "";
Requirement[] resources = tracked_recipe.originalRecipe.m_resources;
foreach (Requirement val2 in resources)
{
text2 += $" {val2.m_resItem},{val2.m_amount},{val2.m_amountPerLevel}";
}
Logger.LogInfo((object)("Targeting Original Recipe: " + ((Object)tracked_recipe.originalRecipe).name + "\n" + $"amount:{tracked_recipe.originalRecipe.m_amount}\n" + $"enabled:{tracked_recipe.originalRecipe.m_enabled}\n" + $"amount:{tracked_recipe.originalRecipe.m_amount}\n" + $"craftingStation:{tracked_recipe.originalRecipe.m_craftingStation}\n" + $"reqStationLevel:{tracked_recipe.originalRecipe.m_minStationLevel}\n" + $"reqOneIngrediant:{tracked_recipe.originalRecipe.m_requireOnlyOneIngredient}\n" + "resources:" + text2));
}
}
bool flag = false;
if (tracked_recipe.action == DataObjects.Action.Disable)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Disable Action called for " + tracked_recipe.prefab + " recipe"));
}
flag = DisableRecipe(tracked_recipe.originalRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Delete)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Delete Action called for " + tracked_recipe.prefab + " recipe"));
}
flag = DeleteRecipe(tracked_recipe.originalRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Modify)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Modify Action called for " + tracked_recipe.prefab + " recipe"));
}
if (ObjectDB.instance.m_recipes.Contains(tracked_recipe.updatedRecipe))
{
DeleteRecipe(tracked_recipe.originalRecipe);
flag = true;
}
else if (ObjectDB.instance.m_recipes.Contains(tracked_recipe.originalRecipe))
{
flag = ModifyRecipeInODB(tracked_recipe.originalRecipe, tracked_recipe.updatedRecipe);
ModifyRecipeInJotunnManager(tracked_recipe.originalCustomRecipe, tracked_recipe.updatedCustomRecipe);
}
}
if (tracked_recipe.action == DataObjects.Action.Add)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Add Action called for " + tracked_recipe.prefab + " recipe"));
}
flag = AddRecipe(tracked_recipe.updatedRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Enable)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogWarning((object)("Enable Action called for " + tracked_recipe.prefab + " recipe. Are you sure you wanted that? Most recipes are already enabled."));
}
flag = EnableRecipe(tracked_recipe.originalRecipe);
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)$"{tracked_recipe.prefab} recipe update applied? {flag}");
}
}
public static void ReverseRecipeModifications(DataObjects.TrackedRecipe tracked_recipe)
{
bool flag = false;
if (tracked_recipe.action == DataObjects.Action.Disable)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Reverting disable for " + tracked_recipe.prefab + " recipe"));
}
flag = EnableRecipe(tracked_recipe.originalRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Delete)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Reverting delete for " + tracked_recipe.prefab + " recipe"));
}
flag = AddRecipe(tracked_recipe.originalRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Modify)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Reversing modify for " + tracked_recipe.prefab + " recipe"));
}
flag = ModifyRecipeInODB(tracked_recipe.updatedRecipe, tracked_recipe.originalRecipe);
ModifyRecipeInJotunnManager(tracked_recipe.updatedCustomRecipe, tracked_recipe.originalCustomRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Add)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Reverting add for " + tracked_recipe.prefab + " recipe"));
}
flag = DeleteRecipe(tracked_recipe.updatedRecipe);
}
if (tracked_recipe.action == DataObjects.Action.Enable)
{
flag = DisableRecipe(tracked_recipe.originalRecipe);
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)$"{tracked_recipe.prefab} recipe modification reverted? {flag}");
}
}
public static bool CheckIfRecipeWasModified(DataObjects.TrackedRecipe trackedRecipe)
{
bool flag = true;
if ((trackedRecipe.action == DataObjects.Action.Modify || trackedRecipe.action == DataObjects.Action.Delete) && ObjectDB.instance.m_recipes.IndexOf(trackedRecipe.originalRecipe) > 0)
{
flag = false;
}
if (trackedRecipe.action == DataObjects.Action.Add && ObjectDB.instance.m_recipes.IndexOf(trackedRecipe.updatedRecipe) < 0)
{
flag = false;
}
if (trackedRecipe.action == DataObjects.Action.Enable || trackedRecipe.action == DataObjects.Action.Disable)
{
flag = false;
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)$"recipe {trackedRecipe.recipeName} already modified? {flag}");
}
return flag;
}
public static void BuildRecipesForTracking()
{
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0266: Unknown result type (might be due to invalid IL or missing references)
//IL_0278: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Unknown result type (might be due to invalid IL or missing references)
//IL_029c: Unknown result type (might be due to invalid IL or missing references)
//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
//IL_02d5: Expected O, but got Unknown
//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
//IL_02d7: Expected O, but got Unknown
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Expected O, but got Unknown
if (RecipesToModify.Count == 0)
{
return;
}
TrackedRecipes.Clear();
foreach (KeyValuePair<string, DataObjects.RecipeModification> item2 in RecipesToModify)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)("Constructing modification details for " + item2.Key));
}
DataObjects.TrackedRecipe trackedRecipe = new DataObjects.TrackedRecipe();
trackedRecipe.action = item2.Value.action;
trackedRecipe.prefab = item2.Value.prefab;
int num = -1;
if (item2.Value.recipeName != null)
{
num = RecipeIndexForRecipeName(item2.Value.recipeName);
trackedRecipe.recipeName = item2.Value.recipeName;
}
if (num == -1)
{
num = RecipeIndexForPrefab(item2.Value.prefab);
}
if (num > -1)
{
trackedRecipe.originalRecipe = ObjectDB.instance.m_recipes[num];
}
else if (ValConfig.EnableDebugMode.Value)
{
Logger.LogWarning((object)("Could not find recipe for: " + item2.Value.prefab));
}
if (item2.Value.recipe != null)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Found custom recipe modifications, building out definition.");
}
RequirementConfig[] array = (RequirementConfig[])(object)new RequirementConfig[0];
if (!item2.Value.recipe.noRecipeCost)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Setting recipe cost requirements.");
}
array = (RequirementConfig[])(object)new RequirementConfig[item2.Value.recipe.ingredients.Count];
int num2 = 0;
foreach (DataObjects.Ingrediant ingredient in item2.Value.recipe.ingredients)
{
array[num2] = new RequirementConfig
{
Item = ingredient.prefab,
Amount = ingredient.craftCost,
AmountPerLevel = ingredient.upgradeCost,
Recover = false
};
num2++;
}
}
if (item2.Value.repairAt == null)
{
item2.Value.repairAt = item2.Value.craftedAt;
}
CustomRecipe val2 = new CustomRecipe(new RecipeConfig
{
Name = ((trackedRecipe.recipeName != null) ? trackedRecipe.recipeName : ("Recipe_" + item2.Value.prefab)),
Amount = item2.Value.craftAmount,
CraftingStation = item2.Value.craftedAt,
RepairStation = item2.Value.repairAt,
MinStationLevel = item2.Value.minStationLevel,
Enabled = (item2.Value.action != DataObjects.Action.Disable),
RequireOnlyOneIngredient = item2.Value.recipe.anyOneResource,
Requirements = array
});
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Built new custom recipe.");
}
Recipe recipe = val2.Recipe;
CustomItem item = ItemManager.Instance.GetItem(item2.Value.prefab);
if (item != null)
{
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Found existing custom item, storing for comparision.");
}
trackedRecipe.originalCustomRecipe = item.Recipe;
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Resolving references on custom recipe.");
}
if (item2.Value.craftedAt != null)
{
try
{
GameObject prefab = PrefabManager.Instance.GetPrefab(item2.Value.craftedAt);
CraftingStation val3 = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
if (item2.Value.craftedAt != item2.Value.repairAt)
{
GameObject prefab2 = PrefabManager.Instance.GetPrefab(item2.Value.repairAt);
if (prefab2 != null)
{
prefab2.GetComponent<CraftingStation>();
}
}
recipe.m_repairStation = val3;
recipe.m_craftingStation = val3;
}
catch
{
Logger.LogWarning((object)("Crafting station (" + item2.Value.craftedAt + ") or repair station (" + item2.Value.repairAt + ") could not be resolved or did not have a craftingStation component"));
}
}
if (item2.Value.repairAt != null)
{
try
{
GameObject prefab3 = PrefabManager.Instance.GetPrefab(item2.Value.repairAt);
CraftingStation repairStation = ((prefab3 != null) ? prefab3.GetComponent<CraftingStation>() : null);
recipe.m_repairStation = repairStation;
}
catch
{
Logger.LogWarning((object)("Repair station (" + item2.Value.repairAt + ") could not be resolved or did not have a craftingStation component"));
}
}
try
{
GameObject prefab4 = PrefabManager.Instance.GetPrefab(item2.Value.prefab);
ItemDrop component = prefab4.GetComponent<ItemDrop>();
if (!((Object)(object)component != (Object)null))
{
Logger.LogWarning((object)$"Could not find a prefab ({item2.Value.prefab}) GO ({prefab4}) with an ItemDrop ({component}) component to reference. This recipe will not have a target and will be skipped.");
continue;
}
recipe.m_item = component;
}
catch
{
Logger.LogWarning((object)("Could not find a prefab (" + item2.Value.prefab + ") with an ItemDrop component to reference. This recipe will not have a target and will be skipped."));
continue;
}
((Object)recipe).name = "Recipe_" + item2.Key;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Resolving resource requirement references.");
}
Requirement[] resources = recipe.m_resources;
foreach (Requirement val4 in resources)
{
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val4.m_resItem).name.Replace("JVLmock_", ""));
if ((Object)(object)itemPrefab != (Object)null)
{
val4.m_resItem = itemPrefab.GetComponent<ItemDrop>();
}
else
{
Logger.LogWarning((object)("Could not resolve itemdrop reference for: " + ((Object)val4.m_resItem).name + ". This requirement will be deleted."));
}
}
recipe.m_resources.Where((Requirement val) => ((object)val.m_resItem).GetType() == typeof(ItemDrop)).ToArray();
trackedRecipe.updatedRecipe = recipe;
trackedRecipe.updatedCustomRecipe = val2;
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Set updated recipe and updatedCustomRecipe.");
}
}
if (ValConfig.EnableDebugMode.Value)
{
Logger.LogInfo((object)"Adding tracked Recipe");
}
TrackedRecipes.Add(trackedRecipe);
}
}
public static int RecipeIndexForPrefab(string prefab)
{
return ObjectDB.instance.m_recipes.FindIndex((Recipe m) => (Object)(object)m.m_item != (Object)null && ((Object)m.m_item).name == prefab);
}
public static int RecipeIndexForRecipeName(string recipe_name)
{
return ObjectDB.instance.m_recipes.FindIndex((Recipe m) => ((Object)m).name != null && ((Object)m).name == recipe_name);
}
public static bool ModifyRecipeInJotunnManager(CustomRecipe recipe, CustomRecipe newRecipe)
{
if (AccessTools.Field(typeof(ItemManager), "Recipes").GetValue(ItemManager.Instance) is HashSet<CustomRecipe> hashSet)
{
if (hashSet.Contains(newRecipe))
{
return true;
}
if (hashSet.Contains(recipe))
{
hashSet.Remove(recipe);
hashSet.Add(newRecipe);
}
return true;
}
return false;
}
public static bool ModifyRecipeInODB(Recipe recipe, Recipe newRecipe)
{
int num = ObjectDB.instance.m_recipes.IndexOf(recipe);
if (num > -1)
{
ObjectDB.instance.m_recipes[num] = newRecipe;
return true;
}
return false;
}
public static bool DisableRecipe(Recipe recipe)
{
int num = ObjectDB.instance.m_recipes.IndexOf(recipe);
if (num > -1)
{
ObjectDB.instance.m_recipes[num].m_enabled = false;
return true;
}
return false;
}
public static bool EnableRecipe(Recipe recipe)
{
int num = ObjectDB.instance.m_recipes.IndexOf(recipe);
if (num > -1)
{
ObjectDB.instance.m_recipes[num].m_enabled = true;
return true;
}
return false;
}
public static bool DeleteRecipe(Recipe recipe)
{
return ObjectDB.instance.m_recipes.Remove(recipe);
}
public static bool AddRecipe(Recipe recipe)
{
if (!ObjectDB.instance.m_recipes.Contains(recipe))
{
ObjectDB.instance.m_recipes.Add(recipe);
}
return true;
}
public static void UpdateRecipeModifications(DataObjects.RecipeModificationCollection recipeMods)
{
RecipesToModify.Clear();
foreach (KeyValuePair<string, DataObjects.RecipeModification> recipeModification in recipeMods.RecipeModifications)
{
RecipesToModify.Add(recipeModification.Key, recipeModification.Value);
}
}
public static void UpdateRecipeModificationsFromList(List<DataObjects.RecipeModificationCollection> lRecipeMods)
{
RecipesToModify.Clear();
foreach (DataObjects.RecipeModificationCollection lRecipeMod in lRecipeMods)
{
foreach (KeyValuePair<string, DataObjects.RecipeModification> recipeModification in lRecipeMod.RecipeModifications)
{
RecipesToModify.Add(recipeModification.Key, recipeModification.Value);
}
}
}
}
}
namespace RecipeManager.Common
{
internal class ValConfig
{
[CompilerGenerated]
private sealed class <OnClientReceivePieceConfigs>d__26 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ZPackage package;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <OnClientReceivePieceConfigs>d__26(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
string text = package.ReadString();
PieceUpdater.RevertPieceModifications();
try
{
PieceUpdater.UpdatePieceModificationsFromRPC(text);
PieceUpdater.UpdatePieceModifications(yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(text));
}
catch
{
Logger.LogWarning("Recieved invalid configuration, all pieces reverted.");
}
PieceUpdater.BuildPieceTracker();
PieceUpdater.PieceUpdateRunner();
<>2__current = null;
<>1__state = 1;
return true;
}
case 1:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <OnClientReceiveRecipeConfigs>d__25 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ZPackage package;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <OnClientReceiveRecipeConfigs>d__25(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
string text = package.ReadString();
RecipeUpdater.RecipeRevert();
try
{
RecipeUpdater.UpdateRecipeModifications(yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(text));
}
catch
{
Logger.LogWarning("Recieved invalid configuration, all recipes reverted.");
}
RecipeUpdater.BuildRecipesForTracking();
RecipeUpdater.SecondaryRecipeSync();
<>2__current = null;
<>1__state = 1;
return true;
}
case 1:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <OnServerRecieveConfigs>d__20 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <OnServerRecieveConfigs>d__20(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (EnableDebugMode.Value)
{
Logger.LogInfo("Server recieved config from client, rejecting due to being the server.");
}
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public static ConfigFile cfg;
public static ConfigEntry<bool> EnableDebugMode;
public static string recipeConfigFilePath = Path.Combine(Paths.ConfigPath, "RecipeManager", "Recipes.yaml");
public static List<string> RecipeConfigFilePaths = new List<string>();
public static string pieceConfigFilePath = Path.Combine(Paths.ConfigPath, "RecipeManager", "Pieces.yaml");
public static List<string> PieceConfigFilePaths = new List<string>();
public static IDeserializer yamldeserializer = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
public static ISerializer yamlserializer = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).ConfigureDefaultValuesHandling((DefaultValuesHandling)2).Build();
private static CustomRPC RecipeConfigRPC;
private static CustomRPC PiecesConfigRPC;
public ValConfig(ConfigFile cfgref)
{
cfg = cfgref;
cfg.SaveOnConfigSet = true;
CreateConfigValues(cfgref);
SetupSecondaryConfigFile();
SetupConfigRPCs();
}
private void CreateConfigValues(ConfigFile Config)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging for Recipe Manager. This is client side and is not syncd with the server.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdvanced = true
} }));
EnableDebugMode.SettingChanged += Logger.enableDebugLogging;
Logger.CheckEnableDebugLogging();
}
private static void SetupSecondaryConfigFile()
{
string secondaryConfigDirectoryPath = GetSecondaryConfigDirectoryPath();
bool flag = false;
bool flag2 = false;
string[] files = Directory.GetFiles(secondaryConfigDirectoryPath);
foreach (string text in files)
{
if (text.Contains("Recipes.yaml") && !text.Contains("ObjectDBRecipes.yaml"))
{
if (EnableDebugMode.Value)
{
Logger.LogInfo("Found recipe configuration yaml: " + text);
}
RecipeConfigFilePaths.Add(text);
flag = true;
}
if (text.Contains("Pieces.yaml"))
{
if (EnableDebugMode.Value)
{
Logger.LogInfo("Found pieces configuration yaml: " + text);
}
PieceConfigFilePaths.Add(text);
flag2 = true;
}
}
if (!flag)
{
Logger.LogInfo("Recipe file missing, recreating.");
using StreamWriter streamWriter = new StreamWriter(recipeConfigFilePath);
string value = "#################################################\n# Recipe Manipulation Config\n#################################################\n# recipeModifications: # <- This is the top level key, all modifications live under this, it is required.\n# DisableWoodArrow: # <- This is the modification name, its primarily for you to understand what this modification does SHOULD BE UNIQUE\n# action: Disable # <- This is the action it should be one of [Disable, Delete, Modify, Add, Enable]\n# prefab: ArrowWood # <- This is the prefab that the modification will target\n# AddNewWoodArrowRecipe:\n# action: Add\n# prefab: ArrowWood\n# recipeName: Recipe_ArrowWood # <- optional, specifying the recipe name allows matching and mutating multiple recipes targeting the same prefab\n# craftedAt: Workbench # <- The crafting station that should craft this recipe, leave it empty or invalid for handcrafting\n# minStationLevel: 2 # <- This is the required crafting station level for discovery AND crafting\n# recipe: # <- When performing [Modify] or [Add] you should define a recipe\n# anyOneResource: false # <- This makes the recipe only require one ingrediant, first from the top will be used.\n# noRecipeCost: false # <- This makes the recipe not require any resources to craft, if this is used the ingredients list will be ignored\n# ingredients: # <- Ingrediants in the recipe, is an array\n# - prefab: Wood # <- Prefab that this ingrediant requires\n# craftCost: 2 # <- The amount of this ingrediant it takes to craft the recipe \n# upgradeCost: 0 # <- The amount of this ingrediant it takes to upgrade the item \n# - prefab: Feathers\n# craftCost: 2\n# upgradeCost: 0\n# DeleteTrollHideArmorRecipe:\n# action: Delete\n# prefab: CapeTrollHide\n# ModifyTrollHideChestRecipe:\n# action: Modify\n# prefab: ArmorTrollLeatherChest\n# craftedAt: Workbench\n# minStationLevel: 1\n# recipe:\n# anyOneResource: false\n# ingredients:\n# - prefab: TrollHide\n# craftCost: 4\n# upgradeCost: 2\n";
streamWriter.WriteLine(value);
streamWriter.WriteLine(YamlRecipeConfigDefinition());
}
if (!flag2)
{
Logger.LogInfo("Pieces file missing, recreating.");
using StreamWriter streamWriter2 = new StreamWriter(pieceConfigFilePath);
string value2 = "############################################################################\n# Piece Manipulation Config\n############################################################################\n# pieceModifications: # <- This is the top level key, it is required\n# modify_the_bed: # <- REQUIRED The name of this modification, it should be unique but is for your information\n# action: Enable # <- REQUIRED This is the action applied can be [Enable, Disable, Modify]\n# prefab: bed # <- REQUIRED This is the prefab that the action will be applied to\n# requirements: # <- If the piece is being modified, you can set requirements which will be the cost to build this\n# - prefab: Wood # <- Each requirement entry requires a prefab name, you can find item prefabs on the valheim wiki\n# amount: 8 # <- The amount of the prefab required\n# requiredToPlaceCraftingStation: piece_workbench # <- The crafting station used to place this item, if it is set to 'none' it will remove the station requirement\n# allowedInDungeon: false # <- If you can build this inside dungeons\n# canBeDeconstructed: true # <- If this can be broken with middle mouse\n# pieceCategory: Furniture # <- The category tab this will be placed in. This can be any of the categories across any available tools\n# comfortAmount: 1 # <- If above 0 this item will provide comfort\n# comfortGroup: Bed # <- The comfort group this is a part of\n# isUpgradeForStation: false # <- If this piece is considered an upgrade for a crafting station\n# craftingStationConnectionRadius: 0 # <- The radius that this will connect to a crafting station\n# mustBeAvobeConnectedStation: false # <- If this upgrade must be placed ABOVE its crafting station- this is normally only used for hanging upgrades for the cooking station\n# spaceRequired: 0 # <- How much space is required for this item\n# pieceName: $piece_bed # <- The localizable name for this, setting \"My Bed\" will make this piece called \"My Bed\"\n# pieceDescription: '' # <- The description for this piece, many pieces do not have this\n# enablePiece: true # <- Whether or not this piece is enabled\n# onlyInSelectBiome: None # <- Whether or not this can be placed in only one biome, in vanilla this is used for plants\n# cultivatedGroundOnly: false # <- Whether this piece needs to be placed on cultivated ground\n# groundPlacement: false # <- Whether this piece needs to be placed on ground (stone is also considered ground)";
streamWriter2.WriteLine(value2);
streamWriter2.WriteLine(YamlPieceConfigDefinition());
}
List<DataObjects.RecipeModificationCollection> list = new List<DataObjects.RecipeModificationCollection>();
foreach (string recipeConfigFilePath in RecipeConfigFilePaths)
{
string text2 = File.ReadAllText(recipeConfigFilePath);
try
{
DataObjects.RecipeModificationCollection item = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(text2);
list.Add(item);
}
catch (Exception arg)
{
Logger.LogError($"There was an error reading recipe data from {recipeConfigFilePath}, it will not be used. Error: {arg}");
}
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
fileSystemWatcher.Path = secondaryConfigDirectoryPath;
fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
fileSystemWatcher.Filter = DetermineFileName(recipeConfigFilePath) ?? "";
fileSystemWatcher.Changed += UpdateRecipeConfigFilesOnChange;
fileSystemWatcher.Created += UpdateRecipeConfigFilesOnChange;
fileSystemWatcher.Renamed += UpdateRecipeConfigFilesOnChange;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
RecipeUpdater.UpdateRecipeModificationsFromList(list);
List<DataObjects.PieceModificationCollection> list2 = new List<DataObjects.PieceModificationCollection>();
foreach (string pieceConfigFilePath in PieceConfigFilePaths)
{
string text3 = File.ReadAllText(pieceConfigFilePath);
try
{
DataObjects.PieceModificationCollection item2 = yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(text3);
list2.Add(item2);
}
catch (Exception arg2)
{
Logger.LogError($"There was an error reading piece data from {pieceConfigFilePath}, it will not be used. Error: {arg2}");
}
FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher();
fileSystemWatcher2.Path = secondaryConfigDirectoryPath;
fileSystemWatcher2.NotifyFilter = NotifyFilters.LastWrite;
fileSystemWatcher2.Filter = DetermineFileName(pieceConfigFilePath) ?? "";
fileSystemWatcher2.Changed += UpdatePieceConfigFilesOnChange;
fileSystemWatcher2.Created += UpdatePieceConfigFilesOnChange;
fileSystemWatcher2.Renamed += UpdatePieceConfigFilesOnChange;
fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher2.EnableRaisingEvents = true;
}
PieceUpdater.UpdatePieceModificationsFromList(list2);
}
internal static void ReloadPieceFiles()
{
List<DataObjects.PieceModificationCollection> list = new List<DataObjects.PieceModificationCollection>();
foreach (string pieceConfigFilePath in PieceConfigFilePaths)
{
string text = File.ReadAllText(pieceConfigFilePath);
try
{
DataObjects.PieceModificationCollection item = yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(text);
list.Add(item);
}
catch (Exception arg)
{
Logger.LogError($"There was an error reading piece data from {pieceConfigFilePath}, it will not be used. Error: {arg}");
}
}
PieceUpdater.UpdatePieceModificationsFromList(list);
}
internal static void ReloadRecipeFiles()
{
List<DataObjects.RecipeModificationCollection> list = new List<DataObjects.RecipeModificationCollection>();
foreach (string recipeConfigFilePath in RecipeConfigFilePaths)
{
string text = File.ReadAllText(recipeConfigFilePath);
try
{
DataObjects.RecipeModificationCollection item = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(text);
list.Add(item);
}
catch (Exception arg)
{
Logger.LogError($"There was an error reading recipe data from {recipeConfigFilePath}, it will not be used. Error: {arg}");
}
}
RecipeUpdater.UpdateRecipeModificationsFromList(list);
}
private static string DetermineFileName(string fullfilepath)
{
string[] array = fullfilepath.Split(new char[1] { '\\' });
if (array.Length < 2)
{
array = fullfilepath.Split(new char[1] { '/' });
}
Logger.LogInfo("File name check: " + string.Join(",", array));
return array[^2];
}
private static void UpdateRecipeConfigFilesOnChange(object sender, FileSystemEventArgs e)
{
if (!File.Exists(recipeConfigFilePath))
{
return;
}
if (EnableDebugMode.Value)
{
Logger.LogInfo($"{e} Recipe filewatcher called, updating recipe Modification values.");
}
RecipeUpdater.RecipeRevert();
RecipeUpdater.UpdateRecipeModifications(ReadAllRecipeConfigs());
RecipeUpdater.BuildRecipesForTracking();
RecipeUpdater.SecondaryRecipeSync();
if (EnableDebugMode.Value)
{
Logger.LogInfo("Updated RecipeModifications in-memory values.");
}
if (GUIManager.IsHeadless())
{
try
{
RecipeConfigRPC.SendPackage(ZNet.instance.m_peers, SendRecipeConfigs());
if (EnableDebugMode.Value)
{
Logger.LogInfo("Sent recipe configs to clients.");
}
return;
}
catch (Exception arg)
{
Logger.LogError($"Error while server syncing recipeModification configs: {arg}");
return;
}
}
if (EnableDebugMode.Value)
{
Logger.LogDebug("Instance is not a server, and will not send znet recipeModification updates.");
}
}
private static void UpdatePieceConfigFilesOnChange(object sender, FileSystemEventArgs e)
{
if (!File.Exists(pieceConfigFilePath))
{
return;
}
if (EnableDebugMode.Value)
{
Logger.LogInfo($"{e} Piece filewatcher called, updating piece Modification values.");
}
PieceUpdater.RevertPieceModifications();
PieceUpdater.UpdatePieceModifications(ReadAllPieceConfigs());
PieceUpdater.BuildPieceTracker();
PieceUpdater.PieceUpdateRunner();
if (EnableDebugMode.Value)
{
Logger.LogInfo("Updated RecipeModifications in-memory values.");
}
if (GUIManager.IsHeadless())
{
try
{
RecipeConfigRPC.SendPackage(ZNet.instance.m_peers, SendPieceConfigs());
if (EnableDebugMode.Value)
{
Logger.LogInfo("Sent levels configs to clients.");
}
return;
}
catch (Exception arg)
{
Logger.LogError($"Error while server syncing recipeModification configs: {arg}");
return;
}
}
if (EnableDebugMode.Value)
{
Logger.LogDebug("Instance is not a server, and will not send znet recipeModification updates.");
}
}
public static string GetSecondaryConfigDirectoryPath()
{
return Directory.CreateDirectory(Path.Combine(Paths.ConfigPath, "RecipeManager")).FullName;
}
public void SetupConfigRPCs()
{
//IL_0011: 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_0027: Expected O, but got Unknown
//IL_0027: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Expected O, but got Unknown
//IL_006e: Expected O, but got Unknown
RecipeConfigRPC = NetworkManager.Instance.AddRPC("recipeManager_recipes_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveRecipeConfigs));
SynchronizationManager.Instance.AddInitialSynchronization(RecipeConfigRPC, (Func<ZPackage>)SendRecipeConfigs);
PiecesConfigRPC = NetworkManager.Instance.AddRPC("recipeManager_pieces_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceivePieceConfigs));
SynchronizationManager.Instance.AddInitialSynchronization(PiecesConfigRPC, (Func<ZPackage>)SendPieceConfigs);
}
[IteratorStateMachine(typeof(<OnServerRecieveConfigs>d__20))]
public static IEnumerator OnServerRecieveConfigs(long sender, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <OnServerRecieveConfigs>d__20(0);
}
private static ZPackage SendRecipeConfigs()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
ZPackage val = new ZPackage();
val.Write(yamlserializer.Serialize((object)ReadAllRecipeConfigs()));
return val;
}
private static ZPackage SendPieceConfigs()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
ZPackage val = new ZPackage();
val.Write(yamlserializer.Serialize((object)ReadAllPieceConfigs()));
return val;
}
private static DataObjects.RecipeModificationCollection ReadAllRecipeConfigs()
{
List<DataObjects.RecipeModificationCollection> list = new List<DataObjects.RecipeModificationCollection>();
foreach (string recipeConfigFilePath in RecipeConfigFilePaths)
{
if (EnableDebugMode.Value)
{
Logger.LogDebug("Loading values from " + recipeConfigFilePath + ".");
}
string text = File.ReadAllText(recipeConfigFilePath);
try
{
DataObjects.RecipeModificationCollection item = yamldeserializer.Deserialize<DataObjects.RecipeModificationCollection>(text);
list.Add(item);
}
catch (Exception arg)
{
Logger.LogError($"There was an error reading recipe data from {recipeConfigFilePath}, it will not be used. Error: {arg}");
}
}
DataObjects.RecipeModificationCollection recipeModificationCollection = new DataObjects.RecipeModificationCollection();
foreach (DataObjects.RecipeModificationCollection item2 in list)
{
foreach (KeyValuePair<string, DataObjects.RecipeModification> recipeModification in item2.RecipeModifications)
{
recipeModificationCollection.RecipeModifications.Add(recipeModification.Key, recipeModification.Value);
}
}
return recipeModificationCollection;
}
private static DataObjects.PieceModificationCollection ReadAllPieceConfigs()
{
List<DataObjects.PieceModificationCollection> list = new List<DataObjects.PieceModificationCollection>();
foreach (string pieceConfigFilePath in PieceConfigFilePaths)
{
if (EnableDebugMode.Value)
{
Logger.LogDebug("Loading values from " + pieceConfigFilePath + ".");
}
string text = File.ReadAllText(pieceConfigFilePath);
try
{
DataObjects.PieceModificationCollection item = yamldeserializer.Deserialize<DataObjects.PieceModificationCollection>(text);
list.Add(item);
}
catch (Exception arg)
{
Logger.LogError($"There was an error reading piece data from {pieceConfigFilePath}, it will not be used. Error: {arg}");
}
}
DataObjects.PieceModificationCollection pieceModificationCollection = new DataObjects.PieceModificationCollection();
foreach (DataObjects.PieceModificationCollection item2 in list)
{
foreach (KeyValuePair<string, DataObjects.PieceModification> pieceModification in item2.PieceModifications)
{
pieceModificationCollection.PieceModifications.Add(pieceModification.Key, pieceModification.Value);
}
}
return pieceModificationCollection;
}
[IteratorStateMachine(typeof(<OnClientReceiveRecipeConfigs>d__25))]
private static IEnumerator OnClientReceiveRecipeConfigs(long sender, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <OnClientReceiveRecipeConfigs>d__25(0)
{
package = package
};
}
[IteratorStateMachine(typeof(<OnClientReceivePieceConfigs>d__26))]
private static IEnumerator OnClientReceivePieceConfigs(long sender, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <OnClientReceivePieceConfigs>d__26(0)
{
package = package
};
}
public static string YamlRecipeConfigDefinition()
{
DataObjects.RecipeModificationCollection recipeModificationCollection = new DataObjects.RecipeModificationCollection();
recipeModificationCollection.RecipeModifications = RecipeUpdater.RecipesToModify;
return yamlserializer.Serialize((object)recipeModificationCollection);
}
public static string YamlPieceConfigDefinition()
{
DataObjects.PieceModificationCollection pieceModificationCollection = new DataObjects.PieceModificationCollection();
pieceModificationCollection.PieceModifications = PieceUpdater.PiecesToModify;
return yamlserializer.Serialize((object)pieceModificationCollection);
}
public ConfigEntry<bool> BindServerConfig(string catagory, string key, bool value, string description, bool advanced = false)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected O, but got Unknown
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
return cfg.Bind<bool>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true,
IsAdvanced = advanced
} }));
}
public ConfigEntry<string> BindServerConfig(string catagory, string key, string value, string description, bool advanced = false)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected O, but got Unknown
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
return cfg.Bind<string>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true,
IsAdvanced = advanced
} }));
}
public ConfigEntry<short> BindServerConfig(string catagory, string key, short value, string description, bool advanced = false, short valmin = 0, short valmax = 150)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
return cfg.Bind<short>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<short>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true,
IsAdvanced = advanced
} }));
}
public ConfigEntry<float> BindServerConfig(string catagory, string key, float value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
return cfg.Bind<float>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true,
IsAdvanced = advanced
} }));
}
}
internal class DataObjects
{
public enum Action
{
Disable,
Delete,
Modify,
Add,
Enable
}
public enum PieceAction
{
Disable,
Modify,
Enable
}
public class TrackedPiece
{
public PieceAction action { get; set; }
public string prefab { get; set; }
public Piece originalPiece { get; set; }
public Requirement[] updatedRequirements { get; set; }
public CraftingStation RequiredToPlaceCraftingStation { get; set; }
public bool AllowedInDungeon { get; set; }
public bool CanBeDeconstructed { get; set; } = true;
public PieceCategory PieceCategory { get; set; } = (PieceCategory)100;
public int ComfortAmount { get; set; } = -1;
public ComfortGroup ComfortGroup { get; set; }
public bool IsUpgradeForStation { get; set; }
public float CraftingStationConnectionRadius { get; set; } = -1f;
public bool MustBeAvobeConnectedStation { get; set; }
public float SpaceRequired { get; set; } = -1f;
public string PieceName { get; set; }
public string PieceDescription { get; set; }
public bool EnablePiece { get; set; } = true;
public Biome OnlyInBiome { get; set; } = (Biome)895;
public bool CultivatedGroundOnly { get; set; }
public bool GroundPlacement { get; set; } = true;
}
[DataContract]
public class PieceModificationCollection
{
public Dictionary<string, PieceModification> PieceModifications { get; set; } = new Dictionary<string, PieceModification>();
}
[DataContract]
public class PieceModification
{
public PieceAction action { get; set; }
public string prefab { get; set; }
public List<SimpleRequirement> requirements { get; set; } = new List<SimpleRequirement>();
public string RequiredToPlaceCraftingStation { get; set; }
public bool AllowedInDungeon { get; set; }
public bool CanBeDeconstructed { get; set; } = true;
public PieceCategory PieceCategory { get; set; } = (PieceCategory)100;
public int ComfortAmount { get; set; } = -1;
public ComfortGroup ComfortGroup { get; set; }
public bool IsUpgradeForStation { get; set; }
public float CraftingStationConnectionRadius { get; set; } = -1f;
public bool MustBeAvobeConnectedStation { get; set; }
public float SpaceRequired { get; set; } = -1f;
public string PieceName { get; set; }
public string PieceDescription { get; set; }
public bool EnablePiece { get; set; } = true;
public Biome OnlyInSelectBiome { get; set; } = (Biome)895;
public bool CultivatedGroundOnly { get; set; }
public bool GroundPlacement { get; set; }
}
[DataContract]
public class SimpleRequirement
{
public string Prefab { get; set; }
public int amount { get; set; }
}
public class TrackedRecipe
{
public Action action { get; set; }
public string prefab { get; set; }
public string recipeName { get; set; }
public Recipe originalRecipe { get; set; }
public Recipe updatedRecipe { get; set; }
public CustomRecipe updatedCustomRecipe { get; set; }
public CustomRecipe originalCustomRecipe { get; set; }
}
[DataContract]
public class RecipeModificationCollection
{
public Dictionary<string, RecipeModification> RecipeModifications { get; set; } = new Dictionary<string, RecipeModification>();
}
[DataContract]
public class RecipeModification
{
public Action action { get; set; }
public string prefab { get; set; }
public string recipeName { get; set; }
public string craftedAt { get; set; }
public string repairAt { get; set; }
public short minStationLevel { get; set; } = 1;
public short craftAmount { get; set; } = 1;
public SimpleRecipe recipe { get; set; }
}
[DataContract]
public class SimpleRecipe
{
public bool anyOneResource { get; set; }
public bool noRecipeCost { get; set; }
public List<Ingrediant> ingredients { get; set; } = new List<Ingrediant>();
}
[DataContract]
public class Ingrediant
{
public string prefab { get; set; }
public short craftCost { get; set; }
public short upgradeCost { get; set; }
}
}
internal class Logger
{
public static LogLevel Level = (LogLevel)16;
public static void enableDebugLogging(object sender, EventArgs e)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
if (ValConfig.EnableDebugMode.Value)
{
Level = (LogLevel)32;
}
else
{
Level = (LogLevel)16;
}
}
public static void CheckEnableDebugLogging()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
if (ValConfig.EnableDebugMode.Value)
{
Level = (LogLevel)32;
}
else
{
Level = (LogLevel)16;
}
}
public static void LogDebug(string message)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
if ((int)Level >= 32)
{
RecipeManager.Log.LogInfo((object)message);
}
}
public static void LogInfo(string message)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
if ((int)Level >= 16)
{
RecipeManager.Log.LogInfo((object)message);
}
}
public static void LogWarning(string message)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
if ((int)Level >= 4)
{
RecipeManager.Log.LogWarning((object)message);
}
}
public static void LogError(string message)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
if ((int)Level >= 2)
{
RecipeManager.Log.LogError((object)message);
}
}
}
}