Skip to content

Commit

Permalink
Anti-Abuse / security changes, bugfixes, better UX and better perform…
Browse files Browse the repository at this point in the history
…ance.

UX:
- Moved error buttons to the side to make more space for the error message.
- Added entity options (C-Menu > Right click) for the radio.
- Added clientside only options to the entity options and entity property editor for volume and muting. (Not affected by Prop Protection)
- Added a clientside only way to look up the error state and the URL on GUI less radios (e.g. speakers). (Not affected by Prop Protection)
- Added a better explanation for "error 20".
- Added more error codes for future updates.
- Added mute option (not clientside!) to the toolgun and added seperator lines to its UI.

Performance / Networking:
- Networking is now delayed to ease on the server performance.
- The GUI is loaded with a delay to avoid freezes on radio spawns.
- The GUI is actually deleted when disabled instead of just being hidden.
- Fixed freezes when entering/leaving a room full of radios.
- The radio being randomly broken/desynced (empty or white screen) on spawn is a way less likely to happen. If it does disabling/enabling the GUI can fix it.

Anti-Abuse / Security:
- Radios from other players can be muted via the addon settings. Does not support buddies.
- Individual radios can be muted on the clientside, even if Prop Protection would block access otherwise.
- Individual radios can have their volume changed the clientside, even if Prop Protection would block access otherwise.
- Added support to the cfc_cl_http_whitelist addon. It is a security addon that whitelist and monitors HTTP and streaming requests. The Radio has a decicated error state for blocked URLs and content now.
- Clientside GM_BASS3 loading can be disabled by the server. (sv_streamradio_bass3_allow_client 0)

ConVars:
- Changed the CVar default of sv_streamradio_rebuildplaylists_community_auto to 2. Pre-existing installs are not affected.
- Added sv_streamradio_bass3_enable: When set to 1, it uses GM_BASS3 on the server if installed. Default: 1
- Added sv_streamradio_bass3_allow_client: Allows connected clients to use GM_BASS3 when set to 1. Overrides cl_streamradio_bass3_enable. Default: 1
- Added cl_streamradio_bass3_enable: When set to 1, it uses GM_BASS3 if installed and allowed on the server. Default: 1

GM_BASS3:
- If installed GM_BASS3 is lazy loaded now. It only loads if it is actually needed by an radio. GM_BASS3 is not supported on x86-64 branches.
  • Loading branch information
Grocel committed Jul 19, 2023
1 parent d40c39a commit eabc71f
Show file tree
Hide file tree
Showing 79 changed files with 3,614 additions and 1,669 deletions.
464 changes: 75 additions & 389 deletions lua/autorun/streamradio_loader.lua

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions lua/entities/base_streamradio.lua
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ function ENT:IsMutedForPlayer(ply)
if not ply:IsPlayer() then return true end
if ply:IsBot() then return true end

if StreamRadioLib.IsMuted(ply) then
if StreamRadioLib.IsMuted(ply, self:GetRealRadioOwner()) then
return true
end

Expand All @@ -378,6 +378,10 @@ function ENT:IsMutedForAll()
return true
end

if self:GetSVMute() then
return true
end

local allplayers = player.GetHumans()

for k, v in pairs(allplayers) do
Expand Down Expand Up @@ -457,8 +461,6 @@ function ENT:FastThink()
return
end

LIBNetwork.Pull(self)

if SERVER then
if self.__IsWiremodLoaded then
self:WiremodThink()
Expand Down
198 changes: 149 additions & 49 deletions lua/entities/base_streamradio_gui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ ENT.AdminOnly = false
local ang_zero = Angle( )
local vec_zero = Vector( )

local g_displayBuildTimer = 0

function ENT:SetScale(scale)
self.Scale = scale or 0
end
Expand All @@ -28,7 +30,7 @@ function ENT:SetDisplayPosAng(pos, ang)
end

function ENT:GetDisplayPos( )
if not self:HasGUI() then return end
if self.NoDisplay then return end
if self:GetDisableDisplay() then return end

local pos = self:GetPos( )
Expand Down Expand Up @@ -242,31 +244,46 @@ function ENT:SetUpModel()

self:SetSoundPosAng(MD.SoundPosOffset, MD.SoundAngOffset)

if self.NoDisplay then
if IsValid(self.GUI_Main) then
self.GUI_Main:Remove()
self.GUI_Main = nil
end
if self.OnModelSetup then
self:OnModelSetup()
end
end

if IsValid(self.GUI) then
self.GUI:Remove()
self.GUI = nil
end
function ENT:RemoveGui()
local tmpGui = self.GUI
local tmpGuiMain = self.GUI_Main

if self.OnSetupModelSetup then
self:OnSetupModelSetup()
end
local hasGui = IsValid(tmpGui)
local hasGuiMain = IsValid(tmpGuiMain)

return
if (hasGui or hasGuiMain) and self.OnGUIRemove then
self:OnGUIRemove(tmpGui, tmpGuiMain)
end

self:SetupGui()
self.GUI = nil
self.GUI_Main = nil

if hasGui then
tmpGui:Remove()
tmpGui = nil
end

if self.OnSetupModelSetup then
self:OnSetupModelSetup()
if hasGuiMain then
tmpGuiMain:Remove()
tmpGuiMain = nil
end
end

function ENT:ResetGui()
self:RemoveGui()

if self.NoDisplay or self:GetDisableDisplay() then
return
end

self:SetupGui()
end

function ENT:SetupGui()
if not IsValid(self.GUI) then
self.GUI = StreamRadioLib.CreateOBJ("gui_controller")
Expand Down Expand Up @@ -319,6 +336,10 @@ function ENT:SetupGui()

self.GUI:SetSkin(LIBSkin.GetDefaultSkin())
self.GUI:PerformRerender(true)

if self.OnGUISetup then
self:OnGUISetup(self.GUI, self.GUI_Main)
end
end

function ENT:StreamOnConnect(stream, channel, metadata)
Expand Down Expand Up @@ -359,8 +380,34 @@ function ENT:GetGUIMain()
return self.GUI_Main
end

function ENT:PollGuiSetup()
if self.NoDisplay then
return
end

if self:GetDisableDisplay() then
return
end

if self.GUI then
return
end

if SysTime() > g_displayBuildTimer then
self:SetupGui()

-- delay the GUI rebuild in case many newly spawned radios are seen at once
g_displayBuildTimer = SysTime() + 0.2
end
end

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

if SERVER then
self:PollGuiSetup()
end

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

Expand Down Expand Up @@ -447,20 +494,36 @@ function ENT:SetupDataTables()
}
})

self:AddDTNetworkVar( "Bool", "DisableSpectrum", {
KeyName = "DisableSpectrum",
Edit = {
category = "GUI",
title = "Disable spectrum",
type = "Boolean",
order = 12
}
})

self:AddDTNetworkVar( "Bool", "EnableDebug", {
KeyName = "EnableDebug",
Edit = {
category = "GUI",
title = "Show debug panel",
type = "Boolean",
order = 12
order = 13
}
})

LIBNetwork.SetDTVarCallback(self, "EnableDebug", function(this, name, oldv, newv)
if not IsValid(self.GUI) then return end
self.GUI:SetDebug(newv)
end)

if CLIENT then
LIBNetwork.SetDTVarCallback(self, "DisableDisplay", function(this, name, oldv, newv)
self:RemoveGui()
end)
end
end

function ENT:IsPlaylistEnabled()
Expand All @@ -484,27 +547,8 @@ function ENT:Initialize()
end

function ENT:OnRemove()
local GUI_Main = self.GUI_Main
local GUI = self.GUI

self:CallModelFunction("OnRemove", model)

-- We run it in a timer to ensure the entity is actually gone
timer.Simple(0.05, function()
if IsValid(self) then
return
end

if IsValid(GUI_Main) then
GUI_Main:Remove()
GUI_Main = nil
end

if IsValid(GUI) then
GUI:Remove()
GUI = nil
end
end)
self:RemoveGui()

BaseClass.OnRemove(self)
end
Expand All @@ -525,7 +569,17 @@ function ENT:OnPlayerShown()
-- Override me
end

function ENT:OnSetupModelSetup()
function ENT:OnModelSetup()
-- Override me
end

function ENT:OnGUISetup()
if self._postClasssystemPasteLoadDupeOnGUISetup then
self:PostClasssystemPaste()
end
end

function ENT:OnGUIRemove()
-- Override me
end

Expand All @@ -543,13 +597,12 @@ if CLIENT then
function ENT:CanSeeDisplay()
if not self.__IsLibLoaded then return false end

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

local ply = LocalPlayer()
if StreamRadioLib.IsGUIHidden(ply) then return false end
if not self:OnGUIShowCheck(ply) then return false end

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

Expand All @@ -569,7 +622,6 @@ if CLIENT then

function ENT:GetCurserFromLastUser()
if not self.__IsLibLoaded then return false end
if not IsValid(self.GUI) then return false end

local lastUser = self:GetLastUser()
local userEntity = self:GetLastUsingEntity()
Expand All @@ -585,14 +637,48 @@ if CLIENT then
return self:GetCursor(lastUser, nil, userEntity)
end

function ENT:ShouldRemoveGUI()
local ply = LocalPlayer()

if StreamRadioLib.IsGUIHidden(ply) then
return true
end

return false
end

function ENT:DrawGUI()
if not self.__IsLibLoaded then return end
if not IsValid(self.GUI) then return end

if not self:CanSeeDisplay() then return end
if self.NoDisplay then
return
end

local ply = LocalPlayer()
if not self:CheckDistanceToEntity(ply, StreamRadioLib.GetDrawDistance(), nil, StreamRadioLib.GetCameraViewPos(ply)) then return end
if self:GetDisableDisplay() then
return
end

if self:ShouldRemoveGUI() then
if self.GUI then
self:RemoveGui()
end

return
end

if not self:CheckDistanceToEntity(ply, StreamRadioLib.GetDrawDistance(), nil, StreamRadioLib.GetCameraViewPos(ply)) then
return true
end

self:PollGuiSetup()

if not IsValid(self.GUI) then
return
end

if not self:CanSeeDisplay() then
return false
end

local lastUser = self:GetLastUsingEntity()
local scale = self:GetScale()
Expand Down Expand Up @@ -622,7 +708,9 @@ if CLIENT then
function ENT:CanDrawSpectrum()
if not self.__IsLibLoaded then return false end
if not IsValid(self.GUI) then return false end

if StreamRadioLib.IsSpectrumHidden() then return false end
if self:GetDisableSpectrum() then return false end

if not self:CanSeeDisplay() then return false end

Expand Down Expand Up @@ -667,8 +755,20 @@ else
end

function ENT:PostClasssystemPaste()
BaseClass.PostClasssystemPaste( self )
if not IsValid(self.GUI) then return end
self.GUI:LoadFromDupe()
BaseClass.PostClasssystemPaste(self)

if not IsValid(self.GUI) then
self._postClasssystemPasteLoadDupeOnGUISetup = true
return
end

self._postClasssystemPasteLoadDupeOnGUISetup = nil

timer.Simple(0.25, function()
if not IsValid(self) then return end
if not IsValid(self.GUI) then return end

self.GUI:LoadFromDupe()
end)
end
end
Loading

0 comments on commit eabc71f

Please sign in to comment.