use crate::setup::NetworkActionOf;
use bevy_ecs::prelude::*;
use bevy_ecs::relationship::Relationship;
use bevy_enhanced_input::prelude::*;
use bevy_replicon::client::confirm_history::ConfirmHistory;
use lightyear_connection::client::Client;
use lightyear_replication::prelude::{Controlled, ControlledBy, HasAuthority};
#[derive(Component)]
pub struct InputMarker<C> {
marker: core::marker::PhantomData<C>,
}
impl<C> Default for InputMarker<C> {
fn default() -> Self {
Self {
marker: core::marker::PhantomData,
}
}
}
fn action_targets_local_client<C: Component>(
action_of: &ActionOf<C>,
contexts: &Query<Option<&ControlledBy>, With<Controlled>>,
clients: &Query<(), With<Client>>,
) -> bool {
match contexts.get(action_of.get()) {
Ok(Some(controlled_by)) => clients.get(controlled_by.owner).is_ok(),
Ok(None) => true,
Err(_) => false,
}
}
pub(crate) fn propagate_input_marker<C: Component>(
trigger: On<Add, InputMarker<C>>,
actions: Query<&Actions<C>>,
confirm: Query<(), With<ConfirmHistory>>,
mut commands: Commands,
) {
if let Ok(actions) = actions.get(trigger.entity) {
actions.iter().for_each(|action| {
if confirm.get(action).is_ok() {
return;
}
commands.entity(action).insert(InputMarker::<C>::default());
});
}
}
pub(crate) fn add_input_marker_from_parent<C: Component>(
trigger: On<Add, ActionOf<C>>,
action_of: Query<&ActionOf<C>, Without<ConfirmHistory>>,
context: Query<(), With<InputMarker<C>>>,
mut commands: Commands,
) {
if let Ok(action_of) = action_of.get(trigger.entity)
&& context.get(action_of.get()).is_ok()
{
commands
.entity(trigger.entity)
.insert(InputMarker::<C>::default());
}
}
pub(crate) fn add_input_marker_from_binding<C: Component>(
trigger: On<Add, (Bindings, ActionMock)>,
action: Query<
&ActionOf<C>,
(
With<ActionOf<C>>,
With<NetworkActionOf<C>>,
Without<ConfirmHistory>,
),
>,
contexts: Query<Option<&ControlledBy>, With<Controlled>>,
clients: Query<(), With<Client>>,
mut commands: Commands,
) {
if let Ok(action_of) = action.get(trigger.entity)
&& action_targets_local_client(action_of, &contexts, &clients)
{
commands
.entity(trigger.entity)
.insert(InputMarker::<C>::default());
}
}
pub(crate) fn add_input_marker_from_authority<C: Component>(
trigger: On<Add, HasAuthority>,
action: Query<
&ActionOf<C>,
(
With<ActionOf<C>>,
With<NetworkActionOf<C>>,
Or<(With<Bindings>, With<ActionMock>)>,
Without<ConfirmHistory>,
),
>,
contexts: Query<Option<&ControlledBy>, With<Controlled>>,
clients: Query<(), With<Client>>,
mut commands: Commands,
) {
if let Ok(action_of) = action.get(trigger.entity)
&& action_targets_local_client(action_of, &contexts, &clients)
{
commands
.entity(trigger.entity)
.insert(InputMarker::<C>::default());
}
}
pub(crate) fn add_input_marker_from_network_action<C: Component>(
trigger: On<Add, NetworkActionOf<C>>,
action: Query<
&ActionOf<C>,
(
With<ActionOf<C>>,
With<NetworkActionOf<C>>,
Or<(With<Bindings>, With<ActionMock>)>,
Without<ConfirmHistory>,
),
>,
contexts: Query<Option<&ControlledBy>, With<Controlled>>,
clients: Query<(), With<Client>>,
mut commands: Commands,
) {
if let Ok(action_of) = action.get(trigger.entity)
&& action_targets_local_client(action_of, &contexts, &clients)
{
commands
.entity(trigger.entity)
.insert(InputMarker::<C>::default());
}
}
pub(crate) fn add_input_marker_from_confirmed_controlled_action<C: Component>(
trigger: On<Add, ConfirmHistory>,
action: Query<&ActionOf<C>, (With<ConfirmHistory>, Or<(With<Bindings>, With<ActionMock>)>)>,
contexts: Query<Option<&ControlledBy>, With<Controlled>>,
clients: Query<(), With<Client>>,
mut commands: Commands,
) {
if let Ok(action_of) = action.get(trigger.entity)
&& action_targets_local_client(action_of, &contexts, &clients)
{
commands
.entity(trigger.entity)
.insert(InputMarker::<C>::default());
}
}