Skip to content

Commit

Permalink
#63 #27 Start fight modules + raulebaque effect
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent4vx committed Oct 14, 2018
1 parent 7c32194 commit 77a3676
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package fr.quatrevieux.araknemu.core.event;

import java.util.Collection;

/**
* Subscribe to events registering listeners
*/
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/fr/quatrevieux/araknemu/game/GameModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import fr.quatrevieux.araknemu.game.exploration.map.cell.trigger.action.teleport.TeleportFactory;
import fr.quatrevieux.araknemu.game.fight.FightService;
import fr.quatrevieux.araknemu.game.fight.builder.ChallengeBuilderFactory;
import fr.quatrevieux.araknemu.game.fight.module.RaulebaqueModule;
import fr.quatrevieux.araknemu.game.handler.loader.*;
import fr.quatrevieux.araknemu.game.item.ItemService;
import fr.quatrevieux.araknemu.game.item.SuperType;
Expand Down Expand Up @@ -425,6 +426,9 @@ private void configureServices(ContainerConfigurator configurator)
container.get(fr.quatrevieux.araknemu.core.event.Dispatcher.class),
Arrays.asList(
new ChallengeBuilderFactory()
),
Arrays.asList(
RaulebaqueModule::new
)
)
);
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import fr.quatrevieux.araknemu.game.fight.exception.InvalidFightStateException;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.map.FightMap;
import fr.quatrevieux.araknemu.game.fight.module.FightModule;
import fr.quatrevieux.araknemu.game.fight.state.*;
import fr.quatrevieux.araknemu.game.fight.team.FightTeam;
import fr.quatrevieux.araknemu.game.fight.turn.FightTurnList;
Expand All @@ -17,6 +18,7 @@
import org.apache.commons.lang3.time.StopWatch;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
Expand All @@ -30,6 +32,7 @@ final public class Fight implements Dispatcher, Sender {
final private FightMap map;
final private List<FightTeam> teams;
final private StatesFlow statesFlow;
final private List<FightModule> modules = new ArrayList<>();

final private ListenerAggregate dispatcher = new DefaultListenerAggregate();
final private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Expand All @@ -56,6 +59,16 @@ public Fight(int id, FightType type, FightMap map, List<FightTeam> teams) {
));
}

/**
* Register a module
*/
public void register(FightModule module)
{
modules.add(module);
dispatcher.register(module);
module.effects(effects);
}

/**
* Get the fight id
*/
Expand Down Expand Up @@ -121,6 +134,7 @@ public <T extends FightState> T state(Class<T> type) {
*/
public void nextState() {
statesFlow.next(this);
modules.forEach(module -> module.stateChanged(statesFlow.current()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import fr.quatrevieux.araknemu.game.fight.builder.FightBuilder;
import fr.quatrevieux.araknemu.game.fight.event.FightCancelled;
import fr.quatrevieux.araknemu.game.fight.event.FightStopped;
import fr.quatrevieux.araknemu.game.fight.module.FightModule;

import java.util.function.Consumer;

Expand All @@ -29,6 +30,8 @@ public Fight start(Consumer<B> configuration) {
configuration.accept(builder);

Fight fight = builder.build(service.newFightId());

service.modules(fight).forEach(fight::register);
fight.nextState();

fight.dispatcher().register(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import fr.quatrevieux.araknemu.game.fight.builder.FightBuilderFactory;
import fr.quatrevieux.araknemu.game.fight.event.FightCreated;
import fr.quatrevieux.araknemu.game.fight.map.FightMap;
import fr.quatrevieux.araknemu.game.fight.module.FightModule;
import fr.quatrevieux.araknemu.game.listener.player.exploration.LeaveExplorationForFight;
import fr.quatrevieux.araknemu.game.listener.player.fight.AttachFighter;
import fr.quatrevieux.araknemu.game.player.event.PlayerLoaded;
Expand All @@ -26,13 +27,15 @@ final public class FightService implements EventsSubscriber {
final private MapTemplateRepository mapRepository;
final private Dispatcher dispatcher;
final private Map<Class, FightBuilderFactory> builderFactories;
final private Collection<FightModule.Factory> moduleFactories;

final private Map<Integer, Map<Integer, Fight>> fightsByMapId = new HashMap<>();
final private AtomicInteger lastFightId = new AtomicInteger();

public FightService(MapTemplateRepository mapRepository, Dispatcher dispatcher, Collection<? extends FightBuilderFactory> factories) {
public FightService(MapTemplateRepository mapRepository, Dispatcher dispatcher, Collection<? extends FightBuilderFactory> factories, Collection<FightModule.Factory> moduleFactories) {
this.mapRepository = mapRepository;
this.dispatcher = dispatcher;
this.moduleFactories = moduleFactories;

this.builderFactories = factories.stream().collect(
Collectors.toMap(
Expand Down Expand Up @@ -155,4 +158,14 @@ synchronized void created(Fight fight) {
synchronized void remove(Fight fight) {
fightsByMapId.get(fight.map().id()).remove(fight.id());
}

/**
* Make modules for a fight
*/
Collection<FightModule> modules(Fight fight) {
return moduleFactories.stream()
.map(factory -> factory.create(fight))
.collect(Collectors.toList())
;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package fr.quatrevieux.araknemu.game.fight.castable.effect.handler.shifting;

import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.castable.CastScope;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.EffectHandler;
import fr.quatrevieux.araknemu.game.fight.map.FightCell;
import fr.quatrevieux.araknemu.game.fight.module.RaulebaqueModule;
import fr.quatrevieux.araknemu.network.game.out.fight.FighterPositions;

/**
* Handle the Raulebaque effect
*/
final public class RaulebaqueHandler implements EffectHandler {
final private Fight fight;
final private RaulebaqueModule module;

public RaulebaqueHandler(Fight fight, RaulebaqueModule module) {
this.fight = fight;
this.module = module;
}

@Override
public void handle(CastScope cast, CastScope.EffectScope effect) {
module.startPositions().forEach((fighter, startCell) -> {
if (fighter.dead()) {
return;
}

FightCell lastCell = fighter.cell();

if (lastCell.equals(startCell)) {
return;
}

fighter.move(null);

// Cell is not free : exchange place
startCell.fighter().ifPresent(other -> other.move(lastCell));
fighter.move(startCell);
});

fight.send(new FighterPositions(fight.fighters()));
}

@Override
public void buff(CastScope cast, CastScope.EffectScope effect) {
throw new UnsupportedOperationException("Cannot use Raulebaque as buff effect");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ public void move(FightCell cell) {
this.cell.removeFighter();
}

cell.set(this);
if (cell != null) {
cell.set(this);
}

this.cell = cell;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package fr.quatrevieux.araknemu.game.fight.module;

import fr.quatrevieux.araknemu.core.event.EventsSubscriber;
import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectsHandler;
import fr.quatrevieux.araknemu.game.fight.state.FightState;

/**
* The fight module is used to register new effects, or listeners on the fight for extends its capabilities
* The module instance is dedicated to one fight instance, and can safely be used as state object
*/
public interface FightModule extends EventsSubscriber {
public interface Factory {
/**
* Create the module for the given fight
*/
public FightModule create(Fight fight);
}

/**
* Register fight effects into the effect handle
*/
public void effects(EffectsHandler handler);

/**
* The fight has changed its current state
*/
public void stateChanged(FightState newState);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package fr.quatrevieux.araknemu.game.fight.module;

import fr.quatrevieux.araknemu.core.event.Listener;
import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectsHandler;
import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.shifting.RaulebaqueHandler;
import fr.quatrevieux.araknemu.game.fight.event.FightStarted;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.map.FightCell;
import fr.quatrevieux.araknemu.game.fight.state.FightState;

import java.util.HashMap;
import java.util.Map;

/**
* Module for handle Raulebaque spell
*
* This spell will reset all fighters position to the initial one
*/
final public class RaulebaqueModule implements FightModule {
final private Fight fight;

private Map<Fighter, FightCell> startPositions;

public RaulebaqueModule(Fight fight) {
this.fight = fight;
}

@Override
public void effects(EffectsHandler handler) {
handler.register(784, new RaulebaqueHandler(fight, this));
}

@Override
public void stateChanged(FightState newState) {

}

public Map<Fighter, FightCell> startPositions() {
return startPositions;
}

@Override
public Listener[] listeners() {
return new Listener[] {
new Listener<FightStarted>() {
@Override
public void on(FightStarted event) {
loadStartPositions();
}

@Override
public Class<FightStarted> event() {
return FightStarted.class;
}
}
};
}

/**
* Load the start positions
*/
private void loadStartPositions() {
startPositions = new HashMap<>();

for (Fighter fighter : fight.fighters()) {
startPositions.put(fighter, fighter.cell());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@
import fr.quatrevieux.araknemu.game.item.type.Weapon;
import fr.quatrevieux.araknemu.game.player.GamePlayer;
import fr.quatrevieux.araknemu.game.player.inventory.slot.WeaponSlot;
import fr.quatrevieux.araknemu.game.spell.Spell;
import fr.quatrevieux.araknemu.game.spell.SpellConstraints;
import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect;
import fr.quatrevieux.araknemu.game.spell.effect.area.CellArea;
import fr.quatrevieux.araknemu.game.spell.effect.target.SpellEffectTarget;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.Mockito;

import java.sql.SQLException;
import java.util.ArrayList;
Expand Down Expand Up @@ -120,4 +125,22 @@ public void equipWeapon(GamePlayer player) throws ContainerException, InventoryE
public CastScope makeCastScope(Fighter caster, Castable castable, SpellEffect effect, FightCell target) {
return new CastScope(castable, caster, target).withEffects(Collections.singletonList(effect));
}

public CastScope makeCastScopeForEffect(int effectId) {
return makeCastScopeForEffect(effectId, player.fighter(), other.fighter().cell());
}

public CastScope makeCastScopeForEffect(int effectId, Fighter caster, FightCell target) {
SpellEffect effect = Mockito.mock(SpellEffect.class);
Spell spell = Mockito.mock(Spell.class);
SpellConstraints constraints = Mockito.mock(SpellConstraints.class);

Mockito.when(effect.effect()).thenReturn(effectId);
Mockito.when(effect.area()).thenReturn(new CellArea());
Mockito.when(effect.target()).thenReturn(SpellEffectTarget.DEFAULT);
Mockito.when(spell.constraints()).thenReturn(constraints);
Mockito.when(constraints.freeCell()).thenReturn(false);

return makeCastScope(caster, spell, effect, target);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import fr.quatrevieux.araknemu.core.di.ContainerException;
import fr.quatrevieux.araknemu.core.event.DefaultListenerAggregate;
import fr.quatrevieux.araknemu.core.event.Dispatcher;
import fr.quatrevieux.araknemu.data.world.repository.environment.MapTemplateRepository;
import fr.quatrevieux.araknemu.game.GameBaseCase;
import fr.quatrevieux.araknemu.core.event.ListenerAggregate;
import fr.quatrevieux.araknemu.game.exploration.ExplorationPlayer;
import fr.quatrevieux.araknemu.game.exploration.event.ExplorationPlayerCreated;
Expand All @@ -13,15 +11,17 @@
import fr.quatrevieux.araknemu.game.fight.builder.ChallengeBuilder;
import fr.quatrevieux.araknemu.game.fight.builder.ChallengeBuilderFactory;
import fr.quatrevieux.araknemu.game.fight.event.FightCreated;
import fr.quatrevieux.araknemu.game.fight.module.FightModule;
import fr.quatrevieux.araknemu.game.fight.module.RaulebaqueModule;
import fr.quatrevieux.araknemu.game.fight.type.ChallengeType;
import fr.quatrevieux.araknemu.game.listener.player.exploration.LeaveExplorationForFight;
import fr.quatrevieux.araknemu.game.listener.player.fight.AttachFighter;
import fr.quatrevieux.araknemu.game.player.event.PlayerLoaded;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.*;
Expand All @@ -42,6 +42,9 @@ public void setUp() throws Exception {
dispatcher = new DefaultListenerAggregate(),
Arrays.asList(
new ChallengeBuilderFactory()
),
Arrays.asList(
RaulebaqueModule::new
)
);
}
Expand Down Expand Up @@ -140,4 +143,14 @@ void fightsByMap() throws ContainerException, SQLException {

assertCollectionEquals(service.fightsByMap(10340), fight1, fight2, fight3);
}

@Test
void modules() throws ContainerException {
Fight fight = new Fight(1, new ChallengeType(), service.map(container.get(ExplorationMapService.class).load(10340)), new ArrayList<>());

Collection<FightModule> modules = service.modules(fight);

assertCount(1, modules);
assertContainsType(RaulebaqueModule.class, modules);
}
}
Loading

0 comments on commit 77a3676

Please sign in to comment.