add sborka
This commit is contained in:
816
garrysmod/addons/luadev/lua/autorun/easylua.lua
Normal file
816
garrysmod/addons/luadev/lua/autorun/easylua.lua
Normal 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
|
||||
18
garrysmod/addons/luadev/lua/autorun/luadev.lua
Normal file
18
garrysmod/addons/luadev/lua/autorun/luadev.lua
Normal 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
|
||||
130
garrysmod/addons/luadev/lua/autorun/server/luadev_chatcmds.lua
Normal file
130
garrysmod/addons/luadev/lua/autorun/server/luadev_chatcmds.lua
Normal 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)
|
||||
202
garrysmod/addons/luadev/lua/autorun/tinylua.lua
Normal file
202
garrysmod/addons/luadev/lua/autorun/tinylua.lua
Normal 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
|
||||
Reference in New Issue
Block a user