-
Notifications
You must be signed in to change notification settings - Fork 1
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
Jokolay And Plugins / Modules / Scripting / Addons / Extensions #3
Comments
first experimentwe were successfully able to use rhai to script egui and embed it into our app using a little bit of unsafe, but rhai doesn't support providing if it is possible with rhai, it might be possible with mlua too. wasm might be possible in the near future, you can already do some awesome things. the benefit of wasm is that we can just use rust for plugins too, but the dev-setup becomes a little bit complex for rust devs to embed/run these wasm files, we will need to choose between wasmer / wamstime, both of which support cranelift backend for great speed. irrespective of the language we choose, egui is still too hard to make bindings for at the moment. two problems in particular.
for the ref mut types, we can just expose an explicit api like OTOH, if we instead just use raw rust cdylibs, and expose a egui bindings crate with a safety abi mentioning the invariants to be upheld, we might be able to get away with a easier (but slightly unsafe) plugin api. the advantage of performance and rust safety would be great. if these things are hard, we can instead go with a grpc route which is much easier to make plugins for, the hard part would be exposing the egui to them. An alternative is to instead just make a nodejs with napi-rs / neon bindings (or deno )to our jokolay rust library, that we can just add other plugins as js scripts. we can even use imgui-js as bindings instead of egui, which would make it a lot faster to develop for and push the performance sensitive stuff into rust. |
so, was successfully able to use mlua to bind egui. callbacks work and more importantly, by using the https://docs.rs/mlua/latest/mlua/struct.Lua.html#method.scope we can actually avoid unsafe as lua can take as for the egui api which takes in things like Egui MLualua is looking very attractive at the moment. we will need to check other things (like loading cdylibs), but if it works out, lua might be a really good option to start with. and we can also look into whether we can use rust as lua dylibs, that would allow us to extract a lot of functionality like markers into an external crate and draw using lua. after asking around in Design 1
return {
name = "myplugin",
description = "my cool plugin",
version = "1.0.0",
exports = {
... -- various "public" plugin methods
},
OnLoad = function(context) end,
OnUnload = function(context) end,
} the context is just jokolay related data that the plugin needs to initialize its state or destroy its state. the
The main hurdle at the moment with lua is the lack of multi-threading. Parallel Processing Methods
|
Just checked and all lua things work properly like require for lua modules as well as native lua modules (rust mlua or C). now, we just need to refine it a little bit and start finalizing the api. then, we can start exposing the required functionality for plugins as requested by plugin devs (fortunately, its not much work :D ) Parallel Processing Methods2 and 3 are both valid methods. I would prefer 3 as its much simpler. it seems native rust modules work well as long as we make sure that the mlua's runtime feature "lua54 or luajit or luau" etc.. match the ones used by jokolay when compiling. threads work too and we can simply use Channels for a lot of these off-threading operations for now. there's also coroutines which can be used to expose |
changed due date to April 06, 2022 |
marked this issue as related to #24 |
marked this issue as related to #31 |
wasm WASI is still too young. none of the proposals are standardized yet. https://github.com/WebAssembly/WASI/blob/main/Proposals.md wasm, though useful to enable plugins, cannot be used as a scripting language directly. so, even if we want to use wasm, we will need to decide on a language which has live wasm interpreter like https://github.com/RustPython/RustPython |
so, there's a bevy scripting api being developed (still in alpha stages) at https://github.com/makspll/bevy_mod_scripting . the design seems to be going for an event based trigger. this sort of design would seems to be popular. lua scripts would be "attached" to a parent object (an individual Lua VM), and it will register the events that it is interested in and the name of the function that it wants run on that event. when the event is emitted, the game will call the right function and pass it the event details. the function then does stuff in the background while the game continues running. if there's any other events emitted while the lua script is still executing, they will be queued to be dealt with after the script is done. so, each script is technically its own parallel thread, which communicates with the main game for input and outputs. the issue we are facing is that egui is immediate mode. it means the UI code is blocking / synchronous and must be run every frame. until now, we planned to run each plugin in a single VM. but if the vm is being used to respond to some events, we will need to wait until the current execution is halted, to run the UI function. bevy_mod_scripting uses a priority event mechanism, so we can keep UI events as top priority to skip any other pending events and use the VM immediately after the current execution finishes. but it still limits the plugins to workaround the 16 milliseconds limit (60 fps assumed) and make the plugin dev harder (non intuitive). but, if we could split a plugin into multiple scripts and use a dedicated vm each for each script, then UI script can have its own VM without having to deal with any delays due to other functions executing in response to events. Plugins would need some sort of way to share a data between different scripts (VMs). could be a simple Arc<RwLock> for json or a channel network between all scripts or a plugin declared number of Strings/Vec or even a simple HashMap<String, String>. what the data means should be interpreted by the plugin itself. |
lua doesn't expose UserData methods which take we could technically, make a wrapper struct EDIT on 9/7/22: taking a lua table is bad:
so, we are going with the |
we still need to figure out how to deal with plugins on web. is it possible to use rhai (or other scripting langauges) for plugins so that they will be able to run on web? or can we use wasmer / wasmtime embedded ? this requires a new issue which will take a while. either way, the performance will not be good enough compared to luajit. so, it makes sense to start with lua for now. if someone figures out a way to run lua on wasm, we can look at porting the lua plugin functionality to web then. one thing to remember is that we can use wasm as a simple we need to keep a persistent json which can be edited by sending events by the plugin. and we can build the Ui for the plugin using the Json. {
"window_one" : {
"container_type" : "Window", // we use this object to build a window
"title" : "My Window", // fields of this object will be the options to be used for the window
"id" : 3242, // some ID decided by plugin to be used for sending related events and uniquely identifying this object.
"open" : true, // whether the window is open. if user closes window, we set this to false and send the close event with id to the plugin
"ui_tree" : { // this is how we fill the window with Ui
"alpha" : {
"widget_type" : "DragValue", // type of widget to use for this object
"id" : 2345, // unique id by plugin
"value" : 0.5, // value to use for this widget. when changed, we send event to plugin. when plugin wants to, it can update this value by sending host an event.
} // alpha closed
}// ui_tree closed
} // window closed
} // root closed this can help with highly performant and safe wasm based plugins. or plugins in any language technically speaking including native rust. we just need the events / signals to be the only issue is that we will need to write a LOT of events and map them properly to the respective egui apis. we will be simulating a retained mode on top of immediate mode. |
created branch |
fortunately, although ideally, we should try to keep within the subset of Lua 5.1 so that we can target Luau + LuaJIT + Lua53 (rust) in future based on our needs. On web, we can only use Lua53 (rust). because C/Cpp bindings cannot work on wasm32-unknown-unknown abi. although C/Cpp bindings can be compiled using wasm32-unknown-emscripten, most of the rust projects don't support this target (winit, bevy etc..). On desktop, there are tradeoffs to be considered:
we need to focus on basic scripting support so as to enable the other parts of the Jokolay (like #24 ) to move forward. also need to create a basic template repo for the plugins development. there's a lot of different projects which transpile into Lua. better to start thinking about how to support them. Tier 1https://github.com/TypeScriptToLua/TypeScriptToLua // typescript Tier 2https://github.com/pigpigyyy/Yuescript // really clean just for completion, we have these too. |
LuaWe are waiting for a while for the lua port to rust. meanwhile, i tried to port Lua myself and it was a horrible experience.
The worst part is that i don't even like Lua. one indexing, lack of types, lack of proper arrays, lack of proper strings (utf-8), breaking changes leading to ecosystem split between Luau, Luajit, Lua reference impl. Life would be better with javascript (or python) which are much more mainstream. The whole reason to use Lua was V8One of the main reasons to chose Lua over JS was because we wanted to support plugins on web too. but if we sacrifice that, we can just use
WASM Revisitedone of the reasons we ignored wasm was the lack of component model (and will take atleast another year before it settles down). This makes integrating wasm / egui hard. struct JsonUI {
/// This contains all the shared data like strings used for labels or text edit buffers and so on.
data: Vec<JsonValue>,
ui_structure: Vec<ContainerType>,
}
enum ContainerType {
Window,
Area,
//...
}
struct Container {
kind: ContainerType,
name: u32, // index into the data field above for the actual string (JsonValue::String).
id_source: Option<u32>,
child_ui:
}
enum UI {
ChildUI(UI),
Label {
data: u32,
},
TextEdit {
data: u32,
},
//...
}
We can also just use rpc over channels or sockets to communicate with external plugins which can be written in any language (js/python/cpp etc..). There's json schema to help users find out any faults while they are still writing the raw json. Anyway, V8 would still be super cool because it allows scripts which want more performance / integration / customization. so, that should be our preference over wasm. |
Considering blish already supports Modules, This feature might be requested eventually.
Short Answer: NO. no support for any sort of addons. it is too big in scope and we will consider it after getting the basic overlay stuff working.
Long Answer: Maybe. scripting will help add features easily when they are lightweight. but
Lua obviously makes sense. its popular in gamedev / game modding communitites, has a lot of libraries, fast af. but lifetimes are a pain and rust doesn't have smooth integration with lua yet.
Javascript. nothing needs to be said. every programmer and their mother know this. will be heavily popular with plugin creators. but package management will probably be a little painful to integrate. again, no smooth integration with rust yet.
Python. not as fast as js or lua. but has an okayish integration with python. has lots of libraries and will be easy for newbies that want to make plugins.
Finally, the real candidate would be Web Assembly. one advantage is that we now have speed AND the integration would be smooth considering rust support is first class for wasm. But more importantly, we can write wasm modules in any language and have them compile to wasm, and pack it for rust. But exposing the plugin API in wasm might not be an easy task at all.
No matter which language we select, we will need to provide a sample template repo on github, a guide for setting up the dev environment for plugins, finally a package format for use with Jokolay. thinking in these terms, self contained wasm files should be ez to distribute/package. we could just refer to already established guides about wasm dev setup for different languages. especially kotlin/rust/js/lua which already work with wasm.
too many decisions and we didn't even consider what we want to expose in plugin api, or security, or what happens if a plugin is too slow, do we wait or do we just skip rendering it this frame? or what kinda refactoring would we need in Jokolay itself to keep it clean and finally if we want to cooperate and expose similar api like Blish/ or make our own.
The text was updated successfully, but these errors were encountered: