add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,816 @@
easylua = {} local s = easylua
local _R = debug.getregistry()
local function compare(a, b)
if a == b then return true end
if a:find(b, nil, true) then return true end
if a:lower() == b:lower() then return true end
if a:lower():find(b:lower(), nil, true) then return true end
return false
end
local function comparenick(a, b)
local MatchTransliteration = GLib and GLib.UTF8 and GLib.UTF8.MatchTransliteration
if not MatchTransliteration then return compare (a, b) end
if a == b then return true end
if a:lower() == b:lower() then return true end
if MatchTransliteration(a, b) then return true end
return false
end
local function compareentity(ent, str)
if ent.GetName and compare(ent:GetName(), str) then
return true
end
if ent:GetModel() and compare(ent:GetModel(), str) then
return true
end
return false
end
local TagPrintOnServer = "elpos"
if CLIENT then
function easylua.PrintOnServer(...)
local args = {...}
local new = {}
for key, value in pairs(args) do
table.insert(new, luadata and luadata.ToString(value) or tostring(value))
end
net.Start(TagPrintOnServer)
local str = table.concat(new," ")
local max = 256
net.WriteString(str:sub(1,max))
net.WriteBool(#str>max)
net.SendToServer()
end
else
util.AddNetworkString(TagPrintOnServer)
end
function easylua.Print(...)
if CLIENT then
easylua.PrintOnServer(...)
end
if SERVER then
local args = {...}
local str = ""
Msg(string.format("[ELua %s] ", IsValid(me) and me:Nick() or "Sv"))
for key, value in pairs(args) do
str = str .. type(value) == "string" and value or luadata.ToString(value) or tostring(value)
if key ~= #args then
str = str .. ","
end
end
print(str)
end
end
if SERVER then
-- Rate limiting, still bad
local spams=setmetatable({},{__mode='k'})
local function canspam(pl,len)
local now = RealTime()
local nextspam = spams[pl] or 0
if now>nextspam then
nextspam = now + len>100 and 3 or 1
spams[pl] = nextspam
return true
else
local plstr = tostring(pl)
timer.Create("easylua_pspam",5,1,function()
Msg "[Easylua Print] Lost messages due to spam: " print(plstr)
end)
end
end
function easylua.CMDPrint(ply, cmd, args, fulln)
if not canspam(ply,#fulln) then
return
end
args = table.concat(args, ", ")
Msg(string.format("[ELua %s] ", IsValid(ply) and ply:Nick() or "Sv"))
print(args)
end
concommand.Add("easylua_print", easylua.CMDPrint)
net.Receive(TagPrintOnServer,function(len,ply)
local str = net.ReadString()
if not canspam(ply,#str) then return end
str=str:sub(1,512)
local more = net.ReadBool()
Msg(string.format("[ELua %s] ", IsValid(ply) and ply:Nick() or "Sv"))
local outstr = ('%s%s'):format(str,more and "..." or ""):gsub("[\r\n]"," ")
print(outstr)
end)
end
function easylua.FindEntity(str)
if not str then return NULL end
str = tostring(str)
if str == "#this" and IsEntity(this) and this:IsValid() then
return this
end
if str == "#owner" and IsEntity(this) and this:IsValid() then
local owner = this.CPPIGetOwner and this:CPPIGetOwner() or this:GetOwner()
return owner
end
if str == "#me" and IsEntity(me) and me:IsPlayer() then
return me
end
if str == "#all" then
return all
end
if str == "#afk" then
return afk
end
if str == "#us" then
return us
end
if str == "#them" then
return them
end
if str == "#friends" then
return friends
end
if str == "#humans" then
return humans
end
if str == "#bots" then
return bots
end
if str == "#randply" then
return table.Random(player.GetAll())
end
if str:sub(1,1) == "#" then
local str = str:sub(2)
if #str > 0 then
str = str:lower()
local found
for teamid, data in pairs(team.GetAllTeams()) do
if data.Name:lower() == str then
found = teamid
break
end
end
if found then
return CreateAllFunction(function()
local t = {}
for k,v in next,player.GetAll() do
if v:IsPlayer() and v:Team() == found then
t[#t+1] = v
end
end
return t
end)
end
for key, ent in ipairs(ents.GetAll()) do
if ent:GetClass():lower() == str then
found = str
break
end
end
if found then
return CreateAllFunction(function()
return ents.FindByClass(found)
end)
end
end
end
-- unique id
local ply = player.GetByUniqueID(str)
if ply and ply:IsPlayer() then
return ply
end
-- steam id
if str:find("STEAM") then
for key, _ply in ipairs(player.GetAll()) do
if _ply:SteamID() == str then
return _ply
end
end
end
if str:sub(1,1) == "_" and tonumber(str:sub(2)) then
str = str:sub(2)
end
if tonumber(str) then
ply = Entity(tonumber(str))
if ply:IsValid() then
return ply
end
end
-- community id
if #str == 17 and str[1] == "7" then
local ply = player.GetBySteamID64(str)
if ply and ply:IsValid() then
return ply
end
end
-- ip
if SERVER then
if str:find("%d+%.%d+%.%d+%.%d+") then
for key, _ply in ipairs(player.GetAll()) do
if _ply:IPAddress():find(str) then
return _ply
end
end
end
end
-- search in sensible order
-- search exact
for _,ply in ipairs(player.GetAll()) do
if ply:Nick()==str then
return ply
end
end
-- Search bots so we target those first
for key, ply in ipairs(player.GetBots()) do
if comparenick(ply:Nick(), str) then
return ply
end
end
-- search from beginning of nick
for _,ply in ipairs(player.GetHumans()) do
if ply:Nick():lower():find(str,1,true)==1 then
return ply
end
end
-- Search normally and search with colorcode stripped
for key, ply in ipairs(player.GetAll()) do
if comparenick(ply:Nick(), str) then
return ply
end
if _G.UndecorateNick and comparenick( UndecorateNick( ply:Nick() ), str) then
return ply
end
end
-- search RealName
if _R.Player.RealName then
for _, ply in ipairs(player.GetAll()) do
if comparenick(ply:RealNick(), str) then
return ply
end
end
end
if IsValid(me) and me:IsPlayer() then
local tr = me:GetEyeTrace()
local plpos = tr and tr.HitPos or me:GetPos()
local closest,mind = nil,math.huge
for key, ent in ipairs(ents.GetAll()) do
local d = ent:GetPos():DistToSqr(plpos)
if d < mind and compareentity(ent, str) then
closest = ent
mind = d
end
end
if closest then
return closest
end
else
for key, ent in ipairs(ents.GetAll()) do
if compareentity(ent, str) then
return ent
end
end
end
do -- class
local _str, idx = str:match("(.-)(%d+)$")
if idx then
idx = tonumber(idx)
str = _str
else
str = str
idx = (me and me.easylua_iterator) or 0
if me and isentity(me) and me:IsPlayer() then
local tr = me:GetEyeTrace()
local plpos = tr and tr.HitPos or me:GetPos()
local closest,mind = nil,math.huge
for key, ent in ipairs(ents.GetAll()) do
local d = ent:GetPos():DistToSqr(plpos)
if d < mind and compare(ent:GetClass(), str) then
closest = ent
mind = d
end
end
if closest then
return closest
end
end
end
local found = {}
for key, ent in ipairs(ents.GetAll()) do
if compare(ent:GetClass(), str) then
table.insert(found, ent)
end
end
return found[math.Clamp(idx%#found, 1, #found)] or NULL
end
end
function easylua.CreateEntity(class, callback)
local mdl = "error.mdl"
if IsEntity(class) and class:IsValid() then
this = class
elseif class:find(".mdl", nil, true) then
mdl = class
class = "prop_physics"
this = ents.Create(class)
this:SetModel(mdl)
else
this = ents.Create(class)
end
if callback and type(callback) == 'function' then
callback(this);
end
this:Spawn()
this:SetPos(there + Vector(0,0,this:BoundingRadius() * 2))
this:DropToFloor()
this:PhysWake()
undo.Create(class)
undo.SetPlayer(me)
undo.AddEntity(this)
undo.Finish()
me:AddCleanup("props", this)
return this
end
function easylua.CopyToClipboard(var, ply)
ply = ply or me
if luadata then
local str = luadata.ToString(var)
if not str and IsEntity(var) and var:IsValid() then
if var:IsPlayer() then
str = string.format("player.GetByUniqueID(--[[%s]] %q)", var:GetName(), var:UniqueID())
else
str = string.format("Entity(%i)", var:EntIndex())
end
end
if CLIENT then
SetClipboardText(str)
end
if SERVER then
local str = string.format("SetClipboardText(%q)", str)
if #str > 255 then
if luadev and luadev.RunOnClient then
luadev.RunOnClient(str, ply)
else
error("Text too long to send and luadev not found",1)
end
else
ply:SendLua(str)
end
end
end
end
local started = false
function easylua.Start(ply)
if started then
Msg"[ELua] "print("Session not ended for ",_G.me or (s.vars and s.vars.me),", restarting session for",ply)
easylua.End()
end
started = true
ply = ply or CLIENT and LocalPlayer() or nil
if not ply or not IsValid(ply) then return end
local vars = {}
local trace = util.QuickTrace(ply:EyePos(), ply:GetAimVector() * 10000, {ply, ply:GetVehicle()})
if trace.Entity:IsWorld() then
trace.Entity = NULL
end
vars.me = ply
vars.this = trace.Entity
vars.wep = ply:GetActiveWeapon()
vars.veh = ply:GetVehicle()
vars.we = {}
for k, v in ipairs(ents.FindInSphere(ply:GetPos(), 512)) do
if v:IsPlayer() then
table.insert(vars.we, v)
end
end
vars.there = trace.HitPos
vars.here = trace.StartPos
vars.dir = ply:GetAimVector()
vars.trace = trace
vars.length = trace.StartPos:Distance(trace.HitPos)
vars.copy = s.CopyToClipboard
vars.create = s.CreateEntity
vars.prints = s.PrintOnServer
if vars.this:IsValid() then
vars.phys = vars.this:GetPhysicsObject()
vars.model = vars.this:GetModel()
end
vars.E = s.FindEntity
vars.last = ply.easylua_lastvars
s.vars = vars
local old_G = {}
s.oldvars = old_G
for k, v in pairs(vars) do
old_G[k] = rawget(_G, k)
rawset(_G, k, v)
end
-- let this gc. maybe allow few more recursions.
if vars.last and istable(vars.last) then vars.last.last = nil end
ply.easylua_lastvars = vars
ply.easylua_iterator = (ply.easylua_iterator or 0) + 1
end
function easylua.End()
if not started then
Msg"[ELua] "print"Ending session without starting"
end
started = false
if s.vars then
for key, value in pairs(s.vars) do
if s.oldvars and s.oldvars[key] then
rawset(_G, key, s.oldvars[key])
else
rawset(_G, key, nil)
end
end
end
end
do -- env meta
local META = {}
local _G = _G
local easylua = easylua
local tonumber = tonumber
local nils={
["CLIENT"]=true,
["SERVER"]=true,
}
function META:__index(key)
local var = _G[key]
if var ~= nil then
return var
end
if not nils [key] then -- uh oh
var = easylua.FindEntity(key)
if var:IsValid() then
return var
end
end
return nil
end
function META:__newindex(key, value)
_G[key] = value
end
easylua.EnvMeta = setmetatable({}, META)
end
function easylua.RunLua(ply, code, env_name)
local data =
{
error = false,
args = {},
}
easylua.Start(ply)
if s.vars then
local header = ""
for key, value in next,(s.vars or {}) do
header = header .. string.format("local %s = %s ", key, key)
end
code = header .. "; " .. code
end
env_name = env_name or string.format("%s", tostring(
IsValid(ply) and ply:IsPlayer()
and "["..ply:SteamID():gsub("STEAM_","").."]"..ply:Name()
or ply))
data.env_name = env_name
local func = CompileString(code, env_name, false)
if type(func) == "function" then
setfenv(func, easylua.EnvMeta)
local args = {pcall(func)}
if args[1] == false then
data.error = args[2]
end
table.remove(args, 1)
data.args = args
else
data.error = func
end
easylua.End()
return data
end
-- legacy luadev compatibility
local STAGE_PREPROCESS=1
local STAGE_COMPILED=2
local STAGE_POST=3
local insession = false
hook.Add("LuaDevProcess","easylua",function(stage,script,info,extra,func)
if stage==STAGE_PREPROCESS then
if insession then
insession=false
easylua.End()
end
if not istable(extra) or not IsValid(extra.ply) or not script or extra.easylua==false then
return
end
insession = true
easylua.Start(extra.ply)
local t={}
for key, value in pairs(easylua.vars or {}) do
t[#t+1]=key
end
if #t>0 then
script=' local '..table.concat(t,", ")..' = '..table.concat(t,", ")..' ; '..script
end
--ErrorNoHalt(script)
return script
elseif stage==STAGE_COMPILED then
if not istable(extra) or not IsValid(extra.ply) or not isfunction(func) or extra.easylua==false then
if insession then
insession=false
easylua.End()
end
return
end
if insession then
local env = getfenv(func)
if not env or env==_G then
setfenv(func, easylua.EnvMeta)
end
end
elseif stage == STAGE_POST and insession then
insession=false
easylua.End()
end
end)
function easylua.StartWeapon(classname)
_G.SWEP = {
Primary = {},
Secondary = {},
ViewModelFlip = false,
}
SWEP.Base = "weapon_base"
SWEP.ClassName = classname
end
function easylua.EndWeapon(spawn, reinit)
if not SWEP then error"missing SWEP" end
if not SWEP.ClassName then error"missing classname" end
weapons.Register(SWEP, SWEP.ClassName)
for key, entity in ipairs(ents.FindByClass(SWEP.ClassName)) do
--if entity:GetTable() then table.Merge(entity:GetTable(), SWEP) end
if reinit then
entity:Initialize()
end
end
if SERVER and spawn then
SafeRemoveEntity(me:GetWeapon(SWEP.ClassName))
local me = me
local class = SWEP.ClassName
timer.Simple(0.2, function() if me:IsPlayer() then me:Give(class) end end)
end
SWEP = nil
end
function easylua.StartEntity(classname)
_G.ENT = {}
ENT.ClassName = classname or "no_ent_name_" .. me:Nick() .. "_" .. me:UniqueID()
end
function easylua.EndEntity(spawn, reinit)
ENT.Model = ENT.Model or Model("models/props_borealis/bluebarrel001.mdl")
if not ENT.Base then -- there can be Base without Type but no Type without base without redefining every function so um
ENT.Base = "base_anim"
ENT.Type = ENT.Type or "anim"
end
scripted_ents.Register(ENT, ENT.ClassName)
for key, entity in ipairs(ents.FindByClass(ENT.ClassName)) do
--table.Merge(entity:GetTable(), ENT)
if reinit then
entity:Initialize()
end
end
if SERVER and spawn then
create(ENT.ClassName)
end
ENT = nil
end
do -- all
include("tinylua.lua") -- Force it to load before we use it
local next = next
local type = type
local INTERNAL = {}
local META = {}
function META:__call()
error("Undefined __call")
end
function META:__index(key)
local wrapped = tinylua(self())
return wrapped[key]
end
function META:__newindex(key, value)
local wrapped = tinylua(self())
wrapped[key] = value
end
function CreateAllFunction(filter, inputTbl)
local allMeta = {}
for ind, metamethod in pairs(META)do
allMeta[ind] = metamethod
end
function allMeta:__call()
return (isfunction(filter) and filter() or filter)
end
return setmetatable(inputTbl or {}, allMeta)
end
function INTERNAL:get()
return self()
end
all = CreateAllFunction(player.GetAll)
humans = CreateAllFunction(player.GetHumans)
bots = CreateAllFunction(player.GetBots)
afk = CreateAllFunction(function()
local t = {}
for k,v in ipairs(player.GetAll()) do
if not v.IsAFK then break end
if v:IsAFK() then
t[#t+1] = v
end
end
return t
end)
us = CreateAllFunction(function()
if _G.we then return _G.we end
if _G.me then return {_G.me} end
return {}
end)
them = CreateAllFunction(function()
local me = _G.me
local we = _G.we or {}
table.RemoveByValue(we, me)
return we
end)
friends = CreateAllFunction(function()
local me = _G.me
local t = {}
for k,v in ipairs(player.GetHumans()) do
if v == me then continue end
if (me.IsFriend and me:IsFriend(v) or (CLIENT and v:GetFriendStatus() == "friend")) then
t[#t+1] = v
end
end
return t
end)
npcs = CreateAllFunction(function()
local t = {}
for _, ent in pairs(ents.GetAll())do
if ent:IsNPC() then
table.insert(t, ent)
end
end
return t
end)
allof = function(class)
if isentity(class) and IsValid(class) then
class = class:GetClass()
end
local results = ents.FindByClass(class)
return CreateAllFunction(function()
return results
end, results)
end
props = CreateAllFunction(function() return ents.FindByClass("prop_physics") end)
if SERVER then
these = CreateAllFunction(function() return constraint.GetAllConstrainedEntities(_G.this) end)
end
those = CreateAllFunction(function() return ents.FindInSphere(_G.there, 250) end)
end

View File

@@ -0,0 +1,18 @@
module("luadev",package.seeall)
-- I think I finally understood why people make these seemingly silly files with just includes
include 'luadev/luadev_sh.lua'
if SERVER then
include 'luadev/luadev_sv.lua'
end
include 'luadev/luadev.lua'
if CLIENT then
include 'luadev/socketdev.lua'
end
if SERVER then
AddCSLuaFile 'luadev/luadev_sh.lua'
AddCSLuaFile 'luadev/luadev.lua'
AddCSLuaFile 'luadev/socketdev.lua'
end

View File

@@ -0,0 +1,130 @@
hook.Add("Think","luadev_cmdsinit",function()
hook.Remove("Think","luadev_cmdsinit")
local function add(cmd,callback)
if aowl and aowl.AddCommand then
aowl.AddCommand(cmd,function(ply,script,param_a,...)
local a,b
easylua.End() -- nesting not supported
local ret,why = callback(ply,script,param_a,...)
if not ret then
if why==false then
a,b = false,why or aowl.TargetNotFound(param_a or "notarget") or "H"
elseif isstring(why) then
ply:ChatPrint("FAILED: "..tostring(why))
a,b= false,tostring(why)
end
end
easylua.Start(ply)
return a,b
end,cmd=="lm" and "players" or "developers")
end
end
local function X(ply,i) return luadev.GetPlayerIdentifier(ply,'cmd:'..i) end
add("l", function(ply, line, target)
if not line or line=="" then return false,"invalid script" end
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,"l") if not valid then return false,err end end
return luadev.RunOnServer(line, X(ply,"l"), {ply=ply})
end)
add("ls", function(ply, line, target)
if not line or line=="" then return false,"invalid script" end
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,"ls") if not valid then return false,err end end
return luadev.RunOnShared(line, X(ply,"ls"), {ply=ply})
end)
add("lc", function(ply, line, target)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,"lc") if not valid then return false,err end end
return luadev.RunOnClients(line, X(ply,"lc"), {ply=ply})
end)
add("lsc", function(ply, line, target)
local script = string.sub(line, string.find(line, target, 1, true)+#target+1)
if luadev.ValidScript then local valid,err = luadev.ValidScript(script,'lsc') if not valid then return false,err end end
easylua.Start(ply) -- for _G.we -> #us
local ent = easylua.FindEntity(target)
if type(ent) == 'table' then
ent = ent.get()
end
easylua.End()
return luadev.RunOnClient(script, ent, X(ply,"lsc"), {ply=ply})
end)
local sv_allowcslua = GetConVar"sv_allowcslua"
add("lm", function(ply, line, target)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,'lm') if not valid then return false,err end end
if not ply:IsAdmin() and not sv_allowcslua:GetBool() then return false,"sv_allowcslua is 0" end
luadev.RunOnClient(line, ply,X(ply,"lm"), {ply=ply})
end)
add("lb", function(ply, line, target)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,'lb') if not valid then return false,err end end
luadev.RunOnClient(line, ply, X(ply,"lb"), {ply=ply})
return luadev.RunOnServer(line, X(ply,"lb"), {ply=ply})
end)
add("print", function(ply, line, target)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript('x('..line..')','print') if not valid then return false,err end end
return luadev.RunOnServer("print(" .. line .. ")", X(ply,"print"), {ply=ply})
end)
add("table", function(ply, line, target)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript('x('..line..')','table') if not valid then return false,err end end
return luadev.RunOnServer("PrintTable(" .. line .. ")", X(ply,"table"), {ply=ply})
end)
add("keys", function(ply, line, table, search)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript('x('..table..')','keys') if not valid then return false,err end end
search = search and search:lower() or ""
return luadev.RunOnServer(
"local t={} for k,v in pairs(" .. table .. ") do t[#t+1]=tostring(k) end table.sort(t) for k,v in pairs(t) do if string.find(v:lower(),\"" .. search .. "\",1,true) then print(v) end end",
X(ply,"keys"), {ply=ply}
)
end)
add("printc", function(ply, line, target)
if not line or line=="" then return end
line = "easylua.PrintOnServer(" .. line .. ")"
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,'printc') if not valid then return false,err end end
return luadev.RunOnClients(line, X(ply,"printc"), {ply=ply})
end)
add("printm", function(ply, line, target)
if not line or line=="" then return end
line = "easylua.PrintOnServer(" .. line .. ")"
if luadev.ValidScript then local valid,err = luadev.ValidScript(line,'printm') if not valid then return false,err end end
luadev.RunOnClient(line, ply, X(ply,"printm"), {ply=ply})
end)
add("printb", function(ply, line, target)
if not line or line=="" then return end
if luadev.ValidScript then local valid,err = luadev.ValidScript('x('..line..')','printb') if not valid then return false,err end end
luadev.RunOnClient("easylua.PrintOnServer(" .. line .. ")", ply, X(ply,"printb"), {ply=ply})
return luadev.RunOnServer("print(" .. line .. ")", X(ply,"printb"), {ply=ply})
end)
end)

View File

@@ -0,0 +1,202 @@
tinylua = setmetatable({}, { __call = function(self, ...) return self.Wrap(...) end})
local INTERNAL = {}
local META = {}
local function pack(...) -- Convenient argument packer
local len, tbl = select('#', ...), {...}
local packFuncs = {}
function packFuncs.unpack()
return unpack(tbl, 1, len)
end
return setmetatable(tbl, {
__index = function(self, index)
return packFuncs[index] or tbl[index]
end,
__call = function(...)
return len, tbl
end
})
end
local function Wrap(input)
local values = {}
local meta = {}
for ind, val in pairs(input)do
values[(tonumber(ind) and val or ind)] = val
end
for ind, val in pairs(META)do
meta[ind] = val
end
return setmetatable(values, meta)
end
local function performCall(tbl, callback)
local results = {}
local errors = {}
local calls = 0
local iKey, iVal = nil, nil
while true do
local succ, err = pcall(function()
while true do
iKey, iVal = next(tbl, iKey)
if iKey == nil then break end
calls = calls + 1
callback(results, iKey, iVal)
end
end)
if not succ then errors[iKey] = err end
if iKey == nil then break end
end
if table.Count(errors) == calls then
if calls ~= 0 then
local _, error = next(errors, nil)
MsgC(Color(235, 111, 111), "[tinylua] "..error)
else
MsgC(Color(235, 111, 111), "[tinylua] No results!\n")
return
end
end
local result = Wrap(results)
getmetatable(result)["errors"] = errors
return result
end
function META:__index(index)
if INTERNAL[index] then
return function(_, ...)
return INTERNAL[index](self, ...)
end
end
return performCall(self, function(results, source, ent)
local target = ent[index]
if isfunction(target) then
results[source] = function(fArg, ...)
return target(ent, ...)
end
else
results[source] = target
end
end)
end
function META:__newindex(index, value)
performCall(self, function(results, source, ent)
ent[index] = value
end)
end
function META:__call(...)
local args = pack(...)
return performCall(self, function(results, source, ent)
if isfunction(ent) then
local rets = pack(ent(args:unpack()))
if #rets ~= 1 then
for _, ret in pairs(rets) do
table.insert(results, ret)
end
else
results[source] = rets[1]
end
end
end)
end
-- Exposed Functions
tinylua.Wrap = Wrap
-- INTERNAL Extensions
local function makePrefix(input)
if not input:match("\n") and isfunction(CompileString("return "..input, "", false)) then
return "return "..input
end
return input
end
local function buildParser(input)
if isfunction(input) then return input end
local argStr, funcStr = input:match("(.-)->(.+)")
if argStr and funcStr then
local codeFull = string.format("return function(%s)\n%s\nend", argStr, makePrefix(funcStr))
local funcFactory = CompileString(codeFull, "funcfactory")
if getfenv(1) then
setfenv(funcFactory, getfenv(1))
end
if funcFactory then
return funcFactory()
end
end
end
function INTERNAL:map(input)
local eval = buildParser(input)
return performCall(self, function(results, source, ent)
local rets = pack(eval(ent, source))
if #rets ~= 1 then
for _, val in pairs(rets) do
table.insert(results, val)
end
else
results[source] = rets[1]
end
end)
end
function INTERNAL:filter(input)
local eval = buildParser(input)
return performCall(self, function(results, source, ent)
if eval(ent, source) then
results[source] = ent
end
end)
end
function INTERNAL:set(vars, val)
vars = (istable(vars) and vars or {vars})
return performCall(self, function(results, source, ent)
for _, var in ipairs(vars) do
ent[var] = val
end
results[source] = ent
end)
end
function INTERNAL:IsValid()
return false
end
function INTERNAL:keys()
return performCall(self, function(results, source, ent)
results[source] = source
end)
end
function INTERNAL:first()
for _, ent in pairs(self) do
return ent
end
end
function INTERNAL:errors()
return (getmetatable(self).errors or {})
end
function INTERNAL:get()
return table.ClearKeys(self)
end