Decompiled source of SignScribe v1.0.0

SignScribe.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SignScribe.Patches;
using SignScribe.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Jubaroo")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2026 Jubaroo")]
[assembly: AssemblyDescription("In-game rich text formatting studio and palette for Valheim signs using Jotunn")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SignScribe")]
[assembly: AssemblyTitle("SignScribe")]
[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]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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;
		}
	}
}
namespace SignScribe
{
	[BepInPlugin("com.jubaroo.signscribe", "SignScribe", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInProcess("valheim.exe")]
	public sealed class SignScribePlugin : BaseUnityPlugin
	{
		public readonly struct EmojiItem
		{
			public readonly string Glyph;

			public readonly string Name;

			public readonly string[]? Tags;

			public EmojiItem(string glyph, string name, string[]? tags = null)
			{
				Glyph = glyph;
				Name = name;
				Tags = tags;
			}
		}

		public readonly struct EmojiGroup
		{
			public readonly string Header;

			public readonly EmojiItem[] Items;

			public EmojiGroup(string header, EmojiItem[] items)
			{
				Header = header;
				Items = items;
			}
		}

		internal static readonly string[] SavedColors = new string[5];

		internal static readonly Color[] SavedColorValues = (Color[])(object)new Color[5];

		internal static readonly string[][] ColorPalette = new string[16][]
		{
			new string[2] { "#FF3B30", "Red" },
			new string[2] { "#FF9500", "Orange" },
			new string[2] { "#FFCC00", "Yellow" },
			new string[2] { "#34C759", "Lime" },
			new string[2] { "#008F39", "Green" },
			new string[2] { "#00C7BE", "Teal" },
			new string[2] { "#32ADE6", "Cyan" },
			new string[2] { "#007AFF", "Blue" },
			new string[2] { "#5856D6", "Indigo" },
			new string[2] { "#AF52DE", "Purple" },
			new string[2] { "#FF2D55", "Magenta" },
			new string[2] { "#FF69B4", "Pink" },
			new string[2] { "#D4AF37", "Gold" },
			new string[2] { "#8B5A2B", "Brown" },
			new string[2] { "#FFFFFF", "White" },
			new string[2] { "#8E8E93", "Gray" }
		};

		internal static readonly EmojiGroup[] EmojiCatalog = new EmojiGroup[9]
		{
			new EmojiGroup("Combat & Tools", new EmojiItem[25]
			{
				new EmojiItem("⚔", "Swords", new string[5] { "combat", "pvp", "battle", "fight", "weapon" }),
				new EmojiItem("\ud83d\udde1", "Dagger", new string[3] { "knife", "weapon", "blade" }),
				new EmojiItem("\ud83c\udff9", "Bow", new string[4] { "arrow", "weapon", "ranged", "hunting" }),
				new EmojiItem("\ud83d\udee1", "Shield", new string[4] { "defense", "guard", "armor", "block" }),
				new EmojiItem("⛏", "Pickaxe", new string[5] { "mine", "mining", "stone", "ore", "tool" }),
				new EmojiItem("\ud83d\udd28", "Hammer", new string[4] { "build", "repair", "craft", "tool" }),
				new EmojiItem("\ud83e\ude93", "Axe", new string[5] { "chop", "wood", "tree", "tool", "weapon" }),
				new EmojiItem("\ud83d\udca3", "Bomb", new string[3] { "explosive", "blast", "danger" }),
				new EmojiItem("\ud83e\udde8", "Dynamite", new string[2] { "explosive", "firecracker" }),
				new EmojiItem("\ud83d\udd2a", "Knife", new string[3] { "blade", "kitchen", "cook" }),
				new EmojiItem("⚙", "Gear", new string[4] { "cog", "settings", "machine", "mechanism" }),
				new EmojiItem("\ud83d\udd27", "Wrench", new string[4] { "tool", "fix", "repair", "spanner" }),
				new EmojiItem("⛓", "Chains", new string[4] { "iron", "metal", "lock", "prison" }),
				new EmojiItem("\ud83e\ude9d", "Hook", new string[3] { "grapple", "fishing", "pirate" }),
				new EmojiItem("\ud83e\ude9a", "Saw", new string[3] { "carpentry", "woodwork", "tool" }),
				new EmojiItem("\ud83e\uddf2", "Magnet", new string[4] { "attract", "iron", "metal", "tool" }),
				new EmojiItem("\ud83e\ude84", "Wand", new string[4] { "magic", "wizard", "spell", "cast" }),
				new EmojiItem("\ud83d\udca5", "Explosion", new string[4] { "bang", "boom", "blast", "impact" }),
				new EmojiItem("\ud83e\ude78", "Blood", new string[3] { "damage", "wound", "bleed" }),
				new EmojiItem("\ud83c\udfaf", "Target", new string[4] { "bullseye", "aim", "archery", "goal" }),
				new EmojiItem("\ud83d\udea9", "Flag", new string[4] { "marker", "banner", "point", "claim" }),
				new EmojiItem("☠", "Skull Bones", new string[4] { "pirate", "death", "poison", "danger" }),
				new EmojiItem("\ud83d\udc80", "Skull", new string[4] { "death", "dead", "skeleton", "danger" }),
				new EmojiItem("⚰", "Coffin", new string[3] { "funeral", "grave", "death" }),
				new EmojiItem("\ud83e\udea6", "Headstone", new string[3] { "gravestone", "rip", "tomb" })
			}),
			new EmojiGroup("Nature & Biomes", new EmojiItem[38]
			{
				new EmojiItem("\ud83c\udf32", "Pine Tree", new string[4] { "wood", "forest", "black forest", "timber" }),
				new EmojiItem("\ud83c\udf33", "Oak Tree", new string[4] { "wood", "meadows", "forest", "nature" }),
				new EmojiItem("\ud83c\udf34", "Palm Tree", new string[4] { "tree", "beach", "tropical", "island" }),
				new EmojiItem("\ud83e\udeb5", "Wood Log", new string[4] { "lumber", "timber", "fuel", "firewood" }),
				new EmojiItem("\ud83c\udf31", "Seedling", new string[4] { "plant", "grow", "sprout", "farming" }),
				new EmojiItem("\ud83c\udf3f", "Herb", new string[4] { "leaf", "alchemy", "ingredient", "plant" }),
				new EmojiItem("☘", "Shamrock", new string[3] { "clover", "plant", "green" }),
				new EmojiItem("\ud83c\udf40", "4-Leaf Clover", new string[4] { "lucky", "luck", "fortune", "plant" }),
				new EmojiItem("\ud83c\udf3e", "Grain / Barley", new string[4] { "wheat", "crop", "plains", "harvest" }),
				new EmojiItem("\ud83c\udf35", "Cactus", new string[3] { "desert", "plant", "spikes" }),
				new EmojiItem("\ud83c\udf37", "Tulip", new string[3] { "flower", "spring", "garden" }),
				new EmojiItem("\ud83c\udf38", "Cherry Blossom", new string[3] { "flower", "pink", "spring" }),
				new EmojiItem("\ud83c\udf39", "Rose", new string[4] { "flower", "red", "love", "garden" }),
				new EmojiItem("\ud83c\udf3b", "Sunflower", new string[3] { "flower", "yellow", "summer" }),
				new EmojiItem("\ud83c\udf3c", "Blossom", new string[3] { "flower", "bloom", "nature" }),
				new EmojiItem("\ud83c\udf44", "Mushroom", new string[4] { "food", "forage", "fungus", "shroom" }),
				new EmojiItem("\ud83c\udf42", "Fallen Leaf", new string[4] { "autumn", "fall", "orange", "leaf" }),
				new EmojiItem("\ud83c\udf41", "Maple Leaf", new string[3] { "autumn", "fall", "nature" }),
				new EmojiItem("\ud83d\udd25", "Fire", new string[5] { "campfire", "flame", "hot", "burn", "warmth" }),
				new EmojiItem("\ud83d\udca7", "Water Drop", new string[4] { "liquid", "water", "wet", "rain" }),
				new EmojiItem("\ud83c\udf0a", "Ocean Wave", new string[4] { "sea", "ocean", "water", "sailing" }),
				new EmojiItem("❄", "Snowflake", new string[5] { "snow", "frost", "cold", "mountain", "freeze" }),
				new EmojiItem("⚡", "Lightning", new string[4] { "thunder", "storm", "shock", "electric" }),
				new EmojiItem("⛅", "Sun Cloud", new string[3] { "weather", "cloudy", "sky" }),
				new EmojiItem("\ud83c\udf27", "Rain Cloud", new string[4] { "weather", "shower", "wet", "storm" }),
				new EmojiItem("\ud83c\udf29", "Thundercloud", new string[3] { "storm", "lightning", "weather" }),
				new EmojiItem("\ud83c\udf19", "Crescent Moon", new string[3] { "night", "dark", "evening" }),
				new EmojiItem("☀\ufe0f", "Sun", new string[4] { "day", "light", "sunny", "warm" }),
				new EmojiItem("⭐", "Star", new string[4] { "night", "sky", "space", "favorite" }),
				new EmojiItem("\ud83c\udf1f", "Glowing Star", new string[3] { "sparkle", "shine", "magic" }),
				new EmojiItem("\ud83c\udf0b", "Volcano", new string[4] { "ashlands", "lava", "fire", "magma" }),
				new EmojiItem("\ud83c\udfd4", "Snow Mountain", new string[4] { "mountains", "peak", "cold", "altitude" }),
				new EmojiItem("⛰", "Mountain", new string[3] { "rock", "hill", "highlands" }),
				new EmojiItem("\ud83c\udfd5", "Camping", new string[4] { "tent", "camp", "outdoors", "base" }),
				new EmojiItem("\ud83c\udfdc", "Desert", new string[3] { "sand", "dry", "sun" }),
				new EmojiItem("\ud83e\udea8", "Rock / Stone", new string[4] { "boulder", "mineral", "ore", "material" }),
				new EmojiItem("\ud83c\udf15", "Full Moon", new string[3] { "night", "lunar", "moonlight" }),
				new EmojiItem("☄", "Comet", new string[3] { "meteor", "space", "falling star" })
			}),
			new EmojiGroup("Creatures & Wildlife", new EmojiItem[42]
			{
				new EmojiItem("\ud83d\udc17", "Boar", new string[5] { "pig", "animal", "tame", "meat", "leather" }),
				new EmojiItem("\ud83d\udc3a", "Wolf", new string[5] { "canine", "animal", "tame", "mountains", "pack" }),
				new EmojiItem("\ud83e\udd8c", "Deer", new string[5] { "animal", "hide", "antlers", "trophy", "hunt" }),
				new EmojiItem("\ud83d\udc3b", "Bear", new string[4] { "animal", "beast", "fur", "predator" }),
				new EmojiItem("\ud83e\udd87", "Bat", new string[4] { "cave", "flying", "night", "animal" }),
				new EmojiItem("\ud83e\udd85", "Eagle", new string[4] { "bird", "raptor", "feathers", "sky" }),
				new EmojiItem("\ud83e\udd89", "Owl", new string[4] { "bird", "night", "wise", "feathers" }),
				new EmojiItem("\ud83d\udc0d", "Snake", new string[4] { "serpent", "poison", "reptile", "sea serpent" }),
				new EmojiItem("\ud83d\udd77", "Spider", new string[4] { "arachnid", "mistlands", "web", "bug" }),
				new EmojiItem("\ud83e\udd82", "Scorpion", new string[3] { "poison", "stinger", "bug" }),
				new EmojiItem("\ud83d\udc1d", "Bee", new string[4] { "queen bee", "honey", "hive", "insect" }),
				new EmojiItem("\ud83d\udc1b", "Bug / Caterpillar", new string[3] { "insect", "larva", "creep" }),
				new EmojiItem("\ud83e\udd8b", "Butterfly", new string[3] { "insect", "wings", "pretty" }),
				new EmojiItem("\ud83d\udc0c", "Snail", new string[3] { "slow", "shell", "garden" }),
				new EmojiItem("\ud83d\udc1c", "Ant", new string[3] { "insect", "colony", "worker" }),
				new EmojiItem("\ud83e\udd9f", "Mosquito", new string[4] { "deathsquito", "plains", "sting", "needle" }),
				new EmojiItem("\ud83d\udc1f", "Fish", new string[4] { "angler", "fishing", "food", "ocean" }),
				new EmojiItem("\ud83e\udd88", "Shark", new string[4] { "predator", "ocean", "sea", "fish" }),
				new EmojiItem("\ud83d\udc19", "Octopus", new string[3] { "kraken", "tentacles", "sea" }),
				new EmojiItem("\ud83e\udd91", "Squid", new string[3] { "ocean", "calamari", "tentacles" }),
				new EmojiItem("\ud83e\udd80", "Crab", new string[3] { "ocean", "shellfish", "beach" }),
				new EmojiItem("\ud83e\udd9e", "Lobster", new string[3] { "seafood", "crustacean", "ocean" }),
				new EmojiItem("\ud83e\udd90", "Shrimp", new string[3] { "seafood", "ocean", "small" }),
				new EmojiItem("\ud83d\udc0e", "Horse", new string[4] { "steed", "mount", "animal", "ride" }),
				new EmojiItem("\ud83d\udc02", "Ox / Lox", new string[5] { "lox", "beast", "plains", "mount", "animal" }),
				new EmojiItem("\ud83d\udc04", "Cow", new string[3] { "farm", "milk", "cattle" }),
				new EmojiItem("\ud83d\udc16", "Pig", new string[3] { "farm", "pork", "swine" }),
				new EmojiItem("\ud83d\udc0f", "Ram", new string[3] { "sheep", "wool", "horns" }),
				new EmojiItem("\ud83d\udc11", "Sheep", new string[3] { "wool", "farm", "flock" }),
				new EmojiItem("\ud83d\udc10", "Goat", new string[3] { "animal", "horns", "farm" }),
				new EmojiItem("\ud83d\udc15", "Dog", new string[3] { "pet", "puppy", "canine" }),
				new EmojiItem("\ud83d\udc08", "Cat", new string[3] { "pet", "kitten", "feline" }),
				new EmojiItem("\ud83d\udc13", "Rooster", new string[4] { "chicken", "bird", "morning", "farm" }),
				new EmojiItem("\ud83e\udd83", "Turkey", new string[3] { "bird", "poultry", "farm" }),
				new EmojiItem("\ud83e\udd86", "Duck", new string[3] { "bird", "pond", "waterfowl" }),
				new EmojiItem("\ud83e\udda2", "Swan", new string[3] { "bird", "lake", "graceful" }),
				new EmojiItem("\ud83d\udc38", "Frog", new string[3] { "swamp", "amphibian", "hop" }),
				new EmojiItem("\ud83d\udc0a", "Crocodile", new string[4] { "reptile", "alligator", "swamp", "predator" }),
				new EmojiItem("\ud83d\udc22", "Turtle", new string[4] { "reptile", "shell", "slow", "chitin" }),
				new EmojiItem("\ud83d\udc09", "Dragon", new string[5] { "moder", "wyrm", "boss", "flying", "drake" }),
				new EmojiItem("\ud83e\udd95", "Sauropod", new string[3] { "dino", "dinosaur", "giant" }),
				new EmojiItem("\ud83e\udd96", "T-Rex", new string[4] { "dino", "dinosaur", "carnivore", "monster" })
			}),
			new EmojiGroup("Food & Farming", new EmojiItem[46]
			{
				new EmojiItem("\ud83c\udf56", "Meat", new string[4] { "food", "cooked meat", "ribs", "eat" }),
				new EmojiItem("\ud83e\udd69", "Steak", new string[4] { "raw meat", "meat", "beef", "grill" }),
				new EmojiItem("\ud83c\udf57", "Poultry Leg", new string[4] { "chicken", "cooked", "food", "meat" }),
				new EmojiItem("\ud83e\udd53", "Bacon", new string[3] { "pork", "breakfast", "food" }),
				new EmojiItem("\ud83c\udf5e", "Bread", new string[5] { "baking", "oven", "barley", "food", "loaf" }),
				new EmojiItem("\ud83e\udd56", "Baguette", new string[3] { "bread", "bakery", "food" }),
				new EmojiItem("\ud83e\uddc0", "Cheese", new string[2] { "dairy", "food" }),
				new EmojiItem("\ud83c\udf73", "Fried Egg", new string[4] { "egg", "breakfast", "cooking", "food" }),
				new EmojiItem("\ud83e\udd5e", "Pancakes", new string[3] { "breakfast", "syrup", "food" }),
				new EmojiItem("\ud83c\udf6f", "Honey", new string[5] { "beehive", "mead", "sweet", "nectar", "food" }),
				new EmojiItem("\ud83c\udf4e", "Red Apple", new string[3] { "fruit", "food", "orchard" }),
				new EmojiItem("\ud83c\udf4f", "Green Apple", new string[3] { "fruit", "sour", "orchard" }),
				new EmojiItem("\ud83c\udf50", "Pear", new string[3] { "fruit", "orchard", "food" }),
				new EmojiItem("\ud83c\udf4a", "Orange", new string[3] { "fruit", "citrus", "food" }),
				new EmojiItem("\ud83c\udf4b", "Lemon", new string[3] { "fruit", "citrus", "sour" }),
				new EmojiItem("\ud83c\udf4c", "Banana", new string[3] { "fruit", "tropical", "food" }),
				new EmojiItem("\ud83c\udf49", "Watermelon", new string[3] { "fruit", "melon", "summer" }),
				new EmojiItem("\ud83c\udf47", "Grapes", new string[4] { "fruit", "wine", "vineyard", "berries" }),
				new EmojiItem("\ud83c\udf53", "Strawberry", new string[3] { "fruit", "berries", "sweet" }),
				new EmojiItem("\ud83e\uded0", "Blueberries", new string[4] { "berries", "forage", "black forest", "food" }),
				new EmojiItem("\ud83c\udf52", "Cherries", new string[3] { "fruit", "berries", "sweet" }),
				new EmojiItem("\ud83c\udf51", "Peach", new string[3] { "fruit", "orchard", "sweet" }),
				new EmojiItem("\ud83e\udd55", "Carrot", new string[5] { "vegetable", "farming", "crop", "seeds", "food" }),
				new EmojiItem("\ud83c\udf3d", "Corn", new string[3] { "vegetable", "crop", "harvest" }),
				new EmojiItem("\ud83e\udd54", "Potato", new string[4] { "turnip", "root", "vegetable", "farming" }),
				new EmojiItem("\ud83e\uddc5", "Onion", new string[4] { "vegetable", "farming", "cooking", "crop" }),
				new EmojiItem("\ud83e\uddc4", "Garlic", new string[3] { "herb", "flavor", "vegetable" }),
				new EmojiItem("\ud83e\udd66", "Broccoli", new string[3] { "vegetable", "healthy", "greens" }),
				new EmojiItem("\ud83e\udd6c", "Leafy Green", new string[3] { "lettuce", "salad", "vegetable" }),
				new EmojiItem("\ud83e\udd5c", "Peanuts", new string[3] { "nuts", "snack", "food" }),
				new EmojiItem("\ud83c\udf30", "Chestnut", new string[4] { "acorn", "nut", "seeds", "tree" }),
				new EmojiItem("\ud83c\udf7a", "Beer Mug", new string[5] { "mead", "ale", "drink", "tavern", "fermenter" }),
				new EmojiItem("\ud83c\udf7b", "Clinking Mugs", new string[4] { "toast", "cheers", "bar", "party" }),
				new EmojiItem("\ud83c\udf77", "Wine Glass", new string[3] { "drink", "alcohol", "vintage" }),
				new EmojiItem("\ud83e\udd42", "Champagne", new string[3] { "celebrate", "cheers", "toast" }),
				new EmojiItem("\ud83e\udd43", "Whiskey Glass", new string[3] { "liquor", "spirits", "drink" }),
				new EmojiItem("\ud83c\udf78", "Cocktail", new string[3] { "drink", "martini", "bar" }),
				new EmojiItem("\ud83c\udf76", "Sake Bottle", new string[3] { "flask", "potion", "bottle" }),
				new EmojiItem("☕", "Coffee Cup", new string[3] { "hot drink", "morning", "caffeine" }),
				new EmojiItem("\ud83c\udf75", "Tea Cup", new string[3] { "hot drink", "herbal", "potion" }),
				new EmojiItem("\ud83e\udd63", "Bowl of Stew", new string[4] { "soup", "stew", "cauldron", "serpent stew" }),
				new EmojiItem("\ud83c\udf72", "Pot of Food", new string[3] { "cauldron", "cooking", "hot pot" }),
				new EmojiItem("\ud83e\udd67", "Meat Pie", new string[4] { "pie", "baked", "food", "pastry" }),
				new EmojiItem("\ud83c\udf70", "Cake Slice", new string[3] { "dessert", "sweet", "party" }),
				new EmojiItem("\ud83c\udf6a", "Cookie", new string[3] { "snack", "biscuit", "sweet" }),
				new EmojiItem("\ud83e\uddc2", "Salt", new string[3] { "seasoning", "spice", "cooking" })
			}),
			new EmojiGroup("Loot & Magic", new EmojiItem[37]
			{
				new EmojiItem("\ud83d\udc51", "Crown", new string[5] { "king", "jarl", "royalty", "leader", "loot" }),
				new EmojiItem("\ud83d\udcb0", "Money Bag", new string[5] { "gold", "coins", "coins bag", "treasure", "rich" }),
				new EmojiItem("\ud83e\ude99", "Gold Coin", new string[4] { "coin", "currency", "haldor", "trader" }),
				new EmojiItem("\ud83d\udc8e", "Gem", new string[6] { "ruby", "amber", "sapphire", "emerald", "crystal", "loot" }),
				new EmojiItem("\ud83d\udc8d", "Ring", new string[4] { "jewelry", "accessory", "magic ring", "treasure" }),
				new EmojiItem("\ud83c\udfc6", "Trophy", new string[4] { "award", "boss trophy", "hunt", "victory" }),
				new EmojiItem("\ud83e\udd47", "1st Gold Medal", new string[3] { "first", "champion", "winner" }),
				new EmojiItem("\ud83e\udd48", "2nd Silver Medal", new string[3] { "second", "silver", "runner-up" }),
				new EmojiItem("\ud83e\udd49", "3rd Bronze Medal", new string[3] { "third", "bronze", "medal" }),
				new EmojiItem("\ud83c\udf96", "Military Medal", new string[3] { "honor", "service", "decoration" }),
				new EmojiItem("\ud83d\udce6", "Storage Chest", new string[5] { "box", "crate", "package", "storage", "loot" }),
				new EmojiItem("\ud83c\udf81", "Gift Box", new string[3] { "present", "holiday", "reward" }),
				new EmojiItem("\ud83d\udcdc", "Scroll", new string[5] { "map", "rune", "recipe", "blueprint", "document" }),
				new EmojiItem("\ud83d\udddd", "Old Key", new string[4] { "swamp key", "crypt key", "dungeon", "lock" }),
				new EmojiItem("\ud83d\udd11", "Key", new string[4] { "lock", "open", "door", "chest" }),
				new EmojiItem("\ud83d\udd12", "Locked", new string[4] { "secure", "ward", "private", "no entry" }),
				new EmojiItem("\ud83d\udd13", "Unlocked", new string[3] { "open", "accessible", "free" }),
				new EmojiItem("\ud83d\udcef", "Postal Horn", new string[4] { "horn", "war horn", "call", "music" }),
				new EmojiItem("\ud83d\udd14", "Bell", new string[4] { "chime", "alarm", "church", "sound" }),
				new EmojiItem("\ud83c\udffa", "Amphora / Vase", new string[4] { "pottery", "relic", "urn", "ancient" }),
				new EmojiItem("\ud83d\udd6f", "Candle", new string[4] { "light", "wax", "flame", "lighting" }),
				new EmojiItem("\ud83d\udd2e", "Crystal Ball", new string[4] { "magic", "seer", "oracle", "future" }),
				new EmojiItem("\ud83e\uddff", "Nazar Amulet", new string[4] { "talisman", "ward", "protection", "charm" }),
				new EmojiItem("\ud83e\uddea", "Test Tube / Potion", new string[4] { "potion", "alchemy", "mead", "brew" }),
				new EmojiItem("\ud83e\uddec", "DNA", new string[3] { "essence", "life", "science" }),
				new EmojiItem("\ud83e\udded", "Compass", new string[4] { "direction", "navigation", "map", "way" }),
				new EmojiItem("⌛", "Hourglass Done", new string[3] { "time", "timer", "wait" }),
				new EmojiItem("⏳", "Hourglass Active", new string[4] { "time", "timing", "loading", "fermenting" }),
				new EmojiItem("\ud83d\udca1", "Lightbulb", new string[4] { "idea", "bright", "electricity", "invention" }),
				new EmojiItem("\ud83d\udd26", "Flashlight", new string[3] { "torch", "beam", "search" }),
				new EmojiItem("\ud83e\ude94", "Oil Lamp", new string[3] { "lantern", "light", "fuel" }),
				new EmojiItem("\ud83d\udcb5", "Dollar Banknote", new string[3] { "money", "cash", "bills" }),
				new EmojiItem("\ud83d\udcb3", "Card", new string[3] { "payment", "ticket", "pass" }),
				new EmojiItem("\ud83c\udff7", "Label / Tag", new string[4] { "portal tag", "tag", "name", "price" }),
				new EmojiItem("\ud83d\uddfa", "World Map", new string[3] { "cartography", "explore", "navigation" }),
				new EmojiItem("✉", "Envelope", new string[4] { "letter", "mail", "message", "note" }),
				new EmojiItem("✨", "Magic Sparkles", new string[5] { "stars", "enchant", "glowing", "clean", "magic" })
			}),
			new EmojiGroup("Base & Travel", new EmojiItem[28]
			{
				new EmojiItem("\ud83c\udfe0", "House", new string[4] { "home", "base", "building", "shelter" }),
				new EmojiItem("\ud83c\udfe1", "Homestead", new string[3] { "farmhouse", "estate", "yard" }),
				new EmojiItem("\ud83c\udff0", "Castle", new string[4] { "fortress", "keep", "stronghold", "stone" }),
				new EmojiItem("\ud83d\uddfc", "Watchtower", new string[3] { "tower", "lookout", "spire" }),
				new EmojiItem("⛺", "Tent", new string[3] { "campsite", "temporary", "outdoors" }),
				new EmojiItem("\ud83d\uded6", "Hut", new string[3] { "cabin", "shack", "primitive" }),
				new EmojiItem("\ud83d\udeaa", "Door", new string[4] { "entrance", "portal", "exit", "entry" }),
				new EmojiItem("\ud83e\ude9f", "Window", new string[3] { "glass", "view", "wall" }),
				new EmojiItem("\ud83d\udecf", "Bed", new string[4] { "spawn point", "sleep", "rest", "comfort" }),
				new EmojiItem("\ud83d\udecb", "Couch", new string[3] { "comfort", "furniture", "living" }),
				new EmojiItem("\ud83e\ude91", "Chair", new string[3] { "throne", "furniture", "seat" }),
				new EmojiItem("⚓", "Anchor", new string[5] { "dock", "port", "harbor", "ship", "boat" }),
				new EmojiItem("⛵", "Sailboat", new string[4] { "karve", "raft", "boat", "sailing" }),
				new EmojiItem("\ud83d\udea4", "Speedboat", new string[2] { "fast boat", "watercraft" }),
				new EmojiItem("\ud83d\udea2", "Longship", new string[4] { "viking ship", "drakkar", "ship", "vessel" }),
				new EmojiItem("\ud83d\udef6", "Canoe", new string[3] { "kayak", "paddle", "boat" }),
				new EmojiItem("\ud83d\udea3", "Rowboat", new string[3] { "rowing", "boat", "water" }),
				new EmojiItem("\ud83d\uded2", "Cart", new string[4] { "wagon", "haul", "transport", "cargo" }),
				new EmojiItem("\ud83d\udee4", "Railway", new string[3] { "tracks", "path", "transport" }),
				new EmojiItem("\ud83d\udee3", "Road", new string[4] { "path", "trail", "highway", "travel" }),
				new EmojiItem("\ud83e\ude9c", "Ladder", new string[3] { "climb", "stairs", "reach" }),
				new EmojiItem("\ud83e\udea2", "Knot / Rope", new string[4] { "rope", "tie", "cord", "rigging" }),
				new EmojiItem("\ud83e\udea3", "Bucket", new string[3] { "water", "well", "pail" }),
				new EmojiItem("\ud83d\udec1", "Bathtub", new string[4] { "wash", "tub", "clean", "water" }),
				new EmojiItem("\ud83d\udebf", "Shower", new string[3] { "clean", "bathroom", "water" }),
				new EmojiItem("\ud83e\uddf9", "Broom", new string[3] { "sweep", "clean", "tidy" }),
				new EmojiItem("\ud83e\uddfa", "Basket", new string[3] { "storage", "container", "woven" }),
				new EmojiItem("\ud83e\ude9e", "Mirror", new string[3] { "reflection", "glass", "vanity" })
			}),
			new EmojiGroup("Smileys & Faces", new EmojiItem[97]
			{
				new EmojiItem("☺", "Smile", new string[4] { "happy", "smile", "classic", "face" }),
				new EmojiItem("\ud83d\ude00", "Grinning", new string[3] { "happy", "smile", "joy" }),
				new EmojiItem("\ud83d\ude03", "Grinning Eyes", new string[3] { "happy", "smile", "open" }),
				new EmojiItem("\ud83d\ude04", "Smiling Eyes", new string[3] { "laugh", "happy", "cheerful" }),
				new EmojiItem("\ud83d\ude01", "Beaming", new string[3] { "grin", "teeth", "happy" }),
				new EmojiItem("\ud83d\ude06", "Laughing Squint", new string[3] { "haha", "lol", "funny" }),
				new EmojiItem("\ud83d\ude05", "Sweat Grin", new string[3] { "phew", "nervous", "relief" }),
				new EmojiItem("\ud83e\udd23", "ROFL", new string[3] { "rolling", "laughing", "hilarious" }),
				new EmojiItem("\ud83d\ude02", "Tears of Joy", new string[3] { "crying laughing", "lol", "funny" }),
				new EmojiItem("\ud83d\ude42", "Slight Smile", new string[3] { "calm", "pleasant", "ok" }),
				new EmojiItem("\ud83d\ude43", "Upside Down", new string[3] { "silly", "irony", "sarcasm" }),
				new EmojiItem("\ud83d\ude09", "Wink", new string[3] { "flirt", "joke", "secret" }),
				new EmojiItem("\ud83d\ude0a", "Warm Smile", new string[3] { "blush", "kind", "friendly" }),
				new EmojiItem("\ud83d\ude07", "Angel Halo", new string[3] { "innocent", "good", "holy" }),
				new EmojiItem("\ud83e\udd70", "Hearts Face", new string[3] { "love", "adorable", "sweet" }),
				new EmojiItem("\ud83d\ude0d", "Heart Eyes", new string[3] { "love", "crush", "gorgeous" }),
				new EmojiItem("\ud83e\udd29", "Star-Struck", new string[3] { "excited", "amazed", "wow" }),
				new EmojiItem("\ud83d\ude18", "Blowing Kiss", new string[3] { "love", "kiss", "affection" }),
				new EmojiItem("\ud83d\ude0b", "Yummy", new string[4] { "delicious", "tasty", "food", "tongue" }),
				new EmojiItem("\ud83d\ude1b", "Tongue Out", new string[3] { "silly", "playful", "joke" }),
				new EmojiItem("\ud83d\ude1c", "Winking Tongue", new string[3] { "crazy", "playful", "fun" }),
				new EmojiItem("\ud83e\udd2a", "Zany", new string[3] { "crazy", "wild", "goofy" }),
				new EmojiItem("\ud83d\ude1d", "Squinting Tongue", new string[3] { "mischief", "playful", "tease" }),
				new EmojiItem("\ud83e\udd11", "Money Face", new string[4] { "rich", "coins", "gold", "wealth" }),
				new EmojiItem("\ud83e\udd17", "Hugging", new string[3] { "hug", "welcome", "open hands" }),
				new EmojiItem("\ud83e\udd2d", "Hand on Mouth", new string[3] { "oops", "secret", "giggle" }),
				new EmojiItem("\ud83e\udd2b", "Shushing", new string[4] { "quiet", "silence", "hush", "secret" }),
				new EmojiItem("\ud83e\udd14", "Thinking", new string[4] { "hmm", "ponder", "wonder", "curious" }),
				new EmojiItem("\ud83e\udd10", "Zipper Mouth", new string[3] { "shut", "silent", "secret" }),
				new EmojiItem("\ud83e\udd28", "Raised Eyebrow", new string[3] { "skeptical", "suspicious", "doubt" }),
				new EmojiItem("\ud83d\ude10", "Neutral", new string[3] { "blank", "poker face", "indifferent" }),
				new EmojiItem("\ud83d\ude11", "Expressionless", new string[3] { "unimpressed", "flat", "done" }),
				new EmojiItem("\ud83d\ude36", "No Mouth", new string[3] { "speechless", "quiet", "mute" }),
				new EmojiItem("\ud83d\ude0f", "Smirking", new string[3] { "smug", "flirt", "clever" }),
				new EmojiItem("\ud83d\ude12", "Unamused", new string[3] { "annoyed", "grumpy", "bored" }),
				new EmojiItem("\ud83d\ude44", "Rolling Eyes", new string[3] { "whatever", "sarcasm", "annoyed" }),
				new EmojiItem("\ud83d\ude2c", "Grimacing", new string[3] { "awkward", "yikes", "nervous" }),
				new EmojiItem("\ud83e\udd25", "Lying Face", new string[3] { "pinocchio", "deceit", "fake" }),
				new EmojiItem("\ud83d\ude0c", "Relieved", new string[4] { "peace", "calm", "zen", "rest" }),
				new EmojiItem("\ud83d\ude14", "Pensive", new string[3] { "sad", "thoughtful", "down" }),
				new EmojiItem("\ud83d\ude2a", "Sleepy", new string[3] { "tired", "snooze", "rest" }),
				new EmojiItem("\ud83e\udd24", "Drooling", new string[3] { "hungry", "craving", "delicious" }),
				new EmojiItem("\ud83d\ude34", "Sleeping", new string[4] { "zzz", "bed", "rest", "night" }),
				new EmojiItem("\ud83d\ude37", "Mask", new string[3] { "sick", "doctor", "hygiene" }),
				new EmojiItem("\ud83e\udd12", "Thermometer", new string[3] { "fever", "sick", "ill" }),
				new EmojiItem("\ud83e\udd15", "Bandage Head", new string[3] { "hurt", "injured", "wound" }),
				new EmojiItem("\ud83e\udd22", "Nauseated", new string[3] { "sick", "gross", "disgust" }),
				new EmojiItem("\ud83e\udd2e", "Vomiting", new string[3] { "puke", "disgusted", "sick" }),
				new EmojiItem("\ud83e\udd27", "Sneezing", new string[3] { "cold", "allergies", "tissue" }),
				new EmojiItem("\ud83e\udd75", "Hot Face", new string[4] { "heat", "sweat", "fire", "spicy" }),
				new EmojiItem("\ud83e\udd76", "Cold Face", new string[4] { "freezing", "ice", "frost", "shivering" }),
				new EmojiItem("\ud83e\udd74", "Woozy", new string[4] { "drunk", "mead", "dizzy", "tipsy" }),
				new EmojiItem("\ud83d\ude35", "Dizzy", new string[3] { "stunned", "dead", "knocked out" }),
				new EmojiItem("\ud83e\udd2f", "Mind Blown", new string[3] { "exploding", "shocked", "amazing" }),
				new EmojiItem("\ud83e\udd20", "Cowboy", new string[3] { "hat", "western", "yeehaw" }),
				new EmojiItem("\ud83e\udd73", "Party Face", new string[3] { "celebration", "horn", "birthday" }),
				new EmojiItem("\ud83d\ude0e", "Sunglasses", new string[4] { "cool", "boss", "swag", "awesome" }),
				new EmojiItem("\ud83e\udd13", "Nerd", new string[3] { "glasses", "smart", "geek" }),
				new EmojiItem("\ud83e\uddd0", "Monocle", new string[3] { "detective", "inspect", "fancy" }),
				new EmojiItem("\ud83d\ude15", "Confused", new string[3] { "puzzled", "uncertain", "what" }),
				new EmojiItem("\ud83d\ude1f", "Worried", new string[3] { "anxious", "nervous", "concern" }),
				new EmojiItem("\ud83d\ude41", "Slight Frown", new string[2] { "disappointed", "sad" }),
				new EmojiItem("☹", "Frowning", new string[3] { "unhappy", "bummed", "sad" }),
				new EmojiItem("\ud83d\ude2e", "Open Mouth", new string[3] { "surprised", "gasp", "whoa" }),
				new EmojiItem("\ud83d\ude2f", "Hushed", new string[3] { "stunned", "quiet", "surprise" }),
				new EmojiItem("\ud83d\ude32", "Astonished", new string[3] { "shocked", "amazed", "unbelievable" }),
				new EmojiItem("\ud83d\ude33", "Flushed", new string[3] { "blushing", "embarrassed", "wide eyes" }),
				new EmojiItem("\ud83e\udd7a", "Pleading Eyes", new string[3] { "begging", "cute", "puppy eyes" }),
				new EmojiItem("\ud83d\ude26", "Frowning Open", new string[2] { "shock", "dismay" }),
				new EmojiItem("\ud83d\ude27", "Anguished", new string[3] { "pain", "distress", "worry" }),
				new EmojiItem("\ud83d\ude28", "Fearful", new string[3] { "scared", "frightened", "panic" }),
				new EmojiItem("\ud83d\ude30", "Anxious Sweat", new string[3] { "nervous", "stressed", "scared" }),
				new EmojiItem("\ud83d\ude25", "Sad Relieved", new string[2] { "close call", "disappointed" }),
				new EmojiItem("\ud83d\ude22", "Crying", new string[3] { "tear", "sad", "unhappy" }),
				new EmojiItem("\ud83d\ude2d", "Loudly Crying", new string[3] { "bawling", "sobbing", "tears" }),
				new EmojiItem("\ud83d\ude31", "Screaming", new string[4] { "horror", "terror", "scared", "munch" }),
				new EmojiItem("\ud83d\ude16", "Confounded", new string[2] { "frustrated", "struggling" }),
				new EmojiItem("\ud83d\ude23", "Persevering", new string[3] { "enduring", "struggling", "trying" }),
				new EmojiItem("\ud83d\ude1e", "Disappointed", new string[3] { "regret", "let down", "sad" }),
				new EmojiItem("\ud83d\ude13", "Downcast Sweat", new string[2] { "exhausted", "hard work" }),
				new EmojiItem("\ud83d\ude29", "Weary", new string[3] { "tired", "frustrated", "fed up" }),
				new EmojiItem("\ud83d\ude2b", "Tired", new string[3] { "exhausted", "whining", "done" }),
				new EmojiItem("\ud83e\udd71", "Yawning", new string[3] { "bored", "sleepy", "tired" }),
				new EmojiItem("\ud83d\ude24", "Steam Triumph", new string[3] { "proud", "determined", "puff" }),
				new EmojiItem("\ud83d\ude21", "Enraged", new string[4] { "mad", "furious", "angry", "red" }),
				new EmojiItem("\ud83d\ude20", "Angry", new string[3] { "mad", "cross", "annoyed" }),
				new EmojiItem("\ud83e\udd2c", "Cursing", new string[3] { "swearing", "profanity", "rage" }),
				new EmojiItem("\ud83d\ude08", "Smiling Devil", new string[3] { "mischief", "evil", "imp" }),
				new EmojiItem("\ud83d\udc7f", "Angry Devil", new string[3] { "demon", "furious", "fiend" }),
				new EmojiItem("\ud83d\udca9", "Poop", new string[3] { "crap", "dung", "funny" }),
				new EmojiItem("\ud83e\udd21", "Clown", new string[3] { "fool", "circus", "jester" }),
				new EmojiItem("\ud83d\udc79", "Ogre", new string[4] { "monster", "troll", "demon", "japanese" }),
				new EmojiItem("\ud83d\udc7a", "Goblin", new string[3] { "red face", "troll", "creature" }),
				new EmojiItem("\ud83d\udc7b", "Ghost", new string[4] { "spooky", "wraith", "phantom", "haunt" }),
				new EmojiItem("\ud83d\udc7d", "Alien", new string[3] { "ufo", "extraterrestrial", "space" }),
				new EmojiItem("\ud83d\udc7e", "Space Monster", new string[4] { "retro", "invader", "game", "pixel" }),
				new EmojiItem("\ud83e\udd16", "Robot", new string[4] { "droid", "mech", "ai", "bot" })
			}),
			new EmojiGroup("Symbols & UI", new EmojiItem[61]
			{
				new EmojiItem("⚠", "Warning", new string[4] { "alert", "caution", "danger", "hazard" }),
				new EmojiItem("⛔", "No Entry", new string[3] { "stop", "forbidden", "restricted" }),
				new EmojiItem("\ud83d\udeab", "Prohibited", new string[3] { "banned", "no", "forbidden" }),
				new EmojiItem("❗", "Exclamation", new string[3] { "important", "notice", "alert" }),
				new EmojiItem("❓", "Question", new string[4] { "help", "info", "query", "unknown" }),
				new EmojiItem("❌", "Cross Mark", new string[4] { "no", "cancel", "wrong", "x" }),
				new EmojiItem("⭕", "Circle", new string[4] { "ok", "correct", "target", "round" }),
				new EmojiItem("\ud83d\uded1", "Stop Sign", new string[3] { "halt", "octagonal", "danger" }),
				new EmojiItem("\ud83d\udd34", "Red Circle", new string[3] { "marker", "dot", "danger" }),
				new EmojiItem("\ud83d\udfe0", "Orange Circle", new string[3] { "marker", "dot", "orange" }),
				new EmojiItem("\ud83d\udfe1", "Yellow Circle", new string[3] { "marker", "dot", "caution" }),
				new EmojiItem("\ud83d\udfe2", "Green Circle", new string[4] { "marker", "dot", "safe", "go" }),
				new EmojiItem("\ud83d\udd35", "Blue Circle", new string[4] { "marker", "dot", "water", "portal" }),
				new EmojiItem("\ud83d\udfe3", "Purple Circle", new string[3] { "marker", "dot", "magic" }),
				new EmojiItem("\ud83d\udfe4", "Brown Circle", new string[3] { "marker", "dot", "earth" }),
				new EmojiItem("⚫", "Black Circle", new string[3] { "marker", "dot", "dark" }),
				new EmojiItem("⚪", "White Circle", new string[3] { "marker", "dot", "light" }),
				new EmojiItem("\ud83d\udfe5", "Red Square", new string[3] { "marker", "box", "red" }),
				new EmojiItem("\ud83d\udfe9", "Green Square", new string[3] { "marker", "box", "green" }),
				new EmojiItem("\ud83d\udfe6", "Blue Square", new string[3] { "marker", "box", "blue" }),
				new EmojiItem("\ud83d\udfe8", "Yellow Square", new string[3] { "marker", "box", "yellow" }),
				new EmojiItem("⬛", "Black Square", new string[3] { "marker", "box", "black" }),
				new EmojiItem("⬜", "White Square", new string[3] { "marker", "box", "white" }),
				new EmojiItem("⬆", "Up Arrow", new string[3] { "north", "upward", "direction" }),
				new EmojiItem("⬇", "Down Arrow", new string[3] { "south", "downward", "direction" }),
				new EmojiItem("⬅", "Left Arrow", new string[3] { "west", "leftward", "direction" }),
				new EmojiItem("➡", "Right Arrow", new string[3] { "east", "rightward", "direction" }),
				new EmojiItem("↗", "Up-Right Arrow", new string[2] { "northeast", "direction" }),
				new EmojiItem("↘", "Down-Right Arrow", new string[2] { "southeast", "direction" }),
				new EmojiItem("↙", "Down-Left Arrow", new string[2] { "southwest", "direction" }),
				new EmojiItem("↖", "Up-Left Arrow", new string[2] { "northwest", "direction" }),
				new EmojiItem("↕", "Up-Down Arrow", new string[2] { "vertical", "direction" }),
				new EmojiItem("↔", "Left-Right Arrow", new string[2] { "horizontal", "direction" }),
				new EmojiItem("↩", "Return Arrow", new string[3] { "back", "undo", "left hook" }),
				new EmojiItem("↪", "Curve Arrow", new string[3] { "forward", "redo", "right hook" }),
				new EmojiItem("\ud83d\udd04", "Counter Clockwise", new string[3] { "refresh", "reload", "cycle" }),
				new EmojiItem("\ud83d\udd03", "Clockwise", new string[3] { "repeat", "loop", "sync" }),
				new EmojiItem("➕", "Plus", new string[3] { "add", "positive", "math" }),
				new EmojiItem("➖", "Minus", new string[3] { "subtract", "negative", "math" }),
				new EmojiItem("✖", "Multiply", new string[3] { "times", "x", "math" }),
				new EmojiItem("➗", "Divide", new string[2] { "division", "math" }),
				new EmojiItem("♾", "Infinity", new string[3] { "forever", "endless", "loop" }),
				new EmojiItem("\ud83d\udcb2", "Dollar", new string[3] { "price", "cost", "money" }),
				new EmojiItem("♻", "Recycle", new string[3] { "reuse", "green", "circle" }),
				new EmojiItem("⚜", "Fleur-de-lis", new string[3] { "heraldry", "lily", "french" }),
				new EmojiItem("\ud83d\udd31", "Trident", new string[3] { "poseidon", "fork", "spear" }),
				new EmojiItem("\ud83d\udd30", "Shield Symbol", new string[3] { "beginner", "leaf", "crest" }),
				new EmojiItem("❇", "Sparkle", new string[3] { "shine", "star", "clean" }),
				new EmojiItem("✳", "Eight-Spoke", new string[2] { "star", "asterisk" }),
				new EmojiItem("✴", "Eight-Point", new string[2] { "star", "burst" }),
				new EmojiItem("\ud83d\udca4", "Zzz", new string[3] { "sleep", "rest", "tired" }),
				new EmojiItem("\ud83d\udca2", "Anger Mark", new string[3] { "furious", "comic", "vein" }),
				new EmojiItem("\ud83d\udcac", "Speech Bubble", new string[3] { "talk", "chat", "message" }),
				new EmojiItem("\ud83d\udcad", "Thought Bubble", new string[3] { "think", "dream", "cloud" }),
				new EmojiItem("\ud83d\udcaf", "100 Points", new string[3] { "perfect", "score", "century" }),
				new EmojiItem("\ud83c\udfb2", "Game Die", new string[4] { "dice", "gamble", "random", "rpg" }),
				new EmojiItem("\ud83d\udd79", "Joystick", new string[3] { "gaming", "arcade", "controller" }),
				new EmojiItem("\ud83c\udfb5", "Musical Note", new string[3] { "song", "sound", "tune" }),
				new EmojiItem("\ud83c\udfb6", "Musical Notes", new string[3] { "music", "melody", "soundtrack" }),
				new EmojiItem("\ud83d\udce2", "Loudspeaker", new string[3] { "shout", "announce", "broadcast" }),
				new EmojiItem("\ud83d\udce3", "Megaphone", new string[3] { "cheer", "alert", "voice" })
			}),
			new EmojiGroup("Hearts & Hands", new EmojiItem[59]
			{
				new EmojiItem("❤", "Red Heart", new string[4] { "love", "health", "life", "heart" }),
				new EmojiItem("\ud83e\udde1", "Orange Heart", new string[3] { "love", "orange", "warmth" }),
				new EmojiItem("\ud83d\udc9b", "Yellow Heart", new string[3] { "love", "friendship", "gold" }),
				new EmojiItem("\ud83d\udc9a", "Green Heart", new string[3] { "love", "nature", "green" }),
				new EmojiItem("\ud83d\udc99", "Blue Heart", new string[3] { "love", "loyalty", "ocean" }),
				new EmojiItem("\ud83d\udc9c", "Purple Heart", new string[3] { "love", "magic", "royalty" }),
				new EmojiItem("\ud83e\udd0e", "Brown Heart", new string[3] { "love", "earth", "wood" }),
				new EmojiItem("\ud83d\udda4", "Black Heart", new string[3] { "love", "dark", "sorrow" }),
				new EmojiItem("\ud83e\udd0d", "White Heart", new string[3] { "love", "pure", "peace" }),
				new EmojiItem("\ud83d\udc94", "Broken Heart", new string[3] { "heartbreak", "sad", "damage" }),
				new EmojiItem("❣", "Heart Exclamation", new string[3] { "emphasis", "love", "alert" }),
				new EmojiItem("\ud83d\udc95", "Two Hearts", new string[3] { "love", "sweet", "affection" }),
				new EmojiItem("\ud83d\udc9e", "Revolving Hearts", new string[3] { "love", "spinning", "motion" }),
				new EmojiItem("\ud83d\udc93", "Beating Heart", new string[3] { "pulse", "alive", "heartbeat" }),
				new EmojiItem("\ud83d\udc97", "Growing Heart", new string[3] { "expand", "love", "affection" }),
				new EmojiItem("\ud83d\udc96", "Sparkle Heart", new string[3] { "sparkling", "shine", "special" }),
				new EmojiItem("\ud83d\udc98", "Cupid Arrow", new string[3] { "love", "archer", "shot" }),
				new EmojiItem("\ud83d\udc9d", "Ribbon Heart", new string[3] { "gift", "present", "valentine" }),
				new EmojiItem("\ud83d\udc4d", "Thumbs Up", new string[5] { "yes", "good", "approve", "like", "agree" }),
				new EmojiItem("\ud83d\udc4e", "Thumbs Down", new string[4] { "no", "bad", "disapprove", "dislike" }),
				new EmojiItem("\ud83d\udc4c", "OK Hand", new string[3] { "perfect", "fine", "understood" }),
				new EmojiItem("✌", "Victory Hand", new string[3] { "peace", "two", "v sign" }),
				new EmojiItem("\ud83e\udd1e", "Crossed Fingers", new string[3] { "luck", "hope", "wish" }),
				new EmojiItem("\ud83e\udd1f", "Love-You Sign", new string[3] { "hand", "rock", "gesture" }),
				new EmojiItem("\ud83e\udd18", "Rock On", new string[3] { "horns", "metal", "heavy" }),
				new EmojiItem("\ud83e\udd19", "Call Me", new string[3] { "shaka", "hang loose", "hand" }),
				new EmojiItem("\ud83d\udc48", "Point Left", new string[3] { "hand", "direction", "west" }),
				new EmojiItem("\ud83d\udc49", "Point Right", new string[3] { "hand", "direction", "east" }),
				new EmojiItem("\ud83d\udc46", "Point Up", new string[3] { "hand", "direction", "north" }),
				new EmojiItem("\ud83d\udc47", "Point Down", new string[3] { "hand", "direction", "south" }),
				new EmojiItem("☝", "Index Point Up", new string[3] { "one", "first", "attention" }),
				new EmojiItem("✋", "Raised Hand", new string[3] { "stop", "high five", "palm" }),
				new EmojiItem("\ud83e\udd1a", "Back of Hand", new string[2] { "raised", "hand" }),
				new EmojiItem("\ud83d\udd90", "Splayed Hand", new string[3] { "five", "fingers", "palm" }),
				new EmojiItem("\ud83d\udd96", "Vulcan Salute", new string[3] { "spock", "prosper", "star trek" }),
				new EmojiItem("\ud83d\udc4b", "Waving Hand", new string[3] { "hello", "goodbye", "wave" }),
				new EmojiItem("\ud83d\udc4f", "Clapping", new string[3] { "applause", "bravo", "good job" }),
				new EmojiItem("\ud83d\ude4c", "Raising Hands", new string[3] { "celebrate", "praise", "cheer" }),
				new EmojiItem("\ud83d\udc50", "Open Hands", new string[3] { "hug", "receptive", "hands" }),
				new EmojiItem("\ud83e\udd32", "Palms Together", new string[3] { "prayer", "offering", "cupped" }),
				new EmojiItem("\ud83e\udd1d", "Handshake", new string[3] { "deal", "agreement", "partner" }),
				new EmojiItem("\ud83d\ude4f", "Folded Hands", new string[4] { "pray", "thank you", "please", "namaste" }),
				new EmojiItem("✍", "Writing Hand", new string[4] { "author", "pen", "sign", "scribe" }),
				new EmojiItem("\ud83d\udcaa", "Flexed Bicep", new string[4] { "strong", "power", "muscle", "workout" }),
				new EmojiItem("\ud83e\uddbe", "Mech Arm", new string[3] { "bionic", "robot", "prosthetic" }),
				new EmojiItem("\ud83e\uddbf", "Mech Leg", new string[3] { "bionic", "robot", "prosthetic" }),
				new EmojiItem("\ud83e\uddb5", "Leg", new string[3] { "limb", "kick", "foot" }),
				new EmojiItem("\ud83e\uddb6", "Foot", new string[3] { "step", "walk", "tracks" }),
				new EmojiItem("\ud83d\udc42", "Ear", new string[3] { "hear", "listen", "sound" }),
				new EmojiItem("\ud83d\udc43", "Nose", new string[3] { "smell", "scent", "sniff" }),
				new EmojiItem("\ud83e\udde0", "Brain", new string[3] { "smart", "intellect", "mind" }),
				new EmojiItem("\ud83e\udec0", "Anatomical Heart", new string[3] { "organ", "cardio", "pulse" }),
				new EmojiItem("\ud83e\udec1", "Lungs", new string[3] { "breath", "stamina", "air" }),
				new EmojiItem("\ud83e\uddb7", "Tooth", new string[3] { "dentist", "bite", "teeth" }),
				new EmojiItem("\ud83e\uddb4", "Bone", new string[3] { "remains", "skeleton", "crafting" }),
				new EmojiItem("\ud83d\udc40", "Eyes", new string[4] { "look", "see", "watch", "stare" }),
				new EmojiItem("\ud83d\udc41", "Single Eye", new string[4] { "odin", "vision", "gaze", "all-seeing" }),
				new EmojiItem("\ud83d\udc45", "Tongue", new string[3] { "taste", "lick", "mouth" }),
				new EmojiItem("\ud83d\udc44", "Lips", new string[3] { "mouth", "kiss", "speech" })
			})
		};

		public const string PluginGuid = "com.jubaroo.signscribe";

		public const string PluginName = "SignScribe";

		public const string PluginVersion = "1.0.0";

		internal const int SavedColorSlots = 5;

		internal const int UndoHistoryLimit = 50;

		internal static SignScribePlugin Instance = null;

		internal static ManualLogSource Log = null;

		private Harmony? _harmony;

		private ConfigEntry<KeyboardShortcut> _toggleKey;

		private ConfigEntry<int> _characterLimitConfig;

		private ConfigEntry<bool> _debugLoggingConfig;

		private ConfigEntry<float> _opacityConfig;

		private static ConfigEntry<string> _savedColorsConfig = null;

		private ConfigEntry<float> _windowPosXConfig;

		private ConfigEntry<float> _windowPosYConfig;

		private ConfigEntry<float> _scrollSensitivityConfig;

		private bool _isSignPrompt;

		private bool _wasOpen;

		private TMP_InputField? _activeField;

		private bool _showHud = true;

		internal static string DefaultHint = "";

		internal static readonly List<string> UndoStack = new List<string>();

		internal static readonly List<string> RedoStack = new List<string>();

		internal const string ShorthandColorPattern = "<#[0-9a-fA-F]{3,8}>";

		internal static readonly Regex ColorTagRegex = new Regex("</?color(=[^>]+)?>|<#[0-9a-fA-F]{3,8}>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		internal static readonly Regex AnyTagRegex = new Regex("<[^>]+>", RegexOptions.Compiled);

		internal static readonly Regex SpriteTagRegex = new Regex("<sprite[^>]*>", RegexOptions.Compiled);

		internal static readonly Regex SizeTagRegex = new Regex("</?size(=[^>]*)?>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		internal static readonly Regex ShorthandColorRegex = new Regex("<(#[0-9a-fA-F]{3,8})>", RegexOptions.Compiled);

		internal static readonly Regex SizeTagNumericRegex = new Regex("<size=([0-9]+)(px)?>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		internal static string[]? SignSpriteLabels;

		internal static string[]? SignSpriteTags;

		private static MethodInfo? _stringToCaretMethod;

		private static bool _stringToCaretResolved;

		internal static string StatusMessage = "";

		internal static float StatusUntil = 0f;

		internal static int LastSelectionStart = -1;

		internal static int LastSelectionEnd = -1;

		private static readonly Dictionary<string, string> KnownHexSpriteNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			["263a"] = "Smile",
			["2639"] = "Frown",
			["1f600"] = "Grinning",
			["1f601"] = "Beaming",
			["1f602"] = "Tears of Joy",
			["1f603"] = "Grinning Eyes",
			["1f604"] = "Smiling Eyes",
			["1f605"] = "Sweat Grin",
			["1f606"] = "Laughing Squint",
			["1f607"] = "Angel Halo",
			["1f609"] = "Wink",
			["1f60a"] = "Warm Smile",
			["1f60b"] = "Yummy",
			["1f60c"] = "Relieved",
			["1f60d"] = "Heart Eyes",
			["1f60e"] = "Sunglasses",
			["1f60f"] = "Smirking",
			["1f618"] = "Blowing Kiss",
			["1f642"] = "Slight Smile",
			["1f643"] = "Upside Down",
			["1f923"] = "ROFL"
		};

		internal static int SignCharacterLimit
		{
			get
			{
				if (!((Object)(object)Instance != (Object)null))
				{
					return 999;
				}
				return Instance._characterLimitConfig.Value;
			}
		}

		internal static bool IsDebugEnabled
		{
			get
			{
				if ((Object)(object)Instance != (Object)null && Instance._debugLoggingConfig != null)
				{
					return Instance._debugLoggingConfig.Value;
				}
				return false;
			}
		}

		internal ConfigEntry<float> OpacityConfig => _opacityConfig;

		internal ConfigEntry<float> PosXConfig => _windowPosXConfig;

		internal ConfigEntry<float> PosYConfig => _windowPosYConfig;

		internal ConfigEntry<float> ScrollSensitivityConfig => _scrollSensitivityConfig;

		internal static void LoadSavedColors()
		{
			string[] array = (_savedColorsConfig?.Value ?? "").Split(new char[1] { ',' });
			Color val = default(Color);
			for (int i = 0; i < 5 && i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0 && ColorUtility.TryParseHtmlString(text, ref val))
				{
					SetSavedColor(i, text, saveConfig: false);
				}
			}
		}

		internal static void SetSavedColor(int slot, string hex, bool saveConfig = true)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (slot >= 0 && slot < 5)
			{
				Color val = default(Color);
				ColorUtility.TryParseHtmlString(hex, ref val);
				SavedColors[slot] = hex;
				SavedColorValues[slot] = val;
				if (saveConfig && (Object)(object)Instance != (Object)null)
				{
					Instance.SaveSettings();
				}
			}
		}

		internal static void ClearSavedColors()
		{
			Array.Clear(SavedColors, 0, SavedColors.Length);
			Array.Clear(SavedColorValues, 0, SavedColorValues.Length);
			Instance?.SaveSettings();
		}

		internal static void DebugLog(string message)
		{
			if (IsDebugEnabled)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)message);
				}
			}
		}

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Key that shows/hides the SignScribe window while editing a sign.");
			_characterLimitConfig = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SignCharacterLimit", 999, new ConfigDescription("Maximum character limit for signs. Vanilla Valheim default is 50. SignScribe expands this to 999 so rich text tags fit comfortably.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 2000), Array.Empty<object>()));
			_debugLoggingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Enable verbose diagnostic logging in the console and log file for troubleshooting sign formatting and UI operations.");
			_opacityConfig = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowOpacity", 0.95f, new ConfigDescription("Opacity of the SignScribe window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			_savedColorsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "SavedColors", "", "Saved custom colors (comma-separated hex, managed by the in-game UI).");
			_windowPosXConfig = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowPositionX", 0f, "Saved horizontal position of the studio window (anchored top-center).");
			_windowPosYConfig = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowPositionY", -20f, "Saved vertical position of the studio window (anchored top-center).");
			_scrollSensitivityConfig = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "ScrollSensitivity", 80f, new ConfigDescription("Scroll sensitivity for the icon palette in SignScribe Studio.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), Array.Empty<object>()));
			_scrollSensitivityConfig.SettingChanged += delegate
			{
				StudioBuilder.UpdateScrollSensitivity(_scrollSensitivityConfig.Value);
			};
			Vector2 sanitizedWindowPosition = GetSanitizedWindowPosition(_windowPosXConfig.Value, _windowPosYConfig.Value);
			if (!Mathf.Approximately(_windowPosXConfig.Value, sanitizedWindowPosition.x) || !Mathf.Approximately(_windowPosYConfig.Value, sanitizedWindowPosition.y))
			{
				Log.LogInfo((object)$"Migrating studio window position from ({_windowPosXConfig.Value}, {_windowPosYConfig.Value}) to ({sanitizedWindowPosition.x}, {sanitizedWindowPosition.y})");
				_windowPosXConfig.Value = sanitizedWindowPosition.x;
				_windowPosYConfig.Value = sanitizedWindowPosition.y;
				((BaseUnityPlugin)this).Config.Save();
			}
			DefaultHint = BuildDefaultHint();
			_toggleKey.SettingChanged += delegate
			{
				DefaultHint = BuildDefaultHint();
			};
			LoadSavedColors();
			_harmony = new Harmony("com.jubaroo.signscribe");
			_harmony.PatchAll(typeof(RequestTextPatch).Assembly);
			List<MethodBase> list = _harmony.GetPatchedMethods().ToList();
			Log.LogInfo((object)string.Format("{0} v{1} loaded! Hooked {2} methods. Jotunn native UI ready.", "SignScribe", "1.0.0", list.Count));
			foreach (MethodBase item in list)
			{
				Log.LogDebug((object)("  Hooked: " + item.DeclaringType?.Name + "." + item.Name));
			}
		}

		private void OnDestroy()
		{
			SaveSettings();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = _toggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_showHud = !_showHud;
				StudioBuilder.ToggleStudio();
			}
			if ((Object)(object)_activeField != (Object)null && _activeField.isFocused)
			{
				int length = _activeField.text.Length;
				int num = Mathf.Clamp(_activeField.selectionStringAnchorPosition, 0, length);
				int num2 = Mathf.Clamp(_activeField.selectionStringFocusPosition, 0, length);
				LastSelectionStart = Mathf.Min(num, num2);
				LastSelectionEnd = Mathf.Max(num, num2);
			}
			bool flag = (Object)(object)TextInput.instance != (Object)null && (((Object)(object)TextInput.instance.m_panel != (Object)null && TextInput.instance.m_panel.activeInHierarchy) || TextInput.IsVisible());
			bool flag2 = _isSignPrompt && flag;
			if (_wasOpen && !flag2)
			{
				OnPromptClosed();
			}
			_wasOpen = flag2;
			if (flag2 && (Object)(object)_activeField != (Object)null)
			{
				bool flag3 = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
				bool flag4 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				if (flag3 && Input.GetKeyDown((KeyCode)122))
				{
					if (flag4)
					{
						RedoNext(_activeField);
					}
					else
					{
						UndoLast(_activeField);
					}
				}
				else if (flag3 && Input.GetKeyDown((KeyCode)121))
				{
					RedoNext(_activeField);
				}
				else if (flag3 && Input.GetKeyDown((KeyCode)98))
				{
					WrapGenericTag(_activeField, "<b>", "</b>");
				}
				else if (flag3 && Input.GetKeyDown((KeyCode)105))
				{
					WrapGenericTag(_activeField, "<i>", "</i>");
				}
				else if (flag3 && Input.GetKeyDown((KeyCode)117))
				{
					WrapGenericTag(_activeField, "<u>", "</u>");
				}
			}
			if (flag2 && StudioBuilder.IsVisible())
			{
				StudioBuilder.UpdatePreview();
				StudioBuilder.UpdateStatusText();
			}
		}

		private string BuildDefaultHint()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return $"{_toggleKey.Value} toggle · drag to move · Ctrl+Z/Y undo/redo · Ctrl+B/I/U tags";
		}

		internal void OnPromptOpened(bool isSign)
		{
			_isSignPrompt = isSign;
			UndoStack.Clear();
			RedoStack.Clear();
			_activeField = null;
			if (!isSign || (Object)(object)TextInput.instance == (Object)null)
			{
				StudioBuilder.CloseStudio();
				return;
			}
			_activeField = ((Component)TextInput.instance).gameObject.GetComponentInChildren<TMP_InputField>(true);
			if ((Object)(object)_activeField == (Object)null)
			{
				Log.LogWarning((object)"SignScribe: TMP_InputField could not be found under TextInput.instance.");
				return;
			}
			if (_activeField.characterLimit < SignCharacterLimit)
			{
				_activeField.characterLimit = SignCharacterLimit;
			}
			_activeField.onFocusSelectAll = false;
			int num = _activeField.text?.Length ?? 0;
			_activeField.selectionStringAnchorPosition = num;
			_activeField.selectionStringFocusPosition = num;
			_activeField.caretPosition = num;
			LastSelectionStart = num;
			LastSelectionEnd = num;
			if (_showHud && (Object)(object)_activeField != (Object)null)
			{
				StudioBuilder.OpenStudio(_activeField);
				_wasOpen = true;
			}
		}

		internal void OnPromptClosed()
		{
			_isSignPrompt = false;
			_activeField = null;
			LastSelectionStart = -1;
			LastSelectionEnd = -1;
			StudioBuilder.CloseStudio();
			UndoStack.Clear();
			SaveSettings();
		}

		internal void SaveSettings()
		{
			if (_savedColorsConfig != null)
			{
				_savedColorsConfig.Value = string.Join(",", SavedColors);
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		internal static Vector2 GetSanitizedWindowPosition(float x, float y)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (y > 0f || y < -2500f)
			{
				y = -20f;
			}
			if (Mathf.Abs(x) > 2500f)
			{
				x = 0f;
			}
			return new Vector2(x, y);
		}

		internal void SaveWindowPosition(float x, float y)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			Vector2 sanitizedWindowPosition = GetSanitizedWindowPosition(x, y);
			if (_windowPosXConfig != null && _windowPosYConfig != null)
			{
				_windowPosXConfig.Value = sanitizedWindowPosition.x;
				_windowPosYConfig.Value = sanitizedWindowPosition.y;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		internal static string GetPreview(string source)
		{
			if (string.IsNullOrEmpty(source))
			{
				return "";
			}
			string input = ShorthandColorRegex.Replace(source, "<color=$1>");
			string text = SizeTagNumericRegex.Replace(input, delegate(Match match)
			{
				if (int.TryParse(match.Groups[1].Value, out var result))
				{
					int num = Mathf.Clamp(Mathf.RoundToInt((float)result * 2.2f), 8, 30);
					return $"<size={num}>";
				}
				return match.Value;
			});
			if (source.IndexOf("<size", StringComparison.OrdinalIgnoreCase) >= 0 || source.IndexOf("<sprite", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				DebugLog("[GetPreview] Source='" + source + "' -> Rendered Preview='" + text + "'");
			}
			return text;
		}

		internal static void SetStatus(string message)
		{
			StatusMessage = message;
			StatusUntil = Time.realtimeSinceStartup + 2.5f;
			StudioBuilder.SetStatus(message);
		}

		internal static void GetSelection(TMP_InputField f, out int start, out int end)
		{
			int length = f.text.Length;
			if (LastSelectionStart >= 0 && LastSelectionEnd >= LastSelectionStart && LastSelectionStart != LastSelectionEnd)
			{
				start = Mathf.Clamp(LastSelectionStart, 0, length);
				end = Mathf.Clamp(LastSelectionEnd, 0, length);
				DebugLog($"[GetSelection] Using LastSelection: [{start}..{end}] of total length {length}");
				return;
			}
			int num = Mathf.Clamp(f.selectionStringAnchorPosition, 0, length);
			int num2 = Mathf.Clamp(f.selectionStringFocusPosition, 0, length);
			start = Mathf.Min(num, num2);
			end = Mathf.Max(num, num2);
			DebugLog($"[GetSelection] Using selectionString: anchor={num}, focus={num2} -> [{start}..{end}] of total length {length} (LastSel: {LastSelectionStart}..{LastSelectionEnd})");
		}

		internal static bool TryReplace(TMP_InputField f, int start, int end, string replacement, int caretOffset)
		{
			string text = f.text;
			DebugLog($"[TryReplace] Current text='{text}' (len={text.Length}), replace range [{start}..{end}], replacement='{replacement}', caretOffset={caretOffset}");
			string text2 = text.Remove(start, end - start).Insert(start, replacement);
			if (text2 == text)
			{
				DebugLog("[TryReplace] Result identical to current ('" + text + "'). No-op returning true.");
				return true;
			}
			if (f.characterLimit > 0 && text2.Length > f.characterLimit)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)$"[TryReplace] Character limit reached! New length={text2.Length} exceeds limit={f.characterLimit}");
				}
				SetStatus($"Sign limit reached ({f.characterLimit} chars)");
				return false;
			}
			UndoStack.Add(text);
			if (UndoStack.Count > 50)
			{
				UndoStack.RemoveAt(0);
			}
			RedoStack.Clear();
			f.text = text2;
			DebugLog($"[TryReplace] Assigned f.text='{f.text}' (actual length={f.text.Length})");
			int num = start + caretOffset;
			LastSelectionStart = (LastSelectionEnd = num);
			FocusAndPlaceCaret(f, num);
			return true;
		}

		internal static void UndoLast(TMP_InputField f)
		{
			if (UndoStack.Count == 0)
			{
				SetStatus("Nothing to undo");
				return;
			}
			RedoStack.Add(f.text ?? "");
			string text = UndoStack[UndoStack.Count - 1];
			UndoStack.RemoveAt(UndoStack.Count - 1);
			f.text = text;
			LastSelectionStart = (LastSelectionEnd = text.Length);
			FocusAndPlaceCaret(f, text.Length);
			SetStatus("Undid last action (Ctrl+Y to redo)");
		}

		internal static void RedoNext(TMP_InputField f)
		{
			if (RedoStack.Count == 0)
			{
				SetStatus("Nothing to redo");
				return;
			}
			UndoStack.Add(f.text ?? "");
			string text = RedoStack[RedoStack.Count - 1];
			RedoStack.RemoveAt(RedoStack.Count - 1);
			f.text = text;
			LastSelectionStart = (LastSelectionEnd = text.Length);
			FocusAndPlaceCaret(f, text.Length);
			SetStatus("Redid action (Ctrl+Z to undo)");
		}

		internal static void InsertText(TMP_InputField f, string textToInsert)
		{
			GetSelection(f, out var start, out var end);
			if (start == 0 && end == f.text.Length && f.text.Length > 0)
			{
				start = end;
			}
			if (start == end)
			{
				Match match = Regex.Match(f.text.Substring(0, start), "(</(size|color|b|i|u|s|uppercase|lowercase|smallcaps|align|mark|sub|sup)>)+$", RegexOptions.IgnoreCase);
				if (match.Success)
				{
					start -= match.Length;
					end -= match.Length;
				}
			}
			TryReplace(f, start, end, textToInsert, textToInsert.Length);
		}

		internal static void WrapGenericTag(TMP_InputField f, string openTag, string closeTag)
		{
			GetSelection(f, out var start, out var end);
			if (start != end)
			{
				string text = openTag + f.text.Substring(start, end - start) + closeTag;
				TryReplace(f, start, end, text, text.Length);
			}
			else
			{
				TryReplace(f, start, end, openTag + closeTag, openTag.Length);
			}
			SetStatus("Applied " + openTag + " tag");
		}

		internal static void ApplySize(TMP_InputField f, int size)
		{
			string text = $"<size={size}>";
			string text2 = f.text ?? "";
			DebugLog($"[ApplySize] Called with size={size}, openTag='{text}', current f.text='{text2}' (len={text2.Length})");
			GetSelection(f, out var start, out var end);
			int num = start;
			bool flag = false;
			if (start == end)
			{
				if (text2.Length <= 0)
				{
					DebugLog("[ApplySize] Empty text, inserting empty tags: '" + text + "</size>'");
					TryReplace(f, start, end, text + "</size>", text.Length);
					return;
				}
				start = 0;
				end = text2.Length;
				flag = true;
				DebugLog($"[ApplySize] No selection (start==end), defaulting to global apply: [0..{text2.Length}]");
			}
			string text3 = text2.Substring(start, end - start);
			string text4 = SizeTagRegex.Replace(text3, "");
			DebugLog($"[ApplySize] Selected range [{start}..{end}]: raw='{text3}', after SizeTagRegex strip='{text4}'");
			int num2 = text2.Substring(0, start).LastIndexOf("<size=", StringComparison.OrdinalIgnoreCase);
			int num3 = text2.IndexOf("</size>", end, StringComparison.OrdinalIgnoreCase);
			DebugLog($"[ApplySize] Enclosing search: prevOpen={num2}, nextClose={num3}");
			if (num2 != -1 && num3 != -1)
			{
				int num4 = text2.IndexOf('>', num2);
				if (num4 != -1 && num4 < start)
				{
					string text5 = text2.Substring(num4 + 1, start - (num4 + 1));
					string text6 = text2.Substring(end, num3 - end);
					DebugLog($"[ApplySize] Found surrounding size tag: prevOpenEnd={num4}, lead='{text5}', trail='{text6}'");
					if (string.IsNullOrWhiteSpace(text5) && string.IsNullOrWhiteSpace(text6))
					{
						string text7 = text + text5 + text4 + text6 + "</size>";
						int num5 = (flag ? (num + text.Length) : (num2 + text7.Length));
						DebugLog(string.Format("[ApplySize] Modifying surrounding size tag block: [{0}..{1}], block='{2}'", num2, num3 + "</size>".Length, text7));
						TryReplace(f, num2, num3 + "</size>".Length, text7, num5 - num2);
						return;
					}
				}
			}
			string text8 = text + text4 + "</size>";
			int num6 = (flag ? (num + text.Length) : (start + text8.Length));
			DebugLog($"[ApplySize] Standard replacement: range [{start}..{end}], newSegment='{text8}'");
			TryReplace(f, start, end, text8, num6 - start);
		}

		internal static void ApplyColor(TMP_InputField f, string colorCode)
		{
			string text = "<color=" + colorCode + ">";
			GetSelection(f, out var start, out var end);
			int num = start;
			bool flag = false;
			if (start == end)
			{
				if (f.text.Length <= 0)
				{
					TryReplace(f, start, end, text + "</color>", text.Length);
					return;
				}
				start = 0;
				end = f.text.Length;
				flag = true;
			}
			string text2 = f.text;
			string text3 = ColorTagRegex.Replace(text2.Substring(start, end - start), "");
			int num2 = text2.Substring(0, start).LastIndexOf("<color=", StringComparison.OrdinalIgnoreCase);
			int num3 = text2.IndexOf("</color>", end, StringComparison.OrdinalIgnoreCase);
			if (num2 != -1 && num3 != -1)
			{
				int num4 = text2.IndexOf('>', num2);
				if (num4 != -1 && num4 < start)
				{
					string text4 = text2.Substring(num4 + 1, start - (num4 + 1));
					string text5 = text2.Substring(end, num3 - end);
					if (string.IsNullOrWhiteSpace(text4) && string.IsNullOrWhiteSpace(text5))
					{
						string text6 = text + text4 + text3 + text5 + "</color>";
						int num5 = (flag ? (num + text.Length) : (num2 + text6.Length));
						TryReplace(f, num2, num3 + "</color>".Length, text6, num5 - num2);
						return;
					}
				}
			}
			string text7 = text + text3 + "</color>";
			int num6 = (flag ? (num + text.Length) : (start + text7.Length));
			TryReplace(f, start, end, text7, num6 - start);
		}

		internal static void RegexClean(TMP_InputField f, Regex regex)
		{
			GetSelection(f, out var start, out var end);
			string text = f.text;
			if (start != end)
			{
				string text2 = regex.Replace(text.Substring(start, end - start), "");
				TryReplace(f, start, end, text2, text2.Length);
			}
			else
			{
				string text3 = regex.Replace(text, "");
				TryReplace(f, 0, text.Length, text3, Mathf.Min(start, text3.Length));
			}
			SetStatus("Cleaned formatting tags (Ctrl+Z to undo)");
		}

		internal static void ClearAll(TMP_InputField f)
		{
			if (!string.IsNullOrEmpty(f.text))
			{
				TryReplace(f, 0, f.text.Length, "", 0);
				SetStatus("Cleared sign text (Ctrl+Z to undo)");
			}
		}

		internal static void FocusAndPlaceCaret(TMP_InputField inputField, int caretPos)
		{
			inputField.onFocusSelectAll = false;
			inputField.ActivateInputField();
			int num = Mathf.Clamp(caretPos, 0, inputField.text.Length);
			int num2 = StringToCaretIndex(inputField, num);
			inputField.selectionStringAnchorPosition = num;
			inputField.selectionStringFocusPosition = num;
			inputField.selectionAnchorPosition = num2;
			inputField.selectionFocusPosition = num2;
			inputField.caretPosition = num2;
			LastSelectionStart = num;
			LastSelectionEnd = num;
		}

		private static int StringToCaretIndex(TMP_InputField inputField, int stringIndex)
		{
			if (!_stringToCaretResolved)
			{
				_stringToCaretMethod = typeof(TMP_InputField).GetMethod("GetCaretPositionFromStringIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_stringToCaretResolved = true;
			}
			if (_stringToCaretMethod != null)
			{
				return (int)_stringToCaretMethod.Invoke(inputField, new object[1] { stringIndex });
			}
			return stringIndex;
		}

		private static bool IsHexCode(string s)
		{
			if (string.IsNullOrEmpty(s) || s.Length < 4 || s.Length > 6)
			{
				return false;
			}
			if (!s.All((char c) => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')))
			{
				return false;
			}
			try
			{
				int num = Convert.ToInt32(s, 16);
				return (num >= 8192 && num <= 13311) || (num >= 126976 && num <= 131071) || (num >= 65024 && num <= 65039);
			}
			catch
			{
				return false;
			}
		}

		private static string? TryGetEmojiNameFromHex(string hex)
		{
			if (KnownHexSpriteNames.TryGetValue(hex, out string value))
			{
				return value;
			}
			try
			{
				string text = char.ConvertFromUtf32(Convert.ToInt32(hex, 16));
				EmojiGroup[] emojiCatalog = EmojiCatalog;
				for (int i = 0; i < emojiCatalog.Length; i++)
				{
					EmojiItem[] items = emojiCatalog[i].Items;
					for (int j = 0; j < items.Length; j++)
					{
						EmojiItem emojiItem = items[j];
						if (emojiItem.Glyph.Equals(text, StringComparison.Ordinal) || emojiItem.Glyph.StartsWith(text, StringComparison.Ordinal) || text.StartsWith(emojiItem.Glyph, StringComparison.Ordinal))
						{
							return emojiItem.Name;
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		internal static void BuildSpriteCache(TMP_InputField inputField)
		{
			if (SignSpriteLabels != null)
			{
				return;
			}
			TMP_SpriteAsset val = (((Object)(object)inputField.textComponent != (Object)null) ? inputField.textComponent.spriteAsset : null);
			if ((Object)(object)val == (Object)null && (Object)(object)TMP_Settings.instance != (Object)null)
			{
				val = TMP_Settings.defaultSpriteAsset;
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			List<string> labelsList = new List<string>();
			List<string> tagsList = new List<string>();
			if (val.spriteCharacterTable != null && val.spriteCharacterTable.Count > 0)
			{
				for (int i = 0; i < val.spriteCharacterTable.Count; i++)
				{
					ProcessSprite(val.spriteCharacterTable[i].name, i, isTable: true);
				}
			}
			else if (val.spriteInfoList != null && val.spriteInfoList.Count > 0)
			{
				for (int j = 0; j < val.spriteInfoList.Count; j++)
				{
					ProcessSprite(val.spriteInfoList[j].name, j, isTable: false);
				}
			}
			SignSpriteLabels = labelsList.ToArray();
			SignSpriteTags = tagsList.ToArray();
			void ProcessSprite(string name, int index, bool isTable)
			{
				string text = name;
				if (string.IsNullOrEmpty(name) || name == ".notdef")
				{
					text = $"Sprite {index}";
				}
				else if (IsHexCode(name))
				{
					text = TryGetEmojiNameFromHex(name) ?? ("U+" + name.ToUpper());
				}
				else if (name.All(char.IsDigit))
				{
					text = "Sprite " + name;
				}
				else
				{
					text = text.Replace("Keyboard_", "KB ").Replace("Gamepad_", "GP ").Replace("Mouse_", "Mouse ")
						.Replace("_", " ");
					if (text.Length > 1)
					{
						text = char.ToUpper(text[0]) + text.Substring(1);
					}
				}
				string item = (isTable ? ("<sprite name=\"" + name + "\">") : $"<sprite={index}>");
				labelsList.Add(text);
				tagsList.Add(item);
			}
		}
	}
}
namespace SignScribe.UI
{
	public class StudioEscapeHandler : MonoBehaviour
	{
		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)27))
			{
				StudioBuilder.CloseStudio();
			}
		}
	}
	public static class StudioBuilder
	{
		private struct SpriteButtonItem
		{
			public GameObject ButtonObj;

			public string Tag;

			public string Label;

			public SpriteButtonItem(GameObject buttonObj, string tag, string label)
			{
				ButtonObj = buttonObj;
				Tag = tag;
				Label = label;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__CloseStudio;

			public static UnityAction<string> <1>__OnHexInputChanged;

			public static UnityAction <2>__ClearSavedColors;

			public static UnityAction<float> <3>__OnSizeSliderChanged;

			public static UnityAction<string> <4>__OnIconSearchChanged;

			public static UnityAction<string> <5>__OnSpriteSearchChanged;

			public static UnityAction<float> <6>__OnOpacityChanged;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__54_0;

			public static UnityAction<float> <>9__56_0;

			public static UnityAction<float> <>9__56_1;

			public static UnityAction<float> <>9__56_2;

			public static UnityAction <>9__56_3;

			public static UnityAction <>9__62_0;

			public static UnityAction <>9__62_1;

			public static UnityAction <>9__62_2;

			public static UnityAction <>9__62_3;

			public static UnityAction <>9__62_4;

			public static UnityAction <>9__62_5;

			public static UnityAction <>9__62_6;

			public static UnityAction <>9__62_7;

			public static UnityAction <>9__62_8;

			public static UnityAction <>9__62_9;

			public static UnityAction <>9__62_10;

			public static UnityAction <>9__62_11;

			public static UnityAction <>9__64_0;

			public static UnityAction <>9__64_1;

			public static UnityAction <>9__64_2;

			public static UnityAction <>9__68_0;

			public static UnityAction <>9__71_0;

			public static UnityAction <>9__71_1;

			public static UnityAction <>9__71_2;

			public static UnityAction <>9__71_3;

			public static UnityAction <>9__71_4;

			public static UnityAction <>9__71_5;

			public static UnityAction <>9__71_6;

			public static UnityAction <>9__71_7;

			public static UnityAction <>9__71_8;

			public static UnityAction <>9__71_9;

			public static UnityAction <>9__71_10;

			public static UnityAction <>9__71_11;

			public static UnityAction <>9__71_12;

			public static UnityAction <>9__71_13;

			public static UnityAction <>9__71_14;

			public static UnityAction <>9__71_15;

			public static UnityAction <>9__71_16;

			internal void <BuildStudio>b__54_0()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.UndoLast(_activeField);
				}
			}

			internal void <BuildColorsTab>b__56_0(float _)
			{
				OnMixerSliderChanged();
			}

			internal void <BuildColorsTab>b__56_1(float _)
			{
				OnMixerSliderChanged();
			}

			internal void <BuildColorsTab>b__56_2(float _)
			{
				OnMixerSliderChanged();
			}

			internal void <BuildColorsTab>b__56_3()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.ApplyColor(_activeField, _currentMixedHex);
				}
			}

			internal void <BuildStylesTab>b__62_0()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<b>", "</b>");
				}
			}

			internal void <BuildStylesTab>b__62_1()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<i>", "</i>");
				}
			}

			internal void <BuildStylesTab>b__62_2()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<u>", "</u>");
				}
			}

			internal void <BuildStylesTab>b__62_3()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<s>", "</s>");
				}
			}

			internal void <BuildStylesTab>b__62_4()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<uppercase>", "</uppercase>");
				}
			}

			internal void <BuildStylesTab>b__62_5()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<lowercase>", "</lowercase>");
				}
			}

			internal void <BuildStylesTab>b__62_6()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<smallcaps>", "</smallcaps>");
				}
			}

			internal void <BuildStylesTab>b__62_7()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<align=\"left\">", "</align>");
				}
			}

			internal void <BuildStylesTab>b__62_8()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<align=\"center\">", "</align>");
				}
			}

			internal void <BuildStylesTab>b__62_9()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<align=\"right\">", "</align>");
				}
			}

			internal void <BuildStylesTab>b__62_10()
			{
				object[] array = new object[5];
				Slider? sliderSize = _sliderSize;
				array[0] = ((sliderSize != null) ? new float?(sliderSize.value) : ((float?)null));
				array[1] = (((Object)(object)_activeField != (Object)null) ? "Valid" : "NULL");
				TMP_InputField? activeField = _activeField;
				array[2] = ((activeField != null) ? activeField.text : null);
				array[3] = SignScribePlugin.LastSelectionStart;
				array[4] = SignScribePlugin.LastSelectionEnd;
				SignScribePlugin.DebugLog(string.Format("[StudioBuilder ApplySize Click] Slider={0}, ActiveField={1}, ActiveFieldText='{2}', SelStart={3}, SelEnd={4}", array));
				if ((Object)(object)_activeField != (Object)null && (Object)(object)_sliderSize != (Object)null)
				{
					int num = Mathf.RoundToInt(_sliderSize.value);
					SignScribePlugin.DebugLog($"[StudioBuilder ApplySize Click] Applying absolute size {num}");
					SignScribePlugin.ApplySize(_activeField, num);
					SignScribePlugin.DebugLog("[StudioBuilder ApplySize Click] After ApplySize: ActiveFieldText='" + _activeField.text + "'");
				}
				else
				{
					ManualLogSource log = SignScribePlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[StudioBuilder ApplySize Click] FAILED: _activeField=" + (((Object)(object)_activeField != (Object)null) ? "Valid" : "NULL") + ", _sliderSize=" + (((Object)(object)_sliderSize != (Object)null) ? "Valid" : "NULL")));
					}
				}
			}

			internal void <BuildStylesTab>b__62_11()
			{
				string[] obj = new string[5]
				{
					"[StudioBuilder DefaultSize Click] ActiveField=",
					((Object)(object)_activeField != (Object)null) ? "Valid" : "NULL",
					", ActiveFieldText='",
					null,
					null
				};
				TMP_InputField? activeField = _activeField;
				obj[3] = ((activeField != null) ? activeField.text : null);
				obj[4] = "'";
				SignScribePlugin.DebugLog(string.Concat(obj));
				if ((Object)(object)_sliderSize != (Object)null)
				{
					_sliderSize.value = 6f;
				}
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.ApplySize(_activeField, 6);
					SignScribePlugin.DebugLog("[StudioBuilder DefaultSize Click] After ApplySize: ActiveFieldText='" + _activeField.text + "'");
				}
			}

			internal void <BuildIconsTab>b__64_0()
			{
				if ((Object)(object)_activeField != (Object)null && (Object)(object)_customEmojiInput != (Object)null && !string.IsNullOrEmpty(_customEmojiInput.text))
				{
					SignScribePlugin.InsertText(_activeField, _customEmojiInput.text);
				}
			}

			internal void <BuildIconsTab>b__64_1()
			{
				Application.OpenURL("https://emojipedia.org/");
			}

			internal void <BuildIconsTab>b__64_2()
			{
			}

			internal void <BuildSpritesTab>b__68_0()
			{
			}

			internal void <BuildToolsTab>b__71_0()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<sub>", "</sub>");
				}
			}

			internal void <BuildToolsTab>b__71_1()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<sup>", "</sup>");
				}
			}

			internal void <BuildToolsTab>b__71_2()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<mark=#FFFF0088>", "</mark>");
				}
			}

			internal void <BuildToolsTab>b__71_3()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<mark=#000000AA>", "</mark>");
				}
			}

			internal void <BuildToolsTab>b__71_4()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.InsertText(_activeField, "<br>");
				}
			}

			internal void <BuildToolsTab>b__71_5()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.WrapGenericTag(_activeField, "<noparse>", "</noparse>");
				}
			}

			internal void <BuildToolsTab>b__71_6()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.RegexClean(_activeField, SignScribePlugin.ColorTagRegex);
				}
			}

			internal void <BuildToolsTab>b__71_7()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.RegexClean(_activeField, SignScribePlugin.AnyTagRegex);
				}
			}

			internal void <BuildToolsTab>b__71_8()
			{
				if ((Object)(object)_activeField != (Object)null)
				{
					SignScribePlugin.ClearAll(_activeField);
				}
			}

			internal void <BuildToolsTab>b__71_9()
			{
				InsertPreset("<color=#FF6B6B><b>⚔\ufe0f Weapons</b></color>");
			}

			internal void <BuildToolsTab>b__71_10()
			{
				InsertPreset("<color=#4D96FF><b>\ud83d\udee1\ufe0f Armor</b></color>");
			}

			internal void <BuildToolsTab>b__71_11()
			{
				InsertPreset("<color=#D4A373><b>\ud83c\udf32 Materials</b></color>");
			}

			internal void <BuildToolsTab>b__71_12()
			{
				InsertPreset("<color=#FFD93D><b>\ud83e\udd69 Food</b></color>");
			}

			internal void <BuildToolsTab>b__71_13()
			{
				InsertPreset("<color=#B983FF><b>\ud83e\uddea Potions</b></color>");
			}

			internal void <BuildToolsTab>b__71_14()
			{
				InsertPreset("<color=#FFD700><b>\ud83e\ude99 Valuables</b></color>");
			}

			internal void <BuildToolsTab>b__71_15()
			{
				InsertPreset("<color=#6BCB77><b>⚡ Portal: </b></color>");
			}

			internal void <BuildToolsTab>b__71_16()
			{
				InsertPreset("<color=#FF3333><b>⚠\ufe0f Warning!</b></color>");
			}
		}

		private static GameObject? _studioPanel;

		private static RectTransform? _studioRect;

		private static CanvasGroup? _canvasGroup;

		private static TMP_InputField? _activeField;

		private static readonly string[] TabNames = new string[5] { "Icons", "Sprites", "Colors", "Styles", "Tools" };

		private static readonly GameObject?[] TabObjects = (GameObject?[])(object)new GameObject[5];

		private static readonly Text?[] TabButtonTexts = (Text?[])(object)new Text[5];

		private static int _currentTabIndex = 0;

		private static Slider? _sliderR;

		private static Slider? _sliderG;

		private static Slider? _sliderB;

		private static Text? _textR;

		private static Text? _textG;

		private static Text? _textB;

		private static Image? _colorSwatchImage;

		private static InputField? _hexInputField;

		private static bool _updatingHexInput;

		private static Text? _applyCustomBtnText;

		private static string _currentMixedHex = "#FFCC33";

		private static readonly Text?[] SavedColorTexts = (Text?[])(object)new Text[5];

		private static readonly Image?[] SavedColorImages = (Image?[])(object)new Image[5];

		private static Slider? _sliderSize;

		private static Text? _textSizeValue;

		private static Text? _applySizeBtnText;

		private static InputField? _customEmojiInput;

		private static InputField? _iconSearchInput;

		private static GameObject? _categoryContainer;

		private static GameObject? _searchContainer;

		private static GameObject? _loadingIndicator;

		private static GameObject? _iconButtonTemplate;

		private static readonly List<GameObject> _searchButtonPool = new List<GameObject>();

		private static readonly List<SignScribePlugin.EmojiItem> _allEmojis = new List<SignScribePlugin.EmojiItem>();

		private static bool _iconsPopulated = false;

		private static Coroutine? _populateCoroutine;

		private static InputField? _spriteSearchInput;

		private static GameObject? _spriteGrid;

		private static GameObject? _spriteButtonTemplate;

		private static readonly List<SpriteButtonItem> _spriteButtons = new List<SpriteButtonItem>();

		private static bool _spritesPopulated = false;

		private static Slider? _sliderOpacity;

		private static Text? _textOpacityValue;

		private static Text? _statusText;

		private static TextMeshProUGUI? _previewText;

		private static string _lastPreviewSource = "";

		public static bool IsVisible()
		{
			if ((Object)(object)_studioPanel != (Object)null)
			{
				return _studioPanel.activeSelf;
			}
			return false;
		}

		public static bool IsMouseOverStudio()
		{
			//IL_002d: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!IsVisible() || (Object)(object)_studioRect == (Object)null)
				{
					return false;
				}
				Canvas componentInParent = ((Component)_studioRect).GetComponentInParent<Canvas>();
				Camera val = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
				return RectTransformUtility.RectangleContainsScreenPoint(_studioRect, Vector2.op_Implicit(Input.mousePosition), val);
			}
			catch
			{
				return false;
			}
		}

		public static void UpdateScrollSensitivity(float sensitivity)
		{
			if ((Object)(object)_studioPanel != (Object)null)
			{
				ScrollRect[] componentsInChildren = _studioPanel.GetComponentsInChildren<ScrollRect>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].scrollSensitivity = sensitivity;
				}
			}
		}

		public static void OpenStudio(TMP_InputField inputField)
		{
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_activeField = inputField;
				if ((Object)(object)_studioPanel == (Object)null)
				{
					BuildStudio();
				}
				if (!((Object)(object)_studioPanel != (Object)null))
				{
					return;
				}
				_studioPanel.SetActive(true);
				if ((Object)(object)_previewText != (Object)null && (Object)(object)_activeField != (Object)null && (Object)(object)_activeField.textComponent != (Object)null)
				{
					((TMP_Text)_previewText).font = _activeField.textComponent.font;
					((TMP_Text)_previewText).fontSharedMaterial = _activeField.textComponent.fontSharedMaterial;
					TMP_SpriteAsset val = _activeField.textComponent.spriteAsset ?? TMP_Settings.defaultSpriteAsset;
					if ((Object)(object)val != (Object)null)
					{
						((TMP_Text)_previewText).spriteAsset = val;
					}
				}
				if ((Object)(object)_iconButtonTemplate != (Object)null && (Object)(object)_activeField != (Object)null && (Object)(object)_activeField.textComponent != (Object)null)
				{
					TextMeshProUGUI componentInChildren = _iconButtonTemplate.GetComponentInChildren<TextMeshProUGUI>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						((TMP_Text)componentInChildren).font = _activeField.textComponent.font;
						((TMP_Text)componentInChildren).fontSharedMaterial = _activeField.textComponent.fontSharedMaterial;
						if ((Object)(object)_activeField.textComponent.spriteAsset != (Object)null)
						{
							((TMP_Text)componentInChildren).spriteAsset = _activeField.textComponent.spriteAsset;
						}
					}
				}
				if ((Object)(object)_spriteButtonTemplate != (Object)null && (Object)(object)_activeField != (Object)null && (Object)(object)_activeField.textComponent != (Object)null)
				{
					TextMeshProUGUI componentInChildren2 = _spriteButtonTemplate.GetComponentInChildren<TextMeshProUGUI>();
					if ((Object)(object)componentInChildren2 != (Object)null)
					{
						((TMP_Text)componentInChildren2).font = _activeField.textComponent.font;
						((TMP_Text)componentInChildren2).fontSharedMaterial = _activeField.textComponent.fontSharedMaterial;
						if ((Object)(object)_activeField.textComponent.spriteAsset != (Object)null)
						{
							((TMP_Text)componentInChildren2).spriteAsset = _activeField.textComponent.spriteAsset;
						}
					}
				}
				if (_currentTabIndex == 0)
				{
					EnsureIconsPopulated();
				}
				else if (_currentTabIndex == 1)
				{
					EnsureSpritesPopulated();
				}
				_lastPreviewSource = "";
				OnMixerSliderChanged();
				RefreshSavedColorButtons();
				UpdatePreview();
				ManualLogSource log = SignScribePlugin.Log;
				if (log != null)
				{
					Transform parent = _studioPanel.transform.parent;
					string arg = ((parent != null) ? ((Object)parent).name : null);
					RectTransform? studioRect = _studioRect;
					log.LogInfo((object)$"SignScribe studio opened! Parent: {arg}, Position: {((studioRect != null) ? new Vector2?(studioRect.anchoredPosition) : ((Vector2?)null))}, Active: {_studioPanel.activeSelf}");
				}
			}
			catch (Exception arg2)
			{
				ManualLogSource log2 = SignScribePlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"Error in OpenStudio: {arg2}");
				}
			}
		}

		public static void CloseStudio()
		{
			//IL_0040: 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)
			if ((Object)(object)_studioPanel != (Object)null && _studioPanel.activeSelf)
			{
				RectTransform component = _studioPanel.GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null && (Object)(object)SignScribePlugin.Instance != (Object)null)
				{
					SignScribePlugin.Instance.SaveWindowPosition(component.anchoredPosition.x, component.anchoredPosition.y);
				}
				_studioPanel.SetActive(false);
				ManualLogSource log = SignScribePlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"SignScribe studio closed.");
				}
			}
		}

		public static void ToggleStudio()
		{
			if (IsVisible())
			{
				CloseStudio();
			}
			else if ((Object)(object)_activeField != (Object)null && (Object)(object)TextInput.instance != (Object)null && (((Object)(object)TextInput.instance.m_panel != (Object)null && TextInput.instance.m_panel.activeInHierarchy) || TextInput.IsVisible()))
			{
				OpenStudio(_activeField);
			}
		}

		public static void SetStatus(string message)
		{
			if ((Object)(object)_statusText != (Object)null)
			{
				_statusText.text = message;
			}
		}

		public static void UpdateStatusText()
		{
			if (!((Object)(object)_statusText == (Object)null))
			{
				if (Time.realtimeSinceStartup < SignScribePlugin.StatusUntil)
				{
					_statusText.text = SignScribePlugin.StatusMessage;
				}
				else
				{
					_statusText.text = SignScribePlugin.DefaultHint;
				}
			}
		}

		public static void UpdatePreview()
		{
			if (!((Object)(object)_activeField == (Object)null) && !((Object)(object)_previewText == (Object)null))
			{
				string text = _activeField.text ?? "";
				if (text != _lastPreviewSource)
				{
					_lastPreviewSource = text;
					string preview = SignScribePlugin.GetPreview(text);
					((TMP_Text)_previewText).text = preview;
					SignScribePlugin.DebugLog("[StudioBuilder.UpdatePreview] Source='" + text + "' -> Rendered Preview='" + preview + "'");
				}
			}
		}

		public static void BuildStudio()
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Expected O, but got Unknown
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Expected O, but got Unknown
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Expected O, but got Unknown
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Expected O, but got Unknown
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)_studioPanel != (Object)null)
				{
					Object.Destroy((Object)(object)_studioPanel);
					_studioPanel = null;
				}
				if (_populateCoroutine != null && (Object)(object)SignScribePlugin.Instance != (Object)null)
				{
					((MonoBehaviour)SignScribePlugin.Instance).StopCoroutine(_populateCoroutine);
					_populateCoroutine = null;
				}
				_iconsPopulated = false;
				_spritesPopulated = false;
				_searchButtonPool.Clear();
				_spriteButtons.Clear();
				Transform val = (((Object)(object)GUIManager.CustomGUIFront != (Object)null) ? GUIManager.CustomGUIFront.transform : (((Object)(object)TextInput.instance != (Object)null) ? ((Component)TextInput.instance).transform : null));
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = SignScribePlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"No suitable GUI parent found for SignScribe studio panel.");
					}
					return;
				}
				Vector2 sanitizedWindowPosition = SignScribePlugin.GetSanitizedWindowPosition(((Object)(object)SignScribePlugin.Instance != (Object)null) ? SignScribePlugin.Instance.PosXConfig.Value : 0f, ((Object)(object)SignScribePlugin.Instance != (Object)null) ? SignScribePlugin.Instance.PosYConfig.Value : (-20f));
				_studioPanel = GUIManager.Instance.CreateWoodpanel(val, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), sanitizedWindowPosition, 520f, 660f, true);
				((Object)_studioPanel).name = "SignScribe_StudioPanel";
				_studioRect = _studioPanel.GetComponent<RectTransform>();
				_studioRect.pivot = new Vector2(0.5f, 1f);
				_studioRect.anchoredPosition = sanitizedWindowPosition;
				_studioPanel.transform.localScale = Vector3.one;
				_canvasGroup = _studioPanel.AddComponent<CanvasGroup>();
				float alpha = (((Object)(object)SignScribePlugin.Instance != (Object)null) ? SignScribePlugin.Instance.OpacityConfig.Value : 0.95f);
				_canvasGroup.alpha = alpha;
				_studioPanel.AddComponent<StudioEscapeHandler>();
				GameObject val2 = new GameObject("StudioContent", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent(_studioPanel.transform, false);
				RectTransform component = val2.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.sizeDelta = Vector2.zero;
				component.anchoredPosition = Vector2.zero;
				GUIManager.Instance.CreateText("<color=#E08A2E>SignScribe</color> Studio", val2.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(-75f, -28f), GUIManager.Instance.AveriaSerifBold, 22, GUIManager.Instance.ValheimOrange, true, Color.black, 260f, 34f, false);
				Transform transform = val2.transform;
				Vector2 anchorMin = new Vector2(0.5f, 1f);
				Vector2 anchorMax = new Vector2(0.5f, 1f);
				Vector2 pos = new Vector2(145f, -28f);
				object obj = <>c.<>9__54_0;
				if (obj == null)
				{
					UnityAction val3 = delegate
					{
						if ((Object)(object)_activeField != (Object)null)
						{
							SignScribePlugin.UndoLast(_activeField);
						}
					};
					<>c.<>9__54_0 = val3;
					obj = (object)val3;
				}
				CreateButton("Undo", transform, anchorMin, anchorMax, pos, 65f, 30f, (UnityAction)obj, 13);
				Transform transform2 = val2.transform;
				Vector2 anchorMin2 = new Vector2(0.5f, 1f);
				Vector2 anchorMax2 = new Vector2(0.5f, 1f);
				Vector2 pos2 = new Vector2(215f, -28f);
				object obj2 = <>O.<0>__CloseStudio;
				if (obj2 == null)
				{
					UnityAction val4 = CloseStudio;
					<>O.<0>__CloseStudio = val4;
					obj2 = (object)val4;
				}
				CreateButton("✕", transform2, anchorMin2, anchorMax2, pos2, 35f, 30f, (UnityAction)obj2);
				float[] array = new float[5] { -192f, -96f,