Advertisement
Guest User

Untitled

a guest
Aug 7th, 2020
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.24 KB | None | 0 0
  1. -- Developer: sbx320
  2. -- License: MIT
  3. -- Github Repos: https://github.com/sbx320/lua_utils
  4.  
  5. --// classlib
  6. --|| A library providing several tools to enhance OOP with MTA and Lua
  7. --\\
  8. SERVER = triggerServerEvent == nil
  9. CLIENT = not SERVER
  10. DEBUG = DEBUG or false
  11.  
  12. function enew(element, class, ...)
  13. -- DEBUG: Validate that we are not instantiating a class with pure virtual methods
  14. if DEBUG then
  15. for k, v in pairs(class) do
  16. assert(v ~= pure_virtual, "Attempted to instanciate a class with an unimplemented pure virtual method (" .. tostring(k) .. ")")
  17. end
  18. end
  19.  
  20. local instance = setmetatable({ element = element },
  21. {
  22. __index = class;
  23. __class = class;
  24. __newindex = class.__newindex;
  25. __call = class.__call;
  26. __len = class.__len;
  27. __unm = class.__unm;
  28. __add = class.__add;
  29. __sub = class.__sub;
  30. __mul = class.__mul;
  31. __div = class.__div;
  32. __pow = class.__pow;
  33. __concat = class.__concat;
  34. })
  35.  
  36. oop.elementInfo[element] = instance
  37.  
  38. local callDerivedConstructor;
  39. callDerivedConstructor = function(parentClasses, instance, ...)
  40. for k, v in pairs(parentClasses) do
  41. if rawget(v, "virtual_constructor") then
  42. rawget(v, "virtual_constructor")(instance, ...)
  43. end
  44. local s = superMultiple(v)
  45. if s then callDerivedConstructor(s, instance, ...) end
  46. end
  47. end
  48.  
  49. callDerivedConstructor(superMultiple(class), element, ...)
  50.  
  51. -- Call constructor
  52. if rawget(class, "constructor") then
  53. rawget(class, "constructor")(element, ...)
  54. end
  55. element.constructor = false
  56.  
  57. -- Add the destruction handler
  58. if isElement(element) then
  59. addEventHandler(triggerClientEvent ~= nil and
  60. "onElementDestroy" or
  61. "onClientElementDestroy", element, __removeElementIndex, false, "low-999999")
  62. end
  63. return element
  64. end
  65.  
  66. function new(class, ...)
  67. assert(type(class) == "table", "first argument provided to new is not a table")
  68.  
  69. -- DEBUG: Validate that we are not instantiating a class with pure virtual methods
  70. if DEBUG then
  71. for k, v in pairs(class) do
  72. assert(v ~= pure_virtual, "Attempted to instanciate a class with an unimplemented pure virtual method (" .. tostring(k) .. ")")
  73. end
  74. end
  75.  
  76. local instance = setmetatable({},
  77. {
  78. __index = class;
  79. __class = class;
  80. __newindex = class.__newindex;
  81. __call = class.__call;
  82. __len = class.__len;
  83. __unm = class.__unm;
  84. __add = class.__add;
  85. __sub = class.__sub;
  86. __mul = class.__mul;
  87. __div = class.__div;
  88. __pow = class.__pow;
  89. __concat = class.__concat;
  90. })
  91.  
  92. -- Call derived constructors
  93. local callDerivedConstructor;
  94. callDerivedConstructor = function(self, instance, ...)
  95. for k, v in pairs(self) do
  96. if rawget(v, "virtual_constructor") then
  97. rawget(v, "virtual_constructor")(instance, ...)
  98. end
  99. local s = superMultiple(v)
  100. if s then callDerivedConstructor(s, instance, ...) end
  101. end
  102. end
  103.  
  104. callDerivedConstructor(superMultiple(class), instance, ...)
  105.  
  106. -- Call constructor
  107. if rawget(class, "constructor") then
  108. rawget(class, "constructor")(instance, ...)
  109. end
  110. instance.constructor = false
  111.  
  112. return instance
  113. end
  114.  
  115. function delete(self, ...)
  116. if self.destructor then --if rawget(self, "destructor") then
  117. self:destructor(...)
  118. end
  119.  
  120. -- Prevent the destructor to be called twice
  121. self.destructor = false
  122.  
  123. local callDerivedDestructor;
  124. callDerivedDestructor = function(parentClasses, instance, ...)
  125. for k, v in pairs(parentClasses) do
  126. if rawget(v, "virtual_destructor") then
  127. rawget(v, "virtual_destructor")(instance, ...)
  128. end
  129. local s = superMultiple(v)
  130. if s then callDerivedDestructor(s, instance, ...) end
  131. end
  132. end
  133. callDerivedDestructor(superMultiple(self), self, ...)
  134. end
  135.  
  136. function superMultiple(self)
  137. if isElement(self) then
  138. assert(oop.elementInfo[self], "Cannot get the superclass of this element") -- at least: not yet
  139. self = oop.elementInfo[self]
  140. end
  141.  
  142. local metatable = getmetatable(self)
  143. if not metatable then
  144. return {}
  145. end
  146.  
  147. if metatable.__class then -- we're dealing with a class object
  148. return superMultiple(metatable.__class)
  149. end
  150.  
  151. if metatable.__super then -- we're dealing with a class
  152. return metatable.__super
  153. end
  154. end
  155.  
  156. function super(self)
  157. return superMultiple(self)[1]
  158. end
  159.  
  160. function classof(self)
  161. if isElement(self) then
  162. assert(oop.elementInfo[self], "Cannot get the class of this element") -- at least: not yet
  163. self = oop.elementInfo[self]
  164. end
  165.  
  166. local metatable = getmetatable(self)
  167. if metatable then
  168. return metatable.__class
  169. end
  170. return {}
  171. end
  172.  
  173. function inherit(from, what)
  174. assert(from, "Attempt to inherit a nil table value")
  175. if not what then
  176. local classt = setmetatable({}, { __index = _inheritIndex, __super = { from } })
  177. if from.onInherit then
  178. from.onInherit(classt)
  179. end
  180. return classt
  181. end
  182.  
  183. local metatable = getmetatable(what) or {}
  184. local oldsuper = metatable and metatable.__super or {}
  185. table.insert(oldsuper, 1, from)
  186. metatable.__super = oldsuper
  187. metatable.__index = _inheritIndex
  188.  
  189. -- Inherit __call
  190. for k, v in ipairs(metatable.__super) do
  191. if v.__call then
  192. metatable.__call = v.__call
  193. break
  194. end
  195. end
  196.  
  197. return setmetatable(what, metatable)
  198. end
  199.  
  200. function _inheritIndex(self, key)
  201. for k, v in pairs(superMultiple(self) or {}) do
  202. if v[key] then return v[key] end
  203. end
  204. return nil
  205. end
  206.  
  207. --- // __removeElementIndex()
  208. --- || @desc: This function calls delete on the hidden source parameter to invoke the destructor
  209. --- || !!! Avoid calling this function manually unless you know what you're doing! !!!
  210. --- \\
  211. function __removeElementIndex()
  212. delete(source)
  213. end
  214.  
  215. function instanceof(self, class, direct)
  216. if direct then
  217. return classof(self) == class
  218. end
  219.  
  220. for k, v in pairs(superMultiple(self)) do
  221. if v == class then return true end
  222. end
  223.  
  224. local check = false
  225. -- Check if any of 'self's base classes is inheriting from 'class'
  226. for k, v in pairs(superMultiple(self)) do
  227. check = instanceof(v, class, false)
  228. if check then
  229. break
  230. end
  231. end
  232. return check
  233. end
  234.  
  235. function pure_virtual()
  236. --outputServerLog(debug.traceback())
  237. error("Function implementation missing")
  238. end
  239.  
  240. function bind(func, ...)
  241. if not func then
  242. if DEBUG then
  243. outputConsole(debug.traceback())
  244. outputServerLog(debug.traceback())
  245. end
  246. error("Bad function pointer @ bind. See console for more details")
  247. end
  248.  
  249. local boundParams = { ... }
  250. return
  251. function(...)
  252. local params = {}
  253. local boundParamSize = select("#", unpack(boundParams))
  254. for i = 1, boundParamSize do
  255. params[i] = boundParams[i]
  256. end
  257.  
  258. local funcParams = { ... }
  259. for i = 1, select("#", ...) do
  260. params[boundParamSize + i] = funcParams[i]
  261. end
  262. return func(unpack(params))
  263. end
  264. end
  265.  
  266. function load(class, ...)
  267. assert(type(class) == "table", "first argument provided to load is not a table")
  268. local instance = setmetatable({},
  269. {
  270. __index = class;
  271. __class = class;
  272. __newindex = class.__newindex;
  273. __call = class.__call;
  274. })
  275.  
  276. -- Call load
  277. if rawget(class, "load") then
  278. rawget(class, "load")(instance, ...)
  279. end
  280. instance.load = false
  281.  
  282. return instance
  283. end
  284.  
  285. -- Magic to allow MTA elements to be used as data storage
  286. -- e.g. localPlayer.foo = 12
  287. oop = {}
  288. oop.elementInfo = setmetatable({}, { __mode = "k" })
  289. oop.elementClasses = {}
  290.  
  291. oop.prepareClass = function(name)
  292. local mt = debug.getregistry().mt[name]
  293.  
  294. if not mt then
  295. --outputDebugString("No such class mt "..tostring(name))
  296. return
  297. end
  298.  
  299. -- Store MTA's metafunctions
  300. local __mtaindex = mt.__index
  301. local __mtanewindex = mt.__newindex
  302. local __set = mt.__set
  303.  
  304. mt.__index = function(self, key)
  305. if not oop.handled then
  306. if not oop.elementInfo[self] and isElement(self) then
  307. enew(self, oop.elementClasses[getElementType(self)] or {})
  308. end
  309. if oop.elementInfo[self] and oop.elementInfo[self][key] ~= nil then
  310. oop.handled = false
  311. return oop.elementInfo[self][key]
  312. end
  313. oop.handled = true
  314. end
  315. local value = __mtaindex(self, key)
  316. oop.handled = false
  317. return value
  318. end
  319.  
  320.  
  321. mt.__newindex = function(self, key, value)
  322. if __set[key] ~= nil then
  323. __mtanewindex(self, key, value)
  324. return
  325. end
  326.  
  327. if not oop.elementInfo[self] and isElement(self) then
  328. enew(self, oop.elementClasses[getElementType(self)] or {})
  329. end
  330.  
  331. oop.elementInfo[self][key] = value
  332. end
  333. end
  334.  
  335. function registerElementClass(name, class)
  336. assert(type(name) == "string", "Bad argument #1 for registerElementClass")
  337. assert(type(class) == "table", "Bad argument #2 for registerElementClass")
  338. oop.elementClasses[name] = class
  339. end
  340.  
  341. oop.initClasses = function()
  342. -- this has to match
  343. -- (Server) MTA10_Server\mods\deathmatch\logic\lua\CLuaMain.cpp
  344. -- (Client) MTA10\mods\shared_logic\lua\CLuaMain.cpp
  345. if SERVER then
  346. oop.prepareClass("ACL")
  347. oop.prepareClass("ACLGroup")
  348. oop.prepareClass("Account")
  349. oop.prepareClass("Ban")
  350. oop.prepareClass("Connection")
  351. oop.prepareClass("QueryHandle")
  352. oop.prepareClass("TextDisplay")
  353. oop.prepareClass("TextItem")
  354. elseif CLIENT then
  355. oop.prepareClass("Projectile")
  356. oop.prepareClass("Sound")
  357. oop.prepareClass("Sound3D")
  358. oop.prepareClass("Weapon")
  359. oop.prepareClass("Effect")
  360. oop.prepareClass("GuiElement")
  361. oop.prepareClass("GuiWindow")
  362. oop.prepareClass("GuiButton")
  363. oop.prepareClass("GuiEdit")
  364. oop.prepareClass("GuiLabel")
  365. oop.prepareClass("GuiMemo")
  366. oop.prepareClass("GuiStaticImage")
  367. oop.prepareClass("GuiComboBox")
  368. oop.prepareClass("GuiCheckBox")
  369. oop.prepareClass("GuiRadioButton")
  370. oop.prepareClass("GuiScrollPane")
  371. oop.prepareClass("GuiScrollBar")
  372. oop.prepareClass("GuiProgressBar")
  373. oop.prepareClass("GuiGridList")
  374. oop.prepareClass("GuiTabPanel")
  375. oop.prepareClass("GuiTab")
  376. oop.prepareClass("GuiFont")
  377. oop.prepareClass("EngineCOL")
  378. oop.prepareClass("EngineTXD")
  379. oop.prepareClass("EngineDFF")
  380. oop.prepareClass("DxMaterial")
  381. oop.prepareClass("DxTexture")
  382. oop.prepareClass("DxFont")
  383. oop.prepareClass("DxShader")
  384. oop.prepareClass("DxScreenSource")
  385. oop.prepareClass("DxRenderTarget")
  386. oop.prepareClass("Weapon")
  387. end
  388.  
  389. oop.prepareClass("Object")
  390. oop.prepareClass("Ped")
  391. oop.prepareClass("Pickup")
  392. oop.prepareClass("Player")
  393. oop.prepareClass("RadarArea")
  394. --oop.prepareClass("Vector2")
  395. --oop.prepareClass("Vector3")
  396. --oop.prepareClass("Vector4")
  397. --oop.prepareClass("Matrix")
  398. oop.prepareClass("Element")
  399. oop.prepareClass("Blip")
  400. oop.prepareClass("ColShape")
  401. oop.prepareClass("File")
  402. oop.prepareClass("Marker")
  403. oop.prepareClass("Vehicle")
  404. oop.prepareClass("Water")
  405. oop.prepareClass("XML")
  406. oop.prepareClass("Timer")
  407. oop.prepareClass("Team")
  408. oop.prepareClass("Resource")
  409. end
  410. oop.initClasses()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement