Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Listen-Only Hooks #2119

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 91 additions & 8 deletions garrysmod/lua/includes/modules/hook.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ local pairs = pairs
local isfunction = isfunction
local isstring = isstring
local isnumber = isnumber
local isbool = isbool
local IsValid = IsValid
local type = type
local ErrorNoHaltWithStack = ErrorNoHaltWithStack
local error = error

module( "hook" )

local Hooks = {}
local ListenersPre = {}
local ListenersPost = {}

--[[---------------------------------------------------------
Name: GetTable
Expand All @@ -20,18 +22,26 @@ function GetTable()
return Hooks
end

--[[---------------------------------------------------------
Name: GetListenTable
Desc: Returns the pre-listeners and post-listeners hook tables.
-----------------------------------------------------------]]
function GetListenTable()
return ListenersPre, ListenersPost
end

--[[---------------------------------------------------------
Name: Add
Args: string hookName, any identifier, function func
Desc: Add a hook to listen to the specified event.
-----------------------------------------------------------]]
function Add( event_name, name, func )

if ( !isstring( event_name ) ) then ErrorNoHaltWithStack( "bad argument #1 to 'Add' (string expected, got " .. type( event_name ) .. ")" ) return end
if ( !isfunction( func ) ) then ErrorNoHaltWithStack( "bad argument #3 to 'Add' (function expected, got " .. type( func ) .. ")" ) return end
if ( !isstring( event_name ) ) then ErrorNoHaltWithStack( "bad argument #1 to 'Add' (string expected, got " .. type( event_name ) .. ")") return end
if ( !isfunction( func ) ) then ErrorNoHaltWithStack( "bad argument #3 to 'Add' (function expected, got " .. type( func ) .. ")") return end

local notValid = name == nil || isnumber( name ) or isbool( name ) or isfunction( name ) or !name.IsValid or !IsValid( name )
if ( !isstring( name ) and notValid ) then ErrorNoHaltWithStack( "bad argument #2 to 'Add' (string expected, got " .. type( name ) .. ")" ) return end
local notValid = !name or name == true or ( !isstring( name ) and ( isnumber( name ) or isfunction( name ) or !IsValid( name ) ) )
if ( notValid ) then ErrorNoHaltWithStack( "bad argument #2 to 'Add' (string expected, got " .. type( name ) .. ")") return end

if ( Hooks[ event_name ] == nil ) then
Hooks[ event_name ] = {}
Expand All @@ -41,6 +51,30 @@ function Add( event_name, name, func )

end

--[[---------------------------------------------------------
Name: Listen
Args: string eventName, any name, bool isPostHook, function func
Desc: Add a listen only hook to the specified event.
-----------------------------------------------------------]]
function Listen( eventName, name, isPostHook, func )

if ( !isstring(eventName) ) then error( "bad argument #1 to 'Listen' (string expected, got " .. type( eventName ) .. ")", 2 ) return end
if ( !isfunction(func) ) then error( "bad argument #3 to 'Listen' (function expected, got " .. type( func ) .. ")", 2 ) return end

local notValid = !name or name == true or ( !isstring( name ) and ( isnumber( name ) or isfunction( name ) or !IsValid( name ) ) )
if ( notValid ) then error( "bad argument #2 to 'Listen' (string expected, got " .. type( name ) .. ")", 2 ) return end

local tbl = isPostHook and ListenersPost or ListenersPre
local tab = tbl[ eventName ]

if ( !tab ) then
tab = {}
tbl[ eventName ] = tab
end

tab[ name ] = func

end

--[[---------------------------------------------------------
Name: Remove
Expand All @@ -51,15 +85,33 @@ function Remove( event_name, name )

if ( !isstring( event_name ) ) then ErrorNoHaltWithStack( "bad argument #1 to 'Remove' (string expected, got " .. type( event_name ) .. ")" ) return end

local notValid = isnumber( name ) or isbool( name ) or isfunction( name ) or !name.IsValid or !IsValid( name )
if ( !isstring( name ) and notValid ) then ErrorNoHaltWithStack( "bad argument #2 to 'Remove' (string expected, got " .. type( name ) .. ")" ) return end
local notValid = !name or name == true or ( !isstring( name ) and ( isnumber( name ) or isfunction( name ) or !IsValid( name ) ) )
if ( notValid ) then ErrorNoHaltWithStack( "bad argument #2 to 'Remove' (string expected, got " .. type( name ) .. ")" ) return end

if ( !Hooks[ event_name ] ) then return end

Hooks[ event_name ][ name ] = nil

end

--[[---------------------------------------------------------
Name: Forget
Args: string eventName, any name, bool isPostHook
Desc: Removes the listen-only hook with the given indentifier.
-----------------------------------------------------------]]
function Forget( eventName, name, isPostHook )

if ( !isstring( eventName ) ) then error( "bad argument #1 to 'Forget' (string expected, got " .. type( eventName ) .. ")", 2 ) return end
if ( name == nil ) then error( "bad argument #2 to 'Forget' (any value expected, got nil)", 2 ) return end

local tbl = isPostHook and ListenersPost or ListenersPre
local tab = tbl[ eventName ]

if ( tab ) then
tab[ name ] = nil
end

end

--[[---------------------------------------------------------
Name: Run
Expand All @@ -72,12 +124,41 @@ end


--[[---------------------------------------------------------
Name: Run
Name: Call
Args: string hookName, table gamemodeTable, vararg args
Desc: Calls hooks associated with the hook name.
-----------------------------------------------------------]]
local function callHooksNoReturn( tbl, name, ... )

local tab = tbl[ name ]
if ( !tab ) then return end

for k, func in pairs( tab ) do

if ( isstring( k ) ) then

func( ... )

else
if ( IsValid( k ) ) then

func( k, ... )

else

tab[ k ] = nil

end
end

end

end

function Call( name, gm, ... )

callHooksNoReturn( ListenersPre, name, ... )

--
-- Run hooks
--
Expand Down Expand Up @@ -124,6 +205,8 @@ function Call( name, gm, ... )
end
end

callHooksNoReturn( ListenersPost, name, ... )

--
-- Call the gamemode function
--
Expand Down