Draw 3d2d when something happens serverside

Im trying to draw a 3d2d text, made on the client, when an entity touches the current entity im trying to draw it on. This is the code. the error it gives is: Tried to use a NULL entity! also I did add the network string but its not shown in the code.


function ENT:Think()
	if self.isCooking == true then
		self:SetColor(Color(255,0,0))
	else
		self:SetColor(Color(0,255,0))
	end
	
	if self.isCooking == true then
		if self.finishCooking <= CurTime() then
			self.isCooking = false
		net.Start("statusclosed")
		net.Send(ply)

			
			local morphine = ents.Create("morphine")
			morphine:SetPos(self:GetPos() + Vector(0,0,50))
			morphine:Spawn()
		end
	end
end


net.Receive("statusclosed",function (ply)

local posss = self:GetPos()
	 local angsss = self:GetAngles()
	 local offsetss = angsss:Up() + angsss:Forward() * 15 + angsss:Right() * 0 ;

    angsss:RotateAroundAxis(self:GetAngles():Up(),90)
    angsss:RotateAroundAxis(self:GetAngles():Right(),-90)
    angsss:RotateAroundAxis(self:GetAngles():Forward(),360)

    local distss = self:GetPos():Distance(EyePos())
	local clamss = math.Clamp(distss, 0, 255 )
	local mainss = (255 - clamss)
	
	if (mainss <= 0) then return end

	cam.Start3D2D(posss+offsetss,angsss,0.13)
         draw.WordBox(0,-55,-40,"Empty","NewFontsz",Color(0,0,0,main),Color(180,10,0,main))
	cam.End3D2D()

	end)

Which line causes the error?


net.Start("statusclosed")
		net.Send(ply)

That one

ply is nil. It needs to be a player object.

So how do you call the player on the serverside then?

keep a reference to the player in the entity and use that?

also you need to have a hook to use 3d2d, PostDrawOpaqueRenderables or similar. A net.Receive is only going to be called once, but you need to draw 3d2d every frame

would net.send(player) work? and yeah im drawing it in ent:draw

no and the code you posted you’re not drawing it in the ent:draw?


function ENT:Draw()

 
 self:DrawModel()



net.Receive("statusclosed",function (ply)

local posss = self:GetPos()
	 local angsss = self:GetAngles()
	 local offsetss = angsss:Up() + angsss:Forward() * 15 + angsss:Right() * 0 ;

    angsss:RotateAroundAxis(self:GetAngles():Up(),90)
    angsss:RotateAroundAxis(self:GetAngles():Right(),-90)
    angsss:RotateAroundAxis(self:GetAngles():Forward(),360)

    local distss = self:GetPos():Distance(EyePos())
	local clamss = math.Clamp(distss, 0, 255 )
	local mainss = (255 - clamss)
	
	if (mainss <= 0) then return end

	cam.Start3D2D(posss+offsetss,angsss,0.13)
         draw.WordBox(0,-55,-40,"Empty","NewFontsz",Color(0,0,0,mainss),Color(0,180,0,mainss))
	cam.End3D2D()

	end)


	

end

It is, just didnt include it in my thread

To start scripting. you need to know how the computer reads and handle the file.

All files only get read once and placed in memory. This means if you place


print("Hello world")

in the file, it only shows up once.

However Garrysmod calls some functions that things run in. the ones you would need is “ENT:Think” and “ENT:Draw”.

“ENT:Think” gets called ever game-tick. This is where all the logic and things happen.
“ENT:Draw” gets called every frame (Your FPS … so that can be many times more than Think), this is where you need to place the 3d2d and draw functions, as you need to draw them every frame.

You need something like:



-- SERVER
util.AddNetworkString("My_first_networkstring") -- To use the net, you would need to add this to the server
function ENT:Init()
	self.switch = false
end
local easy_timer = 0
function ENT:Think() -- This gets called every server tick

	if easy_timer > SysTime() then return end -- This will stop the script and only run it every second. Don't spam the network.
		easy_timer = SysTime() + 1

	self.switch = not self.switch -- Flip the switch

	net.Start("My_first_networkstring")
		net.WriteBool(self.switch) -- Write the switch into the message
		net.WriteEntity(self) -- Be sure the client knows what entity the switch is for
	net.Broadcast() -- Send it to all players.
end

-- CLIENT
function ENT:Init()
	self.switch = false
end
net.Receive("My_first_networkstring",function(len) -- This gets called every time you recive a "message" from the server
	local switch = net.ReadBool() -- Read first message
	local entity = net.ReadEntity() -- Read the second message
	entity.switch = switch -- Set the switch for the entity
net
function ENT:Draw() -- This gets called every time a new frame is drawn
	self:DrawModel() -- Draw itself first
	if not entity.switch then return end -- Be sure that switch is true before drawing stuff

	cam.Start3D2D(posss+offsetss,angsss,0.13) -- Draw the thing
         draw.WordBox(0,-55,-40,"Empty","NewFontsz",Color(0,0,0,main),Color(180,10,0,main))
	cam.End3D2D()
end

Tips:

  • Placing ply anywhere won’t work
  • NEVER place functions inside other functions (before being more skilled. This includes net.Recive)

well turns out, this isn’t so simple as I thought, anyways that helped me a lot, thank you so much!