diff --git a/README.md b/README.md
index 227d79d..564fc79 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,9 @@
-
-
-
-FiveM React and Lua Boilerplate
+
+
+
+
-
-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)