Skip to content

Commit

Permalink
Fixed a bad calls to PlayerUse hook causing lua errors with many addons
Browse files Browse the repository at this point in the history
- Added a cache to prop protection +USE checks avoid call spams. The cache expires after 3 seconds.
- Fixed some edge cases with attempting to use a radio blocked by prop protection.
- Fixed display freezing or menus disappearing when they aren't supposed too.

Thanks for reporting this issue on Steam:
- [DSTM] hesitantv4mpire
- BEan
  • Loading branch information
Grocel committed Jun 9, 2023
1 parent e950f54 commit 56bcb1f
Show file tree
Hide file tree
Showing 17 changed files with 170 additions and 60 deletions.
4 changes: 2 additions & 2 deletions lua/autorun/streamradio_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -486,14 +486,14 @@ end
local outdated = false

if CLIENT then
if Gmodversion < 220608 and Gmodversion > 5 then
if Gmodversion < 220713 and Gmodversion > 5 then
StreamRadioLib.ErrorString = "Your GMod-Client (Version: " .. Gmodversion .. ") is too old!\nPlease update the GMod-Client!"
outdated = true

ErrorNoHalt(AddonPrefix .. StreamRadioLib.ErrorString .. "\n")
end
else
if Gmodversion < 220608 and Gmodversion > 5 then
if Gmodversion < 220713 and Gmodversion > 5 then
StreamRadioLib.ErrorString = "The GMod-Server (Version: " .. Gmodversion .. ") is too old!\nPlease update the GMod-Server!"
outdated = true

Expand Down
43 changes: 17 additions & 26 deletions lua/entities/base_streamradio_gui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,14 @@ function ENT:GetDisplayPos( )
return pos, ang
end

function ENT:CheckPropProtection(ply)
-- Support for prop protections
if self.CPPICanUse then
local use = self:CPPICanUse(ply) or false
if not use then
return false
end
end

if SERVER then
local use = hook.Run("PlayerUse", ply, radio)
if not use then
return false
end
end

return true
end

function ENT:CanControlInternal(ply, userEntity)
if self:GetDisableInput() then return false end

if not self:HasGUI() then return false end
if self:GetDisableDisplay() then return false end

-- Check the player for +use permission
if not self:CheckPropProtection(ply) then
if not StreamRadioLib.CheckPropProtectionAgainstUse(self, ply) then
return false
end

Expand Down Expand Up @@ -118,13 +99,22 @@ function ENT:CanControl(ply, userEntity)
end

local cacheId = tostring(ply) .. "_" .. tostring(userEntity)
local now = RealTime()

-- cache the check result for a short time to avoid running expensive functions every tick
if self._canControlCacheExpire and self._canControlCacheExpire <= now then
self._canControlCache = nil
self._canControlCacheExpire = nil
end

if self._canControlCache and self._canControlCache[cacheId] ~= nil then
return self._canControlCache[cacheId]
end

self._canControlCache = self._canControlCache or {}
self._canControlCache[cacheId] = nil
if not self._canControlCache then
self._canControlCache = {}
self._canControlCacheExpire = now + 0.25
end

local result = self:CanControlInternal(ply, userEntity)

Expand Down Expand Up @@ -176,7 +166,11 @@ function ENT:GetCursor( ply, trace, userEntity )
end

local scale = self:GetScale()
if scale <= 0 then return false end

local pos, ang = self:GetDisplayPos()
if not pos then return false end
if not ang then return false end

local TraceHitPos = util.IntersectRayWithPlane( trace.StartPos, trace.Normal, pos, ang:Up( ) )

Expand Down Expand Up @@ -211,7 +205,7 @@ function ENT:CallModelFunction(index, ...)
local status, err, a, b, c, d, e, f, g = pcall( self.ModelData[index], self.ModelData, self, ... )

if not status and err then
ErrorNoHalt( err .. "\n" )
StreamRadioLib.ErrorNoHaltWithStack( err .. "\n" )
return nil
end

Expand Down Expand Up @@ -356,9 +350,6 @@ end

function ENT:FastThink()
BaseClass.FastThink(self)

self._canControlCache = {}

self:ControlThink(self:GetLastUser(), self:GetLastUsingEntity())
end

Expand Down
2 changes: 1 addition & 1 deletion lua/entities/sent_streamradio/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ function ENT:OnWireInputTrigger(name, value, wired)
end

local delta = math.abs(curtime - value)
local maxDelta = 0.25
local maxDelta = engine.TickInterval() * 4

if delta < maxDelta then
return
Expand Down
6 changes: 3 additions & 3 deletions lua/streamradio_core/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ local function ErrorCheckArg( var, tright, argn, funcname, level )
local t = type( var )

if t ~= tright then
ErrorNoHaltWithStack( string.format( "bad argument #%i to '%s' (%s or nil expected, got %s)", argn, funcname, tright, t ), level or 3 )
StreamRadioLib.ErrorNoHaltWithStack( string.format( "bad argument #%i to '%s' (%s or nil expected, got %s)", argn, funcname, tright, t ), level or 3 )
return false
end

Expand All @@ -92,7 +92,7 @@ local function ErrorCheckRadioSettings( settings, argn, funcname, level )
local t = type( v )
local tright = ValidTypes[k]
if not tright or t == tright then continue end
ErrorNoHaltWithStack( string.format( "bad datatype at index '%s' of argument #%i at '%s' (%s or nil expected, got %s)", k, argn, funcname, tright, t ), level )
StreamRadioLib.ErrorNoHaltWithStack( string.format( "bad datatype at index '%s' of argument #%i at '%s' (%s or nil expected, got %s)", k, argn, funcname, tright, t ), level )

return false
end
Expand Down Expand Up @@ -138,7 +138,7 @@ function StreamRadioLib.SpawnRadio( ply, model, pos, ang, settings )
if StreamRadioLib.Msg then
StreamRadioLib.Msg( ply, err )
else
ErrorNoHaltWithStack( err, 2 )
StreamRadioLib.ErrorNoHaltWithStack( err, 2 )
end

return
Expand Down
12 changes: 6 additions & 6 deletions lua/streamradio_core/classes/gui_controller.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ local ColY = Color(255,255,0, 60)
local tune_nohdr = Vector( 0.80, 0, 0 )
local CursorMat = StreamRadioLib.GetCustomPNG("cursor")

local catchAndErrorNoHalt = StreamRadioLib.CatchAndErrorNoHalt
local catchAndErrorNoHaltWithStack = StreamRadioLib.CatchAndErrorNoHaltWithStack

local g_listengroup = 0

Expand Down Expand Up @@ -116,7 +116,7 @@ function CLASS:Create()
render.PushFilterMin(TEXFILTER.NONE)
render.PushFilterMag(TEXFILTER.NONE)

catchAndErrorNoHalt(self._RenderInternal, self)
catchAndErrorNoHaltWithStack(self._RenderInternal, self)

render.PopFilterMag()
render.PopFilterMin()
Expand Down Expand Up @@ -308,28 +308,28 @@ function CLASS:RenderSystem()
render.SetToneMappingScaleLinear(tune_nohdr) -- Turns off hdr

surface.SetAlphaMultiplier(alpha)
catchAndErrorNoHalt(self.DrawBorder, self)
catchAndErrorNoHaltWithStack(self.DrawBorder, self)
surface.SetAlphaMultiplier(1)

if self:HasRendertarget() then
surface.SetDrawColor(255, 255, 255, alpha * 255)

catchAndErrorNoHalt(self._RT.Render, self._RT)
catchAndErrorNoHaltWithStack(self._RT.Render, self._RT)

surface.SetDrawColor(255, 255, 255, 255)
self.FrameTime = self._RT:ProfilerTime("Render")
else
self:ProfilerStart("Render_rtfallback")
surface.SetAlphaMultiplier(alpha)

catchAndErrorNoHalt(self._RenderInternal, self)
catchAndErrorNoHaltWithStack(self._RenderInternal, self)

surface.SetAlphaMultiplier(1)
self.FrameTime = self:ProfilerEnd("Render_rtfallback")
end

surface.SetAlphaMultiplier(alpha)
catchAndErrorNoHalt(self.DrawCursor, self)
catchAndErrorNoHaltWithStack(self.DrawCursor, self)
surface.SetAlphaMultiplier(1)

render.SetToneMappingScaleLinear(oldtune) -- Resets hdr
Expand Down
4 changes: 2 additions & 2 deletions lua/streamradio_core/classes/rendertarget.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ end
local BASE = CLASS:GetBaseClass()
local g_classname = CLASS:GetClassname()

local catchAndErrorNoHalt = StreamRadioLib.CatchAndErrorNoHalt
local catchAndErrorNoHaltWithStack = StreamRadioLib.CatchAndErrorNoHaltWithStack


local g_RenderTargetsCache = CLASS:GetGlobalVar("rendertarget_RenderTargetsCache", {})
Expand Down Expand Up @@ -345,7 +345,7 @@ function CLASS:Update()
render.PushRenderTarget(self._RT.tex, 0, 0, w, h)
render.Clear(0, 0, 0, 0, true)
cam.Start2D()
catchAndErrorNoHalt(self.CallHook, self, "OnRender")
catchAndErrorNoHaltWithStack(self.CallHook, self, "OnRender")
cam.End2D()
render.PopRenderTarget()
self:ProfilerEnd("Render")
Expand Down
5 changes: 3 additions & 2 deletions lua/streamradio_core/classes/stream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ local SERVER = SERVER
local CLIENT = CLIENT

local EmptyVector = Vector()
local catchAndErrorNoHalt = StreamRadioLib.CatchAndErrorNoHalt
local catchAndErrorNoHaltWithStack = StreamRadioLib.CatchAndErrorNoHaltWithStack

local BASS3 = BASS3 or {}

Expand Down Expand Up @@ -1235,7 +1235,7 @@ function CLASS:_PlayStreamInternal(URL, URLtype, no3d, noBlock, retrycount)
end

local safeCallback = function(...)
catchAndErrorNoHalt(callback, ...)
catchAndErrorNoHaltWithStack(callback, ...)
end

if not URLonline then
Expand Down Expand Up @@ -1871,6 +1871,7 @@ function CLASS:GetType()
end

function CLASS:SetVolume( volume )
if CLIENT then return end
if not self.Valid then return end
self.Volume.SVMul = volume or 1
end
Expand Down
5 changes: 5 additions & 0 deletions lua/streamradio_core/classes/ui/radio/gui_browser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ function CLASS:Create()
self.Errorbox:SetNWName("err")
self.Errorbox:SetSkinIdentifyer("error")

if IsValid(self.Errorbox.CloseButton) and CLIENT then
-- The error box is handled on the server, so the client shouldn't touch it.
self.Errorbox.CloseButton.DoClick = nil
end

self.Errorbox.OnCloseClick = function()
self:GoUpPath()
end
Expand Down
5 changes: 5 additions & 0 deletions lua/streamradio_core/classes/ui/radio/gui_player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function CLASS:Create()
end

self.VolumeBar.OnFractionChangeEdit = function(this, v)
if CLIENT then return end
if not IsValid(self.StreamOBJ) then return end
self.StreamOBJ:SetVolume(v)
end
Expand Down Expand Up @@ -122,6 +123,10 @@ function CLASS:Create()
self.CloseButton:SetSize(200, 60)
self.CloseButton:SetText("Back")
self.CloseButton.DoClick = function()
if CLIENT then
return
end

if self.State then
self.State.Error = 0
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ function CLASS:Create()
self.VolumeDownButton:SetSkinIdentifyer("button")
self.VolumeDownButton:SetTooltip("Decrease volume")
self.VolumeDownButton.OnMousePressed = function()
if CLIENT then return end
if not IsValid(self.StreamOBJ) then return end

local newvol = self.StreamOBJ:GetVolume()
Expand All @@ -171,6 +172,7 @@ function CLASS:Create()
self.VolumeUpButton:SetSkinIdentifyer("button")
self.VolumeUpButton:SetTooltip("Increase volume")
self.VolumeUpButton.OnMousePressed = function()
if CLIENT then return end
if not IsValid(self.StreamOBJ) then return end

local newvol = self.StreamOBJ:GetVolume()
Expand Down Expand Up @@ -270,13 +272,14 @@ function CLASS:Create()
return FormatTimeleft(time, len)
end

-- @TODO: fix that seaking is CLIENT -> SERVER instead if SERVER -> CLIENT
self.PlayBar.OnFractionChangeEdit = function(this, v)
if not IsValid(self.StreamOBJ) then return end

local noise = math.random() * 0.00001
local len = self.StreamOBJ:GetMasterLength()

-- Set a fake value that is minimal off target to force a change detection when the right one is set
-- add a minimal noise to the value, so we force the change in any case
self.StreamOBJ:SetTime(len * v - noise, true)
end

Expand Down Expand Up @@ -548,6 +551,10 @@ function CLASS:UpdateFromStream()

local isEndlessOrNoStream = StreamOBJ:IsEndless() or StreamOBJ:IsLoading() or StreamOBJ:GetError() ~= 0 or StreamOBJ:GetMuted()

-- @TODO: Fix that seaking is CLIENT -> SERVER instead if SERVER -> CLIENT.
-- That's because self.PlayBar is disabled on the server as BASS streams don't exist on servers.
-- Thus these checks below are buggy and will be fixed some day. It is difficult to fix right now.

if IsValid(self.PlayBar) and self.PlayBar:IsVisible() then
if isEndlessOrNoStream then
self.PlayBar:SetFraction(0)
Expand Down
13 changes: 9 additions & 4 deletions lua/streamradio_core/client/cl_lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,18 @@ local g_inRenderScene = false
hook.Add( "RenderScene", "Streamradio_CamInfo", function( origin, angles, fov )
if not StreamRadioLib then return end
if not StreamRadioLib.Loaded then return end
if not StreamRadioLib.HasSpawnedRadios() then return end

if g_inRenderScene then return end
g_inRenderScene = true

if StreamRadioLib.VR.IsActive() then
g_camPos = nil
g_inRenderScene = false

return
end

if g_inRenderScene then return end

g_inRenderScene = true
g_camPos = origin
g_inRenderScene = false
end )
Expand All @@ -64,6 +67,7 @@ local g_lastradio = nil
local function ReleaseLastRadioControl()
if not StreamRadioLib then return end
if not StreamRadioLib.Loaded then return end
if not StreamRadioLib.HasSpawnedRadios() then return end

local ply = LocalPlayer()
if not IsValid( ply ) then return end
Expand Down Expand Up @@ -133,6 +137,7 @@ end
hook.Add("Think", "Streamradio_Control", function( )
if not StreamRadioLib then return end
if not StreamRadioLib.Loaded then return end
if not StreamRadioLib.HasSpawnedRadios() then return end

local ply = LocalPlayer()
if not IsValid( ply ) then return end
Expand Down Expand Up @@ -265,7 +270,7 @@ do
local TestChannel = StreamRadioLib._TestChannel or StreamRadioLib.CreateOBJ("stream")

if not IsValid(TestChannel) then
ErrorNoHaltWithStack("Could not create the TestChannel!\n")
StreamRadioLib.ErrorNoHaltWithStack("Could not create the TestChannel!\n")
return
end

Expand Down
Loading

0 comments on commit 56bcb1f

Please sign in to comment.