Understanding Bitwise Operators In Lua
Written by creekie
Garry's Mod
Permissions
Bitwise
Bitwise Operators
Hey there! Back in September whilst I was working on my organisation system I had to somehow create a permission system with bit flags. (The bit flags weren't a requirement, it was a personal one.)
So I started Googling on how I'd approach this. If you're anything like me, I thought it'd be a hard to understand subject involving lots of math. But as it turns out, it's much easier than that.
Bit flags permission system in GLua
GLua includes Lua BitOp, so that's what I'm using. There's a native implementation of bitwise operators since Lua 5.3.
Config
XYZ_ORGS.Config.Permissions = {
-- Thanks https://gist.github.com/ThomasBurleson/0ae1e9e30d9397da7110e595d21e18e3 <3
ALL = bit.lshift(1, 0),
INVITE = bit.lshift(1, 1),
KICK = bit.lshift(1, 2),
--BAN = bit.lshift(1, 3),
MANAGE_UPGRADES = bit.lshift(1, 3),
WITHDRAW = bit.lshift(1, 4),
DEPOSIT = bit.lshift(1, 5),
MANAGE_PERMISSIONS = bit.lshift(1, 6),
}
As you can see I defined 6 permissions. All, which is totally unneeded but I left it in. Invite, which is 1 shifted left by 1 bit. Kick, which is 1 shifted left by 2 bits. Manage Upgrades, which is 1 shifted left by 3 bits. I think you get the picture.
So how do we actually use this to check if someone has access to something? Again, it's not that hard.
function XYZ_ORGS.Core.HasPerms(perms, permtocheck, ply, dontNotify)
if bit.band(perms, bit.bor(XYZ_ORGS.Config.Permissions.ALL, XYZ_ORGS.Config.Permissions[permtocheck])) == 0 then
if SERVER and not dontNotify then
XYZShit.Msg("Organizations", XYZ_ORGS.Config.Color, "No permission.", ply)
end
return false
end
return true
end
Let's look at what this function does:
First of all, bit.band will perform a bitwise AND on the variable 'perms' and the result of the bit.bor call. So what does the bit.bor do? It performs a bitwise OR on multiple values, so in this case what I'm doing is checking if they either have the ALL permission, or the 'permtocheck' permission. The function then checks if the result is 0, meaning 'perms' doesn't have the permission of ALL, nor 'permtocheck'. If yes, it's going to notify the user (unless dontNotify is true). It then returns either true, or false.
Using this function
Let's use this function in an example:
net.Receive("xyz_orgs_withdraw", function(_, ply)
-- ...
if not XYZ_ORGS.Core.HasPerms(plyorg.roles[plyorg.members[ply:SteamID64()]].perms, 'WITHDRAW', ply) then return end
In this example, we check if HasPerms returns false by feeding it the member's permission value, and checking it against the 'WITHDRAW' permission. If they do not have permission, it will return and they will automatically be notified by the HasPerms function.
I hope this helped you understand Bit Flags. If not, feel free to let me know in the comments.
A special thanks to the following resources, which helped me understand this myself;
This blog post's original markdown can be downloaded here.