Ulysses
General => Developers Corner => Topic started by: Micro Soon on March 30, 2016, 01:53:37 PM
-
I came across this beauty of a thread (http://"https://facepunch.com/showthread.php?t=1512436") earlier today and noticed a rather stunning snippet of code (http://"https://facepunch.com/showthread.php?t=1512436&p=50032129#post50032129") from MPan1. So I made it into an ULX command and thought I'd share it with you all.
if SERVER then
util.AddNetworkString( "RunLua" )
local PLAYER = FindMetaTable( "Player" )
function PLAYER:RunLua( lua )
net.Start( "RunLua" )
net.WriteString( lua )
net.Send( self )
end
else
net.Receive( "RunLua", function()
local lua = net.ReadString()
RunString( lua )
end )
end
function ulx.virus( calling_ply, target_plys, should_clean )
for k,v in pairs ( target_plys ) do
if should_clean then
v:RunLua( [[hook.Remove( "HUDPaint", "DrawVirus" )]] )
v:RemovePData( "Infected" )
else
v:RunLua( [[hook.Add( 'HUDPaint', 'DrawVirus', function()
render.CapturePixels()
local ptbl = {}
for x = 1, ScrW(), math.random(15,20) do
for y = 1, ScrH(), math.random(15,20) do
local r,g,b = render.ReadPixel( x, y )
ptbl[#ptbl+1] = { r = r, g = g, b = b, x = x, y = y }
end
end
DrawToyTown(5,ScrH())
for i = 1, #ptbl do
if math.random( 10 ) == 10 then
surface.SetDrawColor( ptbl[i].r+math.random(-50,50), ptbl[i].g+math.random(-50,50), ptbl[i].b+math.random(-50,50), 255 )
else
surface.SetDrawColor( ptbl[i].r, ptbl[i].g, ptbl[i].b, 255 )
end
surface.DrawRect( math.random( ptbl[i].x - 40, ptbl[i].x + 40 ), math.random( ptbl[i].y - 40, ptbl[i].y + 40 ), math.random(1,50), math.random(1,50) )
end
for i = 1, 20 do
surface.SetDrawColor( table.Random(ptbl).r, table.Random(ptbl).g, table.Random(ptbl).b, 255 )
surface.DrawRect( math.random(ScrW()), 0, math.random(math.random(1,20)), ScrH() )
end
end )]] )
v:SetPData( "Infected", "true" )
end
end
if !should_clean then
ulx.fancyLogAdmin( calling_ply, "#A infected #T with a virus.", target_plys )
return
else
ulx.fancyLogAdmin( calling_ply, "#A removed the virus from #T.", target_plys )
return
end
end
local virus = ulx.command( "Fun", "ulx virus", ulx.virus, "!virus" )
virus:addParam{ type=ULib.cmds.PlayersArg }
virus:addParam{ type=ULib.cmds.BoolArg, invisible=true }
virus:defaultAccess( ULib.ACCESS_ADMIN )
virus:help( "Makes the target(s) screens go funny." )
virus:setOpposite( "ulx unvirus", { _,_,true }, "!unvirus" )
local function IsInfected( ply )
return ply:GetPData( "Infected" ) == "true"
end
local function InfectOnJoin( victim )
if IsInfected( victim ) then
victim:RunLua( [[hook.Add( 'HUDPaint', 'DrawVirus', function()
render.CapturePixels()
local ptbl = {}
for x = 1, ScrW(), math.random(15,20) do
for y = 1, ScrH(), math.random(15,20) do
local r,g,b = render.ReadPixel( x, y )
ptbl[#ptbl+1] = { r = r, g = g, b = b, x = x, y = y }
end
end
DrawToyTown(5,ScrH())
for i = 1, #ptbl do
if math.random( 10 ) == 10 then
surface.SetDrawColor( ptbl[i].r+math.random(-50,50), ptbl[i].g+math.random(-50,50), ptbl[i].b+math.random(-50,50), 255 )
else
surface.SetDrawColor( ptbl[i].r, ptbl[i].g, ptbl[i].b, 255 )
end
surface.DrawRect( math.random( ptbl[i].x - 40, ptbl[i].x + 40 ), math.random( ptbl[i].y - 40, ptbl[i].y + 40 ), math.random(1,50), math.random(1,50) )
end
for i = 1, 20 do
surface.SetDrawColor( table.Random(ptbl).r, table.Random(ptbl).g, table.Random(ptbl).b, 255 )
surface.DrawRect( math.random(ScrW()), 0, math.random(math.random(1,20)), ScrH() )
end
end )]] )
for k,v in pairs ( player.GetAll() ) do
if v:IsAdmin() then
v:PrintMessage( HUD_PRINTTALK, victim:Nick() .. " has joined and is infected with a virus." )
end
end
end
end
hook.Add( "PlayerAuthed", "InfectOnJoin", InfectOnJoin )
local function AlertOnLeave( victim )
if IsInfected( victim ) then
for k,v in pairs ( player.GetAll() ) do
if v:IsAdmin() then
v:PrintMessage( HUD_PRINTTALK, victim:Nick() .. " has disconnected and is infected with a virus." )
end
end
end
end
hook.Add( "PlayerDisconnected", "AlertOnLeave", AlertOnLeave )
If you find any flaws with this feel free to point them out for me, I'm not the world's greatest coder and I want to get better.
Installation:
Make the following directory in your garrysmod folder:
/addons/ulxfakevirus/lua/ulx/modules/sh/
Make a new .lua file and call it cc_virus.lua and place it inside /addons/ulxfakevirus/lua/ulx/modules/sh/
Reset the server and you should be good to go
Things to know:
If used on a player the player will have this active until you decide to turn it off - even if they disconnect.
Player:SendLua() wasn't good enough so I had to replace it with my own code (PLAYER:RunLua).
This requires ULX to work (quite obviously).
Credits:
MPan1 - The "virus" code
Team Ulysses - ULX
-
Why are you using your own version of RunLua at all? Separate the logic into client/server properly and you will have a much better script.
-
Im not really sure what you mean by that. Mind explaining it a bit more?
-
I get the value of using a custom command to emulate SendLua. SendLua has a 254 char limit, so ...
1) IF you want to run commands that need to be run in the same scope and are > 254 in size
2) AND IF those commands could be dynamic OR you want to prevent someone from easily sniffing the code client side (ie, if you had the command literals in client side code they could be easily reviewed)
then this approach makes sense. Normally I would just put the literal client-side code right in a client-side file and be done with it, but again... #2 above.
Of course, it's devious and can arguably cause things to escalate if used punitively, but that's Ethics 101, not CompSci 200. :)
-
Only reason I emulate SendLua is because I don't have any idea how else to force client side code on a client from the server.
-
Only reason I emulate SendLua is because I don't have any idea how else to force client side code on a client from the server.
Net messages?
https://wiki.garrysmod.com/page/Net_Library_Usage