gm_bitflags - Convenient flag system.

[release]


What is this and how is this useful?!

Basically, compressed booleans. Boolean variables, which are used to declare a variable with a value of either true or false, consume 1 byte of memory. But in actuality, you only need 1 bit. A bit (contraction of binary digit) can only have two possible values, usually denoted by 0 and 1.

This is very useful if, for example, you have devised an quite complex admin system and now want to send admin flags/rights/allowances from server to client. Let’s say you allow the admin to kick, ban, freeze, slap etc players. Usually, you’d do this.
[lua]
–Send from server.
umsg.Start( “AdminFlags”, ply )
umsg.Bool( ply:CanKick() )
umsg.Bool( ply:CanBan() )
umsg.Bool( ply:CanFreeze() )
umsg.Bool( ply:CanSlap() )
umsg.End()

–Receive on client.
usermessage.Hook( “AdminFlags”, function( data )
data:ReadBool() --CanKick.
data:ReadBool() --CanBan.

end )
[/lua]

But using bitflags, you can do this.
[lua]
–Init flags.
local flags = 0
flags = bf.FlagsOn( flags, { canKick, canBan, canSlap, canFreeze } )

–Send from server.
umsg.Start( “AdminFlags”, ply )
umsg.Short( flags )
umsg.End()

–Receive on client.
usermessage.Hook( “AdminFlags”, function( data )
local flags = data:ReadShort()
if( bf.FlagsEnabled( flags, { } ) ) then

end

end )
[/lua]

Now, you may ask: “How is this useful?”. The answer is simple. With this module, you can send 4 bytes containing 32 bits instead of 32 booleans (32 bytes).
[/release]
[release]


Functions

[lua]
bf.FlagOn( number, flag ) --Enables flag.
bf.FlagsOn( number, table ) --Enables flags.

bf.FlagOff( number, flag ) --Disables flag.
bf.FlagsOff( number, table ) --Disables flags.

bf.FlagToggle( number, flag ) --Toggles flag.
bf.FlagsToggle( number, table ) --Toggles flags.

bf.FlagEnabled( number, flag ) --Returns true if flag is enabled.
bf.FlagsEnabled( number, table ) --Returns true if flags are enabled.
[/lua]
[/release]
[release]


Examples

First, we have to define the flags somewhere. In gamemodes, shared.lua is a good place to do that.
[lua]
local AdminFlags = { } --Each flag value MUST be a power of two. Maximum value: 2^32.
AdminFlags.TrialAdmin = 1 --2^0
AdminFlags.BasicAdmin = 2 --2^1
AdminFlags.SuperAdmin = 4 --2^2
AdminFlags.CanSlap = 8 --2^3
AdminFlags.CanFreeze = 16 --2^4
AdminFlags.CanChangeMap = 32 --2^5
[/lua]

Example #1.
[lua]
require( ‘bitflags’ )

ply.AdminFlags = 0 --Reset all flags.
ply.AdminFlags = bf.FlagsOn( ply.AdminFlags, { AdminFlags.BasicAdmin, AdminFlags.CanSlap, AdminFlags.CanFreeze } )
print( bf.FlagsEnabled( ply.AdminFlags, { AdminFlags.SuperAdmin, AdminFlags.CanSlap, AdminFlags.CanFreeze } ) )

ply.AdminFlags = bf.FlagOn( bf.FlagOff( ply.AdminFlags, AdminFlags.BasicAdmin ), AdminFlags.SuperAdmin )
print( bf.FlagsEnabled( ply.AdminFlags, { AdminFlags.SuperAdmin, AdminFlags.CanSlap, AdminFlags.CanFreeze } ) )

–Output:
–false
–true
[/lua]

Example #2.
[lua]
require( ‘bitflags’ )

ply.AdminFlags = 0 --Reset all flags.
ply.AdminFlags = bf.FlagOn( ply.AdminFlags, AdminFlags.BasicAdmin )
ply.AdminFlags = bf.FlagOn( ply.AdminFlags, AdminFlags.CanSlap )

if( bf.FlagEnabled( ply.AdminFlags, AdminFlags.BasicAdmin ) ) then
if( bf.FlagEnabled( ply.AdminFlags, AdminFlags.CanSlap ) ) then
print( “I’mma slap yo ass.” )
end

if( bf.FlagEnabled( ply.AdminFlags, AdminFlags.CanFreeze ) ) then
	print( "I'mma freeze yo ass." )
end

end

–Output:
–I’mma slap yo ass.
[/lua]
[/release]
[release]


Download & Source

Latest release date: 29/01/2012.
Click me to download!

gm_bitflags.cpp
gm_bitflags.h
[/release]

Nice! I will definitely be using this in my admin mod! Quality release bro!

Why do you need a binary module for this?

GMod’s lua is missing the bitwise NOT and bitwise XOR. Besides, writing this…
[lua]
if( bf.FlagsEnabled( epicshit, { Flags.ConditionOne, Flags.ConditionTwo, … } ) ) then
<code>
end
[/lua]

… looks a lot cleaner than this.
[lua]
if( (epicshit & (Flags.ConditionOne | Flags.ConditionTwo | …)) == (Flags.ConditionOne | Flags.ConditionTwo | …) ) then
<code>
end
[/lua]

Nice work, though a binary module for something that requires… about 30 lines of Lua is overkill.

[lua]local pairs = pairs

module “flag”

function set( bits, … )
for _, b in pairs( { … } ) do
bits = bits | b
end
return bits
end

function is_set( bits, … )
for _, b in pairs( { … } ) do
if bits & b ~= b then return false end
end
return true
end

function unset( bits, … )
for _, b in pairs( { … } ) do
if bits & b == b then
bits = bits - b
end
end
return bits
end[/lua]

[lua]require “flag”

local stuff = STUFF1 | STUFF2
if flag.is_set( stuff, STUFF1, STUFF3 ) then
– Do stuff
end
stuff = flag.unset( stuff, STUFF2 )[/lua]

[editline]29th January 2012[/editline]

Also, you need to release the source. It’s required.

It’s not too hard to implement band/bnot /xor in lua.

Nice work, raBBish. Your code renders my module completely obsolete. :suicide:

Sorry

http://www.facepunch.com/fp/emoot/shobon.gif

Although you still need to release the source. All releases here need it.

Alright, done.

Holy shit this is really useful, thanks!