veloren_server/sys/
persistence.rs

1use crate::{persistence::character_updater, sys::SysScheduler};
2use common::{
3    comp::{
4        ActiveAbilities, Alignment, Body, Inventory, MapMarker, Presence, PresenceKind, SkillSet,
5        Stats, Waypoint,
6        pet::{Pet, is_tameable},
7    },
8    uid::Uid,
9};
10use common_ecs::{Job, Origin, Phase, System};
11use specs::{Join, LendJoin, ReadStorage, Write, WriteExpect};
12use tracing::error;
13
14#[derive(Default)]
15pub struct Sys;
16
17impl<'a> System<'a> for Sys {
18    type SystemData = (
19        ReadStorage<'a, Alignment>,
20        ReadStorage<'a, Body>,
21        ReadStorage<'a, Presence>,
22        ReadStorage<'a, SkillSet>,
23        ReadStorage<'a, Inventory>,
24        ReadStorage<'a, Uid>,
25        ReadStorage<'a, Waypoint>,
26        ReadStorage<'a, MapMarker>,
27        ReadStorage<'a, Pet>,
28        ReadStorage<'a, Stats>,
29        ReadStorage<'a, ActiveAbilities>,
30        WriteExpect<'a, character_updater::CharacterUpdater>,
31        Write<'a, SysScheduler<Self>>,
32    );
33
34    const NAME: &'static str = "persistence";
35    const ORIGIN: Origin = Origin::Server;
36    const PHASE: Phase = Phase::Create;
37
38    fn run(
39        _job: &mut Job<Self>,
40        (
41            alignments,
42            bodies,
43            presences,
44            player_skill_set,
45            player_inventories,
46            uids,
47            player_waypoints,
48            map_markers,
49            pets,
50            stats,
51            active_abilities,
52            mut updater,
53            mut scheduler,
54        ): Self::SystemData,
55    ) {
56        if scheduler.should_run() {
57            updater.batch_update(
58                (
59                    &presences,
60                    &player_skill_set,
61                    &player_inventories,
62                    &uids,
63                    player_waypoints.maybe(),
64                    &active_abilities,
65                    map_markers.maybe(),
66                )
67                    .join()
68                    .filter_map(
69                        |(
70                            presence,
71                            skill_set,
72                            inventory,
73                            player_uid,
74                            waypoint,
75                            active_abilities,
76                            map_marker,
77                        )| match presence.kind {
78                            PresenceKind::LoadingCharacter(_char_id) => {
79                                error!(
80                                    "Unexpected state when persisting characters! Some of the \
81                                     components required above should only be present after a \
82                                     character is loaded!"
83                                );
84                                None
85                            },
86                            PresenceKind::Character(id) => {
87                                let pets = (&alignments, &bodies, &stats, &pets)
88                                    .join()
89                                    .filter_map(|(alignment, body, stats, pet)| match alignment {
90                                        // Don't try to persist non-tameable pets (likely spawned
91                                        // using /spawn) since there isn't any code to handle
92                                        // persisting them
93                                        Alignment::Owned(ref pet_owner)
94                                            if pet_owner == player_uid && is_tameable(body) =>
95                                        {
96                                            Some(((*pet).clone(), *body, stats.clone()))
97                                        },
98                                        _ => None,
99                                    })
100                                    .collect();
101
102                                Some((
103                                    id,
104                                    skill_set.clone(),
105                                    inventory.clone(),
106                                    pets,
107                                    waypoint.cloned(),
108                                    active_abilities.clone(),
109                                    map_marker.cloned(),
110                                ))
111                            },
112                            PresenceKind::Spectator | PresenceKind::Possessor => None,
113                        },
114                    ),
115            );
116        }
117    }
118}