{"id":25538711,"url":"https://github.com/xan105/anylua","last_synced_at":"2026-04-26T22:31:12.804Z","repository":{"id":277637264,"uuid":"933060906","full_name":"xan105/AnyLua","owner":"xan105","description":"Lua Scripting in any game!","archived":false,"fork":false,"pushed_at":"2025-02-15T04:05:32.000Z","size":9511,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-15T05:17:52.829Z","etag":null,"topics":["lua","luajit"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xan105.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"xan105","custom":"https://www.paypal.me/xan105"}},"created_at":"2025-02-15T03:53:34.000Z","updated_at":"2025-02-15T04:05:38.000Z","dependencies_parsed_at":"2025-02-15T05:27:56.090Z","dependency_job_id":null,"html_url":"https://github.com/xan105/AnyLua","commit_stats":null,"previous_names":["xan105/anylua"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2FAnyLua","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2FAnyLua/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2FAnyLua/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xan105%2FAnyLua/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xan105","download_url":"https://codeload.github.com/xan105/AnyLua/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239781088,"owners_count":19695957,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lua","luajit"],"created_at":"2025-02-20T05:23:47.305Z","updated_at":"2026-04-26T22:31:12.795Z","avatar_url":"https://github.com/xan105.png","language":"C++","funding_links":["https://github.com/sponsors/xan105","https://www.paypal.me/xan105"],"categories":[],"sub_categories":[],"readme":"About\n=====\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/xan105/AnyLua/raw/main/logo.png\" width=\"300\" height=\"300\"/\u003e\n  \u003cbr/\u003e\u003cem\u003eAnyLua\u003c/em\u003e\n\u003c/p\u003e\n\nThis project adds a \"Lua Script engine\" to any process through DLL injection or sideloading.\n\nThe goal is to be able to handle things like memory manipulation and Win32 APIs from Lua.\nIt is powered by [LuaJIT](https://luajit.org/) (Lua 5.1).\n\n🐧 This software has an emphasis on being compatible with Linux/Proton.\n\n💻 This software is for my own personal use but feel free to use it.\n\n\u003e [!IMPORTANT]  \n\u003e This project is in its early stages, it is a work in progress.\n\nExample\n=======\n\nNo Man's Sky: Remove the \"Mod Enabled\" Warning screen on startup\n\n```lua\nlocal memory = require(\"memory\")\n\nlocal patch = { \n    pattern = \"48 8B 01 48 85 C0 74 08 0F B6 80 5A 46 00 00 C3\", \n    offset = 0x06, \n    value = \"EB\",\n}\n\nfunction apply(patch)\n  local address, err = memory.Find(patch.pattern)\n  if err then\n    error(err.message)\n  end\n  local success, err = memory.Write(address + patch.offset, patch.value)\n  if err then\n    error(err.message)\n  end\n  return success\nend\n\nif apply(patch) then\n  console.log(\"Applied patch!)\nend\n```\n\nUsage\n=====\n\nAnyLua will load `AnyLua.lua` relative to its own parent dir.\u003cbr /\u003e\nThe path can be overriden with the env var `ANYLUA_FILEPATH`.\n\nAnyLua can be used either as \n- ~~A) a drop-in replacement _(DLL side-loading)_ or~~\n- **B)** by being injected into a target process.\n\nUnless you know what you are doing stick with the first approach.\n\n## A) DLL Sideloading\n\n//TODO\n\n## B) DLL Injection\n\nYou need a DLL injector to inject `AnyLua` into the target process.\n\nA quick google search will find you plenty on GitHub.\u003cbr/\u003e\n🐧 Linux: the classic combo `createRemoteThread()` + `LoadLibrary()` from `Kernel32` works under Wine/Proton.\n\nAlternatively, here are some of my own:\n\n- [xan105/Mini-Launcher](https://github.com/xan105/Mini-Launcher):\n\n  \u003e CLI launcher with DLL Injection, Lua Scripting, Splash screen, and other goodies.\n\n- [xan105/node-remote-thread](https://github.com/xan105/node-remote-thread):\n\n  \u003e Node.js NAPI Native addon for Windows DLL injection with support for Wow64 and Unicode path.\n\n\u003e [!TIP]\n\u003e Consider changing the file extension from `.dll` to `.asi` to help prevent false positive with Windows Defender.\n\n\u003cdetails\u003e\u003csummary\u003eExample (xan105/Mini-Launcher)\u003c/summary\u003e\n\n```json\n{\n  \"bin\": \"Binaries/NMS.exe\",\n  \"env\": {\n    \"ANYLUA_FILEPATH\": \"%CURRENTDIR%\\\\main.lua\"\n  },\n  \"addons\": [\n    { \"path\": \"Binaries/AnyLua.asi\", \"required\": true }\n  ]\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eExample (xan105/node-remote-thread)\u003c/summary\u003e\n\n```js\nimport { env } from \"node:process\";\nimport { spawn } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { createRemoteThread } from \"@xan105/remote-thread\";\n\nconst EXECUTABLE = \"G:\\\\METAPHOR\\\\METAPHOR.exe\";\nconst ADDON = \"G:\\\\METAPHOR\\\\AnyLua.dll\";\nconst ARGS = [];\n\nconst binary = spawn(EXECUTABLE, ARGS, {\n  cwd: dirname(EXECUTABLE),\n  stdio:[ \"ignore\", \"ignore\", \"ignore\" ], \n  detached: true,\n  env: {\n    ...env,\n    \"ANYLUA_FILEPATH\": join(dirname(EXECUTABLE), \"main.lua\")\n  }\n});\n\nbinary.once(\"spawn\", () =\u003e {\n  binary.unref();\n  createRemoteThread(binary.pid, ADDON);\n});\n```\n\u003c/details\u003e\n\nLUA Scripting\n=============\n\nVery simple scripting engine powered by [LuaJIT](https://luajit.org/) (Lua 5.1).\u003cbr /\u003e\nSee the `./example` directory for some examples.\n\nStandard libs available are:\n\n  - Package\n  - Basic\n  - Table\n  - String\n  - Math\n  - bit (LuaJIT)\n  \nSome standard libraries are not enabled by design.\u003cbr /\u003e\nThe followings modules are exposed to the Lua VM, I might add more later on.\n  \n## 🌐 Globals\n\n### `sleep(ms: int)`\n\nSuspends the execution of the Lua engine until the time-out interval elapses (interval is in milliseconds).\n\n### `console: SetFuncs`\n\n  + `log(any, ...)`\n  + `warn(any, ...)`\n  + `error(any, ...)`\n  \nConvenience methods to print value or array with timestamp and log level. Values are colored depending on their type.\n\n💡 `print()` is an alias to `console.log()`\n\n### `Array: SetFuncs`\n\n  + `find(table, func) any`\n  + `some(table, func) bool`\n  + `includes(table, any) bool`\n  \nConvenience methods to search ~~array~~ Lua table.\n\nExample: \n\n```lua\nlocal arr = {1, 2, 3, 4, 5}\n\nArray.find(arr, function(x) return x \u003e 3 end)\nArray.includes(arr, 3)\n\nlocal arr = {\n  {foo = \"bar\", value = 1},\n  {foo = \"baz\", value = 2}\n}\n\nArray.find(arr, function(x) return x.foo == \"bar\" end)\nArray.some(arr, function(x) return x.foo == \"baz\" end)\n```\n\n### `Failure(code?: string, message?: string) Failure{ code: string, message: string }`\n\nFailure is a custom type (_userdata_) that represents an \"error object\" with an associated error code and message.\nThis provides a structured way to handle error.\n\n- `code?: string` (\"ERR_UNKNOWN\")\n  Error code.\n  \n- `message?: string` (\"An unknown error occurred\")\n  Error message.\n  \n💡 `Failure` has a `__tostring` metamethod. If not invoked automatically, you can explicitly call it using `tostring(Failure)`\n\nExample:\n\n```lua\nlocal err = Failure(\"ERR_NOT_FOUND\", \"The requested item was not found\")\nprint(err.code)    -- \"ERR_NOT_FOUND\"\nprint(err.message) -- \"The requested item was not found\"\nprint(err)         -- \"[ERR_NOT_FOUND]: The requested item was not found\"\n\nlocal value, err = Foo()\nif err and err.code == \"ERR_UNKNOWN\" then\n  error(err.message) -- Raise an error \"An unknown error occurred\"\n  -- or\n  error(tostring(err))\nend\n```\n\n## 📦 Modules\n\n### 📦 Audio\n\n```lua\nlocal audio = require(\"audio\")\n```\n\n- `PlaySystemSound(name: string) void`\n\n  Play specified Windows sytem sound asynchronously.\n\n- `PlaySound(filepath: string) void`\n\n  Play specified `.wav` filepath asynchronously.\n\n### 📦 Dialog\n\n```lua\nlocal dialog = require(\"dialog\")\n```\n\n- `Show({ message: string, title?: string, button?: string, icon?: string }) string`\n\n  Display a messagebox and return the user response input.\n\n  Button: `OK` | `OKCANCEL` | `YESNO` | `YESNOCANCEL` | `RETRYCANCEL` | `ABORTRETRYIGNORE`\n\n  Icon: `INFO` | `WARNING` | `ERROR` | `QUESTION`\n\n  Response: `OK` | `CANCEL` | `ABORT` | `RETRY` | `IGNORE` | `YES` | `NO` | `CONTINUE` | `TRYAGAIN`\n\n### 📦 Gamepad\n\n```lua\nlocal gamepad = require(\"gamepad/xinput\")\n```\n\n- `Rumble(playerID: number, vibration: number | {low?: number, high?: number }, duration?: number = 2500) void`\n\n  Rumble specified XInput gamepad.\n  \n  playderID: 0...3\n  \n  vibration: percent 0-100, as number = both motor.\n  \n  duration: in ms defaults to 2500 \n\n### 📦 Memory\n\n```lua\nlocal memory = require(\"memory\")\n```\n\n\u003e [!WARNING]\n\u003e Note on 64-bit addresses:\n\u003e\n\u003e LuaJIT (Lua 5.1) store numbers as double-precision floats, which only guarantee 53 bits of integer precision. On 64-bit processes,  very high addresses (above 0x20000000000000) may lose precision when returned as Lua numbers. \n\u003e\n\u003e For most Windows modules and processes this usually isn’t an issue, but could be, if you need exact 64-bit pointers.\n\n- `Write(address: number, value: string) bool, Failure | nil`\n\n  Write value byte to specified address. whitespace are ignored.\n\n  Ex: \"90 90 90 90 90 90\"\n\n- `Find(pattern: string, options?: { module?: string, match?: string } | string) address: number | number[], Failure | nil`\n\n  Find specified pattern hex string inside the process memory space and return its address.\n\n  pattern: use `?` for wildcard, whitespace are ignored.\n\n  Ex: `Find(\"AA ?? BB CC ?? ?? DD\")`\n  \n  module: when specified, scan module memory region instead of process.\n\n  Ex: `Find(\"48 8B ?? ?? ??\", { module = \"UnityPlayer.dll\" })`\n  \n  If options is a string then module is assumed.\n  \n  Ex: `Find(\"48 8B ?? ?? ??\", \"UnityPlayer.dll\")`\n  \n  match: `first` | `all` | `last` \n  \n  Return the first match (default), all matches, or the last match.\n  \n  Ex: `Find(\"48 8B ?? ?? ??\", { match = \"all\" })`\n\n- `ReadAs(address: number, typeStr: string, length?: number = 256) number | string | nil, Failure | nil`\n\n  Read the value at address as specified type.\n\n  typeStr: `i8` | `u8` | `i16` | `u16` | `i32` | `u32` | `i64` | `u64` | `f32` | `f64` | `ptr` | `str`\n\n  length: length of `str` (cstring) defaults to 256\n  \n- `GetBaseAddress(module?: string) address: number, Failure | nil`\n\n  Return the base address of the process.\n\n  module: when specified, return the base address of the module instead.\n\n### 📦 Process\n\n```lua\nlocal process = require(\"process\")\n```\n  \n`pid: number`: process pid\u003cbr/\u003e\n`name: string`: process name\u003cbr/\u003e\n`dir: string`: process parent dir\u003cbr/\u003e\n`cwd: string`: process current working dir\u003cbr/\u003e\n\n- `Exit(exitCode: number) void`\n\n  Terminate process with specified code\n\n- `Args() string[], Failure | nil`\n\n  Process command line arguments\n\n- `Env() {key=val, ...}, Failure | nil`\n\n  Process environement variables\n\n- `SetDpiAwareness(awareness: string) void`\n\n  Set process dpi awareness: `UNAWARE` | `SYSTEM` | `MONITOR` | `MONITORv2` | `GDISCALED`\n  \n- `SetExecutionState(stateFlags: string[]) Failure | nil`\n\n  \u003e Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.\n  \n  Set execution state flags: `CONTINUOUS` | `DISPLAY` | `SYSTEM`\n  \n  Example:\n  \n  ```lua\n  local process = require(\"process\")\n  -- This will keep the system and display awake until reset\n  process.SetExecutionState({\"CONTINUOUS\", \"DISPLAY\", \"SYSTEM\"})\n\n  -- Restore to normal behavior\n  process.SetExecutionState({\"CONTINUOUS\"})\n  ```\n\n- `LoadLibrary(filename: string) bool, Failure | nil`\n\n  Load specified dynamic library into the process.\n\n  cf: [Kernel32/LoadLibraryW()](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw)\n  \nBuild\n=====\n\n🆚 **Visual Studio 2022**\n\n📦 Vendor dependencies:\n  - [LuaJIT](http://luajit.org/)\n    + `./vendor/luajit/pull.cmd` to git clone LuaJIT.\n    + `./vendor/luajit/build.cmd` to build LuaJIT as static lib.\n\nSolution: `./vc/AnyLua.sln`\u003cbr /\u003e\nOutput: `./build/output/${platform}/${config}`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxan105%2Fanylua","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxan105%2Fanylua","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxan105%2Fanylua/lists"}