veloren_server/sys/
loot.rs

1use common::{
2    comp::{LootOwner, group::GroupManager, loot_owner::LootOwnerKind},
3    uid::IdMaps,
4};
5use common_ecs::{Job, Origin, Phase, System};
6use specs::{Entities, Entity, Join, Read, WriteStorage};
7use tracing::debug;
8
9// This system manages loot that exists in the world
10#[derive(Default)]
11pub struct Sys;
12impl<'a> System<'a> for Sys {
13    type SystemData = (
14        Entities<'a>,
15        WriteStorage<'a, LootOwner>,
16        Read<'a, IdMaps>,
17        Read<'a, GroupManager>,
18    );
19
20    const NAME: &'static str = "loot";
21    const ORIGIN: Origin = Origin::Server;
22    const PHASE: Phase = Phase::Create;
23
24    fn run(
25        _job: &mut Job<Self>,
26        (entities, mut loot_owners, id_maps, group_manager): Self::SystemData,
27    ) {
28        // Find and remove expired loot ownership. Loot ownership is expired when either
29        // the expiry time has passed, or the owner no longer exists
30        let expired = (&entities, &loot_owners)
31            .join()
32            .filter(|(_, loot_owner)| {
33                loot_owner.expired()
34                    || match loot_owner.owner() {
35                        LootOwnerKind::Player(uid) => id_maps
36                            .uid_entity(uid)
37                            .is_none_or(|entity| !entities.is_alive(entity)),
38                        LootOwnerKind::Group(group) => {
39                            // Special alignment groups (NPC and ENEMY) aren't tracked by the group
40                            // manager, check them separately here
41                            !group.is_special() && group_manager.group_info(group).is_none()
42                        },
43                    }
44            })
45            .map(|(entity, _)| entity)
46            .collect::<Vec<Entity>>();
47
48        if !&expired.is_empty() {
49            debug!("Removing {} expired loot ownerships", expired.iter().len());
50        }
51
52        for entity in expired {
53            loot_owners.remove(entity);
54        }
55    }
56}