using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Pix.Marriage;
[BepInPlugin("Pix.Marriage", "Marriage", "0.2.6")]
public sealed class MarriagePlugin : BaseUnityPlugin
{
private struct Proposal
{
public long FromUid;
public string FromName;
public string FromHouseholdId;
public float LastNotifyTime;
}
private sealed class Household
{
public string id;
public Dictionary<long, Member> members = new Dictionary<long, Member>();
}
private sealed class Member
{
public long uid;
public string name;
public double bondSeconds;
}
[HarmonyPatch(typeof(ZRoutedRpc))]
private static class Patch_ZRoutedRpc_Ctor
{
[HarmonyPostfix]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
private static void Postfix(ZRoutedRpc __instance, bool server)
{
TryRegisterRpcsLate();
}
}
[HarmonyPatch(typeof(Terminal), "Awake")]
private static class Patch_Terminal_Awake
{
private static void Postfix()
{
TryRegisterConsoleCommands();
}
}
[HarmonyPatch(typeof(Character), "OnDeath")]
private static class Patch_Character_OnDeath
{
private static void Postfix(Character __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !_enableMourning.Value)
{
return;
}
Player val = (Player)(object)((__instance is Player) ? __instance : null);
if ((Object)(object)val == (Object)null)
{
return;
}
try
{
long playerID = val.GetPlayerID();
if (playerID == 0L || !UidToHousehold.TryGetValue(playerID, out var value) || string.IsNullOrEmpty(value) || !Households.TryGetValue(value, out var value2))
{
return;
}
int tier = 1;
if (value2.members.TryGetValue(playerID, out var value3))
{
tier = Math.Max(1, GetTierFromBondSeconds(value3.bondSeconds));
}
float durationSeconds = Mathf.Max(1f, _mourningDurationSeconds.Value);
foreach (KeyValuePair<long, Member> member in value2.members)
{
long key = member.Key;
if (key != playerID && ZNet.instance.GetPeer(key) != null)
{
Server_ToClientMourning(key, tier, durationSeconds);
}
}
}
catch
{
}
}
}
[HarmonyPatch(typeof(ObjectDB), "Awake")]
private static class Patch_ObjectDB_Awake
{
private static void Postfix(ObjectDB __instance)
{
TryRegisterStatusEffects(__instance);
}
}
[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
private static class Patch_ObjectDB_CopyOtherDB
{
private static void Postfix(ObjectDB __instance, ObjectDB other)
{
TryRegisterStatusEffects(__instance);
}
}
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static ConsoleEvent <>9__108_0;
public static ConsoleEvent <>9__108_1;
public static ConsoleEvent <>9__108_2;
public static ConsoleEvent <>9__108_3;
public static ConsoleEvent <>9__108_4;
public static ConsoleEvent <>9__108_5;
public static ConsoleEvent <>9__108_6;
internal void <TryRegisterConsoleCommands>b__108_0(ConsoleEventArgs args)
{
try
{
if (args?.Args == null || args.Args.Length < 2)
{
MessageCenter("Usage: /marry <playerName>");
return;
}
string s = string.Join(" ", args.Args, 1, args.Args.Length - 1);
s = NormalizePlayerNameInput(s).Trim(new char[1] { '"' });
if (string.IsNullOrEmpty(s))
{
MessageCenter("Usage: /marry <playerName>");
}
else
{
Client_RequestMarriage(s);
}
}
catch
{
}
}
internal void <TryRegisterConsoleCommands>b__108_1(ConsoleEventArgs args)
{
try
{
Client_RespondMarriage(accept: true);
}
catch
{
}
}
internal void <TryRegisterConsoleCommands>b__108_2(ConsoleEventArgs args)
{
try
{
Client_RespondMarriage(accept: false);
}
catch
{
}
}
internal void <TryRegisterConsoleCommands>b__108_3(ConsoleEventArgs args)
{
try
{
Client_RequestDivorce();
}
catch
{
}
}
internal void <TryRegisterConsoleCommands>b__108_4(ConsoleEventArgs args)
{
int result = 1;
if (args.Args != null && args.Args.Length >= 2)
{
int.TryParse(args.Args[1], out result);
}
result = Mathf.Clamp(result, 1, MaxTierClamped());
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_MarrySelf", new object[1] { result });
}
}
internal void <TryRegisterConsoleCommands>b__108_5(ConsoleEventArgs args)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_ClearMarriage", Array.Empty<object>());
}
}
internal void <TryRegisterConsoleCommands>b__108_6(ConsoleEventArgs args)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_State", Array.Empty<object>());
}
}
}
public const string PluginGuid = "Pix.Marriage";
public const string PluginName = "Marriage";
public const string PluginVersion = "0.2.6";
private static MarriagePlugin _self;
private Harmony _harmony;
private const string RpcRequestMarriage = "PX_Marry_Request";
private const string RpcRespondMarriage = "PX_Marry_Response";
private const string RpcNotifyProposal = "PX_Marry_NotifyProposal";
private const string RpcNotifyToast = "PX_Marry_NotifyToast";
private const string RpcDebugMarrySelf = "PX_Debug_MarrySelf";
private const string RpcDebugClear = "PX_Debug_ClearMarriage";
private const string RpcDebugState = "PX_Debug_State";
private const string RpcClientSetFamilyTier = "PX_Family_SetTier";
private const string RpcClientSetFamilyProgress = "PX_Family_SetProgress";
private const string RpcClientPlayFamilyVfx = "PX_Family_PlayVfx";
private const string RpcClientMourning = "PX_Mourning_Apply";
private const string FamilySeBase = "SE_PX_Marriage_Family_";
private const string MourningSeBase = "SE_PX_Marriage_Mourning_";
private static string[] FamilySeNames;
private static int[] _familySeHashes;
private static string[] MourningSeNames;
private static int[] _mourningSeHashes;
private static Sprite _familyIcon;
private static Sprite _mourningIcon;
private static bool _iconsTried;
private static bool _pngLoaderTried;
private static MethodInfo _miTexture2D_LoadImage_Bytes;
private static MethodInfo _miTexture2D_LoadImage_BytesBool;
private static MethodInfo _miImageConversion_LoadImage;
private static ConfigEntry<float> _rangeMeters;
private static ConfigEntry<float> _saveIntervalSeconds;
private static ConfigEntry<int> _maxTier;
private static ConfigEntry<bool> _startAtTier1;
private static ConfigEntry<int> _tier1Days;
private static ConfigEntry<int> _tier2Days;
private static ConfigEntry<int> _tier3Days;
private static ConfigEntry<int> _tier4Days;
private static ConfigEntry<int> _tier5Days;
private static ConfigEntry<int> _tier6Days;
private static ConfigEntry<int> _tier7Days;
private static ConfigEntry<int> _tier8Days;
private static ConfigEntry<int> _tier9Days;
private static ConfigEntry<int> _tier10Days;
private static ConfigEntry<float> _tierBaseBonus;
private static ConfigEntry<bool> _tierDoubleEachTier;
private static ConfigEntry<float> _tierMaxBonus;
private static ConfigEntry<bool> _buffMove;
private static ConfigEntry<bool> _buffDamage;
private static ConfigEntry<bool> _buffStaminaRegen;
private static ConfigEntry<bool> _buffHealthRegen;
private static ConfigEntry<bool> _buffEitrRegen;
private static ConfigEntry<bool> _enableEnterVfx;
private static ConfigEntry<string> _enterVfxItemPrefab;
private static ConfigEntry<float> _enterVfxCooldownSeconds;
private static ConfigEntry<bool> _enableMourning;
private static ConfigEntry<float> _mourningDurationSeconds;
private static ConfigEntry<float> _mourningBasePenalty;
private static ConfigEntry<float> _mourningMaxPenalty;
private static ConfigEntry<bool> _mourningDoublesWithTier;
private static ConfigEntry<float> _mourningCarryWeightPenalty;
private static ConfigEntry<bool> _announce;
private static ConfigEntry<bool> _familyProgressInTooltip;
private static ConfigEntry<bool> _familyProgressToasts;
private static ConfigEntry<bool> _familyTierUpToasts;
private static ConfigEntry<float> _progressSendIntervalSeconds;
private static ConfigEntry<bool> _debugEnabledServer;
private static ConfigEntry<bool> _diagnosticsVerbose;
private static bool _rpcsRegistered;
private static bool _loggedRpcRegister;
private static bool _consoleCommandsRegistered;
private float _serverTickTimer;
private const float ServerTickInterval = 1f;
private const float ProposalRenotifyInterval = 5f;
private const float InGameDaySeconds = 1800f;
private static readonly Dictionary<long, Proposal> Pending = new Dictionary<long, Proposal>();
private static readonly Dictionary<string, Household> Households = new Dictionary<string, Household>();
private static readonly Dictionary<long, string> UidToHousehold = new Dictionary<long, string>();
private static string _householdsPath;
private static bool _householdsLoaded;
private static bool _householdsDirty;
private static float _lastSaveRealtime;
private static double _lastWorldTimeSeconds;
private static readonly Dictionary<long, int> _lastSentTier = new Dictionary<long, int>();
private static readonly Dictionary<long, float> _lastSentProgressRealtime = new Dictionary<long, float>();
private static readonly HashSet<long> _debugSoloFamily = new HashSet<long>();
private static float _clientNextVfxTime;
private static float _clientMourningEndTime;
private static int _clientMourningTier;
private static int _clientFamilyTier;
private static float _clientFamilyBondDays;
private static int _clientFamilyMilestoneBucket;
private void Awake()
{
//IL_0524: Unknown result type (might be due to invalid IL or missing references)
//IL_052e: Expected O, but got Unknown
_self = this;
_rangeMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Family", "RangeMeters", 25f, "Distance required to activate Family buff.");
_saveIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Persistence", "SaveIntervalSeconds", 60f, "Minimum seconds between household file writes when dirty.");
_maxTier = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "MaxTier", 10, "Maximum tier supported (5 to 10).");
_startAtTier1 = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "StartAtTier1", true, "If true, new household members start at Tier 1 so Family can activate immediately.");
_tier1Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier1Days", 6, "In-game days alive in household to reach tier 1.");
_tier2Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier2Days", 12, "In-game days alive in household to reach tier 2.");
_tier3Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier3Days", 24, "In-game days alive in household to reach tier 3.");
_tier4Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier4Days", 48, "In-game days alive in household to reach tier 4.");
_tier5Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier5Days", 60, "In-game days alive in household to reach tier 5.");
_tier6Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier6Days", 90, "In-game days alive in household to reach tier 6.");
_tier7Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier7Days", 120, "In-game days alive in household to reach tier 7.");
_tier8Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier8Days", 180, "In-game days alive in household to reach tier 8.");
_tier9Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier9Days", 240, "In-game days alive in household to reach tier 9.");
_tier10Days = ((BaseUnityPlugin)this).Config.Bind<int>("Tiers", "Tier10Days", 300, "In-game days alive in household to reach tier 10.");
_tierBaseBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Tiers", "TierBaseBonus", 0.02f, "Tier 1 additive bonus (0.02=2%).");
_tierDoubleEachTier = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "TierDoubleEachTier", true, "If true, the base bonus doubles each tier.");
_tierMaxBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Tiers", "TierMaxBonus", 0.32f, "Max tier bonus cap (0.32=32%).");
_buffMove = ((BaseUnityPlugin)this).Config.Bind<bool>("FamilyBuff", "BuffMoveSpeed", true, "Family buff affects move speed.");
_buffDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("FamilyBuff", "BuffDamage", true, "Family buff affects damage.");
_buffStaminaRegen = ((BaseUnityPlugin)this).Config.Bind<bool>("FamilyBuff", "BuffStaminaRegen", true, "Family buff affects stamina regen.");
_buffHealthRegen = ((BaseUnityPlugin)this).Config.Bind<bool>("FamilyBuff", "BuffHealthRegen", true, "Family buff affects health regen.");
_buffEitrRegen = ((BaseUnityPlugin)this).Config.Bind<bool>("FamilyBuff", "BuffEitrRegen", true, "Family buff affects eitr regen.");
_enableEnterVfx = ((BaseUnityPlugin)this).Config.Bind<bool>("VFX", "EnableEnterRangeVfx", true, "Play a VFX when entering Family range.");
_enterVfxItemPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("VFX", "EnterRangeVfxItemPrefab", "MeadHasty", "Item prefab to copy consume VFX from.");
_enterVfxCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("VFX", "EnterRangeVfxCooldownSeconds", 30f, "Client cooldown to prevent VFX spam.");
_enableMourning = ((BaseUnityPlugin)this).Config.Bind<bool>("Mourning", "EnableMourning", true, "Apply Mourning when a household member dies.");
_mourningDurationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Mourning", "DurationSeconds", 900f, "Mourning duration in seconds.");
_mourningBasePenalty = ((BaseUnityPlugin)this).Config.Bind<float>("Mourning", "BasePenalty", 0.05f, "Tier 1 additive penalty (0.05=5%).");
_mourningMaxPenalty = ((BaseUnityPlugin)this).Config.Bind<float>("Mourning", "MaxPenalty", 0.32f, "Max penalty cap (0.32=32%).");
_mourningDoublesWithTier = ((BaseUnityPlugin)this).Config.Bind<bool>("Mourning", "DoublesWithTier", true, "If true, mourning penalty doubles each tier.");
_mourningCarryWeightPenalty = ((BaseUnityPlugin)this).Config.Bind<float>("Mourning", "CarryWeightPenalty", -100f, "Carry weight penalty.");
_announce = ((BaseUnityPlugin)this).Config.Bind<bool>("Social", "AnnounceHouseholds", true, "Announce household events.");
_familyProgressInTooltip = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "FamilyProgressInTooltip", true, "Show tier progress-to-next in the Family StatusEffect tooltip.");
_familyProgressToasts = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "FamilyProgressToasts", true, "Toast at 25/50/75/100% progress toward next tier (while Family is active).");
_familyTierUpToasts = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "FamilyTierUpToasts", true, "Toast when Family tier increases.");
_progressSendIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "ProgressSendIntervalSeconds", 6f, "Server -> client progress update interval (seconds) while Family is active.");
_debugEnabledServer = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugCommands", false, "Enable server-authoritative debug commands.");
_diagnosticsVerbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseDiagnostics", true, "Extra logs for troubleshooting.");
BuildSeArrays();
_householdsPath = Path.Combine(Paths.ConfigPath, "pix.marriage.households.txt");
_harmony = new Harmony("Pix.Marriage");
_harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"[Marriage] Loaded v0.2.6.");
}
private void OnDestroy()
{
try
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
catch
{
}
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
SaveHouseholdsIfDirty(force: true);
}
}
private void Update()
{
TryRegisterRpcsLate();
Client_UpdateMourning();
if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
{
if (!_householdsLoaded)
{
LoadHouseholdsOnce();
}
ServerTick_AccrueBondSeconds();
_serverTickTimer += Time.deltaTime;
if (!(_serverTickTimer < 1f))
{
_serverTickTimer = 0f;
ServerTick_RenotifyProposals();
ServerTick_ProximityFamily();
ServerTick_CleanupStaleProposals();
ServerTick_CleanupDisconnectedCaches();
SaveHouseholdsIfDirty(force: false);
}
}
}
private static int MaxTierClamped()
{
int num = ((_maxTier != null) ? _maxTier.Value : 5);
return Mathf.Clamp(num, 5, 10);
}
private static void BuildSeArrays()
{
int num = MaxTierClamped();
FamilySeNames = new string[num];
_familySeHashes = new int[num];
for (int i = 0; i < num; i++)
{
FamilySeNames[i] = "SE_PX_Marriage_Family_" + (i + 1).ToString(CultureInfo.InvariantCulture);
_familySeHashes[i] = FamilySeNames[i].GetStableHashCode();
}
MourningSeNames = new string[num];
_mourningSeHashes = new int[num];
for (int j = 0; j < num; j++)
{
MourningSeNames[j] = "SE_PX_Marriage_Mourning_" + (j + 1).ToString(CultureInfo.InvariantCulture);
_mourningSeHashes[j] = MourningSeNames[j].GetStableHashCode();
}
}
private static float GetTierThresholdDays(int tier)
{
tier = Mathf.Clamp(tier, 1, MaxTierClamped());
return tier switch
{
1 => _tier1Days.Value,
2 => _tier2Days.Value,
3 => _tier3Days.Value,
4 => _tier4Days.Value,
5 => _tier5Days.Value,
6 => _tier6Days.Value,
7 => _tier7Days.Value,
8 => _tier8Days.Value,
9 => _tier9Days.Value,
_ => _tier10Days.Value,
};
}
private static int GetTierFromBondSeconds(double bondSeconds)
{
double num = bondSeconds / 1800.0;
int num2 = MaxTierClamped();
int result = 0;
for (int i = 1; i <= num2 && num >= (double)GetTierThresholdDays(i); i++)
{
result = i;
}
return result;
}
private static float GetTierBonus(int tier)
{
if (tier <= 0)
{
return 0f;
}
float num = Mathf.Clamp(_tierBaseBonus.Value, 0f, 5f);
float num2 = num;
if (_tierDoubleEachTier.Value)
{
int num3 = Mathf.Clamp(tier - 1, 0, 20);
num2 = num * (float)(1 << num3);
}
float num4 = Mathf.Clamp(_tierMaxBonus.Value, 0f, 5f);
return Mathf.Min(num2, num4);
}
private static float GetMourningPenalty(int tier)
{
tier = Mathf.Clamp(tier, 1, MaxTierClamped());
float num = Mathf.Clamp(_mourningBasePenalty.Value, 0f, 5f);
float num2 = num;
if (_mourningDoublesWithTier.Value)
{
int num3 = Mathf.Clamp(tier - 1, 0, 20);
num2 = num * (float)(1 << num3);
}
float num4 = Mathf.Clamp(_mourningMaxPenalty.Value, 0f, 5f);
return Mathf.Min(num2, num4);
}
private static double TierToMinBondSeconds(int tier)
{
int tier2 = Mathf.Clamp(tier, 1, MaxTierClamped());
return (double)GetTierThresholdDays(tier2) * 1800.0;
}
private static void TryRegisterRpcsLate()
{
if (!_rpcsRegistered && ZRoutedRpc.instance != null)
{
RegisterRpcs(ZRoutedRpc.instance);
_rpcsRegistered = true;
if (!_loggedRpcRegister && (Object)(object)_self != (Object)null)
{
_loggedRpcRegister = true;
((BaseUnityPlugin)_self).Logger.LogInfo((object)"[Marriage] RPCs registered.");
}
}
}
private static void RegisterRpcs(ZRoutedRpc rpc)
{
rpc.Register<string>("PX_Marry_Request", (Action<long, string>)RPC_Server_RequestMarriage);
rpc.Register<bool>("PX_Marry_Response", (Action<long, bool>)RPC_Server_RespondMarriage);
rpc.Register<int>("PX_Debug_MarrySelf", (Action<long, int>)RPC_Server_DebugMarrySelf);
rpc.Register("PX_Debug_ClearMarriage", (Action<long>)RPC_Server_DebugClearMarriage);
rpc.Register("PX_Debug_State", (Action<long>)RPC_Server_DebugState);
rpc.Register<string, long>("PX_Marry_NotifyProposal", (Action<long, string, long>)RPC_Client_NotifyProposal);
rpc.Register<string>("PX_Marry_NotifyToast", (Action<long, string>)RPC_Client_NotifyToast);
rpc.Register<int>("PX_Family_SetTier", (Action<long, int>)RPC_Client_SetFamilyTier);
rpc.Register<int, float>("PX_Family_SetProgress", (Action<long, int, float>)RPC_Client_SetFamilyProgress);
rpc.Register<string>("PX_Family_PlayVfx", (Action<long, string>)RPC_Client_PlayFamilyVfx);
rpc.Register<int, float>("PX_Mourning_Apply", (Action<long, int, float>)RPC_Client_ApplyMourning);
}
private static void TryRegisterConsoleCommands()
{
//IL_0040: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_0078: 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)
//IL_006f: Expected O, but got Unknown
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Expected O, but got Unknown
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Expected O, but got Unknown
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: 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_014f: Expected O, but got Unknown
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Expected O, but got Unknown
if (_consoleCommandsRegistered)
{
return;
}
_consoleCommandsRegistered = true;
object obj = <>c.<>9__108_0;
if (obj == null)
{
ConsoleEvent val = delegate(ConsoleEventArgs args)
{
try
{
if (args?.Args == null || args.Args.Length < 2)
{
MessageCenter("Usage: /marry <playerName>");
}
else
{
string s = string.Join(" ", args.Args, 1, args.Args.Length - 1);
s = NormalizePlayerNameInput(s).Trim(new char[1] { '"' });
if (string.IsNullOrEmpty(s))
{
MessageCenter("Usage: /marry <playerName>");
}
else
{
Client_RequestMarriage(s);
}
}
}
catch
{
}
};
<>c.<>9__108_0 = val;
obj = (object)val;
}
new ConsoleCommand("marry", "Invite a player to your household. Usage: /marry <playerName>", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj2 = <>c.<>9__108_1;
if (obj2 == null)
{
ConsoleEvent val2 = delegate
{
try
{
Client_RespondMarriage(accept: true);
}
catch
{
}
};
<>c.<>9__108_1 = val2;
obj2 = (object)val2;
}
new ConsoleCommand("ido", "Accept the most recent household invite. Usage: /ido", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj3 = <>c.<>9__108_2;
if (obj3 == null)
{
ConsoleEvent val3 = delegate
{
try
{
Client_RespondMarriage(accept: false);
}
catch
{
}
};
<>c.<>9__108_2 = val3;
obj3 = (object)val3;
}
new ConsoleCommand("idont", "Decline the most recent household invite. Usage: /idont", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj4 = <>c.<>9__108_3;
if (obj4 == null)
{
ConsoleEvent val4 = delegate
{
try
{
Client_RequestDivorce();
}
catch
{
}
};
<>c.<>9__108_3 = val4;
obj4 = (object)val4;
}
new ConsoleCommand("divorce", "Leave your current household. Usage: /divorce", (ConsoleEvent)obj4, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj5 = <>c.<>9__108_4;
if (obj5 == null)
{
ConsoleEvent val5 = delegate(ConsoleEventArgs args)
{
int result = 1;
if (args.Args != null && args.Args.Length >= 2)
{
int.TryParse(args.Args[1], out result);
}
result = Mathf.Clamp(result, 1, MaxTierClamped());
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_MarrySelf", new object[1] { result });
}
};
<>c.<>9__108_4 = val5;
obj5 = (object)val5;
}
new ConsoleCommand("px_marryself", "Debug: set yourself in a solo household, force bond to tier. Usage: px_marryself [tier(1-max)]", (ConsoleEvent)obj5, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj6 = <>c.<>9__108_5;
if (obj6 == null)
{
ConsoleEvent val6 = delegate
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_ClearMarriage", Array.Empty<object>());
}
};
<>c.<>9__108_5 = val6;
obj6 = (object)val6;
}
new ConsoleCommand("px_marryclear", "Debug: leave household. Usage: px_marryclear", (ConsoleEvent)obj6, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj7 = <>c.<>9__108_6;
if (obj7 == null)
{
ConsoleEvent val7 = delegate
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_State", Array.Empty<object>());
}
};
<>c.<>9__108_6 = val7;
obj7 = (object)val7;
}
new ConsoleCommand("px_marrydebug", "Debug: print state. Usage: px_marrydebug", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
}
private static void MessageCenter(string msg)
{
if (!((Object)(object)MessageHud.instance == (Object)null))
{
MessageHud.instance.ShowMessage((MessageType)2, msg, 0, (Sprite)null, false);
}
}
private static void Client_RequestMarriage(string targetName)
{
if (ZRoutedRpc.instance == null)
{
MessageCenter("RPC not ready yet.");
return;
}
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Marry_Request", new object[1] { targetName });
MessageCenter("Invite sent to " + targetName + "…");
}
private static void Client_RespondMarriage(bool accept)
{
if (ZRoutedRpc.instance == null)
{
MessageCenter("RPC not ready yet.");
return;
}
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Marry_Response", new object[1] { accept });
}
private static void Client_RequestDivorce()
{
if (ZRoutedRpc.instance == null)
{
MessageCenter("RPC not ready yet.");
return;
}
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Marry_Response", new object[1] { false });
}
private static void Client_DebugMarrySelf(int tier)
{
if (ZRoutedRpc.instance == null)
{
MessageCenter("RPC not ready yet.");
return;
}
tier = Mathf.Clamp(tier, 1, MaxTierClamped());
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_MarrySelf", new object[1] { tier });
}
private static void Client_DebugClearMarriage()
{
if (ZRoutedRpc.instance == null)
{
MessageCenter("RPC not ready yet.");
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_ClearMarriage", Array.Empty<object>());
}
}
private static void Client_DebugState()
{
if (ZRoutedRpc.instance == null)
{
MessageCenter("RPC not ready yet.");
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "PX_Debug_State", Array.Empty<object>());
}
}
private static void RPC_Client_NotifyProposal(long sender, string fromName, long fromUid)
{
MessageCenter("\ud83c\udfe0 " + fromName + " invited you to their household! Type /ido or /idont");
}
private static void RPC_Client_NotifyToast(long sender, string msg)
{
MessageCenter(msg);
}
private static void RPC_Client_SetFamilyTier(long sender, int tier)
{
int num = MaxTierClamped();
int num2 = Mathf.Clamp(tier, 0, num);
if (num2 > 0 && _familyTierUpToasts.Value && num2 > _clientFamilyTier)
{
MessageCenter($"\ud83c\udfe0 Family reached Tier {num2}!");
}
if (num2 != _clientFamilyTier)
{
_clientFamilyTier = num2;
_clientFamilyMilestoneBucket = 0;
}
Client_ApplyFamilyTierLocal(num2);
if (num2 <= 0)
{
_clientFamilyBondDays = 0f;
_clientFamilyMilestoneBucket = 0;
Client_RefreshAllFamilyTooltips(0f);
}
}
private static void RPC_Client_SetFamilyProgress(long sender, int tier, float bondDays)
{
int num = MaxTierClamped();
int num2 = Mathf.Clamp(tier, 0, num);
float bondDays2 = (_clientFamilyBondDays = Mathf.Max(0f, bondDays));
if (_familyProgressInTooltip.Value)
{
Client_RefreshFamilyTooltipForTier(num2, bondDays2);
}
if (!_familyProgressToasts.Value || num2 <= 0 || num2 >= num)
{
return;
}
int progressMilestoneBucket = GetProgressMilestoneBucket(num2, bondDays2);
if (progressMilestoneBucket > 0 && progressMilestoneBucket > _clientFamilyMilestoneBucket)
{
_clientFamilyMilestoneBucket = progressMilestoneBucket;
if (progressMilestoneBucket >= 100)
{
MessageCenter($"\ud83c\udfe0 Family Tier {num2} complete — next tier ready!");
}
else
{
MessageCenter($"\ud83c\udfe0 Family Tier {num2}: {progressMilestoneBucket}% to Tier {num2 + 1}");
}
}
}
private static int GetProgressMilestoneBucket(int tier, float bondDays)
{
int num = MaxTierClamped();
if (tier <= 0 || tier >= num)
{
return 0;
}
float tierThresholdDays = GetTierThresholdDays(tier);
float tierThresholdDays2 = GetTierThresholdDays(tier + 1);
float num2 = Mathf.Max(0.0001f, tierThresholdDays2 - tierThresholdDays);
float num3 = Mathf.Clamp(bondDays - tierThresholdDays, 0f, num2);
float num4 = num3 / num2 * 100f;
if (num4 >= 100f)
{
return 100;
}
if (num4 >= 75f)
{
return 75;
}
if (num4 >= 50f)
{
return 50;
}
if (num4 >= 25f)
{
return 25;
}
return 0;
}
private static void RPC_Client_PlayFamilyVfx(long sender, string itemPrefabName)
{
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
if (!_enableEnterVfx.Value)
{
return;
}
float time = Time.time;
float num = Mathf.Max(0f, _enterVfxCooldownSeconds.Value);
if (time < _clientNextVfxTime)
{
return;
}
_clientNextVfxTime = time + num;
try
{
Player localPlayer = Player.m_localPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)ObjectDB.instance == (Object)null || string.IsNullOrEmpty(itemPrefabName))
{
return;
}
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemPrefabName);
if ((Object)(object)itemPrefab == (Object)null)
{
return;
}
ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
if ((Object)(object)component == (Object)null)
{
return;
}
SharedData val = ((component.m_itemData != null) ? component.m_itemData.m_shared : null);
if (val != null && (Object)(object)val.m_consumeStatusEffect != (Object)null)
{
EffectList startEffects = val.m_consumeStatusEffect.m_startEffects;
if (startEffects != null)
{
startEffects.Create(((Component)localPlayer).transform.position, Quaternion.identity, ((Component)localPlayer).transform, 1f, -1);
}
}
}
catch
{
}
}
private static void RPC_Client_ApplyMourning(long sender, int tier, float durationSeconds)
{
if (_enableMourning.Value)
{
int num = MaxTierClamped();
int num2 = Mathf.Clamp(tier, 1, num);
float num3 = Mathf.Max(1f, durationSeconds);
if (num2 > _clientMourningTier)
{
_clientMourningTier = num2;
}
float time = Time.time;
float num4 = Mathf.Max(0f, _clientMourningEndTime - time);
_clientMourningEndTime = time + num4 + num3;
Client_EnsureMourningTierSe();
}
}
private static void Client_UpdateMourning()
{
if (!(_clientMourningEndTime <= 0f))
{
if (Time.time >= _clientMourningEndTime)
{
_clientMourningEndTime = 0f;
_clientMourningTier = 0;
Client_ClearMourning();
}
else
{
Client_EnsureMourningTierSe();
}
}
}
private static void Client_ClearMourning()
{
Player localPlayer = Player.m_localPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer))
{
return;
}
SEMan sEMan = ((Character)localPlayer).GetSEMan();
if (sEMan == null)
{
return;
}
int num = MaxTierClamped();
for (int i = 0; i < num; i++)
{
if (sEMan.HaveStatusEffect(_mourningSeHashes[i]))
{
sEMan.RemoveStatusEffect(_mourningSeHashes[i], true);
}
}
}
private static void Client_EnsureMourningTierSe()
{
Player localPlayer = Player.m_localPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer))
{
return;
}
SEMan sEMan = ((Character)localPlayer).GetSEMan();
if (sEMan == null)
{
return;
}
int num = MaxTierClamped();
for (int i = 0; i < num; i++)
{
if (sEMan.HaveStatusEffect(_mourningSeHashes[i]))
{
sEMan.RemoveStatusEffect(_mourningSeHashes[i], true);
}
}
int num2 = Mathf.Clamp(_clientMourningTier, 1, num);
int num3 = num2 - 1;
if (!sEMan.HaveStatusEffect(_mourningSeHashes[num3]))
{
sEMan.AddStatusEffect(_mourningSeHashes[num3], true, 0, 0f);
}
}
private static void Client_ApplyFamilyTierLocal(int tier)
{
Player localPlayer = Player.m_localPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer))
{
return;
}
SEMan sEMan = ((Character)localPlayer).GetSEMan();
if (sEMan == null)
{
return;
}
int num = MaxTierClamped();
for (int i = 0; i < num; i++)
{
if (sEMan.HaveStatusEffect(_familySeHashes[i]))
{
sEMan.RemoveStatusEffect(_familySeHashes[i], true);
}
}
if (tier >= 1 && tier <= num)
{
int num2 = tier - 1;
if (!sEMan.HaveStatusEffect(_familySeHashes[num2]))
{
sEMan.AddStatusEffect(_familySeHashes[num2], true, 0, 0f);
}
}
}
private static void RPC_Server_DebugMarrySelf(long senderUid, int tier)
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
EnsureLoadedOnServer();
if (!_debugEnabledServer.Value)
{
Server_ToClientToast(senderUid, "Debug commands are disabled on this server.");
return;
}
tier = Mathf.Clamp(tier, 1, MaxTierClamped());
ZNetPeer peer = ZNet.instance.GetPeer(senderUid);
string name = ((peer != null) ? (peer.m_playerName ?? "Player") : "Player");
_debugSoloFamily.Add(senderUid);
if (!UidToHousehold.TryGetValue(senderUid, out var value))
{
value = "H" + Guid.NewGuid().ToString("N");
Household household = new Household
{
id = value
};
Households[value] = household;
AddMemberToHousehold(household, senderUid, name);
UidToHousehold[senderUid] = value;
_householdsDirty = true;
}
if (Households.TryGetValue(UidToHousehold[senderUid], out var value2) && value2.members.TryGetValue(senderUid, out var value3))
{
value3.bondSeconds = TierToMinBondSeconds(tier);
_householdsDirty = true;
}
_lastSentTier[senderUid] = 0;
_lastSentProgressRealtime.Remove(senderUid);
Server_ToClientToast(senderUid, $"Debug: set bond to Tier {tier}.");
}
private static void RPC_Server_RequestMarriage(long senderUid, string targetName)
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
EnsureLoadedOnServer();
targetName = NormalizePlayerNameInput(targetName);
if (string.IsNullOrEmpty(targetName))
{
Server_ToClientToast(senderUid, "Usage: /marry <playerName>");
return;
}
ZNetPeer peer = ZNet.instance.GetPeer(senderUid);
if (peer == null)
{
return;
}
ZNetPeer val = FindPeerByNameSmart(targetName);
if (val == null)
{
Server_ToClientToast(senderUid, "Could not find player '" + targetName + "'.");
return;
}
if (val.m_uid == senderUid)
{
Server_ToClientToast(senderUid, "You can’t invite yourself.");
return;
}
if (UidToHousehold.ContainsKey(val.m_uid))
{
Server_ToClientToast(senderUid, val.m_playerName + " is already in a household.");
return;
}
string fromHouseholdId = null;
if (UidToHousehold.TryGetValue(senderUid, out var value))
{
fromHouseholdId = value;
}
float realtimeSinceStartup = Time.realtimeSinceStartup;
Pending[val.m_uid] = new Proposal
{
FromUid = senderUid,
FromName = (peer.m_playerName ?? "Someone"),
FromHouseholdId = fromHouseholdId,
LastNotifyTime = realtimeSinceStartup
};
ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "PX_Marry_NotifyProposal", new object[2]
{
peer.m_playerName ?? "Someone",
senderUid
});
Server_ToClientToast(senderUid, "Invite sent to " + val.m_playerName + ".");
}
private static void RPC_Server_RespondMarriage(long senderUid, bool accept)
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
EnsureLoadedOnServer();
if (!accept && UidToHousehold.ContainsKey(senderUid) && !Pending.ContainsKey(senderUid))
{
Server_LeaveHousehold(senderUid);
return;
}
if (!Pending.TryGetValue(senderUid, out var value))
{
Server_ToClientToast(senderUid, "No pending household invite.");
return;
}
Pending.Remove(senderUid);
ZNetPeer peer = ZNet.instance.GetPeer(senderUid);
ZNetPeer peer2 = ZNet.instance.GetPeer(value.FromUid);
if (peer == null || peer2 == null)
{
Server_ToClientToast(senderUid, "Invite no longer valid.");
return;
}
if (!accept)
{
Server_ToClientToast(value.FromUid, peer.m_playerName + " declined your invite.");
Server_ToClientToast(senderUid, "You declined.");
return;
}
if (UidToHousehold.ContainsKey(senderUid))
{
Server_ToClientToast(senderUid, "You are already in a household.");
return;
}
string fromHouseholdId = value.FromHouseholdId;
Household value2;
if (string.IsNullOrEmpty(fromHouseholdId))
{
fromHouseholdId = "H" + Guid.NewGuid().ToString("N");
Household household = new Household
{
id = fromHouseholdId
};
Households[fromHouseholdId] = household;
AddMemberToHousehold(household, value.FromUid, peer2.m_playerName ?? "Player");
AddMemberToHousehold(household, senderUid, peer.m_playerName ?? "Player");
UidToHousehold[value.FromUid] = fromHouseholdId;
UidToHousehold[senderUid] = fromHouseholdId;
_householdsDirty = true;
if (_announce.Value)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "PX_Marry_NotifyToast", new object[1] { "\ud83c\udfe0 " + peer2.m_playerName + " and " + peer.m_playerName + " formed a Household!" });
}
else
{
Server_ToClientToast(value.FromUid, "Household formed with " + peer.m_playerName + ".");
Server_ToClientToast(senderUid, "Household formed with " + peer2.m_playerName + ".");
}
_lastSentTier[value.FromUid] = 0;
_lastSentTier[senderUid] = 0;
_lastSentProgressRealtime.Remove(value.FromUid);
_lastSentProgressRealtime.Remove(senderUid);
}
else if (!Households.TryGetValue(fromHouseholdId, out value2))
{
Server_ToClientToast(senderUid, "Household missing (try again).");
}
else
{
AddMemberToHousehold(value2, senderUid, peer.m_playerName ?? "Player");
UidToHousehold[senderUid] = fromHouseholdId;
_householdsDirty = true;
if (_announce.Value)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "PX_Marry_NotifyToast", new object[1] { "\ud83c\udfe0 " + peer.m_playerName + " joined " + peer2.m_playerName + "'s Household!" });
}
else
{
Server_ToClientToast(senderUid, "You joined " + peer2.m_playerName + "'s Household.");
Server_ToClientToast(value.FromUid, peer.m_playerName + " joined your Household.");
}
_lastSentTier[senderUid] = 0;
_lastSentProgressRealtime.Remove(senderUid);
}
}
private static void RPC_Server_DebugClearMarriage(long senderUid)
{
if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
{
EnsureLoadedOnServer();
if (!_debugEnabledServer.Value)
{
Server_ToClientToast(senderUid, "Debug commands are disabled on this server.");
return;
}
_debugSoloFamily.Remove(senderUid);
Server_LeaveHousehold(senderUid);
Server_ToClientFamily(senderUid, 0);
Server_ToClientFamilyProgress(senderUid, 0, 0f);
}
}
private static void RPC_Server_DebugState(long senderUid)
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
EnsureLoadedOnServer();
if (!_debugEnabledServer.Value)
{
Server_ToClientToast(senderUid, "Debug commands are disabled on this server.");
return;
}
if (!UidToHousehold.TryGetValue(senderUid, out var value) || string.IsNullOrEmpty(value))
{
Server_ToClientToast(senderUid, "Not in a household.");
return;
}
if (!Households.TryGetValue(value, out var value2))
{
Server_ToClientToast(senderUid, "Household missing.");
return;
}
double num = 0.0;
if (value2.members.TryGetValue(senderUid, out var value3))
{
num = value3.bondSeconds;
}
int tierFromBondSeconds = GetTierFromBondSeconds(num);
Server_ToClientToast(senderUid, $"household={value} members={value2.members.Count} bondDays={num / 1800.0:0.0} tier={tierFromBondSeconds}");
}
private static void AddMemberToHousehold(Household hh, long uid, string name)
{
if (hh == null)
{
return;
}
if (!hh.members.TryGetValue(uid, out var value))
{
double bondSeconds = 0.0;
if (_startAtTier1 != null && _startAtTier1.Value)
{
bondSeconds = TierToMinBondSeconds(1);
}
value = new Member
{
uid = uid,
name = (name ?? "Player"),
bondSeconds = bondSeconds
};
hh.members[uid] = value;
}
else
{
value.name = name ?? value.name;
}
}
private static void Server_LeaveHousehold(long uid)
{
if (!UidToHousehold.TryGetValue(uid, out var value) || string.IsNullOrEmpty(value))
{
Server_ToClientToast(uid, "You are not in a household.");
return;
}
if (!Households.TryGetValue(value, out var value2))
{
UidToHousehold.Remove(uid);
_householdsDirty = true;
Server_ToClientToast(uid, "Household missing; you were removed.");
return;
}
value2.members.Remove(uid);
UidToHousehold.Remove(uid);
_householdsDirty = true;
_lastSentTier.Remove(uid);
_lastSentProgressRealtime.Remove(uid);
Server_ToClientFamily(uid, 0);
Server_ToClientFamilyProgress(uid, 0, 0f);
Server_ToClientToast(uid, "You left the household.");
if (value2.members.Count > 1)
{
return;
}
foreach (KeyValuePair<long, Member> member in value2.members)
{
long key = member.Key;
UidToHousehold.Remove(key);
_lastSentTier.Remove(key);
_lastSentProgressRealtime.Remove(key);
Server_ToClientFamily(key, 0);
Server_ToClientFamilyProgress(key, 0, 0f);
Server_ToClientToast(key, "Your household dissolved.");
}
Households.Remove(value);
_householdsDirty = true;
if (_announce.Value && ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "PX_Marry_NotifyToast", new object[1] { "\ud83c\udfda Household dissolved." });
}
}
private void ServerTick_AccrueBondSeconds()
{
double num = 0.0;
try
{
num = ZNet.instance.GetTimeSeconds();
}
catch
{
num = Time.timeAsDouble;
}
if (_lastWorldTimeSeconds <= 0.0)
{
_lastWorldTimeSeconds = num;
return;
}
double num2 = num - _lastWorldTimeSeconds;
if (num2 <= 0.0 || num2 > 10.0)
{
_lastWorldTimeSeconds = num;
return;
}
_lastWorldTimeSeconds = num;
List<ZNetPeer> peers = ZNet.instance.GetPeers();
if (peers == null)
{
return;
}
for (int i = 0; i < peers.Count; i++)
{
ZNetPeer val = peers[i];
if (val != null && val.m_uid != 0L)
{
long uid = val.m_uid;
if (UidToHousehold.TryGetValue(uid, out var value) && !string.IsNullOrEmpty(value) && Households.TryGetValue(value, out var value2) && value2.members.TryGetValue(uid, out var value3) && TryGetPeerAlive(val, out var alive) && alive)
{
value3.bondSeconds += num2;
_householdsDirty = true;
}
}
}
}
private void ServerTick_ProximityFamily()
{
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
List<ZNetPeer> peers = ZNet.instance.GetPeers();
if (peers == null || peers.Count == 0)
{
return;
}
float num = Mathf.Max(1f, _rangeMeters.Value);
float num2 = num * num;
int num3 = MaxTierClamped();
for (int i = 0; i < peers.Count; i++)
{
ZNetPeer val = peers[i];
if (val == null || val.m_uid == 0L)
{
continue;
}
long uid = val.m_uid;
if (TryGetPeerAlive(val, out var alive) && !alive)
{
continue;
}
if (!UidToHousehold.TryGetValue(uid, out var value) || string.IsNullOrEmpty(value) || !Households.TryGetValue(value, out var value2))
{
MaybeSendTier(uid, 0, 0f);
continue;
}
int num4 = 0;
float num5 = 0f;
if (value2.members.TryGetValue(uid, out var value3))
{
num4 = Mathf.Clamp(GetTierFromBondSeconds(value3.bondSeconds), 0, num3);
num5 = (float)(value3.bondSeconds / 1800.0);
}
if (num4 <= 0)
{
MaybeSendTier(uid, 0, 0f);
continue;
}
if (value2.members.Count <= 1 && _debugSoloFamily.Contains(uid))
{
MaybeSendTier(uid, num4, num5);
continue;
}
if (!TryGetPeerPosition(val, out var pos))
{
MaybeSendTier(uid, 0, 0f);
continue;
}
bool flag = false;
foreach (KeyValuePair<long, Member> member in value2.members)
{
long key = member.Key;
if (key == uid)
{
continue;
}
ZNetPeer peer = ZNet.instance.GetPeer(key);
if (peer != null && peer.m_uid != 0L && (!TryGetPeerAlive(peer, out var alive2) || alive2) && TryGetPeerPosition(peer, out var pos2))
{
Vector3 val2 = pos - pos2;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
if (sqrMagnitude <= num2)
{
flag = true;
break;
}
}
}
MaybeSendTier(uid, flag ? num4 : 0, flag ? num5 : 0f);
}
}
private void MaybeSendTier(long uid, int tier, float bondDays)
{
if (!_lastSentTier.TryGetValue(uid, out var value))
{
value = -999;
}
bool flag = value != tier;
if (flag)
{
bool flag2 = value <= 0 && tier > 0;
_lastSentTier[uid] = tier;
Server_ToClientFamily(uid, tier);
if (tier <= 0)
{
_lastSentProgressRealtime.Remove(uid);
Server_ToClientFamilyProgress(uid, 0, 0f);
}
if (flag2 && _enableEnterVfx.Value)
{
Server_ToClientPlayVfx(uid, _enterVfxItemPrefab.Value ?? "MeadHasty");
}
if (_diagnosticsVerbose.Value && (Object)(object)_self != (Object)null)
{
((BaseUnityPlugin)_self).Logger.LogInfo((object)string.Format("[{0}] set-family uid={1} tier={2} entering={3}", "Marriage", uid, tier, flag2));
}
}
if (tier > 0)
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
float num = Mathf.Clamp(_progressSendIntervalSeconds.Value, 1f, 60f);
if (!_lastSentProgressRealtime.TryGetValue(uid, out var value2) || realtimeSinceStartup - value2 >= num || flag)
{
_lastSentProgressRealtime[uid] = realtimeSinceStartup;
Server_ToClientFamilyProgress(uid, tier, Mathf.Max(0f, bondDays));
}
}
}
private void ServerTick_RenotifyProposals()
{
if (Pending.Count == 0 || ZRoutedRpc.instance == null)
{
return;
}
float realtimeSinceStartup = Time.realtimeSinceStartup;
List<long> list = new List<long>(Pending.Keys);
for (int i = 0; i < list.Count; i++)
{
long num = list[i];
if (Pending.TryGetValue(num, out var value))
{
ZNetPeer peer = ZNet.instance.GetPeer(num);
if (peer != null && !(realtimeSinceStartup - value.LastNotifyTime < 5f))
{
ZRoutedRpc.instance.InvokeRoutedRPC(num, "PX_Marry_NotifyProposal", new object[2] { value.FromName, value.FromUid });
value.LastNotifyTime = realtimeSinceStartup;
Pending[num] = value;
}
}
}
}
private void ServerTick_CleanupStaleProposals()
{
if (Pending.Count == 0)
{
return;
}
List<ZNetPeer> peers = ZNet.instance.GetPeers();
HashSet<long> hashSet = new HashSet<long>();
if (peers != null)
{
for (int i = 0; i < peers.Count; i++)
{
if (peers[i] != null)
{
hashSet.Add(peers[i].m_uid);
}
}
}
List<long> list = new List<long>();
foreach (KeyValuePair<long, Proposal> item in Pending)
{
if (!hashSet.Contains(item.Key))
{
list.Add(item.Key);
}
}
for (int j = 0; j < list.Count; j++)
{
Pending.Remove(list[j]);
}
}
private static void ServerTick_CleanupDisconnectedCaches()
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
List<ZNetPeer> peers = ZNet.instance.GetPeers();
HashSet<long> hashSet = new HashSet<long>();
if (peers != null)
{
for (int i = 0; i < peers.Count; i++)
{
ZNetPeer val = peers[i];
if (val != null && val.m_uid != 0L)
{
hashSet.Add(val.m_uid);
}
}
}
List<long> list = new List<long>();
foreach (KeyValuePair<long, int> item in _lastSentTier)
{
if (!hashSet.Contains(item.Key))
{
list.Add(item.Key);
}
}
for (int j = 0; j < list.Count; j++)
{
long key = list[j];
_lastSentTier.Remove(key);
_lastSentProgressRealtime.Remove(key);
}
}
private static void Server_ToClientToast(long targetUid, string msg)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "PX_Marry_NotifyToast", new object[1] { msg });
}
}
private static void Server_ToClientFamily(long targetUid, int tier)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "PX_Family_SetTier", new object[1] { tier });
}
}
private static void Server_ToClientFamilyProgress(long targetUid, int tier, float bondDays)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "PX_Family_SetProgress", new object[2] { tier, bondDays });
}
}
private static void Server_ToClientPlayVfx(long targetUid, string itemPrefabName)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "PX_Family_PlayVfx", new object[1] { itemPrefabName ?? "" });
}
}
private static void Server_ToClientMourning(long targetUid, int tier, float durationSeconds)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "PX_Mourning_Apply", new object[2] { tier, durationSeconds });
}
}
private static bool TryGetPeerPosition(ZNetPeer peer, out Vector3 pos)
{
//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_001b: 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_002b: 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_004c: 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)
pos = Vector3.zero;
if (peer == null)
{
return false;
}
if (ZDOMan.instance == null)
{
return false;
}
try
{
ZDOID characterID = peer.m_characterID;
if (((ZDOID)(ref characterID)).Equals(default(ZDOID)))
{
return false;
}
ZDO zDO = ZDOMan.instance.GetZDO(characterID);
if (zDO == null)
{
return false;
}
pos = zDO.GetPosition();
return true;
}
catch
{
return false;
}
}
private static bool TryGetPeerAlive(ZNetPeer peer, out bool alive)
{
//IL_0013: 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_0023: 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)
alive = false;
if (peer == null)
{
return false;
}
if (ZDOMan.instance == null)
{
return false;
}
try
{
ZDOID characterID = peer.m_characterID;
if (((ZDOID)(ref characterID)).Equals(default(ZDOID)))
{
return false;
}
ZDO zDO = ZDOMan.instance.GetZDO(characterID);
if (zDO == null)
{
return false;
}
float @float = zDO.GetFloat("health", 0f);
alive = @float > 0.01f;
return true;
}
catch
{
return false;
}
}
private static void EnsureLoadedOnServer()
{
if (!_householdsLoaded)
{
LoadHouseholdsOnce();
}
}
private static void LoadHouseholdsOnce()
{
_householdsLoaded = true;
_lastWorldTimeSeconds = 0.0;
_lastSaveRealtime = Time.realtimeSinceStartup;
try
{
Households.Clear();
UidToHousehold.Clear();
_lastSentTier.Clear();
_lastSentProgressRealtime.Clear();
if (!File.Exists(_householdsPath))
{
return;
}
string[] array = File.ReadAllLines(_householdsPath);
Household household = null;
foreach (string text in array)
{
if (string.IsNullOrEmpty(text) || text.StartsWith("#"))
{
continue;
}
if (text.StartsWith("H\t"))
{
string[] array2 = text.Split(new char[1] { '\t' });
if (array2.Length >= 2)
{
string text2 = array2[1];
household = new Household
{
id = text2
};
Households[text2] = household;
}
}
else
{
if (!text.StartsWith("M\t") || household == null)
{
continue;
}
string[] array3 = text.Split(new char[1] { '\t' });
if (array3.Length >= 4 && long.TryParse(array3[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
string text3 = Unescape(array3[2]);
if (!double.TryParse(array3[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
{
result2 = 0.0;
}
Member value = new Member
{
uid = result,
name = (text3 ?? "Player"),
bondSeconds = Math.Max(0.0, result2)
};
household.members[result] = value;
UidToHousehold[result] = household.id;
}
}
}
}
catch (Exception ex)
{
MarriagePlugin self = _self;
if (self != null)
{
((BaseUnityPlugin)self).Logger.LogWarning((object)("[Marriage] Failed to load households: " + ex.Message));
}
}
}
private static void SaveHouseholdsIfDirty(bool force)
{
if (!_householdsDirty && !force)
{
return;
}
float realtimeSinceStartup = Time.realtimeSinceStartup;
float num = Mathf.Max(5f, _saveIntervalSeconds.Value);
if (!force && realtimeSinceStartup - _lastSaveRealtime < num)
{
return;
}
_lastSaveRealtime = realtimeSinceStartup;
try
{
List<string> list = new List<string> { "# pix.marriage.households.txt", "# H<TAB>householdId", "# M<TAB>uid<TAB>escapedName<TAB>bondSeconds" };
foreach (KeyValuePair<string, Household> household in Households)
{
Household value = household.Value;
if (value == null)
{
continue;
}
list.Add("H\t" + value.id);
foreach (KeyValuePair<long, Member> member in value.members)
{
Member value2 = member.Value;
if (value2 != null)
{
list.Add("M\t" + value2.uid.ToString(CultureInfo.InvariantCulture) + "\t" + Escape(value2.name ?? "Player") + "\t" + value2.bondSeconds.ToString("R", CultureInfo.InvariantCulture));
}
}
}
string text = _householdsPath + ".tmp";
File.WriteAllLines(text, list.ToArray());
File.Copy(text, _householdsPath, overwrite: true);
File.Delete(text);
_householdsDirty = false;
}
catch (Exception ex)
{
MarriagePlugin self = _self;
if (self != null)
{
((BaseUnityPlugin)self).Logger.LogWarning((object)("[Marriage] Failed to save households: " + ex.Message));
}
}
}
private static string Escape(string s)
{
try
{
return Uri.EscapeDataString(s ?? "");
}
catch
{
return "";
}
}
private static string Unescape(string s)
{
try
{
return Uri.UnescapeDataString(s ?? "");
}
catch
{
return s ?? "";
}
}
private static void TryRegisterStatusEffects(ObjectDB odb)
{
if (!((Object)(object)odb == (Object)null) && odb.m_StatusEffects != null)
{
TryLoadIconsOnce();
int num = MaxTierClamped();
if (FamilySeNames == null || FamilySeNames.Length != num || MourningSeNames == null || MourningSeNames.Length != num)
{
BuildSeArrays();
}
for (int i = 1; i <= num; i++)
{
EnsureFamilySe(odb, i);
EnsureMourningSe(odb, i);
}
Client_RefreshAllFamilyTooltips(_clientFamilyBondDays);
}
}
private static void EnsureFamilySe(ObjectDB odb, int tier)
{
//IL_00a8: 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)
int num = MaxTierClamped();
if (tier < 1 || tier > num)
{
return;
}
string name = FamilySeNames[tier - 1];
int hash = _familySeHashes[tier - 1];
StatusEffect val = FindStatusEffectByNameOrHash(odb, name, hash);
if ((Object)(object)val != (Object)null)
{
if ((Object)(object)_familyIcon != (Object)null)
{
val.m_icon = _familyIcon;
}
return;
}
float tierBonus = GetTierBonus(tier);
SE_Stats val2 = ScriptableObject.CreateInstance<SE_Stats>();
((Object)val2).name = name;
((StatusEffect)val2).m_name = $"Family (Tier {tier})";
((StatusEffect)val2).m_tooltip = BuildFamilyTooltip(tier, tierBonus, 0f);
((StatusEffect)val2).m_icon = _familyIcon ?? GetFallbackIcon();
((StatusEffect)val2).m_startMessageType = (MessageType)1;
((StatusEffect)val2).m_startMessage = "";
((StatusEffect)val2).m_stopMessageType = (MessageType)1;
((StatusEffect)val2).m_stopMessage = "";
ApplyFamilyStats(val2, tierBonus);
odb.m_StatusEffects.Add((StatusEffect)(object)val2);
}
private static void EnsureMourningSe(ObjectDB odb, int tier)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
int num = MaxTierClamped();
if (tier < 1 || tier > num)
{
return;
}
string name = MourningSeNames[tier - 1];
int hash = _mourningSeHashes[tier - 1];
StatusEffect val = FindStatusEffectByNameOrHash(odb, name, hash);
if ((Object)(object)val != (Object)null)
{
if ((Object)(object)_mourningIcon != (Object)null)
{
val.m_icon = _mourningIcon;
}
return;
}
float mourningPenalty = GetMourningPenalty(tier);
SE_Stats val2 = ScriptableObject.CreateInstance<SE_Stats>();
((Object)val2).name = name;
((StatusEffect)val2).m_name = "Mourning";
((StatusEffect)val2).m_tooltip = BuildMourningTooltip(tier, mourningPenalty);
((StatusEffect)val2).m_icon = _mourningIcon ?? GetFallbackIcon();
((StatusEffect)val2).m_startMessageType = (MessageType)1;
((StatusEffect)val2).m_startMessage = "";
((StatusEffect)val2).m_stopMessageType = (MessageType)1;
((StatusEffect)val2).m_stopMessage = "";
ApplyMourningStats(val2, mourningPenalty);
odb.m_StatusEffects.Add((StatusEffect)(object)val2);
}
private static StatusEffect FindStatusEffectByNameOrHash(ObjectDB odb, string name, int hash)
{
try
{
List<StatusEffect> statusEffects = odb.m_StatusEffects;
for (int i = 0; i < statusEffects.Count; i++)
{
StatusEffect val = statusEffects[i];
if (!((Object)(object)val == (Object)null))
{
if (!string.IsNullOrEmpty(((Object)val).name) && string.Equals(((Object)val).name, name, StringComparison.Ordinal))
{
return val;
}
if (!string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.GetStableHashCode() == hash)
{
return val;
}
}
}
}
catch
{
}
return null;
}
private static string BuildFamilyTooltip(int tier, float bonus, float bondDays)
{
int num = Mathf.RoundToInt(bonus * 100f);
List<string> list = new List<string>();
if (_buffMove.Value)
{
list.Add($"+{num}% move speed");
}
if (_buffDamage.Value)
{
list.Add($"+{num}% damage");
}
if (_buffStaminaRegen.Value)
{
list.Add($"+{num}% stamina regen");
}
if (_buffHealthRegen.Value)
{
list.Add($"+{num}% health regen");
}
if (_buffEitrRegen.Value)
{
list.Add($"+{num}% eitr regen");
}
if (list.Count == 0)
{
list.Add("No bonuses enabled (check config).");
}
string text = string.Format("Being near your Household grants bonuses.\nTier {0}: {1}", tier, string.Join(", ", list));
if (!_familyProgressInTooltip.Value)
{
return text;
}
string text2 = BuildTierProgressLine(tier, bondDays);
if (!string.IsNullOrEmpty(text2))
{
return text + "\n" + text2;
}
return text;
}
private static string BuildTierProgressLine(int tier, float bondDays)
{
int num = MaxTierClamped();
if (tier <= 0)
{
return "";
}
if (tier >= num)
{
return $"Tier {num}: MAX ({bondDays:0.0} days)";
}
float tierThresholdDays = GetTierThresholdDays(tier);
float tierThresholdDays2 = GetTierThresholdDays(tier + 1);
float num2 = Mathf.Max(0.0001f, tierThresholdDays2 - tierThresholdDays);
float num3 = Mathf.Clamp(bondDays - tierThresholdDays, 0f, num2);
float num4 = num3 / num2 * 100f;
return $"Tier {tier}: {num4:0}% ({num3:0.0} / {num2:0.0} days)";
}
private static string BuildMourningTooltip(int tier, float penalty)
{
int num = Mathf.RoundToInt(penalty * 100f);
float value = _mourningCarryWeightPenalty.Value;
List<string> list = new List<string>
{
$"-{num}% move speed",
$"-{num}% damage",
$"-{num}% stamina regen",
$"-{num}% health regen",
$"-{num}% eitr regen"
};
if (Mathf.Abs(value) > 0.01f)
{
list.Add($"{value:0} carry weight");
}
return string.Format("A Household member has died.\nTier {0}: {1}", tier, string.Join(", ", list));
}
private static void ApplyFamilyStats(SE_Stats se, float bonus)
{
try
{
if (_buffMove.Value)
{
SetFieldIfExists(se, "m_speedModifier", bonus);
}
else
{
SetFieldIfExists(se, "m_speedModifier", 0f);
}
if (_buffDamage.Value)
{
SetFieldIfExists(se, "m_damageModifier", bonus);
}
else
{
SetFieldIfExists(se, "m_damageModifier", 0f);
}
if (_buffStaminaRegen.Value)
{
SetFieldIfExists(se, "m_staminaRegenMultiplier", 1f + bonus);
}
else
{
SetFieldIfExists(se, "m_staminaRegenMultiplier", 1f);
}
if (_buffHealthRegen.Value)
{
SetFieldIfExists(se, "m_healthRegenMultiplier", 1f + bonus);
}
else
{
SetFieldIfExists(se, "m_healthRegenMultiplier", 1f);
}
if (_buffEitrRegen.Value)
{
SetFieldIfExists(se, "m_eitrRegenMultiplier", 1f + bonus);
}
else
{
SetFieldIfExists(se, "m_eitrRegenMultiplier", 1f);
}
}
catch
{
}
}
private static void ApplyMourningStats(SE_Stats se, float penalty)
{
try
{
SetFieldIfExists(se, "m_speedModifier", 0f - penalty);
SetFieldIfExists(se, "m_damageModifier", 0f - penalty);
float num = Mathf.Clamp(1f - penalty, 0.05f, 10f);
SetFieldIfExists(se, "m_staminaRegenMultiplier", num);
SetFieldIfExists(se, "m_healthRegenMultiplier", num);
SetFieldIfExists(se, "m_eitrRegenMultiplier", num);
float value = _mourningCarryWeightPenalty.Value;
SetFieldIfExists(se, "m_addMaxCarryWeight", value);
}
catch
{
}
}
private static void SetFieldIfExists(object obj, string fieldName, object value)
{
if (obj == null)
{
return;
}
try
{
Type type = obj.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (!(field == null))
{
if (value != null && field.FieldType.IsAssignableFrom(value.GetType()))
{
field.SetValue(obj, value);
}
else if (field.FieldType == typeof(float) && value is double num)
{
field.SetValue(obj, (float)num);
}
else if (field.FieldType == typeof(float) && value is int num2)
{
field.SetValue(obj, (float)num2);
}
else if (field.FieldType == typeof(int) && value is float num3)
{
field.SetValue(obj, (int)num3);
}
else if (field.FieldType == typeof(int) && value is double)
{
double num4 = (double)value;
field.SetValue(obj, (int)num4);
}
}
}
catch
{
}
}
private static void Client_RefreshAllFamilyTooltips(float bondDays)
{
if (!((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.m_StatusEffects != null)
{
int num = MaxTierClamped();
for (int i = 1; i <= num; i++)
{
Client_RefreshFamilyTooltipForTier(i, bondDays);
}
}
}
private static void Client_RefreshFamilyTooltipForTier(int tier, float bondDays)
{
int num = MaxTierClamped();
if (tier >= 1 && tier <= num && !((Object)(object)ObjectDB.instance == (Object)null))
{
StatusEffect val = FindStatusEffectByNameOrHash(ObjectDB.instance, FamilySeNames[tier - 1], _familySeHashes[tier - 1]);
if (!((Object)(object)val == (Object)null))
{
float tierBonus = GetTierBonus(tier);
val.m_tooltip = BuildFamilyTooltip(tier, tierBonus, bondDays);
}
}
}
private static Sprite GetFallbackIcon()
{
try
{
ObjectDB instance = ObjectDB.instance;
if ((Object)(object)instance != (Object)null && instance.m_StatusEffects != null)
{
for (int i = 0; i < instance.m_StatusEffects.Count; i++)
{
StatusEffect val = instance.m_StatusEffects[i];
if ((Object)(object)val != (Object)null && (Object)(object)val.m_icon != (Object)null)
{
return val.m_icon;
}
}
}
}
catch
{
}
return null;
}
private static void TryLoadIconsOnce()
{
if (_iconsTried)
{
return;
}
_iconsTried = true;
try
{
string text = "";
try
{
text = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
catch
{
}
if (!string.IsNullOrEmpty(text))
{
string path = Path.Combine(text, "family.png");
string path2 = Path.Combine(text, "mourning.png");
_familyIcon = LoadSpriteFromPngPath(path);
_mourningIcon = LoadSpriteFromPngPath(path2);
}
if ((Object)(object)_familyIcon == (Object)null)
{
_familyIcon = GetFallbackIcon();
}
if ((Object)(object)_mourningIcon == (Object)null)
{
_mourningIcon = GetFallbackIcon();
}
}
catch
{
}
}
private static void EnsurePngLoader()
{
if (_pngLoaderTried)
{
return;
}
_pngLoaderTried = true;
try
{
Type typeFromHandle = typeof(Texture2D);
_miTexture2D_LoadImage_Bytes = typeFromHandle.GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(byte[]) }, null);
_miTexture2D_LoadImage_BytesBool = typeFromHandle.GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
{
typeof(byte[]),
typeof(bool)
}, null);
Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: false) ?? Type.GetType("UnityEngine.ImageConversion, UnityEngine", throwOnError: false);
if (type != null)
{
_miImageConversion_LoadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
{
typeof(Texture2D),
typeof(byte[]),
typeof(bool)
}, null);
}
}
catch
{
}
}
private static bool TryLoadPngIntoTexture(Texture2D tex, byte[] data)
{
if ((Object)(object)tex == (Object)null || data == null || data.Length < 8)
{
return false;
}
EnsurePngLoader();
try
{
if (_miTexture2D_LoadImage_BytesBool != null)
{
if (_miTexture2D_LoadImage_BytesBool.Invoke(tex, new object[2] { data, true }) is bool result)
{
return result;
}
return true;
}
if (_miTexture2D_LoadImage_Bytes != null)
{
if (_miTexture2D_LoadImage_Bytes.Invoke(tex, new object[1] { data }) is bool result2)
{
return result2;
}
return true;
}
if (_miImageConversion_LoadImage != null)
{
if (_miImageConversion_LoadImage.Invoke(null, new object[3] { tex, data, true }) is bool result3)
{
return result3;
}
return true;
}
}
catch
{
}
return false;
}
private static Sprite LoadSpriteFromPngPath(string path)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_006d: 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)
try
{
if (string.IsNullOrEmpty(path))
{
return null;
}
if (!File.Exists(path))
{
return null;
}
byte[] array = File.ReadAllBytes(path);
if (array == null || array.Length < 8)
{
return null;
}
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
if (!TryLoadPngIntoTexture(val, array))
{
return null;
}
((Texture)val).wrapMode = (TextureWrapMode)1;
((Texture)val).filterMode = (FilterMode)1;
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
}
catch
{
return null;
}
}
private static ZNetPeer FindPeerByNameSmart(string input)
{
input = NormalizePlayerNameInput(input);
if (string.IsNullOrEmpty(input))
{
return null;
}
List<ZNetPeer> list = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetPeers() : null);
if (list == null)
{
return null;
}
for (int i = 0; i < list.Count; i++)
{
ZNetPeer val = list[i];
if (val != null && string.Equals(val.m_playerName ?? "", input, StringComparison.OrdinalIgnoreCase))
{
return val;
}
}
for (int j = 0; j < list.Count; j++)
{
ZNetPeer val2 = list[j];
if (val2 != null)
{
string text = val2.m_playerName ?? "";
if (text.StartsWith(input, StringComparison.OrdinalIgnoreCase))
{
return val2;
}
}
}
ZNetPeer val3 = null;
for (int k = 0; k < list.Count; k++)
{
ZNetPeer val4 = list[k];
if (val4 == null)
{
continue;
}
string text2 = val4.m_playerName ?? "";
if (text2.IndexOf(input, StringComparison.OrdinalIgnoreCase) >= 0)
{
if (val3 != null)
{
return null;
}
val3 = val4;
}
}
return val3;
}
private static string NormalizePlayerNameInput(string s)
{
if (string.IsNullOrEmpty(s))
{
return "";
}
s = s.Trim();
while (s.Contains(" "))
{
s = s.Replace(" ", " ");
}
return s;
}
}
internal static class StableHashExtensions
{
public static int GetStableHashCode(this string str)
{
if (str == null)
{
return 0;
}
int num = 5381;
int num2 = num;
for (int i = 0; i < str.Length && str[i] != 0; i += 2)
{
num = ((num << 5) + num) ^ str[i];
if (i == str.Length - 1 || str[i + 1] == '\0')
{
break;
}
num2 = ((num2 << 5) + num2) ^ str[i + 1];
}
return num + num2 * 1566083941;
}
}