Skip to content

Commit d0863ed

Browse files
committed
chore(Lua): update docs
1 parent 300bf00 commit d0863ed

File tree

2 files changed

+192
-6
lines changed

2 files changed

+192
-6
lines changed

assets/Changelog.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,24 @@ Added comprehensive Delayed Action System for game-thread timer management ([UE4
146146
- Per-mod action ownership ensures mods can only control their own timers
147147
- **Deprecates:** `ExecuteAsync` and `LoopAsync` (still work but lack control features)
148148

149+
Added AsyncCompute system for thread-safe async computation with callback support ([UE4SS #1130](https://github.com/UE4SS-RE/RE-UE4SS/pull/1130))
150+
- `AsyncCompute(taskName, input, callback)` - Run registered C++ task handlers asynchronously
151+
- `AsyncComputeLua(sourceCode, input, callback, options)` - Run pure Lua code in isolated worker threads
152+
- Worker code runs in a completely isolated Lua state (no UE4SS bindings or game access)
153+
- Safe standard library: math, string, table, utf8, io, os, coroutine
154+
- Excluded for isolation: debug, load, loadfile, dofile, require, package
155+
- Optional JSON support via `{ json = true }` options table
156+
- `CancelAsyncCompute(handle)` - Cancel a pending async task
157+
- Built-in task handlers: `sleep`, `compute`
158+
- Results delivered via callbacks on the main thread with `{ success, result, error }` table
159+
- Ideal for CPU-intensive operations without blocking the game thread
160+
161+
Added JSON serialization functions for Lua values ([UE4SS #1130](https://github.com/UE4SS-RE/RE-UE4SS/pull/1130))
162+
- `json.encode(value, pretty)` - Convert Lua value to JSON string
163+
- `json.decode(jsonString)` - Parse JSON string to Lua value
164+
- Supports tables (arrays and objects), strings, numbers, booleans, and nil
165+
- Nested structures and Unicode supported
166+
149167
**Updated Lua version to 5.4.7** ([UE4SS #887](https://github.com/UE4SS-RE/RE-UE4SS/pull/887))
150168
- This is necessary to compile with Clang.
151169

docs/lua-api/global-functions/asynccompute.md

Lines changed: 174 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,90 @@ The callback receives a result table with the following structure:
3737
}
3838
```
3939

40+
## AsyncComputeLua
41+
42+
Runs pure Lua code on a worker thread in an isolated Lua state. Unlike `AsyncCompute`, this allows you to write custom computation logic in Lua without needing C++ task handlers.
43+
44+
```lua
45+
local handle = AsyncComputeLua(sourceCode, input, callback, options?)
46+
```
47+
48+
| # | Type | Information |
49+
|---|------|-------------|
50+
| 1 | string | Lua source code that returns a function |
51+
| 2 | any | Input data (serializable primitives and tables only) |
52+
| 3 | function | Callback to receive result |
53+
| 4 | table? | Optional options table (see below) |
54+
| Return | integer | Handle to track/cancel the task |
55+
56+
**Options table:**
57+
```lua
58+
{
59+
json = boolean -- Add json.encode/decode to worker (default: false)
60+
}
61+
```
62+
63+
The source code must return a function that takes input and returns output:
64+
65+
```lua
66+
local handle = AsyncComputeLua([[
67+
return function(input)
68+
-- Computation runs in isolated Lua state
69+
local result = 0
70+
for i = 1, input.iterations do
71+
result = result + math.sqrt(i)
72+
end
73+
return { sum = result }
74+
end
75+
]], { iterations = 1000000 }, function(result)
76+
if result.success then
77+
print("Sum: " .. result.result.sum .. "\n")
78+
else
79+
print("Error: " .. result.error .. "\n")
80+
end
81+
end)
82+
```
83+
84+
### Isolated Environment
85+
86+
The worker runs in a completely independent Lua state with:
87+
88+
**Available:**
89+
- `math.*` - All math functions
90+
- `string.*` - String manipulation
91+
- `table.*` - Table utilities
92+
- `utf8.*` - UTF-8 support
93+
- `io.*` - File I/O (use with care for threading)
94+
- `os.*` - OS functions (time, clock, execute, etc.)
95+
- `coroutine.*` - Coroutines within the worker
96+
- Basic functions: `tonumber`, `tostring`, `type`, `pairs`, `ipairs`, `next`, `select`, `pcall`, `xpcall`, `error`, `assert`, `rawget`, `rawset`, `rawequal`, `rawlen`, `setmetatable`, `getmetatable`, `unpack`/`table.unpack`
97+
98+
**NOT available (for isolation):**
99+
- `debug.*` - Could break isolation
100+
- `load`, `loadfile`, `dofile` - Dynamic code loading
101+
- `require`, `package.*` - Module system
102+
- All UE4SS bindings - No `FindFirstOf`, `RegisterHook`, etc.
103+
- Main state globals - Worker is completely independent
104+
105+
### JSON Support in Workers
106+
107+
Enable JSON with `{ json = true }`:
108+
109+
```lua
110+
AsyncComputeLua([[
111+
return function(input)
112+
-- Parse incoming JSON
113+
local data = json.decode(input.json_string)
114+
115+
-- Process...
116+
data.processed = true
117+
118+
-- Return as JSON
119+
return { result_json = json.encode(data) }
120+
end
121+
]], { json_string = '{"value": 42}' }, callback, { json = true })
122+
```
123+
40124
## CancelAsyncCompute
41125

42126
Cancels a pending async computation.
@@ -144,6 +228,83 @@ AsyncCompute("compute", { iterations = 1000000 }, function(result)
144228
end)
145229
```
146230

231+
### Lua Worker - Custom Computation
232+
233+
```lua
234+
-- Run custom Lua code without a C++ handler
235+
AsyncComputeLua([[
236+
return function(input)
237+
local sum = 0
238+
for i = 1, input.count do
239+
sum = sum + math.sqrt(i)
240+
end
241+
return { sum = sum, count = input.count }
242+
end
243+
]], { count = 1000000 }, function(result)
244+
if result.success then
245+
print(string.format("Sum of %d square roots: %f\n",
246+
result.result.count, result.result.sum))
247+
end
248+
end)
249+
```
250+
251+
### Lua Worker - Data Processing with JSON
252+
253+
```lua
254+
-- Parse and transform JSON data off the main thread
255+
local jsonData = '{"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}'
256+
257+
AsyncComputeLua([[
258+
return function(input)
259+
local data = json.decode(input.json)
260+
261+
-- Process users
262+
local adults = {}
263+
for _, user in ipairs(data.users) do
264+
if user.age >= 18 then
265+
table.insert(adults, user.name)
266+
end
267+
end
268+
269+
return {
270+
adult_names = adults,
271+
count = #adults
272+
}
273+
end
274+
]], { json = jsonData }, function(result)
275+
if result.success then
276+
print("Adults: " .. table.concat(result.result.adult_names, ", ") .. "\n")
277+
end
278+
end, { json = true })
279+
```
280+
281+
### Lua Worker - String Processing
282+
283+
```lua
284+
-- Heavy string processing without blocking
285+
AsyncComputeLua([[
286+
return function(input)
287+
local text = input.text
288+
local words = {}
289+
290+
for word in text:gmatch("%S+") do
291+
table.insert(words, word:lower())
292+
end
293+
294+
table.sort(words)
295+
296+
return {
297+
word_count = #words,
298+
sorted = table.concat(words, " ")
299+
}
300+
end
301+
]], { text = "The quick brown fox jumps over the lazy dog" }, function(result)
302+
if result.success then
303+
print(result.result.word_count .. " words: " .. result.result.sorted .. "\n")
304+
end
305+
end)
306+
```
307+
147308
## Input Serialization
148309

149310
AsyncCompute serializes your input data before passing it to the worker thread. Only these types are supported:
@@ -208,9 +369,16 @@ end)
208369
|----------|--------|----------|
209370
| `ExecuteAsync` (deprecated) | Async thread | Simple delays (unsafe, deprecated) |
210371
| `ExecuteInGameThreadWithDelay` | Game thread | Delayed game logic, UObject access |
211-
| `AsyncCompute` | Worker pool | CPU-intensive computation |
212-
213-
Use `AsyncCompute` when you have work that:
214-
- Takes significant CPU time
215-
- Doesn't need UObject access during computation
216-
- Can have its result serialized as primitives/tables
372+
| `AsyncCompute` | Worker pool | CPU-intensive computation (C++ handlers) |
373+
| `AsyncComputeLua` | Worker pool | Custom Lua computation (no C++ needed) |
374+
375+
**When to use `AsyncCompute`:**
376+
- You need a built-in task (sleep, compute)
377+
- A C++ mod provides custom task handlers you want to use
378+
- Maximum performance for frequently-used operations
379+
380+
**When to use `AsyncComputeLua`:**
381+
- You want to write custom computation logic in Lua
382+
- You don't want to write or depend on C++ code
383+
- You need JSON parsing/generation in the worker
384+
- One-off computations that don't justify a C++ handler

0 commit comments

Comments
 (0)