using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Zen.Config;
using Zen.Controls;
using Zen.Lib;
using Zen.Logging;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenSign")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenSign")]
[assembly: AssemblyCopyright("Copyright \ufffd 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ZenSign
{
public static class Assets
{
private static readonly AssetBundle Bundle;
public static readonly Material SignIcon;
public static readonly Material SignIconOutline;
static Assets()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
try
{
Bundle = AssetUtils.LoadAssetBundleFromResources("Resources.signicon");
SignIcon = Bundle.LoadAsset<Material>("SignIcon");
SignIconOutline = new Material(SignIcon)
{
color = Color.black
};
}
catch (Exception arg)
{
throw new Exception($"Assets failed to load: {arg}");
}
}
public static void Unload()
{
try
{
Bundle.Unload(true);
}
catch
{
Log.Info((object)"Assets already unloaded.", (ushort)0);
}
}
}
[HarmonyPatch]
public static class ContainerPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(Container), "Awake")]
private static void Container_Awake(Container __instance)
{
ExposedGameObjectExtension.GetOrAddComponent<ContainerWatcher>(((Component)__instance).gameObject);
}
}
public class ContainerWatcher : MonoBehaviour, IContainer, ISearchable, IRedecorate
{
private Container _container;
private Tally? _itemTotalsCache;
private Tally? _itemTotalsLastRevision;
public Piece Piece => _container.m_piece;
public Vector3 Position => ((Component)this).transform.position;
private bool IsPrivateChest => (int)_container.m_privacy == 0;
private bool IsPlacedByPlayer
{
get
{
if (Object.op_Implicit((Object)(object)_container.m_piece))
{
return _container.m_piece.IsPlacedByPlayer();
}
return false;
}
}
private bool IsVehicle
{
get
{
if (!Object.op_Implicit((Object)(object)_container.m_wagon))
{
return Object.op_Implicit((Object)(object)((Component)_container).gameObject.GetComponentInParent<Ship>());
}
return true;
}
}
private bool IsIgnored
{
get
{
if (Object.op_Implicit((Object)(object)_container) && !IsPrivateChest && !IsBuildCursor && IsPlacedByPlayer)
{
return IsVehicle;
}
return true;
}
}
private bool IsBuildCursor
{
get
{
if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return (Object)(object)Player.m_localPlayer.m_placementGhost == (Object)(object)((Component)this).gameObject;
}
return false;
}
}
private Tally ItemTotals
{
get
{
if (_itemTotalsCache == null)
{
_itemTotalsCache = InventoryExt.SumItemsByName(_container.GetInventory());
}
return _itemTotalsCache;
}
set
{
_itemTotalsCache = value;
}
}
public int GetItemTotal(string itemName)
{
return ((Tally<string>)(object)ItemTotals)[itemName];
}
public bool HaveItem(string itemName)
{
return _container.GetInventory().HaveItem(itemName, true);
}
internal static void Init()
{
Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
ContainerWatcher containerWatcher = default(ContainerWatcher);
foreach (Container val in array)
{
if (!((Component)val).gameObject.TryGetComponent<ContainerWatcher>(ref containerWatcher))
{
Log.Debug((object)"Init ContainerWatcher", (ushort)0);
((Component)val).gameObject.AddComponent<ContainerWatcher>();
}
}
}
internal static void Shutdown()
{
ContainerWatcher[] array = Object.FindObjectsOfType<ContainerWatcher>();
Log.Info((object)$"- Containers: {array.Length}", (ushort)0);
ContainerWatcher[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
Object.Destroy((Object)(object)array2[i]);
}
}
private void Awake()
{
_container = ((Component)this).GetComponent<Container>();
if (!Object.op_Implicit((Object)(object)_container.m_piece))
{
_container.m_piece = ((Component)((Component)this).transform).GetComponentInParent<Piece>();
}
}
private void Start()
{
if (IsIgnored)
{
Log.Info((object)$"Ignored: {this}, IsBuildCursor: {IsBuildCursor}", (ushort)0);
Object.Destroy((Object)(object)this);
return;
}
Search.All.Containers.Add(this);
Inventory inventory = _container.GetInventory();
inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
Log.Debug((object)$"Start Watching: {this}", (ushort)0);
}
private void OnInventoryChanged()
{
ContainerChanged(destroyed: false);
}
private void OnDestroy()
{
if (!IsIgnored)
{
Inventory inventory = _container.GetInventory();
inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged));
Log.Info((object)$"Watched container destroyed {this}", (ushort)0);
ContainerChanged(destroyed: true);
Search.All.Containers.Remove(this);
Log.Debug((object)$"Stop Watching: {this}", (ushort)0);
}
}
public void OnRedecorateBefore()
{
}
public void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before)
{
//IL_0032: 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)
Log.Info((object)"After move, updating signs...", (ushort)0);
Log.Info((object)"Updating signs at old position", (ushort)0);
HashSet<string> items = ((Dictionary<string, int>)(object)InventoryExt.SumItemsByName(_container.GetInventory())).Keys.ToHashSet();
HashSet<ISign> ignoreSigns = UpdateSigns(items, before.Position);
Log.Info((object)"Updating signs at new position", (ushort)0);
UpdateSigns(items, ((Component)this).transform.position, ignoreSigns);
}
private void ContainerChanged(bool destroyed)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
Log.Info((object)$"Container Changed: {this} destroyed: {destroyed}", (ushort)0);
if (!destroyed)
{
ItemTotals = InventoryExt.SumItemsByName(_container.GetInventory());
}
else
{
ItemTotals = new Tally();
foreach (ItemData allItem in _container.GetInventory().GetAllItems())
{
((Tally<string>)(object)ItemTotals)[ItemDataExt.GetName(allItem)] = 0;
}
}
HashSet<string> hashSet = ((Tally<string>)(object)ItemTotals).Diff((Tally<string>)(object)_itemTotalsLastRevision, (IEqualityComparer<KeyValuePair<string, int>>)null);
_itemTotalsLastRevision = ItemTotals;
if (hashSet.Count == 0)
{
Log.Info((object)"No changes detected", (ushort)0);
return;
}
Log.Info((object)string.Format("Changed Items: {0}: {1}", hashSet.Count, GeneralExtensions.Join<string>((IEnumerable<string>)hashSet, (Func<string, string>)null, ", ")), (ushort)0);
UpdateSigns(hashSet, ((Component)this).transform.position);
}
private static HashSet<ISign> UpdateSigns(HashSet<string> items, Vector3 position, HashSet<ISign>? ignoreSigns = null)
{
//IL_0005: 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_0032: Unknown result type (might be due to invalid IL or missing references)
Log.Info((object)$"UpdateSigns at {MathExt.XZY(position)}", (ushort)0);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
HashSet<ISign> hashSet = new HashSet<ISign>();
foreach (ISign item in Search.All.Signs.InRange(position, Configs.SignDetectRange.Value))
{
if ((ignoreSigns == null || !ignoreSigns.Contains(item)) && item.IsAssignedItem && items.Contains(item.ItemName))
{
item.UpdateQty();
hashSet.Add(item);
}
}
stopwatch.Stop();
Log.Info((object)$"Update {hashSet.Count} signs in {stopwatch.ElapsedMilliseconds}ms", (ushort)0);
return hashSet;
}
public override string ToString()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
return $"{_container.m_name} {MathExt.XZY(((Component)this).transform.position)}";
}
}
internal static class Extensions
{
internal static IEnumerable<T> InRange<T>(this IEnumerable<T> list, Vector3 position, float range, bool ignoreWards = true) where T : ISearchable
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
return list.Where(delegate(T obj)
{
//IL_0004: 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_0032: Unknown result type (might be due to invalid IL or missing references)
T val = obj;
return MathExt.DistanceToSqr(val.Position, position) < range * range && (ignoreWards || WardAccessExt.CanAccessWard(position, false));
});
}
}
[HarmonyPatch]
public static class FindLightsFuel
{
[HarmonyPrefix]
[HarmonyPatch(typeof(Fireplace), "Interact")]
private static void Fireplace_Interact(Fireplace __instance, Humanoid user, bool hold, ref bool __runOriginal)
{
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
Log.Info((object)("Interact with " + __instance.m_piece.m_name), (ushort)0);
float @float = __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f);
if (__instance.m_infiniteFuel || !__instance.m_canRefill || (__instance.m_canTurnOff && @float > 0f))
{
return;
}
ItemDrop fuelItem = __instance.m_fuelItem;
string text = ((fuelItem != null) ? ItemDataExt.GetName(fuelItem) : null);
if (text == null)
{
return;
}
if (!FireplaceExt.IsFuelDaysFull(__instance, (float?)null))
{
if (!user.GetInventory().HaveItem(text, true))
{
Search.Find(Search.All.Containers, text, ((Component)__instance).transform.position, Configs.FuelSearchRange.Value, highlight: true, showNotFoundMsg: true, lookAtClosest: true);
}
}
else
{
Log.Info((object)"Can not add more fuel", (ushort)0);
string text2 = Localization.instance.Localize("$msg_cantaddmore", new string[1] { text });
((Character)Player.m_localPlayer).Message((MessageType)2, text2, 0, (Sprite)null);
__runOriginal = false;
}
}
}
[HarmonyPatch]
public static class Highlight
{
private static readonly Dictionary<Piece, Coroutine> BlinkCoroutines = new Dictionary<Piece, Coroutine>();
[HarmonyPostfix]
[HarmonyPatch(typeof(Piece), "OnDestroy")]
private static void Piece_OnDestroy(Piece __instance)
{
__instance.StopBlink();
}
private static QuickOutline GetOutline(this Piece piece)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
QuickOutline quickOutline = default(QuickOutline);
if (!((Component)piece).gameObject.TryGetComponent<QuickOutline>(ref quickOutline))
{
quickOutline = ((Component)piece).gameObject.AddComponent<QuickOutline>();
quickOutline.OutlineMode = QuickOutline.Mode.OutlineAll;
quickOutline.OutlineWidth = 3f;
((Behaviour)quickOutline).enabled = false;
}
quickOutline.OutlineColor = Configs.HighlightColor.Value;
return quickOutline;
}
public static void Select(Piece? piece, bool active, bool blink = false)
{
if (Object.op_Implicit((Object)(object)piece))
{
Log.Debug((object)$"Highlight: {active} {piece.m_name}", (ushort)0);
((Behaviour)piece.GetOutline()).enabled = active;
if (active && blink)
{
piece.StartBlink(Configs.HighlightDuration.Value);
}
else
{
piece.StopBlink();
}
}
}
private static void StartBlink(this Piece piece, float duration)
{
if (BlinkCoroutines.TryGetValue(piece, out Coroutine value))
{
Timing.StopCoroutine(value);
}
BlinkCoroutines[piece] = Timing.StartCoroutine(Blink(piece, duration));
}
private static void StopBlink(this Piece piece)
{
if (BlinkCoroutines.TryGetValue(piece, out Coroutine value))
{
if (value != null)
{
Timing.StopCoroutine(value);
}
BlinkCoroutines.Remove(piece);
Select(piece, active: false);
}
}
private static IEnumerator Blink(Piece piece, float duration)
{
bool toggle = false;
float bps2 = Configs.HighlightBlinkPerSecond.Value;
bps2 = ((bps2 > 0f) ? bps2 : (1f / ((duration > 0f) ? duration : 1f)));
for (int i = 0; (float)i < duration * bps2; i++)
{
QuickOutline outline = piece.GetOutline();
bool enabled;
toggle = (enabled = !toggle);
((Behaviour)outline).enabled = enabled;
yield return (object)new WaitForSeconds(1f / bps2);
}
Search.Reset();
Select(piece, active: false);
}
public static void None()
{
foreach (Piece key in BlinkCoroutines.Keys)
{
Select(key, active: false);
}
}
}
public interface IContainer : ISearchable
{
}
public interface ISign : ISearchable
{
bool IsAssignedItem { get; }
string ItemName { get; }
void UpdateQty();
}
[HarmonyPatch]
internal static class PrefabInit
{
internal const string SignPrefabName = "sign";
private const string LayoutNodeName = "ZenSign";
private const float ImageScalingFactor = 0.005f;
private const float DefaultIconBrightness = 1f;
private static readonly Vector3 DefaultIconScale = Vector3.one * 0.635f * 0.005f;
private static readonly Vector3 DefaultIconPosition = new Vector3(-0.26f, 0f, 0f);
[HarmonyPostfix]
[HarmonyPatch(typeof(ZNetScene), "Awake")]
internal static void ZNetScene_Awake(ZNetScene __instance)
{
SignInit(__instance);
}
internal static bool SignInit(ZNetScene zNetScene)
{
Log.Info((object)"Initializing Sign Prefab", (ushort)0);
return Object.op_Implicit((Object)(object)CreateStructure(zNetScene.GetPrefab("sign").GetComponent<Sign>()));
}
internal static void RemoveStructure()
{
if (!Object.op_Implicit((Object)(object)ZNetScene.instance))
{
return;
}
GameObject prefab = ZNetScene.instance.GetPrefab("sign");
if (Object.op_Implicit((Object)(object)prefab))
{
SignItem signItem = default(SignItem);
if (!prefab.TryGetComponent<SignItem>(ref signItem))
{
Log.Warning((object)"SignItem component not found during cleanup. This is an unusual sitation that should not happen.", (ushort)0);
return;
}
Object.Destroy((Object)(object)signItem.itemLayout);
Object.Destroy((Object)(object)signItem);
}
}
internal static SignItem? CreateStructure(Sign sign)
{
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Expected O, but got Unknown
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: 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_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: 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_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
if (Object.op_Implicit((Object)(object)((Component)sign).transform.Find("ZenSign")))
{
Log.Info((object)("Structure already exists: " + ((Object)sign).name), (ushort)0);
return null;
}
Log.Info((object)("Initializing Structure: " + ((Object)sign).name), (ushort)0);
GameObject gameObject = ((Component)((Component)sign).transform.Find("Canvas")).gameObject;
GameObject val = Object.Instantiate<GameObject>(gameObject);
val.transform.SetParent(((Component)sign).transform, false);
((Object)val).name = "ZenSign";
val.SetActive(false);
GameObject gameObject2 = ((Component)val.transform.Find("Text")).gameObject;
gameObject2.transform.localPosition = Vector3.right * 0.05f;
Transform transform = gameObject2.transform;
transform.localScale *= 0.8f;
TextMeshProUGUI component = gameObject2.GetComponent<TextMeshProUGUI>();
((TMP_Text)component).alignment = (TextAlignmentOptions)516;
((TMP_Text)component).text = "0";
GameObject val2 = new GameObject("IconImage");
val2.transform.SetParent(val.transform, false);
val2.transform.localPosition = DefaultIconPosition;
val2.transform.localScale = DefaultIconScale;
Image val3 = val2.AddComponent<Image>();
((Graphic)val3).material = Assets.SignIcon;
Color color = Color.white * 1f;
color.a = 1f;
((Graphic)val3).color = color;
GameObject val4 = new GameObject("IconImageOutline", new Type[1] { typeof(RectTransform) });
RectTransform component2 = val4.GetComponent<RectTransform>();
((Transform)component2).localScale = Vector3.one * 1.1f;
Vector3 localPosition = ((Transform)component2).localPosition;
localPosition.z = 0.2f;
((Transform)component2).localPosition = localPosition;
val4.transform.SetParent(val2.transform, false);
Image val5 = val4.AddComponent<Image>();
((Graphic)val5).material = Assets.SignIconOutline;
SignItem signItem = ((Component)sign).gameObject.AddComponent<SignItem>();
signItem.vanillaSign = sign;
signItem.piece = ((Component)sign).GetComponent<Piece>();
signItem.origLayout = gameObject;
signItem.itemLayout = val;
signItem.qtyText = component;
signItem.iconImage = val3;
signItem.iconImageOutline = val5;
return signItem;
}
}
[DisallowMultipleComponent]
public class QuickOutline : MonoBehaviour
{
public enum Mode
{
OutlineAll,
OutlineVisible,
OutlineHidden,
OutlineAndSilhouette,
SilhouetteOnly
}
private static class SP
{
public static readonly int OutlineColor = Shader.PropertyToID("_OutlineColor");
public static readonly int ZTest = Shader.PropertyToID("_ZTest");
public static readonly int OutineWidth = Shader.PropertyToID("_OutlineWidth");
}
private static readonly HashSet<Mesh> RegisteredMeshes = new HashSet<Mesh>();
[SerializeField]
private Mode outlineMode;
[SerializeField]
private Color outlineColor = Color.white;
[SerializeField]
[Range(0f, 10f)]
private float outlineWidth = 2f;
[Header("Optional")]
private Renderer[] _renderers = Array.Empty<Renderer>();
private static Material _outlineMaskMaterial = null;
private static Material _outlineFillMaterial = null;
private bool _needsUpdate;
public Mode OutlineMode
{
get
{
return outlineMode;
}
set
{
outlineMode = value;
_needsUpdate = true;
}
}
public Color OutlineColor
{
get
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return outlineColor;
}
set
{
//IL_0001: 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)
outlineColor = value;
_needsUpdate = true;
}
}
public float OutlineWidth
{
get
{
return outlineWidth;
}
set
{
outlineWidth = value;
_needsUpdate = true;
}
}
public static void InitMaterials()
{
if (!Object.op_Implicit((Object)(object)_outlineMaskMaterial) || !Object.op_Implicit((Object)(object)_outlineFillMaterial))
{
Log.Info((object)"Init material assets", (ushort)0);
AssetBundle obj = AssetUtils.LoadAssetBundleFromResources("Resources.quickoutline");
_outlineMaskMaterial = obj.LoadAsset<Material>("OutlineMask");
_outlineFillMaterial = obj.LoadAsset<Material>("OutlineFill");
((Object)_outlineMaskMaterial).name = "OutlineMask (Instance)";
((Object)_outlineFillMaterial).name = "OutlineFill (Instance)";
obj.Unload(false);
}
}
public void ComputeRenderers()
{
_renderers = (from r in ((Component)this).GetComponentsInChildren<Renderer>()
where !(r is ParticleSystemRenderer)
select r).ToArray();
LoadSmoothNormals();
_needsUpdate = true;
}
private void Awake()
{
ComputeRenderers();
}
private void OnEnable()
{
if (_renderers.Length == 0)
{
((Behaviour)this).enabled = false;
return;
}
Renderer[] renderers = _renderers;
foreach (Renderer obj in renderers)
{
List<Material> list = obj.sharedMaterials.ToList();
list.Add(_outlineMaskMaterial);
list.Add(_outlineFillMaterial);
obj.materials = list.ToArray();
}
}
private void Update()
{
if (_needsUpdate)
{
_needsUpdate = false;
UpdateMaterialProperties();
}
}
private void OnDisable()
{
Renderer[] renderers = _renderers;
foreach (Renderer obj in renderers)
{
List<Material> list = obj.sharedMaterials.ToList();
list.Remove(_outlineMaskMaterial);
list.Remove(_outlineFillMaterial);
obj.materials = list.ToArray();
}
}
internal static void DisableAll()
{
QuickOutline[] array = Object.FindObjectsOfType<QuickOutline>();
for (int i = 0; i < array.Length; i++)
{
((Behaviour)array[i]).enabled = false;
}
}
private void LoadSmoothNormals()
{
MeshFilter[] componentsInChildren = ((Component)this).GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter val in componentsInChildren)
{
Mesh sharedMesh = val.sharedMesh;
if (sharedMesh.isReadable && RegisteredMeshes.Add(sharedMesh))
{
List<Vector3> list = SmoothNormals(sharedMesh);
sharedMesh.SetUVs(3, list);
Renderer component = ((Component)val).GetComponent<Renderer>();
if ((Object)(object)component != (Object)null)
{
CombineSubmeshes(sharedMesh, component.sharedMaterials);
}
}
}
SkinnedMeshRenderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
{
Mesh sharedMesh2 = val2.sharedMesh;
if (sharedMesh2.isReadable && RegisteredMeshes.Add(sharedMesh2))
{
sharedMesh2.uv4 = (Vector2[])(object)new Vector2[sharedMesh2.vertexCount];
CombineSubmeshes(sharedMesh2, ((Renderer)val2).sharedMaterials);
}
}
}
private static List<Vector3> SmoothNormals(Mesh mesh)
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: 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_00de: Unknown result type (might be due to invalid IL or missing references)
IEnumerable<IGrouping<Vector3, (Vector3, int)>> enumerable = from pair in mesh.vertices.Select((Vector3 vertex, int index) => (vertex, index))
group pair by pair.Vertex;
List<Vector3> list = new List<Vector3>(mesh.normals);
foreach (IGrouping<Vector3, (Vector3, int)> item in enumerable)
{
if (item.Count() == 1)
{
continue;
}
Vector3 val = Vector3.zero;
foreach (var item2 in item)
{
val += list[item2.Item2];
}
((Vector3)(ref val)).Normalize();
foreach (var item3 in item)
{
list[item3.Item2] = val;
}
}
return list;
}
private static void CombineSubmeshes(Mesh mesh, Material[] materials)
{
if (mesh.subMeshCount != 1 && mesh.subMeshCount <= materials.Length)
{
int subMeshCount = mesh.subMeshCount;
mesh.subMeshCount = subMeshCount + 1;
mesh.SetTriangles(mesh.triangles, mesh.subMeshCount - 1);
}
}
private void UpdateMaterialProperties()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
_outlineFillMaterial.SetColor(SP.OutlineColor, outlineColor);
switch (outlineMode)
{
case Mode.OutlineAll:
_outlineMaskMaterial.SetFloat(SP.ZTest, 8f);
_outlineFillMaterial.SetFloat(SP.ZTest, 8f);
_outlineFillMaterial.SetFloat(SP.OutineWidth, outlineWidth);
break;
case Mode.OutlineVisible:
_outlineMaskMaterial.SetFloat(SP.ZTest, 8f);
_outlineFillMaterial.SetFloat(SP.ZTest, 4f);
_outlineFillMaterial.SetFloat(SP.OutineWidth, outlineWidth);
break;
case Mode.OutlineHidden:
_outlineMaskMaterial.SetFloat(SP.ZTest, 8f);
_outlineFillMaterial.SetFloat(SP.ZTest, 5f);
_outlineFillMaterial.SetFloat(SP.OutineWidth, outlineWidth);
break;
case Mode.OutlineAndSilhouette:
_outlineMaskMaterial.SetFloat(SP.ZTest, 4f);
_outlineFillMaterial.SetFloat(SP.ZTest, 8f);
_outlineFillMaterial.SetFloat(SP.OutineWidth, outlineWidth);
break;
case Mode.SilhouetteOnly:
_outlineMaskMaterial.SetFloat(SP.ZTest, 4f);
_outlineFillMaterial.SetFloat(SP.ZTest, 5f);
_outlineFillMaterial.SetFloat(SP.OutineWidth, 0f);
break;
}
}
}
[HarmonyPatch]
internal static class SearchPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerController), "TakeInput")]
private static void PlayerController_TakeInput(ref bool __result)
{
__result = __result && !Search.BlockInput;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(WearNTear), "Highlight")]
private static void WearNTear_Highlight(WearNTear __instance)
{
Search.Reset();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterAnimEvent), "UpdateHeadRotation")]
public static void CharacterrAnimEvent_UpdateHeadRotation(CharacterAnimEvent __instance, ref bool __runOriginal)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: 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)
if ((Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer || !PlayerExt.IsReady(Player.m_localPlayer) || !Search.Result.IsActive || Search.Result.Found.Count == 0)
{
return;
}
__runOriginal = false;
Vector3 lookFromPos = __instance.GetLookFromPos();
Vector3 val = Vector3.zero;
float num = float.PositiveInfinity;
foreach (ISearchable item in Search.Result.Found)
{
Vector3 position = item.Position;
float num2 = VectorExtensions.DistanceTo(position, lookFromPos);
if (num2 < num)
{
num = num2;
val = position;
}
}
Vector3 headLookDir = __instance.m_headLookDir;
Vector3 val2 = val - lookFromPos;
__instance.m_headLookDir = Vector3.Slerp(headLookDir, ((Vector3)(ref val2)).normalized, 0.1f);
}
}
[HarmonyPatch]
public static class SignUI
{
private static readonly ActionString InventorySearch = new ActionString("InventorySearch", "Find", true);
public static bool IsContainerOpen => InventoryGui.instance.IsContainerOpen();
public static bool IsAnimating => ((Behaviour)InventoryGui.instance.m_animator).isActiveAndEnabled;
internal static void RegisterInputs()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
InventorySearch.AddButton(Configs.InventorySearchGamepad.Value, false, true, false, 0f, 0f);
InventorySearch.AddButton(Configs.InventorySearchMouseKey.Value, false, false, false, 0f, 0f);
}
internal static void CreateKeyHints()
{
KeyHint.Create((HintType)3, InventorySearch, 1, true);
}
private static void HandleInventorySearch()
{
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
if (!InventoryGui.IsVisible() || !ZInput.GetButton(ActionString.op_Implicit(InventorySearch)))
{
return;
}
ItemData? hoveredItem = InventoryGui.instance.m_playerGrid.GetHoveredItem();
string text = ((hoveredItem != null) ? ItemDataExt.GetName(hoveredItem) : null);
if (text == null && IsContainerOpen)
{
ItemData? hoveredItem2 = InventoryGui.instance.ContainerGrid.GetHoveredItem();
text = ((hoveredItem2 != null) ? ItemDataExt.GetName(hoveredItem2) : null);
}
if (text == null)
{
UITooltip current = UITooltip.m_current;
if (Object.op_Implicit((Object)(object)current) && ((Behaviour)current).isActiveAndEnabled)
{
text = current.m_topic;
}
}
if (text == null)
{
((Character)Player.m_localPlayer).Message((MessageType)2, "Move the cursor onto an item first", 0, (Sprite)null);
}
else
{
Search.Find(Search.All.Containers, text, ((Component)Player.m_localPlayer).transform.position, 25f, highlight: true, showNotFoundMsg: true, lookAtClosest: true);
}
}
private static ItemData? GetHoveredItem(this InventoryGrid self)
{
if (ZInput.GamepadActive)
{
return self.GetGamepadSelectedItem();
}
Element hoveredElement = self.GetHoveredElement();
if (hoveredElement == null)
{
return null;
}
return self.m_inventory.GetItemAt(hoveredElement.m_pos.x, hoveredElement.m_pos.y);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")]
private static void InventoryGrid_UpdateInventory(InventoryGrid __instance)
{
if (Configs.InventorySearchEnabled.Value || ((Character)Player.m_localPlayer).InGodMode())
{
HandleInventorySearch();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryGui), "Show")]
private static void InventoryGui_Show()
{
Search.Reset();
}
}
internal static class Search
{
public static class All
{
public static readonly HashSet<IContainer> Containers = new HashSet<IContainer>();
public static readonly HashSet<ISign> Signs = new HashSet<ISign>();
}
public class SearchResult
{
public string ItemName = string.Empty;
public int Total;
public ISearchable? Closest;
public readonly HashSet<ISearchable> Found = new HashSet<ISearchable>();
public Vector3 SearchOrigin;
public float SearchRange;
public float SearchTime;
public bool IsActive
{
get
{
if (SearchTime != 0f)
{
return ZenMod<Plugin>.Initialized;
}
return false;
}
}
public void LookAtClosest()
{
//IL_0032: 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_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_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (!IsDisableFocusPressed && IsActive && Closest != null && !(((Character)Player.m_localPlayer).m_lookTransitionTime > float.Epsilon))
{
Vector3 val = ((Component)(MonoBehaviour)Closest).transform.position - ((Character)Player.m_localPlayer).GetHeadPoint();
((Character)Player.m_localPlayer).SetLookDir(val, 1f);
BlockInput = true;
Timing.Delay(1f, (Action)delegate
{
BlockInput = false;
});
}
}
public override string ToString()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
return $"{ItemName} Origin: {SearchOrigin} Range: {SearchRange} Locations: {Found.Count} SearchTime: {SearchTime} ";
}
}
public static SearchResult Result = new SearchResult();
public static bool BlockInput;
private static bool IsToggleFocusPressed
{
get
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
if (!ZInput.GetKey(Configs.SearchResultCameraFocusToggleKey.Value, true))
{
return ZInput.GetButton(ControlInputs.JoyAlt);
}
return true;
}
}
public static bool IsDisableFocusPressed => Configs.SearchResultCameraFocusDefault.Value ^ !IsToggleFocusPressed;
public static void Find<T>(IEnumerable<T> searchLocations, string itemName, Vector3 origin, float range, bool highlight, bool showNotFoundMsg, bool lookAtClosest, bool showResultsMsg = true) where T : ISearchable
{
//IL_000f: 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_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
if (Utility.IsNullOrWhiteSpace(itemName))
{
return;
}
Log.Info((object)$"SearchItem: {itemName} Origin: {origin} Range: {range}", (ushort)0);
if (Result.ItemName == itemName && MathExt.Approximately(origin, Result.SearchOrigin))
{
Log.Debug((object)"Duplicate search, aborting", (ushort)0);
return;
}
Reset();
ISearchable searchable = null;
float num = float.PositiveInfinity;
int num2 = 0;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
foreach (T item in searchLocations.InRange(origin, range, ignoreWards: false))
{
if (item.HaveItem(itemName))
{
if (highlight)
{
Highlight.Select(item.Piece, active: true, blink: true);
}
Result.Found.Add(item);
num2 += item.GetItemTotal(itemName);
float num3 = VectorExtensions.DistanceTo(item.Position, ((Component)Player.m_localPlayer).transform.position);
if (!(num3 > num))
{
searchable = item;
num = num3;
}
}
}
stopwatch.Stop();
Result.ItemName = itemName;
Result.Total = num2;
Result.Closest = searchable;
Result.SearchRange = range;
Result.SearchOrigin = origin;
Result.SearchTime = Time.time;
if (showResultsMsg && searchable != null && num2 > 0 && Object.op_Implicit((Object)(object)searchable.Piece))
{
Piece piece = searchable.Piece;
string text = piece.m_name + " has " + itemName;
int num4 = ((searchable is ContainerWatcher containerWatcher) ? containerWatcher.GetItemTotal(itemName) : 0);
Container val = default(Container);
Sprite val2 = (((Component)piece).TryGetComponent<Container>(ref val) ? val.GetInventory().GetItem(itemName, -1, false).GetIcon() : piece.m_icon);
if (num4 == 1)
{
num4 = 0;
}
((Character)Player.m_localPlayer).Message((MessageType)1, text, num4, val2);
}
else if (showNotFoundMsg)
{
NotFoundMessage(itemName);
}
Log.Debug((object)$"{num2} found in {Result.Found.Count} nearby containers: {stopwatch.ElapsedMilliseconds}ms", (ushort)0);
if (lookAtClosest)
{
Result.LookAtClosest();
}
}
private static void NotFoundMessage(string itemName)
{
Player localPlayer = Player.m_localPlayer;
string text = (WardAccessExt.CanAccessWard((MonoBehaviour)(object)localPlayer, false) ? (itemName + " not found nearby") : "$msg_privatezone");
((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
}
public static void Reset()
{
Log.Debug((object)"Search.Reset", (ushort)0);
foreach (ISearchable item in Result.Found)
{
Highlight.Select(item.Piece, active: false);
}
Result = new SearchResult();
BlockInput = false;
Highlight.None();
}
public static int SumInRange<T>(this IEnumerable<T> list, string itemName, Vector3 position, float range = 0f) where T : ISearchable
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
Log.Info((object)("CalcQty: " + itemName), (ushort)0);
IEnumerable<T> enumerable = list.InRange(position, (range > 0f) ? range : Configs.SignDetectRange.Value);
int num = 0;
int num2 = 0;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
foreach (T item in enumerable)
{
num2++;
int itemTotal = item.GetItemTotal(itemName);
if (itemTotal > 0)
{
num += itemTotal;
Log.Debug((object)$"+ {itemTotal} from {item}", (ushort)0);
}
}
stopwatch.Stop();
string text = $"= {num} Scan {num2} containers in {stopwatch.ElapsedMilliseconds}ms";
if (stopwatch.ElapsedMilliseconds > 2)
{
Log.Warning((object)text, (ushort)0);
}
else
{
Log.Debug((object)text, (ushort)0);
}
return num;
}
}
public interface ISearchable
{
Piece? Piece { get; }
Vector3 Position { get; }
bool HaveItem(string itemName);
int GetItemTotal(string itemName);
}
[DisallowMultipleComponent]
public class SignItem : MonoBehaviour, ISign, ISearchable, IRedecorate
{
public enum ViewMode
{
Normal,
ItemQty
}
[SerializeField]
internal Sign vanillaSign;
[SerializeField]
internal Piece piece;
[SerializeField]
internal GameObject origLayout;
[SerializeField]
internal GameObject itemLayout;
[SerializeField]
internal TextMeshProUGUI qtyText;
[SerializeField]
internal Image iconImage;
[SerializeField]
internal Image iconImageOutline;
private int _itemQty;
private bool _isBuildCursor = true;
private ZNetView _nview;
private ItemData? _item;
private static readonly Dictionary<GameObject, SignItem> LookupCache = new Dictionary<GameObject, SignItem>();
public Piece Piece => piece;
public Vector3 Position => ((Component)this).transform.position;
public ViewMode Mode { get; private set; }
public bool IsAssignedItem => _item != null;
public string ItemName
{
get
{
ItemData? item = _item;
return ((item != null) ? ItemDataExt.GetName(item) : null) ?? string.Empty;
}
}
public string ItemText
{
get
{
if (_item == null)
{
throw new InvalidOperationException("No item assigned");
}
return StringExt.Localize(ItemName) + "\n" + StringExt.ToHumanString(ItemQty);
}
}
public Sprite ItemIcon
{
get
{
if (_item == null)
{
throw new InvalidOperationException("No item assigned");
}
return _item.GetIcon();
}
}
public int ItemQty
{
get
{
return _itemQty;
}
private set
{
_itemQty = value;
UpdateDisplayQty();
}
}
public bool HaveItem(string itemName)
{
if (IsAssignedItem)
{
return ItemName == itemName;
}
return false;
}
public int GetItemTotal(string itemName)
{
if (!HaveItem(itemName))
{
return 0;
}
return ItemQty;
}
internal static SignItem Lookup(Sign sign)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
if (!LookupCache.TryGetValue(((Component)sign).gameObject, out SignItem value))
{
Dictionary<GameObject, SignItem> lookupCache = LookupCache;
GameObject gameObject = ((Component)sign).gameObject;
if (!((Component)sign).TryGetComponent<SignItem>(ref value))
{
throw new MissingComponentException("Sign is missing a SignItem");
}
return lookupCache[gameObject] = value;
}
return value;
}
internal static void Init()
{
if (PrefabInit.SignInit(ZNetScene.instance))
{
Sign[] array = Object.FindObjectsByType<Sign>((FindObjectsSortMode)0);
Log.Warning((object)string.Format("Hotreload {0} x{1}", "SignItem", array.Length), (ushort)0);
Sign[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
PrefabInit.CreateStructure(array2[i]);
}
}
}
internal static void Shutdown()
{
LookupCache.Clear();
Search.All.Signs.Clear();
PrefabInit.RemoveStructure();
SignItem[] array = Resources.FindObjectsOfTypeAll<SignItem>();
Log.Info((object)$"Cleaning up Signs: {array.Length}", (ushort)0);
SignItem[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
Object.Destroy((Object)(object)array2[i]);
}
}
private void Start()
{
_isBuildCursor = Player.IsPlacementGhost(((Component)vanillaSign).gameObject);
if (!_isBuildCursor)
{
_nview = vanillaSign.m_nview;
_nview.Register<int>("RPC_SyncDisplayItem", (Action<long, int>)RPC_SyncDisplayItem);
Search.All.Signs.Add(this);
LoadFromZDO();
Timing.SkipFrames(5, (Action)UpdateQty);
}
}
private void Update()
{
//IL_0027: 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)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: 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)
bool flag = Configs.ItemDisplayStyle.Value == Configs.ItemDisplayMode.Icons;
SetViewMode((IsAssignedItem && flag) ? ViewMode.ItemQty : ViewMode.Normal);
Color value = Configs.SignTextColor.Value;
if (((Graphic)qtyText).color != value)
{
((Graphic)qtyText).color = value;
((Graphic)vanillaSign.m_textWidget).color = value;
}
}
private void OnDisable()
{
SetViewMode(ViewMode.Normal);
}
private void OnDestroy()
{
Log.Info((object)$"Unloading {this} IsBuildCursor: {_isBuildCursor}", (ushort)0);
if (!_isBuildCursor)
{
_nview.Unregister("RPC_SyncDisplayItem");
Search.All.Signs.Remove(this);
LookupCache.Remove(((Component)vanillaSign).gameObject);
Object.Destroy((Object)(object)itemLayout);
}
}
public void OnRedecorateBefore()
{
}
public void OnRedecorateAfter((Vector3 Position, Quaternion Rotation) before)
{
Log.Info((object)"Position changed, updating sign from nearby containers", (ushort)0);
UpdateQty();
}
public void UpdateQty()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if (IsAssignedItem)
{
Log.Info((object)("UpdateQty: " + (object)this), (ushort)0);
ItemQty = Search.All.Containers.SumInRange(ItemName, ((Component)this).transform.position);
}
}
private void SetViewMode(ViewMode newMode)
{
if (Mode != newMode)
{
Mode = newMode;
switch (Mode)
{
case ViewMode.Normal:
origLayout.SetActive(true);
itemLayout.SetActive(false);
break;
case ViewMode.ItemQty:
origLayout.SetActive(false);
itemLayout.SetActive(true);
break;
default:
throw new Exception($"Unknown view mode: {newMode}");
}
}
}
public void ResetSign()
{
Log.Info((object)"Reset sign", (ushort)0);
_item = null;
SetVanillaSignText(null);
Save();
SyncDisplayItem();
}
private void SetVanillaSignText(string? text)
{
if (text == null)
{
text = vanillaSign.m_defaultText;
}
vanillaSign.SetText(text);
}
private void SetItem(ItemData item)
{
Log.Info((object)("Set item: " + ItemDataExt.GetName(item)), (ushort)0);
_item = item;
iconImage.sprite = _item.GetIcon();
iconImageOutline.sprite = _item.GetIcon();
}
public void AssignItem(ItemData item)
{
Log.Info((object)("AssignItem: " + ItemDataExt.GetName(item)), (ushort)0);
SetVanillaSignText(StringExt.Localize(ItemDataExt.GetName(item)));
SetItem(item);
Save();
UpdateQty();
SyncDisplayItem();
}
private void SyncDisplayItem()
{
ZNetView nview = _nview;
long everybody = ZNetView.Everybody;
object[] array = new object[1];
ItemData? item = _item;
array[0] = ((item != null) ? ItemDataExt.GetStableHashCode(item) : 0);
nview.InvokeRPC(everybody, "RPC_SyncDisplayItem", array);
}
private void RPC_SyncDisplayItem(long sender, int itemHash)
{
if (sender != ZNet.GetUID())
{
Log.Info((object)"Syncing display item", (ushort)0);
ItemData item;
if (itemHash == 0)
{
Log.Info((object)"Reset sign to default text", (ushort)0);
vanillaSign.SetWidgetText(vanillaSign.m_defaultText);
vanillaSign.m_isViewable = true;
_item = null;
}
else if (TryGetItemFromHash(itemHash, out item))
{
SetItem(item);
UpdateQty();
}
}
}
private void UpdateDisplayQty()
{
if (IsAssignedItem)
{
((TMP_Text)qtyText).text = StringExt.ToHumanString(ItemQty);
vanillaSign.SetWidgetText(ItemText);
}
}
public static bool TryGetItemFromHash(int itemHash, out ItemData item)
{
item = null;
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemHash);
if (!Object.op_Implicit((Object)(object)itemPrefab))
{
Log.Warning((object)$"Prefab not found for itemhash {itemHash}. Was the mod removed?", (ushort)0);
return false;
}
ItemDrop val = default(ItemDrop);
if (!itemPrefab.TryGetComponent<ItemDrop>(ref val))
{
Log.Error((object)("ItemDrop component missing from " + ((Object)itemPrefab).name), (ushort)0);
return false;
}
item = val.m_itemData;
return true;
}
private void LoadFromZDO()
{
int @int = _nview.GetZDO().GetInt(ZDOVars.s_itemPrefab, 0);
if (@int != 0 && TryGetItemFromHash(@int, out ItemData item))
{
SetItem(item);
}
}
private void Save()
{
if (_item != null)
{
Log.Info((object)("Save item: " + ItemDataExt.GetName(_item)), (ushort)0);
}
_nview.ClaimOwnership();
ZDO zDO = _nview.GetZDO();
int s_itemPrefab = ZDOVars.s_itemPrefab;
ItemData? item = _item;
zDO.Set(s_itemPrefab, (item != null) ? ItemDataExt.GetStableHashCode(item) : 0, false);
}
public override string ToString()
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
string arg = (IsAssignedItem ? ItemName : (Object.op_Implicit((Object)(object)vanillaSign) ? vanillaSign.GetText() : "(unknown)"));
return $"{arg} {MathExt.XZY(((Component)this).transform.position)}";
}
}
internal static class Configs
{
public enum ItemDisplayMode
{
Icons,
Text
}
public static readonly ConfigEntry<float> SignDetectRange;
public static readonly ConfigEntry<bool> StackableOnly;
public static readonly ConfigEntry<float> HighlightDuration;
public static readonly ConfigEntry<float> HighlightBlinkPerSecond;
public static readonly ConfigEntry<Color> HighlightColor;
public static readonly ConfigEntry<StringList> IgnoredItems;
public static readonly ConfigEntry<Color> SignTextColor;
public static readonly ConfigEntry<ItemDisplayMode> ItemDisplayStyle;
public static readonly ConfigEntry<float> FuelSearchRange;
public static readonly ConfigEntry<bool> NoRichTextTags;
public static readonly ConfigEntry<bool> InventorySearchEnabled;
public static readonly ConfigEntry<KeyCode> InventorySearchMouseKey;
public static readonly ConfigEntry<GamepadInput> InventorySearchGamepad;
public static readonly ConfigEntry<KeyCode> SearchResultCameraFocusToggleKey;
public static readonly ConfigEntry<bool> SearchResultCameraFocusDefault;
public const float PlayerDetectRange = 25f;
public const float LookAnimationTime = 1f;
static Configs()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
SignDetectRange = Config.Define<float>(true, "General", "Sign Search Radius", 20f, Config.AcceptRange<float>(1f, 25f), "Radius of the sign to search for containers.");
SignTextColor = Config.Define<Color>(true, "General", "Sign Text Color", Color.white, "The color of sign text. White is selected as the default because it's easier to see in the dark. (Vanilla: Black)");
IgnoredItems = Config.Define<StringList>(true, "General", "Ignored Items", StringList.Empty, "Comma separated list of item prefab names that are not assignable to signs.");
HighlightDuration = Config.Define<float>(true, "General", "Highlight Duration", 10f, Config.AcceptRange<float>(0f, 60f), "Number of seconds that highlighted objects will persist. Set to 0 to disable highlighting.");
HighlightBlinkPerSecond = Config.Define<float>(true, "General", "Highlight Blinks/Second", 2f, Config.AcceptRange<float>(0f, 10f), "How many times per second the highlighted objects will blink. Set to 0 to disable blinking.");
HighlightColor = Config.Define<Color>(true, "General", "Highlight Color", new Color(1f, 0.5f, 0f), "The color of the highlighted objects.");
StackableOnly = Config.Define<bool>(true, "General", "Stackable Items Only", false, "Only allow stackable items to be assigned to Signs. Otherwise any item can be assigned.");
ItemDisplayStyle = Config.Define<ItemDisplayMode>(true, "General", "Item Display Style", ItemDisplayMode.Icons, "Show the item on the sign as an icon or text only?");
FuelSearchRange = Config.Define<float>(true, "Fuel", "Fuel Search Range", 25f, Config.AcceptRange<float>(0f, 50f), "Range to search when sourcing fuel from containers for lights.");
NoRichTextTags = Config.Define<bool>(true, "Input", "No Rich Text Tags", true, "Remove Rich Text formatting tags from sign text. This prevents <color> tag changes, but also prevents abuse of <size> tags on multiplayer servers.");
InventorySearchEnabled = Config.Define<bool>(true, "Input", "Inventory Search", true, "Search directly from inventory via hotkeys enabled / disable.\nNote: Admin in God mode can always search from inventory");
InventorySearchMouseKey = Config.Define<KeyCode>(false, "Input", "Inventory Search - Keyboard/Mouse", (KeyCode)325, "Keyboard or mouse button to press to search for an item from the inventory UI.");
InventorySearchGamepad = Config.Define<GamepadInput>(false, "Input", "Inventory Search - Gamepad", (GamepadInput)19, "Gamepad button to press to search for an item from the inventory UI.");
SearchResultCameraFocusToggleKey = Config.Define<KeyCode>(false, "Input", "Search Result - Focus Camera Toggle", (KeyCode)304, "Hold this key down when performing a search to invert the default behavior of focusing the camera on the nearest search result.\r\nNote: Gamepad uses the standard alt-function button as defined in on the in game controls screen and can not be changed.");
SearchResultCameraFocusDefault = Config.Define<bool>(false, "Input", "Search Result - Focus Camera Default", true, "After searching for an item the camera will be focused on the nearest search result.\r\nIf this is false it will not move the camera.\r\nWhatever this setting is " + ((ConfigEntryBase)SearchResultCameraFocusToggleKey).Definition.Key + " will invoke the opposite behavior when pressed.");
}
}
[HarmonyPatch(typeof(Sign))]
internal static class SignPatch
{
private static readonly StringBuilder Sb = new StringBuilder();
private static bool HasTextAssigned(this Sign sign)
{
string text = StringExtensionMethods.RemoveRichTextTags(sign.GetText());
if (!Utility.IsNullOrWhiteSpace(text))
{
return text != sign.m_defaultText;
}
return false;
}
internal static void SetWidgetText(this Sign sign, string text)
{
sign.m_currentText = text;
((TMP_Text)sign.m_textWidget).text = text;
}
[HarmonyPrefix]
[HarmonyPatch("GetHoverText")]
private static void GetHoverText(Sign __instance, ref bool __runOriginal, ref string __result)
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: 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_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
if (!ZenMod<Plugin>.Initialized)
{
return;
}
__runOriginal = false;
Sb.Clear();
Sb.Append(__instance.m_name);
SignItem signItem = SignItem.Lookup(__instance);
switch (signItem.Mode)
{
case SignItem.ViewMode.Normal:
if (WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
{
Sb.Append("\n" + UI.PromptInteract + " $piece_sign_input");
Sb.Append("\n" + UI.PromptUseItem + " $hud_switchitem");
}
if (signItem.IsAssignedItem)
{
Sb.Append($"\n<color={UIColor.MinorInfo}>{signItem.ItemName}</color>");
}
else if (__instance.HasTextAssigned())
{
string arg = StringExtensionMethods.RemoveRichTextTags(__instance.GetText());
Sb.Append($"\n<color={UIColor.MinorInfo}>“{arg}”</color>");
}
break;
case SignItem.ViewMode.ItemQty:
{
string itemName = signItem.ItemName;
if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
{
Sb.Append($"\n<color={UIColor.MinorInfo}>{itemName}</color>");
break;
}
string text = (Search.IsDisableFocusPressed ? "Show" : "Find");
Sb.Append("\n" + UI.PromptInteract + " " + text);
Sb.Append("\n" + UI.PromptUseItem + " $hud_switchitem");
Sb.Append($"\n<color={UIColor.MinorInfo}>{itemName}</color>");
if (signItem.ItemQty >= 10000)
{
Sb.Append($"<color={UIColor.MinorInfo}> {signItem.ItemQty:n0}</color>");
}
break;
}
default:
throw new ArgumentOutOfRangeException();
}
__result = StringExt.Localize(Sb.ToString());
}
[HarmonyPrefix]
[HarmonyPatch("Interact")]
public static void Interact(Sign __instance, ref bool __runOriginal, ref bool __result, Humanoid character, bool hold, bool alt)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
SignItem signItem = SignItem.Lookup(__instance);
__runOriginal = false;
if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
{
__result = false;
return;
}
if (!signItem.IsAssignedItem)
{
__runOriginal = true;
__result = true;
return;
}
if (!hold)
{
Search.Find(Search.All.Containers, signItem.ItemName, ((Component)signItem).transform.position, Configs.SignDetectRange.Value, highlight: true, showNotFoundMsg: true, lookAtClosest: true);
}
__result = false;
}
[HarmonyPrefix]
[HarmonyPatch("UseItem")]
[HarmonyPriority(100)]
private static void UseItem(Sign __instance, ref bool __runOriginal, ref bool __result, ItemData item)
{
if (!__runOriginal)
{
return;
}
if (Configs.StackableOnly.Value && !ItemDataExt.IsStackable(item))
{
Log.Info((object)"Configured to only allow stackable items", (ushort)0);
return;
}
if (Configs.IgnoredItems.Value.Contains(ItemDataExt.GetPrefabName(item), true))
{
Log.Info((object)("Configured to explicitly ignore assignment of: " + ItemDataExt.GetPrefabName(item)), (ushort)0);
return;
}
__result = true;
__runOriginal = false;
if (WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, true))
{
SignItem signItem = SignItem.Lookup(__instance);
if (signItem.ItemName == ItemDataExt.GetName(item))
{
signItem.ResetSign();
}
else
{
signItem.AssignItem(item);
}
}
}
[HarmonyPostfix]
[HarmonyPatch("UpdateText")]
private static void UpdateText(Sign __instance)
{
TextMeshProUGUI textWidget = __instance.m_textWidget;
string text = ((TMP_Text)textWidget).text ?? "";
if (text.Length >= 2 && char.IsUpper(text[0]) && char.IsLower(text[1]))
{
((TMP_Text)textWidget).fontStyle = (FontStyles)33;
}
else
{
((TMP_Text)textWidget).fontStyle = (FontStyles)1;
}
}
[HarmonyPrefix]
[HarmonyPatch("SetText")]
private static void SetText(Sign __instance, ref string text)
{
if (Configs.NoRichTextTags.Value)
{
text = StringExtensionMethods.RemoveRichTextTags(text);
}
}
[HarmonyPostfix]
[HarmonyPatch("OnCheckPermissionCompleted")]
private static void Sign_OnCheckPermissionCompleted(Sign __instance)
{
SignItem signItem = SignItem.Lookup(__instance);
if (signItem.IsAssignedItem)
{
__instance.SetWidgetText(signItem.ItemText);
}
}
}
[BepInIncompatibility("Tekla_ColorfulSigns")]
[BepInIncompatibility("cjayride.AdvancedSigns")]
[BepInIncompatibility("redseiko.valheim.comfysigns")]
[BepInIncompatibility("Azumatt.AzuSigns")]
[BepInPlugin("ZenDragon.ZenSign", "ZenSign", "1.2.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class Plugin : ZenMod<Plugin>
{
public const string PluginName = "ZenSign";
public const string PluginVersion = "1.2.3";
public const string PluginID = "ZenDragon.ZenSign";
protected override void Setup()
{
((ZenMod)this).RegisterInputs += SignUI.RegisterInputs;
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
QuickOutline.InitMaterials();
Search.Reset();
SignItem.Init();
ContainerWatcher.Init();
SignUI.CreateKeyHints();
}
protected override void Shutdown()
{
QuickOutline.DisableAll();
Assets.Unload();
SignItem.Shutdown();
ContainerWatcher.Shutdown();
}
}
}
namespace ZenSign.Server
{
public class ServerMan
{
internal static ServerMan? Instance;
public static void Init()
{
if (!ZNet.instance.IsServer())
{
Log.Info((object)"Not server, skipping server init", (ushort)0);
return;
}
if (Instance != null)
{
throw new Exception("ServerMan already exists");
}
Instance = new ServerMan();
ZDOMan instance = ZDOMan.instance;
instance.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(instance.m_onZDODestroyed, new Action<ZDO>(Instance.OnDestroyZDO));
}
public void OnDestroyZDO(ZDO zdo)
{
ServerContainer.All.Remove(zdo);
ServerSign.All.Remove(zdo);
}
public void OnZDOSerializeIntercept(ZDO zdo, ZPackage pkg)
{
//IL_009a: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
ZDO zdo2 = zdo;
ZPackage pkg2 = pkg;
if (!zdo2.IsSign())
{
zdo2.Serialize(pkg2);
return;
}
try
{
string text2 = zdo2.GetString(ZDOVars.s_text, "") ?? string.Empty;
int @int = zdo2.GetInt(ZDOVars.s_itemPrefab, 0);
string text3 = (Configs.NoRichTextTags.Value ? StringExtensionMethods.RemoveRichTextTags(text2) : text2);
if (SignItem.TryGetItemFromHash(@int, out ItemData item))
{
text3 = StringExt.Localize(ItemDataExt.GetName(item)) + "\nFoo111";
}
ZColor val = ZColor.op_Implicit(Configs.SignTextColor.Value);
if (ZColor.op_Implicit(val) != Color.clear)
{
text3 = $"<color={val}>{text3}</color>";
}
InjectText(text3);
}
catch (Exception ex)
{
Log.Error((object)ex, (ushort)0);
zdo2.Serialize(pkg2);
}
void InjectText(string text)
{
Log.Info((object)("Injected sign text: " + text), (ushort)0);
string @string = zdo2.GetString(ZDOVars.s_text, "");
SetWithoutRevision(ZDOVars.s_text, text);
zdo2.Serialize(pkg2);
SetWithoutRevision(ZDOVars.s_text, @string);
}
void SetWithoutRevision(int hash, string value)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
ZDOExtraData.Set(zdo2.m_uid, hash, value);
}
}
}
public class ServerContainer : IContainer, ISearchable
{
[CompilerGenerated]
private ZDO <zdo>P;
public static readonly Dictionary<ZDO, ServerContainer> All = new Dictionary<ZDO, ServerContainer>();
public ZDO ZDO => <zdo>P;
public Piece? Piece => null;
public Vector3 Position => Vector3.zero;
public ServerContainer(ZDO zdo)
{
<zdo>P = zdo;
base..ctor();
}
public bool HaveItem(string itemName)
{
throw new NotImplementedException();
}
public int GetItemTotal(string itemName)
{
throw new NotImplementedException();
}
}
public class ServerSign : ISign, ISearchable
{
public static readonly int SignPrefabHash = StringExtensionMethods.GetStableHashCode("sign");
public static Dictionary<ZDO, ServerSign> All = new Dictionary<ZDO, ServerSign>();
private ZDO _zdo;
public Piece? Piece => null;
public Vector3 Position => _zdo.GetPosition();
public ZDO ZDO => _zdo;
public bool IsAssignedItem => false;
public string ItemName => "foo";
public ServerSign(ZDO zdo)
{
_zdo = zdo;
All.Add(zdo, this);
}
public bool HaveItem(string itemName)
{
return false;
}
public int GetItemTotal(string itemName)
{
return Random.Range(0, 100);
}
public void UpdateQty()
{
}
}
public static class SignExt
{
public static bool IsSign(this ZDO zdo)
{
return zdo.GetPrefab() == ServerSign.SignPrefabHash;
}
}
public static class TestStub
{
public static void DoTesting()
{
Timing.StartCoroutine(LoopIt());
}
private static IEnumerator LoopIt()
{
while (true)
{
yield return (object)new WaitForSeconds(1f);
Log.Warning((object)"Testing", (ushort)0);
Log.Warning((object)$"Signs loaded: {Search.All.Signs.Count}", (ushort)0);
Log.Warning((object)$"Containers loaded: {Search.All.Containers.Count}", (ushort)0);
Log.Warning((object)$"ZNetScene exists?: {Object.op_Implicit((Object)(object)ZNetScene.instance)}", (ushort)0);
Log.Warning((object)$"ZDOMan zdo count: {ZDOMan.instance.m_objectsByID.Count}", (ushort)0);
}
}
}
}