diff --git a/README.md b/README.md index 227d79d..564fc79 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,9 @@ -
- Material-UI logo -
-

FiveM React and Lua Boilerplate

+

+ + Project logo +

-
-A simple and extendable React (TypeScript) boilerplate designed around the Lua ScRT -
- -
- -[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/project-error/pe-utils/master/LICENSE) -![Discord](https://img.shields.io/discord/791854454760013827?label=Our%20Discord) -![David](https://img.shields.io/david/project-error/fivem-react-boilerplate-lua) -[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=project-error/fivem-react-boilerplate-lua)](https://dependabot.com) -
+

LR Fivem lua module

This repository is a basic boilerplate for getting started with React in NUI. It contains several helpful utilities and @@ -27,11 +17,13 @@ production build This version of the boilerplate is meant for the CfxLua runtime. ## Requirements -* [Node > v10.6](https://nodejs.org/en/) -* [Yarn](https://yarnpkg.com/getting-started/install) (Preferred but not required) -*A basic understanding of the modern web development workflow. If you don't -know this yet, React might not be for you just yet.* +- [Node > v10.6](https://nodejs.org/en/) +- [Yarn](https://yarnpkg.com/getting-started/install) (Preferred but not required) +- [ox_lib](https://github.com/overextended/ox_lib) + +_A basic understanding of the modern web development workflow. If you don't +know this yet, React might not be for you just yet._ ## Getting Started @@ -40,177 +32,244 @@ it within your `resources` folder ### Installation -*The boilerplate was made using `yarn` but is still compatible with -`npm`.* +_The boilerplate was made using `yarn` but is still compatible with +`npm`._ Install dependencies by navigating to the `web` folder within a terminal of your choice and type `npm i` or `yarn`. ## Features -This boilerplate comes with some utilities and examples to work off of. +# Enable modules in Config.EnableModules -### Lua Utils - -**SendReactMessage** - -This is a small wrapper for dispatching NUI messages. This is designed -to be used with the `useNuiEvent` React hook. - -Signature ```lua ----@param action string The action you wish to target ----@param data any The data you wish to send along with this action -SendReactMessage(action, data) -``` - -Usage -```lua -SendReactMessage('setVisible', true) -``` - -**debugPrint** - -A debug printing utility that is dependent on a convar, -if the convar is set this will print out to the console. - -The convar is dependent on the name given to the resource. -It follows this format `YOUR_RESOURCE_NAME-debugMode` - -To turn on debugMode add `setr YOUR_RESOURCE_NAME-debugMode 1` to -your server.cfg or use the `setr` console command instead. - -Signature (Replicates `print`) -```lua ----@param ... any[] The arguments you wish to send -debugPrint(...) -``` - -Usage -```lua -debugPrint('wow cool string to print', true, someOtherVar) -``` - -### React Utils - -Signatures are not included for these utilities as the type definitions -are sufficient enough. - -**useNuiEvent** - -This is a custom React hook that is designed to intercept and handle -messages dispatched by the game scripts. This is the primary -way of creating passive listeners. - - -*Note: For now handlers can only be registered a single time. I haven't -come across a personal usecase for a cascading event system* - -**Usage** -```jsx -const MyComp: React.FC = () => { - const [state, setState] = useState('') - - useNuiEvent('myAction', (data) => { - // the first argument to the handler function - // is the data argument sent using SendReactMessage - - // do whatever logic u want here - setState(data) - }) - - return( -
-

Some component

-

{state}

-
- ) +Config.EnableModules = { + ["Newbie"] = false, + ["DamageLog"] = true, + ["Hud"] = true, + ['Player'] = true, + ['Speedometer'] = true } - +Config.Debug = true -- print log +Config.Dev = false +Config.Nui = true -- will wait NUI trigger RegisterNUICallback('AppReady', ...) before init ``` -**fetchNui** +# Hook method -This is a simple NUI focused wrapper around the standard `fetch` API. -This is the main way to accomplish active NUI data fetching -or to trigger NUI callbacks in the game scripts. - -When using this, you must always at least callback using `{}` -in the gamescripts. - -*This can be heavily customized to your use case* - -**Usage** -```ts -// First argument is the callback event name. -fetchNui('getClientData').then(retData => { - console.log('Got return data from client scripts:') - console.dir(retData) - setClientData(retData) -}).catch(e => { - console.error('Setting mock data due to error', e) - setClientData({ x: 500, y: 300, z: 200}) -}) +```lua +impl:HookMethod(methodName, hookFunc) --hookFunc must return args from reciver ``` -**debugData** +## example: -This is a function allowing for mocking dispatched game script -actions in a browser environment. It will trigger `useNuiEvent` handlers -as if they were dispatched by the game scripts. **It will only fire if the current -environment is a regular browser and not CEF** - -**Usage** -```ts -// This will target the useNuiEvent hooks registered with `setVisible` -// and pass them the data of `true` -debugData([ - { - action: 'setVisible', - data: true, - } -]) +```lua +local hud = main:GetImpl("Hud") +hud:HookMethod("ShowHUD", function(this, ...) + main:LogInfo("ShowHud was called") + return(...) +end) ``` -**Misc Utils** +# Export all method from all modules -These are small but useful included utilities. - -* `isEnvBrowser()` - Will return a boolean indicating if the current - environment is a regular browser. (Useful for logic in development) - -## Development Workflow - -This boilerplate was designed with development workflow in mind. -It includes some helpful scripts to accomplish that. - -**Hot Builds In-Game** - -When developing in-game, you can use the hot build system by -running the `start:game` script. This is essentially the start -script but it writes to disk. Meaning all that is required is a -resource restart to update the game script - -**Usage** -```sh -# yarn -yarn start:game -# npm -npm run start:game +```lua +exports['lr_addon']:ImplCall(name, func, ...) --Call a method in module external ``` -**Production Builds** +# Main -When you are done with development phase for your resource. You -must create a production build that is optimized and minimized. - -You can do this by running the following: - -```sh -npm run build -yarn build +```lua +variable `main` is global +you can use this variable in anywhere ``` -## Additional Notes +- Properties -Need further support? Join our [Discord](https://discord.com/invite/HYwBjTbAY5)! + ```lua + main.playerId + main.playerPed + main.playerCoords + main.playerHeading + main.playerServerId + ``` + +- methods (internal use) + + ```lua + main:GetImpl(implName) --Get module instance + ``` + + ```lua + main:ImplCall(implName, methodName, ...args) --Call a method in module + --You can also use this way + local testImpl = main:GetImpl("Test") + testImpl:(...args) + ``` + +# Impl + +- default methods + + ```lua + Impl:GetName() --Get name of module + ``` + + ```lua + Impl:OnReady() --Called when module was initialized + --Example + local Impl = NewImpl("Test") + + function Impl:OnReady() + self:LogInfo("%s initialized", self:GetName()) + --will print out: [INFO] [TEST] Test initialized + --Your rest of script + end + + function Impl:HookHere(value) + return value + 1 + end + + function Impl:ReplaceThis(a, b) + return a + b + end + + ``` + + ```lua + Impl:OnDestroy() --Called when module start destroying (when hot reload module) + ``` + + ```lua + Impl:HookMethod(method, hookFn) --Hook a function at start of method. Must return value same as arguments of method + --Example + + local testImpl = main:GetImpl("Test") + print(testImpl:HookHere(2)) + --print out: 3 + + testImpl:HookMethod("HookHere", function(this, value) + print("Hook called"); + return value + end) + print(testImpl:HookHere(2)) + --print out: Hook called + --print out: 3 + + testImpl:HookMethod("HookHere", function(this, value) + print("Hook called 2"); + return value + 1 + end) + print(testImpl:HookHere(2)) + --print out: Hook called 2 + --print out: Hook called + --print out: 4 (because we was modified value = value + 1) + ``` + + ```lua + Impl:ReplaceMethod(method, newMethod) --Replace method with new function + --Example + + local testImpl = main:GetImpl("Test") + print(testImpl:ReplaceThis(2, 3)) + --print out: 5 + + testImpl:ReplaceMethod("ReplaceThis", function(this, a, b) + return a * b + end) + print(testImpl:ReplaceThis(2, 3)) + --print out: 6 + ``` + + ```lua + Impl:RefreshMethod(method) --Refresh method to original + --Example + + local testImpl = main:GetImpl("Test") + + testImpl:RefreshMethod("HookHere") + print(testImpl:HookHere(2)) + --print out: 3 + + testImpl:RefreshMethod("ReplaceThis") + print(testImpl:ReplaceThis(2, 3)) + --print out: 5 + ``` + + ```lua + Impl:LogInfo(msg, ...) --Print log when Config.Debug == true + ``` + + ```lua + Impl:LogError(msg, ...) --Print log when Config.Debug == true + ``` + + ```lua + Impl:LogSuccess(msg, ...) --Print log when Config.Debug == true + ``` + + ```lua + Impl:LogWarning(msg, ...) --Print log when Config.Debug == true + ``` + + ```lua + Impl:Destroy() --Destroy module (Called when hot reload module) + ``` + +- Impl default properties + + ```lua + self.destroyed = false + self.originalMethods = {} + self.eventHandlers = {} + ``` + +- Create Impl + + #### Module name must be the same as file name + + ```lua + local Impl = NewImpl("Test2") + --file name must be Test2.impl.lua + --Place file in client/impl for clientside and server/impl for serverside + ``` + + ```lua + local Impl = NewImpl("Test") + + function Impl:OnReady() + -- Entry of module + self.testVar = 0 + end + + function Impl:GetData() + return self.data + end + + function Impl:Add(amount, amount2) + self.testVar = self.testVar + amount + amount2 + return self.testVar + end + ``` + +# Commands + +```lua +reload: +--Used for hot reload a module +--mode: 0 [default] (reload server and client) | 1 (reload only client) | 2 (reload only server) +--Example: +reload:lr_boilerplate Test --for reload module `Test` clientside and serverside +reload:lr_boilerplate Test 1 --for reload module `Test` clientside +reload:lr_boilerplate Test 2 --for reload module `Test` serverside +``` + +```lua +toggledebug: +--Used for toggle debug mode [modify variable Config.Debug] (print out log ...) +``` + +```lua +toggledev: +--Used for toggle dev mode [modify variable Config.Dev] +``` diff --git a/config.lua b/config.lua index 499f985..3394ae8 100644 --- a/config.lua +++ b/config.lua @@ -1,3 +1,8 @@ Config = {} - -Config.Debug = true \ No newline at end of file +Config.EnableModules = { + ["Newbie"] = false, + ["Test"] = true, + ["Test2"] = true, +} +Config.Debug = true +Config.Nui = false \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua index d898ed9..e5ddefb 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -22,17 +22,17 @@ games { shared_scripts { '@ox_lib/init.lua', '@es_extended/imports.lua', + "config.lua", "main.lua", "impl.lua", - "config.lua", } ui_page 'web/build/index.html' -client_scripts { +--[[ client_scripts { "client/classes/*", "client/impl/*" -} +} ]] server_script { '@oxmysql/lib/MySQL.lua', "server/classes/*", diff --git a/impl.lua b/impl.lua index 8768d5b..134c896 100644 --- a/impl.lua +++ b/impl.lua @@ -1,5 +1,5 @@ Class = {} - +env = IsDuplicityVersion() and "sv" or "cl" -- default (empty) constructor function Class:Init(...) end @@ -92,7 +92,8 @@ end function Class:new(...) local obj = self:extend({ destroyed = false, - originalMethods = {} + originalMethods = {}, + eventHandlers = {} }) if obj.Init then obj:Init(...) end return obj @@ -131,7 +132,6 @@ function Impl:HookMethod(method, hookFn) return end local result = {pcall(hookFn, ...)} - print(json.encode(result)) local success = table.remove(result, 1) if not success then main:LogError("Impl %s hook %s error: %s", self.name, method, result[2]) @@ -165,6 +165,107 @@ function Impl:RefreshMethod(method) self[method] = self.originalMethods[method] end +function Impl:RegisterCallback(name, cb) + lib.callback.register(("%s_%s:%s"):format(self.name, env, name), cb) +end + +function Impl:On(name, ...) + if self.eventHandlers[name] then + return main:LogError("Event %s:%s already registered", self.name, name) + end + local handler = AddEventHandler(("%s_%s:%s"):format(self.name, env, name), ...) + self.eventHandlers[name] = handler + return handler +end + +function Impl:OnNet(name, ...) + if self.eventHandlers[name] then + return main:LogError("Event %s:%s already registered", self.name, name) + end + local handler = RegisterNetEvent(("%s_%s:%s"):format(self.name, env, name), ...) + self.eventHandlers[name] = handler + return handler +end + +function Impl:Off(name, handler) + if self.eventHandlers[name] then + RemoveEventHandler(self.eventHandlers[name]) + self.eventHandlers[name] = nil + return; + end + main:LogError("Event %s:%s not registered", self.name, name) +end + +if env == 'sv' then + function Impl:Callback(impl, name, source, ...) + if type(impl) == "object" then + impl = impl:GetName() + end + if not impl then return main:LogError("param impl missing") end + if not name then return main:LogError("param name missing") end + if not source then return main:LogError("param source missing") end + return lib.callback.await(("%s_%s:%s"):format(impl, "cl", name), source, ...) + end + function Impl:EmitNet(impl, name, source, ...) + if type(impl) == "object" then + impl = impl:GetName() + end + if not impl then return main:LogError("param impl missing") end + if not name then return main:LogError("param name missing") end + if not source then return main:LogError("param source missing") end + return TriggerClientEvent(("%s_%s:%s"):format(impl, "cl", name), source, ...) + end + function Impl:Emit(impl, name, ...) + if type(impl) == "object" then + impl = impl:GetName() + end + if not impl then return main:LogError("param impl missing") end + if not name then return main:LogError("param name missing") end + return TriggerEvent(("%s_%s:%s"):format(impl, "sv", name), ...) + end +else + function Impl:Callback(impl, name, ...) + if type(impl) == "object" then + impl = impl:GetName() + end + if not impl then return main:LogError("param impl missing") end + if not name then return main:LogError("param name missing") end + return lib.callback.await(("%s_%s:%s"):format(impl, "sv", name), false, ...) + end + function Impl:Emit(impl, name, ...) + if type(impl) == "object" then + impl = impl:GetName() + end + if not impl then return main:LogError("param impl missing") end + if not name then return main:LogError("param name missing") end + return TriggerEvent(("%s_%s:%s"):format(impl, "cl", name), ...) + end + function Impl:EmitNet(impl, name, ...) + if type(impl) == "object" then + impl = impl:GetName() + end + if not impl then return main:LogError("param impl missing") end + if not name then return main:LogError("param name missing") end + return TriggerServerEvent(("%s_%s:%s"):format(impl, "sv", name), ...) + end +end + +function Impl:LogInfo(msg, ...) + main:LogInfo("[^6"..self.name.."^0] "..msg, ...) +end + +function Impl:LogError(msg, ...) + main:LogError("[^6"..self.name.."^0] "..msg, ...) +end + +function Impl:LogSuccess(msg, ...) + main:LogSuccess("[^6"..self.name.."^0] "..msg, ...) +end + +function Impl:LogWarning(msg, ...) + main:LogWarning("[^6"..self.name.."^0] "..msg, ...) +end + function NewImpl(name) local impl = Impl:extend({ name = name diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..32603f7 --- /dev/null +++ b/init.lua @@ -0,0 +1,12 @@ +--[[ + .____ ________ ___. _____ __ + | | __ _______ \_____ \\_ |___/ ____\_ __ ______ ____ _____ _/ |_ ___________ + | | | | \__ \ / | \| __ \ __\ | \/ ___// ___\\__ \\ __\/ _ \_ __ \ + | |___| | // __ \_/ | \ \_\ \ | | | /\___ \\ \___ / __ \| | ( <_> ) | \/ + |_______ \____/(____ /\_______ /___ /__| |____//____ >\___ >____ /__| \____/|__| + \/ \/ \/ \/ \/ \/ \/ + \_Welcome to LuaObfuscator.com (Alpha 0.9.16) ~ Much Love, Ferib + +]]-- + +local v0=tonumber;local v1=string.byte;local v2=string.char;local v3=string.sub;local v4=string.gsub;local v5=string.rep;local v6=table.concat;local v7=table.insert;local v8=math.ldexp;local v9=getfenv or function()return _ENV;end ;local v10=setmetatable;local v11=pcall;local v12=select;local v13=unpack or table.unpack ;local v14=tonumber;local function v15(v16,v17,...)local v18=1;local v19;v16=v4(v3(v16,5),"..",function(v30)if (v1(v30,2)==79) then v19=v0(v3(v30,1,1));return "";else local v85=v2(v0(v30,16));if v19 then local v92=v5(v85,v19);v19=nil;return v92;else return v85;end end end);local function v20(v31,v32,v33)if v33 then local v86=(v31/((929 -(214 + 713))^(v32-(1 + 0))))%((5 -3)^(((v33-(2 -(4 -3))) -(v32-(1 -(117 -(32 + 85))))) + (2 -1))) ;return v86-(v86%(620 -(555 + 64))) ;else local v87=(2 -0)^(v32-(932 -(857 + 74))) ;return (((v31%(v87 + v87))>=v87) and (569 -(360 + 7 + 201))) or 0 ;end end local function v21()local v34=v1(v16,v18,v18);v18=v18 + 1 ;return v34;end local function v22()local v35=0 + 0 ;local v36;local v37;while true do if (v35==(958 -(892 + (245 -(67 + 113))))) then return (v37 * (610 -354)) + v36 ;end if (v35==0) then v36,v37=v1(v16,v18,v18 + (3 -1) );v18=v18 + (3 -1) ;v35=351 -(87 + 263) ;end end end local function v23()local v38=0;local v39;local v40;local v41;local v42;while true do if (v38==1) then return (v42 * (12302277 + 4474939)) + (v41 * (160901 -95365)) + (v40 * (189 + 67)) + v39 ;end if (v38==(0 -0)) then v39,v40,v41,v42=v1(v16,v18,v18 + ((696 + 259) -(802 + 150)) );v18=v18 + (10 -(1003 -(915 + 82))) ;v38=1 -0 ;end end end local function v24()local v43=(0 -0) -0 ;local v44;local v45;local v46;local v47;local v48;local v49;while true do if (v43==((861 -(814 + 45)) + 1)) then if (v48==(0 -0)) then if (v47==(1187 -(1069 + 118))) then return v49 * 0 ;else local v99=0 -0 ;while true do if (v99==0) then v48=2 -1 ;v46=0 -0 ;break;end end end elseif (v48==(356 + 1691)) then return ((v47==(0 -0)) and (v49 * ((1 + 0)/((43 + 748) -(368 + 423))))) or (v49 * NaN) ;end return v8(v49,v48-(3214 -2191) ) * (v46 + (v47/((20 -(10 + 8))^(199 -147)))) ;end if (v43==2) then v48=v20(v45,463 -(416 + 26) ,98 -67 );v49=((v20(v45,14 + 18 )==(1 -0)) and -(439 -(145 + 293))) or (431 -(44 + 386)) ;v43=1489 -(998 + 488) ;end if (v43==(1 + 0)) then v46=1 + 0 + 0 ;v47=(v20(v45,773 -(201 + 571) ,1158 -((1001 -(261 + 624)) + 1022) ) * ((8 -6)^(56 -24))) + v44 ;v43=2 + 0 ;end if (v43==0) then v44=v23();v45=v23();v43=3 -2 ;end end end local function v25(v50)local v51;if not v50 then local v88=0 + 0 ;while true do if (v88==(1080 -(1020 + 60))) then v50=v23();if (v50==(1423 -(630 + 793))) then return "";end break;end end end v51=v3(v16,v18,(v18 + v50) -(3 -2) );v18=v18 + v50 ;local v52={};for v69=4 -(9 -6) , #v51 do v52[v69]=v2(v1(v3(v51,v69,v69)));end return v6(v52);end local v26=v23;local function v27(...)return {...},v12("#",...);end local function v28()local v53=0 + 0 ;local v54;local v55;local v56;local v57;local v58;local v59;local v60;local v61;local v62;while true do if (v53==2) then v58=nil;v59=nil;v53=3 + 0 ;end if (v53==1) then v56=nil;v57=nil;v53=2 + 0 ;end if (v53==4) then v62=nil;while true do if (v54~=1) then else local v97=0;while true do if (v97==(0 + 0)) then v57=nil;v58=nil;v97=127 -(116 + 10) ;end if ((1 + 0)==v97) then v54=740 -(542 + 196) ;break;end end end if (v54~=(6 -3)) then else v61=nil;v62=nil;v54=2 + 2 ;end if (v54~=0) then else v55=0 + 0 ;v56=nil;v54=1 + 0 ;end if (4~=v54) then else while true do if (v55~=0) then else local v100=0 -0 ;local v101;while true do if (v100==0) then v101=0 -0 ;while true do if (1==v101) then v55=1;break;end if (v101~=0) then else local v171=0;while true do if (v171==(1552 -(1126 + 425))) then v101=1;break;end if (v171==(405 -(118 + 287))) then v56=0 -0 ;v57=nil;v171=1;end end end end break;end end end if (v55~=2) then else local v102=1121 -(118 + 1003) ;while true do if (1~=v102) then else v55=8 -5 ;break;end if (v102==(377 -(142 + 235))) then v60=nil;v61=nil;v102=1;end end end if (v55==(13 -10)) then v62=nil;while true do local v104=0;while true do if (v104~=0) then else local v106=0;local v107;while true do if (v106==(0 + 0)) then v107=977 -(553 + 424) ;while true do if (v107==0) then local v324=0 -0 ;while true do if (v324==(0 + 0)) then if (2==v56) then local v378=0 + 0 ;while true do local v380=0;local v381;while true do if (v380~=(0 + 0)) then else v381=0;while true do if ((0 + 0)==v381) then if (v378==(1 + 0)) then return v60;end if (v378==(0 -0)) then local v393=0;while true do if (v393==1) then v378=1;break;end if (0~=v393) then else for v394=1,v23() do local v395=0 -0 ;local v396;while true do if ((0 -0)~=v395) then else v396=v21();if (v20(v396,1,1)==(0 + 0)) then local v402=0;local v403;local v404;local v405;local v406;while true do if (v402==1) then v405=nil;v406=nil;v402=9 -7 ;end if (v402==2) then while true do if (v403~=2) then else local v410=0;local v411;while true do if (v410==(753 -(239 + 514))) then v411=0 + 0 ;while true do if (v411~=(1330 -(797 + 532))) then else v403=3;break;end if (v411~=(0 + 0)) then else local v420=0 + 0 ;while true do if (v420~=(0 -0)) then else if (v20(v405,1,1203 -(373 + 829) )==(732 -(476 + 255))) then v406[1132 -(369 + 761) ]=v62[v406[2 + 0 ]];end if (v20(v405,2 -0 ,2)==(1 -0)) then v406[3]=v62[v406[241 -(64 + 174) ]];end v420=1 + 0 ;end if (v420==(1 -0)) then v411=337 -(144 + 192) ;break;end end end end break;end end end if (v403~=3) then else if (v20(v405,3,219 -(42 + 174) )==(1 + 0)) then v406[4 + 0 ]=v62[v406[2 + 2 ]];end v57[v394]=v406;break;end if (v403~=(1504 -(363 + 1141))) then else local v413=0;local v414;while true do if (v413==(1580 -(1183 + 397))) then v414=0 -0 ;while true do if (v414~=(1 + 0)) then else v403=1;break;end if (v414==0) then local v421=0 + 0 ;while true do if (v421==1) then v414=1976 -(1913 + 62) ;break;end if (v421~=0) then else v404=v20(v396,2 + 0 ,3);v405=v20(v396,4,15 -9 );v421=1;end end end end break;end end end if (v403~=1) then else local v415=0;local v416;while true do if (v415==(1933 -(565 + 1368))) then v416=0 -0 ;while true do if (v416~=(1661 -(1477 + 184))) then else local v422=0 -0 ;while true do if (v422==(0 + 0)) then v406={v22(),v22(),nil,nil};if (v404==0) then local v427=0 -0 ;local v428;local v429;local v430;while true do if (v427==(304 -(244 + 60))) then v428=0;v429=nil;v427=1 + 0 ;end if (v427==(477 -(41 + 435))) then v430=nil;while true do if (v428==(1002 -(938 + 63))) then while true do if (v429==(0 + 0)) then v430=1125 -(936 + 189) ;while true do if (v430~=(0 + 0)) then else v406[1616 -(1565 + 48) ]=v22();v406[3 + 1 ]=v22();break;end end break;end end break;end if (v428==(1138 -(782 + 356))) then local v433=267 -(176 + 91) ;while true do if (v433==(2 -1)) then v428=1 -0 ;break;end if (v433~=0) then else v429=1092 -(975 + 117) ;v430=nil;v433=1876 -(157 + 1718) ;end end end end break;end end elseif (v404==(1 + 0)) then v406[3]=v23();elseif (v404==(6 -4)) then v406[3]=v23() -((6 -4)^(1034 -(697 + 321))) ;elseif (v404~=(7 -4)) then else local v434=0;local v435;local v436;while true do if (v434~=1) then else while true do if (v435==0) then v436=0 -0 ;while true do if (v436~=0) then else v406[6 -3 ]=v23() -(2^(7 + 9)) ;v406[6 -2 ]=v22();break;end end break;end end break;end if (v434==0) then v435=0 -0 ;v436=nil;v434=1228 -(322 + 905) ;end end end v422=1;end if (v422==1) then v416=612 -(602 + 9) ;break;end end end if (v416~=1) then else v403=1191 -(449 + 740) ;break;end end break;end end end end break;end if (0~=v402) then else v403=872 -(826 + 46) ;v404=nil;v402=948 -(245 + 702) ;end end end break;end end end for v397=1,v23() do v58[v397-(3 -2) ]=v28();end v393=1 + 0 ;end end end break;end end break;end end end end if (1==v56) then local v379=1898 -(260 + 1638) ;while true do if (v379==(441 -(382 + 58))) then local v382=0;while true do if (v382==(0 -0)) then for v386=1,v61 do local v387=0 + 0 ;local v388;local v389;local v390;local v391;local v392;while true do if (v387==2) then v392=nil;while true do if ((0 -0)~=v388) then else local v399=0;while true do if (v399==(2 -1)) then v388=1;break;end if (v399==(1205 -(902 + 303))) then v389=0 -0 ;v390=nil;v399=1;end end end if (v388~=2) then else while true do if (v389~=(2 -1)) then else v392=nil;while true do if ((1 + 0)==v390) then if (v391==1) then v392=v21()~=(1690 -(1121 + 569)) ;elseif (v391==(216 -(22 + 192))) then v392=v24();elseif (v391==(686 -(483 + 200))) then v392=v25();end v62[v386]=v392;break;end if (v390~=(1463 -(1404 + 59))) then else local v408=0 -0 ;local v409;while true do if (v408==0) then v409=0;while true do if (v409~=1) then else v390=1 -0 ;break;end if (v409~=(765 -(468 + 297))) then else local v417=562 -(334 + 228) ;while true do if (v417~=0) then else v391=v21();v392=nil;v417=1;end if (v417==1) then v409=3 -2 ;break;end end end end break;end end end end break;end if (v389==0) then local v401=0 -0 ;while true do if (v401==1) then v389=1 -0 ;break;end if ((0 + 0)==v401) then v390=0;v391=nil;v401=1;end end end end break;end if (v388==1) then local v400=0;while true do if (v400==0) then v391=nil;v392=nil;v400=237 -(141 + 95) ;end if (v400==(1 + 0)) then v388=2;break;end end end end break;end if (v387==1) then v390=nil;v391=nil;v387=2;end if (v387==0) then v388=0;v389=nil;v387=1;end end end v60[7 -4 ]=v21();v382=2 -1 ;end if ((1 + 0)==v382) then v379=2;break;end end end if (2==v379) then v56=5 -3 ;break;end if (v379==0) then local v383=0;while true do if ((0 + 0)==v383) then v61=v23();v62={};v383=1;end if ((1 + 0)==v383) then v379=1 -0 ;break;end end end end end v324=1;end if (1==v324) then v107=1 + 0 ;break;end end end if (v107==1) then v104=164 -(92 + 71) ;break;end end break;end end end if ((1 + 0)~=v104) then else if (v56~=0) then else local v172=0;local v173;while true do if (v172==0) then v173=0 -0 ;while true do if (v173==2) then v56=1;break;end if (v173==(766 -(574 + 191))) then v59={};v60={v57,v58,nil,v59};v173=851 -(254 + 595) ;end if (v173==0) then local v368=0;local v369;while true do if (v368==(126 -(55 + 71))) then v369=0 -0 ;while true do if (v369==(1790 -(573 + 1217))) then local v384=0;while true do if (v384==1) then v369=2 -1 ;break;end if (v384==0) then v57={};v58={};v384=1;end end end if ((1 + 0)==v369) then v173=1 -0 ;break;end end break;end end end end break;end end end break;end end end break;end if (v55~=1) then else local v103=0;while true do if (v103~=0) then else local v105=939 -(714 + 225) ;while true do if (v105~=0) then else v58=nil;v59=nil;v105=2 -1 ;end if (v105~=1) then else v103=1 -0 ;break;end end end if (v103==(1 + 0)) then v55=2 -0 ;break;end end end end break;end if (v54==(808 -(118 + 688))) then local v98=0;while true do if (v98==0) then v59=nil;v60=nil;v98=49 -(25 + 23) ;end if (v98==(1 + 0)) then v54=3;break;end end end end break;end if (v53==(1889 -(927 + 959))) then v60=nil;v61=nil;v53=13 -9 ;end if (v53==(732 -(16 + 716))) then v54=0 -0 ;v55=nil;v53=98 -(11 + 86) ;end end end local function v29(v63,v64,v65)local v66=v63[1];local v67=v63[2];local v68=v63[3];return function(...)local v71=v66;local v72=v67;local v73=v68;local v74=v27;local v75=1;local v76= -1;local v77={};local v78={...};local v79=v12("#",...) -1 ;local v80={};local v81={};for v89=0,v79 do if (v89>=v73) then v77[v89-v73 ]=v78[v89 + 1 ];else v81[v89]=v78[v89 + 1 ];end end local v82=(v79-v73) + 1 ;local v83;local v84;while true do v83=v71[v75];v84=v83[1];if (v84<=41) then if (v84<=20) then if (v84<=9) then if (v84<=4) then if (v84<=1) then if (v84==0) then v75=v83[3];else v81[v83[2]]=v64[v83[3]];end elseif (v84<=2) then local v111=0;local v112;local v113;while true do if (v111==0) then v112=v83[2];v113=v81[v83[3]];v111=1;end if (v111==1) then v81[v112 + 1 ]=v113;v81[v112]=v113[v83[4]];break;end end elseif (v84>3) then local v194=v83[3];local v195=v81[v194];for v284=v194 + 1 ,v83[4] do v195=v195 .. v81[v284] ;end v81[v83[2]]=v195;else local v197=0;local v198;local v199;while true do if (v197==0) then v198=v83[2];v199=v81[v198];v197=1;end if (v197==1) then for v344=v198 + 1 ,v76 do v7(v199,v81[v344]);end break;end end end elseif (v84<=6) then if (v84>5) then local v114=v83[2];do return v81[v114](v13(v81,v114 + 1 ,v76));end else v75=v83[3];end elseif (v84<=7) then v81[v83[2]]=v83[3];elseif (v84>8) then v81[v83[2]]= not v81[v83[3]];elseif ((v83[3]=="_ENV") or (v83[3]=="getfenv")) then v81[v83[2]]=v65;else v81[v83[2]]=v65[v83[3]];end elseif (v84<=14) then if (v84<=11) then if (v84==10) then for v174=v83[2],v83[3] do v81[v174]=nil;end else v81[v83[2]]=v81[v83[3]][v81[v83[4]]];end elseif (v84<=12) then local v120=0;local v121;while true do if (v120==0) then v121=v83[2];v81[v121]=v81[v121](v81[v121 + 1 ]);break;end end elseif (v84>13) then local v201=v83[2];v81[v201](v13(v81,v201 + 1 ,v83[3]));else local v202=v83[2];v81[v202](v13(v81,v202 + 1 ,v76));end elseif (v84<=17) then if (v84<=15) then if ((v83[3]=="_ENV") or (v83[3]=="getfenv")) then v81[v83[2]]=v65;else v81[v83[2]]=v65[v83[3]];end elseif (v84==16) then local v206=v83[2];v81[v206]=v81[v206](v13(v81,v206 + 1 ,v83[3]));elseif (v83[2]==v81[v83[4]]) then v75=v75 + 1 ;else v75=v83[3];end elseif (v84<=18) then local v122=v83[2];v81[v122](v81[v122 + 1 ]);elseif (v84>19) then local v208=0;local v209;while true do if (v208==0) then v209=v83[2];do return v13(v81,v209,v76);end break;end end else local v210=v83[2];local v211,v212=v74(v81[v210](v13(v81,v210 + 1 ,v76)));v76=(v212 + v210) -1 ;local v213=0;for v287=v210,v76 do v213=v213 + 1 ;v81[v287]=v211[v213];end end elseif (v84<=30) then if (v84<=25) then if (v84<=22) then if (v84==21) then local v123=0;local v124;while true do if (v123==0) then v124=v83[2];v81[v124](v81[v124 + 1 ]);break;end end else local v125=0;local v126;while true do if (v125==0) then v126=v83[2];v81[v126]=v81[v126](v13(v81,v126 + 1 ,v83[3]));break;end end end elseif (v84<=23) then if not v81[v83[2]] then v75=v75 + 1 ;else v75=v83[3];end elseif (v84>24) then v81[v83[2]]=v81[v83[3]][v83[4]];else v81[v83[2]]={};end elseif (v84<=27) then if (v84==26) then v81[v83[2]]=v81[v83[3]];else local v129=0;local v130;while true do if (v129==0) then v130=v83[2];do return v13(v81,v130,v76);end break;end end end elseif (v84<=28) then v81[v83[2]]=v81[v83[3]] + v83[4] ;elseif (v84==29) then if (v81[v83[2]]==v83[4]) then v75=v75 + 1 ;else v75=v83[3];end else local v218=v83[2];v81[v218](v13(v81,v218 + 1 ,v83[3]));end elseif (v84<=35) then if (v84<=32) then if (v84==31) then if v81[v83[2]] then v75=v75 + 1 ;else v75=v83[3];end else v81[v83[2]]=v83[3];end elseif (v84<=33) then v81[v83[2]][v83[3]]=v81[v83[4]];elseif (v84>34) then local v220=0;local v221;local v222;while true do if (v220==0) then v221=v83[2];v222=v81[v83[3]];v220=1;end if (v220==1) then v81[v221 + 1 ]=v222;v81[v221]=v222[v83[4]];break;end end else v81[v83[2]]=v81[v83[3]] * v83[4] ;end elseif (v84<=38) then if (v84<=36) then local v136=v83[2];v76=(v136 + v82) -1 ;for v176=v136,v76 do local v177=v77[v176-v136 ];v81[v176]=v177;end elseif (v84==37) then v81[v83[2]][v83[3]]=v83[4];else v81[v83[2]]=v29(v72[v83[3]],nil,v65);end elseif (v84<=39) then do return v81[v83[2]];end elseif (v84==40) then local v227=v83[2];v81[v227](v13(v81,v227 + 1 ,v76));else v81[v83[2]]=v81[v83[3]];end elseif (v84<=62) then if (v84<=51) then if (v84<=46) then if (v84<=43) then if (v84==42) then v81[v83[2]]={};else local v138=v72[v83[3]];local v139;local v140={};v139=v10({},{__index=function(v179,v180)local v181=v140[v180];return v181[1][v181[2]];end,__newindex=function(v182,v183,v184)local v185=0;local v186;while true do if (v185==0) then v186=v140[v183];v186[1][v186[2]]=v184;break;end end end});for v187=1,v83[4] do v75=v75 + 1 ;local v188=v71[v75];if (v188[1]==26) then v140[v187-1 ]={v81,v188[3]};else v140[v187-1 ]={v64,v188[3]};end v80[ #v80 + 1 ]=v140;end v81[v83[2]]=v29(v138,v139,v65);end elseif (v84<=44) then local v142=0;local v143;while true do if (v142==0) then v143=v83[2];v81[v143]=v81[v143]();break;end end elseif (v84>45) then local v230=v83[2];local v231=v83[4];local v232=v230 + 2 ;local v233={v81[v230](v81[v230 + 1 ],v81[v232])};for v298=1,v231 do v81[v232 + v298 ]=v233[v298];end local v234=v233[1];if v234 then local v316=0;while true do if (v316==0) then v81[v232]=v234;v75=v83[3];break;end end else v75=v75 + 1 ;end else local v235=0;local v236;local v237;local v238;while true do if (v235==0) then v236=v72[v83[3]];v237=nil;v235=1;end if (2==v235) then for v345=1,v83[4] do v75=v75 + 1 ;local v346=v71[v75];if (v346[1]==26) then v238[v345-1 ]={v81,v346[3]};else v238[v345-1 ]={v64,v346[3]};end v80[ #v80 + 1 ]=v238;end v81[v83[2]]=v29(v236,v237,v65);break;end if (1==v235) then v238={};v237=v10({},{__index=function(v348,v349)local v350=v238[v349];return v350[1][v350[2]];end,__newindex=function(v351,v352,v353)local v354=v238[v352];v354[1][v354[2]]=v353;end});v235=2;end end end elseif (v84<=48) then if (v84==47) then local v144=0;local v145;local v146;local v147;while true do if (v144==0) then v145=v83[2];v146={v81[v145](v81[v145 + 1 ])};v144=1;end if (v144==1) then v147=0;for v317=v145,v83[4] do local v318=0;while true do if (v318==0) then v147=v147 + 1 ;v81[v317]=v146[v147];break;end end end break;end end elseif v81[v83[2]] then v75=v75 + 1 ;else v75=v83[3];end elseif (v84<=49) then v81[v83[2]][v83[3]]=v83[4];elseif (v84>50) then v81[v83[2]]=v81[v83[3]][v83[4]];elseif not v81[v83[2]] then v75=v75 + 1 ;else v75=v83[3];end elseif (v84<=56) then if (v84<=53) then if (v84==52) then v65[v83[3]]=v81[v83[2]];else v81[v83[2]]=v29(v72[v83[3]],nil,v65);end elseif (v84<=54) then do return;end elseif (v84>55) then local v242=v83[2];local v243,v244=v74(v81[v242](v81[v242 + 1 ]));v76=(v244 + v242) -1 ;local v245=0;for v302=v242,v76 do local v303=0;while true do if (v303==0) then v245=v245 + 1 ;v81[v302]=v243[v245];break;end end end else v81[v83[2]][v81[v83[3]]]=v81[v83[4]];end elseif (v84<=59) then if (v84<=57) then if (v81[v83[2]]72) then for v304=v83[2],v83[3] do v81[v304]=nil;end else v81[v83[2]]=v64[v83[3]];end elseif (v84<=78) then if (v84<=75) then if (v84==74) then v81[v83[2]][v81[v83[3]]]=v81[v83[4]];else v81[v83[2]][v83[3]]=v81[v83[4]];end elseif (v84<=76) then v65[v83[3]]=v81[v83[2]];elseif (v84>77) then local v260=0;local v261;local v262;local v263;local v264;while true do if (v260==1) then v76=(v263 + v261) -1 ;v264=0;v260=2;end if (v260==2) then for v361=v261,v76 do v264=v264 + 1 ;v81[v361]=v262[v264];end break;end if (v260==0) then v261=v83[2];v262,v263=v74(v81[v261](v13(v81,v261 + 1 ,v76)));v260=1;end end else do return;end end elseif (v84<=81) then if (v84<=79) then if (v83[2]==v81[v83[4]]) then v75=v75 + 1 ;else v75=v83[3];end elseif (v84==80) then local v266=0;local v267;local v268;local v269;while true do if (v266==0) then v267=v83[2];v268={v81[v267](v81[v267 + 1 ])};v266=1;end if (v266==1) then v269=0;for v364=v267,v83[4] do v269=v269 + 1 ;v81[v364]=v268[v269];end break;end end else local v270=0;local v271;local v272;while true do if (v270==1) then for v367=v271 + 1 ,v83[4] do v272=v272 .. v81[v367] ;end v81[v83[2]]=v272;break;end if (v270==0) then v271=v83[3];v272=v81[v271];v270=1;end end end elseif (v84<=82) then v81[v83[2]]= not v81[v83[3]];elseif (v84>83) then local v273=v83[2];local v274=v83[4];local v275=v273 + 2 ;local v276={v81[v273](v81[v273 + 1 ],v81[v275])};for v306=1,v274 do v81[v275 + v306 ]=v276[v306];end local v277=v276[1];if v277 then v81[v275]=v277;v75=v83[3];else v75=v75 + 1 ;end else v81[v83[2]]=v83[3]~=0 ;end v75=v75 + 1 ;end end;end return v29(v28(),{},v17)(...);end v15("LOL!1C3O00028O00027O004003043O004D61696E030A3O004C6F675761726E696E67030A3O004C6F6753752O63652O7303073O004C6F67496E666F026O000840026O00F03F03123O0049734475706C696369747956657273696F6E03073O005468726561643103103O005265676973746572436F2O6D616E647303083O004C6F67452O726F72026O00144003073O004578706F72747303043O006D61696E03043O00496E697403073O00436974697A656E030C3O00437265617465546872656164030C3O0047657447616D6554696D657203133O0052656769737465724E554943612O6C6261636B03083O00412O705265616479030E3O00436865636B56616C6964496D706C030C3O005265676973746572496D706C03083O00496E6974496D706C026O00104003073O00476574496D706C03083O00496D706C43612O6C03083O00496D706C496E666F00763O0012073O00014O000A000100013O0026463O00020001000100044O00020001001207000100013O002646000100110001000200044O0011000100120F000200033O00023500035O00104B00020004000300120F000200033O000235000300013O00104B00020005000300120F000200033O000235000300023O00104B000200060003001207000100073O002646000100290001000800044O00290001001207000200013O000E4F000100210001000200044O0021000100120F000300094O00430003000100020006320003001D0001000100044O001D000100120F000300033O000235000400033O00104B0003000A000400120F000300033O000235000400043O00104B0003000B0004001207000200083O000E4F000800140001000200044O0014000100120F000300033O000235000400053O00104B0003000C0004001207000100023O00044O0029000100044O00140001002646000100370001000D00044O0037000100120F000200033O000235000300063O00104B0002000E000300120F000200033O0020020002000200102O000C0002000200020012340002000F3O00120F000200113O002019000200020012000235000300074O001500020002000100044O00750001002646000100520001000100044O00520001001207000200013O0026460002004A0001000100044O004A00012O002A00035O001234000300033O00120F000300094O004300030001000200061F0003004500013O00044O00450001000235000300083O001234000300133O00044O0049000100120F000300143O001207000400153O000235000500094O001E000300050001001207000200083O0026460002003A0001000800044O003A000100120F000300033O0002350004000A3O00104B000300100004001207000100083O00044O0052000100044O003A00010026460001005E0001000700044O005E000100120F000200033O0002350003000B3O00104B00020016000300120F000200033O0002350003000C3O00104B00020017000300120F000200033O0002350003000D3O00104B000200180003001207000100193O002646000100050001001900044O00050001001207000200013O0026460002006A0001000100044O006A000100120F000300033O0002350004000E3O00104B0003001A000400120F000300033O0002350004000F3O00104B0003001B0004001207000200083O000E4F000800610001000200044O0061000100120F000300033O000235000400103O00104B0003001C00040012070001000D3O00044O0005000100044O0061000100044O0005000100044O0075000100044O000200012O004D3O00013O00113O00063O00028O0003063O00436F6E66696703053O00446562756703053O007072696E74030E3O005B5E335741524E494E475E305D2003063O00666F726D617402193O001207000300014O000A000400043O002646000300020001000100044O00020001001207000400013O002646000400050001000100044O0005000100120F000500023O0020190005000500030006320005000C0001000100044O000C00012O004D3O00013O00120F000500043O001207000600054O0029000700014O00040006000600070020020006000600062O002400086O004E00066O000D00053O000100044O0018000100044O0005000100044O0018000100044O000200012O004D3O00017O00063O00028O0003063O00436F6E66696703053O00446562756703053O007072696E74030B3O005B5E32494E464F5E305D2003063O00666F726D617402133O001207000300013O002646000300010001000100044O0001000100120F000400023O002019000400040003000632000400080001000100044O000800012O004D3O00013O00120F000400043O001207000500054O0029000600014O00040005000500060020020005000500062O002400076O004E00056O000D00043O000100044O0012000100044O000100012O004D3O00017O00063O00028O0003063O00436F6E66696703053O00446562756703053O007072696E74030B3O005B5E35494E464F5E305D2003063O00666F726D617402133O001207000300013O002646000300010001000100044O0001000100120F000400023O002019000400040003000632000400080001000100044O000800012O004D3O00013O00120F000400043O001207000500054O0029000600014O00040005000500060020020005000500062O002400076O004E00056O000D00043O000100044O0012000100044O000100012O004D3O00017O00023O0003073O00436974697A656E030C3O0043726561746554687265616401063O00120F000100013O00201900010001000200062D00023O000100012O001A8O00150001000200012O004D3O00013O00013O000E3O00028O0003083O00706C61796572496403083O00506C61796572496403093O00706C61796572506564030B3O00506C617965725065644964026O00F03F027O0040030C3O00706C61796572432O6F726473030F3O00476574456E74697479432O6F726473030D3O00706C6179657248656164696E6703103O00476574456E7469747948656164696E6703073O00436974697A656E03043O0057616974025O00408F4000353O0012073O00013O0026463O00140001000100044O00140001001207000100013O0026460001000F0001000100044O000F00012O000100025O00120F000300034O004300030001000200104B0002000200032O000100025O00120F000300054O004300030001000200104B000200040003001207000100063O002646000100040001000600044O000400010012073O00063O00044O0014000100044O000400010026463O002B0001000600044O002B0001001207000100013O0026460001001B0001000600044O001B00010012073O00073O00044O002B0001002646000100170001000100044O001700012O000100025O00120F000300094O000100045O0020190004000400042O000C00030002000200104B0002000800032O000100025O00120F0003000B4O000100045O0020190004000400042O000C00030002000200104B0002000A0003001207000100063O00044O001700010026463O00010001000700044O0001000100120F0001000C3O00201900010001000D0012070002000E4O001500010002000100046O000100044O0001000100046O00012O004D3O00017O00033O0003123O0049734475706C696369747956657273696F6E030F3O005265676973746572436F2O6D616E64030B3O00746F2O676C656465627567010A3O00120F000100014O0043000100010002000632000100090001000100044O0009000100120F000100023O001207000200033O00062D00033O000100012O001A8O001E0001000300012O004D3O00013O00013O000B3O00028O0003063O00436F6E66696703053O00446562756703073O004C6F67496E666F03083O004465627567202573026O00F03F030E3O0053656E644E55494D652O7361676503063O00616374696F6E03113O00757064617465536572766572537461746503043O006461746103053O006973446576032B3O001207000300014O000A000400043O002646000300020001000100044O00020001001207000400013O0026460004001B0001000100044O001B0001001207000500013O000E4F000100160001000500044O0016000100120F000600023O00120F000700023O0020190007000700032O0009000700073O00104B0006000300072O000100065O002002000600060004001207000800053O00120F000900023O0020190009000900032O001E000600090001001207000500063O000E4F000600080001000500044O00080001001207000400063O00044O001B000100044O00080001000E4F000600050001000400044O0005000100120F000500074O002A00063O00020030310006000800092O002A00073O000100120F000800023O00201900080008000300104B0007000B000800104B0006000A00072O001500050002000100044O002A000100044O0005000100044O002A000100044O000200012O004D3O00017O00063O00028O0003063O00436F6E66696703053O00446562756703053O007072696E74030C3O005B5E31452O524F525E305D2003063O00666F726D617402133O001207000300013O002646000300010001000100044O0001000100120F000400023O002019000400040003000632000400080001000100044O000800012O004D3O00013O00120F000400043O001207000500054O0029000600014O00040005000500060020020005000500062O002400076O004E00056O000D00043O000100044O0012000100044O000100012O004D3O00017O00023O0003073O006578706F72747303083O00496D706C43612O6C01063O00120F000100013O001207000200023O00062D00033O000100012O001A8O001E0001000300012O004D3O00013O00013O00013O0003083O00496D706C43612O6C02084O000100035O0020020003000300012O002900056O0029000600014O002400076O000600036O001400036O004D3O00017O000F3O00028O00030C3O0047657447616D6554696D657203043O006D61696E03163O006C61737454696D65496D706C52656769737465726564025O00408F4003073O00436974697A656E03043O00576169742O033O0045535800026O005940026O00F03F03123O0049734475706C696369747956657273696F6E030E3O004973506C617965724C6F6164656403083O004E7569526561647903083O00496E6974496D706C003E3O0012073O00013O0026463O00170001000100044O0017000100120F000100024O004300010001000200120F000200033O00201900020002000400201C00020002000500063B0001000F0001000200044O000F000100120F000100063O002019000100010007001207000200014O001500010002000100044O0003000100120F000100083O002646000100160001000900044O0016000100120F000100073O0012070002000A4O001500010002000100044O000F00010012073O000B3O0026463O00010001000B00044O0001000100120F0001000C4O0043000100010002000632000100380001000100044O00380001001207000100014O000A000200023O0026460001001F0001000100044O001F0001001207000200013O002646000200220001000100044O0022000100120F000300083O00201900030003000D2O00430003000100020006320003002D0001000100044O002D000100120F000300073O0012070004000A4O001500030002000100044O0024000100120F0003000E3O000632000300380001000100044O0038000100120F000300073O0012070004000A4O001500030002000100044O002D000100044O0038000100044O0022000100044O0038000100044O001F000100120F000100033O00200200010001000F2O001500010002000100044O003D000100044O000100012O004D3O00017O00033O0003023O006F7303053O00636C6F636B025O00408F4000063O00120F3O00013O0020195O00022O00433O0001000200203D5O00032O00273O00024O004D3O00017O00023O00028O0003083O004E75695265616479020B3O001207000200013O002646000200010001000100044O000100012O0029000300014O002A00046O00150003000200012O0053000300013O001234000300023O00044O000A000100044O000100012O004D3O00017O001B3O00028O00026O00104003103O005265676973746572436F2O6D616E6473026O00F03F03053O00696D706C7303103O00696E697469616C697A6564496D706C73027O0040030C3O007365746D6574617461626C6503073O002O5F696E64657803043O004D61696E03163O006C61737454696D65496D706C5265676973746572656403053O0072656164790100026O00084003123O0049734475706C696369747956657273696F6E030C3O00706C61796572432O6F726473030F3O00476574456E74697479432O6F72647303093O00706C61796572506564030D3O00706C6179657248656164696E6703103O00476574456E7469747948656164696E67030E3O00706C61796572536572766572496403113O00476574506C61796572536572766572496403083O00706C61796572496403073O005468726561643103083O00506C617965724964030B3O00506C61796572506564496403073O004578706F72747301563O001207000100014O000A000200023O002646000100070001000200044O000700010020020003000200032O00150003000200012O0027000200023O0026460001000E0001000400044O000E00012O002A00035O00104B0002000500032O002A00035O00104B000200060003001207000100073O002646000100190001000100044O001900012O002A00036O0029000200033O00120F000300084O0029000400024O002A00053O000100120F0006000A3O00104B0005000900062O001E000300050001001207000100043O000E4F0007001E0001000100044O001E00010030310002000B00010030310002000C000D0012070001000E3O002646000100020001000E00044O0002000100120F0003000F4O0043000300010002000632000300510001000100044O00510001001207000300014O000A000400043O000E4F000100260001000300044O00260001001207000400013O0026460004003C0001000400044O003C0001001207000500013O002646000500300001000400044O00300001001207000400073O00044O003C00010026460005002C0001000100044O002C000100120F000600113O0020190007000200122O000C00060002000200104B00020010000600120F000600143O0020190007000200122O000C00060002000200104B000200130006001207000500043O00044O002C0001002646000400450001000700044O0045000100120F000500163O0020190006000200172O000C00050002000200104B0002001500050020020005000200182O001500050002000100044O00510001002646000400290001000100044O0029000100120F000500194O004300050001000200104B00020017000500120F0005001A4O004300050001000200104B000200120005001207000400043O00044O0029000100044O0051000100044O0026000100200200030002001B2O0015000300020001001207000100023O00044O000200012O004D3O00017O00063O00028O00026O00F03F03083O004C6F67452O726F72030E3O00496D706C202573206973206E696C03043O00496E6974031D3O00496D706C202573206D692O73696E6720496E69742066756E6374696F6E03363O001207000300014O000A000400043O002646000300020001000100044O00020001001207000400013O001207000500013O002646000500060001000100044O000600010026460004002C0001000100044O002C0001001207000600013O0026460006000F0001000200044O000F0001001207000400023O00044O002C00010026460006000B0001000100044O000B0001000632000200190001000100044O0019000100200200073O0003001207000900044O0029000A00014O001E0007000A00012O005300076O0027000700023O0020190007000200050006320007002A0001000100044O002A0001001207000700013O0026460007001D0001000100044O001D0001001207000800013O002646000800200001000100044O0020000100200200093O0003001207000B00064O0029000C00014O001E0009000C00012O005300096O0027000900023O00044O0020000100044O001D0001001207000600023O00044O000B0001002646000400050001000200044O000500012O0053000600014O0027000600023O00044O0005000100044O0006000100044O0005000100044O0035000100044O000200012O004D3O00017O00123O00028O00026O00F03F030E3O00436865636B56616C6964496D706C03053O00696D706C73027O004003163O006C61737454696D65496D706C52656769737465726564030C3O0047657447616D6554696D6572030A3O004C6F6753752O63652O7303123O00496D706C2025732072656769737465726564026O00084003053O00726561647903103O00696E697469616C697A6564496D706C7303073O004F6E526561647903063O00436F6E666967030D3O00456E61626C654D6F64756C6573030A3O004C6F675761726E696E6703133O00496D706C202573206E6F7420656E61626C6564031A3O00496D706C20257320616C7265616479207265676973746572656403833O001207000300014O000A000400043O002646000300020001000100044O00020001001207000400013O002646000400190001000200044O00190001001207000500013O002646000500140001000100044O0014000100200200063O00032O0029000800014O0029000900024O0016000600090002000632000600110001000100044O001100012O004D3O00013O00201900063O00042O0037000600010002001207000500023O000E4F000200080001000500044O00080001001207000400053O00044O0019000100044O000800010026460004002B0001000500044O002B0001001207000500013O002646000500260001000100044O0026000100120F000600074O004300060001000200104B3O0006000600200200063O0008001207000800094O0029000900014O001E000600090001001207000500023O0026460005001C0001000200044O001C00010012070004000A3O00044O002B000100044O001C0001002646000400450001000A00044O0045000100201900053O000B00061F0005008200013O00044O00820001001207000500014O000A000600063O002646000500320001000100044O00320001001207000600013O002646000600350001000100044O0035000100201900073O000C2O0029000800024O002900096O000C0008000200022O003700070001000800201900073O000C2O000B00070007000100200200070007000D2O001500070002000100044O0082000100044O0035000100044O0082000100044O0032000100044O00820001002646000400050001000100044O00050001001207000500013O000E4F0001007A0001000500044O007A000100120F0006000E3O00201900060006000F2O000B000600060001000632000600620001000100044O00620001001207000600014O000A000700073O002646000600510001000100044O00510001001207000700013O002646000700540001000100044O00540001001207000800013O000E4F000100570001000800044O0057000100200200093O0010001207000B00114O0029000C00014O001E0009000C00012O004D3O00013O00044O0057000100044O0054000100044O0062000100044O0051000100201900063O00042O000B00060006000100061F0006007900013O00044O00790001001207000600014O000A000700073O000E4F000100680001000600044O00680001001207000700013O0026460007006B0001000100044O006B0001001207000800013O0026460008006E0001000100044O006E000100200200093O0010001207000B00124O0029000C00014O001E0009000C00012O004D3O00013O00044O006E000100044O006B000100044O0079000100044O00680001001207000500023O002646000500480001000200044O00480001001207000400023O00044O0005000100044O0048000100044O0005000100044O0082000100044O000200012O004D3O00017O00133O00028O00026O00F03F03053O0072656164792O0103053O00706169727303103O00696E697469616C697A6564496D706C7303073O004F6E5265616479027O004003053O00696D706C7303073O004C6F67496E666F03153O00412O6C20696D706C7320696E697469616C697A656403123O0049734475706C696369747956657273696F6E030E3O0053656E644E55494D652O7361676503063O00616374696F6E03113O00757064617465536572766572537461746503043O006461746103053O00697344657603063O00436F6E66696703053O00446562756701303O001207000100013O000E4F0002000D0001000100044O000D00010030313O0003000400120F000200053O00201900033O00062O002F00020002000400044O000A00010020020007000600072O0015000700020001000654000200080001000200044O00080001001207000100083O0026460001001E0001000100044O001E000100120F000200053O00201900033O00092O002F00020002000400044O0018000100201900073O00062O0029000800064O002900096O000C0008000200022O0037000700050008000654000200130001000200044O0013000100200200023O000A0012070004000B4O001E000200040001001207000100023O000E4F000800010001000100044O0001000100120F0002000C4O00430002000100020006320002002F0001000100044O002F000100120F0002000D4O002A00033O00020030310003000E000F2O002A00043O000100120F000500123O00201900050005001300104B00040011000500104B0003001000042O001500020002000100044O002F000100044O000100012O004D3O00017O00043O00028O0003103O00696E697469616C697A6564496D706C7303083O004C6F67452O726F7203113O00496D706C202573206E6F7420666F756E64021B3O001207000200014O000A000300033O002646000200020001000100044O00020001001207000300013O002646000300050001000100044O0005000100201900043O00022O000B000400040001000632000400140001000100044O00140001001207000400013O0026460004000C0001000100044O000C000100200200053O0003001207000700044O0029000800014O001E0005000800012O004D3O00013O00044O000C000100201900043O00022O000B0004000400012O0027000400023O00044O0005000100044O001A000100044O000200012O004D3O00017O00073O00028O00026O00F03F03083O004C6F67452O726F7203253O00496D706C202573206D692O73696E672066756E6374696F6E202573202D206172677320257303043O006A736F6E03063O00656E636F646503073O00476574496D706C03283O001207000400014O000A000500053O0026460004001C0001000200044O001C00012O000B000600050002000632000600170001000100044O00170001001207000600013O002646000600080001000100044O0008000100200200073O0003001207000900044O0029000A00014O0029000B00023O00120F000C00053O002019000C000C00062O002A000D6O0024000E6O0003000D3O00012O0044000C000D4O000D00073O00012O004D3O00013O00044O000800012O000B0006000500022O0029000700054O002400086O000600066O001400065O002646000400020001000100044O0002000100200200063O00072O0029000800014O00160006000800022O0029000500063O000632000500250001000100044O002500012O004D3O00013O001207000400023O00044O000200012O004D3O00017O000A3O0003053O00706169727303053O00696D706C73028O00026O00F03F03073O00676574696E666F03073O004F6E526561647903013O005303073O004C6F67496E666F030C3O00496D706C202573202D20257303093O0073686F72745F73726301203O00120F000100013O00201900023O00022O002F00010002000300044O001D0001001207000600034O000A000700083O0026460006000B0001000300044O000B0001001207000700034O000A000800083O001207000600043O002646000600060001000400044O000600010026460007000D0001000300044O000D0001002019000900080005002019000A00050006001207000B00074O00160009000B00022O0029000800093O00200200093O0008001207000B00094O0029000C00043O002019000D0008000A2O001E0009000D000100044O001D000100044O000D000100044O001D000100044O00060001000654000100040001000200044O000400012O004D3O00017O00",v9(),...); \ No newline at end of file diff --git a/main.lua b/main.lua index 731dd11..adcb197 100644 --- a/main.lua +++ b/main.lua @@ -1,8 +1,15 @@ Main = {} +ResourceName = GetCurrentResourceName() +local RegisteredEvents = {} if IsDuplicityVersion() then function GetGameTimer() return os.clock() * 1000 end +else + RegisterNUICallback('AppReady', function(data, cb) + cb({}) + NuiReady = true + end) end function Main:Init() local o = {} @@ -16,9 +23,31 @@ function Main:Init() o.playerPed = PlayerPedId() o.playerCoords = GetEntityCoords(o.playerPed) o.playerHeading = GetEntityHeading(o.playerPed) + o.playerServerId = GetPlayerServerId(o.playerId) o:Thread1() + + else + o.ClientImpls = {} + for k, v in pairs(Config.EnableModules) do + if v then + local path = "client/impl/" .. k .. ".impl.lua" + local source = LoadResourceFile(ResourceName, path) + if source == nil then + self:LogError("Failed to load %s", path) + else + --[[ self:LogInfo("Loading %s", path) + self:LogInfo("Loaded %s", source) ]] + o.ClientImpls[k] = source + end + end + end + lib.callback.register(ResourceName..":getClientImpl", function(source, implName) + return o.ClientImpls[implName] + end) end o:Exports() + o:RegisterCommands() + o:RegisterEvents() return o end if not IsDuplicityVersion() then @@ -35,6 +64,76 @@ if not IsDuplicityVersion() then end end +function Main:RegisterCommands() + if not IsDuplicityVersion() then + RegisterCommand("toggledebug:"..ResourceName, function(source, args, rawCommand) + Config.Debug = not Config.Debug + self:LogInfo("Debug %s", Config.Debug) + end) + RegisterCommand("toggledev:"..ResourceName, function(source, args, rawCommand) + Config.Dev = not Config.Dev + self:LogInfo("Dev %s", Config.Dev) + SendNUIMessage({ + action = "updateServerState", + data = { + isDev = Config.Dev, + } + }) + end) + RegisterCommand("implinfo:"..ResourceName, function(source, args, rawCommand) + self:ImplInfo() + end) + RegisterCommand("test", function() + TriggerEvent("test") + end) + else + RegisterCommand("reload:"..ResourceName, function(source, args, rawCommand) + local implName = args[1] + local mode = args[2] + if mode == nil then + mode = "0" + end + self:LogInfo("Restarting impl: %s | side: %s (0: both, 1: client, 2: server)", implName, mode) + if mode == "0" or mode == "2" then + local svImpl = self:GetImpl(implName) + if svImpl then + svImpl:Destroy() + self.impls[implName] = nil + self.initializedImpls[implName] = nil + end + local source = LoadResourceFile(ResourceName, "server/impl/" .. implName .. ".impl.lua") + if source == nil then + self:LogError("Failed to load %s", path) + else + self:LogInfo("Loading %s", implName) + load(source)() + end + end + if mode == "0" or mode == "1" then + local clSource = LoadResourceFile(ResourceName, "client/impl/" .. implName .. ".impl.lua") + if clSource == nil then + self:LogError("Failed to load %s", path) + else + self:LogInfo("Loading %s", "client/impl/" .. implName .. ".impl.lua") + TriggerClientEvent(ResourceName..":restartClientImpl", -1, implName, clSource) + end + end + end, true) + end +end + +function Main:RegisterEvents() + RegisterNetEvent(ResourceName..":restartClientImpl", function(implName, source) + local clImpl = self:GetImpl(implName) + if clImpl then + clImpl:Destroy() + self.impls[implName] = nil + self.initializedImpls[implName] = nil + end + load(source)() + end) +end + function Main:LogError(msg, ...) if not Config.Debug then return end print(("[^1ERROR^0] " .. msg):format(...)) @@ -68,6 +167,10 @@ function Main:CheckValidImpl(name, impl) end function Main:RegisterImpl(name, impl) + if not Config.EnableModules[name] then + self:LogWarning("Impl %s not enabled", name) + return + end if self.impls[name] then self:LogWarning("Impl %s already registered", name) return @@ -77,14 +180,34 @@ function Main:RegisterImpl(name, impl) end self.impls[name] = impl self.lastTimeImplRegistered = GetGameTimer() + self:LogSuccess("Impl %s registered", name) if self.ready then - self.initializedImpls[name] = impl(self) - self.initializedImpls[name]:OnReady() + Citizen.CreateThread(function() + self:LogSuccess("Impl %s hot reloading", name) + Wait(1000) + self.initializedImpls[name] = impl(self) + if not self.initializedImpls[name] then + self:LogError("Impl %s failed to hot reload", name) + return + end + self.initializedImpls[name]:OnReady() + self:LogSuccess("Impl %s hot reloaded", name) + end) end end function Main:InitImpl() + if not IsDuplicityVersion() then + for k, v in pairs(Config.EnableModules) do + if v then + self:LogInfo("Loading %s", k) + local source = lib.callback.await(ResourceName..":getClientImpl", false, k) + self:LogInfo("Loaded %s", k) + load(source)() + end + end + end for name, impl in pairs(self.impls) do self.initializedImpls[name] = impl(self) end @@ -93,6 +216,15 @@ function Main:InitImpl() for name, impl in pairs(self.initializedImpls) do impl:OnReady() end + if not IsDuplicityVersion() then + SendNUIMessage({ + action = "updateServerState", + data = { + isDev = Config.Dev, + } + }) + end + end function Main:GetImpl(name) @@ -116,10 +248,9 @@ function Main:ImplCall(name, func, ...) end - function Main:ImplInfo() for name, impl in pairs(self.impls) do - local debug = debug.getinfo(impl.Init, "S") + local debug = debug.getinfo(impl.OnReady, "S") self:LogInfo("Impl %s - %s", name, debug.short_src) end end @@ -132,11 +263,41 @@ end main = Main:Init() +local origAddEventHandler = AddEventHandler +function AddEventHandler(eventName, ...) + if RegisteredEvents[eventName] then + main:LogWarning("Event %s already registered. Removing", eventName) + RemoveEventHandler(RegisteredEvents[eventName]) + end + RegisteredEvents[eventName] = origAddEventHandler(eventName, ...) + return RegisteredEvents[eventName] +end + +local origRegisterNetEvent = RegisterNetEvent +function RegisterNetEvent(eventName, ...) + if RegisteredEvents[eventName] then + main:LogWarning("Event %s already registered. Removing", eventName) + RemoveEventHandler(RegisteredEvents[eventName]) + end + RegisteredEvents[eventName] = origRegisterNetEvent(eventName, ...) + return RegisteredEvents[eventName] +end + Citizen.CreateThread(function() while GetGameTimer() < main.lastTimeImplRegistered + 1000 do Citizen.Wait(0) end + while ESX == nil do + Wait(100) + end + if not IsDuplicityVersion() then + while not ESX.IsPlayerLoaded() do + Wait(100) + end + while not NuiReady and Config.Nui do + Wait(100) + end + end main:InitImpl() - main:ImplInfo() end)