-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lua via sol2 #2216
Lua via sol2 #2216
Conversation
I thought about using |
Tidy would be great, but I've given it some thought over the day, and I'm having trouble imagining how to make it work easily.
I'm not sure what else could be used as an alternative though. One option I've considered is to have a PR job that runs a single custom tidy plugin that's basically a tweaked version of DDA's tidy serialize check that instead of checking whether member is serialized would check whether members and methods are bound to Lua. It would still be half-manual, but at least CI would point exact place where manual intervention is required. Another job could scrape the C++ files on |
e377f34
to
2a2050a
Compare
6181f9d
to
6554eac
Compare
Okay, I've "investigated" clang codegen and discovered that thing is way over my head. It basically has the same biggest issue as implementing generator via tidy plugin: someone would need to be familiar with libtooling, or spend some considerable time learning it, to be able to write such tool and extend its functionality. This is not something I would be able to pull off on top of everything else I already do for BN, not without quitting my day job. |
The way I understand it, right now, it still requires manually binding C++ structs to Lua ones. Is that right? |
Yes. |
I can't get the smart remote to work. It always prints "no signal", regardless of whether I spawn it or find one spawned by mapgen. |
It's a bit of a hidden mechanic, but the house it's linked to must have a grid with charged battery. It'll say "no signal" if there's no charge or the character is too far away. |
Alright, got it working. |
Marked it as obsolete. |
Co-authored-by: Zhilkin Serg <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://luals.github.io/wiki/annotations/ by the way, in the future generating definition files would be great, as their syntax doesn't differ much from lua docs generator. here's a branch with incomplete POC definition file generator: https://github.com/scarf005/Cataclysm-BN/tree/lua-definitions |
Summary
SUMMARY: Infrastructure "Bring back Lua"
Purpose of change
Experimental PR to bring back Lua modding.
According to DDA issue tracker and numerous discussions on Discord:
I can't magically make point 5 disappear, but the rest of the issues should be solvable.
As such, this PR uses completely different approach from the one that was used in DDA before Lua got axed.
The old Lua integration used Lua stack directly and then relied on scripts to generate C++ bindings file from a predefined Lua list that mirrored C++ definitions.
This version relies on a Lua C++ wrapper called sol2 to hide Lua stack management from the developer, so creating new bindings can be done by adding a few lines of human-readable C++. It still has to be done manually, but at least sol2 is able to automatically figure out types of objects being bound, so it's not much different from our de-/serialization code.
I'm not planning on re-implementing entire Lua functionality right off the bat, but this PR (if it goes in) should give a solid foundation to build on.
Describe the solution
The idea is to make Lua integration:
As such, the current solution is:
src
namedlua
and put Lua 5.3.6 source code there. Lua is extremely fast to compile (it takes less than 10 seconds to compile on my machine when using single thread), so having it be built alongside other game source files and then be linked in one step mitigates a whole slew of issues (Lua version availability between platforms, Lua version mismatch between build machine and host machine, system Lua installation weirdness on some platforms)src
namedsol
and put sol2 v3.3.0 single-header source code there. Sol2 is a mature, feature-rich and performant C++ Lua wrapper that should cover many of our potential needs.core
non-mod (that's been causing trouble before btw, see Integrate basic.json into data/json #2106 ), and also of per-world mods (it's an obscure and almost unused mechanic with no access from UI).Data loading
part indoc/LUA_SUPPORT.md
for details.log_
output from Lua functionsluna
. The purpose of this wrapper is to provide types registered withsol2
with additional runtime information such as type name as registered in Lua (sol
only keeps track of type name as it's specified in C++, in cases where there is mismatch it becomes impossible to know Lua type from userdata) for (de-)serialization of Lua tables with userdata. It also emits additional information on members registered for the usertype, such as field names and types, method names and their arguments and return types.--lua-doc
runtime switch that makes the game generate documentation for registered types based on information collected byluna
. This way, we can have some rudimentary automatic docs generation for bindings that does not rely on some external tools.Smart House Remotes
mod that uses Lua to open/close curtains and garage doors in a houseSaveLoad Lua Test
mod that uses hooks to preserve its Lua state throughout save/load cycleDescribe alternatives you've considered
Main alternatives and their disadvantages I listed in introduction.
Alternatives regarding current solution:
Use custom
clang-tidy
plugin to generate bindings.Unfortunately I don't know where to even begin writing one. I have little experience with
clang-tidy
, and the current tidy-with-plugins installation workflow could be somewhat hard for new contributors, see comment.Upd: turns out clang's syntax parsing can be used via a standalone library, so it should be possible to create a standalone bindings generator and just have the developers/contributors download precompiled releases.
Upd2: same as with
clang-tidy
, it requires a lot of knowledge regarding clang codegenUse some other Lua bindings library.
I remember using LuaBridge a few years back, and sol2 is definitely nicer to work with. Maybe they've improved over the years, I didn't check. Also after some googling, sol2 seems to be the go to solution for C++ <-> Lua bindings in current year due to its overall performance, flexibility and C++iness.
Testing
Added PR workflows to build and test linux g++ and macos clang++ builds.
The tests include basic stuff like creating lua state, loading Lua libraries, bindings some definitions and running code.
lua_class_members
- Bindspoint
class and its members, various constructors and methods (including math operators), then runs a Lua script that uses these bindingslua_global_functions
- Binds a couple global functions and creature class family, then runs a Lua script that calls the global function and verifies that boundget_character_name
accepts classavatar
which is derived fromCharacter
from Lua side while original C++ function expectsCharacter
.lua_called_from_cpp
- Runs a Lua script that creates and stores a function, then executes that function from C++ side and validates the results.lua_runtime_error
- Causes runtime error on Lua side and checks that we receive appropriate exception on C++ side.lua_called_error_on_lua_side
- Calls Lua'serror()
on Lua side and checks that we receive appropriate exception on C++ side.lua_called_error_on_cpp_side
- Calls Lua'serror()
on C++ side and checks that we receive appropriate exception on C++ side.lua_called_cpp_func_throws
- Throws exception from C++ function called by Lua and checks that we receive appropriate exception on C++ side.lua_table_serde*
- Checks correctness of saving & loading a Lua table to/from JSONid_conversion*
- Checks id conversion functions (raw pointer <-> string_id <-> int_id)TODO list (this PR)
Investigate possibility of writing automated bindings generator using- Way to complex for me to tackle. Also, not sure if this is viable given how diverse the codebase is; it's way easier to write the bindings semi-manually.libclang
Gather feedbackFeedback would have to be gathered after mergingmay just end up making wrappers to gettext calls,xgettext
supports Luaextract_json_strings.py
can now parse Lua source and extract strings from relevant*gettext
calls)Look for a way to abstract away differences between- It seemsint_id<T>
vsstring_id<T>
vsconst T*
on Lua sidesol
does not allow customizing howconst T*
is treated for certain types. Added manual conversion functions.Workaround the sol2 issue where binding- It would require either removing comparison operators fromstring_id<T>
requiresT
to implement operators<
and==
string_id<T>
andint_id<T>
, removingoperator*
andoperator->
from them or patchingsol2
. I don't like all of these variants, meanwhile implementing comparison operators for the types is way simpler and doesn't kill ergonomics. Added a macro to make implementing them easier, it will have to do for now.catalua_bindings.cpp
as it will get progressively slow to compileand maybe game and mod versioning, to avoid potential mismatches hereEnded up adding Lua API versioning in form of single integer, will have to see how it works out.TODO list (long-term)
luna
wrapper.