• UtilX -- Extending GLua -- Need community input
    371 replies, posted
The more generic, the more useful. [lua] function utilx.find(t, func) local matches = {} for k,v in pairs(t) do if func(v) then table.insert(matches, v) end end return matches end [/lua] [lua] for k,v in pairs(utilx.find(player.GetAll(), function(p) return string.match(p:Nick(), "Ownage96") end)) do print(v:Nick().." is a cactus.") end [/lua] [b]Edit:[/b] Thanks, Tobba
if matches(v) then Don't you mean to use func there?
For those of you who didn't see it in the WAYWO thread: [url]http://entoros.pastebin.com/z8W13euC[/url]
Here's my helper function for finding players: [lua]function findTarget(plyID) if type(plyID) == "string" then local isSteamID = string.match(plyID, "^STEAM_") for _, v in ipairs(player.GetAll()) do if ValidEntity(v) then if isSteamID then if v:SteamID() == plyID then return v end else local name = string.lower(plyID) if v:UniqueID() == plyID || string.match(string.lower(v:GetName()), name) then return v end end end end elseif type(plyID) == "number" then local ply = Player(plyID) if ValidEntity(ply) then return ply end end end[/lua]
I'm not sure if this has been posted yet, but whatever. A simple function to flip teams with an option of killsilent and a default team for any other teams to switch to. This would be better in the team library in my opinion. [lua] function utilx.FlipTeams( teamID1, teamID2, teamDefault, bKill ) for _, ply in pairs( player.GetAll() ) do if IsValid(ply) then local couldKill = true if teamDefault then ply:SetTeam( teamDefault ) elseif ply:Team() == teamID1 then ply:SetTeam( teamID2 ) elseif ply:Team() == teamID2 then ply:SetTeam( teamID1 ) else couldKill = false end if bKill and couldKill and ply:Alive() then ply:KillSilent() end end end end[/lua]
I don't know if this has been done already but it's same as expression2s findPlayerByName function. [code] function utilx.FindPlayerByName(stringname) for k,v in pairs(player.GetAll()) do if v:Name() == stringname then return v end end end [/code]
[lua] function util.PrecacheTableRecursive( t ) for k, v in pairs( t ) do if type(v) == "table" then util.PrecacheTableRecursive( v ) elseif type(v) == "string" then local ext = v:sub( -4 ) local isValidSound = (ext == ".wav" or ext == ".mp3") local isValidModel = (ext == ".mdl" and util.IsValidModel(v)) if isValidSound then util.PrecacheSound( v ) elseif isValidModel then util.PrecacheModel( v ) else print( "Attempted to precache '"..tostring(v).."' which is not a valid "..((isValidSound and "sound") or (isValidModel and "model") or "string")..". Skipping..." ) end else print( "Attempted to precache '"..tostring(v).."' which is not a valid string. Skipping..." ) end end end [/lua] Recursively precaches a table of sounds and/or models. Might need some tweaking.
[QUOTE=grea$emonkey;25658381][lua] function util.PrecacheTableRecursive( t ) for k, v in pairs( t ) do if type(v) == "table" then util.PrecacheTableRecursive( v ) elseif type(v) == "string" then local ext = v:sub( -4 ) local isValidSound = (ext == ".wav" or ext == ".mp3") local isValidModel = (ext == ".mdl" and util.IsValidModel(v)) if isSound then util.PrecacheSound( v ) elseif isModel then util.PrecacheModel( v ) else print( "Attempted to precache '"..tostring(v).."' which is not a valid "..((isSound and "sound") or isModel and "model")..". Skipping..." ) end else print( "Attempted to precache '"..tostring(v).."' which is not a valid string. Skipping..." ) end end end [/lua] Recursively precaches a table of sounds and/or models. Might need some tweaking.[/QUOTE] Looks great. Is there anything in here that can match a table value like when you do table.remove(k) to the string/entity that's in the table? This is from 2 different tables.
[QUOTE=grea$emonkey;25658381]-code- Recursively precaches a table of sounds and/or models. Might need some tweaking.[/QUOTE] You're using isSound and isModel, but you've only defined isValidSound and isValidModel.
[QUOTE=raBBish;25658584]You're using isSound and isModel, but you've only defined isValidSound and isValidModel.[/QUOTE] Oops, haha my bad. [editline]26th October 2010[/editline] Fixed. Like I said, may need tweaking.
Couple functions I made when I was bored (inspired by Ruby) Unfortunately they both only support tables with numbered tables. [lua]function utilx.TableFlatten( tbl, new ) new = new or {} for k,v in ipairs( tbl ) do if type( v ) == "table" then utilx.TableFlatten( v, new ) else table.insert( new, v ) end end return new end function utilx.TableUnique( tbl ) local new = {} local done = {} for k,v in ipairs( tbl ) do if not done[v] then table.insert( new, v ) done[v] = true end end return new end[/lua] [url]http://codepad.org/dhk06oKx[/url]
from the WAYWO thread: [lua] function utilx.Check(variable, ...) local name = debug.getinfo(2, "n").name local func = debug.getinfo(2, "f").func local types = {...} local allowed = "" local matched = false for key, value in ipairs(types) do if #types ~= key then allowed = allowed .. value .. " or " else allowed = allowed .. value end if type(variable) == value then matched = true end end local arg = "???" for i=1, math.huge do local key, value = debug.getlocal(2, i) if not key then break end if value == variable then arg = i break end end if not matched then error(("bad argument #%s to '%s' (%s expected, got %s)"):format(arg, name, allowed, type(typ)), 3) end end [/lua] [lua] function Hello( str, entity, hello ) utilx.Check(str, "string") utilx.Check(entity, "Entity") utilx.Check(hello, "Player", "Entity") end Hello("hey", Entity(3), Entity(1)) [/lua] output goes like this: [code] [@addons\autorun\lua\check.lua:42] bad argument #2 to 'Hello' (Entity expected, got Player) [@addons\autorun\lua\check.lua:42] bad argument #3 to 'Hello' (Player or Entity expected, got nil) [/code] if the arg types are wrong in Hello The only problem with this is getting the local from the function you're checking and matching it against the variable in the check function. If you are calling a function with the number "5" in two args, and the second arg is wrong it will pick the first arg that matches that value and say arg #1 is wrong instead of #2.
[lua] function utilx.Crash(ply) ply:SendLua"cam.End3D()" end [/lua] :downs:
Add overloading to lua. [lua] --[[ local tblTest = { [{"string","number","player"}] = function (strName,numID,objPl) end, [{"string","table"}] = function (strName,tbl) end, [{"string","number"}] = function (strName,num) end } local tblOptimized = { ["string"] = { ["number"] = { ["player"] = funcCallback, ["nil"] = funcCallback }, ["table"] = funcCallback } } how it gets the function: tblOptimized["string"]["number"]["player"](str,num,pl, ...) --accumulated/dissipated table accessing ofcourse (or it would probably error) ]] function Overload(tblSetup,funcDefault_or_bNoDefault) local tblOverload = {} for tblParams, funcCallback in pairs(tblSetup) do local tblCurrent = tblOverload for i=1, #tblParams do local strType = tblParams[i] tblCurrent[strType] = tblCurrent[strType] or {} tblCurrent = tblCurrent[strType] end tblCurrent["nil"] = funcCallback end if type(funcDefault_or_bNoDefault) == "function" then return function (...) local tblParams, tblLast, numParam = {...}, tblOverload, 1 while true do local strType = type(tblParams[numParam]) local vNext = tblLast[strType] if type(vNext) == "function" then local bOk, valReturn = pcall(vNext,...) if not bOk then error(valReturn,2) end return valReturn elseif type(vNext) == "table" then tblLast = tblLast[strType] numParam = numParam + 1 else local bOk, valReturn = pcall(funcDefault_or_bNoDefault,...) if not bOk then error(valReturn,2) end return valReturn end end end elseif type(funcDefault_or_bNoDefault) == "boolean" and funcDefault_or_bNoDefault then return function (...) local tblParams, tblLast, numParam = {...}, tblOverload, 1 while true do local strType = type(tblParams[numParam]) local vNext = tblLast[strType] if type(vNext) == "function" then local bOk, valReturn = pcall(vNext,...) if not bOk then error(valReturn,2) end return valReturn elseif type(vNext) == "table" then tblLast = tblLast[strType] numParam = numParam + 1 else local bOk, valReturn = pcall(tblLast["nil"],...) if not bOk then error(valReturn,2) end return valReturn end end end end return function (...) local tblParams, tblLast, numParam = {...}, tblOverload, 1 while true do local strType = type(tblParams[numParam]) local vNext = tblLast[strType] if type(vNext) == "function" then local bOk, valReturn = pcall(vNext,...) if not bOk then error(valReturn,2) end return valReturn elseif type(vNext) == "table" then tblLast = tblLast[strType] numParam = numParam + 1 else return nil end end end end [/lua] I get bored sometimes.
I'm using this in my Trooper Hack, was actually disappointed and surprised at the same time to discover there is no function for this. [lua] function utilx.GetPlayerID( ply ) for k,v in pairs ( player.GetAll() ) do if v == ply then return k end end end [/lua]
Becuse ply:EntIndex() is better, and works perfectly fine
Sorry if there is already something in this like that, but this has been useful to more more than once: [lua]function utilx.SimplifyPath(Path) local Array = string.Explode("/", Path) local NewArray = {} for _, V in pairs(Array) do if V == ".." then if #NewArray == 0 or NewArray[#NewArray] == ".." then NewArray[#NewArray + 1] = ".." else table.remove(NewArray) end elseif V != "." then NewArray[#NewArray + 1] = V end end return table.concat(NewArray, "/") end[/lua] Makes "lua/././../test/../help/me/../../../a.lua" into "../a.lua". Maybe not the most efficient way to do it, but it works :3:.
[QUOTE=iRzilla;26103436]Regular expressions. (Deco fix it.)[/QUOTE] You mean Lua expressions? I wish Lua did regex.
[QUOTE=iRzilla;26103436]Regular expressions. (Deco fix it.)[/QUOTE] Deco and his metapatterns.
Here's an explode function I made which is able to explode around separators larger than 1 character. *old sucky code* see below for new code Let me know if you find any way to optimize it. EDIT: Or if you find wrongs or flaws.
Is it faster than string.Explode?
[QUOTE=Overv;26155232]Is it faster than string.Explode?[/QUOTE] Not sure, but I believe so. Garry uses table.insert as well, which is very slow. And I just noticed a way to make it better: Add another elseif when the pattern is only 1 character long, and also have a count variable instead of using #ret over and over again. I'll add that when I get home. EDIT: I just tested it with the Lua Demo page, and it seems to have a small problem... but it could be the temporary string.Left/Right functions I made (since they aren't standard in Lua). I'll have to see what's up with that when I get home, too.
[lua] function utilx.explode(str, delim, notplain) notplain = not notplain -- I just confused myself local res = {} local newpos, pos, start = 0 repeat pos = newpos+1 start, newpos = string.find(str, delim, pos, notplain) res[#res+1] = string.sub(str, pos, (start or 0)-1) until not start return res end [/lua]
Nicely done. Much better than mine. EDIT: -snip nvm-
[QUOTE=Divran;26155978]EDIT: Which way is faster: str:find( ... ) or string.find( str, ... ) ?[/QUOTE] It's the same exact thing..
[QUOTE=Deco Da Man;26155564]-snip-[/QUOTE] I was trying to rewrite that using gsub/gmatch, then I remembered string sets only work in Regex :arghfist::saddowns:
When I speed tested our functions, yours performed beautifully when exploding around large separators, like entire words. However, when exploding around single character, or empty ("") separators, mine was much faster... So I combined them to get the best of both. I didn't make it able to handle patterns though, like yours could. [lua]local specialchars = { ["%"] = true, ["^"] = true, ["$"] = true, ["("] = true, [")"] = true, ["."] = true, ["["] = true, ["]"] = true, ["*"] = true, ["+"] = true, ["-"] = true, ["?"] = true } local gmatch = string.gmatch local sub = string.sub local Right = string.Right local find = string.find function utilx.explode( str, delim ) if (str == "") then return {} end if (delim == "") then -- Quicker loop for when the delim is empty local ret = {} for i=1,#str do ret[i] = str:sub(i,i) end return ret elseif (#delim == 1) then -- Quicker loop when delim is 1 char local ret = {} local _delim, count = delim, 0 if (specialchars[delim]) then delim = "%" .. delim end for word in str:gmatch( "[^" .. delim .. "]+" ) do count = count + 1 ret[count] = word end return ret else local res = {} local count, newpos, pos, start = 1, 0 repeat pos = newpos+1 start, newpos = str:find( delim, pos, true ) res[count] = str:sub( pos, (start or 0)-1) count = count + 1 until not start return res end end[/lua]
[lua]local lpeg = require "lpeg" function string.split( str, sep ) local sep = lpeg.P( sep ) local txt = lpeg.C( (1-sep) ^ 1 ) local list = lpeg.Ct( txt * (sep * txt)^0 ) return list:match( str ) or {} end table.print( ("this is a test"):split " " )[/lua] [code]1 this 2 is 3 a 4 test[/code] Dug up LPeg :haw:
[QUOTE=raBBish;26156919]Dug up LPeg :haw:[/QUOTE] what's that
I though lpeg was broken?
Sorry, you need to Log In to post a reply to this thread.