using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using NaturalPaintLogic; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyVersion("0.1.2.0")] [BepInPlugin("com.lesly.valheim.paintyourbuild", "Paint Your Build", "0.1.2")] public sealed class NaturalPaintPlugin : BaseUnityPlugin { internal struct BrushTarget { internal Piece Piece; internal WearNTear Wear; internal Vector3 Point; } private sealed class NetworkPaintStore : IPaintStore { private readonly ZNetView _view; public bool CanWrite { get { if (Object.op_Implicit((Object)(object)_view) && _view.IsValid()) { return _view.IsOwner(); } return false; } } public int FinishId { get { return _view.GetZDO().GetInt(PaintHash, 0); } set { if (!CanWrite) { throw new InvalidOperationException("Piece ownership changed"); } _view.GetZDO().Set(PaintHash, value, false); } } internal NetworkPaintStore(ZNetView view) { _view = view; } } private sealed class PaintedPiece { internal WearNTear Wear; internal ZNetView View; internal int Saved; internal bool Highlighted; internal bool Built; internal readonly List Surfaces = new List(); } private sealed class Slot { internal int Index; internal int Property; internal Color Base; } private sealed class Surface { internal Renderer Renderer; internal PaintedPiece Piece; internal readonly List Slots = new List(); internal readonly MaterialPropertyBlock Block = new MaterialPropertyBlock(); internal bool Applied; } private sealed class GameInventory : IBrushInventory { private sealed class Snapshot { internal List Items; internal int[] Stacks; } private readonly Player _player; private readonly Inventory _inventory; internal bool LastCreatedCheated; public int FreeSlots => _inventory.GetEmptySlots(); internal GameInventory(Player player) { _player = player; _inventory = ((Humanoid)player).GetInventory(); } private static string ResourceName(string prefab) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab); if (!Object.op_Implicit((Object)(object)itemPrefab)) { throw new InvalidOperationException("Missing resource prefab " + prefab); } return itemPrefab.GetComponent().m_itemData.m_shared.m_name; } public int Count(string resource) { return _inventory.CountItems(ResourceName(resource), -1, true); } public object Capture() { List list = new List(_inventory.GetAllItems()); return new Snapshot { Items = list, Stacks = list.Select((ItemData item) => item.m_stack).ToArray() }; } public void Restore(object state) { Snapshot snapshot = (Snapshot)state; List allItems = _inventory.GetAllItems(); allItems.Clear(); allItems.AddRange(snapshot.Items); for (int i = 0; i < allItems.Count; i++) { allItems[i].m_stack = snapshot.Stacks[i]; } try { NotifyInventory.Invoke(_inventory, new object[2] { false, false }); } catch (Exception ex) { Instance.ReportOnce("rollback.notify", ex); } } public bool AddBrush() { ItemData val = CreateBrushItem(); LastCreatedCheated |= Instance._craftCompatibility.IsItemCheated(val); if (_inventory.AddItem(val)) { return _inventory.ContainsItem(val); } return false; } internal ItemData CreateBrushItem() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) ItemData val = BrushPrefab.GetComponent().m_itemData.Clone(); val.m_dropPrefab = BrushPrefab; val.m_stack = 1; val.m_quality = 1; val.m_variant = 0; val.m_worldLevel = (byte)Game.m_worldLevel; val.m_crafterID = _player.GetPlayerID(); val.m_crafterName = _player.GetPlayerName(); val.m_gridPos = new Vector2i(-1, -1); val.m_equipped = false; val.m_durability = 100f; CraftCompatibility compatibility = Instance._craftCompatibility; if (compatibility.HasItemFlag) { string woodName = ResourceName("Wood"); bool resourceCheated = _inventory.GetAllItems().Any((ItemData resource) => resource.m_shared.m_name == woodName && resource.m_worldLevel >= Game.m_worldLevel && compatibility.IsItemCheated(resource)); int? stationCheatedKey = compatibility.StationCheatedKey; CraftingStation currentCraftingStation = _player.GetCurrentCraftingStation(); object obj; if (currentCraftingStation == null) { obj = null; } else { ZNetView component = ((Component)currentCraftingStation).GetComponent(); obj = ((component != null) ? component.GetZDO() : null); } ZDO val2 = (ZDO)obj; bool stationCheated = stationCheatedKey.HasValue && val2 != null && val2.GetBool(stationCheatedKey.Value, false); compatibility.SetItemMetadata(val, _player.NoCostCheat(), resourceCheated, stationCheated); } return val; } public void Spend(string resource, int amount) { _inventory.RemoveItem(ResourceName(resource), amount, -1, true); } } private GameObject _prefabRoot; private string _brushAnimation; private ObjectDB _registeredDb; private ZNetScene _registeredScene; private bool _registering; private Sprite _icon; private readonly List _materials = new List(); private ConfigEntry _soundVolume; private Hud _brushHud; private readonly AudioSource[] _brushSources = (AudioSource[])(object)new AudioSource[4]; private AudioClip _brushSound; private AudioMixerGroup _brushMixer; private int _nextBrushSource; private const string HotbarIndicatorName = "PaintYourBuild_EquipmentIndicator"; private static FieldInfo HotbarElements; private static FieldInfo HotbarElementObject; private static MethodInfo UpdateHotbarIcons; private readonly List _hotbarIndicators = new List(); private BrushTarget _hoverTarget; private readonly Dictionary _painted = new Dictionary(); private readonly Dictionary _surfaces = new Dictionary(); private readonly List _deadPieces = new List(); private WearNTear _previewPiece; private int _previewFinish; private float _nextPaintSync; private static readonly string[] ExcludedMaterials = new string[15] { "iron", "metal", "bronze", "copper", "nail", "chain", "rope", "glass", "crystal", "snow", "wet", "flame", "particle", "fire", "smoke" }; private ConfigEntry _paletteKey; private ConfigEntry _selectedId; private GameObject _paletteCanvas; private readonly Button[] _paletteButtons = (Button[])(object)new Button[15]; private readonly Image[] _swatchImages = (Image[])(object)new Image[12]; private readonly TMP_Text[] _swatchLabels = (TMP_Text[])(object)new TMP_Text[12]; private readonly Button[] _paletteTabs = (Button[])(object)new Button[2]; private readonly PaletteReleaseGuard _releaseGuard = new PaletteReleaseGuard(); private static readonly string[] PaletteButtonsHeld = new string[13] { "JoyButtonA", "JoyButtonB", "JoyButtonX", "JoyButtonY", "JoyBuildMenu", "JoyDPadLeft", "JoyDPadRight", "JoyDPadUp", "JoyDPadDown", "JoyLBumper", "JoyRBumper", "JoyLTrigger", "JoyRTrigger" }; private TMP_Text _paletteCaption; private WearNTear _paletteTarget; private int _focusSlot; private int _pageIndex; private int _openedFrame; public const string PluginGuid = "com.lesly.valheim.paintyourbuild"; public const string PluginName = "Paint Your Build"; public const string PluginVersion = "0.1.2"; internal const string BrushPrefabName = "Lesly_Paintbrush"; internal const string PaintKey = "Lesly_PaintYourBuild_Finish_v1"; internal static readonly int PaintHash = StringExtensionMethods.GetStableHashCode("Lesly_PaintYourBuild_Finish_v1"); internal static NaturalPaintPlugin Instance; internal static GameObject BrushPrefab; internal static Recipe BrushRecipe; internal static bool Ready; private Harmony _harmony; private float _nextMaintenance; private float _nextUse; private int _lastCraftFrame = -1; private Recipe _lastSelected; private ObjectDB _selfTestDb; private bool _selfTestPassed; private ConfigEntry _diagnosticKey; private CraftCompatibility _craftCompatibility; private readonly HashSet _reportedErrors = new HashSet(); internal static FieldInfo SelectedRecipeField; internal static PropertyInfo SelectedRecipeProperty; internal static PropertyInfo SelectedItemProperty; internal static MethodInfo NativeCraftComplete; internal static MethodInfo RefreshPanel; internal static MethodInfo NotifyInventory; private static MethodInfo AddKnownRecipe; private static FieldInfo DbByHash; private static FieldInfo DbByData; private static FieldInfo SceneByHash; private static FieldInfo RemoveRayMask; private static FieldInfo SnappingIcon; internal static bool PaletteOpen { get { if (Object.op_Implicit((Object)(object)Instance) && Object.op_Implicit((Object)(object)Instance._paletteCanvas)) { return Instance._paletteCanvas.activeSelf; } return false; } } internal static bool OverlayBlocksInput { get { if (Ready && Object.op_Implicit((Object)(object)Instance)) { if (!PaletteOpen) { return Instance._releaseGuard.Blocked; } return true; } return false; } } private Finish SelectedFinish => Palette.Get(_selectedId.Value); internal static void SafeRegister(ObjectDB db) { if (!Ready || !Object.op_Implicit((Object)(object)Instance) || !Object.op_Implicit((Object)(object)db)) { return; } try { Instance.Register(db); } catch (Exception ex) { Instance.ReportOnce("registration", ex); } } private void Register(ObjectDB db) { //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown if (_registering || ((Object)(object)_registeredDb == (Object)(object)db && (Object)(object)_registeredScene == (Object)(object)ZNetScene.instance && Object.op_Implicit((Object)(object)BrushPrefab) && Object.op_Implicit((Object)(object)BrushRecipe) && (Object)(object)db.GetItemPrefab("Lesly_Paintbrush") == (Object)(object)BrushPrefab && db.m_recipes.Contains(BrushRecipe))) { return; } _registering = true; try { GameObject itemPrefab = db.GetItemPrefab("Hammer"); GameObject itemPrefab2 = db.GetItemPrefab("Wood"); if (!Object.op_Implicit((Object)(object)itemPrefab) || !Object.op_Implicit((Object)(object)itemPrefab2)) { return; } if (!Object.op_Implicit((Object)(object)BrushPrefab)) { CreatePrefab(itemPrefab); } int stableHashCode = StringExtensionMethods.GetStableHashCode("Lesly_Paintbrush"); Dictionary obj = (Dictionary)DbByHash.GetValue(db); if (obj.TryGetValue(stableHashCode, out var value) && Object.op_Implicit((Object)(object)value) && (Object)(object)value != (Object)(object)BrushPrefab) { throw new InvalidOperationException("Brush hash already belongs to " + ((Object)value).name + ". Remove duplicate mod copies."); } if (!db.m_items.Contains(BrushPrefab)) { db.m_items.Add(BrushPrefab); } obj[stableHashCode] = BrushPrefab; ItemDrop component = BrushPrefab.GetComponent(); ((Dictionary)DbByData.GetValue(db))[component.m_itemData.m_shared] = BrushPrefab; ZNetScene instance = ZNetScene.instance; if (Object.op_Implicit((Object)(object)instance)) { Dictionary obj2 = (Dictionary)SceneByHash.GetValue(instance); if (obj2.TryGetValue(stableHashCode, out value) && Object.op_Implicit((Object)(object)value) && (Object)(object)value != (Object)(object)BrushPrefab) { throw new InvalidOperationException("Duplicate brush network prefab"); } if (!instance.m_prefabs.Contains(BrushPrefab)) { instance.m_prefabs.Add(BrushPrefab); } obj2[stableHashCode] = BrushPrefab; } CraftingStation val = FindWorkbench(db, itemPrefab, instance); if (Object.op_Implicit((Object)(object)val)) { if (!Object.op_Implicit((Object)(object)BrushRecipe)) { BrushRecipe = ScriptableObject.CreateInstance(); ((Object)BrushRecipe).name = "Recipe_Paintbrush"; } BrushRecipe.m_item = component; BrushRecipe.m_amount = 1; BrushRecipe.m_enabled = true; BrushRecipe.m_noCraftOnlyUpgrade = false; BrushRecipe.m_minStationLevel = 1; BrushRecipe.m_craftingStation = val; BrushRecipe.m_repairStation = val; BrushRecipe.m_requireOnlyOneIngredient = false; BrushRecipe.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = itemPrefab2.GetComponent(), m_amount = 2, m_amountPerLevel = 0, m_recover = true } }; db.m_recipes.RemoveAll((Recipe r) => Object.op_Implicit((Object)(object)r) && (Object)(object)r != (Object)(object)BrushRecipe && IsBrushRecipe(r)); if (!db.m_recipes.Contains(BrushRecipe)) { db.m_recipes.Add(BrushRecipe); } _registeredDb = db; _registeredScene = instance; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[register.ok] prefab=Lesly_Paintbrush; hash=" + stableHashCode + "; activeSelf=" + BrushPrefab.activeSelf + "; activeInHierarchy=" + BrushPrefab.activeInHierarchy + "; station=" + val.m_name + "; cost=2 Wood; network=" + ((Object)(object)instance != (Object)null))); } } finally { _registering = false; } } private static CraftingStation FindWorkbench(ObjectDB db, GameObject hammer, ZNetScene scene) { GameObject val = (Object.op_Implicit((Object)(object)scene) ? scene.GetPrefab("piece_workbench") : null); if (Object.op_Implicit((Object)(object)val)) { return val.GetComponent(); } PieceTable buildPieces = hammer.GetComponent().m_itemData.m_shared.m_buildPieces; if (Object.op_Implicit((Object)(object)buildPieces)) { foreach (GameObject piece in buildPieces.m_pieces) { if (Object.op_Implicit((Object)(object)piece) && ((Object)piece).name == "piece_workbench") { return piece.GetComponent(); } } } foreach (Recipe recipe in db.m_recipes) { if (Object.op_Implicit((Object)(object)recipe) && Object.op_Implicit((Object)(object)recipe.m_craftingStation) && recipe.m_craftingStation.m_name == "$piece_workbench") { return recipe.m_craftingStation; } } return null; } private void CreatePrefab(GameObject hammer) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_030e: 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_0343: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_prefabRoot)) { _prefabRoot = new GameObject("NaturalPaint_PrefabRoot"); _prefabRoot.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_prefabRoot); } GameObject val = Object.Instantiate(hammer, _prefabRoot.transform, false); try { ((Object)val).name = "Lesly_Paintbrush"; val.SetActive(true); ItemDrop component = val.GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Hammer has no ItemDrop"); } _brushAnimation = hammer.GetComponent().m_itemData.m_shared.m_attack.m_attackAnimation; component.m_itemData = new ItemData(); ItemData itemData = component.m_itemData; SharedData val2 = new SharedData(); val2.m_name = "Paintbrush"; val2.m_description = "Paint wooden and stone building pieces in natural shades. Right-click or P opens the palette; left-click paints. Includes a live preview and Restore original."; val2.m_itemType = (ItemType)19; val2.m_animationState = (AnimationState)1; val2.m_maxStackSize = 1; val2.m_maxQuality = 1; val2.m_weight = 0.5f; val2.m_useDurability = false; val2.m_maxDurability = 100f; val2.m_equipDuration = 0.25f; val2.m_buildPieces = null; val2.m_dlc = ""; val2.m_attackForce = 0f; val2.m_variants = 1; val2.m_attack = new Attack(); val2.m_secondaryAttack = new Attack(); val2.m_icons = (Sprite[])(Application.isBatchMode ? ((Array)hammer.GetComponent().m_itemData.m_shared.m_icons) : ((Array)new Sprite[1] { LoadIcon() })); itemData.m_shared = val2; component.m_itemData.m_dropPrefab = val; component.m_itemData.m_quality = 1; component.m_itemData.m_stack = 1; component.m_itemData.m_durability = 100f; if (Application.isBatchMode) { BrushPrefab = val; return; } Transform val3 = val.transform.Find("attach"); if (!Object.op_Implicit((Object)(object)val3)) { throw new InvalidOperationException("Hammer attach transform missing"); } Material val4 = (from r in ((Component)val3).GetComponentsInChildren(true) select r.sharedMaterial).FirstOrDefault((Func)((Material m) => Object.op_Implicit((Object)(object)m) && Object.op_Implicit((Object)(object)m.shader))); if (!Object.op_Implicit((Object)(object)val4)) { throw new InvalidOperationException("No supported material on Hammer"); } Renderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren(true); for (int num = 0; num < componentsInChildren.Length; num++) { componentsInChildren[num].enabled = false; } Material material = ColoredMaterial(val4, new Color(0.6f, 0.4f, 0.2f), "BrushWood"); Material material2 = ColoredMaterial(val4, new Color(0.4f, 0.26f, 0.13f), "BrushBinding"); Material material3 = ColoredMaterial(val4, new Color(0.68f, 0.55f, 0.36f), "BrushBristles"); MakePart(val3, "Handle", new Vector3(0f, 0.1f, 0f), new Vector3(0.035f, 0.17f, 0.035f), material); MakePart(val3, "Binding", new Vector3(0f, 0.285f, 0f), new Vector3(0.067f, 0.04f, 0.067f), material2); for (int num2 = 0; num2 < 7; num2++) { float num3 = (float)num2 * (float)Math.PI * 2f / 7f; MakePart(val3, "Bristle" + num2, new Vector3(Mathf.Cos(num3) * 0.023f, 0.355f, Mathf.Sin(num3) * 0.023f), new Vector3(0.019f, 0.055f + (float)(num2 % 3) * 0.003f, 0.019f), material3); } BrushPrefab = val; } catch { Object.Destroy((Object)(object)val); throw; } } private Material ColoredMaterial(Material source, Color color, string name) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(source) { name = name }; if (val.HasProperty("_MainTex")) { val.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture); } if (val.HasProperty("_Color")) { val.SetColor("_Color", color); } if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", color); } _materials.Add(val); return val; } private static void MakePart(Transform parent, string name, Vector3 position, Vector3 scale, Material material) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)obj).name = name; obj.transform.SetParent(parent, false); obj.transform.localPosition = position; obj.transform.localScale = scale; Collider component = obj.GetComponent(); component.enabled = false; Object.Destroy((Object)(object)component); obj.GetComponent().sharedMaterial = material; obj.layer = ((Component)parent).gameObject.layer; } private Sprite LoadIcon() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_icon)) { return _icon; } using Stream stream = typeof(NaturalPaintPlugin).Assembly.GetManifestResourceStream("Lesly.PaintYourBuild.NaturalPaintIcon.png"); if (stream == null) { throw new InvalidOperationException("Embedded brush icon missing"); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), true)) { Object.Destroy((Object)(object)val); throw new InvalidOperationException("Invalid brush PNG"); } ((Object)val).name = "NaturalPaintIcon"; _icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 128f); return _icon; } private void ReleaseAssets() { foreach (Material material in _materials) { if (Object.op_Implicit((Object)(object)material)) { Object.Destroy((Object)(object)material); } } if (Object.op_Implicit((Object)(object)_icon)) { Object.Destroy((Object)(object)_icon.texture); Object.Destroy((Object)(object)_icon); } if (Object.op_Implicit((Object)(object)_prefabRoot)) { Object.Destroy((Object)(object)_prefabRoot); } if (Object.op_Implicit((Object)(object)BrushRecipe)) { Object.Destroy((Object)(object)BrushRecipe); } BrushRecipe = null; BrushPrefab = null; } private void BindFeedbackConfig() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown _soundVolume = ((BaseUnityPlugin)this).Config.Bind("Audio", "BrushVolume", 0.65f, new ConfigDescription("Brushing sound volume; follows the game's effects volume.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); } internal static bool BrushSelected(Player player) { if (Ready && Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer) { return IsBrush(((Humanoid)player).RightItem); } return false; } private static bool CanShowBrush(Player player) { if (BrushSelected(player)) { return CanUseTool(player); } return false; } internal void UpdateBrushHud(Hud hud, Player player) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) try { _brushHud = hud; bool flag = CanShowBrush(player) && !PaletteOpen; hud.m_buildHud.SetActive(flag); if (!flag) { if (!PaletteOpen) { ClearPreview(); } return; } if (Object.op_Implicit((Object)(object)hud.m_buildUi) && ((Component)hud.m_buildUi).gameObject.activeSelf) { hud.m_buildUi.Close(); } if (Object.op_Implicit((Object)(object)hud.m_closePieceSelectionButton)) { ((Component)hud.m_closePieceSelectionButton).gameObject.SetActive(false); } object? value = SnappingIcon.GetValue(hud); Image val = (Image)((value is Image) ? value : null); if (Object.op_Implicit((Object)(object)val)) { ((Behaviour)val).enabled = false; } hud.m_buildSelection.text = "Paint · " + SelectedFinish.Name; ((Behaviour)hud.m_buildIcon).enabled = true; hud.m_buildIcon.sprite = _icon; if (TryGetBrushTarget(player, out var target)) { _hoverTarget = target; if (PrivateArea.CheckAccess(((Component)target.Piece).transform.position, 0f, false, false)) { SetPreview(target.Wear, SelectedFinish.Id); hud.m_pieceDescription.text = "Preview · Click / attack to apply\nRight-click / P / build menu: palette"; } else { ClearPreview(); hud.m_pieceDescription.text = "Protected by a ward"; } } else { ClearHover(); hud.m_pieceDescription.text = "Aim at wood or stone within 5 metres\nRight-click / P / build menu: palette"; } GameObject[] requirementItems = hud.m_requirementItems; for (int i = 0; i < requirementItems.Length; i++) { requirementItems[i].SetActive(false); } } catch (Exception ex) { ReportOnce("paint.hud", ex); } } internal void UpdateBrushCrosshair(Hud hud, Player player) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (CanShowBrush(player) && !PaletteOpen && Object.op_Implicit((Object)(object)_hoverTarget.Wear) && Object.op_Implicit((Object)(object)_hoverTarget.Piece)) { string name = ReadFinish(_hoverTarget.Wear).Name; ((TMP_Text)hud.m_hoverName).text = Localization.instance.Localize(_hoverTarget.Piece.m_name) + "\n" + name + " · Preview: " + SelectedFinish.Name; ((Graphic)hud.m_crosshair).color = new Color(0.95f, 0.86f, 0.68f); ((Component)hud.m_pieceHealthRoot).gameObject.SetActive(true); hud.m_pieceHealthBar.SetValue(_hoverTarget.Wear.GetHealthPercentage()); } } internal void ClearHover() { _hoverTarget = default(BrushTarget); ClearPreview(); } internal void PlayBrushSound(Vector3 point) { //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) if (Application.isBatchMode || _soundVolume.Value <= 0f) { return; } try { if (!Object.op_Implicit((Object)(object)_brushSound)) { using Stream stream = typeof(NaturalPaintPlugin).Assembly.GetManifestResourceStream("Lesly.PaintYourBuild.BrushRub.wav"); PcmWave pcmWave = PcmWave.Read(stream); _brushSound = AudioClip.Create("NaturalPaint_ResinRub", pcmWave.Samples.Length / pcmWave.Channels, pcmWave.Channels, pcmWave.SampleRate, false); if (!_brushSound.SetData(pcmWave.Samples, 0)) { Object.Destroy((Object)(object)_brushSound); _brushSound = null; throw new InvalidDataException("AudioClip.SetData failed"); } } if (!Object.op_Implicit((Object)(object)_brushMixer) && Object.op_Implicit((Object)(object)AudioMan.instance)) { AudioMixer masterMixer = AudioMan.instance.m_masterMixer; if (Object.op_Implicit((Object)(object)masterMixer)) { _brushMixer = ((IEnumerable)masterMixer.FindMatchingGroups("")).FirstOrDefault((Func)((AudioMixerGroup group) => string.Equals(((Object)group).name, "SFX", StringComparison.OrdinalIgnoreCase))); } if (!Object.op_Implicit((Object)(object)_brushMixer)) { _brushMixer = AudioMan.instance.m_guiMixer; } } int num = _nextBrushSource++ % _brushSources.Length; AudioSource val = _brushSources[num]; if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = new GameObject("NaturalPaint_RubAudio" + num); val2.transform.SetParent(((Component)this).transform, false); val = val2.AddComponent(); val.playOnAwake = false; val.loop = false; val.spatialBlend = 1f; val.minDistance = 4f; val.maxDistance = 18f; val.rolloffMode = (AudioRolloffMode)1; val.dopplerLevel = 0f; _brushSources[num] = val; } ((Component)val).transform.position = point; val.outputAudioMixerGroup = _brushMixer; val.pitch = Random.Range(0.96f, 1.04f); val.PlayOneShot(_brushSound, _soundVolume.Value * (Object.op_Implicit((Object)(object)_brushMixer) ? 1f : AudioMan.GetSFXVolume())); } catch (Exception ex) { ReportOnce("brush.audio", ex); } } private void ReleaseFeedback() { ClearHover(); if (Object.op_Implicit((Object)(object)_brushHud) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && IsBrush(((Humanoid)Player.m_localPlayer).RightItem)) { _brushHud.m_buildHud.SetActive(false); } AudioSource[] brushSources = _brushSources; foreach (AudioSource val in brushSources) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)((Component)val).gameObject); } } if (Object.op_Implicit((Object)(object)_brushSound)) { Object.Destroy((Object)(object)_brushSound); } } private static void ResolveHotbarApis() { UpdateHotbarIcons = Method(typeof(HotkeyBar), "UpdateIcons", typeof(Player)); HotbarElements = Field(typeof(HotkeyBar), "m_elements"); HotbarElementObject = Field(HotbarElements.FieldType.GetGenericArguments()[0], "m_go"); } internal static void RefreshBlockedHotbar(HotkeyBar bar) { if (!Ready || !Object.op_Implicit((Object)(object)Instance)) { return; } try { UpdateHotbarIcons.Invoke(bar, new object[1] { Player.m_localPlayer }); } catch (Exception ex) { Instance.ReportOnce("hotbar.refresh", ex); } } internal void UpdateBrushHotbar(HotkeyBar bar, Player player, int selectedSlot) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown try { IList list = (IList)HotbarElements.GetValue(bar); Inventory val = ((Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead()) ? ((Humanoid)player).GetInventory() : null); bool flag = ZInput.IsGamepadActive(); for (int i = 0; i < list.Count; i++) { GameObject val2 = (GameObject)HotbarElementObject.GetValue(list[i]); if (!Object.op_Implicit((Object)(object)val2)) { continue; } ItemData val3 = ((val != null) ? val.GetItemAt(i, 0) : null); bool num = IsBrush(val3); bool flag2 = num && ((Humanoid)player).RightItem == val3; bool flag3 = num && flag && selectedSlot == i; Transform val4 = val2.transform.Find("PaintYourBuild_EquipmentIndicator"); if (Object.op_Implicit((Object)(object)val4) || flag2 || flag3) { if (!Object.op_Implicit((Object)(object)val4)) { val4 = CreateHotbarIndicator(val2.transform); } ((Component)val4).gameObject.SetActive(flag2 || flag3); ((Component)val4.GetChild(0)).gameObject.SetActive(flag3); ((Component)val4.GetChild(1)).gameObject.SetActive(flag2); val4.SetAsLastSibling(); } } } catch (Exception ex) { ReportOnce("hotbar.indicator", ex); } } private Transform CreateHotbarIndicator(Transform parent) { //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) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) RectTransform val = HotbarRect(parent, "PaintYourBuild_EquipmentIndicator", Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero); AddHotbarFrame((Transform)(object)val, "Controller focus", 0f, new Color(0.95f, 0.95f, 0.9f, 1f)); AddHotbarFrame((Transform)(object)val, "Equipped", 3f, new Color(1f, 0.77f, 0.28f, 1f)); _hotbarIndicators.RemoveAll((GameObject item) => !Object.op_Implicit((Object)(object)item)); _hotbarIndicators.Add(((Component)val).gameObject); return (Transform)(object)val; } private static RectTransform HotbarRect(Transform parent, string name, Vector2 min, Vector2 max, Vector2 offsetMin, Vector2 offsetMax) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)component).SetParent(parent, false); component.anchorMin = min; component.anchorMax = max; component.offsetMin = offsetMin; component.offsetMax = offsetMax; return component; } private static void AddHotbarFrame(Transform parent, string name, float inset, Color color) { //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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) RectTransform parent2 = HotbarRect(parent, name, Vector2.zero, Vector2.one, new Vector2(inset, inset), new Vector2(0f - inset, 0f - inset)); AddHotbarEdge((Transform)(object)parent2, "Top", new Vector2(0f, 1f), Vector2.one, new Vector2(0f, -2f), Vector2.zero, color); AddHotbarEdge((Transform)(object)parent2, "Bottom", Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 2f), color); AddHotbarEdge((Transform)(object)parent2, "Left", Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(2f, 0f), color); AddHotbarEdge((Transform)(object)parent2, "Right", new Vector2(1f, 0f), Vector2.one, new Vector2(-2f, 0f), Vector2.zero, color); } private static void AddHotbarEdge(Transform parent, string name, Vector2 min, Vector2 max, Vector2 offsetMin, Vector2 offsetMax, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)HotbarRect(parent, name, min, max, offsetMin, offsetMax)).gameObject.AddComponent(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; } private void ReleaseHotbarIndicators() { foreach (GameObject hotbarIndicator in _hotbarIndicators) { if (Object.op_Implicit((Object)(object)hotbarIndicator)) { Object.Destroy((Object)(object)hotbarIndicator); } } _hotbarIndicators.Clear(); } internal static bool CanUseTool(Player player) { if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && !((Character)player).InCutscene() && !InventoryGui.IsVisible() && !Hud.InRadial() && !Menu.IsVisible() && !Console.IsVisible() && !StoreGui.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus())) { return !GameCamera.InFreeFly(); } return false; } internal static bool IsSupported(WearNTear wear) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected I4, but got Unknown if (!Object.op_Implicit((Object)(object)wear)) { return false; } MaterialType materialType = wear.m_materialType; switch ((int)materialType) { case 0: case 1: case 3: case 4: case 5: case 6: case 8: return true; case 2: return ((Object)((Component)wear).gameObject).name.StartsWith("wood_iron", StringComparison.OrdinalIgnoreCase); default: return false; } } internal static bool TryGetBrushTarget(Player player, out BrushTarget target) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) target = default(BrushTarget); GameCamera instance = GameCamera.instance; if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)instance)) { return false; } RaycastHit val = default(RaycastHit); if (!Physics.Raycast(((Component)instance).transform.position, ((Component)instance).transform.forward, ref val, 50f, (int)RemoveRayMask.GetValue(player), (QueryTriggerInteraction)1)) { return false; } if (Vector3.Distance(((Character)player).GetEyePoint(), ((RaycastHit)(ref val)).point) > Math.Min(5f, player.m_maxPlaceDistance)) { return false; } Piece componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent(); WearNTear wear = (Object.op_Implicit((Object)(object)componentInParent) ? ((Component)componentInParent).GetComponent() : null); if (!Object.op_Implicit((Object)(object)componentInParent) || !IsSupported(wear)) { return false; } ZNetView component = ((Component)componentInParent).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { return false; } target = new BrushTarget { Piece = componentInParent, Wear = wear, Point = ((RaycastHit)(ref val)).point }; return true; } internal static Finish ReadFinish(WearNTear wear) { ZNetView val = (Object.op_Implicit((Object)(object)wear) ? ((Component)wear).GetComponent() : null); return Palette.Get((Object.op_Implicit((Object)(object)val) && val.IsValid()) ? val.GetZDO().GetInt(PaintHash, 0) : 0); } internal unsafe void UseBrush(Player player) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) if (!Ready || OverlayBlocksInput || Time.unscaledTime < _nextUse || (Object)(object)player != (Object)(object)Player.m_localPlayer || !CanUseTool(player)) { return; } _nextUse = Time.unscaledTime + 0.3f; try { if (!TryGetBrushTarget(player, out var target)) { Tell(player, "Aim at a wooden or stone building piece within 5 metres."); return; } if (!PrivateArea.CheckAccess(((Component)target.Piece).transform.position, 0f, true, false)) { Tell(player, "A ward prevents you from painting this piece."); return; } Track(target.Wear); if (!HasPaintableSurfaces(target.Wear)) { Tell(player, "This piece has no supported paint surface yet. Press F10 for details."); return; } ZNetView component = ((Component)target.Wear).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { return; } component.ClaimOwnership(); switch (PaintCommit.Apply(new NetworkPaintStore(component), SelectedFinish.Id)) { case PaintResult.NotOwner: Tell(player, "Could not acquire the piece. Please try again."); break; case PaintResult.Unchanged: Tell(player, "This piece already uses " + SelectedFinish.Name + "."); break; case PaintResult.Success: { RefreshSaved(target.Wear); PlayBrushSound(target.Point); ZSyncAnimation component2 = ((Component)player).GetComponent(); if (Object.op_Implicit((Object)(object)component2) && !string.IsNullOrEmpty(_brushAnimation)) { component2.SetTrigger(_brushAnimation); } ManualLogSource logger = ((BaseUnityPlugin)this).Logger; string[] obj = new string[8] { "[paint.ok] piece=", ((Object)((Component)target.Piece).gameObject).name, "; zdo=", null, null, null, null, null }; ZDOID uid = component.GetZDO().m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = "; finish="; obj[5] = SelectedFinish.Id.ToString(); obj[6] = ":"; obj[7] = SelectedFinish.Name; logger.LogInfo((object)string.Concat(obj)); break; } } } catch (Exception ex) { ReportOnce("paint.apply", ex); Tell(player, "Painting failed. Please send BepInEx/LogOutput.log."); } } private void DumpPaintTarget() { if (!TryGetBrushTarget(Player.m_localPlayer, out var target)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[paint.target] No supported target"); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.target] " + ((Object)((Component)target.Piece).gameObject).name + "; material=" + ((object)Unsafe.As(ref target.Wear.m_materialType)/*cast due to .constrained prefix*/).ToString() + "; saved=" + ReadFinish(target.Wear).Name)); Renderer[] componentsInChildren = ((Component)target.Wear).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if (Object.op_Implicit((Object)(object)val2)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.material] renderer=" + ((Object)val).name + "; material=" + ((Object)val2).name + "; shader=" + (Object.op_Implicit((Object)(object)val2.shader) ? ((Object)val2.shader).name : "none") + "; color=" + val2.HasProperty("_Color") + "; baseColor=" + val2.HasProperty("_BaseColor"))); } } } } internal void Track(WearNTear wear) { if (!Ready || Application.isBatchMode || !IsSupported(wear) || _painted.ContainsKey(wear) || !Object.op_Implicit((Object)(object)((Component)wear).GetComponent())) { return; } ZNetView component = ((Component)wear).GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { PaintedPiece paintedPiece = new PaintedPiece { Wear = wear, View = component, Saved = component.GetZDO().GetInt(PaintHash, 0) }; _painted.Add(wear, paintedPiece); if (Palette.IsValid(paintedPiece.Saved) && paintedPiece.Saved != 0) { ApplyPiece(paintedPiece); } } } internal void RefreshSaved(WearNTear wear) { if (_painted.TryGetValue(wear, out var value)) { value.Saved = value.View.GetZDO().GetInt(PaintHash, 0); ApplyPiece(value); } } private void TickPaintSync() { if (Application.isBatchMode || Time.unscaledTime < _nextPaintSync) { return; } _nextPaintSync = Time.unscaledTime + 0.5f; _deadPieces.Clear(); foreach (KeyValuePair item in _painted) { PaintedPiece value = item.Value; if (!Object.op_Implicit((Object)(object)value.Wear) || !Object.op_Implicit((Object)(object)value.View) || !value.View.IsValid()) { _deadPieces.Add(item.Key); continue; } int num = value.View.GetZDO().GetInt(PaintHash, 0); if (num != value.Saved) { value.Saved = num; ApplyPiece(value); } } foreach (WearNTear deadPiece in _deadPieces) { Forget(deadPiece); } if (!BrushSelected(Player.m_localPlayer) || !CanUseTool(Player.m_localPlayer)) { ClearPreview(); } } internal void SetPreview(WearNTear wear, int finish) { if (!((Object)(object)_previewPiece == (Object)(object)wear) || _previewFinish != finish) { ClearPreview(); Track(wear); if (_painted.TryGetValue(wear, out var value)) { _previewPiece = wear; _previewFinish = finish; ApplyPiece(value); } } } internal void ClearPreview() { WearNTear previewPiece = _previewPiece; _previewPiece = null; if (Object.op_Implicit((Object)(object)previewPiece) && _painted.TryGetValue(previewPiece, out var value)) { ApplyPiece(value); } } internal bool HasPaintableSurfaces(WearNTear wear) { if (!_painted.TryGetValue(wear, out var value)) { return false; } BuildSurfaces(value); return value.Surfaces.Count > 0; } private void BuildSurfaces(PaintedPiece entry) { //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) if (entry.Built) { return; } entry.Built = true; Renderer[] componentsInChildren = ((Component)entry.Wear).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)) || (Object)(object)((Component)val).GetComponentInParent() != (Object)(object)entry.Wear || (Object)(object)val == (Object)(object)entry.Wear.m_snow || (Object)(object)val == (Object)(object)entry.Wear.m_snowWorn || (Object)(object)val == (Object)(object)entry.Wear.m_snowBroken || (Object.op_Implicit((Object)(object)entry.Wear.m_wet) && ((Component)val).transform.IsChildOf(entry.Wear.m_wet.transform))) { continue; } Surface surface = new Surface { Renderer = val, Piece = entry }; Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.shader)) { continue; } string text = ((Object)val2).name.ToLowerInvariant() + " " + ((Object)val).name.ToLowerInvariant(); bool flag = false; string[] excludedMaterials = ExcludedMaterials; foreach (string value in excludedMaterials) { if (text.Contains(value)) { flag = true; break; } } if (flag && ((Object)val2).name.ToLowerInvariant().Contains("wood") && !((Object)val2).name.ToLowerInvariant().Contains("snow")) { flag = false; } if (flag || val2.renderQueue >= 3000) { continue; } int num = (val2.HasProperty("_Color") ? Shader.PropertyToID("_Color") : (val2.HasProperty("_BaseColor") ? Shader.PropertyToID("_BaseColor") : (-1))); if (num != -1) { val.GetPropertyBlock(surface.Block, j); if (surface.Block.isEmpty) { surface.Slots.Add(new Slot { Index = j, Property = num, Base = val2.GetColor(num) }); } } } if (surface.Slots.Count != 0) { entry.Surfaces.Add(surface); _surfaces[val] = surface; } } } private void ApplyPiece(PaintedPiece entry) { int num = (((Object)(object)entry.Wear == (Object)(object)_previewPiece) ? _previewFinish : entry.Saved); if (num != 0 && Palette.IsValid(num)) { BuildSurfaces(entry); } foreach (Surface surface in entry.Surfaces) { ApplySurface(surface); } } private void ApplySurface(Surface surface) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)surface.Renderer)) { return; } int num = (((Object)(object)surface.Piece.Wear == (Object)(object)_previewPiece) ? _previewFinish : surface.Piece.Saved); if (num == 0 || !Palette.IsValid(num) || surface.Piece.Highlighted) { RestoreSurface(surface); return; } Finish finish = Palette.Get(num); foreach (Slot slot in surface.Slots) { surface.Renderer.GetPropertyBlock(surface.Block); surface.Block.SetColor(slot.Property, new Color(slot.Base.r * finish.R, slot.Base.g * finish.G, slot.Base.b * finish.B, slot.Base.a)); surface.Renderer.SetPropertyBlock(surface.Block, slot.Index); } surface.Applied = true; } private static void RestoreSurface(Surface surface) { if (!surface.Applied || !Object.op_Implicit((Object)(object)surface.Renderer)) { return; } foreach (Slot slot in surface.Slots) { surface.Renderer.SetPropertyBlock((MaterialPropertyBlock)null, slot.Index); } surface.Applied = false; } internal void NativeMaterialsUpdated(List renderers) { if (_surfaces.Count == 0) { return; } foreach (Renderer renderer in renderers) { if (Object.op_Implicit((Object)(object)renderer) && _surfaces.TryGetValue(renderer, out var value)) { ApplySurface(value); } } } internal void SetHighlight(WearNTear wear, bool highlighted) { if (_painted.TryGetValue(wear, out var value)) { value.Highlighted = highlighted; ApplyPiece(value); } } internal void Forget(WearNTear wear) { if (!_painted.TryGetValue(wear, out var value)) { return; } foreach (Surface surface in value.Surfaces) { RestoreSurface(surface); _surfaces.Remove(surface.Renderer); } _painted.Remove(wear); if ((Object)(object)_previewPiece == (Object)(object)wear) { _previewPiece = null; } } private void ReleasePaint() { _previewPiece = null; foreach (Surface value in _surfaces.Values) { RestoreSurface(value); } _surfaces.Clear(); _painted.Clear(); } private void BindPaintConfig() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) _paletteKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "PaletteKey", new KeyboardShortcut((KeyCode)112, Array.Empty()), "Open the natural colour palette while the paintbrush is equipped."); _selectedId = ((BaseUnityPlugin)this).Config.Bind("Palette", "SelectedFinish", 2, "Last selected natural finish. IDs 0 through 24; 0 restores the original appearance."); } private bool PaletteInputHeld() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) string[] paletteButtonsHeld = PaletteButtonsHeld; for (int i = 0; i < paletteButtonsHeld.Length; i++) { if (ZInput.GetButton(paletteButtonsHeld[i])) { return true; } } if (!ZInput.GetMouseButton(0) && !ZInput.GetMouseButton(1)) { KeyboardShortcut value = _paletteKey.Value; if (!ZInput.GetKey(((KeyboardShortcut)(ref value)).MainKey, true) && !ZInput.GetKey((KeyCode)13, true) && !ZInput.GetKey((KeyCode)271, true) && !ZInput.GetKey((KeyCode)27, true) && !ZInput.GetKey((KeyCode)276, true) && !ZInput.GetKey((KeyCode)275, true) && !ZInput.GetKey((KeyCode)273, true) && !ZInput.GetKey((KeyCode)274, true) && !(Mathf.Abs(ZInput.GetJoyLeftStickX(false)) > 0.25f)) { return Mathf.Abs(ZInput.GetJoyLeftStickY(false)) > 0.25f; } } return true; } private void TickPalette() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) if (Application.isBatchMode) { return; } Player localPlayer = Player.m_localPlayer; try { if (!PaletteOpen && _releaseGuard.Blocked) { if (!Object.op_Implicit((Object)(object)localPlayer)) { _releaseGuard.Reset(); } else { _releaseGuard.Tick(Time.frameCount, PaletteInputHeld()); } } KeyboardShortcut value; if (!BrushSelected(localPlayer) || !CanUseTool(localPlayer)) { if (PaletteOpen) { ClosePalette(); } } else if (PaletteOpen) { if (Time.frameCount == _openedFrame) { return; } value = _paletteKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() || ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("JoyButtonB")) { ClosePalette(); return; } if (ZInput.GetButtonDown("JoyLBumper") || ZInput.GetKeyDown((KeyCode)280, true)) { SetPalettePage(0); } else if (ZInput.GetButtonDown("JoyRBumper") || ZInput.GetKeyDown((KeyCode)281, true)) { SetPalettePage(1); } if (ZInput.GetKeyDown((KeyCode)276, true) || ZInput.GetButtonDown("JoyDPadLeft") || ZInput.GetButtonDown("JoyLStickLeft")) { FocusSlot(PaletteLayout.Move(_focusSlot, -1, 0)); } else if (ZInput.GetKeyDown((KeyCode)275, true) || ZInput.GetButtonDown("JoyDPadRight") || ZInput.GetButtonDown("JoyLStickRight")) { FocusSlot(PaletteLayout.Move(_focusSlot, 1, 0)); } else if (ZInput.GetKeyDown((KeyCode)273, true) || ZInput.GetButtonDown("JoyDPadUp") || ZInput.GetButtonDown("JoyLStickUp")) { FocusSlot(PaletteLayout.Move(_focusSlot, 0, -1)); } else if (ZInput.GetKeyDown((KeyCode)274, true) || ZInput.GetButtonDown("JoyDPadDown") || ZInput.GetButtonDown("JoyLStickDown")) { FocusSlot(PaletteLayout.Move(_focusSlot, 0, 1)); } if (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true) || ZInput.GetButtonDown("JoyButtonA")) { ActivateSlot(_focusSlot); } } else if (!_releaseGuard.Blocked && !(Time.unscaledTime < _nextUse)) { value = _paletteKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() || ZInput.GetButtonDown("BuildMenu") || ZInput.GetButtonDown("JoyBuildMenu")) { OpenPalette(); } } } catch (Exception ex) { ReportOnce("paint.palette", ex); ClosePalette(); } } private void OpenPalette() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_paletteCanvas)) { CreatePalette(); } _paletteTarget = ((TryGetBrushTarget(Player.m_localPlayer, out var target) && PrivateArea.CheckAccess(((Component)target.Piece).transform.position, 0f, false, false)) ? target.Wear : null); _releaseGuard.Reset(); _paletteCanvas.SetActive(true); _openedFrame = Time.frameCount; _nextUse = Time.unscaledTime + 0.3f; _pageIndex = PaletteLayout.PageFor(SelectedFinish.Id); _focusSlot = PaletteLayout.SlotFor(_pageIndex, SelectedFinish.Id); SetPalettePage(_pageIndex); if (Object.op_Implicit((Object)(object)EventSystem.current)) { EventSystem.current.SetSelectedGameObject((GameObject)null); } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } internal void ClosePalette() { if (Object.op_Implicit((Object)(object)_paletteCanvas) && _paletteCanvas.activeSelf) { _paletteCanvas.SetActive(false); _releaseGuard.Arm(Time.frameCount); _nextUse = Time.unscaledTime + 0.3f; _paletteTarget = null; ClearPreview(); if (Object.op_Implicit((Object)(object)EventSystem.current)) { EventSystem.current.SetSelectedGameObject((GameObject)null); } } } private void SetPalettePage(int page) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (page >= 0 && page < PaletteLayout.Pages.Length) { _pageIndex = page; Color color = default(Color); for (int i = 0; i < 12; i++) { Finish finish = Palette.Get(PaletteLayout.Pages[page][i]); _swatchLabels[i].text = finish.Name; ColorUtility.TryParseHtmlString(finish.Swatch, ref color); ((Graphic)_swatchImages[i]).color = color; } for (int j = 0; j < _paletteTabs.Length; j++) { ((Graphic)((Component)_paletteTabs[j]).GetComponent()).color = ((j == page) ? new Color(0.38f, 0.3f, 0.18f) : new Color(0.16f, 0.15f, 0.13f)); } FocusSlot(_focusSlot); } } internal void FocusSlot(int slot) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (slot >= 0 && slot < 15) { _focusSlot = slot; int num = ((slot < 12) ? PaletteLayout.Pages[_pageIndex][slot] : 0); Finish finish = Palette.Get(num); switch (slot) { case 13: _paletteCaption.text = (Object.op_Implicit((Object)(object)_paletteTarget) ? ("Copy saved finish: " + ReadFinish(_paletteTarget).Name) : "Aim at a piece before opening the palette"); break; case 14: _paletteCaption.text = "Close the palette"; break; default: _paletteCaption.text = ((num == 0) ? "Restore this piece's original finish" : (finish.Name + " · " + ((finish.Group == "Wood") ? "Natural wood stain" : "Natural stone finish"))); break; } for (int i = 0; i < _paletteButtons.Length; i++) { ((Graphic)((Component)_paletteButtons[i]).GetComponent()).color = ((i == slot) ? new Color(0.38f, 0.3f, 0.18f, 1f) : new Color(0.16f, 0.15f, 0.13f, 1f)); } if (Object.op_Implicit((Object)(object)_paletteTarget) && slot <= 12) { SetPreview(_paletteTarget, num); } else { ClearPreview(); } } } private void ActivateSlot(int slot) { if (!PaletteOpen) { return; } if (slot >= 0 && slot < 12) { SelectFinish(PaletteLayout.Pages[_pageIndex][slot]); return; } switch (slot) { case 12: SelectFinish(0); break; case 13: CopyTarget(); break; case 14: ClosePalette(); break; } } private void SelectFinish(int id) { if (Palette.IsValid(id)) { _selectedId.Value = id; ((BaseUnityPlugin)this).Config.Save(); ClosePalette(); Tell(Player.m_localPlayer, "Selected: " + Palette.Get(id).Name); } } private void CopyTarget() { if (!Object.op_Implicit((Object)(object)_paletteTarget)) { _paletteCaption.text = "Aim at a building piece before opening the palette"; } else { SelectFinish(ReadFinish(_paletteTarget).Id); } } private RectTransform Box(Transform parent, string name, Vector2 size, Vector2 pos, Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val.GetComponent(); ((Transform)component).SetParent(parent, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 1f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = size; component.anchoredPosition = pos; ((Graphic)val.GetComponent()).color = color; return component; } private TMP_Text Label(Transform parent, string text, float size, Vector2 dimensions, Vector2 position, TextAlignmentOptions align = (TextAlignmentOptions)513) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Label", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); RectTransform component = val.GetComponent(); ((Transform)component).SetParent(parent, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 1f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = dimensions; component.anchoredPosition = position; TextMeshProUGUI component2 = val.GetComponent(); ((TMP_Text)component2).font = ((Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)Hud.instance.m_pieceDescription)) ? Hud.instance.m_pieceDescription.font : TMP_Settings.defaultFontAsset); ((TMP_Text)component2).text = text; ((TMP_Text)component2).fontSize = size; ((Graphic)component2).color = new Color(0.94f, 0.9f, 0.82f); ((TMP_Text)component2).alignment = align; ((Graphic)component2).raycastTarget = false; return (TMP_Text)(object)component2; } private Button ActionButton(Transform parent, string name, Vector2 size, Vector2 pos, Action action) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Box(parent, name, size, pos, new Color(0.23f, 0.21f, 0.17f)); Button obj = ((Component)val).gameObject.AddComponent