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
use crate::{Chunk, MoveStatus, PcHandle, PlayerCharacter, Point, WorldInstant, SECOND};
use serde::{Deserialize, Serialize};

/// Changes to a [Chunk], or an entire [Chunk] to replace the current one with.
#[derive(Clone, Serialize, Deserialize)]
pub enum ChunkUpdate {
    ResetTo(Chunk),
    Effects(Vec<Effect>),
}

/// An effect applied to a [Chunk] that will change its state deterministically.
#[derive(Clone, Serialize, Deserialize)]
pub enum Effect {
    SpawnPlayerCharacter {
        handle: PcHandle,
        position: Point,
    },
    DespawnPlayerCharacter(PcHandle),
    MovePlayerCharacter {
        handle: PcHandle,
        old_position: Point,
        new_position: Point,
    },
}

// Used in docs.
#[allow(unused_imports)]
use crate::{ServerAction, World};

impl Effect {
    /// Applies the effect to a [Chunk]. The time should be the [World::time]
    /// matching this [Effect].
    ///
    /// See also: [ServerAction::Effects].
    pub fn apply_effect(self, time: WorldInstant, chunk: &mut Chunk) {
        use Effect::*;
        match self {
            SpawnPlayerCharacter { handle, position } => {
                chunk.pcs.insert(
                    handle,
                    PlayerCharacter {
                        position,
                        current_move: None,
                    },
                );
            }
            DespawnPlayerCharacter(handle) => {
                chunk.pcs.remove(&handle);
            }
            MovePlayerCharacter {
                handle,
                old_position,
                new_position,
            } => {
                let player = chunk.pcs.get_mut(&handle).unwrap();
                player.position = new_position;
                player.current_move = Some(MoveStatus {
                    duration: SECOND / 4,
                    start_frame: time,
                    from: old_position,
                    to: new_position,
                });
            }
        }
    }
}