Plugins

One of the most important features behind the engine is the ability to develop a plugin. Plugins have the ability to talk to other plugins, and the host. Plugins implement game logic.

Plugins are split into Client and Server sides. This acheived in code like so:

#![allow(unused)]
fn main() {
// Declare structures containing state
// Note that the names do not matter, but are informative
// make_app_state!() only cares about the order of it's arguments
struct ServerState;
struct ClientState;

// Expose the these structures to the engine. Order matters!
// This is analogous to main() in a regular Rust program.
make_app_state!(ClientState, ServerState);

// Implement constructors
impl UserState for ClientState {
    fn new(io: &mut EngineIo, sched: &mut EngineSchedule<Self>) -> Self {
        Self
    }
}

impl UserState for ServerState {
    fn new(io: &mut EngineIo, sched: &mut EngineSchedule<Self>) -> Self {
        Self
    }
}
}

While both the server and client states are declared in the same plugin, only one will be picked at runtime. The client-side code runs independently on each client, and the server-side code runs in a single instance on the server.

ChatImproVR plugins are written in WebAssembly. See the next section for details!

Tips and tricks

If you are implementing a plugin which will behave the same on the client and server, you may use a type alias to avoid duplicating code:

#![allow(unused)]
fn main() {
// Implement your plugin state as usual
struct PluginState;
impl UserState for PluginState {
    // ...
}

// Use a type alias to create an alternate name for the state in order to pass both to make_app_state!() without causing an error
type ServerState = PluginState;
make_app_state!(PluginState, ServerState);

//make_app_state!(PluginState, PluginState); // This would cause an error!
}