Passed
Pull Request — master (#169)
by Vincent
10:14
created

fightPlaces(int)   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
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.map;
21
22
import fr.arakne.utils.maps.DofusMap;
23
import fr.arakne.utils.value.Dimensions;
24
import fr.quatrevieux.araknemu.core.event.DefaultListenerAggregate;
25
import fr.quatrevieux.araknemu.core.event.Dispatcher;
26
import fr.quatrevieux.araknemu.core.event.ListenerAggregate;
27
import fr.quatrevieux.araknemu.data.value.Geolocation;
28
import fr.quatrevieux.araknemu.data.world.entity.environment.MapTemplate;
29
import fr.quatrevieux.araknemu.game.exploration.area.ExplorationSubArea;
30
import fr.quatrevieux.araknemu.game.exploration.creature.ExplorationCreature;
31
import fr.quatrevieux.araknemu.game.exploration.creature.Operation;
32
import fr.quatrevieux.araknemu.game.exploration.creature.operation.SendPacket;
33
import fr.quatrevieux.araknemu.game.exploration.map.cell.BasicCell;
34
import fr.quatrevieux.araknemu.game.exploration.map.cell.CellLoader;
35
import fr.quatrevieux.araknemu.game.exploration.map.cell.ExplorationMapCell;
36
import fr.quatrevieux.araknemu.game.exploration.map.event.NewSpriteOnMap;
37
import fr.quatrevieux.araknemu.game.exploration.map.event.SpriteRemoveFromMap;
38
import fr.quatrevieux.araknemu.game.world.creature.Sprite;
39
40
import java.util.Collection;
41
import java.util.Collections;
42
import java.util.List;
43
import java.util.Map;
44
import java.util.NoSuchElementException;
45
import java.util.concurrent.ConcurrentHashMap;
46
import java.util.concurrent.ConcurrentMap;
47
import java.util.function.Function;
48
import java.util.stream.Collectors;
49
50
/**
51
 * Map object for exploration
52
 */
53
public final class ExplorationMap implements DofusMap<ExplorationMapCell>, Dispatcher {
54
    private final MapTemplate template;
55
    private final ExplorationSubArea subArea;
56
57
    private final Map<Integer, ExplorationMapCell> cells;
58 1
    private final ConcurrentMap<Integer, ExplorationCreature> creatures = new ConcurrentHashMap<>();
59
60 1
    private final ListenerAggregate dispatcher = new DefaultListenerAggregate();
61
62 1
    public ExplorationMap(MapTemplate template, CellLoader loader, ExplorationSubArea subArea) {
63 1
        this.template = template;
64 1
        this.subArea = subArea;
65
66 1
        this.cells = loader.load(this, template.cells())
67 1
            .stream()
68 1
            .collect(Collectors.toMap(ExplorationMapCell::id, Function.identity()))
69
        ;
70 1
    }
71
72
    /**
73
     * Get the map id
74
     *
75
     * filename : data/maps/[id]_[date](X).swf
76
     */
77
    public int id() {
78 1
        return template.id();
79
    }
80
81
    /**
82
     * Get the map data / version
83
     *
84
     * filename : data/maps/[id]_[date](X).swf
85
     */
86
    public String date() {
87 1
        return template.date();
88
    }
89
90
    /**
91
     * Get the map decryption key
92
     * Used by map swf which finish with "X.swf"
93
     */
94
    public String key() {
95 1
        return template.key();
96
    }
97
98
    /**
99
     * Get the map dimensions
100
     *
101
     * /!\ Because cells are interleaved, the real height of the map is x2,
102
     *     and the width is lower one every two lines
103
     */
104
    public Dimensions dimensions() {
105 1
        return template.dimensions();
106
    }
107
108
    /**
109
     * Get the number of cells of the map
110
     */
111
    public int size() {
112 1
        return template.cells().length;
113
    }
114
115
    @Override
116
    public ExplorationMapCell get(int id) {
117 1
        if (cells.containsKey(id)) {
118 1
            return cells.get(id);
119
        }
120
121 1
        return new BasicCell(id, template.cells()[id], this);
122
    }
123
124
    /**
125
     * Add a new creature to the map
126
     */
127
    public void add(ExplorationCreature creature) {
128 1
        if (creatures.containsKey(creature.id())) {
129 1
            throw new IllegalArgumentException("The creature is already added");
130
        }
131
132 1
        creatures.put(creature.id(), creature);
133
134 1
        dispatch(new NewSpriteOnMap(creature.sprite()));
135 1
    }
136
137
    /**
138
     * Remove the creature from the map
139
     */
140
    public void remove(ExplorationCreature creature) {
141 1
        if (!creatures.containsKey(creature.id())) {
142 1
            throw new IllegalArgumentException("The creature do not exists");
143
        }
144
145 1
        creatures.remove(creature.id());
146 1
        dispatch(new SpriteRemoveFromMap(creature.sprite()));
147 1
    }
148
149
    /**
150
     * Get list of map sprites
151
     */
152
    public Collection<Sprite> sprites() {
153 1
        return creatures.values().stream()
154 1
            .map(ExplorationCreature::sprite)
155 1
            .collect(Collectors.toList())
156
        ;
157
    }
158
159
    /**
160
     * Get all creatures on map
161
     */
162
    public Collection<ExplorationCreature> creatures() {
163 1
        return creatures.values();
164
    }
165
166
    /**
167
     * Get a creature by its id
168
     *
169
     * @param id The creature id
170
     */
171
    public ExplorationCreature creature(int id) {
172 1
        if (!creatures.containsKey(id)) {
173 1
            throw new NoSuchElementException("The creature " + id + " cannot be found");
174
        }
175
176 1
        return creatures.get(id);
177
    }
178
179
    /**
180
     * Check if the map has the creature
181
     *
182
     * @param id The creature id
183
     */
184
    public boolean has(int id) {
185 1
        return creatures.containsKey(id);
186
    }
187
188
    @Override
189
    public void dispatch(Object event) {
190 1
        dispatcher.dispatch(event);
191 1
    }
192
193
    /**
194
     * Send a packet to the map
195
     */
196
    public void send(Object packet) {
197 1
        apply(new SendPacket(packet));
198 1
    }
199
200
    /**
201
     * Apply an operation to all creatures in map
202
     *
203
     * @see ExplorationCreature#apply(Operation)
204
     */
205
    public void apply(Operation operation) {
206 1
        creatures.values().forEach(creature -> creature.apply(operation));
207 1
    }
208
209
    /**
210
     * Can launch a fight on the map ?
211
     */
212
    public boolean canLaunchFight() {
213 1
        return template.fightPlaces().length >= 2;
214
    }
215
216
    /**
217
     * Get the available fight places for the given team
218
     *
219
     * @param team The team number. Starts at 0
220
     *
221
     * @return List of placement cells, or empty list if there is not place for the given team
222
     */
223
    public List<ExplorationMapCell> fightPlaces(int team) {
224 1
        if (team >= template.fightPlaces().length) {
225 1
            return Collections.emptyList();
226
        }
227
228 1
        return template.fightPlaces()[team].stream().map(this::get).collect(Collectors.toList());
229
    }
230
231
    /**
232
     * Get the sub-area of the map
233
     */
234
    public ExplorationSubArea subArea() {
235 1
        return subArea;
236
    }
237
238
    /**
239
     * Check if the map is an indoor map (i.e. house or underground)
240
     */
241
    public boolean indoor() {
242 1
        return template.indoor();
243
    }
244
245
    /**
246
     * Get the map geolocation
247
     */
248
    public Geolocation geolocation() {
249 1
        return template.geolocation();
250
    }
251
252
    public ListenerAggregate dispatcher() {
253 1
        return dispatcher;
254
    }
255
}
256