using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BoneLib.BoneMenu;
using LabFusion.Network;
using LabFusion.Network.Serialization;
using LabFusion.Player;
using LabFusion.SDK.Modules;
using LabFusion.UI.Popups;
using LabFusion.Utilities;
using LabLink;
using LabLink.Data;
using LabLink.Net;
using LabLink.Runtime;
using LabLink.UI;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Steamworks;
using Steamworks.Data;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(ModMain), "LabLink", "1.1.0", "Dynamic Team", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("LabLink")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("LabLink")]
[assembly: AssemblyTitle("LabLink")]
[assembly: AssemblyVersion("1.1.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 LabLink
{
public class ModMain : MelonMod
{
public static Instance Log { get; private set; }
public override void OnInitializeMelon()
{
Log = ((MelonBase)this).LoggerInstance;
Settings.Init();
FriendStore.Load();
Menu.Build();
try
{
ModuleManager.RegisterModule<LinkModule>();
Log.Msg("LabLink Fusion module registered.");
}
catch (Exception ex)
{
Log.Warning("Fusion module not registered (LabFusion missing?): " + ex.Message);
}
LobbyTracker.Hook();
Log.Msg("LabLink loaded.");
}
}
public static class Settings
{
public const string Category = "LabLink";
public static MelonPreferences_Category Cat { get; private set; }
public static MelonPreferences_Entry<bool> PresenceToasts { get; private set; }
public static MelonPreferences_Entry<bool> PopupOnRequest { get; private set; }
public static MelonPreferences_Entry<bool> PopupOnMessage { get; private set; }
public static MelonPreferences_Entry<bool> MessagesFromFriendsOnly { get; private set; }
public static MelonPreferences_Entry<float> PopupDuration { get; private set; }
public static MelonPreferences_Entry<string> ComposedMessage { get; private set; }
public static void Init()
{
Cat = MelonPreferences.CreateCategory("LabLink", "LabLink");
PresenceToasts = Cat.CreateEntry<bool>("PresenceToasts", true, "Toast when a friend joins your lobby", (string)null, false, false, (ValueValidator)null, (string)null);
PopupOnRequest = Cat.CreateEntry<bool>("PopupOnRequest", true, "Popup when a friend request arrives", (string)null, false, false, (ValueValidator)null, (string)null);
PopupOnMessage = Cat.CreateEntry<bool>("PopupOnMessage", true, "Popup when a message arrives", (string)null, false, false, (ValueValidator)null, (string)null);
MessagesFromFriendsOnly = Cat.CreateEntry<bool>("MessagesFromFriendsOnly", true, "Only accept messages from friends", (string)null, false, false, (ValueValidator)null, (string)null);
PopupDuration = Cat.CreateEntry<float>("PopupDuration", 5f, "Popup duration in seconds", (string)null, false, false, (ValueValidator)null, (string)null);
ComposedMessage = Cat.CreateEntry<string>("ComposedMessage", "", "Current composed message", (string)null, false, false, (ValueValidator)null, (string)null);
try
{
if (PopupDuration.Value < 1f || PopupDuration.Value > 30f)
{
PopupDuration.Value = 5f;
}
}
catch
{
}
Cat.SaveToFile(false);
}
public static void Save()
{
MelonPreferences_Category cat = Cat;
if (cat != null)
{
cat.SaveToFile(false);
}
}
}
}
namespace LabLink.UI
{
public static class Menu
{
private static readonly Color _green = new Color(0.3f, 0.85f, 0.4f);
private static readonly Color _cyan = new Color(0.2f, 0.8f, 0.9f);
private static readonly Color _gold = new Color(1f, 0.84f, 0f);
private static readonly Color _gray = new Color(0.6f, 0.6f, 0.6f);
private static readonly Color _red = new Color(0.9f, 0.3f, 0.3f);
private static readonly Color _blue = new Color(0.3f, 0.6f, 1f);
private static Page _root;
private static Page _friendsPage;
private static Page _lobbyPage;
private static Page _requestsPage;
private static Page _messagesPage;
private static Page _blockedPage;
private static Page _recipientPage;
private static Page _inboxPage;
private static readonly string[] _quick = new string[6] { "gg", "follow me", "help!", "afk", "nice", "lol" };
public static void Build()
{
//IL_000a: 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_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
_root = Page.Root.CreatePage("LabLink", _green, 0, true);
_friendsPage = _root.CreatePage("Friends", _green, 0, true);
_lobbyPage = _root.CreatePage("Lobby", _blue, 0, true);
_requestsPage = _root.CreatePage("Requests", _gold, 0, true);
_messagesPage = _root.CreatePage("Messages", _cyan, 0, true);
_blockedPage = _root.CreatePage("Blocked", _red, 0, true);
BuildSettingsPage(_root);
RefreshDynamic();
ModMain.Log.Msg("LabLink menu built.");
}
public static void RefreshDynamic()
{
try
{
RebuildFriends();
RebuildLobby();
RebuildRequests();
RebuildMessages();
RebuildBlocked();
}
catch (Exception ex)
{
Instance log = ModMain.Log;
if (log != null)
{
log.Warning("Menu refresh failed: " + ex.Message);
}
}
}
private static void RebuildFriends()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
Page friendsPage = _friendsPage;
if (friendsPage == null)
{
return;
}
friendsPage.RemoveAll();
friendsPage.CreateFunction("Refresh", _green, (Action)RefreshDynamic);
IReadOnlyList<Friend> friends = FriendStore.Friends;
if (friends.Count == 0)
{
friendsPage.CreateFunction("(no friends yet - add from Lobby)", _gray, (Action)delegate
{
});
return;
}
List<Friend> list = new List<Friend>(friends);
list.Sort((Friend a, Friend b) => (a.Favorite != b.Favorite) ? ((!a.Favorite) ? 1 : (-1)) : string.Compare(a.Display(), b.Display(), StringComparison.OrdinalIgnoreCase));
foreach (Friend item in list)
{
ulong platformId = item.PlatformId;
FriendPresence pres = SteamPresence.Get(platformId);
bool flag = pres.Status != PresenceStatus.Offline && pres.Status != PresenceStatus.Unknown;
string value = (item.Favorite ? "* " : "");
BuildFriendActions(friendsPage.CreatePage($"{value}{item.Display()} [{pres.Label}]", flag ? _green : _gray, 0, true), platformId, pres);
}
}
private static void BuildFriendActions(Page page, ulong id, FriendPresence pres)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: 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_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
Friend f = FriendStore.GetFriend(id);
if (f == null)
{
page.CreateFunction("(removed)", _gray, (Action)delegate
{
});
return;
}
if (pres.Status == PresenceStatus.InLobby)
{
page.CreateFunction("Join their lobby", _green, (Action)delegate
{
string message = SteamPresence.JoinFriend(id);
Social.Toast("LabLink", message, (NotificationType)0);
});
}
bool flag = pres.Status == PresenceStatus.InYourLobby;
page.CreateFunction(flag ? "Set as message recipient" : "Message (needs same lobby)", flag ? _cyan : _gray, (Action)delegate
{
Social.CurrentRecipient = id;
Social.Toast("LabLink", "Recipient set to " + f.Display() + ". Open Messages.", (NotificationType)0);
});
page.CreateString("Nickname", _gold, f.Nickname ?? "", (Action<string>)delegate(string v)
{
f.Nickname = v ?? "";
FriendStore.Save();
});
page.CreateString("Note", _gold, f.Note ?? "", (Action<string>)delegate(string v)
{
f.Note = v ?? "";
FriendStore.Save();
});
page.CreateBool("Favorite", _gold, f.Favorite, (Action<bool>)delegate(bool v)
{
f.Favorite = v;
FriendStore.Save();
});
Page obj = page.CreatePage("Remove / Block", _red, 0, true);
obj.CreateFunction("Unfriend", _red, (Action)delegate
{
Social.Unfriend(id);
});
obj.CreateFunction("Block", _red, (Action)delegate
{
Social.Block(id);
});
}
private static void RebuildLobby()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
Page lobbyPage = _lobbyPage;
if (lobbyPage == null)
{
return;
}
lobbyPage.RemoveAll();
lobbyPage.CreateFunction("Refresh", _green, (Action)RefreshDynamic);
if (!Fusion.HasServer)
{
lobbyPage.CreateFunction("(not in a lobby)", _gray, (Action)delegate
{
});
return;
}
int num = 0;
foreach (Fusion.PlayerEntry player in Fusion.GetPlayers())
{
if (player.IsLocal)
{
continue;
}
num++;
ulong id = player.PlatformId;
string name = player.Name;
if (FriendStore.IsBlocked(id))
{
lobbyPage.CreateFunction(name + " [blocked]", _gray, (Action)delegate
{
});
}
else if (FriendStore.IsFriend(id))
{
lobbyPage.CreateFunction(name + " [friend]", _green, (Action)delegate
{
});
}
else if (LobbyTracker.HasMod(id))
{
lobbyPage.CreateFunction("Add Friend: " + name, _cyan, (Action)delegate
{
Social.SendFriendRequest(id, name);
});
}
else
{
lobbyPage.CreateFunction(name + " (no LabLink)", _gray, (Action)delegate
{
});
}
}
if (num == 0)
{
lobbyPage.CreateFunction("(no other players here)", _gray, (Action)delegate
{
});
}
}
private static void RebuildRequests()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: 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)
Page requestsPage = _requestsPage;
if (requestsPage == null)
{
return;
}
requestsPage.RemoveAll();
requestsPage.CreateFunction("Refresh", _green, (Action)RefreshDynamic);
IReadOnlyList<PendingRequest> incoming = FriendStore.Incoming;
IReadOnlyList<PendingRequest> outgoing = FriendStore.Outgoing;
requestsPage.CreateFunction($"-- Incoming ({incoming.Count}) --", _gold, (Action)delegate
{
});
if (incoming.Count == 0)
{
requestsPage.CreateFunction("(none)", _gray, (Action)delegate
{
});
}
foreach (PendingRequest item in incoming)
{
ulong id = item.PlatformId;
Page obj = requestsPage.CreatePage("From " + item.Display(), _gold, 0, true);
obj.CreateFunction("Accept", _green, (Action)delegate
{
Social.AcceptRequest(id);
});
obj.CreateFunction("Decline", _red, (Action)delegate
{
Social.DeclineRequest(id);
});
obj.CreateFunction("Block", _red, (Action)delegate
{
Social.Block(id);
});
}
requestsPage.CreateFunction($"-- Outgoing ({outgoing.Count}) --", _cyan, (Action)delegate
{
});
if (outgoing.Count == 0)
{
requestsPage.CreateFunction("(none)", _gray, (Action)delegate
{
});
}
foreach (PendingRequest item2 in outgoing)
{
string text = (Fusion.IsOnline(item2.PlatformId) ? "pending" : "pending (offline)");
requestsPage.CreateFunction(item2.Display() + " - " + text, _gray, (Action)delegate
{
});
}
}
private static void RebuildMessages()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
Page messagesPage = _messagesPage;
if (messagesPage != null)
{
messagesPage.RemoveAll();
messagesPage.CreateFunction("Refresh", _green, (Action)RefreshDynamic);
string text = ((Social.CurrentRecipient == 0L) ? "none" : (FriendStore.GetFriend(Social.CurrentRecipient)?.Display() ?? Fusion.NameOf(Social.CurrentRecipient) ?? "unknown"));
messagesPage.CreateFunction("To: " + text, _gold, (Action)delegate
{
});
BuildComposePage(messagesPage);
BuildRecipientPage(messagesPage);
BuildQuickSendPage(messagesPage);
BuildInboxPage(messagesPage);
}
}
private static void BuildComposePage(Page parent)
{
//IL_0006: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
Page obj = parent.CreatePage("Compose & Send", _cyan, 0, true);
obj.CreateString("Type Message (VR keyboard)", _gold, Settings.ComposedMessage.Value, (Action<string>)delegate(string v)
{
Settings.ComposedMessage.Value = v ?? "";
Settings.Save();
});
obj.CreateFunction("Send", _green, (Action)delegate
{
Social.SendMessageTo(Social.CurrentRecipient, Settings.ComposedMessage.Value);
});
obj.CreateFunction("Clear", _gray, (Action)delegate
{
Settings.ComposedMessage.Value = "";
Settings.Save();
});
}
private static void BuildRecipientPage(Page parent)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
_recipientPage = parent.CreatePage("Choose Recipient", _blue, 0, true);
RebuildRecipient();
}
private static void RebuildRecipient()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
Page recipientPage = _recipientPage;
if (recipientPage == null)
{
return;
}
recipientPage.RemoveAll();
recipientPage.CreateFunction("Refresh", _green, (Action)RebuildRecipient);
int num = 0;
foreach (Friend friend in FriendStore.Friends)
{
if (Fusion.IsOnline(friend.PlatformId))
{
ulong id = friend.PlatformId;
string label = friend.Display();
recipientPage.CreateFunction(label, _cyan, (Action)delegate
{
Social.CurrentRecipient = id;
Social.Toast("LabLink", "Recipient: " + label, (NotificationType)0);
RebuildMessages();
});
num++;
}
}
if (num == 0)
{
recipientPage.CreateFunction("(no friends online)", _gray, (Action)delegate
{
});
}
}
private static void BuildQuickSendPage(Page parent)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
Page val = parent.CreatePage("Quick Send", _green, 0, true);
string[] quick = _quick;
foreach (string text in quick)
{
string m = text;
val.CreateFunction(m, _green, (Action)delegate
{
Social.SendMessageTo(Social.CurrentRecipient, m);
});
}
}
private static void BuildInboxPage(Page parent)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
_inboxPage = parent.CreatePage("Inbox", _gray, 0, true);
RebuildInbox();
}
private static void RebuildInbox()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: 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)
Page inboxPage = _inboxPage;
if (inboxPage == null)
{
return;
}
inboxPage.RemoveAll();
inboxPage.CreateFunction("Refresh", _green, (Action)RebuildInbox);
inboxPage.CreateFunction("Clear", _gray, (Action)delegate
{
Social.ClearInbox();
RebuildInbox();
});
IReadOnlyList<Social.InboxEntry> inbox = Social.Inbox;
if (inbox.Count == 0)
{
inboxPage.CreateFunction("(no messages)", _gray, (Action)delegate
{
});
return;
}
for (int num = inbox.Count - 1; num >= 0; num--)
{
Social.InboxEntry inboxEntry = inbox[num];
inboxPage.CreateFunction(inboxEntry.Name + ": " + Trunc(inboxEntry.Body, 28), _gray, (Action)delegate
{
});
}
}
private static void RebuildBlocked()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
Page blockedPage = _blockedPage;
if (blockedPage == null)
{
return;
}
blockedPage.RemoveAll();
blockedPage.CreateFunction("Refresh", _green, (Action)RefreshDynamic);
IReadOnlyList<ulong> blocked = FriendStore.Blocked;
if (blocked.Count == 0)
{
blockedPage.CreateFunction("(no one blocked)", _gray, (Action)delegate
{
});
return;
}
foreach (ulong item in blocked)
{
ulong bid = item;
string text = Fusion.NameOf(bid) ?? $"Player {bid}";
blockedPage.CreateFunction("Unblock " + text, _green, (Action)delegate
{
FriendStore.Unblock(bid);
RefreshDynamic();
});
}
}
private static void BuildSettingsPage(Page parent)
{
//IL_0006: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
Page obj = parent.CreatePage("Settings", _gray, 0, true);
obj.CreateBool("Friend-join toasts", _cyan, Settings.PresenceToasts.Value, (Action<bool>)delegate(bool v)
{
Settings.PresenceToasts.Value = v;
Settings.Save();
});
obj.CreateBool("Popup on friend request", _cyan, Settings.PopupOnRequest.Value, (Action<bool>)delegate(bool v)
{
Settings.PopupOnRequest.Value = v;
Settings.Save();
});
obj.CreateBool("Popup on message", _cyan, Settings.PopupOnMessage.Value, (Action<bool>)delegate(bool v)
{
Settings.PopupOnMessage.Value = v;
Settings.Save();
});
obj.CreateBool("Messages from friends only", _cyan, Settings.MessagesFromFriendsOnly.Value, (Action<bool>)delegate(bool v)
{
Settings.MessagesFromFriendsOnly.Value = v;
Settings.Save();
});
obj.CreateFloat("Popup duration (s)", _gold, Settings.PopupDuration.Value, 1f, 1f, 30f, (Action<float>)delegate(float v)
{
Settings.PopupDuration.Value = v;
Settings.Save();
});
}
private static string Trunc(string s, int max)
{
if (string.IsNullOrEmpty(s))
{
return "(empty)";
}
if (s.Length > max)
{
return s.Substring(0, max - 1) + "…";
}
return s;
}
}
}
namespace LabLink.Runtime
{
public static class Fusion
{
public struct PlayerEntry
{
public ulong PlatformId;
public byte SmallId;
public string Name;
public bool IsLocal;
public bool IsHost;
}
public static bool HasServer
{
get
{
try
{
return NetworkInfo.HasServer;
}
catch
{
return false;
}
}
}
public static bool IsHost
{
get
{
try
{
return NetworkInfo.IsHost;
}
catch
{
return false;
}
}
}
public static ulong LocalPlatformId
{
get
{
try
{
return PlayerIDManager.LocalPlatformID;
}
catch
{
return 0uL;
}
}
}
public static string LocalName()
{
try
{
return NameOf(PlayerIDManager.LocalID) ?? "You";
}
catch
{
return "You";
}
}
public static List<PlayerEntry> GetPlayers()
{
List<PlayerEntry> list = new List<PlayerEntry>();
if (!HasServer)
{
return list;
}
try
{
ulong localPlatformId = LocalPlatformId;
foreach (PlayerID playerID in PlayerIDManager.PlayerIDs)
{
if (playerID != null)
{
list.Add(new PlayerEntry
{
PlatformId = playerID.PlatformID,
SmallId = playerID.SmallID,
Name = (NameOf(playerID) ?? $"Player {playerID.SmallID}"),
IsLocal = (playerID.PlatformID == localPlatformId),
IsHost = playerID.IsHost
});
}
}
}
catch (Exception ex)
{
ModMain.Log.Warning("Player list failed: " + ex.Message);
}
return list;
}
public static string NameOf(PlayerID pid)
{
if (pid == null)
{
return null;
}
try
{
string valueOrEmpty = pid.Metadata.Nickname.GetValueOrEmpty();
if (!string.IsNullOrEmpty(valueOrEmpty))
{
return valueOrEmpty;
}
string valueOrEmpty2 = pid.Metadata.Username.GetValueOrEmpty();
if (!string.IsNullOrEmpty(valueOrEmpty2))
{
return valueOrEmpty2;
}
}
catch
{
}
return null;
}
public static string NameOf(ulong platformId)
{
try
{
return NameOf(PlayerIDManager.GetPlayerID(platformId));
}
catch
{
return null;
}
}
public static bool IsOnline(ulong platformId)
{
try
{
return PlayerIDManager.GetPlayerID(platformId) != null;
}
catch
{
return false;
}
}
}
public static class LobbyTracker
{
[CompilerGenerated]
private static class <>O
{
public static ServerEvent <0>__HandleSessionStart;
public static ServerEvent <1>__HandleSessionEnd;
public static PlayerUpdate <2>__HandlePlayerJoined;
public static PlayerUpdate <3>__HandlePlayerLeft;
}
private static readonly HashSet<ulong> _modUsers = new HashSet<ulong>();
private static bool _hooked;
public static bool HasMod(ulong platformId)
{
return _modUsers.Contains(platformId);
}
public static void MarkModUser(ulong platformId, string name)
{
if (platformId != 0L && platformId != Fusion.LocalPlatformId)
{
_modUsers.Add(platformId);
}
}
public static void Hook()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//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_0064: Expected O, but got Unknown
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Expected O, but got Unknown
if (_hooked)
{
return;
}
try
{
object obj = <>O.<0>__HandleSessionStart;
if (obj == null)
{
ServerEvent val = HandleSessionStart;
<>O.<0>__HandleSessionStart = val;
obj = (object)val;
}
MultiplayerHooking.OnJoinedServer += (ServerEvent)obj;
object obj2 = <>O.<0>__HandleSessionStart;
if (obj2 == null)
{
ServerEvent val2 = HandleSessionStart;
<>O.<0>__HandleSessionStart = val2;
obj2 = (object)val2;
}
MultiplayerHooking.OnStartedServer += (ServerEvent)obj2;
object obj3 = <>O.<1>__HandleSessionEnd;
if (obj3 == null)
{
ServerEvent val3 = HandleSessionEnd;
<>O.<1>__HandleSessionEnd = val3;
obj3 = (object)val3;
}
MultiplayerHooking.OnDisconnected += (ServerEvent)obj3;
object obj4 = <>O.<2>__HandlePlayerJoined;
if (obj4 == null)
{
PlayerUpdate val4 = HandlePlayerJoined;
<>O.<2>__HandlePlayerJoined = val4;
obj4 = (object)val4;
}
MultiplayerHooking.OnPlayerJoined += (PlayerUpdate)obj4;
object obj5 = <>O.<3>__HandlePlayerLeft;
if (obj5 == null)
{
PlayerUpdate val5 = HandlePlayerLeft;
<>O.<3>__HandlePlayerLeft = val5;
obj5 = (object)val5;
}
MultiplayerHooking.OnPlayerLeft += (PlayerUpdate)obj5;
_hooked = true;
}
catch (Exception ex)
{
ModMain.Log.Warning("LabLink hooks failed: " + ex.Message);
}
}
private static void HandleSessionStart()
{
_modUsers.Clear();
LinkNet.Broadcast(LinkKind.CapabilityPing);
Menu.RefreshDynamic();
}
private static void HandleSessionEnd()
{
_modUsers.Clear();
Menu.RefreshDynamic();
}
private static void HandlePlayerJoined(PlayerID id)
{
LinkNet.Broadcast(LinkKind.CapabilityPing);
try
{
if (id != null && Settings.PresenceToasts.Value && FriendStore.IsFriend(id.PlatformID))
{
string text = FriendStore.GetFriend(id.PlatformID)?.Display() ?? Fusion.NameOf(id) ?? "A friend";
Social.Toast("Friend online", text + " joined the lobby.", (NotificationType)3);
}
}
catch
{
}
Menu.RefreshDynamic();
}
private static void HandlePlayerLeft(PlayerID id)
{
try
{
if (id != null)
{
_modUsers.Remove(id.PlatformID);
}
}
catch
{
}
Menu.RefreshDynamic();
}
}
public static class Social
{
public struct InboxEntry
{
public float Time;
public ulong FromId;
public string Name;
public string Body;
}
private const int InboxCapacity = 20;
private static readonly List<InboxEntry> _inbox = new List<InboxEntry>();
public static IReadOnlyList<InboxEntry> Inbox => _inbox;
public static ulong CurrentRecipient { get; set; }
public static void OnReceive(LinkData data)
{
if (data == null)
{
return;
}
ulong fromId = data.FromId;
if (fromId == Fusion.LocalPlatformId || (data.ToId != 0L && data.ToId != Fusion.LocalPlatformId) || FriendStore.IsBlocked(fromId))
{
return;
}
string text = ((!string.IsNullOrEmpty(data.FromName)) ? data.FromName : (Fusion.NameOf(fromId) ?? $"Player {fromId}"));
FriendStore.UpdateName(fromId, text);
switch ((LinkKind)data.Kind)
{
case LinkKind.CapabilityPing:
LobbyTracker.MarkModUser(fromId, text);
LinkNet.Send(LinkKind.CapabilityAck, fromId);
Menu.RefreshDynamic();
break;
case LinkKind.CapabilityAck:
LobbyTracker.MarkModUser(fromId, text);
Menu.RefreshDynamic();
break;
case LinkKind.FriendRequest:
OnFriendRequest(fromId, text);
break;
case LinkKind.RequestAccept:
OnRequestAccepted(fromId, text);
break;
case LinkKind.RequestDecline:
FriendStore.RemoveOutgoing(fromId);
Toast("Request declined", text + " declined your friend request.", (NotificationType)0);
Menu.RefreshDynamic();
break;
case LinkKind.DirectMessage:
OnDirectMessage(fromId, text, data.Body);
break;
case LinkKind.Unfriend:
if (FriendStore.IsFriend(fromId))
{
FriendStore.RemoveFriend(fromId);
Toast("Unfriended", text + " removed you as a friend.", (NotificationType)0);
Menu.RefreshDynamic();
}
break;
}
}
private static void OnFriendRequest(ulong from, string name)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: 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_0052: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Expected O, but got Unknown
if (FriendStore.IsFriend(from))
{
LinkNet.Send(LinkKind.RequestAccept, from);
return;
}
FriendStore.AddIncoming(from, name);
Menu.RefreshDynamic();
if (Settings.PopupOnRequest.Value)
{
ulong who = from;
Notify(new Notification
{
Title = NotificationText.op_Implicit("Friend request"),
Message = NotificationText.op_Implicit(name + " wants to add you. Accept?"),
Type = (NotificationType)0,
PopupLength = Mathf.Clamp(Settings.PopupDuration.Value + 5f, 5f, 30f),
ShowPopup = true,
SaveToMenu = true,
OnAccepted = delegate
{
AcceptRequest(who);
},
OnDeclined = delegate
{
DeclineRequest(who);
}
});
}
}
private static void OnRequestAccepted(ulong from, string name)
{
bool num = FriendStore.GetOutgoing(from) != null;
FriendStore.AddFriend(from, name);
if (num)
{
Toast("Friend added", name + " accepted your friend request.", (NotificationType)3);
}
Menu.RefreshDynamic();
}
private static void OnDirectMessage(ulong from, string name, string body)
{
if (!Settings.MessagesFromFriendsOnly.Value || FriendStore.IsFriend(from))
{
RecordInbox(from, name, body);
if (Settings.PopupOnMessage.Value)
{
Toast(name, string.IsNullOrEmpty(body) ? "(empty)" : body, (NotificationType)0);
}
Menu.RefreshDynamic();
}
}
public static void SendFriendRequest(ulong toId, string name)
{
if (!Fusion.HasServer)
{
Toast("LabLink", "You're not in a lobby.", (NotificationType)1);
}
else if (toId != 0L && toId != Fusion.LocalPlatformId)
{
if (FriendStore.IsFriend(toId))
{
Toast("LabLink", "Already friends.", (NotificationType)0);
return;
}
FriendStore.AddOutgoing(toId, name);
LinkNet.Send(LinkKind.FriendRequest, toId);
Toast("Request sent", "Friend request sent to " + name + ".", (NotificationType)3);
Menu.RefreshDynamic();
}
}
public static void AcceptRequest(ulong fromId)
{
PendingRequest incoming = FriendStore.GetIncoming(fromId);
string text = ((incoming != null) ? incoming.Display() : (Fusion.NameOf(fromId) ?? $"Player {fromId}"));
FriendStore.AddFriend(fromId, text);
LinkNet.Send(LinkKind.RequestAccept, fromId);
Toast("Friend added", "You and " + text + " are now friends.", (NotificationType)3);
Menu.RefreshDynamic();
}
public static void DeclineRequest(ulong fromId)
{
FriendStore.RemoveIncoming(fromId);
LinkNet.Send(LinkKind.RequestDecline, fromId);
Menu.RefreshDynamic();
}
public static void Unfriend(ulong id)
{
string text = FriendStore.GetFriend(id)?.Display() ?? "friend";
LinkNet.Send(LinkKind.Unfriend, id);
FriendStore.RemoveFriend(id);
Toast("Unfriended", "Removed " + text + ".", (NotificationType)0);
Menu.RefreshDynamic();
}
public static void Block(ulong id)
{
LinkNet.Send(LinkKind.Unfriend, id);
FriendStore.Block(id);
Toast("Blocked", "They can no longer reach you.", (NotificationType)0);
Menu.RefreshDynamic();
}
public static void SendMessageTo(ulong toId, string body)
{
if (string.IsNullOrWhiteSpace(body))
{
Toast("LabLink", "Type a message first.", (NotificationType)1);
return;
}
if (!Fusion.HasServer)
{
Toast("LabLink", "You're not in a lobby.", (NotificationType)1);
return;
}
if (toId == 0L)
{
Toast("LabLink", "Pick a recipient first.", (NotificationType)1);
return;
}
if (!Fusion.IsOnline(toId))
{
Toast("LabLink", "That friend isn't in this lobby.", (NotificationType)1);
return;
}
LinkNet.Send(LinkKind.DirectMessage, toId, body);
string text = FriendStore.GetFriend(toId)?.Display() ?? Fusion.NameOf(toId) ?? "them";
Toast("Sent", "Message sent to " + text + ".", (NotificationType)3);
}
private static void RecordInbox(ulong from, string name, string body)
{
_inbox.Add(new InboxEntry
{
Time = Time.unscaledTime,
FromId = from,
Name = name,
Body = (body ?? "")
});
while (_inbox.Count > 20)
{
_inbox.RemoveAt(0);
}
}
public static void ClearInbox()
{
_inbox.Clear();
}
public static void Toast(string title, string message, NotificationType type)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: 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_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: 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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
Notify(new Notification
{
Title = NotificationText.op_Implicit(title),
Message = NotificationText.op_Implicit(message),
Type = type,
PopupLength = Mathf.Clamp(Settings.PopupDuration.Value, 1f, 30f),
ShowPopup = true,
SaveToMenu = false
});
}
private static void Notify(Notification n)
{
try
{
Notifier.Send(n);
}
catch (Exception ex)
{
ModMain.Log.Warning("Notifier failed: " + ex.Message);
}
}
}
public enum PresenceStatus
{
Unknown,
Offline,
Online,
InGame,
InLobby,
InYourLobby
}
public struct FriendPresence
{
public PresenceStatus Status;
public bool Joinable;
public ulong HostId;
public string Label;
}
public static class SteamPresence
{
public static bool SteamAvailable
{
get
{
try
{
return SteamClient.IsValid;
}
catch
{
return false;
}
}
}
public static FriendPresence Get(ulong platformId)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
if (Fusion.IsOnline(platformId))
{
return new FriendPresence
{
Status = PresenceStatus.InYourLobby,
Label = "in your lobby"
};
}
if (!SteamAvailable)
{
return new FriendPresence
{
Status = PresenceStatus.Unknown,
Label = "unknown"
};
}
try
{
Friend val = default(Friend);
((Friend)(ref val))..ctor(SteamId.op_Implicit(platformId));
if (((Friend)(ref val)).IsPlayingThisGame)
{
FriendGameInfo? gameInfo = ((Friend)(ref val)).GameInfo;
Lobby? obj;
if (!gameInfo.HasValue)
{
obj = null;
}
else
{
FriendGameInfo valueOrDefault = gameInfo.GetValueOrDefault();
obj = ((FriendGameInfo)(ref valueOrDefault)).Lobby;
}
Lobby? val2 = obj;
if (val2.HasValue)
{
ulong num = 0uL;
try
{
Lobby value = val2.Value;
num = SteamId.op_Implicit(((Lobby)(ref value)).Owner.Id);
}
catch
{
}
if (num != 0L)
{
return new FriendPresence
{
Status = PresenceStatus.InLobby,
Joinable = true,
HostId = num,
Label = "in a lobby"
};
}
return new FriendPresence
{
Status = PresenceStatus.InLobby,
Joinable = false,
Label = "in a lobby"
};
}
return new FriendPresence
{
Status = PresenceStatus.InGame,
Label = "in BONELAB"
};
}
if (((Friend)(ref val)).IsOnline)
{
return new FriendPresence
{
Status = PresenceStatus.Online,
Label = "online"
};
}
if (((Friend)(ref val)).IsFriend)
{
return new FriendPresence
{
Status = PresenceStatus.Offline,
Label = "offline"
};
}
return new FriendPresence
{
Status = PresenceStatus.Unknown,
Label = "not a Steam friend"
};
}
catch (Exception ex)
{
ModMain.Log.Warning("[LabLink] presence read failed: " + ex.Message);
return new FriendPresence
{
Status = PresenceStatus.Unknown,
Label = "unknown"
};
}
}
public static string JoinFriend(ulong platformId)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
if (!SteamAvailable)
{
return "Joining only works on the Steam version.";
}
try
{
Friend val = default(Friend);
((Friend)(ref val))..ctor(SteamId.op_Implicit(platformId));
if (!((Friend)(ref val)).IsPlayingThisGame)
{
return "They're not in BONELAB right now.";
}
FriendGameInfo? gameInfo = ((Friend)(ref val)).GameInfo;
Lobby? obj;
if (!gameInfo.HasValue)
{
obj = null;
}
else
{
FriendGameInfo valueOrDefault = gameInfo.GetValueOrDefault();
obj = ((FriendGameInfo)(ref valueOrDefault)).Lobby;
}
Lobby? val2 = obj;
if (!val2.HasValue)
{
return "They're not in a joinable lobby.";
}
Lobby value = val2.Value;
ulong num = 0uL;
try
{
num = SteamId.op_Implicit(((Lobby)(ref value)).Owner.Id);
}
catch
{
}
if (num == 0L)
{
try
{
((Lobby)(ref value)).Refresh();
}
catch
{
}
return "Fetching their lobby... press Join again in a moment.";
}
NetworkLayer layer = NetworkLayerManager.Layer;
SteamNetworkLayer val3 = (SteamNetworkLayer)(object)((layer is SteamNetworkLayer) ? layer : null);
if (val3 != null)
{
val3.JoinServer(SteamId.op_Implicit(num));
return "Joining " + ((Friend)(ref val)).Name + "...";
}
return "Joining requires the Steam network layer.";
}
catch (Exception ex)
{
ModMain.Log.Warning("[LabLink] join failed: " + ex.Message);
return "Couldn't join (see console).";
}
}
}
}
namespace LabLink.Net
{
public class LinkData : INetSerializable
{
public byte Kind;
public ulong FromId;
public string FromName;
public ulong ToId;
public string Body;
public LinkData()
{
FromName = "";
Body = "";
}
public int? GetSize()
{
return 17 + SizeExtensions.GetSize(FromName) + SizeExtensions.GetSize(Body);
}
public void Serialize(INetSerializer serializer)
{
serializer.SerializeValue(ref Kind);
serializer.SerializeValue(ref FromId);
serializer.SerializeValue(ref FromName);
serializer.SerializeValue(ref ToId);
serializer.SerializeValue(ref Body);
}
}
public class LinkHandler : ModuleMessageHandler
{
protected override void OnHandleMessage(ReceivedMessage received)
{
try
{
LinkData linkData = ((ReceivedMessage)(ref received)).ReadData<LinkData>();
if (linkData != null)
{
Social.OnReceive(linkData);
}
}
catch (Exception value)
{
ModMain.Log.Error($"[LabLink] failed to handle packet: {value}");
}
}
}
public enum LinkKind : byte
{
CapabilityPing,
CapabilityAck,
FriendRequest,
RequestAccept,
RequestDecline,
DirectMessage,
Unfriend
}
public class LinkModule : Module
{
public override string Name => "LabLink";
public override string Author => "Dynamic Team";
public override Version Version => new Version(1, 0, 0);
public override ConsoleColor Color => ConsoleColor.Green;
protected override void OnModuleRegistered()
{
ModuleMessageManager.RegisterHandler<LinkHandler>();
ModMain.Log.Msg("LabLink message handler registered.");
}
}
public static class LinkNet
{
public static void Send(LinkKind kind, ulong toId, string body = "")
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
if (!Fusion.HasServer)
{
return;
}
try
{
LinkData obj = new LinkData
{
Kind = (byte)kind,
FromId = Fusion.LocalPlatformId,
FromName = Fusion.LocalName(),
ToId = toId,
Body = (body ?? "")
};
MessageRoute val = default(MessageRoute);
((MessageRoute)(ref val))..ctor((RelayType)2, (NetworkChannel)0);
MessageRelay.RelayModule<LinkHandler, LinkData>(obj, val);
}
catch (Exception ex)
{
ModMain.Log.Warning($"[LabLink] send {kind} failed: {ex.Message}");
}
}
public static void Broadcast(LinkKind kind, string body = "")
{
Send(kind, 0uL, body);
}
}
}
namespace LabLink.Data
{
public class Friend
{
public ulong PlatformId { get; set; }
public string LastName { get; set; } = "";
public string Nickname { get; set; } = "";
public string Note { get; set; } = "";
public bool Favorite { get; set; }
public long AddedUnix { get; set; }
public string Display()
{
if (!string.IsNullOrEmpty(Nickname))
{
return Nickname;
}
if (!string.IsNullOrEmpty(LastName))
{
return LastName;
}
return $"Player {PlatformId}";
}
}
public class PendingRequest
{
public ulong PlatformId { get; set; }
public string LastName { get; set; } = "";
public long Unix { get; set; }
public string Display()
{
if (!string.IsNullOrEmpty(LastName))
{
return LastName;
}
return $"Player {PlatformId}";
}
}
public static class FriendStore
{
public sealed class StoreData
{
public List<Friend> Friends { get; set; } = new List<Friend>();
public List<ulong> Blocked { get; set; } = new List<ulong>();
public List<PendingRequest> Incoming { get; set; } = new List<PendingRequest>();
public List<PendingRequest> Outgoing { get; set; } = new List<PendingRequest>();
}
private static StoreData _data = new StoreData();
public static IReadOnlyList<Friend> Friends => _data.Friends;
public static IReadOnlyList<ulong> Blocked => _data.Blocked;
public static IReadOnlyList<PendingRequest> Incoming => _data.Incoming;
public static IReadOnlyList<PendingRequest> Outgoing => _data.Outgoing;
private static string FilePath()
{
string text;
try
{
text = Path.Combine(MelonEnvironment.UserDataDirectory, "LabLink");
}
catch
{
text = Path.Combine("UserData", "LabLink");
}
Directory.CreateDirectory(text);
return Path.Combine(text, "labllink.json");
}
public static void Load()
{
try
{
string path = FilePath();
if (File.Exists(path))
{
_data = JsonSerializer.Deserialize<StoreData>(File.ReadAllText(path)) ?? new StoreData();
}
}
catch (Exception ex)
{
ModMain.Log.Warning("Failed to load friends: " + ex.Message);
_data = new StoreData();
}
if (_data.Friends == null)
{
_data.Friends = new List<Friend>();
}
if (_data.Blocked == null)
{
_data.Blocked = new List<ulong>();
}
if (_data.Incoming == null)
{
_data.Incoming = new List<PendingRequest>();
}
if (_data.Outgoing == null)
{
_data.Outgoing = new List<PendingRequest>();
}
}
public static void Save()
{
try
{
string contents = JsonSerializer.Serialize(_data, new JsonSerializerOptions
{
WriteIndented = true
});
File.WriteAllText(FilePath(), contents);
}
catch (Exception ex)
{
ModMain.Log.Warning("Failed to save friends: " + ex.Message);
}
}
private static long Now()
{
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
public static Friend GetFriend(ulong id)
{
return _data.Friends.FirstOrDefault((Friend f) => f.PlatformId == id);
}
public static bool IsFriend(ulong id)
{
return GetFriend(id) != null;
}
public static bool IsBlocked(ulong id)
{
return _data.Blocked.Contains(id);
}
public static PendingRequest GetIncoming(ulong id)
{
return _data.Incoming.FirstOrDefault((PendingRequest r) => r.PlatformId == id);
}
public static PendingRequest GetOutgoing(ulong id)
{
return _data.Outgoing.FirstOrDefault((PendingRequest r) => r.PlatformId == id);
}
public static Friend AddFriend(ulong id, string name)
{
Friend friend = GetFriend(id);
if (friend == null)
{
friend = new Friend
{
PlatformId = id,
LastName = (name ?? ""),
AddedUnix = Now()
};
_data.Friends.Add(friend);
}
else if (!string.IsNullOrEmpty(name))
{
friend.LastName = name;
}
_data.Incoming.RemoveAll((PendingRequest r) => r.PlatformId == id);
_data.Outgoing.RemoveAll((PendingRequest r) => r.PlatformId == id);
Save();
return friend;
}
public static void RemoveFriend(ulong id)
{
_data.Friends.RemoveAll((Friend f) => f.PlatformId == id);
Save();
}
public static void Block(ulong id)
{
_data.Friends.RemoveAll((Friend f) => f.PlatformId == id);
_data.Incoming.RemoveAll((PendingRequest r) => r.PlatformId == id);
_data.Outgoing.RemoveAll((PendingRequest r) => r.PlatformId == id);
if (!_data.Blocked.Contains(id))
{
_data.Blocked.Add(id);
}
Save();
}
public static void Unblock(ulong id)
{
_data.Blocked.RemoveAll((ulong b) => b == id);
Save();
}
public static void AddIncoming(ulong id, string name)
{
PendingRequest incoming = GetIncoming(id);
if (incoming == null)
{
_data.Incoming.Add(new PendingRequest
{
PlatformId = id,
LastName = (name ?? ""),
Unix = Now()
});
}
else if (!string.IsNullOrEmpty(name))
{
incoming.LastName = name;
}
Save();
}
public static void RemoveIncoming(ulong id)
{
_data.Incoming.RemoveAll((PendingRequest r) => r.PlatformId == id);
Save();
}
public static void AddOutgoing(ulong id, string name)
{
if (GetOutgoing(id) == null)
{
_data.Outgoing.Add(new PendingRequest
{
PlatformId = id,
LastName = (name ?? ""),
Unix = Now()
});
}
Save();
}
public static void RemoveOutgoing(ulong id)
{
_data.Outgoing.RemoveAll((PendingRequest r) => r.PlatformId == id);
Save();
}
public static void UpdateName(ulong id, string name)
{
if (!string.IsNullOrEmpty(name))
{
Friend friend = GetFriend(id);
if (friend != null && friend.LastName != name)
{
friend.LastName = name;
Save();
}
}
}
}
}