Advertisement
zSatan

Hook.lua

Dec 17th, 2016
362
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.49 KB | None | 0 0
  1. do
  2.     if (Hook ~= nil) then
  3.         Hook:ClearAllHooks()
  4.     end
  5.    
  6.     Hook = { hookList = {}, enabled = true }
  7.    
  8.     function Hook:AddReplacementHook(originalFctName, newFct)
  9.         local hookDef = self.hookList[originalFctName]
  10.         if (hookDef == nil) then
  11.             hookDef = Hook:InitHook(originalFctName)
  12.         end
  13.         hookDef.replacement = newFct
  14.     end
  15.    
  16.    
  17.     function Hook:RemoveReplacementHook(originalFct)
  18.         local hookDef = self.hookList[originalFctName]
  19.         if (hookDef ~= nil) then
  20.             hookDef.replacement = nil
  21.         end
  22.     end
  23.    
  24.     -- PRIVATE
  25.     function Hook:GenericHook(originalFctName, ...)
  26.         local hookDef = self.hookList[originalFctName]
  27.         if (hookDef ~= nil) then
  28.             if (self.enabled == true and hookDef.enabled == true) then
  29.                 -- Execute pre filters
  30.                 local pre_filter_count = table.getn(hookDef.pre)
  31.                 for i=1, pre_filter_count do
  32.                     local returnedValue = hookDef.pre[i].fct(unpack(arg))
  33.                     if (returnedValue == false) then
  34.                         return;
  35.                     end
  36.                 end
  37.                
  38.                 -- Execute key function (either original or replacement)
  39.                 local returnedValues = nil
  40.                 if (hookDef.replacement ~= nil) then
  41.                     returnedValues = { hookDef.replacement(unpack(arg)) }
  42.                 else
  43.                     returnedValues = { hookDef.original(unpack(arg)) }
  44.                 end
  45.                
  46.                 -- Execute post filters
  47.                 local post_filter_count = table.getn(hookDef.post)
  48.                 for i=1, post_filter_count do
  49.                     newReturnedValues = { hookDef.post[i].fct(returnedValues, unpack(arg)) }
  50.                     if (newReturnedValues ~= nil and table.getn(newReturnedValues) > 0 ) then
  51.                         returnedValues = newReturnedValues
  52.                     end
  53.                 end
  54.                
  55.                 local a, b, c =  unpack(returnedValues)
  56.                 return unpack(returnedValues)
  57.             else
  58.                 return hookDef.original(unpack(arg))
  59.             end
  60.         end
  61.     end
  62.    
  63.     -- PRIVATE
  64.     function Hook:InitHook(originalFctName)
  65.         local hookDef = { pre={} , post={} , original=nil, replacement=nil, enabled=true }
  66.         self.hookList[originalFctName] = hookDef
  67.         hookDef.original = _G[originalFctName]
  68.         _G[originalFctName] =   function (...)
  69.             return Hook:GenericHook(originalFctName, unpack(arg) )
  70.         end
  71.         return hookDef
  72.     end
  73.    
  74.     function Hook:AddPreHook(originalFctName, hookFct, priorityOrder)
  75.         local hookDef = self.hookList[originalFctName]
  76.         if (hookDef == nil) then
  77.             hookDef = Hook:InitHook(originalFctName)
  78.         end
  79.         -- Avoid undefined priorityOrder
  80.         if (priorityOrder == nil) then
  81.             priorityOrder = 999999
  82.         end
  83.         -- Check if the hook is already recorded
  84.         local hookCount = table.getn(hookDef.pre)
  85.         local found = false
  86.         for i=1, hookCount do
  87.             if (hookDef.pre[i].fct == hookFct) then
  88.                 found = true
  89.                 hookDef.pre[i].order = priorityOrder
  90.             end
  91.         end
  92.         if (found == false) then
  93.             table.insert(hookDef.pre, {fct = hookFct, order = priorityOrder} )
  94.         end
  95.         -- Force a re-sorting of hooks to handle execution order
  96.         Hook:SortHooks(hookDef.pre)
  97.     end
  98.    
  99.     -- TODO
  100.     function Hook:RemovePreHook(originalFctName, hookFct, priorityOrder)
  101.         print("ERROR >> Hook:RemovePreHook() is not yet implemented !!")
  102.     end
  103.    
  104.     function Hook:AddPostHook(originalFctName, hookFct, priorityOrder)
  105.         local hookDef = self.hookList[originalFctName]
  106.         if (hookDef == nil) then
  107.             hookDef = Hook:InitHook(originalFctName)
  108.         end
  109.         -- Avoid undefined priorityOrder
  110.         if (priorityOrder == nil) then
  111.             priorityOrder = 999999
  112.         end
  113.         -- Check if the hook is already recorded
  114.         local hookCount = table.getn(hookDef.post)
  115.         local found = false
  116.         for i=1, hookCount do
  117.             if (hookDef.post[i].fct == hookFct) then
  118.                 found = true
  119.                 hookDef.post[i].order = priorityOrder
  120.             end
  121.         end
  122.         if (found == false) then
  123.             table.insert(hookDef.post, {fct = hookFct, order = priorityOrder} )
  124.         end
  125.         -- Force a re-sorting of hooks to handle execution order
  126.         Hook:SortHooks(hookDef.post)
  127.     end
  128.    
  129.    
  130.     -- TODO
  131.     function Hook:RemovePostHook(originalFctName, hookFct, priorityOrder)
  132.         print("ERROR >> Hook:RemovePostHook() is not yet implemented !!")
  133.     end
  134.    
  135.     function Hook:DisableHooks(originalFctName)
  136.         local hookDef = self.hookList[originalFctName]
  137.         if (hookDef ~= nil) then
  138.             hookDef.enabled = false
  139.         end
  140.     end
  141.    
  142.     function Hook:EnableHooks(originalFctName)
  143.         local hookDef = self.hookList[originalFctName]
  144.         if (hookDef ~= nil) then
  145.             hookDef.enabled = true
  146.         end
  147.     end
  148.    
  149.     function Hook:ClearHooks(originalFctName)
  150.         local hookDef = self.hookList[originalFctName]
  151.         if (hookDef ~= nil) then
  152.             hookDef.enabled = true
  153.         end
  154.         _G[originalFctName] = hookDef.original
  155.         self.hookList[originalFctName] = nil
  156.     end
  157.    
  158.    
  159.     -- TODO
  160.     function Hook:ClearAllHooks()
  161.         --print("ERROR >> Hook:ClearAllHooks() is not yet implemented !!")
  162.         for i,v in pairs(self.hookList) do
  163.             Hook:ClearHooks(i)
  164.         end
  165.     end
  166.    
  167.     function Hook:DisableAllHooks()
  168.         self.enabled = false
  169.     end
  170.    
  171.     function Hook:EnableAllHooks()
  172.         self.enabled = true
  173.     end
  174.    
  175.     function Hook:LoadHookFile(filename)
  176.         local split =   function (str, delim, maxNb)
  177.                             -- Eliminate bad cases...
  178.                             if string.find(str, delim) == nil then
  179.                                 return { str }
  180.                             end
  181.                             if maxNb == nil or maxNb < 1 then
  182.                                 maxNb = 0    -- No limit
  183.                             end
  184.                             local result = {}
  185.                             local pat = "(.-)" .. delim .. "()"
  186.                             local nb = 0
  187.                             local lastPos
  188.                             for part, pos in string.gfind(str, pat) do
  189.                                 nb = nb + 1
  190.                                 result[nb] = part
  191.                                 lastPos = pos
  192.                                 if nb == maxNb then break end
  193.                             end
  194.                             -- Handle the last field
  195.                             if nb ~= maxNb then
  196.                                 result[nb + 1] = string.sub(str, lastPos)
  197.                             end
  198.                             return result
  199.                         end
  200.    
  201.    
  202.    
  203.         file = assert(io.open(filename, "r"))
  204.         for line in file:lines() do
  205.             lineData = split(line, "|",3)
  206.            
  207.             -- Make sure original function is defined
  208.             if (_G[lineData[2]] ~= nil) then
  209.                 -- Make sure target function is defined
  210.                 if (_G[lineData[3]] ~= nil) then
  211.                     if (lineData[1] == "REPLACE") then
  212.                         Hook:AddReplacementHook(lineData[2], _G[lineData[3]])
  213.                     elseif (lineData[1] == "PRE") then
  214.                         Hook:AddPreHook(lineData[2], _G[lineData[3]], lineData[4])
  215.                     elseif (lineData[1] == "POST") then
  216.                         Hook:AddPostHook(lineData[2], _G[lineData[3]], lineData[4])
  217.                     else
  218.                         print("ERROR >> Hook:LoadHookFile() : Unrecongized type of hook ["..lineData[1].."] !!")
  219.                     end
  220.                 else
  221.                     print("ERROR >> Hook:LoadHookFile() : Function ["..lineData[3].."] is not defined !!")
  222.                 end
  223.             else
  224.                 print("ERROR >> Hook:LoadHookFile() : Function ["..lineData[2].."] is not defined !!")
  225.             end
  226.         end
  227.         io.close(file)
  228.     end
  229.    
  230.    
  231.     function Hook:SetHookPattern(pattern, hookType, hookFct, priority)
  232.         -- make sure hook fct is defined
  233.         if (hookFct == nil) then
  234.             print("ERROR >> Hook:SetHookPattern() : Hook function is not defined ["..hookFct.."] !!")  
  235.             return
  236.         end
  237.         -- Browse global def list
  238.         for key, value in pairs(_G) do
  239.             -- Filter to retrieve only functions
  240.             if (type(value) == "function") then
  241.                 -- Check the global function toward the provided pattern
  242.                 if (string.find(key, pattern) ~= nil) then
  243.                     if (hookType == "REPLACE") then
  244.                         Hook:AddReplacementHook(key, hookFct)
  245.                     elseif (hookType == "PRE") then
  246.                         Hook:AddPreHook(key, hookFct, priority)
  247.                     elseif (hookType == "POST") then
  248.                         Hook:AddPostHook(key, hookFct, priority)
  249.                     else
  250.                         print("ERROR >> Hook:SetHookPattern() : Unrecongized type of hook ["..hookType.."] !!")
  251.                     end
  252.                 end
  253.             end
  254.         end
  255.     end
  256.        
  257.     -- PRIVATE
  258.     function Hook:SortHooks(hookList)
  259.         local compareFct =  function (a,b)
  260.                                 return a.order < b.order
  261.                             end
  262.         table.sort(hookList, compareFct)
  263.     end
  264. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement