Replies: 5 comments 3 replies
-
Plugins that receive commands from the Mission Scripting EnvironmentAnother use-case for plugins, which I haven't touched on above, is to send commands from within the mission scripting environment to a plugin. Taking the SRS plugin as an example, this would allow to not only use the plugin by connecting to the gRPC server, but also via Lua calls inside the mission. I see two ways of achieving this: a) an untyped way, and a b) typed way. a) Untyped ApproachThis is rather straight forward. We expose an event that can hold arbitrary data: message PluginEvent {
string plugin = 1;
google.protobuf.Struct details = 3;
} Plugins than just listen to the regular event stream, and pick out their events and try to make sense out of the b) Typed ApproachFor plugins, we don't know the types during compile time of the server. So we'd have to make sense of the message types of a plugin during runtime. This can be achieved using self-describing messages. This is how it could look like:
|
Beta Was this translation helpful? Give feedback.
-
If it helps, here is an example plugin (using the EXE) method for a POC I've created: https://github.com/DCS-gRPC/rust-server/blob/poc-plugins/plugin-example/src/main.rs (it doesn't implement actually receiving commands from Lua yet; just starting a gRPC service and talking to the main DCS-gRPC server) |
Beta Was this translation helpful? Give feedback.
-
My vision was that DCS-gRPC would almost always run on multiplayer DCS servers and therefore would be running 24/7 or close to and DCS-gRPC clients to run separately as background services. Therefore I have always optimised for that scenario. Given that line of thinking (which could be wrong) I never thought "Having to install something separately" was a concern. I have also never considered having to start a separate client to be a problem either and can in fact be an advantage as you can update a DCS-gRPC clients without having to restart the DCS server. I make a lot of use of this feature when updating OverlordBot since pdating just the bot is very easy but when I have to update DCS-gRPC as well I have to wait until server restarts which can be a real pain because I need to replace the DLL, I assume plugins would have the same issue. The general bullet-point list of cons I see with plugins are:
However none of the above are deal-breakers and it could well be down to personal preference of the server owners but again I worry about added complexity "This thing is a separate client, this thing is a plugin, they are completely different in how they are installed and managed" My absolute main concern is that there does not become API fragmentation with multiple ways of communicating with DCS-gRPC clients / plugins from the DCS mission environment (or, indeed other clients) and especially that we avoid coupling between any of the parts (MSE, Client, Plugin). Currently we can communicate with a DCS-gRPC client from the MSE using events. The MissionCommand APIs are the first step along those lines and I am considering having a "generic" event that can be emitted from the MSE with scripts.
if (GRPC is not nil) then
local event = {
type = "scriptEvent", -- Defined in DCS-gRPC
publisher = "scriptName" -- All scriptEvents will have a publisher field which should be the name of the script. Used by clients to filter out events from scripts they don't care about. Also avoids possible conflicts in event names.
name = "someEventName" -- Unique event name. Allows the client to identify the exact event.
details = {
-- Add your event specific information here
}
}
GRPC.event(event)
end The advantage of events is that they are essentiall a PubSub system fan out to all clients (and plugins) and completely uncouple the processors of the events from the publisher. This could be a great advantage if you have, for example, one client that processes the event that affects the mission while another performs some sort of event logging to Discord or something like that. Having a specific Related to the above is my concern is that DCS-gRPC non-plugins essentially become second-class citizens which is something I dearly want to avoid. If we can architect plugins such that they process events just like a DCS-gRPC client does and do not require any specific calling convention then that would alleviate my main concern. I realise that this makes plugins that have synchronous APIs that return values to the MSE almost impossible to implement but my thought is that if there is so much custom logic coupling between a specific lua script and a plugin then they should just be bundled together and not use DCS-gRPC at all. |
Beta Was this translation helpful? Give feedback.
-
For reference, here are the main use-cases I have in the back of my mind when thinking about plugins: 1. DATISA service where a client can create new ATIS or other broadcast stations (weather, carrier, ...). Upon creation, the client receives an ID for the station that can be used for subsequent interactions with the station. Interactions like: pausing, stopping, changing the coalition, etc. The SRS-TTS used by DATIS would be another generic plugin, see next use-case. This needs:
What I want from it:
2. Generic SRS-TTS serviceA service where a client can send text, a frequency (and other optional parameters like name, coalition, ...) to. The text is then converted to speech (using either the windows TTS, AWS, GCloud or Azure) and broadcasted on the provided frequency on SRS (either once, or in a loop). This needs:
What I want from it:
3. Mission scenario specific SRS voice callsUsing the above SRS-TTS, I am thinking about integrating this into mission I have. E.g. to call out on SRS things like Enfield 1-1, you are cleared hot. This needs:
What I want from it:
|
Beta Was this translation helpful? Give feedback.
-
Use-cases and services. Now and for future. Very SRP (Single Responsibility focused) with individual services or plugins handling different tasks. Importantly something like 1. SRS STTA client (or plugin) that can be commanded to listen to a specific frequency on SRS, performs STT and emits an event that contains the transcribed text along with frequency information This needs:
2. DCS Voice STTA client (or plugin) that can be commanded to listen to a specific frequency on the built-in DCS Voice comms, performs STT and emits an event that contains the transcribed text along with frequency information This needs:
3. SRS TransmitterA client (or plugin) that transmits audio data on the specified SRS frequency via API call or event 4. DCS Voice comms TransmitterA client (or plugin) that transmits audio data on the specified DCS Voice comms frequency (or room) via API call or event 5. TTSA client (or plugin) that receives text and performs TTS. it does not transmit the data but publishes an event with the audio data, and potentially, frequency information, for transmitter services. This needs:
6. OverlordBot CoreReceives STT transcription events or F10 command events, performs the language recognition and then emits an TTS event so the other services can then do TTS and transmit. This allows me to remove all audio processing from OverlordBot and instead reuse the other services. 7. STT DisplayHave a service that will display the transcriptions from the STT services to a player that opts in to it via the F10 menu. This allows deaf players to read voice chat. I already have a user who is using some hacked-up code to do this in a less integrated manner. 8. SRS Server eventsI would like to modify the SRS server to push events into the DCS-gRPC event stream for things like users joining the server, their tuned radio frequencies etc. for things like Overlordbot, Event loggers and the like. Ciribob has already given his approval of this idea. 9. Event logger(s)Clients or plugins that listen to the Event stream and do stuff with the data. Post to Discord, upload metrics to a metrics server etc. VisionMy goal is to maximise code-reuse and remove coupling to enable maximum flexibilty and allowing people to swap out clients or plugins that can do the same thing but might suit their purposes better. It can also be exclusively event based which aids in removing the coupling but synchronous APis are available. There are a few major changes we would need to do;
I cannot think of a good way to have clients accept synchronous APIs so I think they are just going to have to be second-class citizens is we want to initiate things from inside the DCS SSE. However I still think that for the example given where we want to transmit a message from inside the SSE then we emit an event rather than call a named plugin. This is my not too organised initial set of thoughts. I think an online session in Discord and a whiteboard would be the best way to proceed from here to hammer things out. |
Beta Was this translation helpful? Give feedback.
-
I think it would be great if it'd be possible to extend the DCS-gRPC server with plugins (we can also call them extensions, but I'll just go with plugins for the rest of the post).
Example
Write your own little plugin, with its own proto definition, eg.:
Compile the plugin to either a DLL (or EXE, see implementation ideas at the end) and copy it into a dedicated plugin directory. Example:
Once in there, the server automatically picks it up on its next start. It then takes care of starting, stopping and restarting on errors. It also makes sure to forward all requests to
example.greeter.v0.GreeterService/Greet
, to the plugin. So your plugin would be available through the main gRPC endpoint of the gRPC server. Eg.:Motivation
I'd love for DATIS to use DCS-gRPC instead of its own RPC mechanism (DCS-gRPC actually re-uses parts of DATIS's RPC). I'd also like to expose the SRS integration from DATIS for other use-cases.
So I would:
If both would be standalone programs, everyone would have to start two additional programs besides DCS just to get ATIS stations. Something I personally highly dislike. I'd like for DATIS to stay as much plug'n'play as possible. Right now, you just have to copy files into your saved games DCS directory and that is it (not even
MissionScripting.lua
patching is necessary).The only solution to make it easier to use other tools based on DCS-gRPC I can think of is to make the server a plugin host. So that you can write plugins either as a dll (or exe if we prefer) and the server takes care of starting and stopping the plugins and also of proxying traffic to them.
I could then have a plugin for
srs.tts.v0.TtsService
. Just copy the dll/exe for this plugin into a dedicated plugin directory of the server, and after that I can send requests forsrs.tts.v0.TtsService
to the server, and they are automatically proxied to the plugin.Pros/Cons
I see the following pros and cons.
Pros:
Cons:
Implementation Ideas
DLL
The plugin could be a DLL that exposes certain functions. E.g.:
For the communication between the plugin and the DCS-gRPC server I see the following possible solutions: a) pass requests through FFI functions, too; or b) just let the plugin start its own gRPC server and communicate with the DCS-gRPC server through http2. I have a POC for both, so can confirm that they actually work and are not just theoretically.
a) Pass requests through FFI
This could be achieved by the following adjustment to the C interface:
The functions to pass requests around is basically:
fn(method: &str, request: &[u8]) -> Vec<u8>
. So the plugin basically has a function that it can call to pass requests to the main server, and it exposes a function that it receives requests with. This gets rid of the overhead of sending the requests through HTTP/2 as the main server and the plugin already life in the same process anyway. However, I wouldn't be surprised if this is hard to implement in certain languages (probably depends on how flexible a certain gRPC integration is). Something to keep in mind.b) Communicate through HTTP/2
The start method is adjusted as follows:
It receives a port the main DCS-gRPC listens on (
server_port
). This lets the plugin know where to send requests. It also receives a port where the plugin is expected to listen to itself (plugin_port
). This is where the requests meant for the plugin are proxied to.EXE
If we think that creating DLLs is too complicated. We can also consider EXE plugins instead. Plugins are then basically CLI applications. This is how they could work:
example.greeter.v0.GreeterService.exe
(though I am not sure if Windows is happy with so many.
in a file name)Even though I find the DLL approach subjectively more appealing, objectively, I see some serious advantages with the EXE approach:
Cons I see:
Conclusion
With such a system a distribution of DATIS could just be two plugins for DCS-gRPC that a user has to copy into a plugin directory and that is it. This simplicity of installation / using it could be summarized as the main motivation for me to think about the plugin system.
Let me know what you think. Also no need to go easy on the idea. If you don't like the idea of plugins feel free to simply state that (with the reason to think so ofc) 😊
Beta Was this translation helpful? Give feedback.
All reactions