Passed
Push — master ( c9f44c...4e8a30 )
by Vincent
33:01 queued 20:20
created

populate(ExplorationMap)   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 10
c 1
b 0
f 0
eloc 5
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-2019 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.monster.environment;
21
22
import fr.quatrevieux.araknemu.data.world.entity.monster.MonsterGroupData;
23
import fr.quatrevieux.araknemu.data.world.entity.monster.MonsterGroupPosition;
24
import fr.quatrevieux.araknemu.game.exploration.ExplorationPlayer;
25
import fr.quatrevieux.araknemu.game.exploration.map.ExplorationMap;
26
import fr.quatrevieux.araknemu.game.exploration.map.cell.ExplorationMapCell;
27
import fr.quatrevieux.araknemu.game.fight.Fight;
28
import fr.quatrevieux.araknemu.game.fight.FightService;
29
import fr.quatrevieux.araknemu.game.fight.builder.PvmBuilder;
30
import fr.quatrevieux.araknemu.game.monster.group.MonsterGroup;
31
import fr.quatrevieux.araknemu.game.monster.group.MonsterGroupFactory;
32
33
import java.util.Collections;
34
import java.util.List;
35
import java.util.stream.Collectors;
36
import java.util.stream.Stream;
37
38
/**
39
 * Handle a monster group configuration on map and cell
40
 */
41
public final class LivingMonsterGroupPosition {
42
    private final MonsterGroupFactory factory;
43
    private final FightService fightService;
44
    private final MonsterEnvironmentService environmentService;
45
    private final boolean fixed;
46
47
    private final MonsterGroupData data;
48
    private final SpawnCellSelector cellSelector;
49
50
    private ExplorationMap map;
51
52 1
    public LivingMonsterGroupPosition(MonsterGroupFactory factory, MonsterEnvironmentService environmentService, FightService fightService, MonsterGroupData data, SpawnCellSelector cellSelector, boolean fixed) {
53 1
        this.factory = factory;
54 1
        this.fightService = fightService;
55 1
        this.environmentService = environmentService;
56 1
        this.data = data;
57 1
        this.cellSelector = cellSelector;
58 1
        this.fixed = fixed;
59 1
    }
60
61
    /**
62
     * Link the group to the map and populate (spawn) with configured group data
63
     * This method should be called once, when exploration map is loaded
64
     *
65
     * @see fr.quatrevieux.araknemu.game.exploration.map.event.MapLoaded
66
     */
67
    public void populate(ExplorationMap map) {
68 1
        this.map = map;
69 1
        this.cellSelector.setMap(map);
70
71 1
        for (long i = groupStream().count(); i < data.maxCount(); ++i) {
72 1
            spawn();
73
        }
74 1
    }
75
76
    /**
77
     * Spawn a new group on the map
78
     *
79
     * Note: this method will not check the max count of monsters : if called manually, the group count can exceed max count
80
     */
81
    public void spawn() {
82 1
        map.add(factory.create(data, this));
83 1
    }
84
85
    /**
86
     * Respawn a group on the map
87
     *
88
     * Unlike {@link LivingMonsterGroupPosition#spawn()} the maximum number of groups is checked,
89
     * and this method will do nothing if the map is already full
90
     */
91
    public void respawn() {
92 1
        if (groupStream().count() < data.maxCount()) {
93 1
            map.add(factory.create(data, this));
94
        }
95 1
    }
96
97
    /**
98
     * Get list of available monster groups on the map
99
     */
100
    public List<MonsterGroup> available() {
101 1
        if (map == null) {
102 1
            return Collections.emptyList();
103
        }
104
105 1
        return groupStream().collect(Collectors.toList());
106
    }
107
108
    /**
109
     * Find the group spawn cell
110
     *
111
     * If the cell is fixed (not -1 on {@link MonsterGroupPosition#position() cell}), this cell is returned
112
     * If not, a random free (without creatures, objects, and walkable) cell is returned
113
     *
114
     * @see fr.quatrevieux.araknemu.game.exploration.map.cell.ExplorationMapCell#free()
115
     * @see SpawnCellSelector#cell()
116
     */
117
    public ExplorationMapCell cell() {
118 1
        return cellSelector.cell();
119
    }
120
121
    /**
122
     * Does the current monster group is fixed ?
123
     * If true, the group cannot move
124
     */
125
    public boolean fixed() {
126 1
        return fixed;
127
    }
128
129
    /**
130
     * Start a fight with the group
131
     *
132
     * @param group The monster group. Must be handled by the current instance
133
     * @param player The player
134
     *
135
     * @return The created fight
136
     */
137
    public Fight startFight(MonsterGroup group, ExplorationPlayer player) {
138 1
        map.remove(group);
139 1
        environmentService.respawn(this, data.respawnTime());
140
141 1
        return fightService.handler(PvmBuilder.class).start(
142 1
            builder -> builder
143 1
                .randomize(!data.fixedTeamNumber())
144 1
                .map(map)
145 1
                .initiator(player.player())
146 1
                .monsterGroup(group)
147
        );
148
    }
149
150
    /**
151
     * Get stream of groups related to the current group position
152
     */
153
    private Stream<MonsterGroup> groupStream() {
154 1
        return map.creatures().stream()
155 1
            .filter(MonsterGroup.class::isInstance)
156 1
            .map(creature -> (MonsterGroup) creature)
157 1
            .filter(group -> this.equals(group.handler()))
158
        ;
159
    }
160
}
161