using System; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using GTFO.API; using HarmonyLib; using Microsoft.CodeAnalysis; using OptionalNetworking.Hashing; using OptionalNetworking.Managers; using Player; using SNetwork; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("OptionalNetworkAPI")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+11d78cfdb4cea7dbfa759ea055d91fb7aa24f102")] [assembly: AssemblyProduct("OptionalNetworkAPI")] [assembly: AssemblyTitle("OptionalNetworkAPI")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace OptionalNetworking { internal interface ICustomDataManager : ICustomDataSender { void OnPlayerModRemoved(SNet_Player player); } public class CustomDataManager : CustomDataSender, ICustomDataManager, ICustomDataSender where T : unmanaged { private readonly Dictionary _data = new Dictionary(); public T this[SNet_Player player] { get { return _data[player.Lookup]; } set { SetData(player, value); } } public event Action? PreDataSet; public event Action? OnDataSet; public event Action? OnDataRemoved; private CustomDataManager(ModInfo parent, string id, Func defaultProvider) : base(parent, id, defaultProvider, SenderMode.All) { ReceiveEvent = SetData; } internal static CustomDataManager CreateDataManager(ModInfo parent, int index, Func defaultProvider) { return new CustomDataManager(parent, $"{parent.Hash:x}_{index}", defaultProvider); } public bool TryGetData(SNet_Player player, out T data) { return _data.TryGetValue(player.Lookup, out data); } private void SetData(SNet_Player player, T data) { this.PreDataSet?.Invoke(player, data); _data[player.Lookup] = data; this.OnDataSet?.Invoke(player, data); } void ICustomDataManager.OnPlayerModRemoved(SNet_Player player) { if (player.IsBot) { RemoveData(player); } } private protected override void OnPlayerLeft(SNet_Player player) { base.OnPlayerLeft(player); RemoveData(player); } public void RemoveData(SNet_Player player) { if (_data.Remove(player.Lookup, out var value)) { this.OnDataRemoved?.Invoke(player, value); } } private protected override void OnLobbyLeft() { base.OnLobbyLeft(); _data.Clear(); } } internal interface ICustomDataSender { void SendDefaultData(SNet_Player player); void OnPlayerLeft(SNet_Player player); void OnLobbyLeft(); } [Flags] public enum SenderMode { OtherPlayers = 1, Bots = 4, Self = 8, All = 0xD } public class CustomDataSender : ICustomDataSender where T : unmanaged { private struct CustomPacket { public pPlayer Player; public T Data; public CustomPacket(SNet_Player player, T data) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Player = default(pPlayer); ((pPlayer)(ref Player)).SetPlayer(player); Data = data; } } private const string EventPrefix = "OptionalData"; private static readonly byte[] s_packetBuffer = new byte[Marshal.SizeOf() + Marshal.SizeOf()]; private readonly ModInfo _parent; private readonly string _eventName; private readonly Func? _defaultProvider; private protected Action ReceiveEvent; private readonly Dictionary _sentBots = new Dictionary(); private readonly SenderMode _mode; private CustomDataSender(ModInfo parent, string id, Action receiveEvent, Func? defaultProvider, SenderMode senderMode) : this(parent, id, defaultProvider, senderMode) { ReceiveEvent = receiveEvent; } private protected CustomDataSender(ModInfo parent, string id, Func? defaultProvider, SenderMode senderMode) { _parent = parent; _eventName = "OptionalData" + id; _defaultProvider = defaultProvider; ReceiveEvent = null; _mode = senderMode; NetworkAPI.RegisterFreeSizedEvent(_eventName, (Action)ReceiveDataRaw); } internal static CustomDataSender CreateDataSender(ModInfo parent, int index, Action receiveEvent, Func? defaultProvider, SenderMode senderMode) { return new CustomDataSender(parent, $"{parent.Hash:x}_{index}", receiveEvent, defaultProvider, senderMode); } public void SendDefaultData(SNet_Player player) { if (_defaultProvider == null) { return; } if (!player.IsLocal && !player.IsBot) { if (!_mode.HasFlag(SenderMode.OtherPlayers)) { return; } SendData(SNet.LocalPlayer, _defaultProvider(SNet.LocalPlayer), player, (SNet_ChannelType)0); if (!SNet.IsMaster) { return; } { foreach (SNet_Player value in _sentBots.Values) { SendData(value, _defaultProvider(value), player, (SNet_ChannelType)0); } return; } } if (_mode.HasFlag(SenderMode.Self) && player.IsLocal) { ReceiveEvent(player, _defaultProvider(player)); } else if (_mode.HasFlag(SenderMode.Bots) && player.IsBot && SNet.IsMaster && _sentBots.TryAdd(player.Lookup, player)) { SendData(player, _defaultProvider(player), null, (SNet_ChannelType)0); } } public void SendData(T data, SNet_Player? target = null, SNet_ChannelType channelType = (SNet_ChannelType)0) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) SendData(SNet.LocalPlayer, data, target, channelType); } public void SendData(SNet_Player player, T data, SNet_Player? target = null, SNet_ChannelType channelType = (SNet_ChannelType)0) { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (!_mode.HasFlag(SenderMode.Bots) && player.IsBot) { return; } CustomPacket packet = new CustomPacket(player, data); if ((Object)(object)target == (Object)null) { if (_mode.HasFlag(SenderMode.Self) && player.IsLocal) { ReceiveEvent(player, packet.Data); } if (player.IsBot) { ReceiveEvent(player, packet.Data); } if (!_mode.HasFlag(SenderMode.OtherPlayers)) { return; } if (!player.IsLocal && !player.IsBot) { ReceiveEvent(player, packet.Data); } { foreach (SNet_Player otherPlayer in _parent.OtherPlayers) { NetworkAPI.InvokeFreeSizedEvent(_eventName, ConvertPacket(packet), otherPlayer, channelType); } return; } } if (target.IsLocal) { if (_mode.HasFlag(SenderMode.Self)) { ReceiveEvent(player, packet.Data); } return; } if (target.IsBot) { if (SNet.IsMaster) { ReceiveEvent(player, packet.Data); return; } target = SNet.Master; } if (ModManager.HasMod(target, _parent)) { NetworkAPI.InvokeFreeSizedEvent(_eventName, ConvertPacket(packet), target, channelType); } } private static byte[] ConvertPacket(CustomPacket packet) { MemoryMarshal.Write(s_packetBuffer, in packet); return s_packetBuffer; } private void ReceiveDataRaw(ulong _, byte[] bytes) { ReceiveData(MemoryMarshal.Read(bytes)); } private void ReceiveData(CustomPacket packet) { SNet_Player arg = default(SNet_Player); if (((pPlayer)(ref packet.Player)).TryGetPlayer(ref arg)) { ReceiveEvent(arg, packet.Data); } } void ICustomDataSender.OnPlayerLeft(SNet_Player player) { OnPlayerLeft(player); } private protected virtual void OnPlayerLeft(SNet_Player player) { _sentBots.Remove(player.Lookup); } void ICustomDataSender.OnLobbyLeft() { OnLobbyLeft(); } private protected virtual void OnLobbyLeft() { _sentBots.Clear(); } } internal static class DinoLogger { private static ManualLogSource logger = Logger.CreateLogSource("OptionalNetworkAPI"); public static void Log(string format, params object[] args) { Log(string.Format(format, args)); } public static void Log(string str) { if (logger != null) { logger.Log((LogLevel)8, (object)str); } } public static void Warning(string format, params object[] args) { Warning(string.Format(format, args)); } public static void Warning(string str) { if (logger != null) { logger.Log((LogLevel)4, (object)str); } } public static void Error(string format, params object[] args) { Error(string.Format(format, args)); } public static void Error(string str) { if (logger != null) { logger.Log((LogLevel)2, (object)str); } } public static void Debug(string format, params object[] args) { Debug(string.Format(format, args)); } public static void Debug(string str) { if (logger != null) { logger.Log((LogLevel)32, (object)str); } } } [BepInPlugin("Dinorush.OptionalNetworkAPI", "OptionalNetworkAPI", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal sealed class EntryPoint : BasePlugin { public const string MODNAME = "OptionalNetworkAPI"; public override void Load() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) ModSetNetworkManager.Init(); new Harmony("OptionalNetworkAPI").PatchAll(); ((BasePlugin)this).Log.LogMessage((object)"Loaded OptionalNetworkAPI"); } } public class ModInfo { public readonly string Name; internal readonly ulong Hash; public readonly long Mask; private readonly List _customDataSenders = new List(); private readonly List _customDataManagers = new List(); private readonly Dictionary _bots = new Dictionary(3); private readonly Dictionary _others = new Dictionary(3); private readonly Dictionary _players = new Dictionary(4); private static long s_nextMask = 2L; public bool MasterHasMod { get; private set; } public IReadOnlyCollection Bots => _bots.Values; public IReadOnlyCollection OtherPlayers => _others.Values; public IReadOnlyCollection Players => _players.Values; public event Action? OnPlayerJoined; public event Action? OnPlayerModSet; public event Action? OnPlayerLeft; public event Action? OnPlayerSpawned; public event Action? OnPlayerDespawned; public event Action? OnMasterModSet; public event Action? OnLobbyLeft; private ModInfo(string name, ulong hash, long mask) { Name = name; Hash = hash; Mask = mask; } public CustomDataSender AddCustomDataSender(Action receiveEvent, Func? defaultProvider = null, SenderMode mode = SenderMode.OtherPlayers) where T : unmanaged { CustomDataSender customDataSender = CustomDataSender.CreateDataSender(this, _customDataSenders.Count, receiveEvent, defaultProvider, mode); _customDataSenders.Add(customDataSender); return customDataSender; } public CustomDataManager AddCustomDataManager(Func defaultProvider) where T : unmanaged { CustomDataManager customDataManager = CustomDataManager.CreateDataManager(this, _customDataSenders.Count, defaultProvider); _customDataSenders.Add(customDataManager); _customDataManagers.Add(customDataManager); return customDataManager; } internal void InvokePlayerJoined(PlayerInfo info) { this.OnPlayerJoined?.Invoke(info.Owner); } internal void InvokePlayerModSet(PlayerInfo info) { bool flag = info.HasMod(Mask); if ((flag && !_players.TryAdd(info.Lookup, info.Owner)) || (!flag && !_players.Remove(info.Lookup))) { return; } if (!info.IsLocal) { Dictionary dictionary = (info.IsBot ? _bots : _others); if (flag) { dictionary.Add(info.Lookup, info.Owner); } else { dictionary.Remove(info.Lookup); } } this.OnPlayerModSet?.Invoke(info.Owner, flag); if (flag) { foreach (ICustomDataSender customDataSender in _customDataSenders) { customDataSender.SendDefaultData(info.Owner); } return; } foreach (ICustomDataManager customDataManager in _customDataManagers) { customDataManager.OnPlayerModRemoved(info.Owner); } } internal void InvokePlayerLeft(PlayerInfo info) { (info.IsBot ? _bots : _others).Remove(info.Lookup); this.OnPlayerLeft?.Invoke(info.Owner); foreach (ICustomDataSender customDataSender in _customDataSenders) { customDataSender.OnPlayerLeft(info.Owner); } } internal void InvokePlayerSpawned(PlayerInfo info) { this.OnPlayerSpawned?.Invoke(info.Player); } internal void InvokePlayerDespawned(PlayerInfo info) { this.OnPlayerDespawned?.Invoke(info.Player); } internal void InvokeMasterSet(PlayerInfo info) { MasterHasMod = info.HasMod(Mask); this.OnMasterModSet?.Invoke(MasterHasMod); } internal void InvokeLobbyLeft() { _bots.Clear(); _others.Clear(); _players.Clear(); MasterHasMod = false; this.OnLobbyLeft?.Invoke(); foreach (ICustomDataSender customDataSender in _customDataSenders) { customDataSender.OnLobbyLeft(); } } private static long GetNextMask() { if (s_nextMask == 0L) { return 0L; } long num = s_nextMask & -2; if ((s_nextMask & 1) != 0L) { if (num == long.MinValue) { s_nextMask = 0L; return num | 1; } s_nextMask = (num << 1) | 1; return num | 1; } if (num == long.MinValue) { s_nextMask = 3L; return num; } s_nextMask = num << 1; return num; } internal static ModInfo CreateModInfo(string name, ulong hash) { return new ModInfo(name, hash, GetNextMask()); } } public static class OptionalNetworkAPI { public static PlayerInfo? MasterInfo => ModManager.MasterInfo; public static PlayerInfo? LocalInfo => ModManager.LocalInfo; public static IReadOnlyCollection Mods => ModManager.Mods; public static ModInfo RegisterMod(string name) { return ModManager.AddMod(name); } public static bool HasMod(string name) { return ModManager.HasMod(name); } public static bool HasMod(SNet_Player player, string name) { return ModManager.HasMod(player, name); } public static bool HasMod(SNet_Player player, ModInfo modInfo) { return ModManager.HasMod(player, modInfo); } public static bool TryGetModInfo(string name, [MaybeNullWhen(false)] out ModInfo modInfo) { return ModManager.TryGetModInfo(name, out modInfo); } public static bool TryGetPlayerInfo(SNet_Player player, [MaybeNullWhen(false)] out PlayerInfo playerInfo) { return ModManager.TryGetPlayerInfo(player, out playerInfo); } } public class PlayerInfo { public (long mask1, long mask2) ModMask { get; internal set; } = (mask1: 0L, mask2: 1L); public ulong Lookup { get; } public SNet_Player Owner { get; } public PlayerAgent? Player { get; internal set; } public bool IsLocal { get; } public bool IsBot { get; } public bool IsRemote { get; } internal PlayerInfo(SNet_Player owner) { Owner = owner; Lookup = Owner.Lookup; IsLocal = Owner.IsLocal; IsBot = Owner.IsBot; IsRemote = !Owner.IsBot && !Owner.IsLocal; } public bool HasMod(ModInfo modInfo) { return HasMod(modInfo.Mask); } public bool HasMod(long modMask) { if ((modMask & 1) == 0L) { return (ModMask.mask1 & modMask) != 0; } return (ModMask.mask2 & modMask) != 1; } } } namespace OptionalNetworking.Patches { [HarmonyPatch] internal static class NetworkPatches { [HarmonyPatch(typeof(SNet_SessionHub), "AddPlayerToSession")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_AddPlayer(SNet_Player player) { ModManager.OnAddPlayer(player); ModSetNetworkManager.OnAddPlayer(player); } [HarmonyPatch(typeof(SNet_SessionHub), "OnLeftLobby")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_RemovePlayer(SNet_Player player) { ModManager.OnRemovePlayer(player); } [HarmonyPatch(typeof(SNet_SyncManager), "OnFoundMaster")] [HarmonyPatch(typeof(SNet_SyncManager), "OnFoundNewMasterDuringMigration")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_FoundMaster() { ModManager.OnMasterSet(); } [HarmonyPatch(typeof(PlayerSync), "OnSpawn")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_PlayerSpawn(PlayerSync __instance) { ModManager.OnPlayerSpawned(__instance.m_agent); } [HarmonyPatch(typeof(PlayerAgent), "OnDespawn")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_PlayerDespawn(PlayerAgent __instance) { ModManager.OnPlayerDespawned(__instance); } [HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_LeaveHub() { ModManager.OnLobbyLeft(); } } } namespace OptionalNetworking.Managers { internal static class ModManager { private static readonly Dictionary _bots = new Dictionary(); private static readonly Dictionary _players = new Dictionary(); private static readonly Dictionary _modInfos = new Dictionary(); private static readonly Dictionary _hashToMod = new Dictionary(); private static (long mask1, long mask2) _localMask = (mask1: 0L, mask2: 1L); public static PlayerInfo? MasterInfo { get; private set; } public static PlayerInfo? LocalInfo { get; private set; } public static IReadOnlyCollection Mods => _modInfos.Values; internal static IReadOnlyCollection ModHashes => _hashToMod.Keys; public static bool HasMod(string name) { return _modInfos.ContainsKey(name); } public static bool HasMod(SNet_Player player, string name) { if (!_players.TryGetValue(player.Lookup, out PlayerInfo value) || !_modInfos.TryGetValue(name, out ModInfo value2)) { return false; } return value.HasMod(value2); } public static bool TryGetModInfo(string name, [MaybeNullWhen(false)] out ModInfo modInfo) { return _modInfos.TryGetValue(name, out modInfo); } public static bool TryGetPlayerInfo(SNet_Player player, [MaybeNullWhen(false)] out PlayerInfo playerInfo) { return _players.TryGetValue(player.Lookup, out playerInfo); } private static void CombineMask(ref (long mask1, long mask2) mask, long maskToAdd) { if ((maskToAdd & 1) == 0L) { mask.mask1 |= maskToAdd; } else { mask.mask2 |= maskToAdd; } } internal static (long mask1, long mask2) HashesToMask(ulong[] hashes) { (long, long) mask = (0L, 1L); foreach (ulong key in hashes) { if (_hashToMod.TryGetValue(key, out ModInfo value)) { CombineMask(ref mask, value.Mask); } } return mask; } internal static ModInfo AddMod(string name) { if (_modInfos.ContainsKey(name)) { throw new ArgumentException("Cannot register duplicate mod name " + name + "."); } ulong num = MurmurHash2.Hash(name); if (_hashToMod.TryGetValue(num, out ModInfo value)) { throw new ArgumentException($"Hash for mod name {name} collides with {value.Name}, can't register!"); } ModInfo modInfo = ModInfo.CreateModInfo(name, num); if (modInfo.Mask == 0L) { throw new IndexOutOfRangeException("Out of internal space (126 mods registered), unable to register mod " + name + "."); } _modInfos.Add(name, modInfo); _hashToMod.Add(num, modInfo); CombineMask(ref _localMask, modInfo.Mask); return modInfo; } internal static bool HasMod(SNet_Player? player, ModInfo modInfo) { if ((Object)(object)player == (Object)null || !_players.TryGetValue(player.Lookup, out PlayerInfo value)) { return false; } return value.HasMod(modInfo); } internal static void OnAddPlayer(SNet_Player player) { if (_players.ContainsKey(player.Lookup)) { return; } PlayerInfo playerInfo = new PlayerInfo(player); _players.Add(player.Lookup, playerInfo); foreach (ModInfo value in _modInfos.Values) { value.InvokePlayerJoined(playerInfo); } if (playerInfo.IsLocal) { LocalInfo = playerInfo; OnPlayerModSet(player, _localMask); } else if (playerInfo.IsBot) { _bots.Add(playerInfo.Lookup, playerInfo); if (MasterInfo != null) { OnPlayerModSet(player, MasterInfo.ModMask); } } } internal static void OnRemovePlayer(SNet_Player player) { if (!_players.Remove(player.Lookup, out PlayerInfo value)) { return; } _bots.Remove(player.Lookup); if (value.IsLocal) { LocalInfo = null; } foreach (ModInfo value2 in _modInfos.Values) { value2.InvokePlayerLeft(value); } } internal static void OnPlayerSpawned(PlayerAgent agent) { if (!_players.TryGetValue(agent.Owner.Lookup, out PlayerInfo value)) { return; } value.Player = agent; foreach (ModInfo value2 in _modInfos.Values) { value2.InvokePlayerSpawned(value); } } internal static void OnPlayerDespawned(PlayerAgent agent) { if (!_players.TryGetValue(agent.Owner.Lookup, out PlayerInfo value) || (Object)(object)value.Player == (Object)null) { return; } foreach (ModInfo value2 in _modInfos.Values) { value2.InvokePlayerDespawned(value); } value.Player = null; } internal static void OnPlayerModSet(SNet_Player player, (long mask1, long mask2) modMask) { if (!_players.TryGetValue(player.Lookup, out PlayerInfo value)) { OnAddPlayer(player); value = _players[player.Lookup]; } value.ModMask = modMask; foreach (ModInfo value2 in _modInfos.Values) { value2.InvokePlayerModSet(value); } } internal static void OnLobbyLeft() { foreach (ModInfo value in _modInfos.Values) { value.InvokeLobbyLeft(); } _players.Clear(); MasterInfo = null; LocalInfo = null; } internal static void OnMasterSet() { if (!SNet.HasMaster) { MasterInfo = null; return; } if (!_players.TryGetValue(SNet.Master.Lookup, out PlayerInfo value)) { OnAddPlayer(SNet.Master); value = _players[SNet.Master.Lookup]; } else if (MasterInfo == value) { return; } MasterInfo = value; foreach (ModInfo value2 in _modInfos.Values) { value2.InvokeMasterSet(value); } foreach (PlayerInfo value3 in _bots.Values) { OnPlayerModSet(value3.Owner, MasterInfo.ModMask); } } } internal static class ModSetNetworkManager { private const string ModSetEvent = "OptionalNetworkAPIModSet"; public static void Init() { NetworkAPI.RegisterFreeSizedEvent("OptionalNetworkAPIModSet", (Action)ReceiveModSet); } internal static void OnAddPlayer(SNet_Player player) { if (player.IsBot || player.IsLocal) { return; } byte[] array = new byte[ModManager.ModHashes.Count * 8]; int num = 0; foreach (ulong modHash in ModManager.ModHashes) { BinaryPrimitives.WriteUInt64BigEndian(array.AsSpan(num++ * 8, 8), modHash); } NetworkAPI.InvokeFreeSizedEvent("OptionalNetworkAPIModSet", array, player, (SNet_ChannelType)0); } private static void ReceiveModSet(ulong lookup, byte[] data) { SNet_Player player = default(SNet_Player); if (SNet.TryGetPlayer(lookup, ref player)) { ulong[] array = new ulong[data.Length / 8]; int num = 0; for (int i = 0; i < data.Length; i += 8) { array[num++] = BinaryPrimitives.ReadUInt64BigEndian(data.AsSpan(i, 8)); } ModManager.OnPlayerModSet(player, ModManager.HashesToMask(array)); } } } } namespace OptionalNetworking.Hashing { internal static class MurmurHash2 { private const ulong seed = 3314489978uL; private const ulong m = 14313749767032793493uL; private const int r = 47; public static ulong Hash(string data) { return Hash(Encoding.UTF8.GetBytes(data)); } public static ulong Hash(byte[] data) { return Hash(data, 3314489978uL); } public static ulong Hash(byte[] data, ulong seed) { int num = data.Length; if (num == 0) { return 0uL; } ulong num2 = seed ^ (ulong)(num * -4132994306676758123L); int num3 = 0; while (num >= 8) { ulong num4 = (ulong)(data[num3++] | (data[num3++] << 8) | (data[num3++] << 16) | (data[num3++] << 24) | data[num3++] | (data[num3++] << 8) | (data[num3++] << 16) | (data[num3++] << 24)); num4 *= 14313749767032793493uL; num4 ^= num4 >> 47; num4 *= 14313749767032793493uL; num2 ^= num4; num2 *= 14313749767032793493uL; num -= 8; } switch (num) { case 7: num2 ^= (ulong)(data[num3++] | (data[num3++] << 8) | (data[num3++] << 16) | (data[num3++] << 24) | data[num3++] | (data[num3++] << 8) | (data[num3] << 16)); num2 *= 14313749767032793493uL; break; case 6: num2 ^= (ulong)(data[num3++] | (data[num3++] << 8) | (data[num3++] << 16) | (data[num3++] << 24) | data[num3++] | (data[num3++] << 8)); num2 *= 14313749767032793493uL; break; case 5: num2 ^= (ulong)(data[num3++] | (data[num3++] << 8) | (data[num3++] << 16) | (data[num3++] << 24) | data[num3++]); num2 *= 14313749767032793493uL; break; case 4: num2 ^= (ulong)(data[num3++] | (data[num3++] << 8) | (data[num3++] << 16) | (data[num3++] << 24)); num2 *= 14313749767032793493uL; break; case 3: num2 ^= (ulong)(data[num3++] | (data[num3++] << 8) | (data[num3++] << 16)); num2 *= 14313749767032793493uL; break; case 2: num2 ^= (ulong)(data[num3++] | (data[num3++] << 8)); num2 *= 14313749767032793493uL; break; case 1: num2 ^= data[num3++]; num2 *= 14313749767032793493uL; break; } num2 ^= num2 >> 47; num2 *= 14313749767032793493uL; return num2 ^ (num2 >> 47); } } }