Lua scripting in OpenMW

Everything about development and the OpenMW source code.
User avatar
akortunov
Posts: 899
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation

Re: Lua scripting in OpenMW

Post by akortunov »

IMO, separate thread here is a premature optimization.
We do not know how much widely scripting system will be used, how many time per frame it will require and which thread will be a bottleneck.
For example, earlier we usually had a main thread as a bottleneck (Cull and Physics), but now we can tweak actors processing range, have active grid batching, async physics, instanced groundcover, etc, so there is more cases when a Draw thread becomes a bottleneck, not the main one. There will be more such situations if things such as hardware skinning will be a thing.

Also most of our game mechanics actually is not a threadsafe, so we will need to add a lot of locks, which may be an additional source of freezes or microstuttering.
ptmikheev
Posts: 69
Joined: 01 Jun 2020, 21:05
Gitlab profile: https://gitlab.com/ptmikheev

Re: Lua scripting in OpenMW

Post by ptmikheev »

akortunov wrote: 10 Apr 2021, 15:00 IMO, separate thread here is a premature optimization.
It is not. If it is not inherent in architecture from the beginning, it will never be possible.
With such a logic you can also say "it is too early to think about the multiplayer" and block the possibility of having it in the future by an incompatible API.
akortunov wrote: 10 Apr 2021, 15:00 For example, earlier we usually had a main thread as a bottleneck (Cull and Physics), but now we can tweak actors processing range, have active grid batching, async physics, instanced groundcover, etc, so there is more cases when a Draw thread becomes a bottleneck, not the main one.
If many people worked hard to solve performance issues, it doesn't mean that now it is fine to choose a non-scalable solution.
User avatar
akortunov
Posts: 899
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation

Re: Lua scripting in OpenMW

Post by akortunov »

ptmikheev wrote: 12 Apr 2021, 23:51 It is not. If it is not inherent in architecture from the beginning, it will never be possible.
There is not enough evidence to tell that there is a real need to make it "inherent". There is only a vague term "heavy scripts" yet.
With async physics main thread handles such "hardcoded" things:
1. Input
2. UI
3. Game mechanics
4. AI
5. Scene graph tweaking
Lua scripts are supposed mostly to do same things, but via Lua code rather than C++ one, and a separate scripting thread may lead to differences in behaviour betwen the same logic written on Lua and C++ due to different timings.
If scene graph tweaking (mostly Cull) takes about 25% of frame time, you will have at least 60% of frame time to handle scripts (because other parts usually do not take a lot of time). With separate scripting thread you may get about 1.5x of that time, but I'd not call that "scalable" - you still have a hard cap to maintain required FPS.

It should be possible to run a whole server on the separate thread at the cost of breaking some legacy content which is not aware of such changes (server scripts may work in the server thread with this approach), but it is a separate question. If some advanced users desperately need to run huge calculations, probably it is worth to introduce a some kind of WorkItem pattern which we already use to run background tasks on threads from thread pool.
ptmikheev
Posts: 69
Joined: 01 Jun 2020, 21:05
Gitlab profile: https://gitlab.com/ptmikheev

Re: Lua scripting in OpenMW

Post by ptmikheev »

akortunov wrote: 13 Apr 2021, 07:24 There is not enough evidence to tell that there is a real need to make it "inherent". There is only a vague term "heavy scripts" yet.
With async physics main thread handles such "hardcoded" things:
1. Input
2. UI
3. Game mechanics
4. AI
5. Scene graph tweaking
Lua scripts are supposed mostly to do same things, but via Lua code rather than C++ one, and a separate scripting thread may lead to differences in behaviour betwen the same logic written on Lua and C++ due to different timings.
The idea of Lua scripting is not to do the same as C++, but to do much more that was possible before.
For example I would like to see an advanced AI. Not just "like in later games", but really advanced. Modern RPG are too focused on graphics and animation and don't really care about AI. But maybe it is possible to create something completely new and amazing in this area. And it definitely can require heavy scripts.
akortunov wrote: 13 Apr 2021, 07:24 If scene graph tweaking (mostly Cull) takes about 25% of frame time, you will have at least 60% of frame time to handle scripts (because other parts usually do not take a lot of time).
It is true only on specific hardware with specific settings. With other settings or maybe just in another location the Cull traversal easily can take 75% of the frame time.

It is true that placing scripting to a separate thread adds some limitations to the API. But these are actually the same limitations that are necessary for multiplayer. If I design it differently, later it would be much harder to use it with multiplayer.
Chris
Posts: 1625
Joined: 04 Sep 2011, 08:33

Re: Lua scripting in OpenMW

Post by Chris »

ptmikheev wrote: 17 Apr 2021, 21:16 The idea of Lua scripting is not to do the same as C++, but to do much more that was possible before.
For example I would like to see an advanced AI. Not just "like in later games", but really advanced. Modern RPG are too focused on graphics and animation and don't really care about AI. But maybe it is possible to create something completely new and amazing in this area. And it definitely can require heavy scripts.
To do that properly, it couldn't be done via scripts since AI isn't script-driven. Unless we move all AI processing to scripts, in which case you'd replace/override the AI script functions.

It's also possible to have two separate scripting contexts. One which is frame-dependent (so if you need frame accuracy for some functionality), and one which is asynchronous (if you can work in the background). Perhaps scripts could even launch their own threads/asynchronous methods, though that may be a bit too much of a security risk (in that it could inadvertently suck up resources and bring the system down).

With Papyrus in Skyrim, script processing could actually be timesliced. Scripts would run for a certain number of instructions or within a time limit, then stop for the engine to handle the frame, then on the next frame it would resume where it left off. It was synchronous, but created pseudo-asynchronous processing as you could do complex calculations in scripts and not worry about rendering or core engine logic getting stalled since you'd be scheduled away and back as needed.
ptmikheev
Posts: 69
Joined: 01 Jun 2020, 21:05
Gitlab profile: https://gitlab.com/ptmikheev

Re: Lua scripting in OpenMW

Post by ptmikheev »

Chris wrote: 18 Apr 2021, 01:32 To do that properly, it couldn't be done via scripts since AI isn't script-driven. Unless we move all AI processing to scripts, in which case you'd replace/override the AI script functions.
Yes, there is a plan to make AI script-driven. But of course it will take a lot time and effort.
Chris wrote: 18 Apr 2021, 01:32 It's also possible to have two separate scripting contexts. One which is frame-dependent (so if you need frame accuracy for some functionality), and one which is asynchronous (if you can work in the background). Perhaps scripts could even launch their own threads/asynchronous methods, though that may be a bit too much of a security risk (in that it could inadvertently suck up resources and bring the system down).

With Papyrus in Skyrim, script processing could actually be timesliced. Scripts would run for a certain number of instructions or within a time limit, then stop for the engine to handle the frame, then on the next frame it would resume where it left off. It was synchronous, but created pseudo-asynchronous processing as you could do complex calculations in scripts and not worry about rendering or core engine logic getting stalled since you'd be scheduled away and back as needed.
There is a big problem with time slicing. If the game is saved in the middle of evaluating a lua function, we can not save the state of the function (we don't have access to the lua runtime internals). And if we just interrupt it, the game world can be left in an inconsistent state. We could use some workarounds (e.g. forbid saving the game in some cases), but they adds too lot of complications (especially with a connection to multiplayer) and I would like to avoid it.
So it will not work the same as Papyrus in Skyrim. But we will be able to use Lua coroutines in some form.

Launching additional worker threads from Lua may be possible, but only in distant future.
ptmikheev
Posts: 69
Joined: 01 Jun 2020, 21:05
Gitlab profile: https://gitlab.com/ptmikheev

Re: Lua scripting in OpenMW

Post by ptmikheev »

Lua MR is ready. I hope it will be merged soon (but it will not be included to the 0.47.0 release).

Builds for testing: https://gitlab.com/ptmikheev/openmw/-/p ... /295138173
Documentation: https://openmw-lua-work-in-progress.readthedocs.io
Quick start: how to run a script
Example mods: https://gitlab.com/ptmikheev/openmw-lua-examples

Note that the initial OpenMW Lua API is very limited.
The next step will be a framework for integration tests. And only after covering the API with tests it will be possible to extend it further.
User avatar
psi29a
Posts: 5355
Joined: 29 Sep 2011, 10:13
Location: Belgium
Gitlab profile: https://gitlab.com/psi29a/
Contact:

Re: Lua scripting in OpenMW

Post by psi29a »

Can you explain more about what to expect and NOT expect?

I know there was a healthy discussion about async behaviour, co-routines and threading for example.

How are currently handled when it comes to saving?

Changed save-game format?
User avatar
AnyOldName3
Posts: 2666
Joined: 26 Nov 2015, 03:25

Re: Lua scripting in OpenMW

Post by AnyOldName3 »

So it will not work the same as Papyrus in Skyrim. But we will be able to use Lua coroutines in some form.
I'm aware our threading model is pretty different to that of Papyrus, but we're eventually going to need to support transpiling papyrus to OpenMW Lua (or write a Papyrus/Papyrus bytecode interpreter in OpenMW Lua). Is that something that'll be possible without a big redesign? If not, it's better that we change things now before anyone's relying on them rather than in five/ten/fifty years when we get around to supporting Skyrim.
ptmikheev
Posts: 69
Joined: 01 Jun 2020, 21:05
Gitlab profile: https://gitlab.com/ptmikheev

Re: Lua scripting in OpenMW

Post by ptmikheev »

AnyOldName3 wrote: 01 May 2021, 18:10
So it will not work the same as Papyrus in Skyrim. But we will be able to use Lua coroutines in some form.
I'm aware our threading model is pretty different to that of Papyrus, but we're eventually going to need to support transpiling papyrus to OpenMW Lua (or write a Papyrus/Papyrus bytecode interpreter in OpenMW Lua). Is that something that'll be possible without a big redesign? If not, it's better that we change things now before anyone's relying on them rather than in five/ten/fifty years when we get around to supporting Skyrim.
Most limitations in OpenMW Lua come from the idea that it should work well with multiplayer and that it should be possible to process physics and most of mechanics on clients. Threading model here is secondary. Supporting Papyrus will be tricky, but, I hope, still possible. However I suspect that there will be some minor differences in behaviour (like delays after some commands), but that is the price of supporting multiplayer. I doubt that it can be redesigned to precisely mimic Skyrim without losing compatibility with multiplayer.
psi29a wrote: 01 May 2021, 13:35 Can you explain more about what to expect and NOT expect?

I know there was a healthy discussion about async behaviour, co-routines and threading for example.

How are currently handled when it comes to saving?

Changed save-game format?
Coroutines and async behaviour
It is important to understand that coroutines are not multithreading. It is a way to suspend a function (e.g. when it requests some async operation) and then (when the operation is finished) instead of using a callback just resume the same function from the same place. It's all happening in one thread.

Saving
With Lua it is not possible to save and restore the state of a script automatically. Each script is responsible for its saved state and should explicitly control it using handlers `onSave` and `onLoad`. It is already implemented this way and I don't see any alternatives. Saving process happens between frames, so it can not happen in the middle of a function, unless the function is a suspended coroutine. With coroutines it can be hard to write a script that properly saves its state, so modders should use them carefully and Lua API shouldn't force modders to use them if it can be avoided.

Save format
Save format is changed. As usual, there is one-way compatibility. Old saves can be opened with a new version, but not vice versa.

Threads
Lua runtime is always single-threaded. Multiple threads are possible only if some scripts work in one instance of the runtime, and some in a completely separate runtime. For example, local scripts and global scripts can theoretically live in separate threads. But all the global scripts should work in one thread because otherwise they will not be able to interact with each other.
Maybe in the future we can provide some API to run heavy calculations in a separate worker thread, but only in quite a distant future and it is not related to coroutines in any way.

MWSE
OpenMW Lua will not be compatible with MWSE. At least because it would conflict with being compatible with multiplayer. To make an MWSE mod working in OpenMW all scripts have to be rewritten. Automatic conversion with some tool also will not be possible.

TES3MP
Despite mentioning "multiplayer" a lot, OpenMW Lua is not compatible with the scripting system that is currently used in TES3MP. Don't expect TES3MP to immediately migrate to OpenMW Lua, it requires plenty of work.

Overriding Morrowind mechanics
Overriding original mechanics in Lua will become possible only after dehardcoding them. It is planned, but not in the nearest future.

What to expect in the nearest months
I think that at first we should focus on adding features, that are not possible via MWScript. UI, camera control, custom AI.
Post Reply