1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Input traits required by networking. These traits are networking specific, either only used in networking,
//! or extending other traits from [`crate::input`] for networking.

use std::fmt::Debug;

use bones_schema::HasSchema;

use crate::input::{InputCollector, PlayerControls};

use super::NetworkInputStatus;

/// Define input types used by game for use in networking.
///
/// As long as types `PlayerControls` and `InputCollector` implement traits [`PlayerControls`] and [`InputCollector`],
/// trait bounds [`NetworkPlayerControl`] and [`NetworkInputCollector`] are automatically implemented.
#[allow(missing_docs)]
pub trait NetworkInputConfig<'a> {
    type Dense: DenseInput + Debug + Default;
    type Control: NetworkPlayerControl<Self::Dense>;

    // Must be HasSchema because expected to be retrieved from `World` as `Resource`.
    type PlayerControls: PlayerControls<'a, Self::Control> + HasSchema;

    // InputCollector type params must match that of PlayerControls, so using associated types.
    type InputCollector: InputCollector<
            'a,
            <Self::PlayerControls as PlayerControls<'a, Self::Control>>::ControlMapping,
            <Self::PlayerControls as PlayerControls<'a, Self::Control>>::ControlSource,
            Self::Control,
        > + Default;
}

/// Required for use of [`PlayerControls`] in networking.
pub trait NetworkPlayerControls<'a, Dense: DenseInput, Control>:
    PlayerControls<'a, Control>
{
    /// Update control of player from dense input.
    ///
    /// [`NetworkInputStatus`] communicates if input is confirmed, predicted, or from disconnected player.
    fn network_update(
        &mut self,
        player_idx: usize,
        dense_input: &Dense,
        status: NetworkInputStatus,
    );

    /// Get dense control for player.
    fn get_dense_control(&self, player_idx: usize) -> Dense;
}

impl<'a, T, Dense, Control> NetworkPlayerControls<'a, Dense, Control> for T
where
    Dense: DenseInput,
    Control: NetworkPlayerControl<Dense>,
    T: PlayerControls<'a, Control>,
{
    // type NetworkControl = PlayerControl;
    fn network_update(
        &mut self,
        player_idx: usize,
        dense_input: &Dense,
        _status: NetworkInputStatus,
    ) {
        self.get_control_mut(player_idx)
            .update_from_dense(dense_input);
    }

    fn get_dense_control(&self, player_idx: usize) -> Dense {
        self.get_control(player_idx).get_dense_input()
    }
}

/// Dense input for network replication.
pub trait DenseInput:
    bytemuck::Pod + bytemuck::Zeroable + Copy + Clone + PartialEq + Eq + Send + Sync
{
}

/// Automatic implementation for `DenseInput`.
impl<T> DenseInput for T where
    T: bytemuck::Pod + bytemuck::Zeroable + Copy + Clone + PartialEq + Eq + Send + Sync
{
}

///  Trait allowing for creating and applying [`DenseInput`] from control.
pub trait NetworkPlayerControl<Dense: DenseInput>: Send + Sync + Default {
    /// Get [`DenseInput`] for control.
    fn get_dense_input(&self) -> Dense;

    /// Update control from [`DenseInput`].
    fn update_from_dense(&mut self, new_control: &Dense);
}

/// Extension of [`InputCollector`] exposing dense control for networking.
///
/// This trait is automatically implemented for [`InputCollector`]'s such that `Control`
/// implements [`NetworkPlayerControl`] (i.e. implements dense input)
pub trait NetworkInputCollector<'a, Dense, ControlMapping, ControlSource, Control>:
    InputCollector<'a, ControlMapping, ControlSource, Control>
where
    Dense: DenseInput,
    ControlMapping: HasSchema,
    Control: NetworkPlayerControl<Dense>,
{
    /// Get dense control
    fn get_dense_control(&self, player_idx: usize, control_soure: ControlSource) -> Dense;
}

/// Provide automatic [`NetworkInputCollector`] for [`InputCollector`] when type parameters
/// meet required bounds for networking.
impl<'a, T, Dense, ControlMapping, ControlSource, Control>
    NetworkInputCollector<'a, Dense, ControlMapping, ControlSource, Control> for T
where
    Dense: DenseInput,
    Control: NetworkPlayerControl<Dense>,
    ControlMapping: HasSchema,
    T: InputCollector<'a, ControlMapping, ControlSource, Control>,
{
    fn get_dense_control(&self, player_idx: usize, control_source: ControlSource) -> Dense {
        self.get_control(player_idx, control_source)
            .get_dense_input()
    }
}