createByEntity(Npc)   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
dl 0
loc 22
ccs 13
cts 13
cp 1
crap 2
rs 9.6
c 1
b 0
f 0
eloc 16
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.exploration.npc;
21
22
import fr.quatrevieux.araknemu.core.event.EventsSubscriber;
23
import fr.quatrevieux.araknemu.core.event.Listener;
24
import fr.quatrevieux.araknemu.data.world.entity.environment.npc.Npc;
25
import fr.quatrevieux.araknemu.data.world.entity.environment.npc.NpcTemplate;
26
import fr.quatrevieux.araknemu.data.world.repository.environment.npc.NpcRepository;
27
import fr.quatrevieux.araknemu.data.world.repository.environment.npc.NpcTemplateRepository;
28
import fr.quatrevieux.araknemu.game.PreloadableService;
29
import fr.quatrevieux.araknemu.game.exploration.map.event.MapLoaded;
30
import fr.quatrevieux.araknemu.game.exploration.npc.dialog.DialogService;
31
import org.apache.logging.log4j.Logger;
32
33
import java.util.Collection;
34
import java.util.Optional;
35
import java.util.concurrent.ConcurrentHashMap;
36
import java.util.concurrent.ConcurrentMap;
37
import java.util.stream.Collectors;
38
39
/**
40
 * Manage living NPCs
41
 */
42
public final class NpcService implements EventsSubscriber, PreloadableService {
43
    private final DialogService dialogService;
44
    private final NpcTemplateRepository templateRepository;
45
    private final NpcRepository npcRepository;
46
    private final Collection<ExchangeProvider> exchangeProviders;
47
48 1
    private final ConcurrentMap<Integer, GameNpc> npcByEntityId = new ConcurrentHashMap<>();
49
50 1
    public NpcService(DialogService dialogService, NpcTemplateRepository templateRepository, NpcRepository npcRepository, Collection<ExchangeProvider> exchangeProviders) {
51 1
        this.dialogService = dialogService;
52 1
        this.templateRepository = templateRepository;
53 1
        this.npcRepository = npcRepository;
54 1
        this.exchangeProviders = exchangeProviders;
55 1
    }
56
57
    @Override
58
    public void preload(Logger logger) {
59 1
        logger.info("Loading NPCs...");
60
61 1
        logger.info("{} NPC templates loaded", templateRepository.all().size());
62
63 1
        npcRepository.all().forEach(this::createByEntity);
64 1
        logger.info("{} NPCs loaded", npcByEntityId.size());
65 1
    }
66
67
    @Override
68
    public String name() {
69 1
        return "npc";
70
    }
71
72
    @Override
73
    public Listener[] listeners() {
74 1
        return new Listener[] {
75 1
            new Listener<MapLoaded>() {
76
                @Override
77
                public void on(MapLoaded event) {
78 1
                    npcRepository.byMapId(event.map().id()).stream()
79 1
                        .map(NpcService.this::createByEntity)
80 1
                        .forEach(npc -> npc.join(event.map()))
81
                    ;
82 1
                }
83
84
                @Override
85
                public Class<MapLoaded> event() {
86 1
                    return MapLoaded.class;
87
                }
88
            },
89
        };
90
    }
91
92
    /**
93
     * Get the NPC by the entity ID
94
     *
95
     * @param id The entity ID. /!\ Not same as sprite id
96
     */
97
    public GameNpc get(int id) {
98 1
        final GameNpc alreadyLoaded = npcByEntityId.get(id);
99
100 1
        if (alreadyLoaded != null) {
101 1
            return alreadyLoaded;
102
        }
103
104 1
        return createByEntity(npcRepository.get(id));
105
    }
106
107
    /**
108
     * Create the GameNpc from entity if not yet created
109
     *
110
     * @param entity The NPC entity to create
111
     */
112
    private GameNpc createByEntity(Npc entity) {
113 1
        final GameNpc alreadyLoaded = npcByEntityId.get(entity.id());
114
115 1
        if (alreadyLoaded != null) {
116 1
            return alreadyLoaded;
117
        }
118
119 1
        final NpcTemplate template = templateRepository.get(entity.templateId());
120 1
        final GameNpc npc = new GameNpc(
121
            entity,
122
            template,
123 1
            dialogService.forNpc(entity),
124 1
            exchangeProviders.stream()
125 1
                .map(provider -> provider.load(template))
126 1
                .filter(Optional::isPresent)
127 1
                .map(Optional::get)
128 1
                .collect(Collectors.toList())
129
        );
130
131 1
        npcByEntityId.put(entity.id(), npc);
132
133 1
        return npc;
134
    }
135
}
136