using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[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: AssemblyCompany("UnknOwnUtilities")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UnknOwnUtilities")]
[assembly: AssemblyTitle("UnknOwnUtilities")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 UnknOwnUtilities
{
public enum ProtectionMode
{
HostOnly,
EveryoneAlwaysOn,
OnKeypress
}
public static class ModConfig
{
public static ConfigEntry<bool> EnableSacrifice;
public static ConfigEntry<float> MoneyPercentPerPart;
public static ConfigEntry<int> TicketsPerPart;
public static ConfigEntry<KeyCode> SacrificeKey;
public static ConfigEntry<bool> EnableProtection;
public static ConfigEntry<ProtectionMode> ProtectionBehavior;
public static ConfigEntry<KeyCode> ProtectionKey;
public static void Initialize(BaseUnityPlugin plugin)
{
EnableSacrifice = plugin.Config.Bind<bool>("Sacrifice", "Enabled", true, "Enable organ sacrifice with a Bat.");
MoneyPercentPerPart = plugin.Config.Bind<float>("Sacrifice", "MoneyPercentPerPart", 15f, "Percentage of the current quota awarded per sacrificed organ.");
TicketsPerPart = plugin.Config.Bind<int>("Sacrifice", "TicketsPerPart", 5, "Tickets awarded per sacrificed organ.");
SacrificeKey = plugin.Config.Bind<KeyCode>("Sacrifice", "TriggerKey", (KeyCode)306, "Key held while hitting another player with a Bat.");
EnableProtection = plugin.Config.Bind<bool>("Protection", "Enabled", true, "Enable Bat protection.");
ProtectionBehavior = plugin.Config.Bind<ProtectionMode>("Protection", "Mode", ProtectionMode.OnKeypress, "HostOnly, EveryoneAlwaysOn, or OnKeypress.");
ProtectionKey = plugin.Config.Bind<KeyCode>("Protection", "TriggerKey", (KeyCode)324, "Key held for protection in OnKeypress mode.");
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct ConfigRequestMessage : NetworkMessage
{
}
public struct ConfigSyncMessage : NetworkMessage
{
public bool enableSacrifice;
public float moneyPercentPerPart;
public int ticketsPerPart;
public int sacrificeKey;
public bool enableProtection;
public int protectionMode;
public int protectionKey;
}
public static class RuntimeConfig
{
private static bool _initialized;
private static bool _requestSent;
private static bool _hasHostConfig;
public static bool EnableSacrifice { get; private set; } = true;
public static float MoneyPercentPerPart { get; private set; } = 15f;
public static int TicketsPerPart { get; private set; } = 5;
public static KeyCode SacrificeKey { get; private set; } = (KeyCode)306;
public static bool EnableProtection { get; private set; } = true;
public static ProtectionMode ProtectionBehavior { get; private set; } = ProtectionMode.OnKeypress;
public static KeyCode ProtectionKey { get; private set; } = (KeyCode)324;
public static bool HasHostConfig
{
get
{
if (!NetworkServer.active)
{
return _hasHostConfig;
}
return true;
}
}
public static void Initialize()
{
if (!_initialized)
{
_initialized = true;
Writer<ConfigRequestMessage>.write = delegate
{
};
Reader<ConfigRequestMessage>.read = (NetworkReader reader) => default(ConfigRequestMessage);
Writer<ConfigSyncMessage>.write = delegate(NetworkWriter writer, ConfigSyncMessage message)
{
NetworkWriterExtensions.WriteBool(writer, message.enableSacrifice);
NetworkWriterExtensions.WriteFloat(writer, message.moneyPercentPerPart);
NetworkWriterExtensions.WriteInt(writer, message.ticketsPerPart);
NetworkWriterExtensions.WriteInt(writer, message.sacrificeKey);
NetworkWriterExtensions.WriteBool(writer, message.enableProtection);
NetworkWriterExtensions.WriteInt(writer, message.protectionMode);
NetworkWriterExtensions.WriteInt(writer, message.protectionKey);
};
Reader<ConfigSyncMessage>.read = (NetworkReader reader) => new ConfigSyncMessage
{
enableSacrifice = NetworkReaderExtensions.ReadBool(reader),
moneyPercentPerPart = NetworkReaderExtensions.ReadFloat(reader),
ticketsPerPart = NetworkReaderExtensions.ReadInt(reader),
sacrificeKey = NetworkReaderExtensions.ReadInt(reader),
enableProtection = NetworkReaderExtensions.ReadBool(reader),
protectionMode = NetworkReaderExtensions.ReadInt(reader),
protectionKey = NetworkReaderExtensions.ReadInt(reader)
};
NetworkServer.RegisterHandler<ConfigRequestMessage>((Action<NetworkConnectionToClient, ConfigRequestMessage>)HandleConfigRequest, false);
NetworkClient.RegisterHandler<ConfigSyncMessage>((Action<ConfigSyncMessage>)ReceiveHostConfig, false);
LoadLocalConfig();
}
}
private static void LoadLocalConfig()
{
//IL_0047: 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)
EnableSacrifice = ModConfig.EnableSacrifice.Value;
MoneyPercentPerPart = Mathf.Clamp(ModConfig.MoneyPercentPerPart.Value, 0f, 100f);
TicketsPerPart = Mathf.Max(0, ModConfig.TicketsPerPart.Value);
SacrificeKey = ModConfig.SacrificeKey.Value;
EnableProtection = ModConfig.EnableProtection.Value;
ProtectionBehavior = ModConfig.ProtectionBehavior.Value;
ProtectionKey = ModConfig.ProtectionKey.Value;
}
public static void Tick()
{
if (NetworkServer.active)
{
LoadLocalConfig();
_hasHostConfig = true;
_requestSent = false;
}
else if (!NetworkClient.active || !NetworkClient.isConnected)
{
_requestSent = false;
_hasHostConfig = false;
}
else if (!_requestSent)
{
_requestSent = true;
_hasHostConfig = false;
NetworkClient.Send<ConfigRequestMessage>(default(ConfigRequestMessage), 0);
}
}
private static void HandleConfigRequest(NetworkConnectionToClient sender, ConfigRequestMessage message)
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Expected I4, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected I4, but got Unknown
if (NetworkServer.active && sender != null && ((NetworkConnection)sender).isAuthenticated)
{
LoadLocalConfig();
((NetworkConnection)sender).Send<ConfigSyncMessage>(new ConfigSyncMessage
{
enableSacrifice = EnableSacrifice,
moneyPercentPerPart = MoneyPercentPerPart,
ticketsPerPart = TicketsPerPart,
sacrificeKey = (int)SacrificeKey,
enableProtection = EnableProtection,
protectionMode = (int)ProtectionBehavior,
protectionKey = (int)ProtectionKey
}, 0);
}
}
private static void ReceiveHostConfig(ConfigSyncMessage message)
{
EnableSacrifice = message.enableSacrifice;
MoneyPercentPerPart = Mathf.Clamp(message.moneyPercentPerPart, 0f, 100f);
TicketsPerPart = Mathf.Max(0, message.ticketsPerPart);
SacrificeKey = (KeyCode)message.sacrificeKey;
EnableProtection = message.enableProtection;
ProtectionBehavior = (ProtectionMode)Mathf.Clamp(message.protectionMode, 0, 2);
ProtectionKey = (KeyCode)message.protectionKey;
_hasHostConfig = true;
if (UnknOwnUtilities.Log != null)
{
UnknOwnUtilities.Log.LogInfo((object)"Received authoritative settings from the host.");
}
}
public static bool IsPlayerProtected(PlayerController player, bool keypressProtected)
{
if ((Object)(object)player == (Object)null || !EnableProtection)
{
return false;
}
switch (ProtectionBehavior)
{
case ProtectionMode.HostOnly:
if (NetworkServer.active)
{
return ((NetworkBehaviour)player).isLocalPlayer;
}
return false;
case ProtectionMode.EveryoneAlwaysOn:
return true;
case ProtectionMode.OnKeypress:
return keypressProtected;
default:
return false;
}
}
}
[BepInPlugin("com.unknownlv.unknownutilities", "UnknOwn Utilities", "1.0.1")]
public class UnknOwnUtilities : BaseUnityPlugin
{
internal static ManualLogSource Log;
private Harmony _harmony;
private bool _serverHandlersRegistered;
private void Awake()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ModConfig.Initialize((BaseUnityPlugin)(object)this);
RuntimeConfig.Initialize();
_harmony = new Harmony("com.unknownlv.unknownutilities");
_harmony.PatchAll(typeof(BatPatches));
_harmony.PatchAll(typeof(KnockbackPatches));
_harmony.PatchAll(typeof(OrganProtectionPatches));
RegisterMirrorMessageTypes();
NetworkServer.OnDisconnectedEvent = (Action<NetworkConnectionToClient>)Delegate.Combine(NetworkServer.OnDisconnectedEvent, new Action<NetworkConnectionToClient>(OnServerDisconnected));
((BaseUnityPlugin)this).Logger.LogInfo((object)"UnknOwn Utilities loaded.");
}
private static void RegisterMirrorMessageTypes()
{
Writer<OrganHitMessage>.write = delegate(NetworkWriter writer, OrganHitMessage msg)
{
NetworkWriterExtensions.WriteUInt(writer, msg.victimNetId);
};
Reader<OrganHitMessage>.read = (NetworkReader reader) => new OrganHitMessage
{
victimNetId = NetworkReaderExtensions.ReadUInt(reader)
};
Writer<ProtectionStateMessage>.write = delegate(NetworkWriter writer, ProtectionStateMessage msg)
{
NetworkWriterExtensions.WriteBool(writer, msg.isProtected);
};
Reader<ProtectionStateMessage>.read = (NetworkReader reader) => new ProtectionStateMessage
{
isProtected = NetworkReaderExtensions.ReadBool(reader)
};
Log.LogInfo((object)"Custom Mirror serializers registered.");
}
private void Update()
{
try
{
RuntimeConfig.Tick();
if (NetworkServer.active)
{
if (!_serverHandlersRegistered)
{
NetworkServer.RegisterHandler<OrganHitMessage>((Action<NetworkConnectionToClient, OrganHitMessage>)BatPatches.ServerHandleOrganHit, true);
NetworkServer.RegisterHandler<ProtectionStateMessage>((Action<NetworkConnectionToClient, ProtectionStateMessage>)ServerProtection.HandleProtectionState, true);
_serverHandlersRegistered = true;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom Mirror server handlers registered.");
}
}
else
{
_serverHandlersRegistered = false;
}
UpdateProtectionState();
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogError((object)$"Update failed: {arg}");
}
}
private static void UpdateProtectionState()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!NetworkClient.active || !NetworkClient.isConnected)
{
ServerProtection.LocalLastSentState = false;
}
else if (RuntimeConfig.HasHostConfig)
{
bool flag = RuntimeConfig.EnableProtection && RuntimeConfig.ProtectionBehavior == ProtectionMode.OnKeypress && IsConfiguredKeyHeld(RuntimeConfig.ProtectionKey);
if (flag != ServerProtection.LocalLastSentState)
{
NetworkClient.Send<ProtectionStateMessage>(new ProtectionStateMessage
{
isProtected = flag
}, 0);
ServerProtection.LocalLastSentState = flag;
Log.LogInfo((object)$"Sent protection state to server: {flag}");
}
}
}
catch (Exception ex)
{
if (Log != null)
{
Log.LogWarning((object)("Could not update protection state: " + ex.Message));
}
}
}
internal static bool IsConfiguredKeyHeld(KeyCode key)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected I4, but got Unknown
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Invalid comparison between Unknown and I4
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Invalid comparison between Unknown and I4
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Invalid comparison between Unknown and I4
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Expected I4, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Invalid comparison between Unknown and I4
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Invalid comparison between Unknown and I4
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Invalid comparison between Unknown and I4
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Expected I4, but got Unknown
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Expected I4, but got Unknown
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Invalid comparison between Unknown and I4
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Expected I4, but got Unknown
try
{
Mouse current = Mouse.current;
switch (key - 323)
{
case 0:
return current != null && current.leftButton.isPressed;
case 1:
return current != null && current.rightButton.isPressed;
case 2:
return current != null && current.middleButton.isPressed;
default:
{
Keyboard current2 = Keyboard.current;
if (current2 == null)
{
return false;
}
if ((int)key <= 27)
{
if ((int)key <= 9)
{
if ((int)key == 8)
{
return ((ButtonControl)current2.backspaceKey).isPressed;
}
if ((int)key == 9)
{
return ((ButtonControl)current2.tabKey).isPressed;
}
}
else
{
if ((int)key == 13)
{
return ((ButtonControl)current2.enterKey).isPressed;
}
if ((int)key == 27)
{
return ((ButtonControl)current2.escapeKey).isPressed;
}
}
}
else if ((int)key <= 53)
{
if ((int)key == 32)
{
return ((ButtonControl)current2.spaceKey).isPressed;
}
switch (key - 49)
{
case 0:
return ((ButtonControl)current2.digit1Key).isPressed;
case 1:
return ((ButtonControl)current2.digit2Key).isPressed;
case 2:
return ((ButtonControl)current2.digit3Key).isPressed;
case 3:
return ((ButtonControl)current2.digit4Key).isPressed;
case 4:
return ((ButtonControl)current2.digit5Key).isPressed;
}
}
else
{
switch (key - 97)
{
default:
switch (key - 113)
{
default:
switch (key - 303)
{
case 3:
return ((ButtonControl)current2.leftCtrlKey).isPressed;
case 2:
return ((ButtonControl)current2.rightCtrlKey).isPressed;
case 1:
return ((ButtonControl)current2.leftShiftKey).isPressed;
case 0:
return ((ButtonControl)current2.rightShiftKey).isPressed;
case 5:
return ((ButtonControl)current2.leftAltKey).isPressed;
case 4:
return ((ButtonControl)current2.rightAltKey).isPressed;
}
break;
case 0:
return ((ButtonControl)current2.qKey).isPressed;
case 1:
return ((ButtonControl)current2.rKey).isPressed;
case 5:
return ((ButtonControl)current2.vKey).isPressed;
case 6:
return ((ButtonControl)current2.wKey).isPressed;
case 2:
return ((ButtonControl)current2.sKey).isPressed;
case 3:
case 4:
break;
}
break;
case 4:
return ((ButtonControl)current2.eKey).isPressed;
case 5:
return ((ButtonControl)current2.fKey).isPressed;
case 2:
return ((ButtonControl)current2.cKey).isPressed;
case 0:
return ((ButtonControl)current2.aKey).isPressed;
case 3:
return ((ButtonControl)current2.dKey).isPressed;
case 1:
break;
}
}
return false;
}
}
}
catch
{
return false;
}
}
private static void OnServerDisconnected(NetworkConnectionToClient conn)
{
if (conn != null)
{
ServerProtection.Clear(conn.connectionId);
}
}
private void OnGUI()
{
StatusHud.Draw();
}
private void OnDestroy()
{
NetworkServer.OnDisconnectedEvent = (Action<NetworkConnectionToClient>)Delegate.Remove(NetworkServer.OnDisconnectedEvent, new Action<NetworkConnectionToClient>(OnServerDisconnected));
if (_harmony != null)
{
_harmony.UnpatchSelf();
}
}
}
public struct OrganHitMessage : NetworkMessage
{
public uint victimNetId;
}
public struct ProtectionStateMessage : NetworkMessage
{
public bool isProtected;
}
public static class ServerProtection
{
private static readonly Dictionary<int, bool> ProtectedConnections = new Dictionary<int, bool>();
public static bool LocalLastSentState;
public static void HandleProtectionState(NetworkConnectionToClient sender, ProtectionStateMessage msg)
{
try
{
if (NetworkServer.active && sender != null && ((NetworkConnection)sender).isAuthenticated && !((Object)(object)((NetworkConnection)sender).identity == (Object)null))
{
ProtectedConnections[sender.connectionId] = msg.isProtected;
}
}
catch (Exception arg)
{
UnknOwnUtilities.Log.LogError((object)$"HandleProtectionState failed: {arg}");
}
}
public static bool IsProtected(PlayerController player)
{
if ((Object)(object)player == (Object)null || !RuntimeConfig.EnableProtection)
{
return false;
}
bool value = false;
NetworkConnectionToClient connectionToClient = ((NetworkBehaviour)player).connectionToClient;
if (connectionToClient != null)
{
ProtectedConnections.TryGetValue(connectionToClient.connectionId, out value);
}
return RuntimeConfig.IsPlayerProtected(player, value);
}
public static void Clear(int connectionId)
{
ProtectedConnections.Remove(connectionId);
BatPatches.ClearConnectionCooldowns(connectionId);
}
}
public static class BatPatches
{
private const float LocalOrganHitCooldown = 0.3f;
private const float ServerOrganHitCooldown = 0.3f;
private static readonly Dictionary<uint, float> LastOrganHitTime = new Dictionary<uint, float>();
private static readonly Dictionary<string, float> ServerLastOrganHitTime = new Dictionary<string, float>();
internal static void ClearConnectionCooldowns(int connectionId)
{
string value = connectionId + ":";
List<string> list = new List<string>();
foreach (string key in ServerLastOrganHitTime.Keys)
{
if (key.StartsWith(value, StringComparison.Ordinal))
{
list.Add(key);
}
}
foreach (string item in list)
{
ServerLastOrganHitTime.Remove(item);
}
}
private static bool IsLocalCtrlHeld()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
return UnknOwnUtilities.IsConfiguredKeyHeld(RuntimeConfig.SacrificeKey);
}
[HarmonyPatch(typeof(Bat), "OnTriggerEnter")]
[HarmonyPrefix]
private static void Pre_OnTriggerEnter(Bat __instance, Collider hit)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Invalid comparison between Unknown and I4
try
{
if (!RuntimeConfig.EnableSacrifice || (Object)(object)__instance == (Object)null || (Object)(object)((Item)__instance).NetworkHolder == (Object)null || !((NetworkBehaviour)((Item)__instance).NetworkHolder).isLocalPlayer || (Object)(object)hit == (Object)null || hit.isTrigger)
{
return;
}
GameManager instance = NetworkSingleton<GameManager>.Instance;
if ((Object)(object)instance == (Object)null || (int)instance.state != 1 || !IsLocalCtrlHeld() || (Object)(object)hit.attachedRigidbody == (Object)null)
{
return;
}
PlayerController component = ((Component)hit.attachedRigidbody).GetComponent<PlayerController>();
if (!((Object)(object)component == (Object)null) && ((NetworkBehaviour)component).netId != ((NetworkBehaviour)((Item)__instance).NetworkHolder).netId && NetworkClient.active && NetworkClient.isConnected)
{
float time = Time.time;
if (!LastOrganHitTime.TryGetValue(((NetworkBehaviour)component).netId, out var value) || !(time - value < 0.3f))
{
LastOrganHitTime[((NetworkBehaviour)component).netId] = time;
NetworkClient.Send<OrganHitMessage>(new OrganHitMessage
{
victimNetId = ((NetworkBehaviour)component).netId
}, 0);
UnknOwnUtilities.Log.LogInfo((object)$"Sacrifice key + bat hit detected on player {((NetworkBehaviour)component).netId}.");
}
}
}
catch (Exception arg)
{
UnknOwnUtilities.Log.LogError((object)$"Pre_OnTriggerEnter failed: {arg}");
}
}
public static void ServerHandleOrganHit(NetworkConnectionToClient sender, OrganHitMessage msg)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Invalid comparison between Unknown and I4
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0262: Unknown result type (might be due to invalid IL or missing references)
//IL_0267: Unknown result type (might be due to invalid IL or missing references)
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!NetworkServer.active || !RuntimeConfig.EnableSacrifice || sender == null || !((NetworkConnection)sender).isAuthenticated || (Object)(object)((NetworkConnection)sender).identity == (Object)null)
{
return;
}
GameManager instance = NetworkSingleton<GameManager>.Instance;
MoneyManager instance2 = NetworkSingleton<MoneyManager>.Instance;
OrganManager instance3 = NetworkSingleton<OrganManager>.Instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance3 == (Object)null || (int)instance.state != 1 || instance2.balance >= instance.currentQuota || !NetworkServer.spawned.TryGetValue(msg.victimNetId, out var value) || (Object)(object)value == (Object)null)
{
return;
}
PlayerController component = ((Component)value).GetComponent<PlayerController>();
if ((Object)(object)component == (Object)null || ((NetworkBehaviour)component).connectionToClient == null)
{
return;
}
NetworkIdentity identity = ((NetworkConnection)sender).identity;
PlayerController component2 = ((Component)identity).GetComponent<PlayerController>();
if ((Object)(object)component2 == (Object)null || ((NetworkBehaviour)component2).netId == ((NetworkBehaviour)component).netId)
{
return;
}
PlayerInventory component3 = ((Component)identity).GetComponent<PlayerInventory>();
if ((Object)(object)component3 == (Object)null || !(component3.NetworkholdingItem is Bat))
{
return;
}
int connectionId = sender.connectionId;
string key = connectionId + ":" + ((NetworkBehaviour)component).netId;
float time = Time.time;
if (ServerLastOrganHitTime.TryGetValue(key, out var value2) && time - value2 < 0.3f)
{
return;
}
ServerLastOrganHitTime[key] = time;
if (ServerProtection.IsProtected(component))
{
UnknOwnUtilities.Log.LogInfo((object)$"Organ removal blocked: player {((NetworkBehaviour)component).netId} is protected.");
return;
}
PlayerOrgans component4 = ((Component)component).GetComponent<PlayerOrgans>();
if ((Object)(object)component4 == (Object)null)
{
return;
}
PlayerOrganData organData = instance3.GetOrganData(component4);
if (organData != null)
{
List<OrganType> list = new List<OrganType>();
if (organData.body)
{
list.Add((OrganType)2);
}
if (organData.mouth)
{
list.Add((OrganType)3);
}
if (organData.leftEye && organData.rightEye)
{
list.Add((OrganType)(!(Random.value > 0.5f)));
}
if (list.Count == 0)
{
UnknOwnUtilities.Log.LogInfo((object)$"No removable organs remain on player {((NetworkBehaviour)component).netId}.");
return;
}
OrganType val = list[Random.Range(0, list.Count)];
instance3.ServerToggleOrgan(component4, val, false);
UnknOwnUtilities.Log.LogInfo((object)$"Removed {val} from player {((NetworkBehaviour)component).netId}.");
AwardRewards();
}
}
catch (Exception arg)
{
UnknOwnUtilities.Log.LogError((object)$"ServerHandleOrganHit failed: {arg}");
}
}
private static void AwardRewards()
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: 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_0078: Unknown result type (might be due to invalid IL or missing references)
try
{
MoneyManager instance = NetworkSingleton<MoneyManager>.Instance;
GameManager instance2 = NetworkSingleton<GameManager>.Instance;
if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null))
{
instance.TryChangeTicketBalance((long)RuntimeConfig.TicketsPerPart);
BigNumber currentQuota = instance2.currentQuota;
BigNumber val = currentQuota * (double)(RuntimeConfig.MoneyPercentPerPart / 100f);
BigNumber val2 = ((BigNumber)(ref val)).RoundByFirstNDigits(2);
BigNumber val3 = currentQuota - instance.balance;
if (val2 > val3)
{
val2 = val3;
}
if (val2 > BigNumber.Zero)
{
instance.TryChangeBalance(val2, (PlayerProfile)null, (ChangeType)2);
}
UnknOwnUtilities.Log.LogInfo((object)($"Awarded {RuntimeConfig.TicketsPerPart} tickets and " + $"{val2} quota progress."));
}
}
catch (Exception arg)
{
UnknOwnUtilities.Log.LogError((object)$"AwardRewards failed: {arg}");
}
}
}
public static class StatusHud
{
private class HudIndicator
{
public string Label;
public Color Background;
public Func<bool> IsActive;
}
private static readonly List<HudIndicator> Indicators = new List<HudIndicator>
{
new HudIndicator
{
Label = "D",
Background = new Color(0.15f, 0.45f, 1f, 0.9f),
IsActive = IsRightClickHeld
},
new HudIndicator
{
Label = "S",
Background = new Color(1f, 0.15f, 0.15f, 0.9f),
IsActive = IsSacrificeModeActive
}
};
private const float BoxSize = 64f;
private const float Spacing = 12f;
private const float BottomMargin = 32f;
private const int CornerRadius = 14;
private const int FontSize = 32;
private static Texture2D _whiteRounded;
private static GUIStyle _labelStyle;
public static bool IsRightClickHeld()
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (RuntimeConfig.EnableProtection && RuntimeConfig.ProtectionBehavior == ProtectionMode.OnKeypress)
{
return UnknOwnUtilities.IsConfiguredKeyHeld(RuntimeConfig.ProtectionKey);
}
return false;
}
public static bool IsCtrlHeld()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
if (RuntimeConfig.EnableSacrifice)
{
return UnknOwnUtilities.IsConfiguredKeyHeld(RuntimeConfig.SacrificeKey);
}
return false;
}
private static PlayerController GetLocalPlayer()
{
try
{
if ((Object)(object)NetworkClient.localPlayer != (Object)null)
{
PlayerController component = ((Component)NetworkClient.localPlayer).GetComponent<PlayerController>();
if ((Object)(object)component != (Object)null)
{
return component;
}
}
PlayerController[] array = Object.FindObjectsByType<PlayerController>((FindObjectsSortMode)0);
foreach (PlayerController val in array)
{
if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).isLocalPlayer)
{
return val;
}
}
}
catch (Exception ex)
{
if (UnknOwnUtilities.Log != null)
{
UnknOwnUtilities.Log.LogWarning((object)("Could not find local player for HUD: " + ex.Message));
}
}
return null;
}
public static bool IsSacrificeModeActive()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Invalid comparison between Unknown and I4
if (!IsCtrlHeld())
{
return false;
}
try
{
GameManager instance = NetworkSingleton<GameManager>.Instance;
if ((Object)(object)instance == (Object)null || (int)instance.state != 1)
{
return false;
}
PlayerController localPlayer = GetLocalPlayer();
if ((Object)(object)localPlayer == (Object)null)
{
return false;
}
PlayerInventory component = ((Component)localPlayer).GetComponent<PlayerInventory>();
return (Object)(object)component != (Object)null && component.NetworkholdingItem is Bat;
}
catch
{
return false;
}
}
private static Texture2D GetRoundedTexture()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_whiteRounded != (Object)null)
{
return _whiteRounded;
}
_whiteRounded = new Texture2D(64, 64, (TextureFormat)5, false);
((Texture)_whiteRounded).wrapMode = (TextureWrapMode)1;
float num = 14f;
float num2 = 31.5f;
float num3 = 31.5f;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < 64; j++)
{
float num4 = Mathf.Max(Mathf.Abs((float)j - num2) - (32f - num), 0f);
float num5 = Mathf.Max(Mathf.Abs((float)i - num3) - (32f - num), 0f);
float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5);
float num7 = Mathf.Clamp01(num - num6 + 0.5f);
_whiteRounded.SetPixel(j, i, new Color(1f, 1f, 1f, num7));
}
}
_whiteRounded.Apply();
return _whiteRounded;
}
private static GUIStyle GetLabelStyle()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (_labelStyle != null)
{
return _labelStyle;
}
_labelStyle = new GUIStyle(GUI.skin.label)
{
alignment = (TextAnchor)4,
fontStyle = (FontStyle)1,
fontSize = 32
};
_labelStyle.normal.textColor = Color.white;
return _labelStyle;
}
public static void Draw()
{
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
try
{
int num = 0;
foreach (HudIndicator indicator in Indicators)
{
if (indicator.IsActive())
{
num++;
}
}
if (num == 0)
{
return;
}
float num2 = (float)num * 64f + (float)(num - 1) * 12f;
float num3 = ((float)Screen.width - num2) / 2f;
float num4 = (float)Screen.height - 32f - 64f;
Texture2D roundedTexture = GetRoundedTexture();
GUIStyle labelStyle = GetLabelStyle();
float num5 = num3;
Rect val = default(Rect);
foreach (HudIndicator indicator2 in Indicators)
{
if (indicator2.IsActive())
{
((Rect)(ref val))..ctor(num5, num4, 64f, 64f);
Color color = GUI.color;
GUI.color = indicator2.Background;
GUI.DrawTexture(val, (Texture)(object)roundedTexture, (ScaleMode)0, true);
GUI.color = color;
Rect val2 = new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width, ((Rect)(ref val)).height);
labelStyle.normal.textColor = new Color(0f, 0f, 0f, 0.5f);
GUI.Label(val2, indicator2.Label, labelStyle);
labelStyle.normal.textColor = Color.white;
GUI.Label(val, indicator2.Label, labelStyle);
num5 += 76f;
}
}
}
catch (Exception ex)
{
if (UnknOwnUtilities.Log != null)
{
UnknOwnUtilities.Log.LogWarning((object)("HUD drawing failed: " + ex.Message));
}
}
}
}
public static class KnockbackPatches
{
private static bool IsLocalRightClickHeld()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
return UnknOwnUtilities.IsConfiguredKeyHeld(RuntimeConfig.ProtectionKey);
}
[HarmonyPatch(typeof(PlayerController), "ServerKnockback")]
[HarmonyPrefix]
private static bool Pre_ServerKnockback(PlayerController __instance)
{
if (NetworkServer.active && ServerProtection.IsProtected(__instance))
{
UnknOwnUtilities.Log.LogInfo((object)$"Blocked knockback on protected player {((NetworkBehaviour)__instance).netId}.");
return false;
}
return true;
}
[HarmonyPatch(typeof(PlayerController), "UserCode_TargetKnockback__NetworkConnection__Vector3__Vector3")]
[HarmonyPrefix]
private static bool Pre_TargetKnockback(PlayerController __instance)
{
if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).isLocalPlayer && RuntimeConfig.EnableProtection && RuntimeConfig.ProtectionBehavior == ProtectionMode.OnKeypress && IsLocalRightClickHeld())
{
UnknOwnUtilities.Log.LogInfo((object)"Blocked knockback: local player is protected.");
return false;
}
return true;
}
}
public static class OrganProtectionPatches
{
[HarmonyPatch(typeof(OrganManager), "ServerToggleOrgan")]
[HarmonyPrefix]
private static bool Pre_ServerToggleOrgan(PlayerOrgans organs, OrganType organType, bool isEnabled)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
if (isEnabled || !NetworkServer.active || (Object)(object)organs == (Object)null)
{
return true;
}
PlayerController component = ((Component)organs).GetComponent<PlayerController>();
if ((Object)(object)component == (Object)null || !ServerProtection.IsProtected(component))
{
return true;
}
UnknOwnUtilities.Log.LogInfo((object)$"Blocked {organType} removal from protected player {((NetworkBehaviour)component).netId}.");
return false;
}
}
}