#[cfg(feature = "server")]
use crate::input_message::BEIBuffer;
#[cfg(any(feature = "client", feature = "server"))]
use crate::input_message::BEIStateSequence;
#[cfg(any(feature = "client", feature = "server"))]
use crate::setup::InputRegistryPlugin;
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
#[cfg(any(feature = "client", feature = "server"))]
use bevy_ecs::schedule::IntoScheduleConfigs;
#[cfg(all(feature = "client", feature = "server"))]
use bevy_ecs::schedule::common_conditions::not;
#[cfg(any(feature = "client", feature = "server"))]
use bevy_enhanced_input::EnhancedInputSystems;
#[cfg(feature = "client")]
use bevy_enhanced_input::action::TriggerState;
use bevy_enhanced_input::context::InputContextAppExt;
use bevy_enhanced_input::prelude::ActionOf;
use bevy_reflect::TypePath;
use bevy_replicon::prelude::AppRuleExt;
use bevy_replicon::shared::replication::registry::receive_fns::MutWrite;
use core::fmt::Debug;
#[cfg(feature = "client")]
use lightyear_core::prelude::is_in_rollback;
#[cfg(feature = "client")]
use lightyear_inputs::client::InputSystems;
use lightyear_inputs::config::InputConfig;
use serde::Serialize;
use serde::de::DeserializeOwned;
pub struct InputPlugin<C> {
pub config: InputConfig<C>,
}
impl<C> Default for InputPlugin<C> {
fn default() -> Self {
Self {
config: Default::default(),
}
}
}
impl<C> InputPlugin<C> {
pub fn new(config: InputConfig<C>) -> Self {
Self { config }
}
}
impl<
C: Component<Mutability: MutWrite<C>>
+ PartialEq
+ Clone
+ Debug
+ Serialize
+ DeserializeOwned
+ TypePath,
> Plugin for InputPlugin<C>
{
fn build(&self, app: &mut App) {
#[cfg(feature = "server")]
app.register_required_components::<ActionOf<C>, BEIBuffer<C>>();
if !app.is_plugin_added::<bevy_enhanced_input::EnhancedInputPlugin>() {
app.add_plugins(bevy_enhanced_input::EnhancedInputPlugin);
}
app.add_input_context_to::<FixedPreUpdate, C>();
app.replicate::<C>();
app.replicate_once::<ActionOf<C>>();
#[cfg(feature = "client")]
{
use crate::disable::{disable_context_actions, enable_context_actions};
use crate::marker::{
add_action_markers_from_context, add_input_marker_from_binding,
propagate_input_marker,
};
app.register_required_components::<ActionOf<C>, TriggerState>();
app.add_observer(propagate_input_marker::<C>);
app.add_observer(add_action_markers_from_context::<C>);
app.add_observer(add_input_marker_from_binding::<C>);
app.add_observer(disable_context_actions::<C>);
app.add_observer(enable_context_actions::<C>);
if self.config.rebroadcast_inputs {
app.add_observer(InputRegistryPlugin::on_rebroadcast_action_received::<C>);
app.add_observer(InputRegistryPlugin::on_rebroadcast_context_received::<C>);
app.add_observer(InputRegistryPlugin::on_rebroadcast_context_controlled::<C>);
#[cfg(feature = "server")]
app.add_observer(InputRegistryPlugin::add_action_of_host_server_rebroadcast::<C>);
}
#[cfg(feature = "server")]
{
app.add_observer(InputRegistryPlugin::mock_non_host_owned_action::<C>);
app.add_observer(
InputRegistryPlugin::mock_non_host_owned_actions_on_controlled_by::<C>,
);
}
app.add_plugins(lightyear_inputs::client::ClientInputPlugin::<
BEIStateSequence<C>,
>::new(self.config));
app.configure_sets(
FixedPreUpdate,
(
EnhancedInputSystems::Update.run_if(not(is_in_rollback)),
InputSystems::BufferClientInputs,
EnhancedInputSystems::Apply,
)
.chain(),
);
}
#[cfg(feature = "server")]
{
if self.config.rebroadcast_inputs {
app.add_observer(InputRegistryPlugin::on_action_of_replicated::<C>);
}
app.add_plugins(
lightyear_inputs::server::ServerInputPlugin::<BEIStateSequence<C>> {
rebroadcast_inputs: self.config.rebroadcast_inputs,
marker: core::marker::PhantomData,
},
);
#[cfg(not(feature = "client"))]
{
use bevy_app::PreUpdate;
app.configure_sets(PreUpdate, EnhancedInputSystems::Prepare.run_if(never));
app.configure_sets(FixedPreUpdate, EnhancedInputSystems::Update.run_if(never));
}
#[cfg(feature = "client")]
{
app.configure_sets(
FixedPreUpdate,
EnhancedInputSystems::Update
.run_if(not(lightyear_connection::identity::is_headless_server)),
);
}
app.configure_sets(
FixedPreUpdate,
lightyear_inputs::server::InputSystems::UpdateActionState
.before(EnhancedInputSystems::Apply),
);
}
}
}
fn never() -> bool {
false
}