diff --git a/src/Discord.Net/DiscordClient.API.cs b/src/Discord.Net/DiscordClient.API.cs index de9e94125..038f017c1 100644 --- a/src/Discord.Net/DiscordClient.API.cs +++ b/src/Discord.Net/DiscordClient.API.cs @@ -547,8 +547,8 @@ namespace Discord await _api.SetChannelPermissions(channel.Id, targetId, targetType, allowValue, denyValue); if (perms != null) { - perms.Allow.SetRawValue(allowValue); - perms.Deny.SetRawValue(denyValue); + perms.Allow.SetRawValueInternal(allowValue); + perms.Deny.SetRawValueInternal(denyValue); } else { diff --git a/src/Discord.Net/Models/Member.cs b/src/Discord.Net/Models/Member.cs index 57b85229d..2b313510e 100644 --- a/src/Discord.Net/Models/Member.cs +++ b/src/Discord.Net/Models/Member.cs @@ -177,7 +177,7 @@ namespace Discord if (!_permissions.TryGetValue(channelId, out permissions)) return; uint newPermissions = 0x0; uint oldPermissions = permissions.RawValue; - + if (UserId == server.OwnerId) newPermissions = PackedChannelPermissions.All.RawValue; else @@ -199,12 +199,12 @@ namespace Discord } - permissions.SetRawValue(newPermissions); + permissions.SetRawValueInternal(newPermissions); if (permissions.General_ManagePermissions) - permissions.SetRawValue(PackedChannelPermissions.All.RawValue); + permissions.SetRawValueInternal(PackedChannelPermissions.All.RawValue); else if (server.DefaultChannelId == channelId) - permissions.Text_ReadMessages = true; + permissions.SetBitInternal(PackedPermissions.Text_ReadMessagesBit, true); if (permissions.RawValue != oldPermissions) channel.InvalidMembersCache(); diff --git a/src/Discord.Net/Models/PackedPermissions.cs b/src/Discord.Net/Models/PackedPermissions.cs index 6bdc0a49f..4ddc579e1 100644 --- a/src/Discord.Net/Models/PackedPermissions.cs +++ b/src/Discord.Net/Models/PackedPermissions.cs @@ -17,15 +17,15 @@ namespace Discord public PackedServerPermissions(uint rawValue = 0) : base(rawValue) { } /// If True, a user may ban users from the server. - public bool General_BanMembers { get { return GetBit(2); } set { SetBit(2, value); } } + public bool General_BanMembers { get { return GetBit(General_BanMembersBit); } set { SetBit(General_BanMembersBit, value); } } /// If True, a user may kick users from the server. - public bool General_KickMembers { get { return GetBit(3); } set { SetBit(3, value); } } + public bool General_KickMembers { get { return GetBit(General_KickMembersBit); } set { SetBit(General_KickMembersBit, value); } } /// If True, a user may adjust roles. This also implictly grants all other permissions. - public bool General_ManageRoles { get { return GetBit(4); } set { SetBit(4, value); } } + public bool General_ManageRoles { get { return GetBit(General_ManagePermissionsBit); } set { SetBit(General_ManagePermissionsBit, value); } } /// If True, a user may create, delete and modify channels. - public bool General_ManageChannels { get { return GetBit(5); } set { SetBit(5, value); } } + public bool General_ManageChannels { get { return GetBit(General_ManageChannelBit); } set { SetBit(General_ManageChannelBit, value); } } /// If True, a user may adjust server properties. - public bool General_ManageServer { get { return GetBit(6); } set { SetBit(6, value); } } + public bool General_ManageServer { get { return GetBit(General_ManageServerBit); } set { SetBit(General_ManageServerBit, value); } } public PackedServerPermissions Copy() => new PackedServerPermissions(RawValue); } @@ -45,15 +45,36 @@ namespace Discord public PackedChannelPermissions(uint rawValue = 0) : base(rawValue) { } /// If True, a user may adjust permissions. This also implictly grants all other permissions. - public bool General_ManagePermissions { get { return GetBit(4); } set { SetBit(4, value); } } + public bool General_ManagePermissions { get { return GetBit(General_ManagePermissionsBit); } set { SetBit(General_ManagePermissionsBit, value); } } /// If True, a user may create, delete and modify this channel. - public bool General_ManageChannel { get { return GetBit(5); } set { SetBit(5, value); } } + public bool General_ManageChannel { get { return GetBit(General_ManageChannelBit); } set { SetBit(General_ManageChannelBit, value); } } public PackedChannelPermissions Copy() => new PackedChannelPermissions(RawValue); } public abstract class PackedPermissions { + internal const byte General_CreateInstantInviteBit = 0; + internal const byte General_BanMembersBit = 1; + internal const byte General_KickMembersBit = 2; + internal const byte General_ManagePermissionsBit = 3; + internal const byte General_ManageChannelBit = 4; + internal const byte General_ManageServerBit = 5; + internal const byte Text_ReadMessagesBit = 10; + internal const byte Text_SendMessagesBit = 11; + internal const byte Text_SendTTSMessagesBit = 12; + internal const byte Text_ManageMessagesBit = 13; + internal const byte Text_EmbedLinksBit = 14; + internal const byte Text_AttachFilesBit = 15; + internal const byte Text_ReadMessageHistoryBit = 16; + internal const byte Text_MentionEveryoneBit = 17; + internal const byte Voice_ConnectBit = 20; + internal const byte Voice_SpeakBit = 21; + internal const byte Voice_MuteMembersBit = 22; + internal const byte Voice_DeafenMembersBit = 23; + internal const byte Voice_MoveMembersBit = 24; + internal const byte Voice_UseVoiceActivationBit = 25; + private bool _isLocked; private uint _rawValue; public uint RawValue @@ -70,64 +91,61 @@ namespace Discord protected PackedPermissions(uint rawValue) { _rawValue = rawValue; } /// If True, a user may create invites. - public bool General_CreateInstantInvite { get { return GetBit(1); } set { SetBit(1, value); } } - //Bit 2 = BanMembers/??? - //Bit 3 = KickMembers/??? - //Bit 4 = ManageRoles/ManagePermissions - //Bit 5 = ManageChannels/ManageChannel - //Bit 6 = ManageServer/??? - - //4 Unused + public bool General_CreateInstantInvite { get { return GetBit(General_CreateInstantInviteBit); } set { SetBit(General_CreateInstantInviteBit, value); } } /// If True, a user may join channels. - public bool Text_ReadMessages { get { return GetBit(11); } set { SetBit(11, value); } } + public bool Text_ReadMessages { get { return GetBit(Text_ReadMessagesBit); } set { SetBit(Text_ReadMessagesBit, value); } } /// If True, a user may send messages. - public bool Text_SendMessages { get { return GetBit(12); } set { SetBit(12, value); } } + public bool Text_SendMessages { get { return GetBit(Text_SendMessagesBit); } set { SetBit(Text_SendMessagesBit, value); } } /// If True, a user may send text-to-speech messages. - public bool Text_SendTTSMessages { get { return GetBit(13); } set { SetBit(13, value); } } + public bool Text_SendTTSMessages { get { return GetBit(Text_SendTTSMessagesBit); } set { SetBit(Text_SendTTSMessagesBit, value); } } /// If True, a user may delete messages. - public bool Text_ManageMessages { get { return GetBit(14); } set { SetBit(14, value); } } + public bool Text_ManageMessages { get { return GetBit(Text_ManageMessagesBit); } set { SetBit(Text_ManageMessagesBit, value); } } /// If True, Discord will auto-embed links sent by this user. - public bool Text_EmbedLinks { get { return GetBit(15); } set { SetBit(15, value); } } + public bool Text_EmbedLinks { get { return GetBit(Text_EmbedLinksBit); } set { SetBit(Text_EmbedLinksBit, value); } } /// If True, a user may send files. - public bool Text_AttachFiles { get { return GetBit(16); } set { SetBit(16, value); } } + public bool Text_AttachFiles { get { return GetBit(Text_AttachFilesBit); } set { SetBit(Text_AttachFilesBit, value); } } /// If True, a user may read previous messages. - public bool Text_ReadMessageHistory { get { return GetBit(17); } set { SetBit(17, value); } } + public bool Text_ReadMessageHistory { get { return GetBit(Text_ReadMessageHistoryBit); } set { SetBit(Text_ReadMessageHistoryBit, value); } } /// If True, a user may mention @everyone. - public bool Text_MentionEveryone { get { return GetBit(18); } set { SetBit(18, value); } } - - //2 Unused + public bool Text_MentionEveryone { get { return GetBit(Text_MentionEveryoneBit); } set { SetBit(Text_MentionEveryoneBit, value); } } /// If True, a user may connect to a voice channel. - public bool Voice_Connect { get { return GetBit(21); } set { SetBit(21, value); } } + public bool Voice_Connect { get { return GetBit(Voice_ConnectBit); } set { SetBit(Voice_ConnectBit, value); } } /// If True, a user may speak in a voice channel. - public bool Voice_Speak { get { return GetBit(22); } set { SetBit(22, value); } } + public bool Voice_Speak { get { return GetBit(Voice_SpeakBit); } set { SetBit(Voice_SpeakBit, value); } } /// If True, a user may mute users. - public bool Voice_MuteMembers { get { return GetBit(23); } set { SetBit(23, value); } } + public bool Voice_MuteMembers { get { return GetBit(Voice_MuteMembersBit); } set { SetBit(Voice_MuteMembersBit, value); } } /// If True, a user may deafen users. - public bool Voice_DeafenMembers { get { return GetBit(24); } set { SetBit(24, value); } } + public bool Voice_DeafenMembers { get { return GetBit(Voice_DeafenMembersBit); } set { SetBit(Voice_DeafenMembersBit, value); } } /// If True, a user may move other users between voice channels. - public bool Voice_MoveMembers { get { return GetBit(25); } set { SetBit(25, value); } } + public bool Voice_MoveMembers { get { return GetBit(Voice_MoveMembersBit); } set { SetBit(Voice_MoveMembersBit, value); } } /// If True, a user may use voice activation rather than push-to-talk. - public bool Voice_UseVoiceActivation { get { return GetBit(26); } set { SetBit(26, value); } } - - //6 Unused + public bool Voice_UseVoiceActivation { get { return GetBit(Voice_UseVoiceActivationBit); } set { SetBit(Voice_UseVoiceActivationBit, value); } } internal void Lock() => _isLocked = true; - internal void SetRawValue(uint rawValue) - { - //Bypasses isLocked for API changes. - _rawValue = rawValue; - } - protected bool GetBit(int pos) => ((_rawValue >> (pos - 1)) & 1U) == 1; + protected bool GetBit(int pos) => ((_rawValue >> pos) & 1U) == 1; protected void SetBit(int pos, bool value) { if (_isLocked) throw new InvalidOperationException("Unable to edit cached permissions directly, use Copy() to make an editable copy."); if (value) - _rawValue |= (1U << (pos - 1)); + _rawValue |= (1U << pos); else - _rawValue &= ~(1U << (pos - 1)); + _rawValue &= ~(1U << pos); + } + + //Bypasses isLocked for API changes. + internal void SetBitInternal(int pos, bool value) + { + if (value) + _rawValue |= (1U << pos); + else + _rawValue &= ~(1U << pos); + } + internal void SetRawValueInternal(uint rawValue) + { + _rawValue = rawValue; } } } diff --git a/src/Discord.Net/Models/Role.cs b/src/Discord.Net/Models/Role.cs index 106945fc1..50c889e06 100644 --- a/src/Discord.Net/Models/Role.cs +++ b/src/Discord.Net/Models/Role.cs @@ -65,7 +65,7 @@ namespace Discord if (model.Color != null) Color.SetRawValue(model.Color.Value); if (model.Permissions != null) - Permissions.SetRawValue(model.Permissions.Value); + Permissions.SetRawValueInternal(model.Permissions.Value); foreach (var member in Members) member.UpdatePermissions();