Passed
Push — master ( dce7e6...e2e6ab )
by Vincent
06:59 queued 12s
created

name()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
eloc 3
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.item;
21
22
import fr.quatrevieux.araknemu.data.value.ItemTemplateEffectEntry;
23
import fr.quatrevieux.araknemu.data.world.entity.item.ItemSet;
24
import fr.quatrevieux.araknemu.data.world.entity.item.ItemTemplate;
25
import fr.quatrevieux.araknemu.data.world.repository.item.ItemSetRepository;
26
import fr.quatrevieux.araknemu.data.world.repository.item.ItemTemplateRepository;
27
import fr.quatrevieux.araknemu.data.world.repository.item.ItemTypeRepository;
28
import fr.quatrevieux.araknemu.game.PreloadableService;
29
import fr.quatrevieux.araknemu.game.item.effect.CharacteristicEffect;
30
import fr.quatrevieux.araknemu.game.item.effect.SpecialEffect;
31
import fr.quatrevieux.araknemu.game.item.effect.mapping.EffectMapper;
32
import fr.quatrevieux.araknemu.game.item.factory.ItemFactory;
33
import org.apache.logging.log4j.Logger;
34
import org.checkerframework.checker.index.qual.Positive;
35
36
import java.util.ArrayList;
37
import java.util.HashMap;
38
import java.util.List;
39
import java.util.Map;
40
import java.util.concurrent.ConcurrentHashMap;
41
import java.util.concurrent.ConcurrentMap;
42
43
/**
44
 * Service for handle items
45
 */
46
public final class ItemService implements PreloadableService {
47
    private final ItemTemplateRepository repository;
48
    private final ItemFactory factory;
49
    private final ItemSetRepository itemSetRepository;
50
    private final ItemTypeRepository itemTypeRepository;
51
    private final EffectMapper<CharacteristicEffect> characteristicEffectEffectMapper;
52
    private final EffectMapper<SpecialEffect> specialEffectEffectMapper;
53
54 1
    private final ConcurrentMap<Integer, GameItemSet> itemSetsById = new ConcurrentHashMap<>();
55
56 1
    public ItemService(ItemTemplateRepository repository, ItemFactory factory, ItemSetRepository itemSetRepository, ItemTypeRepository itemTypeRepository, EffectMapper<CharacteristicEffect> characteristicEffectEffectMapper, EffectMapper<SpecialEffect> specialEffectEffectMapper) {
57 1
        this.repository = repository;
58 1
        this.factory = factory;
59 1
        this.itemSetRepository = itemSetRepository;
60 1
        this.itemTypeRepository = itemTypeRepository;
61 1
        this.characteristicEffectEffectMapper = characteristicEffectEffectMapper;
62 1
        this.specialEffectEffectMapper = specialEffectEffectMapper;
63 1
    }
64
65
    @Override
66
    public void preload(Logger logger) {
67 1
        loadItemTypes(logger);
68 1
        loadItemSets(logger);
69 1
        loadItems(logger);
70 1
    }
71
72
    @Override
73
    public String name() {
74 1
        return "item";
75
    }
76
77
    /**
78
     * Create a new item
79
     *
80
     * @param id The item template id
81
     * @param maximize Maximize item stats ?
82
     */
83
    public Item create(int id, boolean maximize) {
84 1
        return create(repository.get(id), maximize);
85
    }
86
87
    /**
88
     * Create a new item
89
     *
90
     * @param id The item template id
91
     */
92
    public Item create(int id) {
93 1
        return create(id, false);
94
    }
95
96
    /**
97
     * Create a new item by its template
98
     *
99
     * @param template The item template
100
     * @param maximize Maximize item stats ?
101
     */
102
    public Item create(ItemTemplate template, boolean maximize) {
103 1
        return factory.create(
104
            template,
105 1
            itemTypeRepository.get(template.type()),
106 1
            template.itemSet() == 0
107 1
                ? null
108 1
                : itemSet(template.itemSet()),
109
            maximize
110
        );
111
    }
112
113
    /**
114
     * Create a new item by its template
115
     *
116
     * @param template The item template
117
     */
118
    public Item create(ItemTemplate template) {
119 1
        return create(template, false);
120
    }
121
122
    /**
123
     * Creates many times an item, with random stats on each creation
124
     *
125
     * @param template The item template to generates
126
     * @param quantity The desired quantity
127
     *
128
     * @return Map of item associated with the quantity
129
     */
130
    public Map<Item, @Positive Integer> createBulk(ItemTemplate template, @Positive int quantity) {
131 1
        final Map<Item, @Positive Integer> items = new HashMap<>();
132
133 1
        for (int count = 0; count < quantity; ++count) {
134 1
            final Item generated = create(template);
135
136 1
            items.merge(generated, 1, (a, b) -> a + b); // Do not use Integer::sum because it does not handle @Positive
137
        }
138
139 1
        return items;
140
    }
141
142
    /**
143
     * Retrieve an item with its effects
144
     *
145
     * @param id The item template id
146
     * @param effects The item effects
147
     */
148
    public Item retrieve(int id, List<ItemTemplateEffectEntry> effects) {
149 1
        final ItemTemplate template = repository.get(id);
150
151 1
        return factory.retrieve(
152
            template,
153 1
            itemTypeRepository.get(template.type()),
154 1
            template.itemSet() == 0
155 1
                ? null
156 1
                : itemSet(template.itemSet()),
157
            effects
158
        );
159
    }
160
161
    /**
162
     * Get an item set
163
     *
164
     * @param id The item set id
165
     *
166
     * @throws fr.quatrevieux.araknemu.core.dbal.repository.EntityNotFoundException When the item set do not exists
167
     */
168
    public GameItemSet itemSet(int id) {
169 1
        return itemSetsById.computeIfAbsent(id, mid -> createItemSet(itemSetRepository.get(id)));
170
    }
171
172
    private GameItemSet createItemSet(ItemSet entity) {
173 1
        final List<GameItemSet.Bonus> bonuses = new ArrayList<>();
174
175 1
        for (List<ItemTemplateEffectEntry> effects : entity.bonus()) {
176 1
            bonuses.add(
177
                new GameItemSet.Bonus(
178
                    effects,
179 1
                    characteristicEffectEffectMapper.create(effects),
180 1
                    specialEffectEffectMapper.create(effects)
181
                )
182
            );
183 1
        }
184
185 1
        return new GameItemSet(entity, bonuses);
186
    }
187
188
    private void loadItems(Logger logger) {
189 1
        logger.info("Loading items...");
190
191 1
        final int loaded = repository.load().size();
192
193 1
        logger.info("Successfully load {} items", loaded);
194 1
    }
195
196
    private void loadItemSets(Logger logger) {
197 1
        logger.info("Loading item sets...");
198
199 1
        for (ItemSet entity : itemSetRepository.load()) {
200 1
            itemSetsById.put(entity.id(), createItemSet(entity));
201 1
        }
202
203 1
        logger.info("Successfully load {} item sets", itemSetsById.size());
204 1
    }
205
206
    private void loadItemTypes(Logger logger) {
207 1
        logger.info("Loading item types...");
208 1
        logger.info("Successfully load {} item sets", itemTypeRepository.load().size());
209 1
    }
210
}
211