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
use common::{
    comp::{Ori, Pos, Vel},
    resources::{PlayerEntity, Time},
};
use common_base::prof_span;
use common_ecs::{Job, Origin, Phase, System};
use common_net::sync::InterpolatableComponent;
use specs::{
    prelude::ParallelIterator, shred, Entities, ParJoin, Read, ReadStorage, SystemData,
    WriteStorage,
};

#[derive(SystemData)]
pub struct ReadData<'a> {
    time: Read<'a, Time>,
    player: Read<'a, PlayerEntity>,
    entities: Entities<'a>,
    pos_interpdata: ReadStorage<'a, <Pos as InterpolatableComponent>::InterpData>,
    vel_interpdata: ReadStorage<'a, <Vel as InterpolatableComponent>::InterpData>,
    ori_interpdata: ReadStorage<'a, <Ori as InterpolatableComponent>::InterpData>,
}

#[derive(Default)]
pub struct Sys;

impl<'a> System<'a> for Sys {
    type SystemData = (
        ReadData<'a>,
        WriteStorage<'a, Pos>,
        WriteStorage<'a, Vel>,
        WriteStorage<'a, Ori>,
    );

    const NAME: &'static str = "interpolation";
    const ORIGIN: Origin = Origin::Common;
    const PHASE: Phase = Phase::Apply;

    fn run(_job: &mut Job<Self>, (data, mut pos, mut vel, mut ori): Self::SystemData) {
        let time = data.time.0;
        let player = data.player.0;

        (
            &data.entities,
            &mut pos,
            &data.pos_interpdata,
            &data.vel_interpdata,
        )
            .par_join()
            .filter(|(e, _, _, _)| Some(e) != player.as_ref())
            .for_each_init(
                || {
                    prof_span!(guard, "interpolate pos rayon job");
                    guard
                },
                |_guard, (_, pos, interp, vel)| {
                    *pos = pos.interpolate(interp, time, vel);
                },
            );
        (&data.entities, &mut vel, &data.vel_interpdata)
            .par_join()
            .filter(|(e, _, _)| Some(e) != player.as_ref())
            .for_each_init(
                || {
                    prof_span!(guard, "interpolate vel rayon job");
                    guard
                },
                |_guard, (_, vel, interp)| {
                    *vel = vel.interpolate(interp, time, &());
                },
            );
        (&data.entities, &mut ori, &data.ori_interpdata)
            .par_join()
            .filter(|(e, _, _)| Some(e) != player.as_ref())
            .for_each_init(
                || {
                    prof_span!(guard, "interpolate ori rayon job");
                    guard
                },
                |_guard, (_, ori, interp)| {
                    *ori = ori.interpolate(interp, time, &());
                },
            );
    }
}