Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PaintYourBuild v1.10.0
BepInEx/plugins/PaintYourBuild/PaintYourBuild.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BrushCameraCompatibility; using HarmonyLib; using Microsoft.CodeAnalysis; using NaturalPaintLogic; using PaintCameraLogic; using PaintFixtureSupport; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.UI; using ValheimBuildCamera; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("1.6.15")] [assembly: AssemblyVersion("1.6.15.0")] [BepInPlugin("valheim.paintyourbuild", "Paint Your Build", "1.6.15")] public sealed class NaturalPaintPlugin : BaseUnityPlugin { private enum BuildingStage { None, Selecting, Detecting, Review, Running } private sealed class BuildingRecord { internal Piece Piece; internal ZDOID Id; internal ZNetView View; internal int Finish; internal float Opacity; internal float OwnershipDeadline; internal int AppliedFinish; internal float AppliedOpacity = -1f; } internal struct BrushTarget { internal Piece Piece; internal WearNTear Wear; internal NaturalPaintLogic.PaintMaterial Kind; 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 Piece Piece; internal WearNTear Wear; internal NaturalPaintLogic.PaintMaterial Kind; internal ZNetView View; internal int Saved; internal float Opacity = -1f; internal bool Highlighted; internal bool Built; internal readonly List<Surface> Surfaces = new List<Surface>(); } 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<Slot> Slots = new List<Slot>(); internal readonly MaterialPropertyBlock Block = new MaterialPropertyBlock(); internal bool Applied; } private sealed class GameInventory : IBrushInventory { private sealed class Snapshot { internal List<ItemData> 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<ItemDrop>().m_itemData.m_shared.m_name; } public int Count(string resource) { return _inventory.CountItems(ResourceName(resource), -1, true); } public object Capture() { List<ItemData> list = new List<ItemData>(_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<ItemData> 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<ItemDrop>().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<ZNetView>(); 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<Material> _materials = new List<Material>(); private ConfigEntry<KeyboardShortcut> _cameraKey; private ConfigEntry<KeyboardShortcut> _cameraResetKey; private ConfigEntry<bool> _cameraController; private ConfigEntry<bool> _cameraHideBody; private ConfigEntry<bool> _cameraExitDamage; private ConfigEntry<float> _cameraSpeed; private ConfigEntry<float> _cameraFast; private ConfigEntry<float> _cameraRadius; private ConfigEntry<float> _cameraReach; private ConfigEntry<float> _cameraMultiplier; private ConfigEntry<float> _cameraPitch; private ConfigEntry<float> _cameraFov; private readonly CameraToggleInput _cameraToggle = new CameraToggleInput(); private readonly Dictionary<Renderer, bool> _hiddenBody = new Dictionary<Renderer, bool>(); private readonly List<Renderer> _bodyRenderers = new List<Renderer>(32); private readonly List<Renderer> _retiredBody = new List<Renderer>(8); private bool _paintCamera; private bool _cameraChord; private int _cameraFrame = -1; private float _cameraSuppressUntil; private float _nextBodyScan; private float _flightYaw; private float _flightPitch; private float _flightFov; private Player _cameraPlayer; private GameCamera _paintGameCamera; private Camera _paintLens; private Camera _paintSky; private Vector3 _bodyAnchor; private Vector3 _flightPosition; private Vector3 _previousCameraPosition; private Quaternion _flightRotation; private Quaternion _previousCameraRotation; private float _previousFov; private float _previousSkyFov; private float _previousNearClip; private BaseUnityPlugin _externalBuildCamera; private FieldInfo _externalCameraActive; private MethodInfo _externalCameraStop; private ConfigEntry<float> _soundVolume; private Hud _brushHud; private readonly AudioSource[] _brushSources = (AudioSource[])(object)new AudioSource[4]; private AudioClip _brushSound; private AudioMixerGroup _brushMixer; private int _nextBrushSource; private static FieldInfo HotbarElements; private static FieldInfo HotbarElementEquipped; private static MethodInfo UpdateHotbarIcons; private BuildingStage _buildingStage; private BuildingConnectivity _buildingGraph; private readonly List<PaintedPiece> _buildingCandidates = new List<PaintedPiece>(); private readonly List<PaintedPiece> _buildingNodes = new List<PaintedPiece>(); private int _buildingScanIndex; private int _buildingSeedIndex; private int _buildingCollectIndex; private int _buildingProtected; private bool _buildingGraphStarted; private bool _buildingHasBounds; private readonly List<Bounds> _buildingNodeBounds = new List<Bounds>(); private Piece _buildingSeed; private NaturalPaintLogic.PaintMaterial _buildingClearMaterial; private Vector3 _buildingSeedPosition; private int _buildingOutsideScope; private int _buildingInvalidBounds; private Bounds _buildingBounds; private Player _buildingPlayer; private Player _undoPlayer; private readonly List<BuildingRecord> _buildingSelection = new List<BuildingRecord>(); private readonly List<BuildingRecord> _buildingUndo = new List<BuildingRecord>(); private readonly Queue<BuildingRecord> _buildingQueue = new Queue<BuildingRecord>(); private bool _buildingIsUndo; private bool _buildingStartedUndoRecord; private int _buildingChanged; private int _buildingSkipped; private int _buildingReviewFrame; private GameObject _buildingCanvas; private TMP_Text _buildingMessage; private TMP_Text _buildingTitle; private Button _buildingConfirm; private Button _buildingCancel; private Button _buildingEdit; private readonly HashSet<Piece> _buildingPreviewPieces = new HashSet<Piece>(); private static readonly Color BuildingPreviewColour = new Color(0.12f, 0.65f, 0.28f, 1f); private bool _buildingMultiPaint; private int _multiFinish; private float _multiOpacity; private BrushTarget _hoverTarget; private readonly Dictionary<Piece, PaintedPiece> _painted = new Dictionary<Piece, PaintedPiece>(); private readonly Dictionary<Renderer, Surface> _surfaces = new Dictionary<Renderer, Surface>(); private readonly List<Piece> _deadPieces = new List<Piece>(); private Piece _previewPiece; private int _previewFinish; private float _previewOpacity = -1f; private float _nextPaintSync; private ConfigEntry<KeyboardShortcut> _paletteKey; private ConfigEntry<int> _selectedId; private ConfigEntry<float> _selectedOpacity; private GameObject _paletteCanvas; private readonly Button[] _paletteButtons = (Button[])(object)new Button[21]; private readonly Image[] _swatchImages = (Image[])(object)new Image[15]; private readonly TMP_Text[] _swatchLabels = (TMP_Text[])(object)new TMP_Text[15]; private TMP_Text _pageTitle; private TMP_Text _pageHint; private TMP_Text _opacityLabel; private TMP_Text _colourSetLabel; private GameObject _colourSetControls; private int _colourSet; private GameObject _opacityControls; private Slider _opacitySlider; private float _paletteOpacity = -1f; 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 Piece _paletteTarget; private int _focusSlot; private int _pageIndex; private int _lastPageIndex; private int _openedFrame; private bool _explicitPaletteToolSwitch; public const string PluginGuid = "valheim.paintyourbuild"; public const string PluginName = "Paint Your Build"; public const string PluginVersion = "1.6.15"; internal const string BrushPrefabName = "PaintYourBuild_Paintbrush"; internal const int LegacyBrushHash = -1067267138; internal static readonly int PaintHash = -945813667; internal static readonly int CrystalOpacityHash = StringExtensionMethods.GetStableHashCode("PaintYourBuild.CrystalOpacity"); 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<KeyboardShortcut> _diagnosticKey; private CraftCompatibility _craftCompatibility; private readonly HashSet<string> _reportedErrors = new HashSet<string>(); 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 const int ExpectedPatchCount = 42; private Queue<PaintedPiece> _syncQueue; private int _syncFrame; private int _syncChecked; private int _syncChanged; private double _syncMs; private double _syncMax; private float _syncNextReport; internal bool PaintCameraActive { get { if (Ready) { return _paintCamera; } return false; } } internal bool CameraInputSuppressed { get { if (!_cameraChord) { return Time.unscaledTime < _cameraSuppressUntil; } return true; } } internal bool CameraOwnsControls { get { if (!PaintCameraActive) { return CameraInputSuppressed; } return true; } } internal float CameraPaintReach => CameraMath.FreeCameraRange(_cameraReach.Value, 5f, _cameraMultiplier.Value); private float CameraRadius => CameraMath.FreeCameraRange(_cameraRadius.Value, 8f, _cameraMultiplier.Value); private bool BuildingClearActive => _buildingStage != BuildingStage.None; private bool BuildingModalOpen { get { if (_buildingStage != BuildingStage.Detecting && _buildingStage != BuildingStage.Review) { return _buildingStage == BuildingStage.Running; } return true; } } private string BuildingSelectionHint { get { if (_buildingStage != BuildingStage.Selecting) { return "Detecting house…"; } return "Multi-paint · " + Palette.Get(_multiFinish).Name + " · " + _buildingSelection.Count + " selected\nClick / attack: select or deselect\nRight-click / Enter / Y: review · P / Esc / B: cancel"; } } 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 && !Instance.BuildingModalOpen) { return Instance._releaseGuard.Blocked; } return true; } return false; } } internal static bool PaintModalOpen { get { if (!PaletteOpen) { if (Object.op_Implicit((Object)(object)Instance)) { return Instance.BuildingModalOpen; } return false; } return true; } } internal static bool ExplicitPaletteToolSwitch { get { if (Object.op_Implicit((Object)(object)Instance)) { return Instance._explicitPaletteToolSwitch; } 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_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: 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("PaintYourBuild_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("PaintYourBuild_Paintbrush"); Dictionary<int, GameObject> obj = (Dictionary<int, GameObject>)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; obj[-1067267138] = BrushPrefab; ItemDrop component = BrushPrefab.GetComponent<ItemDrop>(); ((Dictionary<SharedData, GameObject>)DbByData.GetValue(db))[component.m_itemData.m_shared] = BrushPrefab; ZNetScene instance = ZNetScene.instance; if (Object.op_Implicit((Object)(object)instance)) { Dictionary<int, GameObject> obj2 = (Dictionary<int, GameObject>)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; obj2[-1067267138] = BrushPrefab; } CraftingStation val = FindWorkbench(db, itemPrefab, instance); if (Object.op_Implicit((Object)(object)val)) { if (!Object.op_Implicit((Object)(object)BrushRecipe)) { BrushRecipe = ScriptableObject.CreateInstance<Recipe>(); ((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<ItemDrop>(), 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=PaintYourBuild_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<CraftingStation>(); } PieceTable buildPieces = hammer.GetComponent<ItemDrop>().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<CraftingStation>(); } } } 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<GameObject>(hammer, _prefabRoot.transform, false); try { ((Object)val).name = "PaintYourBuild_Paintbrush"; val.SetActive(true); ItemDrop component = val.GetComponent<ItemDrop>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Hammer has no ItemDrop"); } _brushAnimation = hammer.GetComponent<ItemDrop>().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<ItemDrop>().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<Renderer>(true) select r.sharedMaterial).FirstOrDefault((Func<Material, bool>)((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<Renderer>(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<Collider>(); component.enabled = false; Object.Destroy((Object)(object)component); obj.GetComponent<Renderer>().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("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 BindCameraConfig() { //IL_001b: 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) _cameraKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Camera controls", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Enter/leave painting free camera; only while Paintbrush is equipped."); _cameraResetKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Camera controls", "ResetViewKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Reset the active painting camera."); _cameraController = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera controls", "ControllerStickToggle", true, "Press both stick buttons together to toggle. Release both before toggling again."); _cameraHideBody = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera view", "HideLocalPlayer", true, "Hide the local character on this client during painting camera. Your body remains in the world."); _cameraExitDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera safety", "ExitOnDamage", true, "Return to the normal camera when your body takes damage."); _cameraSpeed = CameraFloat("MoveSpeed", 6f, 1f, 15f, "Flight speed in metres per second."); _cameraFast = CameraFloat("FastMultiplier", 2f, 1f, 3f, "Hold Run to fly faster."); _cameraRadius = CameraFloat("CameraRadius", 25f, 8f, 25f, "Base radius around your body. Multiplied by FreeCameraRangeMultiplier."); _cameraReach = CameraFloat("PaintReach", 25f, 5f, 25f, "Base painting reach from your body, only in painting free camera. Normal reach is unchanged."); _cameraMultiplier = CameraFloat("FreeCameraRangeMultiplier", 2f, 1f, 2f, "Default camera radius and painting reach: 25 x 2 = 50 metres. Matches Build Camera 0.1.13."); ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Painting camera", "Range50mUpgradeApplied", false, "Tracks the one-time 0.1.4 upgrade to a 50-metre camera radius and painting reach."); if (!val.Value) { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; try { _cameraRadius.Value = 25f; _cameraReach.Value = 25f; _cameraMultiplier.Value = 2f; val.Value = true; ((BaseUnityPlugin)this).Config.Save(); } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[paint.camera] Range upgraded: camera radius=50m; paint reach=50m."); } _cameraPitch = CameraFloat("StartingPitch", 50f, 20f, 75f, "Initial downward viewing angle."); _cameraFov = CameraFloat("FieldOfView", 45f, 25f, 75f, "Initial FOV. Page Up/Down zoom outside the palette."); } private ConfigEntry<float> CameraFloat(string key, float value, float min, float max, string description) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<float>("Painting camera", key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } internal bool EnsureBrushSession() { if (Application.isBatchMode) { return false; } Player localPlayer = Player.m_localPlayer; bool flag = ((Behaviour)this).isActiveAndEnabled && BrushSessionRules.CanStay(BrushSelected(localPlayer), Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead(), Object.op_Implicit((Object)(object)localPlayer) && (((Character)localPlayer).IsTeleporting() || ((Character)localPlayer).InCutscene() || ((Character)localPlayer).IsAttached() || localPlayer.GetDoodadController() != null)); if (flag && _paintCamera) { flag = (Object)(object)localPlayer == (Object)(object)_cameraPlayer && Object.op_Implicit((Object)(object)_paintGameCamera) && (Object)(object)_paintGameCamera == (Object)(object)GameCamera.instance && Object.op_Implicit((Object)(object)_paintLens); } if (flag) { return true; } ClosePalette(); StopBrushCamera("Brush unequipped or player/camera changed"); ClearHover(); _cameraToggle.Reset(waitForRelease: true); _cameraChord = false; _cameraSuppressUntil = 0f; return false; } internal void TickBrushCamera() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) TickClearBuildingView(); if (!Ready || Application.isBatchMode || _cameraFrame == Time.frameCount) { return; } _cameraFrame = Time.frameCount; try { if (!EnsureBrushSession()) { return; } ReleaseExternalBuildCamera(); if (ZInput.instance == null || !Application.isFocused) { return; } bool flag = ZInput.GetButton("JoyLStick"); bool flag2 = ZInput.GetButton("JoyRStick"); Gamepad current = Gamepad.current; if (current != null) { flag |= current.leftStickButton.isPressed; flag2 |= current.rightStickButton.isPressed; } bool flag3 = CameraModal() || OverlayBlocksInput; bool flag4 = _cameraController.Value && !flag3; _cameraChord = flag4 && flag && flag2; CameraToggleInput cameraToggle = _cameraToggle; int frameCount = Time.frameCount; KeyboardShortcut value = _cameraKey.Value; if (cameraToggle.Step(frameCount, ((KeyboardShortcut)(ref value)).IsDown(), !flag3, flag, flag2, flag4, Time.unscaledDeltaTime)) { if (_paintCamera) { StopBrushCamera("Toggled off"); } else { StartBrushCamera(Player.m_localPlayer); } } else { if (!_paintCamera) { return; } if (!flag3 && !BuildingClearActive && ZInput.GetKeyDown((KeyCode)27, true)) { StopBrushCamera("Escape"); return; } KeepPaintBodyStill(); if (!flag3) { value = _cameraResetKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ResetPaintCamera(); } } if (!flag3 && !CameraInputSuppressed) { MovePaintCamera(); } ApplyPaintCameraPose(); } } catch (Exception ex) { StopBrushCamera("Camera error"); ClosePalette(); ReportOnce("paint.camera", ex); } } private static bool CameraModal() { try { return !CanUseTool(Player.m_localPlayer) || UnifiedPopup.IsVisible() || (Object.op_Implicit((Object)(object)TextViewer.instance) && TextViewer.instance.IsVisible()) || PlayerCustomizaton.IsBarberGuiVisible() || (Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Game.IsPaused()); } catch (NullReferenceException) { return true; } } private void StartBrushCamera(Player player) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) if (!BrushSelected(player) || CameraModal() || OverlayBlocksInput) { return; } if (!((Character)player).IsOnGround() || ((Character)player).IsSwimming()) { Tell(player, "Stand on solid ground to enter the painting camera."); return; } _paintGameCamera = GameCamera.instance; _paintLens = (Object.op_Implicit((Object)(object)_paintGameCamera) ? ((Component)_paintGameCamera).GetComponent<Camera>() : null); if (Object.op_Implicit((Object)(object)_paintLens) && !GameCamera.InFreeFly()) { _paintSky = _paintGameCamera.m_skyCamera; _cameraPlayer = player; _bodyAnchor = ((Component)player).transform.position; _previousCameraPosition = ((Component)_paintGameCamera).transform.position; _previousCameraRotation = ((Component)_paintGameCamera).transform.rotation; _previousFov = _paintLens.fieldOfView; _previousNearClip = _paintLens.nearClipPlane; _previousSkyFov = (Object.op_Implicit((Object)(object)_paintSky) ? _paintSky.fieldOfView : _previousFov); _paintCamera = true; player.m_autoRun = false; ((Character)player).StopMovement(); player.SetControls(Vector3.zero, false, false, false, false, false, false, false, false, false, false, false); ((Character)player).m_onDamaged = (Action<float, Character>)Delegate.Combine(((Character)player).m_onDamaged, new Action<float, Character>(PaintCameraDamaged)); ResetPaintCamera(); HidePaintBody(); _cameraSuppressUntil = Time.unscaledTime + 0.2f; ApplyPaintCameraPose(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.camera] ON; radius=" + CameraRadius + "; paint reach=" + CameraPaintReach)); } } private void ResetPaintCamera() { //IL_000c: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Quaternion rotation = ((Character)_cameraPlayer).m_eye.rotation; _flightYaw = ((Quaternion)(ref rotation)).eulerAngles.y; _flightPitch = CameraMath.Clamp(_cameraPitch.Value, 50f, 20f, 75f); _flightFov = CameraMath.Clamp(_cameraFov.Value, 45f, 25f, 75f); _flightRotation = Quaternion.Euler(_flightPitch, _flightYaw, 0f); Vector3 val = _bodyAnchor + Quaternion.Euler(0f, _flightYaw, 0f) * Vector3.forward * 5f + Vector3.up; _flightPosition = val - _flightRotation * Vector3.forward * 12f; ClampPaintCamera(); } private void MovePaintCamera() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_0044: 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) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) float num = CameraMath.Clamp(Time.unscaledDeltaTime, 0f, 0f, 0.05f); Vector2 val = Vector2.zero; if (ZInput.IsMouseActive()) { val = ZInput.GetMouseDelta() * (ZInput.IsGamepadMouseActive() ? PlayerController.m_switchMouseSens : PlayerController.m_mouseSens); if (PlayerController.m_invertMouse) { val.y *= -1f; } } else if (ZInput.IsGamepadActive()) { val = new Vector2(StickInput.RightStickX(), 0f - StickInput.RightStickY()) * 110f * num * PlayerController.m_gamepadSens; if (PlayerController.m_invertCameraX) { val.x *= -1f; } if (PlayerController.m_invertCameraY) { val.y *= -1f; } } _flightYaw = Mathf.Repeat(_flightYaw + val.x, 360f); _flightPitch = Mathf.Clamp(_flightPitch - val.y, -80f, 85f); if (ZInput.GetKey((KeyCode)280, true)) { _flightFov -= 25f * num; } if (ZInput.GetKey((KeyCode)281, true)) { _flightFov += 25f * num; } _flightFov = Mathf.Clamp(_flightFov, 25f, 75f); _flightRotation = Quaternion.Euler(_flightPitch, _flightYaw, 0f); float x = (float)((ZInput.GetButton("Right") ? 1 : 0) - (ZInput.GetButton("Left") ? 1 : 0)) + StickInput.LeftStickX(); float z = (float)((ZInput.GetButton("Forward") ? 1 : 0) - (ZInput.GetButton("Backward") ? 1 : 0)) - StickInput.LeftStickY(); float y = ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) ? 1 : 0) - ((ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) ? 1 : 0); CameraMath.NormalizeInput(ref x, ref y, ref z); MovementVector movementVector = CameraMath.ViewRelativeMovement(_flightYaw, _flightPitch, x, y, z); CameraMath.NormalizeInput(ref movementVector.X, ref movementVector.Y, ref movementVector.Z); float num2 = CameraMath.Clamp(_cameraSpeed.Value, 6f, 1f, 15f); if (ZInput.GetButton("Run") || ZInput.GetButton("JoyRun")) { num2 *= CameraMath.Clamp(_cameraFast.Value, 2f, 1f, 3f); } _flightPosition += new Vector3(movementVector.X, movementVector.Y, movementVector.Z) * num2 * num; ClampPaintCamera(); } private void ClampPaintCamera() { //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_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_0012: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _bodyAnchor + Vector3.up; Vector3 val2 = _flightPosition - val; CameraMath.ClampToSphere(ref val2.x, ref val2.y, ref val2.z, CameraRadius); _flightPosition = val + val2; } private void KeepPaintBodyStill() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_cameraPlayer)) { Vector3 val = ((Component)_cameraPlayer).transform.position - _bodyAnchor; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { ((Component)_cameraPlayer).transform.position = _bodyAnchor; Physics.SyncTransforms(); } ((Character)_cameraPlayer).StopMovement(); } } internal void ApplyPaintCameraPose() { //IL_0030: 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_0039: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) if (!_paintCamera || !Object.op_Implicit((Object)(object)_paintLens) || !Object.op_Implicit((Object)(object)_paintGameCamera)) { return; } Transform transform = ((Component)_paintGameCamera).transform; Vector3 position = transform.position; if (((Vector3)(ref position)).Equals(_flightPosition)) { Quaternion rotation = transform.rotation; if (((Quaternion)(ref rotation)).Equals(_flightRotation)) { goto IL_006d; } } transform.SetPositionAndRotation(_flightPosition, _flightRotation); goto IL_006d; IL_006d: if (_paintLens.fieldOfView != _flightFov) { _paintLens.fieldOfView = _flightFov; } float num = Mathf.Min(_previousNearClip, 0.1f); if (_paintLens.nearClipPlane != num) { _paintLens.nearClipPlane = num; } if (Object.op_Implicit((Object)(object)_paintSky) && _paintSky.fieldOfView != _flightFov) { _paintSky.fieldOfView = _flightFov; } } private void HidePaintBody() { if (!_cameraHideBody.Value) { RestorePaintBody(); return; } GameObject val = (Object.op_Implicit((Object)(object)_cameraPlayer) ? ((Character)_cameraPlayer).GetVisual() : null); if (!Object.op_Implicit((Object)(object)val)) { return; } _bodyRenderers.Clear(); val.GetComponentsInChildren<Renderer>(true, _bodyRenderers); foreach (Renderer bodyRenderer in _bodyRenderers) { if (Object.op_Implicit((Object)(object)bodyRenderer)) { if (!_hiddenBody.ContainsKey(bodyRenderer)) { _hiddenBody.Add(bodyRenderer, bodyRenderer.forceRenderingOff); } bodyRenderer.forceRenderingOff = true; } } _retiredBody.Clear(); foreach (KeyValuePair<Renderer, bool> item in _hiddenBody) { if (!Object.op_Implicit((Object)(object)item.Key)) { _retiredBody.Add(item.Key); } else if ((Object)(object)((Component)item.Key).transform != (Object)(object)val.transform && !((Component)item.Key).transform.IsChildOf(val.transform)) { item.Key.forceRenderingOff = item.Value; _retiredBody.Add(item.Key); } } foreach (Renderer item2 in _retiredBody) { _hiddenBody.Remove(item2); } _retiredBody.Clear(); _bodyRenderers.Clear(); } private void RestorePaintBody() { foreach (KeyValuePair<Renderer, bool> item in _hiddenBody) { try { if (Object.op_Implicit((Object)(object)item.Key)) { item.Key.forceRenderingOff = item.Value; } } catch (Exception ex) { ReportOnce("camera.renderer.restore", ex); } } _hiddenBody.Clear(); _bodyRenderers.Clear(); _retiredBody.Clear(); } internal void StopBrushCamera(string reason) { //IL_0122: 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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) ClearBuildingView.Stop(); _cameraToggle.CancelPending(); if (!_paintCamera) { return; } _paintCamera = false; try { if (Object.op_Implicit((Object)(object)_cameraPlayer)) { Player cameraPlayer = _cameraPlayer; ((Character)cameraPlayer).m_onDamaged = (Action<float, Character>)Delegate.Remove(((Character)cameraPlayer).m_onDamaged, new Action<float, Character>(PaintCameraDamaged)); } } catch (Exception ex) { ReportOnce("camera.damage.restore", ex); } RestorePaintBody(); try { if (Object.op_Implicit((Object)(object)_paintLens)) { _paintLens.fieldOfView = _previousFov; _paintLens.nearClipPlane = _previousNearClip; } if (Object.op_Implicit((Object)(object)_paintSky)) { _paintSky.fieldOfView = _previousSkyFov; } if (Object.op_Implicit((Object)(object)_cameraPlayer) && (Object)(object)_cameraPlayer == (Object)(object)Player.m_localPlayer && !((Character)_cameraPlayer).IsTeleporting() && !((Character)_cameraPlayer).InCutscene() && !((Character)_cameraPlayer).IsAttached() && _cameraPlayer.GetDoodadController() == null) { Vector3 val = ((Component)_cameraPlayer).transform.position - _bodyAnchor; if (((Vector3)(ref val)).sqrMagnitude < 1f && Object.op_Implicit((Object)(object)_paintGameCamera) && (Object)(object)_paintGameCamera == (Object)(object)GameCamera.instance && !GameCamera.InFreeFly()) { ((Component)_paintGameCamera).transform.SetPositionAndRotation(_previousCameraPosition, _previousCameraRotation); } } } catch (Exception ex2) { ReportOnce("camera.pose.restore", ex2); } _cameraPlayer = null; _paintGameCamera = null; _paintLens = null; _paintSky = null; _cameraSuppressUntil = Time.unscaledTime + 0.2f; ClearHover(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.camera] OFF: " + reason)); } private void PaintCameraDamaged(float damage, Character attacker) { if (_paintCamera && _cameraExitDamage.Value && damage > 0f) { ClosePalette(); StopBrushCamera("Player damaged"); } } private void LateUpdate() { if (!Ready || Application.isBatchMode) { return; } try { if (EnsureBrushSession() && _paintCamera) { KeepPaintBodyStill(); ApplyPaintCameraPose(); if (Time.unscaledTime >= _nextBodyScan) { HidePaintBody(); _nextBodyScan = Time.unscaledTime + 0.25f; } } } catch (Exception ex) { StopBrushCamera("Camera error"); ReportOnce("paint.camera.late", ex); } } private void OnDisable() { CancelBuildingClear(); ClosePalette(); StopBrushCamera("Plugin disabled"); _cameraToggle.Reset(waitForRelease: true); _releaseGuard.Reset(); _cameraChord = false; _cameraSuppressUntil = 0f; } private void OnApplicationFocus(bool focused) { ClearBuildingView.FocusChanged(focused); if (!focused) { CancelBuildingClear(); ClosePalette(); StopBrushCamera("Focus lost"); _cameraToggle.Reset(waitForRelease: true); } } private void ReleaseExternalBuildCamera() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_externalBuildCamera)) { if (!Chainloader.PluginInfos.TryGetValue("valheim.buildcamera", out var value) || !Object.op_Implicit((Object)(object)value.Instance)) { return; } _externalBuildCamera = value.Instance; Type type = ((object)_externalBuildCamera).GetType(); _externalCameraActive = AccessTools.Field(type, "_active"); _externalCameraStop = AccessTools.Method(type, "StopCamera", new Type[2] { typeof(string), typeof(bool) }, (Type[])null); MethodInfo methodInfo = AccessTools.Method(type, "StartCamera", new Type[1] { typeof(Player) }, (Type[])null); if (methodInfo != null && _harmony != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(NaturalPaintPlugin), "AllowStandaloneBuildCameraStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } if (_externalCameraActive != null && (bool)_externalCameraActive.GetValue(_externalBuildCamera)) { if (_externalCameraStop == null) { throw new InvalidOperationException("Exit the standalone build camera before using the paintbrush."); } _externalCameraStop.Invoke(_externalBuildCamera, new object[2] { "Paintbrush selected", false }); } } private static bool AllowStandaloneBuildCameraStart() { return !BrushSelected(Player.m_localPlayer); } 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<float>("Audio", "BrushVolume", 0.65f, new ConfigDescription("Brushing sound volume; follows the game's effects volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); } 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: 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_0238: Unknown result type (might be due to invalid IL or missing references) try { _brushHud = hud; bool flag = CanShowBrush(player) && !PaintModalOpen; 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 = (PaintCameraActive ? "Paint camera · " : "Paint · ") + SelectedFinish.Name; ((Behaviour)hud.m_buildIcon).enabled = true; hud.m_buildIcon.sprite = _icon; GameObject[] requirementItems; if (BuildingClearActive) { ClearHover(); hud.m_buildSelection.text = (_buildingMultiPaint ? ("Multi-paint · " + _buildingSelection.Count + " selected") : "Clear building colours"); hud.m_pieceDescription.text = BuildingSelectionHint; requirementItems = hud.m_requirementItems; for (int i = 0; i < requirementItems.Length; i++) { requirementItems[i].SetActive(false); } return; } if (TryGetBrushTarget(player, out var target)) { _hoverTarget = target; if (PrivateArea.CheckAccess(((Component)target.Piece).transform.position, 0f, false, false)) { bool flag2 = MaterialRules.Accepts(target.Kind, SelectedFinish.Id); SetPreview(target.Piece, SelectedFinish.Id, _selectedOpacity.Value); hud.m_pieceDescription.text = (flag2 ? "Preview · Click / attack to apply" : ("Select a " + target.Kind.ToString().ToLowerInvariant() + " finish")); TMP_Text pieceDescription = hud.m_pieceDescription; pieceDescription.text = pieceDescription.text + "\nRight-click / P: palette · " + ((object)_cameraKey.Value/*cast due to .constrained prefix*/).ToString() + ": free camera"; } else { ClearPreview(); hud.m_pieceDescription.text = "Protected by a ward"; } } else { ClearHover(); hud.m_pieceDescription.text = (PaintCameraActive ? ("Aim at a building piece within " + CameraPaintReach + " metres of your body") : "Aim at a building piece or furniture within 5 metres") + "\nRight-click / P: palette · " + ((object)_cameraKey.Value/*cast due to .constrained prefix*/).ToString() + ": free camera"; } 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_00ff: Unknown result type (might be due to invalid IL or missing references) if (CanShowBrush(player) && !PaintModalOpen && !BuildingClearActive && Object.op_Implicit((Object)(object)_hoverTarget.Piece)) { string name = ReadFinish(_hoverTarget.Piece).Name; bool flag = MaterialRules.Accepts(_hoverTarget.Kind, SelectedFinish.Id); ((TMP_Text)hud.m_hoverName).text = Localization.instance.Localize(_hoverTarget.Piece.m_name) + "\n<color=#F3DCAD>" + name + "</color> · " + (flag ? ("Preview: " + SelectedFinish.Name) : ("Requires " + _hoverTarget.Kind.ToString().ToLowerInvariant() + " paint")); ((Graphic)hud.m_crosshair).color = new Color(0.95f, 0.86f, 0.68f); ((Component)hud.m_pieceHealthRoot).gameObject.SetActive((Object)(object)_hoverTarget.Wear != (Object)null); if (Object.op_Implicit((Object)(object)_hoverTarget.Wear)) { 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("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<AudioMixerGroup>)masterMixer.FindMatchingGroups("")).FirstOrDefault((Func<AudioMixerGroup, bool>)((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<AudioSource>(); 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"); HotbarElementEquipped = Field(HotbarElements.FieldType.GetGenericArguments()[0], "m_equiped"); } 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown try { if (!Object.op_Implicit((Object)(object)player)) { return; } IList list = (IList)HotbarElements.GetValue(bar); Inventory inventory = ((Humanoid)player).GetInventory(); for (int i = 0; i < list.Count; i++) { ItemData itemAt = inventory.GetItemAt(i, 0); if (IsBrush(itemAt)) { GameObject val = (GameObject)HotbarElementEquipped.GetValue(list[i]); if (Object.op_Implicit((Object)(object)val)) { val.SetActive(!((Character)player).IsDead() && ((Humanoid)player).RightItem == itemAt); } } } } catch (Exception ex) { ReportOnce("hotbar.indicator", ex); } } private void StartBuildingSelection() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) Piece paletteTarget = _paletteTarget; if (!Object.op_Implicit((Object)(object)paletteTarget)) { _paletteCaption.text = "Aim at a house wall or floor, then reopen the palette"; return; } _buildingClearMaterial = ClassifyPiece(paletteTarget); if (_buildingClearMaterial == NaturalPaintLogic.PaintMaterial.Unsupported) { _paletteCaption.text = "Aim at a supported building material first"; return; } ClosePalette(); ClearHover(); _buildingPlayer = Player.m_localPlayer; _buildingIsUndo = false; _buildingMultiPaint = false; _buildingSelection.Clear(); _buildingCandidates.Clear(); _buildingNodes.Clear(); _buildingNodeBounds.Clear(); _buildingSeedPosition = ((Component)paletteTarget).transform.position; _buildingOutsideScope = 0; _buildingInvalidBounds = 0; foreach (PaintedPiece value in _painted.Values) { if (Object.op_Implicit((Object)(object)value.Piece) && ((Component)value.Piece).gameObject.activeInHierarchy && Object.op_Implicit((Object)(object)value.View) && value.View.IsValid() && BatchPaintRules.SameClearMaterial(_buildingClearMaterial, ClassifyPiece(value.Piece))) { if (!InBuildingScope(((Component)value.Piece).transform.position)) { _buildingOutsideScope++; } else { _buildingCandidates.Add(value); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.batch.detect] material=" + _buildingClearMaterial.ToString() + "; candidates=" + _buildingCandidates.Count + "; outsideScope=" + _buildingOutsideScope)); if (_buildingCandidates.Count > 20000) { FailBuilding("Too many nearby loaded pieces. Use Multi-paint with Restore original to select specific pieces."); return; } _buildingSeed = paletteTarget; _buildingSeedIndex = -1; _buildingScanIndex = 0; _buildingGraph = new BuildingConnectivity(); _buildingGraphStarted = false; _buildingHasBounds = false; _buildingCollectIndex = 0; _buildingProtected = 0; if (!Object.op_Implicit((Object)(object)_buildingCanvas)) { CreateBuildingWindow(); } _buildingStage = BuildingStage.Detecting; _buildingMessage.text = "Finding connected " + MaterialRules.DisplayName(_buildingClearMaterial) + " pieces…\nOther material types are excluded.\nEsc / B: cancel"; _buildingTitle.text = "FINDING HOUSE PIECES"; ((Component)_buildingConfirm).gameObject.SetActive(false); ((Component)_buildingEdit).gameObject.SetActive(false); ((Component)_buildingCancel).gameObject.SetActive(true); _buildingCanvas.SetActive(true); } private bool TryBuildingBounds(Piece piece, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if (!val.enabled || val.isTrigger || (Object)(object)((Component)val).GetComponentInParent<Piece>() != (Object)(object)piece) { continue; } Bounds bounds2 = val.bounds; Vector3 size = ((Bounds)(ref bounds2)).size; if (!(((Vector3)(ref size)).sqrMagnitude < 0.0001f)) { if (!flag) { bounds = bounds2; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(bounds2); } } } return flag; } private void TickBuildingDetection() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_009b: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) Stopwatch stopwatch = Stopwatch.StartNew(); int num = 0; while (_buildingScanIndex < _buildingCandidates.Count && num++ < 64 && stopwatch.ElapsedMilliseconds < 2) { PaintedPiece paintedPiece = _buildingCandidates[_buildingScanIndex++]; if (Object.op_Implicit((Object)(object)paintedPiece.Piece) && Object.op_Implicit((Object)(object)paintedPiece.View) && paintedPiece.View.IsValid() && BatchPaintRules.SameClearMaterial(_buildingClearMaterial, ClassifyPiece(paintedPiece.Piece)) && TryBuildingBounds(paintedPiece.Piece, out var bounds)) { Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; int buildingSeedIndex; try { buildingSeedIndex = _buildingGraph.Add(new BuildingBox(min.x, min.y, min.z, max.x, max.y, max.z)); } catch (InvalidOperationException) { _buildingInvalidBounds++; continue; } _buildingNodes.Add(paintedPiece); _buildingNodeBounds.Add(bounds); if ((Object)(object)paintedPiece.Piece == (Object)(object)_buildingSeed) { _buildingSeedIndex = buildingSeedIndex; } } } if (_buildingScanIndex < _buildingCandidates.Count) { return; } if (!_buildingGraphStarted) { if (!Object.op_Implicit((Object)(object)_buildingSeed) || _buildingSeedIndex < 0) { FailBuilding("Aim at a solid house wall or floor and try again."); return; } _buildingGraph.Start(_buildingSeedIndex); _buildingSeed = null; _buildingGraphStarted = true; } num = 0; while (!_buildingGraph.Complete && num++ < 2048 && stopwatch.ElapsedMilliseconds < 2) { _buildingGraph.Step(); } if (!_buildingGraph.Complete) { return; } num = 0; while (_buildingCollectIndex < _buildingGraph.Selected.Count && num++ < 64 && stopwatch.ElapsedMilliseconds < 2) { int index = _buildingGraph.Selected[_buildingCollectIndex++]; PaintedPiece paintedPiece2 = _buildingNodes[index]; if (!Object.op_Implicit((Object)(object)paintedPiece2.Piece) || !Object.op_Implicit((Object)(object)paintedPiece2.View) || !paintedPiece2.View.IsValid() || !BatchPaintRules.SameClearMaterial(_buildingClearMaterial, ClassifyPiece(paintedPiece2.Piece))) { continue; } if (!InBuildingScope(((Component)paintedPiece2.Piece).transform.position)) { _buildingOutsideScope++; continue; } Bounds val = _buildingNodeBounds[index]; if (!_buildingHasBounds) { _buildingBounds = val; _buildingHasBounds = true; } else { ((Bounds)(ref _buildingBounds)).Encapsulate(val); } int finish = paintedPiece2.View.GetZDO().GetInt(PaintHash, 0); float opacity = paintedPiece2.View.GetZDO().GetFloat(CrystalOpacityHash, -1f); if (BuildingClearRules.Changed(finish, opacity)) { if (!PrivateArea.CheckAccess(((Component)paintedPiece2.Piece).transform.position, 0f, false, false)) { _buildingProtected++; continue; } _buildingSelection.Add(new BuildingRecord { Id = paintedPiece2.View.GetZDO().m_uid, Piece = paintedPiece2.Piece, View = paintedPiece2.View, Finish = finish, Opacity = opacity }); HighlightBuildingPiece(paintedPiece2.Piece); } } if (_buildingCollectIndex >= _buildingGraph.Selected.Count) { if (_buildingSelection.Count > 10000) { FailBuilding("Too many coloured pieces. Use Multi-paint with Restore original to select specific pieces."); return; } if (!_buildingHasBounds) { FailBuilding("The selected house is no longer loaded. Nothing changed."); return; } ShowBuildingReview("Clear colours from " + _buildingSelection.Count + " connected " + MaterialRules.DisplayName(_buildingClearMaterial) + " pieces?\nGREEN surfaces = selected pieces. Hidden pieces are included in the count.\nOnly " + MaterialRules.DisplayName(_buildingClearMaterial) + ". Other material types stay unchanged.\n" + _buildingProtected + " protected pieces skipped. Unhighlighted pieces stay unchanged.\nWithin 64 m of target and 96 m of you. Undo last batch is available."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.batch.preview] material=" + _buildingClearMaterial.ToString() + "; selected=" + _buildingSelection.Count + "; protected=" + _buildingProtected + "; invalidBounds=" + _buildingInvalidBounds)); _buildingGraph = null; _buildingCandidates.Clear(); _buildingNodes.Clear(); _buildingNodeBounds.Clear(); } } private void PreviewBuildingUndo() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_undoPlayer != (Object)(object)Player.m_localPlayer) { _buildingUndo.Clear(); } if (_buildingUndo.Count == 0) { _paletteCaption.text = "No batch to undo in this session"; return; } ClosePalette(); ClearHover(); _buildingPlayer = Player.m_localPlayer; _buildingIsUndo = true; _buildingMultiPaint = false; _buildingSelection.Clear(); foreach (BuildingRecord item in _buildingUndo) { ResolveBuildingRecord(item); if (Object.op_Implicit((Object)(object)item.Piece) && Object.op_Implicit((Object)(object)item.View) && item.View.IsValid() && PrivateArea.CheckAccess(((Component)item.Piece).transform.position, 0f, false, false) && BuildingClearRules.Matches(item.View.GetZDO().GetInt(PaintHash, 0), item.View.GetZDO().GetFloat(CrystalOpacityHash, -1f), item.AppliedFinish, item.AppliedOpacity)) { _buildingSelection.Add(item); HighlightBuildingPiece(item.Piece); } } ShowBuildingReview("Restore colours on up to " + _buildingSelection.Count + " pieces?\nGREEN surfaces = previous colours will be restored.\nRepainted, unloaded, missing or protected pieces are skipped.\nUndo is available only in this play session. B / Esc cancels."); } private void ShowBuildingReview(string message) { if (!Object.op_Implicit((Object)(object)_buildingCanvas)) { CreateBuildingWindow(); } _buildingStage = BuildingStage.Review; _buildingReviewFrame = Time.frameCount; _buildingTitle.text = (_buildingIsUndo ? "UNDO LAST BATCH" : (_buildingMultiPaint ? "APPLY MULTI-PAINT" : "CLEAR HOUSE COLOURS")); _buildingMessage.text = message; ((Component)_buildingEdit).gameObject.SetActive(_buildingMultiPaint && !_buildingIsUndo); ((Component)_buildingConfirm).gameObject.SetActive(true); ((Selectable)_buildingConfirm).interactable = _buildingSelection.Count != 0; ((Component)_buildingCancel).gameObject.SetActive(true); _buildingCanvas.SetActive(true); _releaseGuard.Arm(Time.frameCount); ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } private void CreateBuildingWindow() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) _buildingCanvas = new GameObject("PaintYourBuild_ClearBuilding", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); _buildingCanvas.transform.SetParent(((Component)this).transform, false); Canvas component = _buildingCanvas.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 30001; CanvasScaler component2 = _buildingCanvas.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1600f, 900f); component2.matchWidthOrHeight = 0.5f; RectTransform parent = Box(_buildingCanvas.transform, "Clear building colours", new Vector2(900f, 290f), new Vector2(0f, -35f), new Color(0.09f, 0.085f, 0.072f, 0.97f)); _buildingTitle = Label((Transform)(object)parent, "CLEAR HOUSE COLOURS", 28f, new Vector2(840f, 42f), new Vector2(0f, -14f), (TextAlignmentOptions)514); _buildingMessage = Label((Transform)(object)parent, "", 21f, new Vector2(840f, 166f), new Vector2(0f, -60f), (TextAlignmentOptions)514); _buildingConfirm = ActionButton((Transform)(object)parent, "Confirm · Enter / A", new Vector2(260f, 46f), new Vector2(-285f, -230f), BeginBuildingOperation); _buildingEdit = ActionButton((Transform)(object)parent, "Edit selection · Y", new Vector2(260f, 46f), new Vector2(0f, -230f), ReturnToMultiSelection); ((Component)_buildingEdit).gameObject.SetActive(false); _buildingCancel = ActionButton((Transform)(object)parent, "Cancel / stop · Esc / B", new Vector2(260f, 46f), new Vector2(285f, -230f), CancelBuildingClear); } private void BeginBuildingOperation() { if (_buildingStage != BuildingStage.Review || _buildingSelection.Count == 0 || _releaseGuard.Blocked || Time.frameCount <= _buildingReviewFrame) { return; } ClearBuildingPreview(); _buildingStartedUndoRecord = false; _buildingQueue.Clear(); foreach (BuildingRecord item in _buildingSelection) { item.OwnershipDeadline = 0f; _buildingQueue.Enqueue(item); } _buildingChanged = (_buildingSkipped = 0); _buildingStage = BuildingStage.Running; ((Component)_buildingEdit).gameObject.SetActive(false); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.batch.start] mode=" + (_buildingIsUndo ? "undo" : (_buildingMultiPaint ? "paint" : "clear")) + "; count=" + _buildingSelection.Count)); ((Component)_buildingConfirm).gameObject.SetActive(false); if (Object.op_Implicit((Object)(object)EventSystem.current)) { EventSystem.current.SetSelectedGameObject((GameObject)null); } ClearPreview(); } private void TickBuildingClear() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (_undoPlayer != null && _undoPlayer != Player.m_localPlayer) { _buildingUndo.Clear(); _undoPlayer = null; } if (!BuildingClearActive) { return; } try { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)localPlayer != (Object)(object)_buildingPlayer || !BrushSelected(localPlayer) || !CanUseTool(localPlayer)) { CancelBuildingClear(); return; } if (!ZInput.GetKeyDown((KeyCode)27, true) && !ZInput.GetButtonDown("JoyButtonB")) { KeyboardShortcut value = _paletteKey.Value; if (!((KeyboardShortcut)(ref value)).IsDown()) { if (_buildingStage == BuildingStage.Selecting) { if (!_releaseGuard.Blocked && Time.unscaledTime >= _nextUse && (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true) || ZInput.GetButtonDown("JoyButtonY") || ZInput.GetButtonDown("BuildMenu") || ZInput.GetButtonDown("JoyBuildMenu"))) { ReviewMultiPaint(); } return; } if (_buildingStage == BuildingStage.Review && _buildingMultiPaint && !_releaseGuard.Blocked && ZInput.GetButtonDown("JoyButtonY")) { ReturnToMultiSelection(); return; } if (_buildingStage == BuildingStage.Detecting) { TickBuildingDetection(); return; } if (_buildingStage == BuildingStage.Review && !_releaseGuard.Blocked && Time.frameCount > _buildingReviewFrame && (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true) || ZInput.GetButtonDown("JoyButtonA"))) { BeginBuildingOperation(); } if (_buildingStage != BuildingStage.Running) { return; } Stopwatch stopwatch = Stopwatch.StartNew(); int num = Math.Min(8, _buildingQueue.Count); while (num-- > 0 && stopwatch.ElapsedMilliseconds < 2 && _buildingQueue.Count > 0) { BuildingRecord record = _buildingQueue.Dequeue(); try { ProcessBuildingRecord(record); } catch (Exception ex) { _buildingSkipped++; ReportOnce("paint.building.piece", ex); } } _buildingMessage.text = (_buildingIsUndo ? "Restoring colours…" : (_buildingMultiPaint ? "Painting selected pieces…" : "Clearing colours…")) + "\nChanged: " + _buildingChanged + " · Skipped: " + _buildingSkipped + " · Remaining: " + _buildingQueue.Count + "\nYou can stop now; completed changes remain undoable."; if (_buildingQueue.Count == 0) { CancelBuildingClear(); } return; } } CancelBuildingClear(); } catch (Exception ex2) { ReportOnce("paint.building", ex2); FailBuilding("Batch stopped: " + ex2.GetType().Name + ". Details are in LogOutput.log; completed changes can be undone."); } } private void ResolveBuildingRecord(BuildingRecord record) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if ((!Object.op_Implicit((Object)(object)record.Piece) || !Object.op_Implicit((Object)(object)record.View) || !record.View.IsValid()) && Object.op_Implicit((Object)(object)ZNetScene.instance)) { GameObject val = ZNetScene.instance.FindInstance(record.Id); if (Object.op_Implicit((Object)(object)val)) { record.Piece = val.GetComponent<Piece>(); record.View = val.GetComponent<ZNetView>(); } } } private void ProcessBuildingRecord(BuildingRecord record) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) ResolveBuildingRecord(record); if (!Object.op_Implicit((Object)(object)record.Piece) || !Object.op_Implicit((Object)(object)record.View) || !record.View.IsValid() || Vector3.Distance(((Component)record.Piece).transform.position, ((Component)_buildingPlayer).transform.position) > 96f || !PrivateArea.CheckAccess(((Component)record.Piece).transform.position, 0f, false, false)) { _buildingSkipped++; return; } if (!_buildingIsUndo && (!_buildingMultiPaint || _multiFinish == 0) && !BatchPaintRules.SameClearMaterial(_buildingClearMaterial, ClassifyPiece(record.Piece))) { _buildingSkipped++; return; } ZDO zDO = record.View.GetZDO(); int num = (_buildingIsUndo ? record.AppliedFinish : record.Finish); float num2 = (_buildingIsUndo ? record.AppliedOpacity : record.Opacity); if (!BuildingClearRules.Matches(zDO.GetInt(PaintHash, 0), zDO.GetFloat(CrystalOpacityHash, -1f), num, num2)) { _buildingSkipped++; return; } if (_buildingMultiPaint && !MaterialRules.Accepts(ClassifyPiece(record.Piece), _multiFinish)) { _buildingSkipped++; return; } if (!record.View.IsOwner()) { if (record.OwnershipDeadline == 0f) { record.OwnershipDeadline = Time.unscaledTime + 2f; record.View.ClaimOwnership(); } if (!record.View.IsOwner()) { if (Time.unscaledTime < record.OwnershipDeadline) { _buildingQueue.Enqueue(record); } else { _buildingSkipped++; } return; } } int num3 = (_buildingIsUndo ? record.Finish : (_buildingMultiPaint ? _multiFinish : 0)); float num4 = (_buildingIsUndo ? record.Opacity : (_buildingMultiPaint ? BatchPaintRules.Opacity(_multiFinish, ClassifyPiece(record.Piece) == NaturalPaintLogic.PaintMaterial.Crystal, _multiOpacity, record.Opacity) : (-1f))); if (BuildingClearRules.Matches(num, num2, num3, num4)) { _buildingSkipped++; return; } zDO.Set(PaintHash, num3, false); zDO.Set(CrystalOpacityHash, num4); if (!_buildingIsUndo) { record.AppliedFinish = num3; record.AppliedOpacity = num4; } if (_buildingIsUndo) { _buildingUndo.Remove(record); } else { if (!_buildingStartedUndoRecord) { _buildingUndo.Clear(); _undoPlayer = _buildingPlayer; _buildingStartedUndoRecord = true; } _buildingUndo.Add(record); } _buildingChanged++; RefreshSaved(record.Piece); } private void CancelBuildingClear() { if (_buildingStage == BuildingStage.Running) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[paint.batch.done] changed=" + _buildingChanged + "; skipped=" + _buildingSkipped + "; stopped=" + _buildingQueue.Count)); Tell(Player.m_localPlayer, (_buildingIsUndo ? "Restore" : (_buildingMultiPaint ? "Paint" : "Clear")) + ": " + _buildingChanged + " changed, " + _buildingSkipped + " skipped, " + _buildingQueue.Count + " stopped. Undo remaining: " + _buildingUndo.Count + "."); } bool buildingClearActive = BuildingClearActive; _buildingStage = BuildingStage.None; _buildingMultiPaint = false; _buildingSelection.Clear(); _buildingQueue.Clear(); _buildingPlayer = null; _buildingGraph = null; _buildingCandidates.Clear(); _buildingNodes.Clear(); _buildingNodeBounds.Clear(); _buildingSeed = null; if (Object.op_Implicit((Object)(object)_buildingCanvas)) { _buildingCanvas.SetActive(false); } ClearBuildingPreview(); if (buildingClearActive) { _releaseGuard.Arm(Time.frameCount); _nextUse = Time.unscaledTime + 0.3f; } if (Object.op_Implicit((Object)(object)EventSystem.current) && Object.op_Implicit((Object)(object)EventSystem.current.currentSelectedGameObject) && Object.op_Implicit((Object)(object)_buildingCanvas) && EventSystem.current.currentSelectedGameObject.transform.IsChildOf(_buildingCanvas.transform)) { EventSystem.current.SetSelectedGameObject((GameObject)null); } } private void HighlightBuildingPiece(Piece piece) { if (Object.op_Implicit((Object)(object)piece) && _painted.TryGetValue(piece, out var value) && _buildingPreviewPieces.Add(piece)) { BuildSurfaces(value); ApplyPiece(value); } } private void RemoveBuildingHighlight(Piece piece) { _buildingPreviewPieces.Remove(piece); if (Object.op_Implicit((Object)(object)piece)) { RefreshSaved(piece); } } private bool ApplyBuildingPreview(Surface surface) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if (!_buildingPreviewPieces.Contains(surface.Piece.Piece)) { return false; } int saved = surface.Piece.Saved; bool flag = saved != 0 && Palette.IsValid(saved) && MaterialRules.Accepts(surface.Piece.Kind, saved); Finish finish = Palette.Get(flag ? saved : 0); foreach (Slot slot in surface.Slots) { Color val = Color.Lerp((Color)(flag ? new Color(slot.Base.r * finish.R, slot.Base.g * finish.G, slot.Base.b * finish.B, slot.Base.a) : slot.Base), BuildingPreviewColour, 0.65f); val.r = Mathf.Clamp01(val.r); val.g = Mathf.Clamp01(val.g); val.b = Mathf.Clamp01(val.b); val.a = ((surface.Piece.Kind == NaturalPaintLogic.PaintMaterial.Crystal) ? Mathf.Max(0.4f, CrystalOpacity.Alpha(slot.Base.a, surface.Piece.Opacity)) : slot.Base.a); surface.Renderer.GetPropertyBlock(surface.Block); surface.Block.SetColor(slot.Property, val); surface.Renderer.SetPropertyBlock(surface.Block, slot.Index); } surface.Applied = true; return true; } private void ClearBuildingPreview() { List<Piece> list = new List<Piece>(_buildingPreviewPieces); _buildingPreviewPieces.Clear(); foreach (Piece item in list) { if (Object.op_Implicit((Object)(object)item)) { try { RefreshSaved(item); } catch (Exception ex) { ReportOnce("paint.building.preview.restore", ex); } } } } private bool InBuildingScope(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_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) Vector3 val = position - _buildingSeedPosition; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = position - ((Component)_buildingPlayer).transform.position; return BatchPaintRules.InScope(sqrMagnitude, ((Vector3)(ref val)).sqrMagnitude); } private void FailBuilding(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[paint.batch.stop] " + message)); CancelBuildingClear(); Tell(Player.m_localPlayer, message); } private void StartMultiPaint() { _multiFinish = SelectedFinish.Id; _multiOpacity = CrystalOpacity.Normalize(_selectedOpacity.Value); ClosePalette(); ClearHover(); _buildingPlayer = Player.m_localPlayer; _buildingIsUndo = false; _buildingMultiPaint = true; _buildingSelection.Clear(); _buildingClearMaterial = NaturalPaintLogic.PaintMaterial.Unsupported; _buildingStage = BuildingStage.Selecting; _nextUse = Time.unscaledTime + 0.3f; Tell(_buildingPlayer, "Multi-paint: " + Palette.Get(_multiFinish).Name + ". Click pieces to select. Right-click / Enter / Y to review."); } private void ToggleMultiPiece(Player player) { //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) if (OverlayBlocksInput || CameraInputSuppressed || Time.unscaledTime < _nextUse || !CanUseTool(player)) { return; } _nextUse = Time.unscaledTime + 0.25f; if (!TryGetBrushTarget(player, out var target)) { Tell(player, "Aim at a building piece within brush reach."); return; } int num = _buildingSelection.FindIndex((BuildingRecord r) => (Object)(object)r.Piece == (Object)(object)target.Piece); if (num >= 0) { _buildingSelection.RemoveAt(num); if (_buildingSelection.Count == 0) { _buildingClearMaterial = NaturalPaintLogic.PaintMaterial.Unsupported; } RemoveBuildingHighlight(target.Piece); } else if (_buildingSelection.Count >= 500) { Tell(player, "Select up to 500 pieces per batch."); } else if (!MaterialRules.Accepts(target.Kind, _multiFinish)) { Tell(player, "This finish cannot paint " + MaterialRules.DisplayName(target.Kind) + "."); } else if (_multiFinish == 0 && _buildingSelection.Count > 0 && !BatchPaintRules.SameClearMaterial(_buildingClearMaterial, target.Kind)) { Tell(player, "This removal batch is " + MaterialRules.DisplayName(_buildingClearMaterial) + " only. Clear the selection to choose another material."); } else { if (!PrivateArea.CheckAccess(((Component)target.Piece).transform.position, 0f, true, false)) { return; } if (!HasPaintableSurfaces(target.Piece)) { Tell(player, "This piece has no supported paint surface."); return; } ZNetView component = ((Component)target.Piece).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { return; } int num2 = component.GetZDO().GetInt(PaintHash, 0); float num3 = component.GetZDO().GetFloat(CrystalOpacityHash, -1f); float expectedOpacity = BatchPaintRules.Opacity(_multiFinish, target.Kind == NaturalPaintLogic.PaintMaterial.Crystal, _multiOpacity, num3); if (BuildingClearRules.Matches(num2, num3, _multiFinish, expectedOpacity)) { Tell(player, "This piece already has the selected finish."); return; } if (_multiFinish == 0 && _buildingSelection.Count == 0) { _buildingClearMaterial = target.Kind; } _buildingSelection.Add(new BuildingRecord { Piece = target.Piece, View = component, Id = component.GetZDO().m_uid, Finish = num2, Opacity = num3 }); HighlightBuildingPiece(target.Piece); } } private void ReviewMultiPaint() { if (_buildingSelection.Count == 0) { Tell(_buildingPlayer, "Select at least one piece first."); return; } ClearHover(); ShowBuildingReview("Apply " + Palette.Get(_multiFinish).Name + ((_multiFinish == 0) ? (" (" + MaterialRules.DisplayName(_buildingClearMaterial) + " only)") : "") + " to " + _buildingSelection.Count + " selected pieces?\nGREEN marks your selected pieces. It is not the final colour.\nEdit selection / Y: add or remove pieces.\nChanges are applied together after confirmation. Undo last batch is available."); } private void ReturnToMultiSelection() { if (_buildingMultiPaint && _buildingStage == BuildingStage.Review) { if (Object.op_Implicit((Object)(object)EventSystem.current)) { EventSystem.current.SetSelectedGameObject((GameObject)null); } _buildingCanvas.SetActive(false); _buildingStage = BuildingStage.Selecting; _releaseGuard.Arm(Time.frameCount); _nextUse = Time.unscaledTime + 0.3f; } } 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 NaturalPaintLogic.PaintMaterial ClassifyPiece(Piece piece) { if (!Object.op_Implicit((Object)(object)piece)) { return (NaturalPaintLogic.PaintMaterial)SurfaceSupport.RefineKind(0, piece); } WearNTear component = ((Component)piece).GetComponent<WearNTear>(); string support = (Object.op_Implicit((Object)(object)component) ? ((object)Unsafe.As<MaterialType, MaterialType>(ref component.m_materialType)/*cast due to .constrained prefix*/).ToString() : ""); NaturalPaintLogic.PaintMaterial paintMaterial = MaterialRules.Classify(support, ((Object)piece).name, woodenSurface: false, stoneSurface: false); if (paintMaterial != NaturalPaintLogic.PaintMaterial.Unsupported) { return (NaturalPaintLogic.PaintMaterial)SurfaceSupport.RefineKind((int)paintMaterial, piece); } bool flag = false; bool flag2 = false; Renderer[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)((Component)val).GetComponentInParent<Piece>() != (Object)(object)piece) { continue; } Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if (Object.op_Implicit((Object)(object)val2)) { flag |= MaterialRules.WoodLabel(((Object)val2).name) && MaterialRules.PaintableSlot(NaturalPaintLogic.PaintMaterial.Wood, ((Object)val2).name, ((Object)val).name); flag2 |= MaterialRules.StoneLabel(((Object)val2).name) && MaterialRules.PaintableSlot(NaturalPaintLogic.PaintMaterial.Stone, ((Object)val2).name, ((Object)val).name); } } } return (NaturalPaintLogic.PaintMaterial)SurfaceSupport.RefineKind((int)MaterialRules.Classify(support, ((Object)piece).name, flag, flag2), piece); } internal static bool TryGetBrushTarget(Player player, out BrushTarget target) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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; } float num = ((Object.op_Implicit((Object)(object)Instance) && Instance.PaintCameraActive) ? Instance.CameraPaintReach : Math.Min(5f, player.m_maxPlaceDistance)); float num2 = CameraMath.BuildRayDistance(Vector3.Distance(((Component)instance).transform.position, ((Character)player).GetEyePoint()), num, 0f); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(((Component)instance).transform.position, ((Component)instance).transform.forward, ref val, num2, (int)RemoveRayMask.GetValue(player), (QueryTriggerInteraction)1)) { return false; } if (Vector3.Distance(((Character)player).GetEyePoint(), ((RaycastHit)(ref val)).point) > num) { return false; } Piece componentInParent = ((Component)((Rayca