• gm_bitflags - Convenient flag system.
    9 replies, posted
[release] [highlight]What is this and how is this useful?![/highlight] Basically, compressed [I]booleans[/I]. [I]Boolean[/I] variables, which are used to declare a variable with a value of either [I]true[/I] or [I]false[/I], consume 1 byte of memory. But in actuality, you only need 1 bit. A bit (contraction of [I]binary digit[/I]) 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 <code> end ... end ) [/lua] Now, you may ask: "How is this useful?". The answer is simple. With this module, you can send [B]4 bytes[/B] containing [B]32 bits[/B] instead of 32 booleans ([B]32 bytes[/B]). [/release] [release] [highlight]Functions[/highlight] [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] [highlight]Examples[/highlight] First, we have to define the flags somewhere. In gamemodes, [I]shared.lua[/I] 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] [highlight]Download & Source[/highlight] Latest release date: [I]29/01/2012[/I]. [URL="http://dl.dropbox.com/u/59073685/gm_bitflags/gm_bitflags.dll"]Click me to download![/URL] [URL="http://dl.dropbox.com/u/59073685/gm_bitflags/gm_bitflags.cpp"]gm_bitflags.cpp[/URL] [URL="http://dl.dropbox.com/u/59073685/gm_bitflags/gm_bitflags.h"]gm_bitflags.h[/URL] [/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:
[QUOTE=Panto;34451447]Nice work, raBBish. Your code renders my module completely obsolete. :suicide:[/QUOTE] Sorry [img]http://www.facepunch.com/fp/emoot/shobon.gif[/img] Although you still need to release the source. All releases here need it.
Alright, done.
[QUOTE=raBBish;34451180]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.[/QUOTE] Holy shit this is really useful, thanks!
Sorry, you need to Log In to post a reply to this thread.