if (type(_Extend) == 'function' or type(Import) == 'function' or type(Require) == 'function') then return false, 'ShExtend já está carregado' end local _string_format = string.format local _string_gsub = string.gsub local type = type local getResourceFromName = getResourceFromName local getResourceState = getResourceState local loadstring = loadstring local pcall = pcall local outputDebugString = outputDebugString local triggerEvent = triggerEvent local addEvent = addEvent local decodeString = decodeString local isElement = isElement local getResourceName = getResourceName local getThisResource = getThisResource local pairs = pairs local ipairs = ipairs local setmetatable = setmetatable local error = error local tostring = tostring local resourceRoot = resourceRoot local root = root local localPlayer = localPlayer local resourceName = resourceName function enum(Name) return (function(Values) local e, c = {}, 0 for i, v in ipairs(Values) do if (type(v) == 'string') then e[v] = c _G[v] = c c = c + 1 elseif (type(v) == 'table') then for k, val in pairs(v) do e[k] = val _G[k] = val end end end if (#Values == 0) then for k, v in pairs(Values) do e[k] = v _G[k] = v end end return setmetatable(e, { __newindex = function(_, k, v) error(('[Enum \'%s\']: Read-only! Cannot set %s = %s'):format(name, tostring(k), tostring(v))) end, __tostring = function() return ('enum<%s>'):format(name) end }) end) end enum 'Definitions' { Gamemode = 'Roleplay', isClient = (isElement(localPlayer)), isServer = (not isElement(localPlayer)), resourceName = (resourceName or getResourceName(getThisResource())) } addEvent('onExtensionUpdate', isClient) addEvent('onExtensionUpdateAll', isClient) addEvent('onExecutionCallback', isClient) addEvent('onExecutionCallbackAll', isClient) ------------------------------------------------------------------- -- Import / Extend ------------------------------------------------------------------- LIBRARY_NAME = LIBRARY_NAME or 'nc_libraries' local LOADED = _G.Loaded or {} _G.Loaded = LOADED function _Extend(ExtensionName, ResourceName, ...) if (LOADED[ResourceName] and LOADED[ResourceName][ExtensionName]) then return LOADED[ResourceName][ExtensionName], _string_format('Module %s already loaded!', ExtensionName) end if not ResourceName then ResourceName = LIBRARY_NAME end if not LOADED[ResourceName] then LOADED[ResourceName] = {} end local response = getResourceFromName(ResourceName) if ResourceName ~= resourceName and (not response or getResourceState(response) ~= 'running') then return false, _string_format('%s is not running', ResourceName) end local response2 = getResourceFromName(LIBRARY_NAME) if LIBRARY_NAME ~= resourceName and (not response2 or getResourceState(response2) ~= 'running') then return false, _string_format('%s is not running', LIBRARY_NAME) end local str, err = exports[LIBRARY_NAME]:extend(ExtensionName, ResourceName, ... ) if (type(str) == 'string' and not err) then local chunk, err2 = loadstring(str, ExtensionName) if (chunk) then local ok, res = pcall(chunk, ...) if (not ok) then return false, res and _string_gsub(res,"%[string \".*%.%.%.\"%]:(%d+):", _string_format("[%s.lua:%%1]", ExtensionName)) or 'Error!' else LOADED[ResourceName][ExtensionName] = ok and res or ok or true return LOADED[ResourceName][ExtensionName], true end else err2 = err2 and _string_gsub(err2, "%[string \".*%.%.%.\"%]:(%d+):", _string_format("[%s.lua:%%1]", ExtensionName)) or 'Error!' outputDebugString(err2, 4, 255, 0, 0) return false, err2 end else return false, err end end Import = function(ExtensionName, ...) return _Extend(ExtensionName, ...) end Require = function(ExtensionName, ... ) local ok, err = _Extend(ExtensionName, ...) if (not ok and err) then outputDebugString(err, 1) end return ok end _G.require = Require; Execute = function(ExtensionName, ...) return _Extend(ExtensionName, resourceName, ...) end ImportFunctions = function(...) local _Resources = {...} for k, _ResourceName in ipairs(_Resources) do local _Resource = getResourceFromName(_ResourceName) if _Resource and getResourceState(_Resource) == 'running' then local Exports = getResourceExportedFunctions(_Resource) or {} for _, w in ipairs(Exports) do local _Function = function(...) local _Resource = getResourceFromName(_ResourceName) if not _Resource then return false, 'Recurso não encontrado' end if getResourceState(_Resource) ~= 'running' then addEventHandler(isClient and 'onClientResourceStart' or 'onResourceStart', root, function(res) if getResourceName(res) == _ResourceName then removeEventHandler(isClient and 'onClientResourceStart' or 'onResourceStart', root, debug.getinfo(1).func) ImportFunctions(_ResourceName) end end) return false, 'Não foi possível exportar a função ' .. w .. ' do recurso ' .. _ResourceName .. ' porque o recurso não está em execução' end return exports[_ResourceName][w](...) end if type (_G[w]) ~= 'function' then _G[w] = _Function -- else -- outputDebugString('nao foi possivel exportar a função ' .. w .. ' do recurso ' .. _ResourceName..' porque a função já está exportada', 4, 255, 0, 0) end if type (_G[_ResourceName]) ~= 'table' then _G[_ResourceName] = {} end if type(_G[_ResourceName][w]) ~= 'function' then _G[_ResourceName][w] = _Function end end end end end ------------------------------------------------------------------- -- Remote Updates / Hotpatch ------------------------------------------------------------------- addEventHandler('onExtensionUpdate', resourceRoot, function(Chunk, Encrypted, Player) assert(type(Chunk) == 'string', 'Chunk must be a string') local _Chunk = Chunk Chunk = decodeString('base64', _Chunk, {variant = 'URL'}) if not Chunk then Chunk = _Chunk end local is_returnable = isElement(Player) local result, err if (is_returnable) then result, err = loadstring('return ' .. Chunk); end if (not result or err) then result, err = loadstring(Chunk) end if (not result or err) then result = err else result = { result() } end if (is_returnable) then triggerEvent('onExecutionCallback', Player, unpack(type(result) == 'table' and result or {result})) end end, true, 'high+999') ------------------------------------------------------------------- -- Remote Updates / Hotpatch (for all Resources) ------------------------------------------------------------------- addEventHandler('onExtensionUpdateAll', root, function(Chunk, Encrypted, Player) assert(type(Chunk) == 'string', 'Chunk must be a string') local _Chunk = Chunk Chunk = decodeString('base64', _Chunk, {variant = 'URL'}) if not Chunk then Chunk = _Chunk end local is_returnable = isElement(Player) local result, err if (is_returnable) then result, err = loadstring('return ' .. Chunk); end if (not result or err) then result, err = loadstring(Chunk) end if (not result or err) then result = err else result = { result() } end if (is_returnable) then triggerEvent('onExecutionCallbackAll', Player, unpack(type(result) == 'table' and result or {result})) end end, true, 'high+999')