using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComfyLib;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PassWard")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PassWard")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f51143e3-8886-4bc6-901c-89f307cc9714")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace PassWard
{
public static class PluginConfig
{
public enum UserListSeperator
{
Newline,
Comma
}
public enum UserListSorting
{
Unsorted,
Alphabetically,
ReverseAlphabetically
}
public static ConfigEntry<bool> IsModEnabled { get; private set; }
public static ConfigEntry<KeyboardShortcut> EnterPasswordKey { get; private set; }
public static ConfigEntry<KeyboardShortcut> RemovePasswordKey { get; private set; }
public static ConfigEntry<UserListSeperator> WardHoverTextUserListSeparator { get; private set; }
public static ConfigEntry<UserListSorting> WardHoverTextUserListSorting { get; private set; }
public static void BindConfig(ConfigFile config)
{
//IL_003c: 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)
IsModEnabled = config.BindInOrder("_Global", "isModEnabled", defaultValue: true, "Globally enable or disable this mod.");
EnterPasswordKey = config.BindInOrder<KeyboardShortcut>("Hotkeys", "enterPasswordShortcut", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Enter password into a passworded ward OR assign password to own ward.");
RemovePasswordKey = config.BindInOrder<KeyboardShortcut>("Hotkeys", "removePasswordKey", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Removes password on player's own passworded ward.");
WardHoverTextUserListSeparator = config.BindInOrder("HoverText", "userListSeparator", UserListSeperator.Newline, "Separator to use between player names for a ward's hover-text.");
WardHoverTextUserListSorting = config.BindInOrder("HoverText", "userListSorting", UserListSorting.Unsorted, "What sorting (if any) to use for player names for a ward's hover-text.");
WardHoverTextUserListSorting.OnSettingChanged<UserListSorting>(WardManager.ClearCachedPermittedPlayerNames);
}
}
public sealed class TryPasswordReceiver : TextReceiver
{
private readonly PrivateArea _privateArea;
public TryPasswordReceiver(PrivateArea privateArea)
{
_privateArea = privateArea;
}
public string GetText()
{
return string.Empty;
}
public void SetText(string enteredPassword)
{
int @int = _privateArea.m_nview.GetZDO().GetInt(1595635768, -1);
if (@int == -1)
{
WardManager.ShowMessage("No password on ward.");
}
else if (StringExtensionMethods.GetStableHashCode(enteredPassword) != @int)
{
WardManager.ShowMessage("Incorrect password.");
}
else
{
WardManager.OptPlayerIn(_privateArea);
}
}
}
public sealed class WardPasswordReceiver : TextReceiver
{
private readonly PrivateArea _privateArea;
public WardPasswordReceiver(PrivateArea privateArea)
{
_privateArea = privateArea;
}
public string GetText()
{
return string.Empty;
}
public void SetText(string password)
{
_privateArea.m_nview.GetZDO().Set(1595635768, StringExtensionMethods.GetStableHashCode(password), false);
WardManager.ShowMessage("Password set.");
}
}
public static class WardManager
{
public const int GuardStoneHash = -1024209535;
public const int PasswordHash = 1595635768;
private static readonly List<string> _cachedPlayerNames = new List<string>(100);
private static ZDOID _lastZDOID = ZDOID.None;
private static uint _lastDataRevision = uint.MaxValue;
private static int[] _cachedPuIdHashCodes = Array.Empty<int>();
private static int[] _cachedPuNameHashCodes = Array.Empty<int>();
public static void OptPlayerIn(PrivateArea privateArea)
{
if (!Object.op_Implicit((Object)(object)privateArea) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
PassWard.LogError("Error opting-in after password success.");
return;
}
long playerID = Player.m_localPlayer.GetPlayerID();
if (privateArea.IsPermitted(playerID))
{
ShowMessage("Already opted-in.");
return;
}
privateArea.AddPermitted(playerID, Player.m_localPlayer.GetPlayerName());
ShowMessage("Password accepted.");
Talker val = default(Talker);
if (((Component)Player.m_localPlayer).TryGetComponent<Talker>(ref val))
{
val.Say((Type)1, "[PassWard] " + privateArea.GetCreatorName() + "'s Ward: password accepted.");
}
}
public static void AddPasswordHoverText(PrivateArea privateArea, StringBuilder hoverText)
{
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
bool flag = HasPassword(privateArea);
if (privateArea.m_piece.IsCreator())
{
if (flag)
{
hoverText.Append("\n<size=18>[<color=yellow>").Append(PluginConfig.RemovePasswordKey.Value).Append("</color>] Remove password.</size>");
}
hoverText.Append("\n<size=18>[<color=yellow>").Append(PluginConfig.EnterPasswordKey.Value).Append("</color>] ")
.Append(flag ? "Change password.</size>" : "Add password.</size>");
}
else if (flag)
{
hoverText.Append("\n\n<size=18><color=green>Password enabled</color>\n[<color=yellow>").Append(PluginConfig.EnterPasswordKey.Value).Append("</color>] Enter password.</size>");
}
else
{
hoverText.Append("\n\n<size=18><color=red>No password</color></size>");
}
}
public static void EnterPassword(PrivateArea privateArea)
{
bool flag = HasPassword(privateArea);
if (privateArea.m_piece.IsCreator())
{
WardPasswordReceiver wardPasswordReceiver = new WardPasswordReceiver(privateArea);
TextInput.instance.RequestText((TextReceiver)(object)wardPasswordReceiver, flag ? "Change password" : "Set password", 32);
}
else if (!flag)
{
ShowMessage("No password assigned to this ward. Cannot opt-in using password.");
}
else
{
TryPasswordReceiver tryPasswordReceiver = new TryPasswordReceiver(privateArea);
TextInput.instance.RequestText((TextReceiver)(object)tryPasswordReceiver, "Enter password", 32);
}
}
public static void RemovePassword(PrivateArea privateArea)
{
if (!privateArea.m_piece.IsCreator())
{
ShowMessage("You do not own this ward. Cannot remove password.");
return;
}
if (!HasPassword(privateArea))
{
ShowMessage("No password on this ward to remove.");
return;
}
privateArea.m_nview.m_zdo.Set(1595635768, -1, false);
ShowMessage("Password removed.");
}
public static bool HasPassword(PrivateArea privateArea)
{
int num = default(int);
if (privateArea.m_nview.m_zdo.GetInt(1595635768, ref num))
{
return num != -1;
}
return false;
}
public static void ShowMessage(string message)
{
if (Object.op_Implicit((Object)(object)MessageHud.instance))
{
MessageHud.instance.ShowMessage((MessageType)1, message, 0, (Sprite)null, false);
}
}
public static void ClearCachedPermittedPlayerNames()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
_lastZDOID = ZDOID.None;
_lastDataRevision = uint.MaxValue;
_cachedPlayerNames.Clear();
}
public static List<string> GetCachedPermittedPlayerNames(ZDO zdo)
{
//IL_0000: 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_0026: 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)
if (_lastZDOID == zdo.m_uid && _lastDataRevision == zdo.DataRevision)
{
return _cachedPlayerNames;
}
_lastZDOID = zdo.m_uid;
_lastDataRevision = zdo.DataRevision;
_cachedPlayerNames.Clear();
int num = Mathf.Max(zdo.GetInt(ZDOVars.s_permitted, 0), 0);
CachePuIdNameHashCodes(num);
for (int i = 0; i < num; i++)
{
if (zdo.GetLong(_cachedPuIdHashCodes[i], 0L) != 0L)
{
string @string = zdo.GetString(_cachedPuNameHashCodes[i], string.Empty);
if (@string.Length > 0)
{
_cachedPlayerNames.Add(@string);
}
}
}
switch (PluginConfig.WardHoverTextUserListSorting.Value)
{
case PluginConfig.UserListSorting.Alphabetically:
_cachedPlayerNames.Sort(StringComparer.OrdinalIgnoreCase);
break;
case PluginConfig.UserListSorting.ReverseAlphabetically:
_cachedPlayerNames.Sort(StringComparer.OrdinalIgnoreCase);
_cachedPlayerNames.Reverse();
break;
}
return _cachedPlayerNames;
}
private static void CachePuIdNameHashCodes(int capacity)
{
int num = Mathf.Min(_cachedPuIdHashCodes.Length, _cachedPuNameHashCodes.Length);
if (capacity > 0 && capacity >= num)
{
Array.Resize(ref _cachedPuIdHashCodes, capacity);
Array.Resize(ref _cachedPuNameHashCodes, capacity);
for (int i = num; i < capacity; i++)
{
_cachedPuIdHashCodes[i] = StringExtensionMethods.GetStableHashCode($"pu_id{i}");
_cachedPuNameHashCodes[i] = StringExtensionMethods.GetStableHashCode($"pu_name{i}");
}
}
}
}
[BepInPlugin("bruce.valheim.mods.passward", "PassWard", "1.3.0")]
public sealed class PassWard : BaseUnityPlugin
{
public const string PluginGuid = "bruce.valheim.mods.passward";
public const string PluginName = "PassWard";
public const string PluginVersion = "1.3.0";
private static ManualLogSource _logger;
private void Awake()
{
_logger = ((BaseUnityPlugin)this).Logger;
PluginConfig.BindConfig(((BaseUnityPlugin)this).Config);
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "bruce.valheim.mods.passward");
}
public static void LogError(object obj)
{
_logger.LogError((object)$"[{DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo)}] {obj}");
}
}
[HarmonyPatch(typeof(Game))]
internal static class GamePatch
{
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void StartPostfix()
{
if (PluginConfig.IsModEnabled.Value)
{
WardManager.ClearCachedPermittedPlayerNames();
}
}
[HarmonyPrefix]
[HarmonyPatch("OnDestroy")]
private static void OnDestroyPrefix()
{
if (PluginConfig.IsModEnabled.Value)
{
WardManager.ClearCachedPermittedPlayerNames();
}
}
}
[HarmonyPatch(typeof(Player))]
internal static class PlayerPatch
{
[HarmonyTranspiler]
[HarmonyPatch("Update")]
private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0002: 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_003b: Expected O, but got Unknown
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
return new CodeMatcher(instructions, (ILGenerator)null).Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdateHover", (Type[])null, (Type[])null), (string)null)
}).ThrowIfInvalid("Could not patch Player.Update()! (update-hover)")
.Advance(1)
.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldloc_1, (object)null),
new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlayerPatch), "UpdateHoverPostDelegate", (Type[])null, (Type[])null))
})
.InstructionEnumeration();
}
private static void UpdateHoverPostDelegate(bool takeInput)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
if (takeInput && PluginConfig.IsModEnabled.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
KeyboardShortcut value = PluginConfig.EnterPasswordKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown() && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_hovering) && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_hovering.TryGetComponentInParent<PrivateArea>(out PrivateArea component)))
{
WardManager.EnterPassword(component);
}
value = PluginConfig.RemovePasswordKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown() && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_hovering) && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_hovering.TryGetComponentInParent<PrivateArea>(out component)))
{
WardManager.RemovePassword(component);
}
}
}
public static T TryGetComponentInParent<T>(this GameObject gameObject, out T component) where T : Component
{
component = gameObject.GetComponentInParent<T>();
return component;
}
}
[HarmonyPatch(typeof(PrivateArea))]
internal static class PrivateAreaPatch
{
[HarmonyPrefix]
[HarmonyPatch("AddUserList")]
private static bool AddUserList(PrivateArea __instance, StringBuilder text)
{
if (PluginConfig.IsModEnabled.Value)
{
AddUserListUsingSeparator(__instance, text);
return false;
}
return true;
}
public static void AddUserListUsingSeparator(PrivateArea privateArea, StringBuilder text)
{
List<string> cachedPermittedPlayerNames = WardManager.GetCachedPermittedPlayerNames(privateArea.m_nview.m_zdo);
int count = cachedPermittedPlayerNames.Count;
text.Append("\n$piece_guardstone_additional: ");
if (count >= 1)
{
string value = ((PluginConfig.WardHoverTextUserListSeparator.Value == PluginConfig.UserListSeperator.Newline) ? "\n" : ", ");
text.Append(cachedPermittedPlayerNames[0]);
for (int i = 1; i < count; i++)
{
text.Append(value).Append(cachedPermittedPlayerNames[i]);
}
}
}
[HarmonyPostfix]
[HarmonyPatch("AddUserList")]
private static void AddUserListPostfix(PrivateArea __instance, StringBuilder text)
{
if (PluginConfig.IsModEnabled.Value)
{
WardManager.AddPasswordHoverText(__instance, text);
}
}
}
}
namespace ComfyLib
{
public static class ConfigFileExtensions
{
internal sealed class ConfigurationManagerAttributes
{
public Action<ConfigEntryBase> CustomDrawer;
public bool? Browsable;
public bool? HideDefaultButton;
public bool? HideSettingName;
public bool? IsAdvanced;
public int? Order;
public bool? ReadOnly;
}
private static readonly Dictionary<string, int> _sectionToSettingOrder = new Dictionary<string, int>();
private static int GetSettingOrder(string section)
{
if (!_sectionToSettingOrder.TryGetValue(section, out var value))
{
value = 0;
}
_sectionToSettingOrder[section] = value - 1;
return value;
}
public static ConfigEntry<T> BindInOrder<T>(this ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase acceptableValues, bool browsable = true, bool hideDefaultButton = false, bool hideSettingName = false, bool isAdvanced = false, bool readOnly = false)
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, new object[1]
{
new ConfigurationManagerAttributes
{
Browsable = browsable,
CustomDrawer = null,
HideDefaultButton = hideDefaultButton,
HideSettingName = hideSettingName,
IsAdvanced = isAdvanced,
Order = GetSettingOrder(section),
ReadOnly = readOnly
}
}));
}
public static ConfigEntry<T> BindInOrder<T>(this ConfigFile config, string section, string key, T defaultValue, string description, Action<ConfigEntryBase> customDrawer = null, bool browsable = true, bool hideDefaultButton = false, bool hideSettingName = false, bool isAdvanced = false, bool readOnly = false)
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Browsable = browsable,
CustomDrawer = customDrawer,
HideDefaultButton = hideDefaultButton,
HideSettingName = hideSettingName,
IsAdvanced = isAdvanced,
Order = GetSettingOrder(section),
ReadOnly = readOnly
}
}));
}
public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action settingChangedHandler)
{
configEntry.SettingChanged += delegate
{
settingChangedHandler();
};
}
public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action<T> settingChangedHandler)
{
configEntry.SettingChanged += delegate(object _, EventArgs eventArgs)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
settingChangedHandler((T)((SettingChangedEventArgs)eventArgs).ChangedSetting.BoxedValue);
};
}
public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action<ConfigEntry<T>> settingChangedHandler)
{
configEntry.SettingChanged += delegate(object _, EventArgs eventArgs)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
settingChangedHandler((ConfigEntry<T>)((SettingChangedEventArgs)eventArgs).ChangedSetting.BoxedValue);
};
}
}
}