Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
de2a942
Extend `CScriptStorage` with optional dialect specifier
ProfLander May 16, 2025
d2b2e7f
CScriptStorage / CScriptDialect refactor
ProfLander May 17, 2025
52193c8
Generalize script dialects to console commands
ProfLander May 17, 2025
f68ec6b
Refactor `parse_namespace`
ProfLander May 18, 2025
2a15c75
Use return semantics instead of public bindings for lisp
ProfLander May 18, 2025
1941b72
Move dialect string manipulation machinery into `lua_macros.h`
ProfLander May 18, 2025
6acf97a
Script namespace sanitization pass
ProfLander May 19, 2025
2cdacb9
Account for null namespace name in `CWuaGDialect`
ProfLander May 19, 2025
83da17a
Expose `CScriptDialect` to luabind
ProfLander May 19, 2025
678c2a9
Factor out `CWuaGDialect` in favor of `CWuaDialect`
ProfLander May 19, 2025
d73467b
Refactor around macro semantic
ProfLander May 19, 2025
6911324
Compiler semantic pass
ProfLander May 20, 2025
e1ca36b
Macro hygeine pass
ProfLander May 20, 2025
f26f936
Move `CScriptStorage::object` into `CScriptEngine`
ProfLander May 21, 2025
9c2bdb4
Implement direct package unloading
ProfLander May 21, 2025
318992e
Return error code instead of bool from `load_buffer`
ProfLander May 21, 2025
86e4e06
Improve error checking / reporting for `namespace_loaded`
ProfLander May 21, 2025
c56f05d
Run `init` before `_G`, use to implement Lua `print`
ProfLander May 21, 2025
c714adf
Move script compiler internals to Lua
ProfLander May 21, 2025
61a33dc
Factor out `CScriptCompiler` and `CScriptMacro`
ProfLander May 21, 2025
d27c174
Replace C-side `macro_wua` with Lua implementation
ProfLander May 22, 2025
d0cf8f1
Factor out `CScriptStorage`, `CScriptEngine::process_file`
ProfLander May 22, 2025
6806d78
Move sandboxing and `package.loader` setup into Lua
ProfLander May 22, 2025
20efcc3
Move `register_script_classes` into Lua
ProfLander May 22, 2025
6f6aa8a
Move `object_factory.register_script` call into Lua
ProfLander May 22, 2025
a89cdae
Move `load_common_scripts` into Lua
ProfLander May 22, 2025
eec5af8
Factor out `parse_script_namespace`
ProfLander May 22, 2025
3ab5d16
Rename `_init.script` to `init.script`
ProfLander May 22, 2025
5c7b73b
First-pass Lua-side loading
ProfLander May 23, 2025
4a6f250
Factor out `ScriptStorage` namespace in favor of `ScriptEngine`
ProfLander May 23, 2025
826daa7
Reimplement `CScriptStorage` as basic persistent Lua storage
ProfLander May 23, 2025
9c7cd2b
Rescan `$game_scripts$` recursively before booting script engine
ProfLander May 24, 2025
1bb8314
Print engine-level load message for `init.lua`, document globals
ProfLander May 24, 2025
00b9af3
Consistent logging style for `init.lua` load
ProfLander May 25, 2025
e93110d
Use X-Ray FS to load `init.lua`
ProfLander May 31, 2025
27bb3ff
Implement `load_file` to work around broken Lua `IReader` string beha…
ProfLander Jun 1, 2025
cb6caae
Reinstate `unlocalizers.lua`
ProfLander Jun 3, 2025
f255ea2
Integrate latest `wua`
ProfLander Jun 3, 2025
82b3076
Reintegrate latest `macro/wua`
ProfLander Jun 3, 2025
33bffff
Consistent logging for `init.lua`
ProfLander Jun 3, 2025
52513b8
Remove `macro/lua`
ProfLander Jun 3, 2025
d56a8d2
Remove `macro/lisp`
ProfLander Jun 3, 2025
d650534
Reorganize `macro` and `scam`, add `amx`
ProfLander Jun 3, 2025
0f053c1
Integrate up-to-date `init`, `boot`, `scam`
ProfLander Jun 3, 2025
49ccc4e
Integrate up-to-date `amx`
ProfLander Jun 3, 2025
c9eb2fd
Unify `pcall` / stack tracing into unwind-aware `init` compiler
ProfLander Jun 4, 2025
9d177a5
Register built-in `lua` compiler implicitly
ProfLander Jun 5, 2025
7716d87
Bind `_FILE` in `lua` compiler, improve error reporting
ProfLander Jun 5, 2025
7bc76d7
Skip modules with non-table `require` output in `amx/scripts`
ProfLander Jun 5, 2025
dce8d4f
Remove `_UNWIND` machinery, as it breaks consecutive error backtraces
ProfLander Jun 5, 2025
646b218
Patch `load`, `loadfile`, proper handling of nameless wua modules
ProfLander Jun 5, 2025
34a18ca
Don't try to unload console commands before running
ProfLander Jun 6, 2025
15e00b8
Only populate `_M` for named modules
ProfLander Jun 6, 2025
cf76d36
Replace old `eval_*` commands with `eval`, wraps `print`
ProfLander Jun 6, 2025
11cdc34
C++ Script Engine Cleanup
ProfLander Jun 8, 2025
f1106f6
Rename `amx` to `xr`, `xr/wua` to `xr/lua`
ProfLander Jun 8, 2025
7fe288b
Restructure boot process around `script.ltx` for flexibility
ProfLander Jun 8, 2025
05810fc
Replace `_COMPILER` with `loadstring`, simplify `boot/loader` impl
ProfLander Jun 8, 2025
88cbe1c
Use tables for compiler references, documentation pass
ProfLander Jun 8, 2025
9c4f25e
Fix broken `local function x(a, b, c)` unlocalization
ProfLander Jun 10, 2025
8c8fb1c
Account for `\r` endings when splitting Lua lines for unlocalization
ProfLander Jun 10, 2025
883f58f
Use `@`-prefixed `script_name` instead of `namespace_name` for `xr/lua`
ProfLander Jun 10, 2025
126aa01
Pass `loadstring` to base impl with env extension in `xr/lua`
ProfLander Jun 10, 2025
2c0b7d8
Replace all stateful `xr/lua` environment with metatable indirection
ProfLander Jun 11, 2025
d1057c4
Fix broken unlocalization of `local a, b` definitions
ProfLander Jun 11, 2025
36d9ec6
Remove unnecessary key redirection from `XR_PACKAGE`
ProfLander Jun 11, 2025
69eaff4
Unlocalizer: Fix `local function` early-out, comment matching
ProfLander Jun 11, 2025
0490053
Implement basic unit testing machinery in `tests`
ProfLander Jun 11, 2025
5218de6
Implement unlocalizer unit tests
ProfLander Jun 11, 2025
4bb0e73
Use `loadstring` instead of `_COMPILER` in `CScriptEngine`
ProfLander Jun 11, 2025
ca369d4
Preserve results of recursive filesystem scans to prevent loss of lis…
ProfLander Jun 13, 2025
e0aafea
Migrate module path separators from `/` to idiomatic Lua `.`
ProfLander Jun 13, 2025
e48329d
Improve `boot/loader` error aggregation
ProfLander Jun 13, 2025
30f75e8
Fix `_G` inheritance in `.lua` loaded from `.script`, add missing `xr…
ProfLander Jun 13, 2025
7eaddb3
Update `gamedata` directory tree in VS solution
ProfLander Jun 18, 2025
677459f
Reintegrate binary package loader
ProfLander Jun 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions gamedata/configs/mod_script_amx.ltx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
![common]
script = xr.compiler, xr.lua, amx, _G, _g_patches, xr.classes, xr.processes, dxml_core
>class_registrators = amx.registrator.register
3 changes: 0 additions & 3 deletions gamedata/configs/mod_script_dxml.ltx

This file was deleted.

13 changes: 13 additions & 0 deletions gamedata/scripts/amx/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Anomaly Modded eXes Entrypoint
-- Extends base X-Ray script functionality

--- Setup unlocalizer data model
require(_PACKAGE .. ".unlocalize")

--- Patch xr/lua compiler with modded exes extensions
require(_PACKAGE .. ".lua")

--- Export registrator from module to allow foo.bar.baz syntax in script.ltx
return {
registrator = require(_PACKAGE .. ".registrator")
}
20 changes: 20 additions & 0 deletions gamedata/scripts/amx/lua/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- AMX Lua Compiler
-- Patches unlocalization onto the base XR Lua compiler

local xr_lua = require("xr.lua")
local unlocalize = require(_PACKAGE .. ".unlocalize").unlocalize

function xr_lua.loadstring(src, namespace_name, script_name)
if namespace_name then
print("* [" .. _PACKAGE .. "] compiling " .. namespace_name)
end

return xr_lua.compile(
unlocalize(src, namespace_name),
namespace_name,
script_name
)
end

-- Run unit tests
require("amx.lua.tests")
110 changes: 110 additions & 0 deletions gamedata/scripts/amx/lua/tests.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
local run_tests = require("tests.util").run_tests
local unlocalize_with = require("amx.lua.unlocalize").unlocalize_with

local SRC = {
declare_function = [[
local function x(a, b, c) -- define a function
return a, b, c
end
]],

declare_var_single = [[
local a -- declare a single var
]],

define_var_single = [[
local a = 1 -- define a single var
]],
declare_var_multi = [[
local a, b, c -- declare multiple vars
]],
define_var_multi = [[
local a, b, c = 1, 2, 3 -- define multiple vars
]],
declare_var_single_sequence = [[
local a; local b; local c; -- declare a sequence of vars
]],
define_var_single_sequence = [[
local a = 1; local b = 2; local c = 3; define a sequence of vars
]],
}

local PASSES = {
declare_function = [[
function x(a, b, c) -- define a function
return a, b, c
end
]],

declare_var_single = [[
a = nil -- declare a single var
]],

define_var_single = [[
a = 1 -- define a single var
]],
declare_var_multi = [[
a, b, c = nil -- declare multiple vars
]],
define_var_multi = [[
a, b, c = 1, 2, 3 -- define multiple vars
]],
}

local FAILS = {
declare_var_single_sequence = [[
a = nil; b = nil; c = nil; -- declare a sequence of vars
]],
define_var_single_sequence = [[
a = 1; b = 2; c = 3; -- define a sequence of vars
]],
}

local unlocalizer = {"x", "a", "b", "c"}

local tests = {}

local ERR_MISMATCHED =
[[Mismatched unlocalizer output
src:
%s
unlocalized:
%s
target:
%s]]

for k,targ in pairs(PASSES) do
tests[k] = function()
local src = SRC[k]
local res = unlocalize_with(src, unlocalizer)

if res == targ then
return true
else
return false, string.format(ERR_MISMATCHED, v, res, targ)
end
end
end

local ERR_UNEXPECTED =
[[Unexpected unlocalizer output
src:
%s
unlocalized:
%s
target:
%s]]

for k,targ in pairs(FAILS) do
tests[k .. " (unsupported)"] = function()
local src = SRC[k]
local res = unlocalize_with(src, unlocalizer)
if res ~= targ then
return true
else
return false, string.format(ERR_UNEXPECTED, src, res, targ)
end
end
end

run_tests("amx/lua", tests)
121 changes: 121 additions & 0 deletions gamedata/scripts/amx/lua/unlocalize.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
-- Unlocalizer for xr/lua scripts

local DEBUG = false

local function string_trim(s, v)
if v == nil then
v = " \t\n\r\f\v"
end
local pattern = string.format("^[%s]*([^%s]*)[%s]*$", v, v, v)
return string.match(s, pattern)
end

local function contains(lst, a)
for _,b in ipairs(lst) do
if a == b then
return true
end
end

return false
end

local function unlocalize_with(src, unlocalizer)
local unlocal_performed = false

local temp = src
local tokens = {}
for line in string.gmatch(temp, "[^\n\r]+") do
table.insert(tokens, line)
end

for i,s in ipairs(tokens) do
s = string_trim(s, "\n\r")
tokens[i] = s

if s == "" then
goto next_token
end

-- local function x(a,b,c)
local _, _, c, d, e, f, g = string.match(
s,
[[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]]
)

if e then
if contains(unlocalizer, e) then
if DEBUG then
print("[unlocal_regex] found variable " .. e .. " to unlocal")
end
tokens[i] = c .. d .. e .. f .. g
unlocal_performed = true
end
goto next_token
end

-- local a = ...
-- local a
-- local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized)
-- local x; local y; - unsupported yet
local c = string.match(s, [[^local%s+(.*)]]) or ""
if #c > 0 then
local r = [[(.*)--.*]]
local nc = string.match(c, r)
if nc then
c = nc
end
end

local variables = string.match(c, [[^([^=]+)]])
local values = string.match(c, [[=([^=]+)$]])
if variables then
for v in string.gmatch(variables, "[^, ]+") do
v = string_trim(v)
if contains(unlocalizer, v) then
unlocal_performed = true
if DEBUG then
print("found variable", v, "to unlocal")
end
s = c
if not values then
local lhs, rhs = string.match(s, [[([^-]+)(%-%-[^-]*)]])
if lhs and rhs then
s = lhs .. "= nil " .. rhs
else
s = s .. "= nil"
end
end
tokens[i] = s
break
end
end
end

::next_token::
end

if unlocal_performed then
return table.concat(tokens, "\n")
end

return src
end

local function unlocalize(src, namespace_name)
if not namespace_name then
return src
end

local unlocalizer = require("amx.unlocalize").get(namespace_name)
if not unlocalizer then
return src
end

return unlocalize_with(src, unlocalizer)
end

return {
unlocalize_with = unlocalize_with,
unlocalize = unlocalize,
}
33 changes: 33 additions & 0 deletions gamedata/scripts/amx/registrator.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- AMX Class Registrator
-- Add custom classes for registration here

local function cs_register(factory, ...)
factory:register(...)
end

local function c_register(factory, ...)
if editor() == false then
factory:register(...)
end
end

local function s_register(factory, ...)
factory:register(...)
end

local function register(object_factory)
cs_register(
object_factory,
"CWeaponSSRS",
"se_item.se_weapon_magazined",
"_WP_SSRS",
"wpn_ssrs_s"
)
end

return {
cs_register = cs_register,
c_register = c_register,
s_register = s_register,
register = register,
}
68 changes: 68 additions & 0 deletions gamedata/scripts/amx/unlocalize.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
-- AMX Unlocalizer Storage
-- Loads unlocalizers from disk and exposes them via `get`

local unlocalizers = {}

local function update()
local fs = getFS()
local list = fs:file_list_open(
"$game_config$",
"unlocalizers\\",
bit_or(
FS.FS_ListFiles,
FS.FS_RootOnly
)
)

if not list then
return
end

local count = list:Size() or 0
if count == 0 then
return
end

for i=1,count do
local id = list:GetAt(i - 1)

if #id < 4 then
goto next_filename
end

if string.sub(id, #id - 3, #id) ~= ".ltx" then
goto next_filename
end

print("opening file:", id)

local config = ini_file("unlocalizers\\" .. id)
config:section_for_each(function(section)
local name = string.lower(section)
local count = config:line_count(name)
for j=0,count-1 do
local res, sec = config:r_line(name, j)
if not res then
goto next_line
end
unlocalizers[name] = unlocalizers[name] or {}
table.insert(unlocalizers[name], sec)

::next_line::
end
end)

::next_filename::
end
end

local function get(k)
return unlocalizers[k]
end

update()

return {
update = update,
get = get
}
Loading
Loading