Decompiled source of Cart Control v0.4.3

FrizzQOL.CartControl.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("FrizzQOL.CartControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b5ff921dd55e0d4d16c1710703ae9d2ec02d8f4e")]
[assembly: AssemblyProduct("FrizzQOL.CartControl")]
[assembly: AssemblyTitle("FrizzQOL.CartControl")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 static class CartRules
{
	public const int MaxWidth = 8;

	public static int ResolveWidth(int config, int vanilla)
	{
		if (config <= 0)
		{
			return vanilla;
		}
		if (config > 8)
		{
			return 8;
		}
		return config;
	}

	public static int ResolveHeight(int config, int vanilla)
	{
		if (config > 0)
		{
			return config;
		}
		return vanilla;
	}

	public static float ResolveCartWeight(float config, float vanilla)
	{
		if (!(config < 0f))
		{
			return config;
		}
		return vanilla;
	}

	public static float ResolveCargoPull(float config, float vanilla)
	{
		if (!(config < 0f))
		{
			return config;
		}
		return vanilla;
	}

	public static float ResolvePullMass(float cartWeight, float vanillaCart, float cargoPull, float vanillaPull, float cargoWeight)
	{
		float num = ResolveCartWeight(cartWeight, vanillaCart);
		float num2 = ResolveCargoPull(cargoPull, vanillaPull);
		float num3 = ((cargoWeight > 0f) ? cargoWeight : 0f);
		return num + num3 * num2;
	}

	public static bool BlocksBreak(bool invincible)
	{
		return invincible;
	}

	public static bool? RemovalOverride(bool featureOn, bool isCart, bool inUse, bool duringWear)
	{
		if (duringWear || !featureOn || !isCart || inUse)
		{
			return null;
		}
		return true;
	}

	public static bool ShouldSpillCargo(bool featureOn, bool isCart, bool hammerRemove, bool blockDrop)
	{
		if (featureOn && isCart && hammerRemove)
		{
			return !blockDrop;
		}
		return false;
	}

	public static bool CanAddWeight(float currentWeight, float itemWeight, float maxWeight)
	{
		if (maxWeight <= 0f)
		{
			return true;
		}
		return currentWeight + itemWeight <= maxWeight;
	}
}
namespace CartControl
{
	internal static class CartApplier
	{
		private static readonly FieldInfo ContainerWidth = AccessTools.Field(typeof(Container), "m_width");

		private static readonly FieldInfo ContainerHeight = AccessTools.Field(typeof(Container), "m_height");

		private static readonly FieldInfo InventoryWidth = AccessTools.Field(typeof(Inventory), "m_width");

		private static readonly FieldInfo InventoryHeight = AccessTools.Field(typeof(Inventory), "m_height");

		private static readonly MethodInfo UpdateMass = AccessTools.Method(typeof(Vagon), "UpdateMass", (Type[])null, (Type[])null);

		public static void Apply(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return;
			}
			Vagon componentInParent = ((Component)container).GetComponentInParent<Vagon>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			CartCatalog.CartConfig cartConfig = CartCatalog.BindFromVagon(componentInParent);
			if (cartConfig == null)
			{
				return;
			}
			int num = CartRules.ResolveWidth(cartConfig.Width.Value, cartConfig.VanillaWidth);
			int num2 = CartRules.ResolveHeight(cartConfig.Height.Value, cartConfig.VanillaHeight);
			if (ContainerWidth != null)
			{
				ContainerWidth.SetValue(container, num);
			}
			if (ContainerHeight != null)
			{
				ContainerHeight.SetValue(container, num2);
			}
			Inventory inventory = container.GetInventory();
			if (inventory != null)
			{
				if (InventoryWidth != null)
				{
					InventoryWidth.SetValue(inventory, num);
				}
				inventory.SetHeight(num2);
				if (InventoryHeight != null)
				{
					InventoryHeight.SetValue(inventory, num2);
				}
				CartCatalog.RegisterInventory(inventory, CartCatalog.PrefabName(((Component)componentInParent).gameObject));
			}
			ApplyPull(componentInParent);
			if (AccessTools.Field(typeof(Vagon), "m_nview")?.GetValue(componentInParent) == null || UpdateMass == null)
			{
				return;
			}
			try
			{
				UpdateMass.Invoke(componentInParent, null);
			}
			catch (Exception ex)
			{
				Exception ex2 = ((ex is TargetInvocationException { InnerException: not null } ex3) ? ex3.InnerException : ex);
				Plugin.LogError("Cart pull weight was not applied: " + ex2.Message);
			}
		}

		public static void ApplyPull(Vagon cart)
		{
			if ((Object)(object)cart == (Object)null)
			{
				return;
			}
			CartCatalog.CartConfig cartConfig = CartCatalog.BindFromVagon(cart);
			if (cartConfig != null)
			{
				float cargoWeight = 0f;
				Container container = cart.m_container;
				if ((Object)(object)container != (Object)null && container.GetInventory() != null)
				{
					cargoWeight = container.GetInventory().GetTotalWeight();
				}
				float num = CartRules.ResolveCartWeight(cartConfig.CartWeight.Value, cartConfig.VanillaCartWeight);
				float num2 = CartRules.ResolveCargoPull(cartConfig.CargoPull.Value, cartConfig.VanillaCargoPull);
				cart.m_baseMass = num;
				cart.m_itemWeightMassFactor = num2;
				Plugin.LogPull(cart, num, num2, CartRules.ResolvePullMass(cartConfig.CartWeight.Value, cartConfig.VanillaCartWeight, cartConfig.CargoPull.Value, cartConfig.VanillaCargoPull, cargoWeight));
			}
		}

		public static void ApplyAllLoaded()
		{
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			if (array != null)
			{
				Container[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					Apply(array2[i]);
				}
			}
		}
	}
	internal static class CartCatalog
	{
		internal sealed class CartConfig
		{
			public int VanillaWidth;

			public int VanillaHeight;

			public float VanillaCartWeight;

			public float VanillaCargoPull;

			public ConfigEntry<int> Width;

			public ConfigEntry<int> Height;

			public ConfigEntry<float> CartWeight;

			public ConfigEntry<float> CargoWeight;

			public ConfigEntry<float> CargoPull;
		}

		private static ConfigFile _config;

		private static readonly Dictionary<string, CartConfig> Entries = new Dictionary<string, CartConfig>();

		private static readonly Dictionary<Inventory, string> Inventories = new Dictionary<Inventory, string>();

		public static void Initialize(ConfigFile config)
		{
			_config = config;
		}

		public static void DiscoverFromScene(ZNetScene scene)
		{
			if (_config == null || (Object)(object)scene == (Object)null || !(AccessTools.Field(typeof(ZNetScene), "m_prefabs")?.GetValue(scene) is List<GameObject> list))
			{
				return;
			}
			int num = 0;
			foreach (GameObject item in list)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item.GetComponent<Vagon>() == (Object)null) && Bind(item))
				{
					num++;
				}
			}
			if (num > 0)
			{
				Plugin.LogInfo("Bound config for " + num + " carts.");
			}
		}

		public static CartConfig BindFromVagon(Vagon cart)
		{
			if ((Object)(object)cart == (Object)null)
			{
				return null;
			}
			Bind(((Component)cart).gameObject);
			return Get(PrefabName(((Component)cart).gameObject));
		}

		public static CartConfig Get(string prefabName)
		{
			if (prefabName == null || !Entries.TryGetValue(prefabName, out var value))
			{
				return null;
			}
			return value;
		}

		public static void RegisterInventory(Inventory inventory, string prefabName)
		{
			if (inventory != null && !string.IsNullOrEmpty(prefabName))
			{
				Inventories[inventory] = prefabName;
			}
		}

		public static CartConfig GetForInventory(Inventory inventory)
		{
			if (inventory == null || !Inventories.TryGetValue(inventory, out var value))
			{
				return null;
			}
			return Get(value);
		}

		public static string PrefabName(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return null;
			}
			string name = ((Object)obj).name;
			int num = name.IndexOf("(Clone)");
			if (num < 0)
			{
				return name;
			}
			return name.Substring(0, num).Trim();
		}

		private static bool Bind(GameObject cartObj)
		{
			string text = PrefabName(cartObj);
			if (string.IsNullOrEmpty(text) || _config == null || Entries.ContainsKey(text))
			{
				return false;
			}
			Vagon component = cartObj.GetComponent<Vagon>();
			Container val = (((Object)(object)component != (Object)null) ? component.m_container : null);
			if ((Object)(object)val == (Object)null)
			{
				val = cartObj.GetComponentInChildren<Container>(true);
			}
			int num = (((Object)(object)val != (Object)null) ? ReadInt(val, "m_width", 6) : 6);
			int num2 = (((Object)(object)val != (Object)null) ? ReadInt(val, "m_height", 3) : 3);
			float num3 = (((Object)(object)component != (Object)null) ? component.m_baseMass : 20f);
			float vanillaCargoPull = (((Object)(object)component != (Object)null) ? component.m_itemWeightMassFactor : 1f);
			Entries[text] = new CartConfig
			{
				VanillaWidth = num,
				VanillaHeight = num2,
				VanillaCartWeight = num3,
				VanillaCargoPull = vanillaCargoPull,
				Width = _config.Bind<int>(text, "Width", num, "Storage columns. 1 to 8. 0 or less keeps the cart's normal width."),
				Height = _config.Bind<int>(text, "Height", num2, "Storage rows. 0 or less keeps the cart's normal height."),
				CartWeight = _config.Bind<float>(text, "CartWeight", num3, "Pull weight of the empty cart. 0 is weightless. Below 0 keeps the normal empty weight."),
				CargoWeight = _config.Bind<float>(text, "CargoWeight", 0f, "Most item weight this cart will hold. 0 or less means no storage limit. This does not change how heavy the cart feels to pull."),
				CargoPull = _config.Bind<float>(text, "CargoPull", 0.25f, "How much cargo weight counts while pulling. 1 is normal Valheim. 0.25 makes a full cart about one quarter as heavy and easier to steer. 0 means cargo adds no pull weight. Below 0 keeps the cart's normal pull.")
			};
			return true;
		}

		private static int ReadInt(object instance, string fieldName, int fallback)
		{
			FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), fieldName);
			object obj = ((fieldInfo != null) ? fieldInfo.GetValue(instance) : null);
			if (obj is int)
			{
				return (int)obj;
			}
			return fallback;
		}
	}
	internal static class CartDeconstruct
	{
		private static readonly Dictionary<string, bool> Originals = new Dictionary<string, bool>();

		private static readonly FieldInfo ContainerNview = AccessTools.Field(typeof(Container), "m_nview");

		private static readonly MethodInfo DropAllItems = AccessTools.Method(typeof(Container), "DropAllItems", Type.EmptyTypes, (Type[])null);

		internal static Vagon FindCart(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			Vagon component2 = component.GetComponent<Vagon>();
			if ((Object)(object)component2 != (Object)null)
			{
				return component2;
			}
			return component.GetComponentInParent<Vagon>();
		}

		internal static void ApplyAllLoaded(bool featureOn)
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ApplyPrefabs(ZNetScene.instance, featureOn);
			}
			Vagon[] array = Object.FindObjectsByType<Vagon>((FindObjectsSortMode)0);
			if (array == null)
			{
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					ApplyPiece(((Component)array[i]).gameObject, featureOn);
				}
			}
		}

		internal static void ApplyPrefabs(ZNetScene scene, bool featureOn)
		{
			if ((Object)(object)scene == (Object)null || !(AccessTools.Field(typeof(ZNetScene), "m_prefabs")?.GetValue(scene) is List<GameObject> list))
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				GameObject val = list[i];
				if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<Vagon>() != (Object)null)
				{
					ApplyPiece(val, featureOn);
				}
			}
		}

		internal static void ApplyPiece(GameObject cartObject, bool featureOn)
		{
			if ((Object)(object)cartObject == (Object)null)
			{
				return;
			}
			Piece[] array = cartObject.GetComponentsInChildren<Piece>(true);
			if (array == null || array.Length == 0)
			{
				Piece componentInParent = cartObject.GetComponentInParent<Piece>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					return;
				}
				array = (Piece[])(object)new Piece[1] { componentInParent };
			}
			string text = CartCatalog.PrefabName(cartObject);
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			foreach (Piece val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					if (!Originals.ContainsKey(text))
					{
						Originals[text] = val.m_canBeRemoved;
					}
					val.m_canBeRemoved = featureOn || Originals[text];
				}
			}
		}

		internal static bool AllowDestroy(WearNTear wear, bool featureOn, bool hammerRemove, bool blockDrop)
		{
			if (!featureOn || !hammerRemove || blockDrop)
			{
				return true;
			}
			Vagon val = FindCart((Component)(object)wear);
			if (!CartRules.ShouldSpillCargo(featureOn, (Object)(object)val != (Object)null, hammerRemove, blockDrop))
			{
				return true;
			}
			if (DropAllItems == null)
			{
				Plugin.LogError("Container.DropAllItems() was not found. Cart was not removed.");
				return false;
			}
			Container[] componentsInChildren = ((Component)val).GetComponentsInChildren<Container>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (!TryDrop(componentsInChildren[i]))
				{
					return false;
				}
			}
			return true;
		}

		private static bool TryDrop(Container chest)
		{
			if ((Object)(object)chest == (Object)null || chest.GetInventory() == null)
			{
				return true;
			}
			object? obj = ContainerNview?.GetValue(chest);
			ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null);
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner())
			{
				return true;
			}
			try
			{
				DropAllItems.Invoke(chest, null);
				return true;
			}
			catch (Exception ex)
			{
				Exception ex2 = ((ex is TargetInvocationException { InnerException: not null } ex3) ? ex3.InnerException : ex);
				Plugin.LogError("Cargo drop failed. Cart was not removed: " + ex2.Message);
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakePatch
	{
		private static void Postfix(ZNetScene __instance)
		{
			CartCatalog.DiscoverFromScene(__instance);
			CartDeconstruct.ApplyPrefabs(__instance, Plugin.FeatureOn());
		}
	}
	[HarmonyPatch(typeof(Vagon), "UpdateMass")]
	internal static class VagonUpdateMassPatch
	{
		private static void Prefix(Vagon __instance)
		{
			try
			{
				CartApplier.ApplyPull(__instance);
			}
			catch (Exception ex)
			{
				Plugin.LogError("Cart pull weight was not applied: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear), "ApplyDamage")]
	internal static class CartBreakPatch
	{
		private static bool Prefix(WearNTear __instance, ref bool __result)
		{
			if (Plugin.Invincible == null || !CartRules.BlocksBreak(Plugin.Invincible.Value))
			{
				return true;
			}
			if (!IsCart(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool IsCart(WearNTear wear)
		{
			if ((Object)(object)wear == (Object)null)
			{
				return false;
			}
			if (!((Object)(object)((Component)wear).GetComponent<Vagon>() != (Object)null))
			{
				return (Object)(object)((Component)wear).GetComponentInParent<Vagon>() != (Object)null;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Vagon), "Awake")]
	internal static class VagonAwakePatch
	{
		private static void Postfix(Vagon __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				CartDeconstruct.ApplyPiece(((Component)__instance).gameObject, Plugin.FeatureOn());
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
	internal static class WearNTearUpdateWearPatch
	{
		[ThreadStatic]
		private static int s_depth;

		internal static bool IsActive => s_depth > 0;

		private static void Prefix()
		{
			s_depth++;
		}

		private static Exception Finalizer(Exception __exception)
		{
			if (s_depth > 0)
			{
				s_depth--;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "RPC_Remove")]
	internal static class WearNTearRpcRemovePatch
	{
		[ThreadStatic]
		private static int s_depth;

		internal static bool IsActive => s_depth > 0;

		private static void Prefix()
		{
			s_depth++;
		}

		private static Exception Finalizer(Exception __exception)
		{
			if (s_depth > 0)
			{
				s_depth--;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Piece), "CanBeRemoved")]
	internal static class PieceCanBeRemovedPatch
	{
		private static void Postfix(Piece __instance, ref bool __result)
		{
			try
			{
				if (!WearNTearUpdateWearPatch.IsActive && !((Object)(object)__instance == (Object)null))
				{
					Vagon val = CartDeconstruct.FindCart((Component)(object)__instance);
					bool? flag = CartRules.RemovalOverride(Plugin.FeatureOn(), (Object)(object)val != (Object)null, inUse: false, duringWear: false);
					if (flag.HasValue)
					{
						__result = flag.Value;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.LogError("Cart remove check failed: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Destroy")]
	internal static class WearNTearDestroyPatch
	{
		private static bool Prefix(WearNTear __instance, bool blockDrop)
		{
			try
			{
				return CartDeconstruct.AllowDestroy(__instance, Plugin.FeatureOn(), WearNTearRpcRemovePatch.IsActive, blockDrop);
			}
			catch (Exception ex)
			{
				Plugin.LogError("Cart remove failed: " + ex.Message);
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "Awake")]
	internal static class PieceAwakePatch
	{
		private static void Postfix(Piece __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && Plugin.FeatureOn() && !((Object)(object)CartDeconstruct.FindCart((Component)(object)__instance) == (Object)null))
			{
				__instance.m_canBeRemoved = true;
			}
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class ContainerAwakePatch
	{
		private static void Postfix(Container __instance)
		{
			CartApplier.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	internal static class CanAddItemPatch
	{
		private static bool Prefix(Inventory __instance, ItemData __0, int __1, ref bool __result)
		{
			if (CargoGate.Allows(__instance, CargoGate.ItemWeight(__0, __1)))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	internal static class AddItemPatch
	{
		private static bool Prefix(Inventory __instance, ItemData __0)
		{
			return CargoGate.Allows(__instance, CargoGate.ItemWeight(__0, __0?.m_stack ?? 0));
		}
	}
	internal static class CargoGate
	{
		public static bool Allows(Inventory inventory, float itemWeight)
		{
			CartCatalog.CartConfig forInventory = CartCatalog.GetForInventory(inventory);
			if (forInventory == null)
			{
				return true;
			}
			return CartRules.CanAddWeight(inventory.GetTotalWeight(), itemWeight, forInventory.CargoWeight.Value);
		}

		public static float ItemWeight(ItemData item, int stack)
		{
			if (item == null || item.m_shared == null)
			{
				return 0f;
			}
			int num = ((stack <= 0) ? 1 : stack);
			return item.m_shared.m_weight * (float)num;
		}
	}
	[BepInPlugin("com.frizzqol.cartcontrol", "FrizzQOL Cart Control", "0.4.3")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.frizzqol.cartcontrol";

		public const string PluginName = "FrizzQOL Cart Control";

		public const string PluginVersion = "0.4.3";

		private static readonly HashSet<string> _pullLogs = new HashSet<string>();

		internal static Plugin Instance { get; private set; }

		internal static ConfigEntry<bool> Invincible { get; private set; }

		internal static ConfigEntry<bool> HammerDeconstruct { get; private set; }

		private void Awake()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			Instance = this;
			Invincible = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Invincible", true, "On by default. Carts take no damage and do not wear down, so they cannot break. Set this to false to use normal cart breaking.");
			HammerDeconstruct = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HammerDeconstruct", true, "On by default. Hammer middle-click empties a cart onto the ground, then removes the cart and returns its materials.");
			CartCatalog.Initialize(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				CartApplier.ApplyAllLoaded();
				CartDeconstruct.ApplyAllLoaded(FeatureOn());
			};
			Harmony val = new Harmony("com.frizzqol.cartcontrol");
			try
			{
				val.PatchAll();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"FrizzQOL Cart Control 0.4.3 loaded");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Harmony patch failed: " + ex.Message));
			}
		}

		internal static bool FeatureOn()
		{
			if (HammerDeconstruct != null)
			{
				return HammerDeconstruct.Value;
			}
			return false;
		}

		internal static void LogInfo(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogPull(Vagon cart, float empty, float cargoPull, float pullMass)
		{
			if (!((Object)(object)Instance == (Object)null) && !((Object)(object)cart == (Object)null))
			{
				string item = ((Object)cart).GetInstanceID() + ":" + empty.ToString("0.##") + ":" + cargoPull.ToString("0.##") + ":" + pullMass.ToString("0.##");
				if (_pullLogs.Add(item))
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)(CartCatalog.PrefabName(((Component)cart).gameObject) + " pull mass " + pullMass.ToString("0.##") + " (empty " + empty.ToString("0.##") + ", cargo factor " + cargoPull.ToString("0.##") + ")."));
				}
			}
		}

		internal static void LogError(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)message);
			}
		}

		internal static void LogWarning(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)message);
			}
		}
	}
}