Decompiled source of TorvaldsAffordablePainters v1.3.0

plugins/torvalds-painters.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("torvalds-painters")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("torvalds-painters")]
[assembly: AssemblyCopyright("Copyright \ufffd  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
public static class MaterialManExtensions
{
	public static PropertyContainer GetPropertyContainer(this MaterialMan materialManager, GameObject gameObject)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		int instanceID = ((Object)gameObject).GetInstanceID();
		if (!materialManager.m_blocks.TryGetValue(instanceID, out var value))
		{
			gameObject.AddComponent<MaterialManNotifier>();
			value = new PropertyContainer(gameObject, materialManager.m_propertyBlock);
			PropertyContainer obj = value;
			obj.MarkDirty = (Action<PropertyContainer>)Delegate.Combine(obj.MarkDirty, new Action<PropertyContainer>(materialManager.QueuePropertyUpdate));
			materialManager.m_blocks.Add(instanceID, value);
		}
		return value;
	}

	public static PropertyContainer SetValue<T>(this PropertyContainer propertyContainer, int propertyId, T value)
	{
		propertyContainer.SetValue<T>(propertyId, value);
		return propertyContainer;
	}
}
namespace TorvaldsPainters;

public class ConfigurationManagerAttributes
{
	public bool? IsAdminOnly { get; set; }

	public bool? IsAdvanced { get; set; }

	public int? Order { get; set; }

	public bool? Browsable { get; set; }

	public string Category { get; set; }

	public Action<ConfigEntryBase> CustomDrawer { get; set; }
}
public class PickerCloser : MonoBehaviour
{
	public Action OnClose;

	private void Update()
	{
		if (ZInput.GetKeyDown((KeyCode)27, true))
		{
			Close();
		}
	}

	public void Close()
	{
		OnClose?.Invoke();
		GUIManager.BlockInput(false);
		Object.Destroy((Object)(object)((Component)this).gameObject);
	}
}
public enum LogLevel
{
	None,
	Basic,
	Detailed,
	Debug
}
[Flags]
public enum BuildCategory
{
	None = 0,
	Building = 1,
	Furniture = 2,
	Crafting = 4,
	Misc = 8,
	All = 0xF
}
[Flags]
public enum FunctionalBucket
{
	None = 0,
	Stations = 1,
	Production = 2,
	Storage = 4,
	Beds = 8,
	PortalsWard = 0x10,
	Lighting = 0x20,
	SignsStands = 0x40,
	Transport = 0x80,
	Defenses = 0x100,
	All = -1
}
[Flags]
public enum MaterialBucket
{
	Unknown = 0,
	Wood = 1,
	Stone = 2,
	Metal = 4,
	Marble = 8,
	All = -1
}
[BepInPlugin("cebero.TorvaldsAffordablePainters", "Torvald's Affordable Painters", "1.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class TorvaldsPainters : BaseUnityPlugin
{
	public struct PieceAttributes
	{
		public string Prefab;

		public BuildCategory Category;

		public FunctionalBucket Functional;

		public MaterialBucket Material;

		public bool HasRenderer;

		public bool HasValidZNV;

		public bool ComfortGiving;
	}

	public const string PluginGUID = "cebero.TorvaldsAffordablePainters";

	public const string PluginName = "Torvald's Affordable Painters";

	public const string PluginVersion = "1.3.0";

	private static ConfigEntry<string> RecipeConfig;

	private static ConfigEntry<bool> RequireWorkbenchConfig;

	private static ConfigEntry<string> DarkBrownRGBMultiplierConfig;

	private static ConfigEntry<string> MediumBrownRGBMultiplierConfig;

	private static ConfigEntry<string> NaturalWoodRGBMultiplierConfig;

	private static ConfigEntry<string> LightBrownRGBMultiplierConfig;

	private static ConfigEntry<string> PaleWoodRGBMultiplierConfig;

	private static ConfigEntry<string> BlackRGBMultiplierConfig;

	private static ConfigEntry<string> WhiteRGBMultiplierConfig;

	private static ConfigEntry<string> RedRGBMultiplierConfig;

	private static ConfigEntry<string> BlueRGBMultiplierConfig;

	private static ConfigEntry<string> GreenRGBMultiplierConfig;

	private static ConfigEntry<string> YellowRGBMultiplierConfig;

	private static ConfigEntry<string> OrangeRGBMultiplierConfig;

	private static ConfigEntry<string> PurpleRGBMultiplierConfig;

	private static ConfigEntry<LogLevel> LogLevelConfig;

	private static ConfigEntry<float> MaxPaintDistanceConfig;

	private static ConfigEntry<bool> RequireBuildPermissionConfig;

	private static ConfigEntry<BuildCategory> AllowedCategoriesConfig;

	private static ConfigEntry<FunctionalBucket> ExcludedFunctionalConfig;

	private static ConfigEntry<MaterialBucket> AllowedMaterialsConfig;

	private static ConfigEntry<string> WhitelistPrefabsConfig;

	private static ConfigEntry<string> BlacklistPrefabsConfig;

	public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

	private Harmony harmony;

	public static readonly Dictionary<string, Color> VikingColors = new Dictionary<string, Color>();

	public static string currentSelectedColor = "Natural Wood";

	public static int colorIndex = 2;

	internal static readonly Dictionary<int, (string color, float t)> _lastApply = new Dictionary<int, (string, float)>();

	internal const float HighlightReapplyMinInterval = 0.25f;

	private static readonly int PaintPieceMask = LayerMask.GetMask(new string[5] { "piece", "piece_nonsolid", "Default", "Default_small", "static_solid" });

	private static readonly RaycastHit[] _hitsBuf = (RaycastHit[])(object)new RaycastHit[16];

	private static HashSet<string> _whitelist;

	private static HashSet<string> _blacklist;

	private static HashSet<int> _buildingCats;

	private static int _craftingCat;

	private static int _furnitureCat;

	private static int _miscCat;

	private static bool _categoriesInitialized = false;

	private static CustomPieceTable paintingPieceTable;

	public GameObject colorPickerPanel;

	public static TorvaldsPainters Instance { get; private set; }

	private void Awake()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		Instance = this;
		Logger.LogInfo((object)"\ud83c\udfa8 Torvald's Affordable Painters is loading...");
		InitializeConfiguration();
		InitializeColorsFromConfig();
		harmony = new Harmony("cebero.TorvaldsAffordablePainters");
		harmony.PatchAll();
		PrefabManager.OnVanillaPrefabsAvailable += AddCustomItems;
		PrefabManager.OnVanillaPrefabsAvailable += InitializeCategoryMapping;
		Logger.LogInfo((object)"\ud83c\udfa8 Torvald's Affordable Painters ready for business!");
	}

	private void InitializeConfiguration()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Expected O, but got Unknown
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Expected O, but got Unknown
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Expected O, but got Unknown
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Expected O, but got Unknown
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Expected O, but got Unknown
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Expected O, but got Unknown
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Expected O, but got Unknown
		//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Expected O, but got Unknown
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Expected O, but got Unknown
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Expected O, but got Unknown
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03af: Expected O, but got Unknown
		//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Expected O, but got Unknown
		//IL_0414: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Expected O, but got Unknown
		//IL_0466: Unknown result type (might be due to invalid IL or missing references)
		//IL_0470: Expected O, but got Unknown
		//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b0: Expected O, but got Unknown
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04db: Expected O, but got Unknown
		//IL_0500: Unknown result type (might be due to invalid IL or missing references)
		//IL_050a: Expected O, but got Unknown
		//IL_052c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0536: Expected O, but got Unknown
		//IL_055b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0565: Expected O, but got Unknown
		//IL_058a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0594: Expected O, but got Unknown
		RecipeConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Materials", "Wood:10,LeatherScraps:5,Coal:1", new ConfigDescription("Recipe materials in format: Material1:Amount1,Material2:Amount2,etc.\nExamples:\n- Early game: \"Wood:10,LeatherScraps:5,Coal:1\"\n- Mid game: \"FineWood:8,Bronze:2,LeatherScraps:3\"\n- Late game: \"BlackMetal:1,Silver:2,LoxPelt:1\"\nUse exact Valheim item names (case sensitive)", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		RequireWorkbenchConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Recipe", "RequireWorkbench", true, new ConfigDescription("Whether the painting mallet requires a workbench to craft", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		DarkBrownRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.WoodTones", "DarkBrownRGBMultiplier", "0.45,0.25,0.15", new ConfigDescription("RGB multiplier values for Dark Brown wood effect (format: R,G,B with values 0.0-3.0)\nValues <1.0 darken, 1.0 = unchanged, >1.0 brighten. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		MediumBrownRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.WoodTones", "MediumBrownRGBMultiplier", "1.2,0.8,0.4", new ConfigDescription("RGB multiplier values for Medium Brown wood effect (format: R,G,B with values 0.0-3.0)\nValues <1.0 darken, 1.0 = unchanged, >1.0 brighten. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		NaturalWoodRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.WoodTones", "NaturalWoodRGBMultiplier", "1.0,1.0,1.0", new ConfigDescription("RGB multiplier values for Natural Wood - leaves texture unchanged (format: R,G,B)\n1.0,1.0,1.0 = original texture with no modifications.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		LightBrownRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.WoodTones", "LightBrownRGBMultiplier", "1.3,1.1,0.8", new ConfigDescription("RGB multiplier values for Light Brown wood effect (format: R,G,B with values 0.0-3.0)\nValues <1.0 darken, 1.0 = unchanged, >1.0 brighten. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		PaleWoodRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.WoodTones", "PaleWoodRGBMultiplier", "1.1,1.4,1.9", new ConfigDescription("RGB multiplier values for Pale Wood effect (format: R,G,B with values 0.0-3.0)\nValues <1.0 darken, 1.0 = unchanged, >1.0 brighten. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		BlackRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "BlackRGBMultiplier", "0.1,0.1,0.1", new ConfigDescription("RGB multiplier values for Black paint effect (format: R,G,B with values 0.0-3.0)\nLow values create dark colors. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		WhiteRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "WhiteRGBMultiplier", "1.55,1.75,1.95", new ConfigDescription("RGB multiplier values for White paint effect (format: R,G,B with values 0.0-3.0)\nHigh values create bright/white colors. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		RedRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "RedRGBMultiplier", "1.5,0.2,0.2", new ConfigDescription("RGB multiplier values for Red paint effect (format: R,G,B with values 0.0-3.0)\nBoost red channel, reduce green/blue for red tint. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		BlueRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "BlueRGBMultiplier", "0.2,0.3,1.5", new ConfigDescription("RGB multiplier values for Blue paint effect (format: R,G,B with values 0.0-3.0)\nBoost blue channel, reduce red/green for blue tint. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		GreenRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "GreenRGBMultiplier", "0.3,1.5,0.3", new ConfigDescription("RGB multiplier values for Green paint effect (format: R,G,B with values 0.0-3.0)\nBoost green channel, reduce red/blue for green tint. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		YellowRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "YellowRGBMultiplier", "1.8,1.6,0.2", new ConfigDescription("RGB multiplier values for Yellow paint effect (format: R,G,B with values 0.0-3.0)\nBoost red/green channels, reduce blue for yellow tint. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		OrangeRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "OrangeRGBMultiplier", "1.5,0.9,0.25", new ConfigDescription("RGB multiplier values for Orange paint effect (format: R,G,B with values 0.0-3.0)\nBoost red, moderate green, low blue for orange tint. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		PurpleRGBMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Colors.PaintColors", "PurpleRGBMultiplier", "1.2,0.5,1.4", new ConfigDescription("RGB multiplier values for Purple paint effect (format: R,G,B with values 0.0-3.0)\nBoost red/blue channels, reduce green for purple tint. Multiplies with base texture.", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		LogLevelConfig = ((BaseUnityPlugin)this).Config.Bind<LogLevel>("Debug", "LogLevel", LogLevel.Basic, new ConfigDescription("Debug logging level: None (0), Basic (1), Detailed (2), Debug (3)\n- None: No debug logging\n- Basic: Basic operations and errors only\n- Detailed: Detailed operations and validation info\n- Debug: Everything including raycast details", (AcceptableValueBase)null, Array.Empty<object>()));
		MaxPaintDistanceConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Debug", "MaxPaintDistance", 8f, new ConfigDescription("Maximum distance for painting objects (meters)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		RequireBuildPermissionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "RequireBuildPermission", true, new ConfigDescription("Require build permission to paint objects (recommended for multiplayer)", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			}
		}));
		AllowedCategoriesConfig = ((BaseUnityPlugin)this).Config.Bind<BuildCategory>("Filtering", "AllowedCategories", BuildCategory.Building | BuildCategory.Furniture, new ConfigDescription("Which vanilla hammer categories are paintable.\nValid flags: Building, Furniture, Crafting, Misc, All", (AcceptableValueBase)null, Array.Empty<object>()));
		ExcludedFunctionalConfig = ((BaseUnityPlugin)this).Config.Bind<FunctionalBucket>("Filtering", "ExcludedFunctional", FunctionalBucket.Stations | FunctionalBucket.Production | FunctionalBucket.Storage | FunctionalBucket.Beds | FunctionalBucket.PortalsWard | FunctionalBucket.Transport, new ConfigDescription("Functional groups to exclude even if their category is allowed.\nValid flags: Stations, Production, Storage, Beds, PortalsWard, Lighting, SignsStands, Transport, Defenses, All, None", (AcceptableValueBase)null, Array.Empty<object>()));
		AllowedMaterialsConfig = ((BaseUnityPlugin)this).Config.Bind<MaterialBucket>("Filtering", "AllowedMaterials", MaterialBucket.Wood | MaterialBucket.Stone | MaterialBucket.Marble, new ConfigDescription("Material families that are paintable.\nValid flags: Wood, Stone, Metal, Marble, All", (AcceptableValueBase)null, Array.Empty<object>()));
		WhitelistPrefabsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Filtering", "WhitelistPrefabs", "", new ConfigDescription("Comma-separated prefab names to always allow painting.\nThese override all other filtering rules.\nExample: piece_chest,portal_wood", (AcceptableValueBase)null, Array.Empty<object>()));
		BlacklistPrefabsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Filtering", "BlacklistPrefabs", "", new ConfigDescription("Comma-separated prefab names to always exclude from painting.\nThese override all other filtering rules (including whitelist).\nExample: piece_workbench,piece_forge", (AcceptableValueBase)null, Array.Empty<object>()));
		Logger.LogDebug((object)"⚙\ufe0f Configuration loaded successfully!");
		RebuildNameSets();
		WhitelistPrefabsConfig.SettingChanged += delegate
		{
			RebuildNameSets();
		};
		BlacklistPrefabsConfig.SettingChanged += delegate
		{
			RebuildNameSets();
		};
		DarkBrownRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		MediumBrownRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		NaturalWoodRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		LightBrownRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		PaleWoodRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		BlackRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		WhiteRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		RedRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		BlueRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		GreenRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		YellowRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		OrangeRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
		PurpleRGBMultiplierConfig.SettingChanged += delegate
		{
			InitializeColorsFromConfig();
		};
	}

	private void InitializeColorsFromConfig()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: 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_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		VikingColors["Dark Brown"] = ParseColorFromConfig(DarkBrownRGBMultiplierConfig.Value, new Color(0.45f, 0.25f, 0.15f));
		VikingColors["Medium Brown"] = ParseColorFromConfig(MediumBrownRGBMultiplierConfig.Value, new Color(1.2f, 0.8f, 0.4f));
		VikingColors["Natural Wood"] = ParseColorFromConfig(NaturalWoodRGBMultiplierConfig.Value, new Color(1f, 1f, 1f));
		VikingColors["Light Brown"] = ParseColorFromConfig(LightBrownRGBMultiplierConfig.Value, new Color(1.3f, 1.1f, 0.8f));
		VikingColors["Pale Wood"] = ParseColorFromConfig(PaleWoodRGBMultiplierConfig.Value, new Color(1.1f, 1.4f, 1.9f));
		VikingColors["Black"] = ParseColorFromConfig(BlackRGBMultiplierConfig.Value, new Color(0.1f, 0.1f, 0.1f));
		VikingColors["White"] = ParseColorFromConfig(WhiteRGBMultiplierConfig.Value, new Color(1.55f, 1.75f, 1.95f));
		VikingColors["Red"] = ParseColorFromConfig(RedRGBMultiplierConfig.Value, new Color(1.5f, 0.2f, 0.2f));
		VikingColors["Blue"] = ParseColorFromConfig(BlueRGBMultiplierConfig.Value, new Color(0.2f, 0.3f, 1.5f));
		VikingColors["Green"] = ParseColorFromConfig(GreenRGBMultiplierConfig.Value, new Color(0.3f, 1.5f, 0.3f));
		VikingColors["Yellow"] = ParseColorFromConfig(YellowRGBMultiplierConfig.Value, new Color(1.8f, 1.6f, 0.2f));
		VikingColors["Orange"] = ParseColorFromConfig(OrangeRGBMultiplierConfig.Value, new Color(1.5f, 0.9f, 0.25f));
		VikingColors["Purple"] = ParseColorFromConfig(PurpleRGBMultiplierConfig.Value, new Color(1.2f, 0.5f, 1.4f));
		Logger.LogDebug((object)"\ud83c\udfa8 RGB multiplier values loaded from configuration!");
	}

	private Color ParseColorFromConfig(string colorString, Color defaultColor)
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			string[] array = colorString.Split(new char[1] { ',' });
			if (array.Length == 3 && float.TryParse(array[0], out var result) && float.TryParse(array[1], out var result2) && float.TryParse(array[2], out var result3))
			{
				result = Mathf.Clamp(result, 0f, 3f);
				result2 = Mathf.Clamp(result2, 0f, 3f);
				result3 = Mathf.Clamp(result3, 0f, 3f);
				return new Color(result, result2, result3);
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("⚠\ufe0f Invalid RGB multiplier format '" + colorString + "', using default: " + ex.Message));
		}
		return defaultColor;
	}

	private static void RebuildNameSets()
	{
		_whitelist = BuildNameSet(WhitelistPrefabsConfig.Value);
		_blacklist = BuildNameSet(BlacklistPrefabsConfig.Value);
		Logger.LogDebug((object)$"Rebuilt name sets: {_whitelist.Count} whitelist, {_blacklist.Count} blacklist");
	}

	private static void InitializeCategoryMapping()
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Expected I4, but got Unknown
		if (_categoriesInitialized)
		{
			return;
		}
		try
		{
			List<PieceCategory> list = Enum.GetValues(typeof(PieceCategory)).Cast<PieceCategory>().ToList();
			Logger.LogDebug((object)("Available piece categories: " + string.Join(", ", list)));
			_miscCat = GetCategoryByName(list, "Misc");
			_craftingCat = GetCategoryByName(list, "Crafting");
			_furnitureCat = GetCategoryByName(list, "Furniture");
			_buildingCats = new HashSet<int>();
			foreach (PieceCategory item in list)
			{
				PieceCategory current = item;
				string text = ((object)(PieceCategory)(ref current)).ToString();
				if (text.IndexOf("Building", StringComparison.OrdinalIgnoreCase) >= 0 || text.Equals("Building", StringComparison.OrdinalIgnoreCase))
				{
					_buildingCats.Add((int)current);
				}
			}
			if (_buildingCats.Count == 0)
			{
				_buildingCats.Add(0);
			}
			Logger.LogDebug((object)string.Format("Category mapping: Misc={0}, Crafting={1}, Furniture={2}, Building=[{3}]", _miscCat, _craftingCat, _furnitureCat, string.Join(",", _buildingCats)));
			_categoriesInitialized = true;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Failed to initialize category mapping: " + ex.Message));
			_miscCat = 0;
			_craftingCat = 1;
			_furnitureCat = 2;
			_buildingCats = new HashSet<int> { 3 };
			_categoriesInitialized = true;
		}
	}

	private static int GetCategoryByName(List<PieceCategory> categories, string targetName)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: 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_0029: Expected I4, but got Unknown
		foreach (PieceCategory category in categories)
		{
			PieceCategory current = category;
			if (((object)(PieceCategory)(ref current)).ToString().Equals(targetName, StringComparison.OrdinalIgnoreCase))
			{
				return (int)current;
			}
		}
		return 0;
	}

	private static HashSet<string> BuildNameSet(string csv)
	{
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		if (string.IsNullOrWhiteSpace(csv))
		{
			return hashSet;
		}
		string[] array = csv.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			hashSet.Add(text.Trim());
		}
		return hashSet;
	}

	private static string GetPrefabNameStable(Piece piece)
	{
		ZNetView component = ((Component)piece).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid())
		{
			try
			{
				return component.GetPrefabName();
			}
			catch
			{
			}
		}
		return Utils.GetPrefabName(((Component)piece).gameObject);
	}

	private static BuildCategory MapCategory(Piece piece)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected I4, but got Unknown
		if (!_categoriesInitialized)
		{
			Logger.LogError((object)"Category mapping not initialized - using fallback");
			return BuildCategory.None;
		}
		int num = (int)piece.m_category;
		if (_buildingCats.Contains(num))
		{
			return BuildCategory.Building;
		}
		if (num == _craftingCat)
		{
			return BuildCategory.Crafting;
		}
		if (num == _furnitureCat)
		{
			return BuildCategory.Furniture;
		}
		if (num == _miscCat)
		{
			return BuildCategory.Misc;
		}
		Logger.LogDebug((object)$"Unknown piece category ID {num} for piece '{((Object)piece).name}'");
		return BuildCategory.None;
	}

	private static FunctionalBucket DetectFunctionalBuckets(Piece piece)
	{
		GameObject gameObject = ((Component)piece).gameObject;
		FunctionalBucket functionalBucket = FunctionalBucket.None;
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<CraftingStation>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<StationExtension>()))
		{
			functionalBucket |= FunctionalBucket.Stations;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Smelter>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Fermenter>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<CookingStation>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Windmill>()))
		{
			functionalBucket |= FunctionalBucket.Production;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Container>()))
		{
			functionalBucket |= FunctionalBucket.Storage;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Bed>()))
		{
			functionalBucket |= FunctionalBucket.Beds;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<TeleportWorld>()) || HasWardComponent(gameObject))
		{
			functionalBucket |= FunctionalBucket.PortalsWard;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Fireplace>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Light>()))
		{
			functionalBucket |= FunctionalBucket.Lighting;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Sign>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<ItemStand>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<ArmorStand>()))
		{
			functionalBucket |= FunctionalBucket.SignsStands;
		}
		if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Ship>()) || Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren<Vagon>()))
		{
			functionalBucket |= FunctionalBucket.Transport;
		}
		if (MightBeDefense(piece))
		{
			functionalBucket |= FunctionalBucket.Defenses;
		}
		return functionalBucket;
		static bool HasWardComponent(GameObject g)
		{
			return (Object)(object)g.GetComponentInChildren<PrivateArea>() != (Object)null;
		}
		static bool MightBeDefense(Piece p)
		{
			string prefabNameStable = GetPrefabNameStable(p);
			if (prefabNameStable.IndexOf("stake", StringComparison.OrdinalIgnoreCase) < 0 && prefabNameStable.IndexOf("spike", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return prefabNameStable.IndexOf("ballista", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}
	}

	private static bool HasComponentNamed(GameObject go, string typeName)
	{
		MonoBehaviour[] components = go.GetComponents<MonoBehaviour>();
		foreach (MonoBehaviour val in components)
		{
			if ((Object)(object)val != (Object)null)
			{
				Type type = ((object)val).GetType();
				if (type != null && type.Name.Equals(typeName, StringComparison.Ordinal))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static MaterialBucket MapMaterialBucket(Piece piece)
	{
		WearNTear component = ((Component)piece).GetComponent<WearNTear>();
		if ((Object)(object)component != (Object)null)
		{
			return ((object)(MaterialType)(ref component.m_materialType)).ToString() switch
			{
				"Wood" => MaterialBucket.Wood, 
				"Stone" => MaterialBucket.Stone, 
				"Iron" => MaterialBucket.Metal, 
				"Marble" => MaterialBucket.Marble, 
				"BlackMarble" => MaterialBucket.Marble, 
				_ => MaterialBucket.Unknown, 
			};
		}
		return MaterialBucket.Unknown;
	}

	private static PieceAttributes Classify(Piece piece)
	{
		PieceAttributes result = default(PieceAttributes);
		result.Prefab = GetPrefabNameStable(piece);
		result.Category = MapCategory(piece);
		result.Functional = DetectFunctionalBuckets(piece);
		result.Material = MapMaterialBucket(piece);
		result.HasRenderer = (Object)(object)((Component)piece).GetComponentInChildren<MeshRenderer>() != (Object)null || (Object)(object)((Component)piece).GetComponentInChildren<SkinnedMeshRenderer>() != (Object)null;
		ZNetView component = ((Component)piece).GetComponent<ZNetView>();
		result.HasValidZNV = component != null && component.IsValid();
		result.ComfortGiving = piece.m_comfort > 0;
		return result;
	}

	public static bool IsPaintableByPolicy(Piece piece, Vector3 hitPos, out string reason)
	{
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		reason = "";
		if ((Object)(object)piece == (Object)null)
		{
			reason = "Not a building piece";
			return false;
		}
		PieceAttributes attrs = Classify(piece);
		BuildCategory value = AllowedCategoriesConfig.Value;
		FunctionalBucket value2 = ExcludedFunctionalConfig.Value;
		MaterialBucket value3 = AllowedMaterialsConfig.Value;
		Logger.LogDebug((object)$"Policy check: '{attrs.Prefab}' Category={attrs.Category} Functional={attrs.Functional} Material={attrs.Material}");
		if (_blacklist.Contains(attrs.Prefab))
		{
			reason = "Excluded by blacklist configuration";
			Logger.LogDebug((object)("Policy: '" + attrs.Prefab + "' blacklisted"));
			return false;
		}
		if (_whitelist.Contains(attrs.Prefab))
		{
			Logger.LogDebug((object)("Policy: '" + attrs.Prefab + "' whitelisted - allowing"));
			return FinalChecks(piece, attrs, hitPos, ref reason);
		}
		if ((value & attrs.Category) == 0)
		{
			reason = $"Category '{attrs.Category}' not allowed";
			Logger.LogDebug((object)$"Policy: '{attrs.Prefab}' category '{attrs.Category}' not in allowed categories '{value}'");
			return false;
		}
		if ((attrs.Functional & value2) != 0)
		{
			FunctionalBucket functionalBucket = attrs.Functional & value2;
			reason = $"Functional group excluded: {functionalBucket}";
			Logger.LogDebug((object)$"Policy: '{attrs.Prefab}' has excluded functional components: {functionalBucket}");
			return false;
		}
		if (attrs.Material != 0 && (value3 & attrs.Material) == 0)
		{
			reason = $"Material '{attrs.Material}' not allowed";
			Logger.LogDebug((object)$"Policy: '{attrs.Prefab}' material '{attrs.Material}' not in allowed materials '{value3}'");
			return false;
		}
		Logger.LogDebug((object)("Policy: '" + attrs.Prefab + "' passed all policy checks"));
		return FinalChecks(piece, attrs, hitPos, ref reason);
	}

	private static bool FinalChecks(Piece piece, PieceAttributes attrs, Vector3 hitPos, ref string reason)
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		if (!attrs.HasRenderer)
		{
			reason = "Object has no renderers to paint";
			Logger.LogDebug((object)("FinalChecks: '" + attrs.Prefab + "' has no renderers"));
			return false;
		}
		if (!attrs.HasValidZNV)
		{
			reason = "Object cannot sync in multiplayer";
			Logger.LogDebug((object)("FinalChecks: '" + attrs.Prefab + "' missing/invalid ZNetView"));
			return false;
		}
		if (RequireBuildPermissionConfig.Value && !PrivateArea.CheckAccess(hitPos, 0f, true, false))
		{
			reason = "No build permission for this area";
			Logger.LogDebug((object)$"FinalChecks: '{attrs.Prefab}' denied by PrivateArea at {hitPos}");
			return false;
		}
		Logger.LogDebug((object)("FinalChecks: '" + attrs.Prefab + "' passed all final checks"));
		return true;
	}

	private static GameObject GetPaintableObjectAtLook(out string errorMessage, out float distance)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		errorMessage = "";
		distance = 0f;
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			errorMessage = "No local player found";
			Logger.LogError((object)"GetPaintableObjectAtLook: No local player found");
			return null;
		}
		Camera mainCamera = Utils.GetMainCamera();
		if (!Object.op_Implicit((Object)(object)mainCamera))
		{
			errorMessage = "No main camera found";
			Logger.LogError((object)"GetPaintableObjectAtLook: No main camera found");
			return null;
		}
		Ray val = mainCamera.ScreenPointToRay(Input.mousePosition);
		Logger.LogDebug((object)$"GetPaintableObjectAtLook: Ray origin={((Ray)(ref val)).origin}, direction={((Ray)(ref val)).direction}");
		float value = MaxPaintDistanceConfig.Value;
		Logger.LogDebug((object)"GetPaintableObjectAtLook: Using PaintPieceMask for layers: piece, piece_nonsolid, Default, Default_small, static_solid");
		int num = Physics.RaycastNonAlloc(val, _hitsBuf, value, PaintPieceMask, (QueryTriggerInteraction)1);
		if (num <= 0)
		{
			errorMessage = "No objects found in range";
			Logger.LogDebug((object)$"GetPaintableObjectAtLook: No raycast hits found (maxDistance={value})");
			return null;
		}
		Logger.LogDebug((object)$"GetPaintableObjectAtLook: Found {num} raycast hits");
		Array.Sort(_hitsBuf, 0, num, Comparer<RaycastHit>.Create((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)));
		for (int i = 0; i < num; i++)
		{
			RaycastHit val2 = _hitsBuf[i];
			distance = ((RaycastHit)(ref val2)).distance;
			Logger.LogDebug((object)$"GetPaintableObjectAtLook: Hit {i}: object='{((Object)((RaycastHit)(ref val2)).collider).name}', distance={((RaycastHit)(ref val2)).distance:F2}m, layer={((Component)((RaycastHit)(ref val2)).collider).gameObject.layer} ({LayerMask.LayerToName(((Component)((RaycastHit)(ref val2)).collider).gameObject.layer)})");
			Piece componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Piece>();
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				Logger.LogDebug((object)$"GetPaintableObjectAtLook: Hit {i} '{((Object)((RaycastHit)(ref val2)).collider).name}' has no Piece component in parent");
				continue;
			}
			Logger.LogDebug((object)("GetPaintableObjectAtLook: Found Piece component on '" + ((Object)componentInParent).name + "'"));
			if (IsPaintableByPolicy(componentInParent, ((RaycastHit)(ref val2)).point, out var reason))
			{
				Logger.LogDebug((object)$"GetPaintableObjectAtLook: Found paintable piece '{((Object)componentInParent).name}' at {((RaycastHit)(ref val2)).distance:F2}m");
				return ((Component)componentInParent).gameObject;
			}
			Logger.LogDebug((object)("GetPaintableObjectAtLook: Piece '" + ((Object)componentInParent).name + "' rejected by policy: " + reason));
			errorMessage = reason;
			return null;
		}
		errorMessage = ((num == 1) ? "Object cannot be painted" : $"None of the {num} objects found can be painted");
		Logger.LogDebug((object)("GetPaintableObjectAtLook: " + errorMessage));
		return null;
	}

	private static string GetUserFriendlyErrorMessage(string technicalError)
	{
		if (string.IsNullOrEmpty(technicalError))
		{
			return "$paint_cannot_paint";
		}
		if (technicalError.Contains("No objects found in range"))
		{
			return "❌ No objects in range to paint";
		}
		if (technicalError.Contains("Not a building piece"))
		{
			return "❌ Can only paint building pieces";
		}
		if (technicalError.Contains("too far"))
		{
			return "❌ Too far away to paint";
		}
		if (technicalError.Contains("No build permission"))
		{
			return "❌ No permission to paint here";
		}
		if (technicalError.Contains("exclusion list"))
		{
			return "❌ This object is excluded from painting";
		}
		if (technicalError.Contains("Functional pieces"))
		{
			return "❌ Cannot paint functional objects";
		}
		if (technicalError.Contains("This type of object cannot be painted"))
		{
			return "❌ This object type cannot be painted";
		}
		if (technicalError.Contains("Object has no renderers"))
		{
			return "❌ Object cannot be painted";
		}
		if (technicalError.Contains("cannot sync in multiplayer"))
		{
			return "❌ Object not compatible with multiplayer painting";
		}
		if (technicalError.Contains("None of the") && technicalError.Contains("objects found can be painted"))
		{
			return "❌ No paintable objects found";
		}
		if (technicalError.StartsWith("Object '") && technicalError.Contains("cannot be painted"))
		{
			return "❌ Selected object cannot be painted";
		}
		return "$paint_cannot_paint";
	}

	private void ApplyRecipeFromConfig(ItemConfig itemConfig)
	{
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Expected O, but got Unknown
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Expected O, but got Unknown
		try
		{
			string value = RecipeConfig.Value;
			Logger.LogDebug((object)("\ud83d\udccb Parsing recipe: " + value));
			if (string.IsNullOrWhiteSpace(value))
			{
				Logger.LogWarning((object)"⚠\ufe0f Recipe config is empty, using default recipe");
				ApplyDefaultRecipe(itemConfig);
				return;
			}
			string[] array = value.Split(new char[1] { ',' });
			int num = 0;
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				string text = array2[i].Trim();
				if (string.IsNullOrWhiteSpace(text))
				{
					continue;
				}
				string[] array3 = text.Split(new char[1] { ':' });
				if (array3.Length != 2)
				{
					Logger.LogWarning((object)("⚠\ufe0f Invalid recipe format: '" + text + "' (expected Material:Amount)"));
					continue;
				}
				string text2 = array3[0].Trim();
				if (!int.TryParse(array3[1].Trim(), out var result) || result <= 0)
				{
					Logger.LogWarning((object)("⚠\ufe0f Invalid amount for material '" + text2 + "': '" + array3[1] + "'"));
				}
				else if (ValidateMaterialName(text2))
				{
					itemConfig.AddRequirement(new RequirementConfig(text2, result, 0, true));
					num++;
					Logger.LogDebug((object)$"✅ Added recipe requirement: {text2} x{result}");
				}
				else
				{
					Logger.LogWarning((object)("⚠\ufe0f Potentially invalid material name: '" + text2 + "' (added anyway - check spelling!)"));
					itemConfig.AddRequirement(new RequirementConfig(text2, result, 0, true));
					num++;
				}
			}
			if (num == 0)
			{
				Logger.LogWarning((object)"⚠\ufe0f No valid materials found in recipe config, using default recipe");
				ApplyDefaultRecipe(itemConfig);
			}
			else
			{
				Logger.LogDebug((object)$"\ud83c\udfa8 Successfully applied recipe with {num} materials");
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("❌ Error parsing recipe config: " + ex.Message));
			Logger.LogWarning((object)"\ud83d\udd27 Falling back to default recipe");
			ApplyDefaultRecipe(itemConfig);
		}
	}

	private bool ValidateMaterialName(string materialName)
	{
		if (string.IsNullOrWhiteSpace(materialName))
		{
			return false;
		}
		string[] array = new string[50]
		{
			"Wood", "Stone", "Flint", "Coal", "Resin", "LeatherScraps", "DeerHide", "BoarHide", "WolfHide", "LoxPelt",
			"FineWood", "CoreWood", "ElderBark", "YggdrasilWood", "Copper", "Tin", "Bronze", "Iron", "Silver", "BlackMetal",
			"CopperOre", "TinOre", "IronOre", "SilverOre", "BlackMetalOre", "Chitin", "Carapace", "Scale_Hide", "Crystal", "Obsidian",
			"Amber", "AmberPearl", "GreydwarfEye", "SurtlingCore", "AncientSeed", "WitheredBone", "TrophyDeer", "TrophyBoar", "TrophyNeck", "TrophyGreydwarf",
			"Feathers", "Guck", "Bloodbag", "Ooze", "Chain", "Nails", "IronNails", "LinenThread", "JuteRed", "JuteBlue"
		};
		foreach (string b in array)
		{
			if (string.Equals(materialName, b, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
		}
		if (materialName.Length >= 2 && materialName.Length <= 50 && !materialName.Contains(":"))
		{
			return !materialName.Contains(",");
		}
		return false;
	}

	private void ApplyDefaultRecipe(ItemConfig itemConfig)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Expected O, but got Unknown
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		itemConfig.AddRequirement(new RequirementConfig("Wood", 10, 0, true));
		itemConfig.AddRequirement(new RequirementConfig("LeatherScraps", 5, 0, true));
		itemConfig.AddRequirement(new RequirementConfig("Coal", 1, 0, true));
		Logger.LogDebug((object)"\ud83d\udd27 Applied default recipe: Wood x10, LeatherScraps x5, Coal x1");
	}

	private void AddCustomItems()
	{
		try
		{
			CreatePaintingMalletTable();
			CreatePaintingMallet();
			RegisterInputs();
			Logger.LogInfo((object)"✅ Custom painting mallet created successfully!");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("❌ Error creating custom items: " + ex.Message));
		}
	}

	private void CreatePaintingMalletTable()
	{
		//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_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		PieceTableConfig val = new PieceTableConfig
		{
			UseCategories = false,
			UseCustomCategories = false,
			CustomCategories = Array.Empty<string>(),
			CanRemovePieces = false
		};
		paintingPieceTable = new CustomPieceTable("_PaintTable", val);
		PieceConfig val2 = new PieceConfig
		{
			Name = "$item_painting_mallet",
			Description = "$item_painting_mallet_desc",
			PieceTable = "_PaintTable",
			Category = "Misc"
		};
		CustomPiece val3 = new CustomPiece("PaintMode", "piece_repair", val2);
		PieceManager.Instance.AddPiece(val3);
		PieceManager.Instance.AddPieceTable(paintingPieceTable);
		Logger.LogDebug((object)"\ud83c\udfa8 Created piece table with default Paint Mode piece");
	}

	private void CreatePaintingMallet()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = PrefabManager.Instance.CreateClonedPrefab("TorvaldsMallet", "Hammer");
		if (!Object.op_Implicit((Object)(object)val))
		{
			Logger.LogError((object)"Could not clone hammer for painting mallet");
			return;
		}
		ItemConfig val2 = new ItemConfig
		{
			Name = "$item_painting_mallet",
			Description = "$item_painting_mallet_desc"
		};
		ApplyRecipeFromConfig(val2);
		if (RequireWorkbenchConfig.Value)
		{
			val2.CraftingStation = "piece_workbench";
			Logger.LogDebug((object)"\ud83d\udd28 Workbench requirement enabled for painting mallet");
		}
		else
		{
			Logger.LogDebug((object)"\ud83d\udeab No crafting station required for painting mallet");
		}
		CustomItem val3 = new CustomItem(val, true, val2);
		ItemManager.Instance.AddItem(val3);
		Logger.LogDebug((object)("\ud83c\udfaf Added mallet to ItemManager - ID: " + val3.ItemDrop.m_itemData.m_shared.m_name));
		SharedData shared = val3.ItemDrop.m_itemData.m_shared;
		shared.m_buildPieces = paintingPieceTable.PieceTable;
		shared.m_itemType = (ItemType)19;
		shared.m_useDurability = true;
		shared.m_maxDurability = 200f;
		shared.m_durabilityPerLevel = 50f;
		shared.m_canBeReparied = true;
		shared.m_toolTier = 2;
		shared.m_damages = default(DamageTypes);
		shared.m_blockPower = 0f;
		shared.m_timedBlockBonus = 0f;
		shared.m_deflectionForce = 0f;
		shared.m_attack.m_attackAnimation = "";
		shared.m_attack.m_attackStamina = 0f;
		shared.m_attack.m_attackRange = 0f;
		shared.m_secondaryAttack.m_attackAnimation = "";
		Logger.LogDebug((object)"\ud83c\udfa8 Created proper painting mallet tool with empty piece table");
		CustomizePaintingMalletAppearance(val3.ItemPrefab);
		AddLocalization();
	}

	private void AddLocalization()
	{
		CustomLocalization localization = Localization;
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "item_painting_mallet", "Torvald's Painting Mallet" },
			{ "item_painting_mallet_desc", "A fine mallet from Torvald's Affordable Painters! Left-click to paint building pieces, right-click to select colors." },
			{ "paint_apply_hint", "Apply Paint" },
			{ "paint_select_color_hint", "Select Color" },
			{ "paint_applied", "\ud83c\udfa8 Painted with" },
			{ "paint_cannot_paint", "❌ Cannot paint this object" },
			{ "paint_color_picker_title", "Select Paint Color" },
			{ "paint_wood_stains_section", "Wood Stains" },
			{ "paint_colors_section", "Paint Colors" },
			{ "paint_close_button", "Close" }
		});
	}

	internal static void OnRpcSetColor(long sender, ZDOID id, string colorName)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
		{
			return;
		}
		GameObject val = null;
		if ((Object)(object)ZNetScene.instance != (Object)null)
		{
			val = ZNetScene.instance.FindInstance(id);
		}
		if ((Object)(object)val == (Object)null)
		{
			Logger.LogDebug((object)$"TP_SetColor: Instance not found for ZDOID {id}");
			return;
		}
		Piece componentInParent = val.GetComponentInParent<Piece>();
		if ((Object)(object)componentInParent == (Object)null)
		{
			Logger.LogDebug((object)("TP_SetColor: No Piece component found on " + ((Object)val).name));
			return;
		}
		ApplyColorToPiece(componentInParent, colorName, persistToZdo: false, logOnApply: false);
		Logger.LogDebug((object)("TP_SetColor: Applied " + colorName + " to " + ((Object)componentInParent).name + " from RPC"));
	}

	private static Sprite LoadPngSpriteFromFile(string fileName, float ppu = 100f)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		Logger.LogDebug((object)("\ud83d\udd0d Attempting to load icon from path: " + fileName));
		Sprite val = AssetUtils.LoadSpriteFromFile(fileName, new Vector2(0.5f, 0.5f));
		if ((Object)(object)val != (Object)null)
		{
			string name = ((Object)val).name;
			Rect rect = val.rect;
			object arg = ((Rect)(ref rect)).width;
			rect = val.rect;
			Logger.LogDebug((object)$"✅ Successfully loaded sprite: {name} ({arg}x{((Rect)(ref rect)).height})");
		}
		else
		{
			Logger.LogWarning((object)("❌ Failed to load sprite from: " + fileName));
		}
		return val;
	}

	private void CustomizePaintingMalletAppearance(GameObject malletPrefab)
	{
		ItemDrop component = malletPrefab.GetComponent<ItemDrop>();
		if (!((Object)(object)component != (Object)null))
		{
			return;
		}
		SharedData shared = component.m_itemData.m_shared;
		string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
		Logger.LogDebug((object)("Available embedded resources: " + string.Join(", ", manifestResourceNames)));
		Logger.LogDebug((object)$"Number of resources found: {manifestResourceNames.Length}");
		Sprite val = null;
		string[] array = new string[4] { "mallet.png", "cebero-TorvaldsAffordablePainters/mallet.png", "torvalds-painters/mallet.png", "../mallet.png" };
		foreach (string text in array)
		{
			val = LoadPngSpriteFromFile(text);
			if ((Object)(object)val != (Object)null)
			{
				Logger.LogInfo((object)("\ud83c\udfa8 Successfully loaded custom icon from: " + text));
				break;
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			shared.m_icons = (Sprite[])(object)new Sprite[1] { val };
			Logger.LogInfo((object)"\ud83c\udfa8 Applied custom icon for painting mallet");
		}
		else
		{
			Logger.LogWarning((object)"⚠\ufe0f Custom icon not found; leaving default hammer icon.");
		}
	}

	public static void ApplyColorToPiece(Piece piece, string colorName, bool persistToZdo = true, bool logOnApply = true)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		if (!VikingColors.TryGetValue(colorName, out var value))
		{
			return;
		}
		WearNTear component = ((Component)piece).GetComponent<WearNTear>();
		if (Object.op_Implicit((Object)(object)component) && ((int)component.m_materialType == 1 || ((object)(MaterialType)(ref component.m_materialType)).ToString().Contains("Marble")))
		{
			value *= 0.9f;
		}
		if ((Object)(object)MaterialMan.instance != (Object)null)
		{
			MaterialMan.instance.GetPropertyContainer(((Component)piece).gameObject).SetValue<Color>(ShaderProps._Color, value);
		}
		else
		{
			MeshRenderer[] componentsInChildren = ((Component)piece).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer obj in componentsInChildren)
			{
				MaterialPropertyBlock val = new MaterialPropertyBlock();
				val.SetColor("_Color", value);
				((Renderer)obj).SetPropertyBlock(val);
			}
		}
		if (persistToZdo)
		{
			ZNetView component2 = ((Component)piece).GetComponent<ZNetView>();
			ZDO val2 = ((component2 != null) ? component2.GetZDO() : null);
			if (val2 != null && !string.Equals(val2.GetString("TorvaldsPainters.Color", ""), colorName, StringComparison.Ordinal))
			{
				val2.Set("TorvaldsPainters.Color", colorName);
			}
		}
		if (logOnApply)
		{
			Logger.LogDebug((object)("Applied " + colorName + " to piece " + ((Object)piece).name));
		}
	}

	private void RegisterInputs()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		KeyHintManager instance = KeyHintManager.Instance;
		KeyHintConfig val = new KeyHintConfig();
		val.Item = "TorvaldsMallet";
		val.ButtonConfigs = (ButtonConfig[])(object)new ButtonConfig[2]
		{
			new ButtonConfig
			{
				Name = "Attack",
				HintToken = "$paint_apply_hint"
			},
			new ButtonConfig
			{
				Name = "Block",
				HintToken = "$paint_select_color_hint"
			}
		};
		instance.AddKeyHint(val);
		Logger.LogDebug((object)"\ud83c\udfa8 Registered painting mallet key hints");
	}

	public void PaintAtLook()
	{
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		Logger.LogDebug((object)"PaintAtLook: Paint attempt started");
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			Logger.LogError((object)"PaintAtLook: No local player found");
			return;
		}
		string errorMessage;
		float distance;
		GameObject paintableObjectAtLook = GetPaintableObjectAtLook(out errorMessage, out distance);
		if ((Object)(object)paintableObjectAtLook == (Object)null)
		{
			string userFriendlyErrorMessage = GetUserFriendlyErrorMessage(errorMessage);
			((Character)localPlayer).Message((MessageType)1, userFriendlyErrorMessage, 0, (Sprite)null);
			Logger.LogDebug((object)("PaintAtLook: Failed - " + errorMessage));
			return;
		}
		Piece componentInParent = paintableObjectAtLook.GetComponentInParent<Piece>();
		if ((Object)(object)componentInParent == (Object)null)
		{
			Logger.LogError((object)"PaintAtLook: Object passed validation but has no Piece component - this should not happen");
			((Character)localPlayer).Message((MessageType)1, "$paint_cannot_paint", 0, (Sprite)null);
			return;
		}
		try
		{
			ApplyColorToPiece(componentInParent, currentSelectedColor);
			ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid() && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "TP_SetColor", new object[2]
				{
					component.GetZDO().m_uid,
					currentSelectedColor
				});
				Logger.LogDebug((object)("Broadcasted color change for " + ((Object)componentInParent).name + " to all clients"));
			}
			string text = "\ud83c\udfa8 Painted " + ((Object)componentInParent).name + " with " + currentSelectedColor + "!";
			((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null);
			Logger.LogInfo((object)("\ud83c\udfa8 Painted '" + ((Object)componentInParent).name + "' with '" + currentSelectedColor + "'"));
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("PaintAtLook: Failed to apply color to '" + ((Object)componentInParent).name + "': " + ex.Message));
			((Character)localPlayer).Message((MessageType)1, "Failed to paint object", 0, (Sprite)null);
		}
	}

	public void ShowColorPicker()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Expected O, but got Unknown
		if ((Object)(object)colorPickerPanel != (Object)null)
		{
			CloseColorPicker();
			return;
		}
		colorPickerPanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 650f, 400f, false);
		GUIManager.Instance.CreateText(Localization.TryTranslate("$paint_color_picker_title"), colorPickerPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -30f), GUIManager.Instance.Norse, 28, GUIManager.Instance.ValheimOrange, true, Color.black, 550f, 40f, false);
		CreateSimpleSection(Localization.TryTranslate("$paint_wood_stains_section"), new string[5] { "Dark Brown", "Medium Brown", "Natural Wood", "Light Brown", "Pale Wood" }, -180f);
		CreatePaintColorSection(Localization.TryTranslate("$paint_colors_section"), new string[8] { "Black", "White", "Red", "Blue", "Green", "Yellow", "Orange", "Purple" }, 80f);
		((UnityEvent)GUIManager.Instance.CreateButton(Localization.TryTranslate("$paint_close_button"), colorPickerPanel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 30f), 100f, 30f).GetComponent<Button>().onClick).AddListener(new UnityAction(CloseColorPicker));
		colorPickerPanel.AddComponent<PickerCloser>().OnClose = CloseColorPicker;
		GUIManager.BlockInput(true);
	}

	private void CreateSimpleSection(string sectionTitle, string[] colorNames, float xOffset)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		GUIManager.Instance.CreateText(sectionTitle, colorPickerPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(xOffset, 120f), GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimOrange, true, Color.black, 200f, 25f, false);
		for (int i = 0; i < colorNames.Length; i++)
		{
			GameObject obj = GUIManager.Instance.CreateButton(colorNames[i], colorPickerPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(xOffset, 80f - (float)i * 35f), 160f, 30f);
			string colorName = colorNames[i];
			((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				SelectColor(colorName);
			});
		}
	}

	private void CreatePaintColorSection(string sectionTitle, string[] colorNames, float xOffset)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Expected O, but got Unknown
		GUIManager.Instance.CreateText(sectionTitle, colorPickerPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(xOffset + 80f, 120f), GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimOrange, true, Color.black, 200f, 25f, false);
		int num = 4;
		for (int i = 0; i < colorNames.Length; i++)
		{
			int num2 = i / num;
			int num3 = i % num;
			float num4 = xOffset - 40f + (float)num2 * 160f;
			float num5 = 80f - (float)num3 * 35f;
			GameObject obj = GUIManager.Instance.CreateButton(colorNames[i], colorPickerPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(num4, num5), 150f, 30f);
			string colorName = colorNames[i];
			((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				SelectColor(colorName);
			});
		}
	}

	private void SelectColor(string colorName)
	{
		currentSelectedColor = colorName;
		colorIndex = VikingColors.Keys.ToList().IndexOf(colorName);
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null)
		{
			((Character)localPlayer).Message((MessageType)2, "\ud83c\udfa8 Selected: " + colorName, 0, (Sprite)null);
		}
		Logger.LogDebug((object)("\ud83c\udfa8 Color selected from GUI: " + colorName));
		CloseColorPicker();
	}

	public void CloseColorPicker()
	{
		if ((Object)(object)colorPickerPanel != (Object)null)
		{
			Object.Destroy((Object)(object)colorPickerPanel);
			colorPickerPanel = null;
		}
		GUIManager.BlockInput(false);
	}

	private void OnDestroy()
	{
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
		PrefabManager.OnVanillaPrefabsAvailable -= AddCustomItems;
		if ((Object)(object)colorPickerPanel != (Object)null)
		{
			CloseColorPicker();
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}
}
[HarmonyPatch(typeof(Player), "PlayerAttackInput")]
public static class PlayerAttackInputPatch
{
	private static bool Prefix(Player __instance)
	{
		if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).TakeInput())
		{
			return true;
		}
		if (((Humanoid)__instance).GetRightItem()?.m_shared.m_name != "$item_painting_mallet")
		{
			return true;
		}
		if ((Object)(object)TorvaldsPainters.Instance == (Object)null)
		{
			return false;
		}
		if ((Object)(object)TorvaldsPainters.Instance.colorPickerPanel != (Object)null)
		{
			if (ZInput.GetButtonDown("Block") || ZInput.GetButtonDown("JoyButtonB"))
			{
				TorvaldsPainters.Instance.CloseColorPicker();
			}
			return false;
		}
		if (ZInput.GetButtonDown("Attack") || ZInput.GetButtonDown("JoyButtonX"))
		{
			TorvaldsPainters.Instance.PaintAtLook();
		}
		else if (ZInput.GetButtonDown("Block") || ZInput.GetButtonDown("JoyButtonB"))
		{
			TorvaldsPainters.Instance.ShowColorPicker();
		}
		return false;
	}
}
[HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")]
public static class PlayerUpdateBuildGuiInputPatch
{
	private static bool Prefix(Player __instance)
	{
		if (((Humanoid)__instance).GetRightItem()?.m_shared.m_name == "$item_painting_mallet")
		{
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Player), "Repair")]
public static class PlayerRepairPatch
{
	private static bool Prefix(Player __instance)
	{
		if (((Humanoid)__instance).GetRightItem()?.m_shared.m_name == "$item_painting_mallet")
		{
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Game), "Start")]
public static class GameStartPatch
{
	private static void Postfix()
	{
		if (ZRoutedRpc.instance != null)
		{
			ZRoutedRpc.instance.Register<ZDOID, string>("TP_SetColor", (Action<long, ZDOID, string>)TorvaldsPainters.OnRpcSetColor);
			Logger.LogDebug((object)"\ud83d\udd17 Multiplayer color sync ready");
		}
	}
}
[HarmonyPatch(typeof(Piece), "Awake")]
public static class PieceAwakePatch
{
	private static void Postfix(Piece __instance)
	{
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
		{
			return;
		}
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if (!((Object)(object)component == (Object)null) && component.IsValid())
		{
			string @string = component.GetZDO().GetString("TorvaldsPainters.Color", "");
			if (!string.IsNullOrEmpty(@string))
			{
				TorvaldsPainters.ApplyColorToPiece(__instance, @string, persistToZdo: false, logOnApply: false);
			}
		}
	}
}
[HarmonyPatch(typeof(WearNTear), "ResetHighlight")]
public static class WearNTearResetHighlightPatch
{
	private static void Postfix(WearNTear __instance)
	{
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())
		{
			return;
		}
		Piece component = ((Component)__instance).GetComponent<Piece>();
		ZNetView component2 = ((Component)__instance).GetComponent<ZNetView>();
		if (!Object.op_Implicit((Object)(object)component) || component2 == null || !component2.IsValid())
		{
			return;
		}
		string @string = component2.GetZDO().GetString("TorvaldsPainters.Color", "");
		if (!string.IsNullOrEmpty(@string))
		{
			int instanceID = ((Object)((Component)component).gameObject).GetInstanceID();
			float time = Time.time;
			if (!TorvaldsPainters._lastApply.TryGetValue(instanceID, out (string, float) value) || !(value.Item1 == @string) || !(time - value.Item2 < 0.25f))
			{
				TorvaldsPainters.ApplyColorToPiece(component, @string, persistToZdo: false, logOnApply: false);
				TorvaldsPainters._lastApply[instanceID] = (@string, time);
			}
		}
	}
}