You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClientState.cs 5.3 kB

7 years ago
7 years ago
7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace Discord.WebSocket
  6. {
  7. internal class ClientState
  8. {
  9. private const double AverageChannelsPerGuild = 10.22; //Source: Googie2149
  10. private const double AverageUsersPerGuild = 47.78; //Source: Googie2149
  11. private const double CollectionMultiplier = 1.05; //Add 5% buffer to handle growth
  12. private readonly ConcurrentDictionary<ulong, SocketChannel> _channels;
  13. private readonly ConcurrentDictionary<ulong, SocketDMChannel> _dmChannels;
  14. private readonly ConcurrentDictionary<ulong, SocketGuild> _guilds;
  15. private readonly ConcurrentDictionary<ulong, SocketGlobalUser> _users;
  16. private readonly ConcurrentHashSet<ulong> _groupChannels;
  17. internal IReadOnlyCollection<SocketChannel> Channels => _channels.ToReadOnlyCollection();
  18. internal IReadOnlyCollection<SocketDMChannel> DMChannels => _dmChannels.ToReadOnlyCollection();
  19. internal IReadOnlyCollection<SocketGroupChannel> GroupChannels => _groupChannels.Select(x => GetChannel(x) as SocketGroupChannel).ToReadOnlyCollection(_groupChannels);
  20. internal IReadOnlyCollection<SocketGuild> Guilds => _guilds.ToReadOnlyCollection();
  21. internal IReadOnlyCollection<SocketGlobalUser> Users => _users.ToReadOnlyCollection();
  22. internal IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels =>
  23. _dmChannels.Select(x => x.Value as ISocketPrivateChannel).Concat(
  24. _groupChannels.Select(x => GetChannel(x) as ISocketPrivateChannel))
  25. .ToReadOnlyCollection(() => _dmChannels.Count + _groupChannels.Count);
  26. public ClientState(int guildCount, int dmChannelCount)
  27. {
  28. double estimatedChannelCount = guildCount * AverageChannelsPerGuild + dmChannelCount;
  29. double estimatedUsersCount = guildCount * AverageUsersPerGuild;
  30. _channels = new ConcurrentDictionary<ulong, SocketChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedChannelCount * CollectionMultiplier));
  31. _dmChannels = new ConcurrentDictionary<ulong, SocketDMChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(dmChannelCount * CollectionMultiplier));
  32. _guilds = new ConcurrentDictionary<ulong, SocketGuild>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier));
  33. _users = new ConcurrentDictionary<ulong, SocketGlobalUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier));
  34. _groupChannels = new ConcurrentHashSet<ulong>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(10 * CollectionMultiplier));
  35. }
  36. internal SocketChannel GetChannel(ulong id)
  37. {
  38. if (_channels.TryGetValue(id, out SocketChannel channel))
  39. return channel;
  40. return null;
  41. }
  42. internal SocketDMChannel GetDMChannel(ulong userId)
  43. {
  44. if (_dmChannels.TryGetValue(userId, out SocketDMChannel channel))
  45. return channel;
  46. return null;
  47. }
  48. internal void AddChannel(SocketChannel channel)
  49. {
  50. _channels[channel.Id] = channel;
  51. switch (channel)
  52. {
  53. case SocketDMChannel dmChannel:
  54. _dmChannels[dmChannel.Recipient.Id] = dmChannel;
  55. break;
  56. case SocketGroupChannel groupChannel:
  57. _groupChannels.TryAdd(groupChannel.Id);
  58. break;
  59. }
  60. }
  61. internal SocketChannel RemoveChannel(ulong id)
  62. {
  63. if (_channels.TryRemove(id, out SocketChannel channel))
  64. {
  65. switch (channel)
  66. {
  67. case SocketDMChannel dmChannel:
  68. _dmChannels.TryRemove(dmChannel.Recipient.Id, out var _);
  69. break;
  70. case SocketGroupChannel _:
  71. _groupChannels.TryRemove(id);
  72. break;
  73. }
  74. return channel;
  75. }
  76. return null;
  77. }
  78. internal SocketGuild GetGuild(ulong id)
  79. {
  80. if (_guilds.TryGetValue(id, out SocketGuild guild))
  81. return guild;
  82. return null;
  83. }
  84. internal void AddGuild(SocketGuild guild)
  85. {
  86. _guilds[guild.Id] = guild;
  87. }
  88. internal SocketGuild RemoveGuild(ulong id)
  89. {
  90. if (_guilds.TryRemove(id, out SocketGuild guild))
  91. return guild;
  92. return null;
  93. }
  94. internal SocketGlobalUser GetUser(ulong id)
  95. {
  96. if (_users.TryGetValue(id, out SocketGlobalUser user))
  97. return user;
  98. return null;
  99. }
  100. internal SocketGlobalUser GetOrAddUser(ulong id, Func<ulong, SocketGlobalUser> userFactory)
  101. {
  102. return _users.GetOrAdd(id, userFactory);
  103. }
  104. internal SocketGlobalUser RemoveUser(ulong id)
  105. {
  106. if (_users.TryRemove(id, out SocketGlobalUser user))
  107. return user;
  108. return null;
  109. }
  110. }
  111. }