From 099a180a3359331be5e7f7cf5edf6e42ab5e0b16 Mon Sep 17 00:00:00 2001 From: ccgauche Date: Sun, 28 Feb 2021 22:39:53 +0100 Subject: [PATCH] Update lib.rs --- plugin/api/src/lib.rs | 128 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/plugin/api/src/lib.rs b/plugin/api/src/lib.rs index 043ac0ea0f..0ce193cac7 100644 --- a/plugin/api/src/lib.rs +++ b/plugin/api/src/lib.rs @@ -8,7 +8,27 @@ pub use common::{resources::GameMode, uid::Uid}; mod errors; pub use errors::*; +pub use event::*; +/// The [`Action`] enum represents a push modification that will be made in the +/// ECS in the next tick Note that all actions when sent are async and will not +/// be executed in order like [`Retrieve`] that are sync. All actions sent will +/// be executed in the send order in the ticking before the rest of the logic +/// applies. +/// +/// # Usage: +/// ```rust +/// # use veloren_plugin_api::*; +/// # pub fn emit_action(action: Action) { emit_actions(vec![action]) } +/// # pub fn emit_actions(_actions: Vec) {} +/// // Packing actions is better than sending multiple ones at the same time! +/// emit_actions(vec![ +/// Action::KillEntity(Uid(1)), +/// Action::PlayerSendMessage(Uid(0), "This is a test message".to_owned()), +/// ]); +/// // You can also use this to only send one action +/// emit_action(Action::KillEntity(Uid(1))); +/// ``` #[derive(Deserialize, Serialize, Debug)] pub enum Action { ServerClose, @@ -17,26 +37,98 @@ pub enum Action { KillEntity(Uid), } +/// The [`Retrieve`] enum represents read of the ECS is sync and blocking. +/// This enum shouldn't be used by itself. You should always prefer `get` +/// methods on Plugin API Types For instance, prefer this method: +/// ```rust +/// # use veloren_plugin_api::*; +/// # let entityid = Player {id: Uid(0)}; +/// # trait G { fn get_entity_health(&self) -> Option; } +/// # impl G for Player {fn get_entity_health(&self) -> Option {Some(1)}} +/// let life = entityid.get_entity_health().unwrap(); +/// // Do something with life +/// ``` +/// Over this one: +/// ```rust +/// # use veloren_plugin_api::*; +/// # let entityid = Uid(0); +/// # fn retrieve_action(r: &Retrieve) -> Result { Ok(RetrieveResult::GetEntityHealth(Health::empty()))} +/// let life = if let RetrieveResult::GetEntityHealth(e) = +/// retrieve_action(&Retrieve::GetEntityHealth(entityid)).unwrap() +/// { +/// e +/// } else { +/// unreachable!() +/// }; +/// // Do something with life +/// ``` #[derive(Deserialize, Serialize, Debug)] pub enum Retrieve { GetPlayerName(Uid), GetEntityHealth(Uid), } +/// The [`RetrieveResult`] struct is generated while using the `retrieve_action` +/// function +/// +/// You should always prefer using `get` methods available in Plugin API types. +/// +/// Example: +/// ```rust +/// # use veloren_plugin_api::*; +/// # let entityid = Uid(0); +/// # fn retrieve_action(r: &Retrieve) -> Result { Ok(RetrieveResult::GetEntityHealth(Health::empty()))} +/// let life = if let RetrieveResult::GetEntityHealth(e) = +/// retrieve_action(&Retrieve::GetEntityHealth(entityid)).unwrap() +/// { +/// e +/// } else { +/// unreachable!() +/// }; +/// // Do something with life +/// ``` #[derive(Serialize, Deserialize, Debug)] pub enum RetrieveResult { GetPlayerName(String), GetEntityHealth(Health), } +/// This trait is implement by all events and ensure type safety of FFI. pub trait Event: Serialize + DeserializeOwned + Send + Sync { type Response: Serialize + DeserializeOwned + Send + Sync; } +/// This module contains all events from the api pub mod event { use super::*; use serde::{Deserialize, Serialize}; + /// This event is called when a chat command is run. + /// Your event should be named `on_command_` + /// + /// If you return an Error the displayed message will be the error message + /// in red You can return a Vec that will be print to player + /// chat as info + /// + /// # Example + /// ```ignore + /// #[event_handler] + /// pub fn on_command_testplugin(command: ChatCommandEvent) -> Result, String> { + /// Ok(vec![format!( + /// "Player of id {:?} named {} with {:?} sended command with args {:?}", + /// command.player.id, + /// command + /// .player + /// .get_player_name() + /// .expect("Can't get player name"), + /// command + /// .player + /// .get_entity_health() + /// .expect("Can't get player health"), + /// command.command_args + /// )]) + /// } + /// ``` #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct ChatCommandEvent { pub command: String, @@ -48,11 +140,25 @@ pub mod event { type Response = Result, String>; } + /// This struct represent a player #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct Player { pub id: Uid, } + /// This event is called when a player connects. + /// Your event should be named `on_join` + /// + /// You can either return `CloseConnection` or `None` + /// If `CloseConnection` is returned the player will be kicked + /// + /// # Example + /// ```ignore + /// #[event_handler] + /// pub fn on_join(command: PlayerJoinEvent) -> PlayerJoinResult { + /// PlayerJoinResult::CloseConnection + /// } + /// ``` #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct PlayerJoinEvent { pub player_name: String, @@ -63,6 +169,11 @@ pub mod event { type Response = PlayerJoinResult; } + /// This is the return type of an `on_join` event. See [`PlayerJoinEvent`] + /// + /// Variants: + /// - `CloseConnection` will kick the player. + /// - `None` will let the player join the server. #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub enum PlayerJoinResult { CloseConnection, @@ -73,6 +184,20 @@ pub mod event { fn default() -> Self { Self::None } } + /// This event is called when the plugin is loaded + /// Your event should be named `on_load` + /// + /// # Example + /// ```ignore + /// #[event_handler] + /// pub fn on_load(load: PluginLoadEvent) { + /// match load.game_mode { + /// GameMode::Server => emit_action(Action::Print("Hello, server!".to_owned())), + /// GameMode::Client => emit_action(Action::Print("Hello, client!".to_owned())), + /// GameMode::Singleplayer => emit_action(Action::Print("Hello, singleplayer!".to_owned())), + /// } + /// } + /// ``` #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct PluginLoadEvent { pub game_mode: GameMode, @@ -82,9 +207,6 @@ pub mod event { type Response = (); } - // #[derive(Serialize, Deserialize, Debug)] - // pub struct EmptyResult; - // impl Default for PlayerJoinResult { // fn default() -> Self { // Self::None