From e520a4e2d566ee7e86225c09166e17c6a883cdf3 Mon Sep 17 00:00:00 2001 From: Vincent Quatrevieux Date: Thu, 8 Jun 2023 18:33:40 +0200 Subject: [PATCH 1/3] feat(fight): Start base for static invocation (#27) --- .../araknemu/game/admin/server/Info.java | 2 +- .../araknemu/game/fight/Fight.java | 17 +- .../araknemu/game/fight/FighterList.java | 126 ++++++++++++ .../araknemu/game/fight/ai/FighterAI.java | 2 +- .../invocations/MonsterInvocationHandler.java | 3 +- .../invocations/StaticInvocationHandler.java | 74 +++++++ .../fight/module/MonsterInvocationModule.java | 4 +- .../game/fight/state/ActiveState.java | 2 +- .../game/fight/state/PlacementState.java | 8 +- .../game/fight/turn/FightTurnList.java | 6 +- .../spectator/SendFightStateToSpectator.java | 4 +- .../game/out/fight/FighterPositions.java | 19 +- .../game/out/fight/action/ActionEffect.java | 12 ++ .../game/out/fight/turn/TurnMiddle.java | 6 +- .../araknemu/game/GameDataSet.java | 4 +- .../game/chat/channel/FightChannelTest.java | 2 +- .../fight/JoinFightAsSpectatorTest.java | 2 +- .../araknemu/game/fight/FightBaseCase.java | 17 +- .../araknemu/game/fight/FightServiceTest.java | 2 +- .../araknemu/game/fight/FightTest.java | 8 +- .../araknemu/game/fight/FighterListTest.java | 181 ++++++++++++++++++ .../FunctionalFromExplorationMapTest.java | 4 +- .../ai/factory/MonsterAiFactoryTest.java | 2 +- .../game/fight/ai/proxy/ProxyAITest.java | 25 +-- .../fight/ai/proxy/ProxyBattlefieldTest.java | 2 +- .../game/fight/builder/BaseBuilderTest.java | 2 +- .../fight/builder/ChallengeBuilderTest.java | 2 +- .../game/fight/builder/FightHandlerTest.java | 2 +- .../game/fight/castable/CastScopeTest.java | 9 +- .../fight/castable/effect/FunctionalTest.java | 79 +++++--- .../StealCharacteristicHandlerTest.java | 32 ++-- .../StealVitalityHandlerTest.java | 48 ++--- .../point/StealActionPointHandlerTest.java | 14 +- .../point/StealMovementPointHandlerTest.java | 14 +- .../heal/GivePercentLifeHandlerTest.java | 6 +- .../MonsterInvocationHandlerTest.java | 4 +- .../StaticInvocationHandlerTest.java | 113 +++++++++++ .../shifting/SwitchPositionApplierTest.java | 2 +- .../shifting/SwitchPositionHandlerTest.java | 2 +- .../SwitchPositionOnAttackHandlerTest.java | 4 +- .../InvocationCountValidatorTest.java | 28 +++ .../generator/PvmRewardsGeneratorTest.java | 2 +- .../module/MonsterInvocationModuleTest.java | 37 ++-- .../game/fight/state/ActiveStateTest.java | 10 +- .../game/fight/state/PlacementStateTest.java | 24 +-- .../game/fight/turn/FightTurnListTest.java | 3 +- .../fight/turn/action/ActionHandlerTest.java | 2 +- .../move/validators/TackleValidatorTest.java | 7 +- .../game/handler/StopSessionTest.java | 2 +- .../game/handler/fight/KickFighterTest.java | 12 +- .../game/handler/fight/LeaveFightTest.java | 10 +- .../fight/option/ToggleLockTeamTest.java | 2 +- .../fight/SendFighterPositionsTest.java | 4 +- .../fight/fighter/LeaveOnDisconnectTest.java | 2 +- ...SendBattlefieldObjectsToSpectatorTest.java | 19 +- .../SendFightStateToSpectatorTest.java | 12 +- .../turn/action/SendFightActionTest.java | 2 +- .../LivingMonsterGroupPositionTest.java | 6 +- .../game/monster/group/MonsterGroupTest.java | 6 +- .../out/fight/action/ActionEffectTest.java | 20 +- .../game/out/fight/turn/TurnMiddleTest.java | 2 +- 61 files changed, 843 insertions(+), 236 deletions(-) create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java create mode 100644 src/test/java/fr/quatrevieux/araknemu/game/fight/FighterListTest.java create mode 100644 src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java diff --git a/src/main/java/fr/quatrevieux/araknemu/game/admin/server/Info.java b/src/main/java/fr/quatrevieux/araknemu/game/admin/server/Info.java index 1b7ddf356..0f13f9e5c 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/admin/server/Info.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/admin/server/Info.java @@ -74,7 +74,7 @@ public void execute(AdminPerformer performer, Void arguments) { performer.info("Online : {} sessions and {} players", gameService.sessions().size(), playerService.online().size()); performer.info("Fights : {} fights with {} fighters", fightService.fights().size(), - fightService.fights().stream().mapToLong(fight -> fight.fighters().size()).sum() + fightService.fights().stream().mapToLong(fight -> fight.fighters().all().size()).sum() ); performer.info( "RAM usage : {} / {}", diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java index 651a231f0..7ae1e6680 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java @@ -57,7 +57,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * Handle fight @@ -75,6 +74,7 @@ public final class Fight implements Dispatcher, Sender { private final ScheduledExecutorService executor; private final Spectators spectators; private final ActionsFactory actions; + private final FighterList fighters; private final Lock executorLock = new ReentrantLock(); private final EffectsHandler effects = new EffectsHandler(); @@ -94,6 +94,7 @@ public Fight(int id, FightType type, FightMap map, List teams this.executor = executor; this.dispatcher = new DefaultListenerAggregate(logger); this.spectators = new Spectators(this); + this.fighters = new FighterList(this); this.actions = actions; } @@ -132,17 +133,8 @@ public FightTeam team(int number) { /** * Get all fighters on the fight */ - public List fighters() { - final FightTurnList turnList = this.turnList; - final Stream fighterStream = turnList != null - ? turnList.fighters().stream() - : teams.stream().flatMap(fightTeam -> fightTeam.fighters().stream()) - ; - - return fighterStream - .filter(Fighter::isOnFight) - .collect(Collectors.toList()) - ; + public FighterList fighters() { + return fighters; } /** @@ -409,6 +401,7 @@ public void destroy() { map.destroy(); attachments.clear(); spectators.clear(); + fighters.clear(); } /** diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java new file mode 100644 index 000000000..0a8c0a164 --- /dev/null +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java @@ -0,0 +1,126 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2023 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight; + +import fr.quatrevieux.araknemu.game.fight.event.FighterRemoved; +import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.map.FightCell; +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.stream.Stream; + +/** + * Handle the fighters list of a fight + */ +public final class FighterList implements Iterable { + private final Fight fight; + private final Set fighters = new LinkedHashSet<>(); + + public FighterList(Fight fight) { + this.fight = fight; + } + + @Override + public @NonNull Iterator iterator() { + return fighters.iterator(); + } + + /** + * Get all fighters as collection. + */ + public Collection all() { + return Collections.unmodifiableCollection(fighters); + } + + /** + * Add a fighter to the fight + * + * @param fighter The fighter to add + * @param cell The cell where the fighter will be placed + * + * @see Fighter#joinFight(Fight, FightCell) Will be called by this method + * @see #joinTurnList(Fighter, FightCell) Call this method if you want to add the fighter to the turn list + */ + public void join(Fighter fighter, FightCell cell) { + fighter.joinFight(fight, cell); + fighters.add(fighter); + } + + /** + * Add a fighter to the fight and to the turn list + * + * Note: this method can only be called if the fight is active, during placement state, use {@link #join(Fighter, FightCell)} instead + * + * @param fighter The fighter to add + * @param cell The cell where the fighter will be placed + * + * @see fr.quatrevieux.araknemu.game.fight.turn.FightTurnList#add(Fighter) Will be called by this method + */ + public void joinTurnList(Fighter fighter, FightCell cell) { + join(fighter, cell); + fight.turnList().add(fighter); + } + + /** + * Remove a fighter from the fight + * Will trigger {@link FighterRemoved} event + * + * Note: if the fighter is on the turn list, it will be removed too + * + * @param fighter The fighter to remove + */ + public void leave(Fighter fighter) { + fighters.remove(fighter); + + if (fight.active()) { + fight.turnList().remove(fighter); // @todo discriminate active vs static fighter + } + + fight.dispatch(new FighterRemoved(fighter, fight)); + } + + /** + * Get a sequential {@code Stream} with this fighter list as its source. + */ + public Stream stream() { + return fighters.stream(); + } + + /** + * Get all alive fighters as stream + * + * @see Fighter#dead() + */ + public Stream alive() { + return fighters.stream().filter(fighter -> !fighter.dead()); + } + + /** + * Internal method for clear all fighters objects. + */ + void clear() { + fighters.clear(); + } +} diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java index 00422b681..b529d7c5f 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java @@ -127,7 +127,7 @@ public BattlefieldMap map() { @Override public Stream fighters() { - return fight.fighters().stream().filter(other -> !other.dead()); + return fight.fighters().alive(); } @Override diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java index 305394bfb..8059c24e3 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java @@ -65,8 +65,7 @@ public void handle(FightCastScope cast, FightCastScope.EffectScope effect) { cast.caster() )); - invocation.joinFight(fight, cast.target()); - fight.turnList().add(invocation); + fight.fighters().joinTurnList(invocation, cast.target()); invocation.init(); diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java new file mode 100644 index 000000000..7f56630d7 --- /dev/null +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java @@ -0,0 +1,74 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2021 Vincent Quatrevieux Jean-Alexandre Valentin + */ + +package fr.quatrevieux.araknemu.game.fight.castable.effect.handler.invocations; + +import fr.quatrevieux.araknemu.game.fight.Fight; +import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; +import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.EffectHandler; +import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; +import fr.quatrevieux.araknemu.game.monster.MonsterService; +import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect; + +/** + * Handle invocation of a static creature + * Unlike {@link MonsterInvocationHandler}, the invoked monster does not appear in timeline, and cannot perform any action + * + * A new fighter will be created and added to fight but not in timeline + * + * Effect parameters : + * - #1 (min) : monster id + * - #2 (max) : grade number + * + * @see InvocationFighter Invoked fighter @todo change + */ +public final class StaticInvocationHandler implements EffectHandler { + private final MonsterService monsterService; + private final FighterFactory fighterFactory; + private final Fight fight; + + public StaticInvocationHandler(MonsterService monsterService, FighterFactory fighterFactory, Fight fight) { + this.monsterService = monsterService; + this.fighterFactory = fighterFactory; + this.fight = fight; + } + + @Override + public void buff(FightCastScope cast, FightCastScope.EffectScope effect) { + throw new UnsupportedOperationException("StaticInvocationHandler cannot be used as buff"); + } + + @Override + public void handle(FightCastScope cast, FightCastScope.EffectScope effect) { + // @todo do not use InvocationFighter + final Fighter invocation = fighterFactory.generate(id -> new InvocationFighter( + id, + monsterService.load(effect.effect().min()).get(effect.effect().max()), + cast.caster().team(), + cast.caster() + )); + + fight.fighters().join(invocation, cast.target()); + invocation.init(); + + fight.send(ActionEffect.addStaticInvocation(cast.caster(), invocation)); + } +} diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModule.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModule.java index 125d2f825..77e19f422 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModule.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModule.java @@ -23,6 +23,7 @@ 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.invocations.MonsterInvocationHandler; +import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.invocations.StaticInvocationHandler; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterDie; @@ -51,6 +52,7 @@ public MonsterInvocationModule(MonsterService monsterService, FighterFactory fig public void effects(EffectsHandler handler) { // moving creatures handler.register(181, new MonsterInvocationHandler(monsterService, fighterFactory, fight)); + handler.register(185, new StaticInvocationHandler(monsterService, fighterFactory, fight)); } @Override @@ -73,7 +75,7 @@ public void on(FighterDie event) { // If the creature is an invocation, delete from turn list if (event.fighter().invoked()) { - fight.turnList().remove(event.fighter()); + fight.fighters().leave(event.fighter()); } } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java index 62f71acf1..7dc67c74f 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/ActiveState.java @@ -137,7 +137,7 @@ public synchronized void leave(Fighter fighter) { } fighter.team().kick(fighter); - fight.turnList().remove(fighter); + fight.fighters().leave(fighter); final FightRewardsSheet rewardsSheet = fight.type().rewards().generate( new EndFightResults( diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java index 3065932c2..40acedc76 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/state/PlacementState.java @@ -22,6 +22,7 @@ import fr.quatrevieux.araknemu.core.event.EventsSubscriber; import fr.quatrevieux.araknemu.core.event.Listener; import fr.quatrevieux.araknemu.game.fight.Fight; +import fr.quatrevieux.araknemu.game.fight.FighterList; import fr.quatrevieux.araknemu.game.fight.JoinFightError; import fr.quatrevieux.araknemu.game.fight.ending.EndFightResults; import fr.quatrevieux.araknemu.game.fight.ending.reward.FightRewardsSheet; @@ -29,7 +30,6 @@ import fr.quatrevieux.araknemu.game.fight.event.FightLeaved; import fr.quatrevieux.araknemu.game.fight.event.FighterAdded; import fr.quatrevieux.araknemu.game.fight.event.FighterPlaceChanged; -import fr.quatrevieux.araknemu.game.fight.event.FighterRemoved; import fr.quatrevieux.araknemu.game.fight.exception.FightException; import fr.quatrevieux.araknemu.game.fight.exception.FightMapException; import fr.quatrevieux.araknemu.game.fight.exception.InvalidFightStateException; @@ -289,8 +289,10 @@ private void punishDeserter(Fighter fighter) { @RequiresNonNull("fight") @SuppressWarnings("dereference.of.nullable") // cellsGenerators.get(fighter.team()) cannot be null private void addFighters(Collection fighters) { + final FighterList fightersList = fight.fighters(); + for (Fighter fighter : fighters) { - fighter.joinFight(fight, NullnessUtil.castNonNull(cellsGenerators).get(fighter.team()).next()); + fightersList.join(fighter, NullnessUtil.castNonNull(cellsGenerators).get(fighter.team()).next()); } for (Fighter fighter : fighters) { @@ -307,8 +309,8 @@ private void addFighters(Collection fighters) { */ @RequiresNonNull("fight") private void removeFighter(Fighter fighter) { + fight.fighters().leave(fighter); fighter.dispatch(new FightLeaved()); - fight.dispatch(new FighterRemoved(fighter, fight)); } /** diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java index ce8d7342b..5c69bfe05 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java @@ -21,6 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.event.NextTurnInitiated; import fr.quatrevieux.araknemu.game.fight.turn.event.TurnListChanged; import fr.quatrevieux.araknemu.game.fight.turn.order.FighterOrderStrategy; @@ -28,7 +29,6 @@ import org.checkerframework.checker.nullness.util.NullnessUtil; import java.util.List; -import java.util.NoSuchElementException; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; @@ -73,7 +73,7 @@ public void remove(Fighter fighter) { final int index = fighters.indexOf(fighter); if (index == -1) { - throw new NoSuchElementException("Fighter " + fighter.id() + " is not found on the turn list"); + return; } fighters.remove(index); @@ -95,6 +95,8 @@ public void remove(Fighter fighter) { /** * Add a fighter after the current one * + * Note: this method should not be called directly, use {@link fr.quatrevieux.araknemu.game.fight.FighterList#joinTurnList(Fighter, FightCell)} instead + * * @param fighter Fighter to add * * @see TurnListChanged Event triggered after the list is updated diff --git a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectator.java b/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectator.java index 0fb3c4622..f0865022b 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectator.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectator.java @@ -21,6 +21,7 @@ import fr.quatrevieux.araknemu.core.event.Listener; import fr.quatrevieux.araknemu.game.fight.Fight; +import fr.quatrevieux.araknemu.game.fight.FighterList; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buff; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; @@ -36,7 +37,6 @@ import fr.quatrevieux.araknemu.network.game.out.fight.turn.TurnMiddle; import fr.quatrevieux.araknemu.network.game.out.game.AddSprites; -import java.util.List; import java.util.stream.Collectors; /** @@ -52,7 +52,7 @@ public SendFightStateToSpectator(Spectator spectator) { @Override public void on(StartWatchFight event) { final Fight fight = spectator.fight(); - final List fighters = fight.fighters(); + final FighterList fighters = fight.fighters(); spectator.send(new JoinFightAsSpectator(fight)); spectator.send( diff --git a/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/FighterPositions.java b/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/FighterPositions.java index ada5f60c8..e3d4777bc 100644 --- a/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/FighterPositions.java +++ b/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/FighterPositions.java @@ -21,9 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; -import java.util.Collection; import java.util.Collections; -import java.util.stream.Collectors; /** * Send all fighters positions @@ -31,23 +29,24 @@ * https://github.com/Emudofus/Dofus/blob/1.29/dofus/aks/Game.as#L193 */ public final class FighterPositions { - private final Collection fighters; + private final Iterable fighters; public FighterPositions(FighterData fighter) { this(Collections.singleton(fighter)); } - public FighterPositions(Collection fighters) { + public FighterPositions(Iterable fighters) { this.fighters = fighters; } @Override public String toString() { - return - "GIC|" + - fighters.stream() - .map(fighter -> fighter.id() + ";" + fighter.cell().id()) - .collect(Collectors.joining("|")) - ; + final StringBuilder sb = new StringBuilder("GIC"); + + for (FighterData fighter : fighters) { + sb.append('|').append(fighter.id()).append(';').append(fighter.cell().id()); + } + + return sb.toString(); } } diff --git a/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffect.java b/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffect.java index 2ad61a4ea..edce954a2 100644 --- a/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffect.java +++ b/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffect.java @@ -353,6 +353,18 @@ public static ActionEffect addInvocation(FighterData caster, FighterData invocat return new ActionEffect(181, caster, "+" + invocation.sprite()); } + /** + * Add an invoked static creature to the fight + * Unlike {@link #addInvocation(FighterData, FighterData)}, the client will take this creature in account + * for invocations count limit + * + * @param caster Invoker + * @param invocation Invocation to add + */ + public static ActionEffect addStaticInvocation(FighterData caster, FighterData invocation) { + return new ActionEffect(185, caster, "+" + invocation.sprite()); + } + /** * A glyph has been triggered by a fighter * diff --git a/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddle.java b/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddle.java index 1bef863ec..50d1f3ef3 100644 --- a/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddle.java +++ b/src/main/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddle.java @@ -22,17 +22,15 @@ import fr.quatrevieux.araknemu.data.constant.Characteristic; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; -import java.util.Collection; - /** * Send fighters information between two turns * * https://github.com/Emudofus/Dofus/blob/1.29/dofus/aks/Game.as#L326 */ public final class TurnMiddle { - private final Collection fighters; + private final Iterable fighters; - public TurnMiddle(Collection fighters) { + public TurnMiddle(Iterable fighters) { this.fighters = fighters; } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java b/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java index a9b94ed3c..910ebc550 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/GameDataSet.java @@ -540,6 +540,7 @@ public GameDataSet pushFunctionalSpells() throws SQLException, ContainerExceptio "(1493, 'Explosion de masse', -1, '0,0,0', '97,2,10,,0,0,2d5+0||2|1|1|0|100|true|true|false|false|0|0|3|0|Cc||18;19;3;1;41|0|false', '97,4,12,,0,0,2d5+2||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,6,14,,0,0,2d5+4||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,7,15,,0,0,2d5+5||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,9,17,,0,0,2d5+7||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '97,13,21,,0,0,2d5+11||0|0|0|0|0|false|true|false|false|0|0|0|0|Cc||18;19;3;1;41|0|false', '')", "(16, 'Science du bâton', 101, '10,1,1', '142,5,,,5,0,0d0+5|142,7,,,5,0,0d0+7|3|0|1|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,6,,,5,0,0d0+6|142,8,,,5,0,0d0+8|3|0|2|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,8,,,5,0,0d0+8|142,11,,,5,0,0d0+11|3|0|3|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,10,,,5,0,0d0+10|142,15,,,5,0,0d0+15|3|0|4|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,15,,,5,0,0d0+15|142,20,,,5,0,0d0+20|3|0|5|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|42|false', '142,25,,,5,0,0d0+25|142,30,,,5,0,0d0+30|2|0|6|40|100|false|false|false|true|0|0|0|6|PaPa||18;19;3;1;41|142|false', '')", "(197, 'Puissance Sylvestre', 0, '10,1,1', '149,,,8005,2,0;169,100,,,2,0,0d0+100;183,1000,,,2,0,0d0+1000;184,1000,,,2,0,0d0+1000;168,100,,,2,0,0d0+100;108,10,,,2,0,0d0+10||6|0|1|0|100|true|false|false|true|0|0|0|15|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,2,0;169,100,,,2,0,0d0+100;183,1000,,,2,0,0d0+1000;184,1000,,,2,0,0d0+1000;168,100,,,2,0,0d0+100;108,11,,,2,0,0d0+11||5|0|2|0|100|true|false|false|true|0|0|0|14|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,3,0;169,100,,,3,0,0d0+100;183,1000,,,3,0,0d0+1000;184,1000,,,3,0,0d0+1000;168,100,,,3,0,0d0+100;108,12,,,3,0,0d0+12||5|0|3|0|100|true|false|false|true|0|0|0|13|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,3,0;169,100,,,3,0,0d0+100;183,1000,,,3,0,0d0+1000;184,1000,,,3,0,0d0+1000;168,100,,,3,0,0d0+100;108,13,,,3,0,0d0+13||4|0|4|0|100|true|false|false|true|0|0|0|12|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,4,0;169,100,,,4,0,0d0+100;183,1000,,,4,0,0d0+1000;184,1000,,,4,0,0d0+1000;168,100,,,4,0,0d0+100;108,14,,,4,0,0d0+14||3|0|5|0|100|true|false|false|true|0|0|0|11|PaPaPaPaPaPa||8;18;19;3;1;41|17|false', '149,,,8005,4,0;169,100,,,4,0,0d0+100;183,1000,,,4,0,0d0+1000;184,1000,,,4,0,0d0+1000;168,100,,,4,0,0d0+100;108,16,,,4,0,0d0+16||2|0|6|0|100|true|false|false|true|0|0|0|10|PaPaPaPaPaPa||8;18;19;3;1;41|117|false', '4;4;4;4;4;4;5;5;5;5;5;5')", + "(186, 'Arbre', 1100, '11,1,1', '185,282,1,,0,0||6|1|1|0|100|false|true|true|true|0|0|0|10|Pa||18;19;3;1;41|42|false', '185,282,2,,0,0||5|1|2|0|100|false|true|true|true|0|0|0|9|Pa||18;19;3;1;41|42|false', '185,282,3,,0,0||5|1|3|0|100|false|true|true|true|0|0|0|8|Pa||18;19;3;1;41|42|false', '185,282,4,,0,0||5|1|4|0|100|false|true|true|true|0|0|0|7|Pa||18;19;3;1;41|42|false', '185,282,5,,0,0||4|1|5|0|100|false|true|true|true|0|0|0|6|Pa||18;19;3;1;41|42|false', '185,282,6,,0,0||3|1|6|0|100|false|true|true|true|0|0|0|3|Pa||18;19;3;1;41|142|false', '')", }, ",") + ";" ); @@ -935,7 +936,8 @@ public GameDataSet pushMonsterTemplateInvocations() throws SQLException, Contain connection.query( "INSERT OR IGNORE INTO `MONSTER_TEMPLATE` (`MONSTER_ID`, `MONSTER_NAME`, `GFXID`, `COLORS`, `AI`, `CHARACTERISTICS`, `LIFE_POINTS`, `INITIATIVES`, `SPELLS`) VALUES " + - "(36, 'Bouftou', 1566, '-1,-1,-1', 'AGGRESSIVE', '1@v:p;1f:-c;17:6;1b:-1i;s:f;t:f;a:2g;c:1s;f:2g;d:2g;e:26;8:5;9:3;|2@v:u;1f:-a;17:7;1b:-1d;s:g;t:g;a:2l;c:21;f:2l;d:2l;e:2b;8:5;9:3;|3@v:13;1f:-9;17:8;1b:-18;s:h;t:h;a:2q;c:26;f:2q;d:2q;e:2b;8:5;9:3;|4@v:18;1f:-8;17:9;1b:-13;s:i;t:i;a:2v;c:2l;f:2v;d:2v;e:2b;8:5;9:3;|5@v:1d;1f:-7;17:a;1b:-u;s:k;t:k;a:34;c:2q;f:34;d:34;e:2g;8:5;9:4;|6@v:1i;1f:-6;17:c;1b:-p;s:p;t:p;a:4m;c:4m;f:4m;d:7q;e:7q;8:6;9:4;', '30|40|50|60|70|140', '12|15|20|21|23|25', '2000@1;202@1;1709@1|2000@2;202@2;1709@2|2000@3;202@3;1709@3|2000@4;202@4;1709@4|2000@5;202@5;1709@5|2000@6;1709@6')" + "(36, 'Bouftou', 1566, '-1,-1,-1', 'AGGRESSIVE', '1@v:p;1f:-c;17:6;1b:-1i;s:f;t:f;a:2g;c:1s;f:2g;d:2g;e:26;8:5;9:3;|2@v:u;1f:-a;17:7;1b:-1d;s:g;t:g;a:2l;c:21;f:2l;d:2l;e:2b;8:5;9:3;|3@v:13;1f:-9;17:8;1b:-18;s:h;t:h;a:2q;c:26;f:2q;d:2q;e:2b;8:5;9:3;|4@v:18;1f:-8;17:9;1b:-13;s:i;t:i;a:2v;c:2l;f:2v;d:2v;e:2b;8:5;9:3;|5@v:1d;1f:-7;17:a;1b:-u;s:k;t:k;a:34;c:2q;f:34;d:34;e:2g;8:5;9:4;|6@v:1i;1f:-6;17:c;1b:-p;s:p;t:p;a:4m;c:4m;f:4m;d:7q;e:7q;8:6;9:4;', '30|40|50|60|70|140', '12|15|20|21|23|25', '2000@1;202@1;1709@1|2000@2;202@2;1709@2|2000@3;202@3;1709@3|2000@4;202@4;1709@4|2000@5;202@5;1709@5|2000@6;1709@6')," + + "(282, 'Arbre', 1183, '-1,-1,-1', 'AGGRESSIVE', '1@v:u;13:u;1f:u;17:-k;1b:-k;a:2g;f:2g;d:2g;|2@v:13;13:13;1f:13;17:-j;1b:-j;a:2l;f:2l;d:2l;|3@v:18;13:18;1f:18;17:-i;1b:-i;a:2q;f:2q;d:2q;|4@v:1n;13:1n;1f:1n;17:1n;1b:-1d;a:2v;f:2v;d:2v;|5@v:1n;13:1n;1f:1n;17:1n;1b:-1d;a:34;f:34;d:34;|6@v:1n;13:1n;1f:1n;17:p;1b:-p;s:-p;t:-p;a:au;f:au;d:au;', '100|150|200|250|300|350', '1|1|1|1|1|1', '|||||')" ); use(MonsterRewardData.class, MonsterRewardItem.class); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/chat/channel/FightChannelTest.java b/src/test/java/fr/quatrevieux/araknemu/game/chat/channel/FightChannelTest.java index c8388e934..358b125c7 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/chat/channel/FightChannelTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/chat/channel/FightChannelTest.java @@ -98,7 +98,7 @@ void sendToFightShouldAlsoSendToSpectators() throws Exception { Spectator spectator = new Spectator(gamePlayer(), fight); spectator.join(); - PlayerFighter fighter = PlayerFighter.class.cast(fight.fighters().get(0)); + PlayerFighter fighter = PlayerFighter.class.cast(fight.team(0).leader()); GamePlayer from = fighter.player(); from.start(fighter); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/exploration/interaction/action/fight/JoinFightAsSpectatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/exploration/interaction/action/fight/JoinFightAsSpectatorTest.java index 4046276df..403882d5c 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/exploration/interaction/action/fight/JoinFightAsSpectatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/exploration/interaction/action/fight/JoinFightAsSpectatorTest.java @@ -121,7 +121,7 @@ void success() throws InterruptedException, SQLException { fight.turnList().start(); BattlefieldObject bo = Mockito.mock(BattlefieldObject.class); - Mockito.when(bo.caster()).thenReturn(fight.fighters().get(0)); + Mockito.when(bo.caster()).thenReturn(getFighter(0)); Mockito.when(bo.cell()).thenReturn(fight.map().get(123)); Mockito.when(bo.size()).thenReturn(2); Mockito.when(bo.color()).thenReturn(1); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/FightBaseCase.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/FightBaseCase.java index c31eeaf08..702d4864b 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/FightBaseCase.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/FightBaseCase.java @@ -96,6 +96,7 @@ public class FightBaseCase extends GameBaseCase { protected GamePlayer player; protected GamePlayer other; protected ScheduledExecutorService executor; + private Fight lastCreatedFight; private int lastPlayerId = 5; @@ -117,11 +118,12 @@ public void tearDown() throws ContainerException { executor.shutdownNow(); super.tearDown(); + lastCreatedFight = null; } public Fight createFight(boolean init) throws Exception { FightMap map; - Fight fight = new Fight( + Fight fight = lastCreatedFight = new Fight( 1, new ChallengeType(configuration.fight()), map = loadFightMap(10340), @@ -152,7 +154,7 @@ public Fight createFight(boolean init) throws Exception { public Fight createPvmFight() throws Exception { FightMap map; - Fight fight = new Fight( + Fight fight = lastCreatedFight = new Fight( 1, container.get(PvmType.class), map = loadFightMap(10340), @@ -236,7 +238,7 @@ public Fight createSimpleFight(ExplorationMap map) throws ContainerException, SQ GamePlayer player1 = makeSimpleGamePlayer(++lastPlayerId); GamePlayer player2 = makeSimpleGamePlayer(++lastPlayerId); - return container.get(FightService.class) + return lastCreatedFight = container.get(FightService.class) .handler(ChallengeBuilder.class) .start(builder -> builder .map(map) @@ -283,6 +285,13 @@ public PlayerFighter makePlayerFighter(GamePlayer player) throws ContainerExcept return container.get(FighterFactory.class).create(player); } + /** + * Get a fighter by its index in the turn list. + */ + public Fighter getFighter(int index) { + return lastCreatedFight.turnList().fighters().get(index); + } + public FightBuilder fightBuilder() { return new FightBuilder(); } @@ -391,7 +400,7 @@ public Class event() { fight.nextState(); } - return fight; + return lastCreatedFight = fight; } private FightTeam.Factory buildTeam(int number, List fighters) { diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/FightServiceTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/FightServiceTest.java index 81ca6f34a..21433b8cc 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/FightServiceTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/FightServiceTest.java @@ -135,7 +135,7 @@ void gameStoppedListenerShouldCancelFight() throws Exception { assertTrue(service.fightsByMap(fight.map().id()).isEmpty()); assertCount(0, fight.teams()); - assertCount(0, fight.fighters()); + assertCount(0, fight.fighters().all()); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/FightTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/FightTest.java index fe52d8afb..d05773a03 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/FightTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/FightTest.java @@ -135,14 +135,14 @@ void getters() { @Test void fighters() { - assertCount(0, fight.fighters()); + assertCount(0, fight.fighters().all()); new PlacementState().start(fight); - assertEquals(Arrays.asList(fighter1, fighter2), fight.fighters()); + assertIterableEquals(Arrays.asList(fighter1, fighter2), fight.fighters()); fight.start(new AlternateTeamFighterOrder()); - assertEquals(Arrays.asList(fighter1, fighter2), fight.fighters()); + assertIterableEquals(Arrays.asList(fighter1, fighter2), fight.fighters()); } @Test @@ -375,7 +375,7 @@ void cancel() { assertSame(fight, ref.get().fight()); assertCount(0, fight.teams()); - assertCount(0, fight.fighters()); + assertCount(0, fight.fighters().all()); assertFalse(fight.alive()); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/FighterListTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/FighterListTest.java new file mode 100644 index 000000000..3169cf079 --- /dev/null +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/FighterListTest.java @@ -0,0 +1,181 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2023 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight; + +import fr.quatrevieux.araknemu.game.fight.event.FighterRemoved; +import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; +import fr.quatrevieux.araknemu.game.fight.turn.order.AlternateTeamFighterOrder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class FighterListTest extends FightBaseCase { + private Fight fight; + private FighterList fighterList; + + @BeforeEach + @Override + public void setUp() throws Exception { + super.setUp(); + + fight = createFight(); + fighterList = fight.fighters(); + } + + @Test + void join() throws SQLException { + Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + fighterList.join(fighter, fight.map().get(146)); + + assertSame(fight.map().get(146), fighter.cell()); + assertSame(fighter, fight.map().get(146).fighter()); + assertContains(fighter, fighterList.all()); + + boolean found = false; + + for(Fighter f : fighterList){ + if(f == fighter){ + found = true; + break; + } + } + + assertTrue(found); + } + + @Test + void joinOnStartedFightShouldNotAddToTurnList() throws SQLException { + fight.nextState(); + + Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + fighterList.join(fighter, fight.map().get(146)); + + assertSame(fight.map().get(146), fighter.cell()); + assertSame(fighter, fight.map().get(146).fighter()); + assertContains(fighter, fighterList.all()); + assertFalse(fight.turnList().fighters().contains(fighter)); + + boolean found = false; + + for(Fighter f : fighterList){ + if(f == fighter){ + found = true; + break; + } + } + + assertTrue(found); + } + + @Test + void joinTurnList() throws SQLException { + fight.nextState(); + + Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + fighterList.joinTurnList(fighter, fight.map().get(146)); + + assertSame(fight.map().get(146), fighter.cell()); + assertSame(fighter, fight.map().get(146).fighter()); + assertContains(fighter, fighterList.all()); + assertTrue(fight.turnList().fighters().contains(fighter)); + + boolean found = false; + + for(Fighter f : fighterList){ + if(f == fighter){ + found = true; + break; + } + } + + assertTrue(found); + } + + @Test + void leaveNotStarted() throws SQLException { + AtomicReference ref = new AtomicReference<>(); + fight.dispatcher().add(FighterRemoved.class, ref::set); + + Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + fighterList.join(fighter, fight.map().get(146)); + assertContains(fighter, fighterList.all()); + + fighterList.leave(fighter); + + assertFalse(fighterList.all().contains(fighter)); + assertSame(fighter, ref.get().fighter()); + assertSame(fight, ref.get().fight()); + + boolean found = false; + + for(Fighter f : fighterList){ + if(f == fighter){ + found = true; + break; + } + } + + assertFalse(found); + } + + @Test + void leaveStarted() throws SQLException { + fight.nextState(); + + AtomicReference ref = new AtomicReference<>(); + fight.dispatcher().add(FighterRemoved.class, ref::set); + + Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + fighterList.joinTurnList(fighter, fight.map().get(146)); + assertContains(fighter, fighterList.all()); + + fighterList.leave(fighter); + + assertFalse(fighterList.all().contains(fighter)); + assertFalse(fight.turnList().fighters().contains(fighter)); + assertSame(fighter, ref.get().fighter()); + assertSame(fight, ref.get().fight()); + } + + @Test + void alive() throws SQLException { + fight.nextState(); + + Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + fighterList.join(fighter, fight.map().get(146)); + fighter.init(); + + assertContains(fighter, fighterList.alive().collect(Collectors.toList())); + assertContains(fighter, fighterList.all()); + + fighter.life().kill(fighter); + + assertFalse(fighterList.alive().collect(Collectors.toList()).contains(fighter)); + assertContains(fighter, fighterList.all()); + } +} diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalFromExplorationMapTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalFromExplorationMapTest.java index 7367bc8f9..5a356e464 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalFromExplorationMapTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalFromExplorationMapTest.java @@ -90,7 +90,7 @@ void joinFightWillRemoveSpriteFromMap() throws Exception { assertFalse(other.isExploring()); assertFalse(map.creatures().contains(explorationPlayer)); assertTrue(other.isFighting()); - assertContains(otherFighter, fight.fighters()); + assertContains(otherFighter, fight.fighters().all()); assertContains(otherFighter, fight.team(0).fighters()); requestStack.assertAll( @@ -113,7 +113,7 @@ void leaveFightWillRemoveFromTeam() throws Exception { fight.state(PlacementState.class).leave(otherFighter); assertFalse(other.isFighting()); - assertFalse(fight.fighters().contains(otherFighter)); + assertFalse(fight.fighters().all().contains(otherFighter)); requestStack.assertAll( new RemoveTeamFighters(fight.team(0), Collections.singleton(otherFighter)) diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java index 7580229c2..038dd57ac 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java @@ -67,7 +67,7 @@ void createSuccessWithInvocation() throws SQLException { -1, container.get(MonsterService.class).load(36).get(3), fight.team(1), - fight.fighters().get(0) + fight.team(0).leader() ); fighter.joinFight(fight, fight.map().get(123)); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyAITest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyAITest.java index 9f2fa5ebd..4d7088103 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyAITest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyAITest.java @@ -19,6 +19,7 @@ package fr.quatrevieux.araknemu.game.fight.ai.proxy; +import fr.quatrevieux.araknemu.data.constant.Characteristic; import fr.quatrevieux.araknemu.game.fight.ai.AiBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.turn.Turn; @@ -39,8 +40,8 @@ class ProxyAITest extends AiBaseCase { @Test void baseProxy() { configureFight(fb -> fb - .addSelf(builder -> builder.cell(152)) - .addEnemy(builder -> builder.cell(167)) + .addSelf(builder -> builder.cell(152).charac(Characteristic.STRENGTH, 100)) + .addEnemy(builder -> builder.cell(167).charac(Characteristic.STRENGTH, 50)) .addAlly(builder -> builder.cell(166)) ); @@ -61,7 +62,7 @@ void baseProxy() { assertSame(proxy.fighter(), fighters.get(0)); assertInstanceOf(ProxyPassiveFighter.class, fighters.get(1)); assertInstanceOf(ProxyPassiveFighter.class, fighters.get(2)); - assertSame(proxy.enemy().get(), fighters.get(1)); + assertSame(proxy.enemy().get(), fighters.get(2)); assertSame(proxy.fighter().cell(), ai.fighter().cell()); assertSame(ai.map().get(fighters.get(1).cell().id()), fighters.get(1).cell()); @@ -101,7 +102,7 @@ void withPosition() { assertSame(proxy.fighter(), fighters.get(0)); assertInstanceOf(ProxyPassiveFighter.class, fighters.get(1)); assertInstanceOf(ProxyPassiveFighter.class, fighters.get(2)); - assertSame(proxy.enemy().get(), fighters.get(1)); + assertSame(proxy.enemy().get(), fighters.get(2)); assertNotSame(proxy.fighter().cell(), ai.fighter().cell()); assertNotSame(ai.map().get(fighters.get(1).cell().id()), fighters.get(1).cell()); @@ -110,11 +111,11 @@ void withPosition() { assertEquals(123, proxy.fighter().cell().id()); assertSame(proxy.map().get(123), proxy.fighter().cell()); assertSame(proxy.fighter(), proxy.fighter().cell().fighter()); - assertEquals(167, fighters.get(1).cell().id()); - assertSame(proxy.map().get(167), fighters.get(1).cell()); + assertEquals(166, fighters.get(1).cell().id()); + assertSame(proxy.map().get(166), fighters.get(1).cell()); assertSame(fighters.get(1), fighters.get(1).cell().fighter()); - assertEquals(166, fighters.get(2).cell().id()); - assertSame(proxy.map().get(166), fighters.get(2).cell()); + assertEquals(167, fighters.get(2).cell().id()); + assertSame(proxy.map().get(167), fighters.get(2).cell()); assertSame(fighters.get(2), fighters.get(2).cell().fighter()); assertFalse(proxy.map().get(152).hasFighter()); @@ -128,11 +129,11 @@ void withPosition() { assertEquals(125, proxy.fighter().cell().id()); assertSame(proxy.map().get(125), proxy.fighter().cell()); assertSame(proxy.fighter(), proxy.fighter().cell().fighter()); - assertEquals(167, fighters.get(1).cell().id()); - assertSame(proxy.map().get(167), fighters.get(1).cell()); + assertEquals(166, fighters.get(1).cell().id()); + assertSame(proxy.map().get(166), fighters.get(1).cell()); assertSame(fighters.get(1), fighters.get(1).cell().fighter()); - assertEquals(166, fighters.get(2).cell().id()); - assertSame(proxy.map().get(166), fighters.get(2).cell()); + assertEquals(167, fighters.get(2).cell().id()); + assertSame(proxy.map().get(167), fighters.get(2).cell()); assertSame(fighters.get(2), fighters.get(2).cell().fighter()); assertFalse(proxy.map().get(123).hasFighter()); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyBattlefieldTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyBattlefieldTest.java index 027526e5d..2a542b7aa 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyBattlefieldTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyBattlefieldTest.java @@ -79,7 +79,7 @@ void modifyWithFreeCell() { assertTrue(modified.get(152).walkable()); assertFalse(modified.get(152).sightBlocking()); - assertSame(ai.fighters().collect(Collectors.toList()).get(2), modified.get(166).fighter()); + assertSame(ai.fighters().collect(Collectors.toList()).get(1), modified.get(166).fighter()); assertTrue(modified.get(166).walkableIgnoreFighter()); assertFalse(modified.get(166).walkable()); assertTrue(modified.get(166).sightBlocking()); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/BaseBuilderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/BaseBuilderTest.java index 2179bb789..e240d01b8 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/BaseBuilderTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/BaseBuilderTest.java @@ -80,7 +80,7 @@ void buildSimple() throws Exception { assertCount(1, fight.team(0).fighters()); assertCount(1, fight.team(1).fighters()); assertContainsOnly(SimpleTeam.class, fight.teams()); - assertContainsOnly(PlayerFighter.class, fight.fighters()); + assertContainsOnly(PlayerFighter.class, fight.fighters().all()); assertEquals(1, fight.id()); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/ChallengeBuilderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/ChallengeBuilderTest.java index 930030217..e99bd4025 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/ChallengeBuilderTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/ChallengeBuilderTest.java @@ -67,7 +67,7 @@ void buildSimple() throws Exception { assertCount(1, fight.team(0).fighters()); assertCount(1, fight.team(1).fighters()); assertContainsOnly(SimpleTeam.class, fight.teams()); - assertContainsOnly(PlayerFighter.class, fight.fighters()); + assertContainsOnly(PlayerFighter.class, fight.fighters().all()); assertEquals(1, fight.id()); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/FightHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/FightHandlerTest.java index 4b9aa0687..72a163600 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/FightHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/builder/FightHandlerTest.java @@ -85,7 +85,7 @@ void withChallengeFight() throws ContainerException { assertInstanceOf(ChallengeType.class, fight.type()); assertInstanceOf(PlacementState.class, fight.state()); assertCount(2, fight.teams()); - assertCount(2, fight.fighters()); + assertCount(2, fight.fighters().all()); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java index 55d6ebfbe..3ffc5bba2 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java @@ -39,6 +39,7 @@ import org.mockito.Mockito; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -488,7 +489,7 @@ void replaceTargetChaining() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); @@ -520,7 +521,7 @@ void replaceTargetChainingWithRecursionOnFirstTarget() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); @@ -553,7 +554,7 @@ void replaceTargetChainingWithRecursionOnMiddleTarget() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); @@ -586,7 +587,7 @@ void removeTargetWithReplaceTargetChain() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java index a915f6786..f01c585da 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java @@ -58,6 +58,7 @@ import org.junit.jupiter.api.Test; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -514,18 +515,18 @@ void switchOnAttackWithChaining() { .build(true) ; - List fighters = fight.fighters(); - fight.state(PlacementState.class).startFight(); fight.turnList().start(); + List fighters = fight.turnList().fighters(); + castNormal(440, fight.map().get(271)); // Sacrifice fighters.get(0).turn().stop(); - fighters.get(3).turn().stop(); + fighters.get(1).turn().stop(); castNormal(440, fight.map().get(211)); // Sacrifice - fighters.get(1).turn().stop(); fighters.get(2).turn().stop(); + fighters.get(3).turn().stop(); fighters.get(0).turn().stop(); castNormal(183, fight.map().get(211)); // Simple attack @@ -535,12 +536,12 @@ void switchOnAttackWithChaining() { assertBetween(10, 17, fighters.get(0).life().max() - fighters.get(0).life().current()); assertEquals(211, fighters.get(0).cell().id()); - assertEquals(328, fighters.get(1).cell().id()); - assertEquals(271, fighters.get(2).cell().id()); + assertEquals(328, fighters.get(2).cell().id()); + assertEquals(271, fighters.get(3).cell().id()); - requestStack.assertOne(ActionEffect.teleport(fighters.get(1), fighters.get(2), fight.map().get(271))); - requestStack.assertOne(ActionEffect.teleport(fighters.get(1), fighters.get(1), fight.map().get(211))); - requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(1), fight.map().get(328))); + requestStack.assertOne(ActionEffect.teleport(fighters.get(2), fighters.get(3), fight.map().get(271))); + requestStack.assertOne(ActionEffect.teleport(fighters.get(2), fighters.get(2), fight.map().get(211))); + requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(2), fight.map().get(328))); requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(0), fight.map().get(211))); } @@ -555,11 +556,11 @@ void switchOnAttackWithSpellReturn() { .build(true) ; - List fighters = fight.fighters(); - fight.state(PlacementState.class).startFight(); fight.turnList().start(); + List fighters = fight.turnList().fighters(); + castNormal(440, fight.map().get(271)); // Sacrifice castNormal(4, fight.map().get(328)); // Renvoi de Sort fighters.get(0).turn().stop(); @@ -567,13 +568,13 @@ void switchOnAttackWithSpellReturn() { castNormal(183, fight.map().get(271)); // Simple attack assertEquals(fighters.get(0).life().max(), fighters.get(0).life().current()); - assertEquals(fighters.get(1).life().max(), fighters.get(1).life().current()); - assertBetween(10, 17, fighters.get(2).life().max() - fighters.get(2).life().current()); + assertEquals(fighters.get(2).life().max(), fighters.get(2).life().current()); + assertBetween(10, 17, fighters.get(1).life().max() - fighters.get(1).life().current()); assertEquals(271, fighters.get(0).cell().id()); - assertEquals(328, fighters.get(1).cell().id()); + assertEquals(328, fighters.get(2).cell().id()); - requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(1), fight.map().get(328))); + requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(2), fight.map().get(328))); requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(0), fight.map().get(271))); requestStack.assertOne(ActionEffect.returnSpell(fighters.get(0), true)); } @@ -644,36 +645,36 @@ void switchOnAttackAndReflectDamage() { .build(true) ; - List fighters = fight.fighters(); - fight.state(PlacementState.class).startFight(); fight.turnList().start(); + List fighters = fight.turnList().fighters(); + castNormal(440, fight.map().get(271)); // Sacrifice fighters.get(0).turn().stop(); - fighters.get(3).turn().stop(); + fighters.get(1).turn().stop(); castNormal(183, fight.map().get(256)); // Simple attack - assertTrue(fighters.get(1).life().isFull()); assertTrue(fighters.get(2).life().isFull()); + assertTrue(fighters.get(3).life().isFull()); int damage = fighters.get(0).life().max() - fighters.get(0).life().current(); assertBetween(16, 18, damage); - assertEquals(256, fighters.get(1).cell().id()); - assertEquals(328, fighters.get(2).cell().id()); + assertEquals(256, fighters.get(2).cell().id()); + assertEquals(328, fighters.get(3).cell().id()); assertEquals(271, fighters.get(0).cell().id()); // Damage reflected to himself requestStack.assertOne(ActionEffect.reflectedDamage(fighters.get(0), 1)); - requestStack.assertOne(ActionEffect.alterLifePoints(fighters.get(1), fighters.get(0), -damage + 1)); + requestStack.assertOne(ActionEffect.alterLifePoints(fighters.get(2), fighters.get(0), -damage + 1)); requestStack.assertOne(ActionEffect.alterLifePoints(fighters.get(0), fighters.get(0), -1)); // Position switches - requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(2), fight.map().get(328))); + requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(3), fight.map().get(328))); requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(0), fight.map().get(256))); - requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(1), fight.map().get(256))); + requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(2), fight.map().get(256))); requestStack.assertOne(ActionEffect.teleport(fighters.get(0), fighters.get(0), fight.map().get(271))); } @@ -1197,7 +1198,7 @@ void invocation() throws SQLException { requestStack.assertOne(new ActionEffect(181, fighter1, "+" + invocation.sprite())); requestStack.assertOne(new ActionEffect(999, fighter1, (new FighterTurnOrder(fight.turnList())).toString())); - assertTrue(fight.fighters().contains(invocation)); + assertTrue(fight.fighters().all().contains(invocation)); assertEquals(1, fight.turnList().fighters().indexOf(invocation)); assertSame(fighter1.team(), invocation.team()); assertSame(fighter1, invocation.invoker()); @@ -1402,6 +1403,32 @@ void increaseResistance() { assertTrue(fighter1.life().isFull()); } + @Test + void staticInvocation() throws SQLException { + dataSet.pushMonsterTemplateInvocations(); + + castNormal(186, fight.map().get(183)); // Arbre + + Fighter invoc = fight.fighters().stream().filter(f -> fighter1.equals(f.invoker())).findFirst().get(); + + assertEquals(invoc, fight.map().get(183).fighter()); + assertEquals(183, invoc.cell().id()); + assertEquals("282", invoc.sprite().name()); + assertTrue(fight.fighters().all().contains(invoc)); + assertFalse(fight.turnList().fighters().contains(invoc)); + + requestStack.assertOne(new ActionEffect(185, fighter1, "+" + invoc.sprite())); + + // Ignore invocation count limit + passTurns(7); + castNormal(186, fight.map().get(198)); // Arbre + assertTrue(fight.map().get(198).hasFighter()); + + passTurns(7); + castNormal(186, fight.map().get(213)); // Arbre + assertTrue(fight.map().get(213).hasFighter()); + } + private List configureFight(Consumer configurator) { fight.cancel(true); @@ -1412,7 +1439,7 @@ private List configureFight(Consumer configurator) { fight = builder.build(true); fight.register(new IndirectSpellApplyEffectsModule(fight, container.get(SpellService.class))); - List fighters = fight.fighters(); + List fighters = new ArrayList<>(fight.fighters().all()); fight.state(PlacementState.class).startFight(); fight.turnList().start(); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandlerTest.java index d50912899..5795a3126 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandlerTest.java @@ -243,29 +243,29 @@ void buffMultipleTargets() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - FightCastScope scope = makeCastScope(fight.fighters().get(0), spell, effect, fight.map().get(241)); + FightCastScope scope = makeCastScope(getFighter(0), spell, effect, fight.map().get(241)); handler.buff(scope, scope.effects().get(0)); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(1).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get(), 10)); - requestStack.assertOne(new AddBuff(fight.fighters().get(1).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get())); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(2).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get(), 10)); - requestStack.assertOne(new AddBuff(fight.fighters().get(2).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get())); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(3).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get(), 10)); - requestStack.assertOne(new AddBuff(fight.fighters().get(3).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get())); + requestStack.assertOne(ActionEffect.buff(getFighter(1).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get(), 10)); + requestStack.assertOne(new AddBuff(getFighter(1).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get())); + requestStack.assertOne(ActionEffect.buff(getFighter(2).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get(), 10)); + requestStack.assertOne(new AddBuff(getFighter(2).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get())); + requestStack.assertOne(ActionEffect.buff(getFighter(3).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get(), 10)); + requestStack.assertOne(new AddBuff(getFighter(3).buffs().stream().filter(buff -> buff.effect().effect() == 152).findFirst().get())); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(0).buffs().stream().filter(buff -> buff.effect().effect() == 123).findFirst().get(), 30)); + requestStack.assertOne(ActionEffect.buff(getFighter(0).buffs().stream().filter(buff -> buff.effect().effect() == 123).findFirst().get(), 30)); requestStack.assertOne("GIE123;1;30;;0;;5;0"); - assertEquals(30, fight.fighters().get(0).characteristics().get(Characteristic.LUCK)); - assertEquals(-10, fight.fighters().get(1).characteristics().get(Characteristic.LUCK)); - assertEquals(-10, fight.fighters().get(2).characteristics().get(Characteristic.LUCK)); - assertEquals(-10, fight.fighters().get(3).characteristics().get(Characteristic.LUCK)); + assertEquals(30, getFighter(0).characteristics().get(Characteristic.LUCK)); + assertEquals(-10, getFighter(1).characteristics().get(Characteristic.LUCK)); + assertEquals(-10, getFighter(2).characteristics().get(Characteristic.LUCK)); + assertEquals(-10, getFighter(3).characteristics().get(Characteristic.LUCK)); fight.fighters().forEach(fighter -> fighter.buffs().removeAll()); - assertEquals(0, fight.fighters().get(0).characteristics().get(Characteristic.LUCK)); - assertEquals(0, fight.fighters().get(1).characteristics().get(Characteristic.LUCK)); - assertEquals(0, fight.fighters().get(2).characteristics().get(Characteristic.LUCK)); - assertEquals(0, fight.fighters().get(3).characteristics().get(Characteristic.LUCK)); + assertEquals(0, getFighter(0).characteristics().get(Characteristic.LUCK)); + assertEquals(0, getFighter(1).characteristics().get(Characteristic.LUCK)); + assertEquals(0, getFighter(2).characteristics().get(Characteristic.LUCK)); + assertEquals(0, getFighter(3).characteristics().get(Characteristic.LUCK)); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealVitalityHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealVitalityHandlerTest.java index 53b566865..76a0c8f96 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealVitalityHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealVitalityHandlerTest.java @@ -295,39 +295,39 @@ void buffMultipleTargets() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - FightCastScope scope = makeCastScope(fight.fighters().get(0), spell, effect, fight.map().get(241)); + FightCastScope scope = makeCastScope(getFighter(0), spell, effect, fight.map().get(241)); handler.buff(scope, scope.effects().get(0)); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(1).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get(), 10)); - requestStack.assertOne(new AddBuff(fight.fighters().get(1).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get())); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(2).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get(), 10)); - requestStack.assertOne(new AddBuff(fight.fighters().get(2).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get())); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(3).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get(), 10)); - requestStack.assertOne(new AddBuff(fight.fighters().get(3).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get())); + requestStack.assertOne(ActionEffect.buff(getFighter(1).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get(), 10)); + requestStack.assertOne(new AddBuff(getFighter(1).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get())); + requestStack.assertOne(ActionEffect.buff(getFighter(2).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get(), 10)); + requestStack.assertOne(new AddBuff(getFighter(2).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get())); + requestStack.assertOne(ActionEffect.buff(getFighter(3).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get(), 10)); + requestStack.assertOne(new AddBuff(getFighter(3).buffs().stream().filter(buff -> buff.effect().effect() == 153).findFirst().get())); - requestStack.assertOne(ActionEffect.buff(fight.fighters().get(0).buffs().stream().filter(buff -> buff.effect().effect() == 125).findFirst().get(), 30)); + requestStack.assertOne(ActionEffect.buff(getFighter(0).buffs().stream().filter(buff -> buff.effect().effect() == 125).findFirst().get(), 30)); requestStack.assertOne("GIE125;1;30;;0;;5;0"); - assertEquals(30, fight.fighters().get(0).characteristics().get(Characteristic.VITALITY)); - assertEquals(-10, fight.fighters().get(1).characteristics().get(Characteristic.VITALITY)); - assertEquals(-10, fight.fighters().get(2).characteristics().get(Characteristic.VITALITY)); - assertEquals(-10, fight.fighters().get(3).characteristics().get(Characteristic.VITALITY)); + assertEquals(30, getFighter(0).characteristics().get(Characteristic.VITALITY)); + assertEquals(-10, getFighter(1).characteristics().get(Characteristic.VITALITY)); + assertEquals(-10, getFighter(2).characteristics().get(Characteristic.VITALITY)); + assertEquals(-10, getFighter(3).characteristics().get(Characteristic.VITALITY)); - assertEquals(325, fight.fighters().get(0).life().max()); - assertEquals(40, fight.fighters().get(1).life().max()); - assertEquals(40, fight.fighters().get(2).life().max()); - assertEquals(40, fight.fighters().get(3).life().max()); + assertEquals(325, getFighter(0).life().max()); + assertEquals(40, getFighter(1).life().max()); + assertEquals(40, getFighter(2).life().max()); + assertEquals(40, getFighter(3).life().max()); fight.fighters().forEach(fighter -> fighter.buffs().removeAll()); - assertEquals(0, fight.fighters().get(0).characteristics().get(Characteristic.VITALITY)); - assertEquals(0, fight.fighters().get(1).characteristics().get(Characteristic.VITALITY)); - assertEquals(0, fight.fighters().get(2).characteristics().get(Characteristic.VITALITY)); - assertEquals(0, fight.fighters().get(3).characteristics().get(Characteristic.VITALITY)); + assertEquals(0, getFighter(0).characteristics().get(Characteristic.VITALITY)); + assertEquals(0, getFighter(1).characteristics().get(Characteristic.VITALITY)); + assertEquals(0, getFighter(2).characteristics().get(Characteristic.VITALITY)); + assertEquals(0, getFighter(3).characteristics().get(Characteristic.VITALITY)); - assertEquals(295, fight.fighters().get(0).life().max()); - assertEquals(50, fight.fighters().get(1).life().max()); - assertEquals(50, fight.fighters().get(2).life().max()); - assertEquals(50, fight.fighters().get(3).life().max()); + assertEquals(295, getFighter(0).life().max()); + assertEquals(50, getFighter(1).life().max()); + assertEquals(50, getFighter(2).life().max()); + assertEquals(50, getFighter(3).life().max()); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealActionPointHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealActionPointHandlerTest.java index 770a88830..5e2aa369e 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealActionPointHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealActionPointHandlerTest.java @@ -270,20 +270,20 @@ void withArea() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - FightCastScope scope = makeCastScope(fight.fighters().get(0), spell, effect, fight.map().get(150)); + FightCastScope scope = makeCastScope(getFighter(0), spell, effect, fight.map().get(150)); handler.buff(scope, scope.effects().get(0)); - Optional buff0 = fight.fighters().get(0).buffs().stream().filter(b -> b.effect().effect() == 111).findFirst(); - Optional buff1 = fight.fighters().get(1).buffs().stream().filter(b -> b.effect().effect() == 101).findFirst(); - Optional buff2 = fight.fighters().get(2).buffs().stream().filter(b -> b.effect().effect() == 101).findFirst(); + Optional buff0 = getFighter(0).buffs().stream().filter(b -> b.effect().effect() == 111).findFirst(); + Optional buff1 = getFighter(1).buffs().stream().filter(b -> b.effect().effect() == 101).findFirst(); + Optional buff2 = getFighter(2).buffs().stream().filter(b -> b.effect().effect() == 101).findFirst(); assertTrue(buff0.isPresent()); assertTrue(buff1.isPresent()); assertTrue(buff2.isPresent()); - assertEquals(18, fight.fighters().get(0).characteristics().get(Characteristic.ACTION_POINT)); - assertEquals(0, fight.fighters().get(1).characteristics().get(Characteristic.ACTION_POINT)); - assertEquals(0, fight.fighters().get(2).characteristics().get(Characteristic.ACTION_POINT)); + assertEquals(18, getFighter(0).characteristics().get(Characteristic.ACTION_POINT)); + assertEquals(0, getFighter(1).characteristics().get(Characteristic.ACTION_POINT)); + assertEquals(0, getFighter(2).characteristics().get(Characteristic.ACTION_POINT)); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealMovementPointHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealMovementPointHandlerTest.java index 3a22212ad..d634b60fc 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealMovementPointHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/point/StealMovementPointHandlerTest.java @@ -271,20 +271,20 @@ void withArea() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - FightCastScope scope = makeCastScope(fight.fighters().get(0), spell, effect, fight.map().get(150)); + FightCastScope scope = makeCastScope(getFighter(0), spell, effect, fight.map().get(150)); handler.buff(scope, scope.effects().get(0)); - Optional buff0 = fight.fighters().get(0).buffs().stream().filter(b -> b.effect().effect() == 128).findFirst(); - Optional buff1 = fight.fighters().get(1).buffs().stream().filter(b -> b.effect().effect() == 127).findFirst(); - Optional buff2 = fight.fighters().get(2).buffs().stream().filter(b -> b.effect().effect() == 127).findFirst(); + Optional buff0 = getFighter(0).buffs().stream().filter(b -> b.effect().effect() == 128).findFirst(); + Optional buff1 = getFighter(1).buffs().stream().filter(b -> b.effect().effect() == 127).findFirst(); + Optional buff2 = getFighter(2).buffs().stream().filter(b -> b.effect().effect() == 127).findFirst(); assertTrue(buff0.isPresent()); assertTrue(buff1.isPresent()); assertTrue(buff2.isPresent()); - assertEquals(9, fight.fighters().get(0).characteristics().get(Characteristic.MOVEMENT_POINT)); - assertEquals(0, fight.fighters().get(1).characteristics().get(Characteristic.MOVEMENT_POINT)); - assertEquals(0, fight.fighters().get(2).characteristics().get(Characteristic.MOVEMENT_POINT)); + assertEquals(9, getFighter(0).characteristics().get(Characteristic.MOVEMENT_POINT)); + assertEquals(0, getFighter(1).characteristics().get(Characteristic.MOVEMENT_POINT)); + assertEquals(0, getFighter(2).characteristics().get(Characteristic.MOVEMENT_POINT)); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/heal/GivePercentLifeHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/heal/GivePercentLifeHandlerTest.java index eded76bb6..7e66450af 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/heal/GivePercentLifeHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/heal/GivePercentLifeHandlerTest.java @@ -190,7 +190,7 @@ void withMultipleAlliesShouldOnlyRemoveCasterLifeOnce() { fight.nextState(); - caster = (PlayerFighter) fight.fighters().get(0); + caster = (PlayerFighter) getFighter(0); SpellEffect effect = Mockito.mock(SpellEffect.class); Spell spell = Mockito.mock(Spell.class); @@ -209,8 +209,8 @@ void withMultipleAlliesShouldOnlyRemoveCasterLifeOnce() { requestStack.assertAll( ActionEffect.alterLifePoints(caster, caster, -25), - ActionEffect.alterLifePoints(caster, fight.fighters().get(3), 25), - ActionEffect.alterLifePoints(caster, fight.fighters().get(2), 25) + ActionEffect.alterLifePoints(caster, getFighter(3), 25), + ActionEffect.alterLifePoints(caster, getFighter(2), 25) ); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java index d821aa29c..0b25e7e3d 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java @@ -84,7 +84,7 @@ void handle() { FighterData invoc = fight.map().get(123).fighter(); assertInstanceOf(InvocationFighter.class, invoc); - assertContains(invoc, fight.fighters()); + assertContains(invoc, fight.fighters().all()); assertContains(invoc, fight.turnList().fighters()); assertSame(caster.team(), invoc.team()); assertEquals(1, invoc.level()); @@ -116,7 +116,7 @@ void buff() { FighterData invoc = fight.map().get(123).fighter(); assertInstanceOf(InvocationFighter.class, invoc); - assertContains(invoc, fight.fighters()); + assertContains(invoc, fight.fighters().all()); assertContains(invoc, fight.turnList().fighters()); assertSame(caster.team(), invoc.team()); assertEquals(1, invoc.level()); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java new file mode 100644 index 000000000..769060d1e --- /dev/null +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java @@ -0,0 +1,113 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2019 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.castable.effect.handler.invocations; + +import fr.quatrevieux.araknemu.game.fight.Fight; +import fr.quatrevieux.araknemu.game.fight.FightBaseCase; +import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; +import fr.quatrevieux.araknemu.game.monster.MonsterService; +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 fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class StaticInvocationHandlerTest extends FightBaseCase { + private Fight fight; + private PlayerFighter caster; + private StaticInvocationHandler handler; + + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + dataSet.pushMonsterTemplateInvocations().pushMonsterSpellsInvocations().pushRewardItems(); + + fight = createFight(); + fight.nextState(); + + caster = player.fighter(); + + handler = new StaticInvocationHandler(container.get(MonsterService.class), container.get(FighterFactory.class), fight); + + requestStack.clear(); + } + + @Test + void handle() { + SpellEffect effect = Mockito.mock(SpellEffect.class); + Spell spell = Mockito.mock(Spell.class); + SpellConstraints constraints = Mockito.mock(SpellConstraints.class); + + Mockito.when(effect.area()).thenReturn(new CellArea()); + Mockito.when(effect.min()).thenReturn(36); // bouftou + Mockito.when(effect.max()).thenReturn(1); // grade 1 + Mockito.when(effect.target()).thenReturn(SpellEffectTarget.DEFAULT); + Mockito.when(spell.constraints()).thenReturn(constraints); + Mockito.when(constraints.freeCell()).thenReturn(true); + + FightCastScope scope = makeCastScope(caster, spell, effect, fight.map().get(123)); + handler.handle(scope, scope.effects().get(0)); + + FighterData invoc = fight.map().get(123).fighter(); + + assertInstanceOf(InvocationFighter.class, invoc); + assertContains(invoc, fight.fighters().all()); + assertFalse(fight.turnList().fighters().contains(invoc)); + assertSame(caster.team(), invoc.team()); + assertEquals(1, invoc.level()); + assertEquals(36, ((InvocationFighter) invoc).monster().id()); + + requestStack.assertAll( + new ActionEffect(185, caster, "+" + invoc.sprite()) + ); + } + + @Test + void buff() { + SpellEffect effect = Mockito.mock(SpellEffect.class); + Spell spell = Mockito.mock(Spell.class); + SpellConstraints constraints = Mockito.mock(SpellConstraints.class); + + Mockito.when(effect.area()).thenReturn(new CellArea()); + Mockito.when(effect.min()).thenReturn(36); // bouftou + Mockito.when(effect.max()).thenReturn(1); // grade 1 + Mockito.when(effect.target()).thenReturn(SpellEffectTarget.DEFAULT); + Mockito.when(spell.constraints()).thenReturn(constraints); + Mockito.when(constraints.freeCell()).thenReturn(true); + + FightCastScope scope = makeCastScope(caster, spell, effect, fight.map().get(123)); + assertThrows(UnsupportedOperationException.class, () -> handler.buff(scope, scope.effects().get(0))); + } +} diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionApplierTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionApplierTest.java index eb6cb584c..e85f7fd5a 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionApplierTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionApplierTest.java @@ -49,7 +49,7 @@ void applySuccess() { ); PlayerFighter caster = player.fighter(); - Fighter other = fight.fighters().get(1); + Fighter other = getFighter(1); SpellEffect effect = Mockito.mock(SpellEffect.class); Spell spell = Mockito.mock(Spell.class); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionHandlerTest.java index b70aa30fb..c3fad8841 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionHandlerTest.java @@ -51,7 +51,7 @@ void applySuccess() { ); PlayerFighter caster = player.fighter(); - Fighter other = fight.fighters().get(1); + Fighter other = getFighter(1); SpellEffect effect = Mockito.mock(SpellEffect.class); Spell spell = Mockito.mock(Spell.class); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionOnAttackHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionOnAttackHandlerTest.java index 2173b690c..821aee1a6 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionOnAttackHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/shifting/SwitchPositionOnAttackHandlerTest.java @@ -156,8 +156,8 @@ void buffWithAreaMultipleFighters() { FightCastScope scope = makeCastScope(player.fighter(), spell, effect, fight.map().get(122)); handler.buff(scope, scope.effects().get(0)); - assertTrue(fight.fighters().get(1).buffs().stream().anyMatch(buff -> buff.effect().equals(effect))); - assertTrue(fight.fighters().get(2).buffs().stream().anyMatch(buff -> buff.effect().equals(effect))); + assertTrue(getFighter(1).buffs().stream().anyMatch(buff -> buff.effect().equals(effect))); + assertTrue(getFighter(2).buffs().stream().anyMatch(buff -> buff.effect().equals(effect))); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java index 7f23375d9..a0174304a 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java @@ -101,6 +101,34 @@ void maxInvocReachedWithMultipleInvoc() { ); } + @Test + void shouldIgnoreStaticInvocation() { + Spell spell = Mockito.mock(Spell.class); + + Fighter invoc1 = Mockito.mock(Fighter.class); + Fighter invoc2 = Mockito.mock(Fighter.class); + Fighter invoc3 = Mockito.mock(Fighter.class); + Fighter invoc4 = Mockito.mock(Fighter.class); + + Mockito.when(invoc1.invoker()).thenReturn(fighter); + Mockito.when(invoc2.invoker()).thenReturn(fighter); + Mockito.when(invoc3.invoker()).thenReturn(fighter); + Mockito.when(invoc4.invoker()).thenReturn(fighter); + + fight.fighters().join(invoc1, fight.map().get(146)); + fight.fighters().join(invoc2, fight.map().get(146)); + fight.fighters().join(invoc3, fight.map().get(146)); + fight.fighters().join(invoc4, fight.map().get(146)); + + SpellEffect effect = Mockito.mock(SpellEffect.class); + Mockito.when(effect.effect()).thenReturn(180); + Mockito.when(spell.effects()).thenReturn(Collections.singletonList(effect)); + + fighter.characteristics().alter(Characteristic.MAX_SUMMONED_CREATURES, 3); + + assertTrue(validator.check(turn, spell, fight.map().get(123))); + } + @Test void success() { Spell spell = Mockito.mock(Spell.class); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java index 71d7dac16..999b5b81f 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ending/reward/generator/PvmRewardsGeneratorTest.java @@ -72,7 +72,7 @@ void generate() throws Exception { FightRewardsSheet sheet = generator.generate(results); assertSame(results, sheet.results()); - assertCount(fight.fighters().size(), sheet.rewards()); + assertCount(fight.fighters().all().size(), sheet.rewards()); assertEquals(FightRewardsSheet.Type.NORMAL, sheet.type()); assertEquals(RewardType.WINNER, sheet.rewards().get(0).type()); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModuleTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModuleTest.java index 3a8705ad6..4ae4963dc 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModuleTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/module/MonsterInvocationModuleTest.java @@ -65,13 +65,9 @@ void onFighterDieShouldKillAllItsInvocation() throws Exception { InvocationFighter invoc2 = new InvocationFighter(-6, monsterService.load(36).get(2), player.fighter().team(), player.fighter()); InvocationFighter invoc3 = new InvocationFighter(-7, monsterService.load(36).get(4), other.fighter().team(), other.fighter()); - invoc1.joinFight(fight, fight.map().get(123)); - invoc2.joinFight(fight, fight.map().get(124)); - invoc3.joinFight(fight, fight.map().get(125)); - - fight.turnList().add(invoc1); - fight.turnList().add(invoc2); - fight.turnList().add(invoc3); + fight.fighters().joinTurnList(invoc1, fight.map().get(123)); + fight.fighters().joinTurnList(invoc2, fight.map().get(124)); + fight.fighters().joinTurnList(invoc3, fight.map().get(125)); invoc1.init(); invoc2.init(); @@ -85,14 +81,14 @@ void onFighterDieShouldKillAllItsInvocation() throws Exception { assertFalse(fight.map().get(124).hasFighter()); assertFalse(fight.turnList().fighters().contains(invoc1)); assertFalse(fight.turnList().fighters().contains(invoc2)); - assertFalse(fight.fighters().contains(invoc1)); - assertFalse(fight.fighters().contains(invoc2)); + assertFalse(fight.fighters().all().contains(invoc1)); + assertFalse(fight.fighters().all().contains(invoc2)); // Do not change invocation of other fighter assertFalse(invoc3.dead()); assertTrue(fight.map().get(125).hasFighter()); assertTrue(fight.turnList().fighters().contains(invoc3)); - assertTrue(fight.fighters().contains(invoc3)); + assertTrue(fight.fighters().all().contains(invoc3)); } @Test @@ -113,7 +109,26 @@ void onFighterDieInvocationShouldBeRemovedFromTurnList() throws Exception { assertTrue(invoc.dead()); assertFalse(fight.map().get(123).hasFighter()); assertFalse(fight.turnList().fighters().contains(invoc)); - assertFalse(fight.fighters().contains(invoc)); + assertFalse(fight.fighters().all().contains(invoc)); + } + + @Test + void onFighterDieStaticInvocationShouldBeRemovedFromFight() throws Exception { + Fight fight = createFight(true); + + fight.register(new MonsterInvocationModule(monsterService, container.get(FighterFactory.class), fight)); + fight.state(PlacementState.class).startFight(); + fight.turnList().start(); + + InvocationFighter invoc = new InvocationFighter(-5, monsterService.load(36).get(2), player.fighter().team(), player.fighter()); + invoc.joinFight(fight, fight.map().get(123)); + invoc.init(); + + invoc.life().kill(player.fighter()); + + assertTrue(invoc.dead()); + assertFalse(fight.map().get(123).hasFighter()); + assertFalse(fight.fighters().all().contains(invoc)); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java index b0f4bef0f..5d197ce2a 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/ActiveStateTest.java @@ -45,6 +45,7 @@ import fr.quatrevieux.araknemu.network.game.out.fight.turn.FighterTurnOrder; import fr.quatrevieux.araknemu.network.game.out.fight.turn.StartTurn; import fr.quatrevieux.araknemu.network.game.out.fight.turn.TurnMiddle; +import fr.quatrevieux.araknemu.network.game.out.game.RemoveSprite; import fr.quatrevieux.araknemu.util.ExecutorFactory; import io.github.artsok.RepeatedIfExceptionsTest; import org.apache.logging.log4j.Logger; @@ -191,7 +192,7 @@ void leaveFightLastOfTeamWillTerminateTheFight() { assertTrue(other.dead()); assertFalse(fight.active()); - assertContains(other, fight.fighters()); + assertContains(other, fight.fighters().all()); requestStack.assertLast(ActionEffect.fighterDie(other, other)); } @@ -204,7 +205,7 @@ void leaveFightCancelledShouldDoNothing() { state.leave(other); assertFalse(other.dead()); - assertContains(other, fight.fighters()); + assertContains(other, fight.fighters().all()); } @Test @@ -223,12 +224,13 @@ void leaveNotLastOfTeamWillKillAndRemoveTheFighterFromFight() throws SQLExceptio assertFalse(mutineer.cell().hasFighter()); assertTrue(mutineer.dead()); assertFalse(fight.team(0).fighters().contains(mutineer)); - assertFalse(fight.fighters().contains(mutineer)); + assertFalse(fight.fighters().all().contains(mutineer)); assertFalse(fight.turnList().fighters().contains(mutineer)); requestStack.assertAll( ActionEffect.fighterDie(mutineer, mutineer), - new FighterTurnOrder(fight.turnList()) + new FighterTurnOrder(fight.turnList()), + new RemoveSprite(mutineer.sprite()) ); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/PlacementStateTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/PlacementStateTest.java index fc30b2051..1ad0a105b 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/state/PlacementStateTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/state/PlacementStateTest.java @@ -137,11 +137,11 @@ void start() { assertEquals(123, fighter.cell().id()); assertEquals(fight.team(0), fighter.team()); assertEquals(fight, fighter.fight()); - assertEquals(321, fight.fighters().get(1).cell().id()); - assertEquals(fight.team(1), fight.fighters().get(1).team()); - assertEquals(fight, fight.fighters().get(1).fight()); + assertEquals(321, fight.team(1).leader().cell().id()); + assertEquals(fight.team(1), fight.team(1).leader().team()); + assertEquals(fight, fight.team(1).leader().fight()); - assertCount(2, fight.fighters()); + assertCount(2, fight.fighters().all()); } @Test @@ -153,9 +153,9 @@ void startRandomized() { assertNotNull(fighter.cell()); assertEquals(fight.team(0), fighter.team()); assertEquals(fight, fighter.fight()); - assertNotNull(fight.fighters().get(1).cell()); - assertEquals(fight.team(1), fight.fighters().get(1).team()); - assertEquals(fight, fight.fighters().get(1).fight()); + assertNotNull(fight.team(1).leader().cell()); + assertEquals(fight.team(1), fight.team(1).leader().team()); + assertEquals(fight, fight.team(1).leader().fight()); } @RepeatedIfExceptionsTest @@ -406,7 +406,7 @@ void leaveBadState() throws SQLException, ContainerException, JoinFightException assertThrows(InvalidFightStateException.class, () -> state.leave(newFighter)); assertNull(ref.get()); - assertContains(newFighter, fight.fighters()); + assertContains(newFighter, fight.fighters().all()); } @Test @@ -422,7 +422,7 @@ void leaveNotLeader() throws SQLException, ContainerException, JoinFightExceptio state.leave(newFighter); assertSame(newFighter, ref.get().fighter()); - assertFalse(fight.fighters().contains(newFighter)); + assertFalse(fight.fighters().all().contains(newFighter)); assertFalse(newFighter.cell().hasFighter()); requestStack.assertLast(new RemoveSprite(newFighter.sprite())); @@ -441,7 +441,7 @@ void leaveLeaderWillDissolveTeam() throws SQLException, ContainerException, Join state.leave(fighter); - assertCount(0, fight.fighters()); + assertCount(0, fight.fighters().all()); assertSame(fight, ref.get().fight()); requestStack.assertLast(new CancelFight()); } @@ -468,7 +468,7 @@ void kickBadState() throws SQLException, ContainerException, JoinFightException assertThrows(InvalidFightStateException.class, () -> state.kick(newFighter)); assertNull(ref.get()); - assertContains(newFighter, fight.fighters()); + assertContains(newFighter, fight.fighters().all()); } @Test @@ -492,7 +492,7 @@ void kickSuccess() throws SQLException, ContainerException, JoinFightException { state.kick(newFighter); assertSame(newFighter, ref.get().fighter()); - assertFalse(fight.fighters().contains(newFighter)); + assertFalse(fight.fighters().all().contains(newFighter)); assertFalse(newFighter.cell().hasFighter()); requestStack.assertLast(new RemoveSprite(newFighter.sprite())); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java index 4a756263d..3739ae079 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java @@ -272,8 +272,9 @@ void removeFighterNotFound() throws SQLException { PlayerFighter third = makePlayerFighter(makeSimpleGamePlayer(5)); turnList.start(); + turnList.remove(third); // Do nothing - assertThrows(NoSuchElementException.class, () -> turnList.remove(third)); + assertCount(2, turnList.fighters()); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionHandlerTest.java index 6648c0b34..db3b04b33 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionHandlerTest.java @@ -52,7 +52,7 @@ public void setUp() throws Exception { fight = createFight(); fight.start(new AlternateTeamFighterOrder()); - turn = new FightTurn(fight.fighters().get(0), fight, Duration.ZERO); + turn = new FightTurn(getFighter(0), fight, Duration.ZERO); actionHandler = new ActionHandler(turn, fight); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java index 538178355..c8cb52968 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java @@ -45,6 +45,7 @@ import java.lang.reflect.Method; import java.sql.SQLException; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; import java.util.stream.Stream; @@ -369,12 +370,12 @@ public static Stream provideEnemiesAndChances() { @ParameterizedTest void computeTackle(int performerAgility, int enemyAgility, double escapeProbability) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { FightBuilder builder = fightBuilder() - .addSelf(fb -> fb.cell(185).charac(Characteristic.AGILITY, performerAgility)) + .addSelf(fb -> fb.cell(185).charac(Characteristic.AGILITY, performerAgility).charac(Characteristic.INTELLIGENCE, 1000)) .addEnemy(fb -> fb.cell(170).charac(Characteristic.AGILITY, enemyAgility)) ; fight = builder.build(true); - fight.start(a -> fight.fighters()); + fight.start(new AlternateTeamFighterOrder()); fighter = player.fighter(); turn = new FightTurn(fighter, fight, Duration.ofSeconds(30)); @@ -383,7 +384,7 @@ void computeTackle(int performerAgility, int enemyAgility, double escapeProbabil Method method = validator.getClass().getDeclaredMethod("computeTackle", Fighter.class, FighterData.class); method.setAccessible(true); - assertEquals(escapeProbability, (double) method.invoke(validator, fighter, fight.fighters().get(1)), 0.01); + assertEquals(escapeProbability, (double) method.invoke(validator, fighter, getFighter(1)), 0.01); } public static Stream provideAgilityAndChance() { diff --git a/src/test/java/fr/quatrevieux/araknemu/game/handler/StopSessionTest.java b/src/test/java/fr/quatrevieux/araknemu/game/handler/StopSessionTest.java index 35bcfbf67..28a1c2f40 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/handler/StopSessionTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/handler/StopSessionTest.java @@ -144,7 +144,7 @@ void withFighterWillLeaveTheFight() throws Exception { handler.handle(session, new SessionClosed()); assertNull(session.fighter()); - assertFalse(fight.fighters().contains(fighter)); + assertFalse(fight.fighters().all().contains(fighter)); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/KickFighterTest.java b/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/KickFighterTest.java index 97c3ff9b4..e9471a784 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/KickFighterTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/KickFighterTest.java @@ -56,7 +56,7 @@ void notInPlacementState() throws Exception { requestStack.clear(); handlePacket(new KickFighterRequest(teammate.id())); - assertTrue(fight.fighters().contains(teammate)); + assertTrue(fight.fighters().all().contains(teammate)); requestStack.assertLast(Error.cantDoDuringFight()); } @@ -68,7 +68,7 @@ void notTeammate() throws Exception { handlePacket(new KickFighterRequest(enemy.id())); - assertTrue(fight.fighters().contains(enemy)); + assertTrue(fight.fighters().all().contains(enemy)); requestStack.assertLast(new Noop()); } @@ -91,7 +91,7 @@ void notLeader() throws Exception { handlePacket(new KickFighterRequest(me.id())); requestStack.assertLast(new Noop()); - assertTrue(fight.fighters().contains(me)); + assertTrue(fight.fighters().all().contains(me)); } @RepeatedIfExceptionsTest @@ -102,7 +102,7 @@ void success() throws Exception { handlePacket(new KickFighterRequest(teammate.id())); - assertFalse(fight.fighters().contains(teammate)); + assertFalse(fight.fighters().all().contains(teammate)); requestStack.assertLast(new RemoveSprite(teammate.sprite())); } @@ -113,12 +113,12 @@ void otherKickMe() throws Exception { fight.state(PlacementState.class).joinTeam(me, fight.team(0)); - PlayerFighter otherFighter = (PlayerFighter) fight.fighters().get(0); + PlayerFighter otherFighter = (PlayerFighter) fight.team(0).leader(); GameSession otherSession = accessors.session(otherFighter); otherSession.setFighter(otherFighter); new KickFighter().handle(otherSession, new KickFighterRequest(me.id())); requestStack.assertLast(new CancelFight()); - assertFalse(fight.fighters().contains(me)); + assertFalse(fight.fighters().all().contains(me)); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/LeaveFightTest.java b/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/LeaveFightTest.java index a234c0ca2..61f56af65 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/LeaveFightTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/LeaveFightTest.java @@ -70,8 +70,8 @@ void leaveFightDuringPlacementNotLeader() throws SQLException, ContainerExceptio handler.handle(session, new LeaveFightRequest()); assertFalse(gamePlayer().isFighting()); - assertFalse(fight.fighters().contains(fighter)); - assertCount(2, fight.fighters()); + assertFalse(fight.fighters().all().contains(fighter)); + assertCount(2, fight.fighters().all()); requestStack.assertLast(new CancelFight()); } @@ -89,7 +89,7 @@ void leaveFightDuringPlacementLeaderWillDissolveTeam() throws Exception { assertFalse(gamePlayer().isFighting()); assertFalse(other.isFighting()); - assertCount(0, fight.fighters()); + assertCount(0, fight.fighters().all()); assertTrue(container.get(FightService.class).fightsByMap(map.id()).isEmpty()); requestStack.assertLast(new CancelFight()); @@ -109,10 +109,10 @@ void leaveFightActiveStateNotLastOfTeam() throws SQLException, ContainerExceptio handler.handle(session, new LeaveFightRequest()); assertFalse(gamePlayer().isFighting()); - assertFalse(fight.fighters().contains(fighter)); + assertFalse(fight.fighters().all().contains(fighter)); assertTrue(fight.active()); assertTrue(fighter.dead()); - assertCount(2, fight.fighters()); + assertCount(2, fight.fighters().all()); assertCount(2, fight.turnList().fighters()); assertFalse(fight.turnList().fighters().contains(fighter)); requestStack.assertLast(new CancelFight()); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/option/ToggleLockTeamTest.java b/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/option/ToggleLockTeamTest.java index 0bafd2e23..0eb84ba23 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/option/ToggleLockTeamTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/handler/fight/option/ToggleLockTeamTest.java @@ -103,6 +103,6 @@ void fromExplorationMapShouldSendTeamOptionAndDenyJoin() throws Exception { requestStack.assertLast(new FightOption(leader.team().id(), FightOption.Type.BLOCK_JOINER, false)); PlayerFighter fighter = makePlayerFighter(gamePlayer()); fight.state(PlacementState.class).joinTeam(fighter, fight.team(0)); - assertContains(fighter, fight.fighters()); + assertContains(fighter, fight.fighters().all()); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/SendFighterPositionsTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/SendFighterPositionsTest.java index 9aa3a512e..78de9c87e 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/SendFighterPositionsTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/SendFighterPositionsTest.java @@ -29,6 +29,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.ArrayList; + class SendFighterPositionsTest extends GameBaseCase { private Fight fight; private SendFighterPositions listener; @@ -60,7 +62,7 @@ public void setUp() throws Exception { @Test void onFighterPlaceChanged() { - listener.on(new FighterPlaceChanged(fight.fighters().get(0))); + listener.on(new FighterPlaceChanged(new ArrayList<>(fight.fighters().all()).get(0))); requestStack.assertLast(new FighterPositions(fight.fighters())); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/LeaveOnDisconnectTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/LeaveOnDisconnectTest.java index b637a471f..d9ddec1b7 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/LeaveOnDisconnectTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/fighter/LeaveOnDisconnectTest.java @@ -56,7 +56,7 @@ public void setUp() throws Exception { void onDisconnect() throws InterruptedException { listener.on(new Disconnected()); - assertFalse(fight.fighters().contains(fighter)); + assertFalse(fight.fighters().all().contains(fighter)); requestStack.assertLast(new RemoveSprite(fighter.sprite())); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendBattlefieldObjectsToSpectatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendBattlefieldObjectsToSpectatorTest.java index 3bf869530..9f6d99eaa 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendBattlefieldObjectsToSpectatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendBattlefieldObjectsToSpectatorTest.java @@ -25,6 +25,7 @@ import fr.quatrevieux.araknemu.game.fight.map.BattlefieldObject; import fr.quatrevieux.araknemu.game.fight.spectator.Spectator; import fr.quatrevieux.araknemu.game.fight.spectator.event.StartWatchFight; +import fr.quatrevieux.araknemu.game.fight.turn.order.AlternateTeamFighterOrder; import fr.quatrevieux.araknemu.network.game.out.fight.battlefield.AddZones; import fr.quatrevieux.araknemu.network.game.out.game.UpdateCells; import org.junit.jupiter.api.BeforeEach; @@ -46,15 +47,17 @@ public void setUp() throws Exception { @Test void onStartWatchFightWithObjects() throws SQLException { + fight.nextState(); + BattlefieldObject bo1 = Mockito.mock(BattlefieldObject.class); BattlefieldObject bo2 = Mockito.mock(BattlefieldObject.class); BattlefieldObject bo3 = Mockito.mock(BattlefieldObject.class); BattlefieldObject bo4 = Mockito.mock(BattlefieldObject.class); - Mockito.when(bo1.caster()).thenReturn(fight.fighters().get(0)); - Mockito.when(bo2.caster()).thenReturn(fight.fighters().get(1)); - Mockito.when(bo3.caster()).thenReturn(fight.fighters().get(0)); - Mockito.when(bo4.caster()).thenReturn(fight.fighters().get(0)); + Mockito.when(bo1.caster()).thenReturn(getFighter(0)); + Mockito.when(bo2.caster()).thenReturn(getFighter(1)); + Mockito.when(bo3.caster()).thenReturn(getFighter(0)); + Mockito.when(bo4.caster()).thenReturn(getFighter(0)); Mockito.when(bo1.cell()).thenReturn(fight.map().get(123)); Mockito.when(bo2.cell()).thenReturn(fight.map().get(220)); @@ -81,8 +84,6 @@ void onStartWatchFightWithObjects() throws SQLException { Mockito.when(bo3.color()).thenReturn(3); Mockito.when(bo4.color()).thenReturn(1); - fight.nextState(); - fight.map().objects().add(bo1); fight.map().objects().add(bo2); fight.map().objects().add(bo3); @@ -104,9 +105,11 @@ void onStartWatchFightWithObjects() throws SQLException { @Test void onStartWatchFightWithObjectsWithCustomCellData() throws SQLException { + fight.nextState(); + BattlefieldObject bo1 = Mockito.mock(BattlefieldObject.class); - Mockito.when(bo1.caster()).thenReturn(fight.fighters().get(0)); + Mockito.when(bo1.caster()).thenReturn(fight.team(0).leader()); Mockito.when(bo1.cell()).thenReturn(fight.map().get(123)); Mockito.when(bo1.visible()).thenCallRealMethod(); Mockito.when(bo1.cellsProperties()).thenReturn( @@ -115,8 +118,6 @@ void onStartWatchFightWithObjectsWithCustomCellData() throws SQLException { Mockito.when(bo1.size()).thenReturn(2); Mockito.when(bo1.color()).thenReturn(1); - fight.nextState(); - fight.map().objects().add(bo1); SendBattlefieldObjectsToSpectator listener = new SendBattlefieldObjectsToSpectator(new Spectator(gamePlayer(), fight)); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectatorTest.java index e48b0d4fc..3cde5216b 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/spectator/SendFightStateToSpectatorTest.java @@ -137,11 +137,11 @@ void onStartWatchFightWithBuffs() throws SQLException { Mockito.when(effect2.min()).thenReturn(80); Mockito.when(effect2.duration()).thenReturn(10); - Buff buff1 = new Buff(effect1, Mockito.mock(Spell.class), fight.fighters().get(0), fight.fighters().get(0), Mockito.mock(BuffHook.class)); - Buff buff2 = new Buff(effect2, Mockito.mock(Spell.class), fight.fighters().get(0), fight.fighters().get(0), Mockito.mock(BuffHook.class)); + Buff buff1 = new Buff(effect1, Mockito.mock(Spell.class), getFighter(0), getFighter(0), Mockito.mock(BuffHook.class)); + Buff buff2 = new Buff(effect2, Mockito.mock(Spell.class), getFighter(0), getFighter(0), Mockito.mock(BuffHook.class)); - fight.fighters().get(0).buffs().add(buff1); - fight.fighters().get(0).buffs().add(buff2); + getFighter(0).buffs().add(buff1); + getFighter(0).buffs().add(buff2); requestStack.clear(); listener.on(new StartWatchFight()); @@ -165,7 +165,7 @@ void onStartWatchFightWithInvisibility() throws SQLException { fight.nextState(); fight.turnList().start(); - fight.fighters().get(0).setHidden(fight.fighters().get(0), true); + getFighter(0).setHidden(getFighter(0), true); requestStack.clear(); listener.on(new StartWatchFight()); @@ -177,7 +177,7 @@ void onStartWatchFightWithInvisibility() throws SQLException { new FighterTurnOrder(fight.turnList()), new TurnMiddle(fight.fighters()), new StartTurn(fight.turnList().current().get()), - ActionEffect.fighterHidden(fight.fighters().get(0), fight.fighters().get(0)) + ActionEffect.fighterHidden(getFighter(0), getFighter(0)) ); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java index 01c9d17b3..a658af4f1 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java @@ -198,7 +198,7 @@ void whenSecretAndMonsterFighterShouldSendNothing() throws Exception { fight = createPvmFight(); listener = new SendFightAction(fight); - Fighter monster = fight.fighters().get(1); + Fighter monster = new ArrayList<>(fight.team(1).fighters()).get(0); monster.setHidden(monster, true); requestStack.clear(); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/monster/environment/LivingMonsterGroupPositionTest.java b/src/test/java/fr/quatrevieux/araknemu/game/monster/environment/LivingMonsterGroupPositionTest.java index 27f732ad9..424bae49c 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/monster/environment/LivingMonsterGroupPositionTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/monster/environment/LivingMonsterGroupPositionTest.java @@ -172,9 +172,9 @@ void startFight() throws SQLException { assertFalse(map.creatures().contains(group)); assertFalse(map.creatures().contains(player)); - assertCount(group.monsters().size() + 1, fight.fighters()); - assertContainsType(MonsterFighter.class, fight.fighters()); - assertContains(player.player().fighter(), fight.fighters()); + assertCount(group.monsters().size() + 1, fight.fighters().all()); + assertContainsType(MonsterFighter.class, fight.fighters().all()); + assertContains(player.player().fighter(), fight.fighters().all()); assertInstanceOf(PvmType.class, fight.type()); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/monster/group/MonsterGroupTest.java b/src/test/java/fr/quatrevieux/araknemu/game/monster/group/MonsterGroupTest.java index 008f02121..d5dca4435 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/monster/group/MonsterGroupTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/monster/group/MonsterGroupTest.java @@ -139,9 +139,9 @@ void startFight() throws SQLException { assertFalse(map.creatures().contains(group)); assertFalse(map.creatures().contains(player)); - assertCount(5, fight.fighters()); - assertContainsType(MonsterFighter.class, fight.fighters()); - assertContains(player.player().fighter(), fight.fighters()); + assertCount(5, fight.fighters().all()); + assertContainsType(MonsterFighter.class, fight.fighters().all()); + assertContains(player.player().fighter(), fight.fighters().all()); assertInstanceOf(PvmType.class, fight.type()); } diff --git a/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffectTest.java b/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffectTest.java index 3834bd014..8df7ca5fc 100644 --- a/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffectTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/ActionEffectTest.java @@ -378,10 +378,26 @@ void addInvocation() throws Exception { ; Fight fight = createFight(); - InvocationFighter fighter = new InvocationFighter(-5, container.get(MonsterService.class).load(36).get(2), fight.team(0), fight.fighters().get(0)); + Fighter invoker = fight.team(0).leader(); + InvocationFighter fighter = new InvocationFighter(-5, container.get(MonsterService.class).load(36).get(2), fight.team(0), invoker); fighter.joinFight(fight, fight.map().get(118)); - assertEquals("GA;181;1;+118;1;0;-5;36;-2;1566^100;2;-1;-1;-1;0,0,0,0;60;5;3;30;0;-10;7;-45;16;16;0", ActionEffect.addInvocation(fight.fighters().get(0), fighter).toString()); + assertEquals("GA;181;1;+118;1;0;-5;36;-2;1566^100;2;-1;-1;-1;0,0,0,0;60;5;3;30;0;-10;7;-45;16;16;0", ActionEffect.addInvocation(invoker, fighter).toString()); + } + + @Test + void addStaticInvocation() throws Exception { + dataSet + .pushMonsterTemplates() + .pushMonsterSpells() + ; + + Fight fight = createFight(); + Fighter invoker = fight.team(0).leader(); + InvocationFighter fighter = new InvocationFighter(-5, container.get(MonsterService.class).load(36).get(2), fight.team(0), invoker); + fighter.joinFight(fight, fight.map().get(118)); + + assertEquals("GA;185;1;+118;1;0;-5;36;-2;1566^100;2;-1;-1;-1;0,0,0,0;60;5;3;30;0;-10;7;-45;16;16;0", ActionEffect.addStaticInvocation(invoker, fighter).toString()); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddleTest.java b/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddleTest.java index 62decffb1..806cceb0a 100644 --- a/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddleTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/turn/TurnMiddleTest.java @@ -48,7 +48,7 @@ void generate() { @Test void generateWithHiddenFighterShouldNotSendCell() { - fight.fighters().get(1).setHidden(fight.fighters().get(1), true); + other.fighter().setHidden(other.fighter(), true); assertEquals( "GTM|1;0;295;6;3;122;;295|2;0;50;6;3;-1;;50", From bf9eee8f9c6f0af1d2c9a7c4f88b925943190515 Mon Sep 17 00:00:00 2001 From: Vincent Quatrevieux Date: Tue, 13 Jun 2023 18:25:31 +0200 Subject: [PATCH 2/3] chore(fight): Add PlayableFighter and StaticInvocationFighter --- .../constraint/player/PlayerConstraints.java | 2 +- .../game/admin/account/AccountContext.java | 2 +- .../game/admin/debug/DebugContext.java | 2 +- .../admin/debug/DebugContextResolver.java | 2 +- .../game/admin/player/PlayerContext.java | 2 +- .../game/admin/server/ServerContext.java | 2 +- .../araknemu/game/fight/Fight.java | 24 +- .../araknemu/game/fight/FighterList.java | 23 +- .../araknemu/game/fight/ai/FighterAI.java | 12 +- .../action/FightAiActionFactoryAdapter.java | 8 +- .../ai/factory/AbstractAiBuilderFactory.java | 12 +- .../game/fight/ai/factory/ChainAiFactory.java | 19 +- .../fight/ai/factory/MonsterAiFactory.java | 20 +- .../fight/ai/factory/type/Aggressive.java | 3 +- .../game/fight/ai/factory/type/Fixed.java | 4 +- .../game/fight/ai/factory/type/Runaway.java | 4 +- .../game/fight/ai/factory/type/Support.java | 4 +- .../game/fight/ai/factory/type/Tactical.java | 4 +- .../fight/ai/proxy/ProxyActiveFighter.java | 2 +- .../fight/ai/proxy/ProxyPassiveFighter.java | 2 +- .../game/fight/castable/BaseCastScope.java | 1 + .../StealCharacteristicHandler.java | 2 +- .../invocations/MonsterInvocationHandler.java | 4 +- .../invocations/StaticInvocationHandler.java | 13 +- .../handler/misc/InvisibilityHandler.java | 2 +- .../castable/effect/handler/object/Trap.java | 2 - .../game/fight/fighter/AbstractFighter.java | 37 -- .../fighter/AbstractPlayableFighter.java | 67 ++++ .../game/fight/fighter/EmptySpellList.java | 54 +++ .../araknemu/game/fight/fighter/Fighter.java | 39 +-- .../game/fight/fighter/FighterFactory.java | 6 +- .../game/fight/fighter/PlayableFighter.java | 61 ++++ .../fighter/invocation/InvocationFighter.java | 6 +- .../invocation/StaticInvocationFighter.java | 132 +++++++ .../fight/fighter/monster/MonsterFighter.java | 6 +- .../fighter/operation/FighterOperation.java | 8 + .../fight/fighter/player/PlayerFighter.java | 7 +- .../araknemu/game/fight/module/AiModule.java | 13 +- .../fight/module/CommonEffectsModule.java | 2 +- .../araknemu/game/fight/turn/FightTurn.java | 8 +- .../game/fight/turn/FightTurnList.java | 15 +- .../game/fight/turn/action/ActionResult.java | 4 +- .../game/fight/turn/action/cast/Cast.java | 9 +- .../fight/turn/action/cast/CastFactory.java | 8 +- .../fight/turn/action/cast/CastFailed.java | 8 +- .../fight/turn/action/cast/CastSuccess.java | 8 +- .../fight/turn/action/cast/SpellNotFound.java | 6 +- .../turn/action/closeCombat/CloseCombat.java | 10 +- .../closeCombat/CloseCombatFactory.java | 6 +- .../action/closeCombat/CloseCombatFailed.java | 8 +- .../closeCombat/CloseCombatSuccess.java | 8 +- .../factory/FightActionsFactoryRegistry.java | 24 +- .../game/fight/turn/action/move/Move.java | 8 +- .../fight/turn/action/move/MoveFactory.java | 8 +- .../fight/turn/action/move/MoveFailed.java | 8 +- .../fight/turn/action/move/MoveSuccess.java | 8 +- .../move/validators/TackleValidator.java | 3 +- .../turn/order/AlternateTeamFighterOrder.java | 21 +- .../turn/order/FighterOrderStrategy.java | 4 +- .../game/handler/fight/PerformTurnAction.java | 4 +- .../game/handler/loader/FightingLoader.java | 2 +- .../network/game/in/GameParserLoader.java | 2 +- .../game/out/fight/turn/TurnMiddle.java | 8 +- .../araknemu/game/fight/FightBaseCase.java | 4 +- .../araknemu/game/fight/FightTest.java | 3 +- .../araknemu/game/fight/FighterListTest.java | 27 +- .../araknemu/game/fight/FunctionalTest.java | 3 +- .../araknemu/game/fight/ai/AiBaseCase.java | 7 +- .../araknemu/game/fight/ai/FighterAITest.java | 3 +- .../game/fight/ai/action/DummyGenerator.java | 3 +- .../FightAiActionFactoryAdapterTest.java | 3 +- .../fight/ai/factory/ChainAiFactoryTest.java | 3 +- .../ai/factory/MonsterAiFactoryTest.java | 7 +- .../game/fight/ai/util/PredicatesTest.java | 19 +- .../game/fight/castable/CastScopeTest.java | 9 +- .../fight/castable/effect/FunctionalTest.java | 17 +- .../handler/damage/StealLifeHandlerTest.java | 3 +- .../MonsterInvocationHandlerTest.java | 7 +- .../StaticInvocationHandlerTest.java | 16 +- .../spell/SpellConstraintsValidatorTest.java | 3 +- .../validator/ApCostValidatorTest.java | 3 +- .../InvocationCountValidatorTest.java | 11 +- .../validator/LineLaunchValidatorTest.java | 3 +- .../validator/LineOfSightValidatorTest.java | 3 +- .../validator/RangeValidatorTest.java | 3 +- .../validator/SpellLaunchValidatorTest.java | 3 +- .../validator/StatesValidatorTest.java | 3 +- .../validator/TargetCellValidatorTest.java | 3 +- .../WeaponConstraintsValidatorTest.java | 3 +- .../fight/fighter/EmptySpellListTest.java | 49 +++ .../StaticInvocationFighterTest.java | 327 ++++++++++++++++++ .../game/fight/turn/FightTurnListTest.java | 7 +- .../game/fight/turn/action/cast/CastTest.java | 3 +- .../turn/action/cast/SpellNotFoundTest.java | 3 +- .../action/closeCombat/CloseCombatTest.java | 3 +- .../FightActionsFactoryRegistryTest.java | 3 +- .../game/fight/turn/action/move/MoveTest.java | 3 +- .../StopOnBattlefieldObjectValidatorTest.java | 3 +- .../validators/StopOnEnemyValidatorTest.java | 3 +- .../move/validators/TackleValidatorTest.java | 3 +- .../order/AlternateTeamFighterOrderTest.java | 11 +- .../turn/action/SendFightActionTest.java | 3 +- .../out/fight/action/FightActionTest.java | 9 +- 103 files changed, 1063 insertions(+), 352 deletions(-) create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractPlayableFighter.java create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellList.java create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/PlayableFighter.java create mode 100644 src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java create mode 100644 src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellListTest.java create mode 100644 src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighterTest.java diff --git a/src/main/java/fr/quatrevieux/araknemu/data/living/constraint/player/PlayerConstraints.java b/src/main/java/fr/quatrevieux/araknemu/data/living/constraint/player/PlayerConstraints.java index b12ffceef..424cfe2d3 100644 --- a/src/main/java/fr/quatrevieux/araknemu/data/living/constraint/player/PlayerConstraints.java +++ b/src/main/java/fr/quatrevieux/araknemu/data/living/constraint/player/PlayerConstraints.java @@ -19,8 +19,8 @@ package fr.quatrevieux.araknemu.data.living.constraint.player; -import fr.quatrevieux.araknemu.data.living.constraint.ConstraintBuilder; import fr.quatrevieux.araknemu.data.living.constraint.AbstractConstraintBuilderFactory; +import fr.quatrevieux.araknemu.data.living.constraint.ConstraintBuilder; import fr.quatrevieux.araknemu.data.living.entity.player.Player; import fr.quatrevieux.araknemu.data.living.repository.player.PlayerRepository; import fr.quatrevieux.araknemu.game.GameConfiguration; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/admin/account/AccountContext.java b/src/main/java/fr/quatrevieux/araknemu/game/admin/account/AccountContext.java index 17ca9e5d0..55a4453ec 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/admin/account/AccountContext.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/admin/account/AccountContext.java @@ -21,8 +21,8 @@ import fr.quatrevieux.araknemu.game.account.GameAccount; import fr.quatrevieux.araknemu.game.admin.context.AbstractContext; -import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator; +import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.SimpleContext; import java.util.List; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContext.java b/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContext.java index 51eaf17b2..94dc62b9e 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContext.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContext.java @@ -21,8 +21,8 @@ import fr.quatrevieux.araknemu.core.di.ContainerException; import fr.quatrevieux.araknemu.game.admin.context.AbstractContext; -import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator; +import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.SimpleContext; import java.util.List; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContextResolver.java b/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContextResolver.java index c06c05a3e..8cf229698 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContextResolver.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/admin/debug/DebugContextResolver.java @@ -20,9 +20,9 @@ package fr.quatrevieux.araknemu.game.admin.debug; import fr.quatrevieux.araknemu.game.admin.AdminPerformer; +import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator; import fr.quatrevieux.araknemu.game.admin.context.ConfigurableContextResolver; import fr.quatrevieux.araknemu.game.admin.context.Context; -import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/admin/player/PlayerContext.java b/src/main/java/fr/quatrevieux/araknemu/game/admin/player/PlayerContext.java index 2c0e9684f..ee0c9ff5d 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/admin/player/PlayerContext.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/admin/player/PlayerContext.java @@ -20,8 +20,8 @@ package fr.quatrevieux.araknemu.game.admin.player; import fr.quatrevieux.araknemu.game.admin.context.AbstractContext; -import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator; +import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.SimpleContext; import fr.quatrevieux.araknemu.game.player.GamePlayer; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/admin/server/ServerContext.java b/src/main/java/fr/quatrevieux/araknemu/game/admin/server/ServerContext.java index 17269d39c..037cda68c 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/admin/server/ServerContext.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/admin/server/ServerContext.java @@ -20,8 +20,8 @@ package fr.quatrevieux.araknemu.game.admin.server; import fr.quatrevieux.araknemu.game.admin.context.AbstractContext; -import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.AbstractContextConfigurator; +import fr.quatrevieux.araknemu.game.admin.context.Context; import fr.quatrevieux.araknemu.game.admin.context.SimpleContext; import java.util.List; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java index 7ae1e6680..cd32527f1 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java @@ -29,6 +29,7 @@ import fr.quatrevieux.araknemu.game.fight.event.FightStopped; import fr.quatrevieux.araknemu.game.fight.exception.InvalidFightStateException; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightMap; import fr.quatrevieux.araknemu.game.fight.module.FightModule; import fr.quatrevieux.araknemu.game.fight.spectator.Spectators; @@ -73,7 +74,7 @@ public final class Fight implements Dispatcher, Sender { private final ListenerAggregate dispatcher; private final ScheduledExecutorService executor; private final Spectators spectators; - private final ActionsFactory actions; + private final ActionsFactory actions; private final FighterList fighters; private final Lock executorLock = new ReentrantLock(); @@ -84,7 +85,7 @@ public final class Fight implements Dispatcher, Sender { private volatile boolean alive = true; @SuppressWarnings({"assignment", "argument"}) - public Fight(int id, FightType type, FightMap map, List teams, StatesFlow statesFlow, Logger logger, ScheduledExecutorService executor, ActionsFactory actions) { + public Fight(int id, FightType type, FightMap map, List teams, StatesFlow statesFlow, Logger logger, ScheduledExecutorService executor, ActionsFactory actions) { this.id = id; this.type = type; this.map = map; @@ -206,7 +207,7 @@ public EffectsHandler effects() { /** * Get available fight actions factories */ - public ActionsFactory actions() { + public ActionsFactory actions() { return actions; } @@ -237,22 +238,7 @@ public void dispatch(Object event) { * @see Fight#dispatch(Object) To dispatch on the Fight's listeners */ public void dispatchToAll(Object event) { - if (turnList != null) { - for (Fighter fighter : turnList.fighters()) { - if (fighter.isOnFight()) { - fighter.dispatch(event); - } - } - } else { - for (FightTeam team : teams) { - for (Fighter fighter : team.fighters()) { - if (fighter.isOnFight()) { - fighter.dispatch(event); - } - } - } - } - + fighters.dispatch(event); spectators.dispatch(event); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java index 0a8c0a164..6e4b565f7 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/FighterList.java @@ -19,8 +19,10 @@ package fr.quatrevieux.araknemu.game.fight; +import fr.quatrevieux.araknemu.core.event.Dispatcher; import fr.quatrevieux.araknemu.game.fight.event.FighterRemoved; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import org.checkerframework.checker.nullness.qual.NonNull; @@ -34,7 +36,7 @@ /** * Handle the fighters list of a fight */ -public final class FighterList implements Iterable { +public final class FighterList implements Iterable, Dispatcher { private final Fight fight; private final Set fighters = new LinkedHashSet<>(); @@ -47,6 +49,15 @@ public FighterList(Fight fight) { return fighters.iterator(); } + @Override + public void dispatch(Object event) { + for (Fighter fighter : fighters) { + if (fighter.isOnFight()) { + fighter.dispatch(event); + } + } + } + /** * Get all fighters as collection. */ @@ -61,7 +72,7 @@ public Collection all() { * @param cell The cell where the fighter will be placed * * @see Fighter#joinFight(Fight, FightCell) Will be called by this method - * @see #joinTurnList(Fighter, FightCell) Call this method if you want to add the fighter to the turn list + * @see #joinTurnList(PlayableFighter, FightCell) Call this method if you want to add the fighter to the turn list */ public void join(Fighter fighter, FightCell cell) { fighter.joinFight(fight, cell); @@ -76,9 +87,9 @@ public void join(Fighter fighter, FightCell cell) { * @param fighter The fighter to add * @param cell The cell where the fighter will be placed * - * @see fr.quatrevieux.araknemu.game.fight.turn.FightTurnList#add(Fighter) Will be called by this method + * @see fr.quatrevieux.araknemu.game.fight.turn.FightTurnList#add(PlayableFighter) Will be called by this method */ - public void joinTurnList(Fighter fighter, FightCell cell) { + public void joinTurnList(PlayableFighter fighter, FightCell cell) { join(fighter, cell); fight.turnList().add(fighter); } @@ -94,8 +105,8 @@ public void joinTurnList(Fighter fighter, FightCell cell) { public void leave(Fighter fighter) { fighters.remove(fighter); - if (fight.active()) { - fight.turnList().remove(fighter); // @todo discriminate active vs static fighter + if (fight.active() && fighter instanceof PlayableFighter) { + fight.turnList().remove((PlayableFighter) fighter); } fight.dispatch(new FighterRemoved(fighter, fight)); diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java index b529d7c5f..d06fbb2d0 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAI.java @@ -23,8 +23,8 @@ import fr.quatrevieux.araknemu.game.fight.ai.action.ActionGenerator; import fr.quatrevieux.araknemu.game.fight.ai.action.FightAiActionFactoryAdapter; import fr.quatrevieux.araknemu.game.fight.ai.util.AIHelper; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldMap; import fr.quatrevieux.araknemu.game.fight.turn.Turn; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; @@ -42,10 +42,10 @@ * and the next action is scheduled after the last one. * So the AI execution is not blocking, and executed in parallel of the turn timer. */ -public final class FighterAI implements Runnable, AI { - private final Fighter fighter; +public final class FighterAI implements Runnable, AI { + private final PlayableFighter fighter; private final Fight fight; - private final ActionGenerator generator; + private final ActionGenerator generator; private final AIHelper helper; private @Nullable Turn turn; @@ -57,7 +57,7 @@ public final class FighterAI implements Runnable, AI { * @param generator The action generator */ @SuppressWarnings({"argument", "assignment"}) - public FighterAI(Fighter fighter, Fight fight, ActionGenerator generator) { + public FighterAI(PlayableFighter fighter, Fight fight, ActionGenerator generator) { this.fighter = fighter; this.fight = fight; this.generator = generator; @@ -105,7 +105,7 @@ public void run() { } @Override - public Fighter fighter() { + public PlayableFighter fighter() { return fighter; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapter.java index 42b1d078c..a0487c018 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapter.java @@ -23,7 +23,7 @@ import fr.arakne.utils.maps.path.PathStep; import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.castable.validator.CastConstraintValidator; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldCell; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.map.FightMap; @@ -38,11 +38,11 @@ * Generated actions can be applied directly to fight */ public final class FightAiActionFactoryAdapter implements AiActionFactory { - private final Fighter fighter; + private final PlayableFighter fighter; private final Fight fight; - private final ActionsFactory actionFactory; + private final ActionsFactory actionFactory; - public FightAiActionFactoryAdapter(Fighter fighter, Fight fight, ActionsFactory actionFactory) { + public FightAiActionFactoryAdapter(PlayableFighter fighter, Fight fight, ActionsFactory actionFactory) { this.fighter = fighter; this.fight = fight; this.actionFactory = actionFactory; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/AbstractAiBuilderFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/AbstractAiBuilderFactory.java index be259b2cc..3838f44a1 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/AbstractAiBuilderFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/AbstractAiBuilderFactory.java @@ -22,31 +22,31 @@ import fr.quatrevieux.araknemu.game.fight.ai.AI; import fr.quatrevieux.araknemu.game.fight.ai.FighterAI; import fr.quatrevieux.araknemu.game.fight.ai.action.builder.GeneratorBuilder; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import java.util.Optional; /** * AiFactory implementation using a generator builder for configure the AI */ -public abstract class AbstractAiBuilderFactory implements AiFactory { +public abstract class AbstractAiBuilderFactory implements AiFactory { /** * Configure the AI generator */ - protected void configure(GeneratorBuilder builder) { + protected void configure(GeneratorBuilder builder) { // To implements if configure(GeneratorBuilder, Fighter) is not implemented } /** * Configure the AI generator */ - public void configure(GeneratorBuilder builder, Fighter fighter) { + public void configure(GeneratorBuilder builder, PlayableFighter fighter) { configure(builder); } @Override - public final Optional> create(Fighter fighter) { - final GeneratorBuilder builder = new GeneratorBuilder<>(); + public final Optional> create(PlayableFighter fighter) { + final GeneratorBuilder builder = new GeneratorBuilder<>(); configure(builder, fighter); diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactory.java index 9fe0bc95a..507af875a 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactory.java @@ -20,24 +20,27 @@ package fr.quatrevieux.araknemu.game.fight.ai.factory; import fr.quatrevieux.araknemu.game.fight.ai.AI; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; +import java.util.Arrays; +import java.util.List; import java.util.Optional; /** * Chain AI factories */ -public final class ChainAiFactory implements AiFactory { - private final AiFactory[] factories; +public final class ChainAiFactory implements AiFactory { + private final List> factories; - public ChainAiFactory(AiFactory... factories) { - this.factories = factories; + @SafeVarargs + public ChainAiFactory(AiFactory... factories) { + this.factories = Arrays.asList(factories); } @Override - public Optional> create(Fighter fighter) { - for (AiFactory factory : factories) { - final Optional> ai = factory.create(fighter); + public Optional> create(PlayableFighter fighter) { + for (AiFactory factory : factories) { + final Optional> ai = factory.create(fighter); if (ai.isPresent()) { return ai; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactory.java index c6506d126..b475ffac8 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactory.java @@ -14,13 +14,13 @@ * You should have received a copy of the GNU Lesser General Public License * along with Araknemu. If not, see . * - * Copyright (c) 2017-2019 Vincent Quatrevieux + * Copyright (c) 2017-2023 Vincent Quatrevieux */ package fr.quatrevieux.araknemu.game.fight.ai.factory; import fr.quatrevieux.araknemu.game.fight.ai.AI; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter; import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; @@ -33,20 +33,20 @@ /** * Registry of AI factories for monsters */ -public final class MonsterAiFactory implements AiFactory { - private final Map> factories = new HashMap<>(); +public final class MonsterAiFactory implements AiFactory { + private final Map> factories = new HashMap<>(); - public void register(String type, AiFactory factory) { + public void register(String type, AiFactory factory) { factories.put(type, factory); } @Override - public Optional> create(Fighter fighter) { + public Optional> create(PlayableFighter fighter) { return fighter.apply(new ResolveAi()).get(); } class ResolveAi implements FighterOperation { - private @MonotonicNonNull AI ai; + private @MonotonicNonNull AI ai; @Override public void onMonster(MonsterFighter fighter) { @@ -58,12 +58,12 @@ public void onInvocation(InvocationFighter fighter) { resolve(fighter, fighter.monster().ai()); } - public Optional> get() { + public Optional> get() { return Optional.ofNullable(ai); } - private void resolve(Fighter fighter, String type) { - final AiFactory factory = factories.get(type); + private void resolve(PlayableFighter fighter, String type) { + final AiFactory factory = factories.get(type); if (factory == null) { throw new IllegalArgumentException("Unsupported AI type " + type); diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Aggressive.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Aggressive.java index e69b1780c..cd7da1c1f 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Aggressive.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Aggressive.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.factory.AbstractAiBuilderFactory; import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.effect.SpellEffect; @@ -40,7 +41,7 @@ public Aggressive(Simulator simulator) { } @Override - public void configure(GeneratorBuilder builder, Fighter fighter) { + public void configure(GeneratorBuilder builder, PlayableFighter fighter) { builder .boostSelf(simulator) .attack(simulator) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Fixed.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Fixed.java index 045b113ec..b2e9843e7 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Fixed.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Fixed.java @@ -22,7 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.action.builder.GeneratorBuilder; import fr.quatrevieux.araknemu.game.fight.ai.factory.AbstractAiBuilderFactory; import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; /** * AI for poutch ingball or any fixed monsters @@ -36,7 +36,7 @@ public Fixed(Simulator simulator) { } @Override - public void configure(GeneratorBuilder builder) { + public void configure(GeneratorBuilder builder) { builder.attack(simulator); } } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Runaway.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Runaway.java index 8a5554f63..2030a59e3 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Runaway.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Runaway.java @@ -22,7 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.action.builder.GeneratorBuilder; import fr.quatrevieux.araknemu.game.fight.ai.factory.AbstractAiBuilderFactory; import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; /** * AI for run away monsters (like Tofu) @@ -37,7 +37,7 @@ public Runaway(Simulator simulator) { } @Override - public void configure(GeneratorBuilder builder) { + public void configure(GeneratorBuilder builder) { builder .boostSelf(simulator) .attackFromNearestCell(simulator) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Support.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Support.java index 69fbf4f28..f7708e55e 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Support.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Support.java @@ -23,7 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.factory.AbstractAiBuilderFactory; import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; import fr.quatrevieux.araknemu.game.fight.ai.util.Predicates; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; /** * AI for support allies on fight @@ -45,7 +45,7 @@ public Support(Simulator simulator, AbstractAiBuilderFactory aloneAi) { } @Override - public void configure(GeneratorBuilder builder, Fighter fighter) { + public void configure(GeneratorBuilder builder, PlayableFighter fighter) { builder.when(Predicates.hasAllies(), cb -> cb .success(sb -> sb .moveToBoost(simulator) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Tactical.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Tactical.java index 0f35ef5e6..d721f1aad 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Tactical.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/factory/type/Tactical.java @@ -23,7 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.factory.AbstractAiBuilderFactory; import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; import fr.quatrevieux.araknemu.game.fight.ai.util.Predicates; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; /** * AI between {@link Runaway} and {@link Aggressive} @@ -41,7 +41,7 @@ public Tactical(Simulator simulator) { } @Override - public void configure(GeneratorBuilder builder) { + public void configure(GeneratorBuilder builder) { builder .boostSelf(simulator) .attackFromBestCell(simulator) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyActiveFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyActiveFighter.java index 7c317576d..d0ff92d35 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyActiveFighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyActiveFighter.java @@ -24,8 +24,8 @@ import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs; import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics; -import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.States; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldCell; import fr.quatrevieux.araknemu.game.fight.team.Team; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyPassiveFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyPassiveFighter.java index 688c18654..277dd9cf9 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyPassiveFighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/ai/proxy/ProxyPassiveFighter.java @@ -24,8 +24,8 @@ import fr.quatrevieux.araknemu.game.fight.ai.AI; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buffs; import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics; -import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.States; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldCell; import fr.quatrevieux.araknemu.game.fight.team.Team; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/BaseCastScope.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/BaseCastScope.java index db5d0c316..1db6503e5 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/BaseCastScope.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/BaseCastScope.java @@ -48,6 +48,7 @@ public class BaseCastScope imp private final List effects; private final Map targetMapping = new HashMap<>(); + @SuppressWarnings("unchecked") protected BaseCastScope(Castable action, F caster, C target, List effects) { this(action, caster, (C) caster.cell(), target, effects); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandler.java index 3e8ee5ed3..b9214a01d 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandler.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/characteristic/StealCharacteristicHandler.java @@ -21,8 +21,8 @@ import fr.quatrevieux.araknemu.data.constant.Characteristic; import fr.quatrevieux.araknemu.game.fight.Fight; -import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.castable.Castable; +import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectValue; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buff; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffEffect; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java index 8059c24e3..3a5af3a9f 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandler.java @@ -22,8 +22,8 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.EffectHandler; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; import fr.quatrevieux.araknemu.game.monster.MonsterService; import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect; @@ -58,7 +58,7 @@ public void buff(FightCastScope cast, FightCastScope.EffectScope effect) { @Override public void handle(FightCastScope cast, FightCastScope.EffectScope effect) { - final Fighter invocation = fighterFactory.generate(id -> new InvocationFighter( + final PlayableFighter invocation = fighterFactory.generate(id -> new InvocationFighter( id, monsterService.load(effect.effect().min()).get(effect.effect().max()), cast.caster().team(), diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java index 7f56630d7..3be6a1d5f 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandler.java @@ -24,7 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.EffectHandler; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; -import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.StaticInvocationFighter; import fr.quatrevieux.araknemu.game.monster.MonsterService; import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect; @@ -38,12 +38,12 @@ * - #1 (min) : monster id * - #2 (max) : grade number * - * @see InvocationFighter Invoked fighter @todo change + * @see StaticInvocationFighter Invoked fighter */ public final class StaticInvocationHandler implements EffectHandler { - private final MonsterService monsterService; - private final FighterFactory fighterFactory; - private final Fight fight; + private final MonsterService monsterService; + private final FighterFactory fighterFactory; + private final Fight fight; public StaticInvocationHandler(MonsterService monsterService, FighterFactory fighterFactory, Fight fight) { this.monsterService = monsterService; @@ -58,8 +58,7 @@ public void buff(FightCastScope cast, FightCastScope.EffectScope effect) { @Override public void handle(FightCastScope cast, FightCastScope.EffectScope effect) { - // @todo do not use InvocationFighter - final Fighter invocation = fighterFactory.generate(id -> new InvocationFighter( + final Fighter invocation = fighterFactory.generate(id -> new StaticInvocationFighter( id, monsterService.load(effect.effect().min()).get(effect.effect().max()), cast.caster().team(), diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/InvisibilityHandler.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/InvisibilityHandler.java index 0456c23e8..8d83f892c 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/InvisibilityHandler.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/misc/InvisibilityHandler.java @@ -21,8 +21,8 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.castable.CastScope; -import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.castable.Castable; +import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectsUtils; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.Buff; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffHook; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/object/Trap.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/object/Trap.java index 48461884d..730342bf8 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/object/Trap.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/object/Trap.java @@ -40,8 +40,6 @@ /** * Trap object, created by {@link AddTrapHandler} - * - * @todo handle trap damage bonus */ final class Trap implements BattlefieldObject { private static final UpdateCells.PropertyValue[] CELL_PROPERTIES = new UpdateCells.PropertyValue[]{ diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java index a344fbdf9..fc7dd6895 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractFighter.java @@ -24,19 +24,16 @@ import fr.quatrevieux.araknemu.core.event.ListenerAggregate; import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffList; -import fr.quatrevieux.araknemu.game.fight.exception.FightException; import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterHidden; import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterInitialized; import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterMoved; import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterVisible; import fr.quatrevieux.araknemu.game.fight.map.FightCell; -import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.HashMap; import java.util.Map; -import java.util.function.Consumer; /** * Base class for implements a fighter @@ -53,7 +50,6 @@ public abstract class AbstractFighter implements Fighter { // Mutable attributes private @Nullable FightCell cell; private @MonotonicNonNull Fight fight; - private @Nullable FightTurn turn; private Direction orientation = Direction.SOUTH_EAST; private boolean hidden = false; @@ -141,39 +137,6 @@ public final void joinFight(Fight fight, FightCell startCell) { startCell.set(this); } - @Override - public void play(FightTurn turn) { - this.turn = turn; - } - - @Override - public void stop() { - turn = null; - } - - @Override - public final FightTurn turn() { - if (turn == null) { - throw new FightException("It's not your turn"); - } - - return turn; - } - - @Override - public final void perform(Consumer action) { - final FightTurn turn = this.turn; - - if (turn != null) { - action.accept(turn); - } - } - - @Override - public boolean isPlaying() { - return turn != null && turn.active(); - } - @Override public final void attach(Object key, Object value) { attachments.put(key, value); diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractPlayableFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractPlayableFighter.java new file mode 100644 index 000000000..7201bd4c5 --- /dev/null +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/AbstractPlayableFighter.java @@ -0,0 +1,67 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2023 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.fighter; + +import fr.quatrevieux.araknemu.game.fight.exception.FightException; +import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.function.Consumer; + +/** + * Base class for implements a fighter which can play + * Add a {@link FightTurn} handling + */ +public abstract class AbstractPlayableFighter extends AbstractFighter implements PlayableFighter { + private @Nullable FightTurn turn; + + @Override + public void play(FightTurn turn) { + this.turn = turn; + } + + @Override + public void stop() { + turn = null; + } + + @Override + public final FightTurn turn() { + if (turn == null) { + throw new FightException("It's not your turn"); + } + + return turn; + } + + @Override + public final void perform(Consumer action) { + final FightTurn turn = this.turn; + + if (turn != null) { + action.accept(turn); + } + } + + @Override + public boolean isPlaying() { + return turn != null && turn.active(); + } +} diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellList.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellList.java new file mode 100644 index 000000000..14a08ca9d --- /dev/null +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellList.java @@ -0,0 +1,54 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2023 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.fighter; + +import fr.quatrevieux.araknemu.game.spell.Spell; +import fr.quatrevieux.araknemu.game.spell.boost.SpellsBoosts; + +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Null object for {@link FighterSpellList} + */ +public final class EmptySpellList implements FighterSpellList { + public static final EmptySpellList INSTANCE = new EmptySpellList(); + + @Override + public void boost(int spellId, SpellsBoosts.Modifier modifier, int value) { + // do nothing + } + + @Override + public Spell get(int spellId) { + throw new NoSuchElementException(); + } + + @Override + public boolean has(int spellId) { + return false; + } + + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } +} diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java index 0d488828b..d5238ec5c 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/Fighter.java @@ -24,15 +24,11 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffList; import fr.quatrevieux.araknemu.game.fight.castable.weapon.CastableWeapon; -import fr.quatrevieux.araknemu.game.fight.exception.FightException; import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.team.FightTeam; -import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.function.Consumer; - /** * Base fighter */ @@ -78,30 +74,13 @@ public interface Fighter extends Dispatcher, ActiveFighter { */ public CastableWeapon weapon(); - /** - * Get the current fighter turn - * - * @throws FightException If it's not the turn of the current fighter - * - * @see Fighter#perform(Consumer) For perform action on fighter in a safe way (no exception) - */ - public FightTurn turn(); - - /** - * Perform an action on the current active turn - * The action will take as parameter the current turn - * - * If it's not the turn of the fighter, this method will not call the action - * - * @param action Action to perform - */ - public void perform(Consumer action); - /** * Does the current fighter can play ? * Return true if it's the turn of the current fighter * - * @see Fighter#turn() Can be called if this method return true + * Note: this method can return true only if the fighter is an instance of {@link PlayableFighter} + * + * @see PlayableFighter#turn() Can be called if this method return true */ public boolean isPlaying(); @@ -151,18 +130,6 @@ public default void attach(Object value) { */ public boolean ready(); - /** - * Start to play the turn - * - * @param turn The fighter turn - */ - public void play(FightTurn turn); - - /** - * Stop the turn - */ - public void stop(); - /** * Check if the fighter is on the fight (The fight is set and is on a cell) */ diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterFactory.java index 5406f1ced..cb586ce13 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/FighterFactory.java @@ -47,12 +47,12 @@ public interface FighterFactory { * Generate a fighter with a unique ID * The generated ID will be a negative integer */ - public Fighter generate(FighterGenerator generator); + public F generate(FighterGenerator generator); - public static interface FighterGenerator { + public static interface FighterGenerator { /** * Create a fighter with a generated ID */ - public Fighter create(int id); + public F create(int id); } } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/PlayableFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/PlayableFighter.java new file mode 100644 index 000000000..f7bc18a74 --- /dev/null +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/PlayableFighter.java @@ -0,0 +1,61 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2023 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.fighter; + +import fr.quatrevieux.araknemu.game.fight.exception.FightException; +import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; + +import java.util.function.Consumer; + +/** + * Base type for a fighter which can play a turn + */ +public interface PlayableFighter extends Fighter { + /** + * Get the current fighter turn + * + * @throws FightException If it's not the turn of the current fighter + * + * @see PlayableFighter#perform(Consumer) For perform action on fighter in a safe way (no exception) + */ + public FightTurn turn(); + + /** + * Perform an action on the current active turn + * The action will take as parameter the current turn + * + * If it's not the turn of the fighter, this method will not call the action + * + * @param action Action to perform + */ + public void perform(Consumer action); + + /** + * Start to play the turn + * + * @param turn The fighter turn + */ + public void play(FightTurn turn); + + /** + * Stop the turn + */ + public void stop(); +} diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java index 0efecf676..091e7756c 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/InvocationFighter.java @@ -21,13 +21,13 @@ import fr.quatrevieux.araknemu.game.fight.castable.weapon.CastableWeapon; import fr.quatrevieux.araknemu.game.fight.exception.FightException; -import fr.quatrevieux.araknemu.game.fight.fighter.AbstractFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.AbstractPlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterSpellList; import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList; -import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighterSprite; import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; import fr.quatrevieux.araknemu.game.fight.team.FightTeam; @@ -40,7 +40,7 @@ * Fighter for invoked monster * Its characteristics are modified by the invoker level */ -public final class InvocationFighter extends AbstractFighter { +public final class InvocationFighter extends AbstractPlayableFighter { private final int id; private final Monster monster; private final FightTeam team; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java new file mode 100644 index 000000000..52133a3e4 --- /dev/null +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighter.java @@ -0,0 +1,132 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2022 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.fighter.invocation; + +import fr.quatrevieux.araknemu.game.fight.castable.weapon.CastableWeapon; +import fr.quatrevieux.araknemu.game.fight.exception.FightException; +import fr.quatrevieux.araknemu.game.fight.fighter.AbstractFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterLife; +import fr.quatrevieux.araknemu.game.fight.fighter.EmptySpellList; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList; +import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighterSprite; +import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; +import fr.quatrevieux.araknemu.game.fight.team.FightTeam; +import fr.quatrevieux.araknemu.game.monster.Monster; +import fr.quatrevieux.araknemu.game.world.creature.Sprite; +import org.checkerframework.checker.index.qual.Positive; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Fighter for invoked monster + * Its characteristics are modified by the invoker level + */ +public final class StaticInvocationFighter extends AbstractFighter { + private final int id; + private final Monster monster; + private final FightTeam team; + private final BaseFighterLife life; + private final FighterCharacteristics characteristics; + private final MonsterFighterSprite sprite; + private final FighterData invoker; + + @SuppressWarnings({"assignment", "argument"}) + public StaticInvocationFighter(int id, Monster monster, FightTeam team, FighterData invoker) { + this.id = id; + this.monster = monster; + this.team = team; + this.invoker = invoker; + + this.life = new BaseFighterLife(this, Math.round(monster.life() * InvocationFighterCharacteristics.modifier(invoker))); + this.characteristics = new InvocationFighterCharacteristics(monster, this, invoker); + this.sprite = new MonsterFighterSprite(this, monster); + } + + @Override + public O apply(O operation) { + operation.onStaticInvocation(this); + + return operation; + } + + @Override + public @Positive int level() { + return monster.level(); + } + + @Override + public boolean ready() { + return true; + } + + @Override + public FightTeam team() { + return team; + } + + @Override + public CastableWeapon weapon() { + throw new FightException("The fighter do not have any weapon"); + } + + @Override + public int id() { + return id; + } + + @Override + public Sprite sprite() { + return sprite; + } + + @Override + public FighterSpellList spells() { + return EmptySpellList.INSTANCE; + } + + @Override + public FighterCharacteristics characteristics() { + return characteristics; + } + + @Override + public FighterLife life() { + return life; + } + + @Override + public @NonNull FighterData invoker() { + return invoker; + } + + /** + * Get the invoked monster + */ + public Monster monster() { + return monster; + } + + @Override + public boolean isPlaying() { + return false; + } +} diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighter.java index e3ce2d78f..891246add 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/monster/MonsterFighter.java @@ -21,13 +21,13 @@ import fr.quatrevieux.araknemu.game.fight.castable.weapon.CastableWeapon; import fr.quatrevieux.araknemu.game.fight.exception.FightException; -import fr.quatrevieux.araknemu.game.fight.fighter.AbstractFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.AbstractPlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterSpellList; import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList; -import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; import fr.quatrevieux.araknemu.game.fight.team.FightTeam; import fr.quatrevieux.araknemu.game.monster.Monster; @@ -39,7 +39,7 @@ /** * Fighter for a monster */ -public final class MonsterFighter extends AbstractFighter { +public final class MonsterFighter extends AbstractPlayableFighter { private final int id; private final Monster monster; private final FightTeam team; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/operation/FighterOperation.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/operation/FighterOperation.java index 170ac9ba4..f44f9f837 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/operation/FighterOperation.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/operation/FighterOperation.java @@ -21,6 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.StaticInvocationFighter; import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; @@ -52,6 +53,13 @@ public default void onInvocation(InvocationFighter fighter) { onGenericFighter(fighter); } + /** + * Apply the operation to an StaticInvocationFighter + */ + public default void onStaticInvocation(StaticInvocationFighter fighter) { + onGenericFighter(fighter); + } + /** * Apply the operation to a generic fighter type */ diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighter.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighter.java index 6015ac077..85e1918b7 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighter.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/fighter/player/PlayerFighter.java @@ -22,13 +22,12 @@ import fr.quatrevieux.araknemu.game.fight.castable.weapon.CastableWeapon; import fr.quatrevieux.araknemu.game.fight.event.FighterReadyStateChanged; import fr.quatrevieux.araknemu.game.fight.exception.FightException; -import fr.quatrevieux.araknemu.game.fight.fighter.AbstractFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.AbstractPlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.BaseFighterSpellList; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterCharacteristics; +import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList; -import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; import fr.quatrevieux.araknemu.game.fight.team.FightTeam; import fr.quatrevieux.araknemu.game.item.type.Weapon; @@ -46,7 +45,7 @@ /** * Fighter for a player */ -public final class PlayerFighter extends AbstractFighter implements Fighter, PlayerSessionScope { +public final class PlayerFighter extends AbstractPlayableFighter implements PlayerSessionScope { private final GamePlayer player; private final PlayerFighterProperties properties; private final PlayerFighterSprite sprite; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/AiModule.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/AiModule.java index 5f593c2d4..e61499140 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/AiModule.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/AiModule.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.FighterAI; import fr.quatrevieux.araknemu.game.fight.ai.factory.AiFactory; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterInitialized; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.event.TurnStarted; @@ -31,9 +32,9 @@ * Fight module for enable AI */ public final class AiModule implements FightModule { - private final AiFactory factory; + private final AiFactory factory; - public AiModule(AiFactory factory) { + public AiModule(AiFactory factory) { this.factory = factory; } @@ -43,7 +44,11 @@ public Listener[] listeners() { new Listener() { @Override public void on(FighterInitialized event) { - init(event.fighter()); + final Fighter fighter = event.fighter(); + + if (fighter instanceof PlayableFighter) { + init((PlayableFighter) fighter); + } } @Override @@ -68,7 +73,7 @@ public Class event() { /** * Initialize the AI for the fighter (if supported) */ - private void init(Fighter fighter) { + private void init(PlayableFighter fighter) { factory.create(fighter).ifPresent(fighter::attach); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java index 0df135c3d..0f40c6910 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/module/CommonEffectsModule.java @@ -24,8 +24,8 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.castable.effect.EffectsHandler; import fr.quatrevieux.araknemu.game.fight.castable.effect.Element; -import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.HealOrMultiplyDamageHandler; import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.AlterResistanceHandler; +import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.HealOrMultiplyDamageHandler; import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.ReduceDamageHandler; import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.ReflectDamageHandler; import fr.quatrevieux.araknemu.game.fight.castable.effect.handler.armor.SpellReturnHandler; diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurn.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurn.java index d2de87c93..5f06d5aaf 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurn.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurn.java @@ -21,7 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.exception.FightException; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionHandler; import fr.quatrevieux.araknemu.game.fight.turn.event.TurnStarted; @@ -44,7 +44,7 @@ public final class FightTurn implements Turn { private final AtomicBoolean active = new AtomicBoolean(false); - private final Fighter fighter; + private final PlayableFighter fighter; private final Fight fight; private final Duration duration; @@ -54,7 +54,7 @@ public final class FightTurn implements Turn { private @MonotonicNonNull FighterTurnPoints points; @SuppressWarnings({"assignment", "argument"}) - public FightTurn(Fighter fighter, Fight fight, Duration duration) { + public FightTurn(PlayableFighter fighter, Fight fight, Duration duration) { this.fighter = fighter; this.fight = fight; this.duration = duration; @@ -62,7 +62,7 @@ public FightTurn(Fighter fighter, Fight fight, Duration duration) { } @Override - public Fighter fighter() { + public PlayableFighter fighter() { return fighter; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java index 5c69bfe05..58f071aa7 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnList.java @@ -21,6 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.event.NextTurnInitiated; import fr.quatrevieux.araknemu.game.fight.turn.event.TurnListChanged; @@ -38,8 +39,8 @@ public final class FightTurnList { private final Fight fight; - private final List fighters; - private Fighter current; + private final List fighters; + private PlayableFighter current; private @Nullable FightTurn turn; private int index; private final AtomicBoolean active = new AtomicBoolean(false); @@ -58,7 +59,7 @@ public FightTurnList(Fight fight, FighterOrderStrategy orderStrategy) { /** * Get all fighters ordered by their turn order */ - public List fighters() { + public List fighters() { return fighters; } @@ -69,7 +70,7 @@ public List fighters() { * * @see TurnListChanged Event triggered after the list is updated */ - public void remove(Fighter fighter) { + public void remove(PlayableFighter fighter) { final int index = fighters.indexOf(fighter); if (index == -1) { @@ -101,7 +102,7 @@ public void remove(Fighter fighter) { * * @see TurnListChanged Event triggered after the list is updated */ - public void add(Fighter fighter) { + public void add(PlayableFighter fighter) { fighters.add(index + 1, fighter); fight.dispatch(new TurnListChanged(this)); } @@ -118,7 +119,7 @@ public Optional current() { /** * Get the current turn fighter */ - public Fighter currentFighter() { + public PlayableFighter currentFighter() { return current; } @@ -157,7 +158,7 @@ public void stop() { void next() { // next is called internally by turn system, and fighters if used only with active turn system // so fighters is always non-null - final List fighters = NullnessUtil.castNonNull(this.fighters); + final List fighters = NullnessUtil.castNonNull(this.fighters); turn = null; fight.dispatch(new NextTurnInitiated()); diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionResult.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionResult.java index 06b4f8f75..880a1c035 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionResult.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/ActionResult.java @@ -19,7 +19,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; /** @@ -34,7 +34,7 @@ public interface ActionResult { /** * The action performer */ - public Fighter performer(); + public PlayableFighter performer(); /** * The action arguments diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/Cast.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/Cast.java index 655a552d7..76358e905 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/Cast.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/Cast.java @@ -22,6 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.castable.spell.SpellConstraintsValidator; import fr.quatrevieux.araknemu.game.fight.castable.validator.CastConstraintValidator; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.operation.SendPacket; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.Turn; @@ -39,17 +40,17 @@ * Cast a spell */ public final class Cast implements Action { - private final Fighter caster; + private final PlayableFighter caster; private final Spell spell; private final FightCell target; private final CastConstraintValidator validator; private final CriticalityStrategy criticalityStrategy; - public Cast(Fighter caster, Spell spell, FightCell target) { + public Cast(PlayableFighter caster, Spell spell, FightCell target) { this(caster, spell, target, new SpellConstraintsValidator(), new BaseCriticalityStrategy()); } - public Cast(Fighter caster, Spell spell, FightCell target, CastConstraintValidator validator, CriticalityStrategy criticalityStrategy) { + public Cast(PlayableFighter caster, Spell spell, FightCell target, CastConstraintValidator validator, CriticalityStrategy criticalityStrategy) { this.caster = caster; this.spell = spell; this.target = target; @@ -90,7 +91,7 @@ public ActionResult start() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFactory.java index 29d6eb340..2166a6ef4 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFactory.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.cast; import fr.quatrevieux.araknemu.game.fight.castable.validator.CastConstraintValidator; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.map.FightMap; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; @@ -33,7 +33,7 @@ /** * Factory for cast action */ -public final class CastFactory implements CastActionFactory { +public final class CastFactory implements CastActionFactory { private final CastConstraintValidator validator; private final CriticalityStrategy criticalityStrategy; @@ -43,7 +43,7 @@ public CastFactory(CastConstraintValidator validator, CriticalityStrategy } @Override - public Action create(Fighter fighter, String[] arguments) { + public Action create(PlayableFighter fighter, String[] arguments) { if (arguments.length < 2) { throw new IllegalArgumentException("Invalid cast arguments"); } @@ -71,7 +71,7 @@ public ActionType type() { } @Override - public Cast create(Fighter performer, Spell spell, FightCell target) { + public Cast create(PlayableFighter performer, Spell spell, FightCell target) { return new Cast(performer, spell, target, validator, criticalityStrategy); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFailed.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFailed.java index c78bc959d..3ed9d0465 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFailed.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastFailed.java @@ -19,7 +19,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.cast; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; import fr.quatrevieux.araknemu.game.spell.Spell; @@ -28,10 +28,10 @@ * Result for critical failure for spell cast */ public final class CastFailed implements ActionResult { - private final Fighter caster; + private final PlayableFighter caster; private final Spell spell; - public CastFailed(Fighter caster, Spell spell) { + public CastFailed(PlayableFighter caster, Spell spell) { this.caster = caster; this.spell = spell; } @@ -42,7 +42,7 @@ public int action() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastSuccess.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastSuccess.java index 000ad6eaf..170c7e9e0 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastSuccess.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastSuccess.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.cast; import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; @@ -37,12 +37,12 @@ */ public final class CastSuccess implements ActionResult { private final Cast action; - private final Fighter caster; + private final PlayableFighter caster; private final Spell spell; private final FightCell target; private final boolean critical; - public CastSuccess(Cast action, Fighter caster, Spell spell, FightCell target, boolean critical) { + public CastSuccess(Cast action, PlayableFighter caster, Spell spell, FightCell target, boolean critical) { this.action = action; this.caster = caster; this.spell = spell; @@ -56,7 +56,7 @@ public int action() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFound.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFound.java index e283a25d4..1cc6acc0b 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFound.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFound.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.cast; import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.operation.SendPacket; import fr.quatrevieux.araknemu.game.fight.turn.Turn; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; @@ -34,9 +34,9 @@ * Fake action to perform when an invalid spell is required */ public final class SpellNotFound implements Action { - private final Fighter caster; + private final PlayableFighter caster; - public SpellNotFound(Fighter caster) { + public SpellNotFound(PlayableFighter caster) { this.caster = caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombat.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombat.java index 4ddf41f3c..ce3108425 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombat.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombat.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.closeCombat; import fr.quatrevieux.araknemu.game.fight.castable.weapon.WeaponConstraintsValidator; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.operation.SendPacket; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.Turn; @@ -37,16 +37,16 @@ * Use weapon / close combat attack */ public final class CloseCombat implements Action { - private final Fighter caster; + private final PlayableFighter caster; private final FightCell target; private final WeaponConstraintsValidator validator; private final CriticalityStrategy criticalityStrategy; - public CloseCombat(Fighter caster, FightCell target) { + public CloseCombat(PlayableFighter caster, FightCell target) { this(caster, target, new WeaponConstraintsValidator(), new BaseCriticalityStrategy()); } - public CloseCombat(Fighter caster, FightCell target, WeaponConstraintsValidator validator, CriticalityStrategy criticalityStrategy) { + public CloseCombat(PlayableFighter caster, FightCell target, WeaponConstraintsValidator validator, CriticalityStrategy criticalityStrategy) { this.caster = caster; this.target = target; this.validator = validator; @@ -81,7 +81,7 @@ public ActionResult start() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFactory.java index fc2da9783..e35ece1f4 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFactory.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.closeCombat; import fr.quatrevieux.araknemu.game.fight.castable.weapon.WeaponConstraintsValidator; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightMap; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; @@ -31,7 +31,7 @@ /** * Factory for close combat action */ -public final class CloseCombatFactory implements FightActionFactory { +public final class CloseCombatFactory implements FightActionFactory { private final WeaponConstraintsValidator validator; private final CriticalityStrategy criticalityStrategy; @@ -41,7 +41,7 @@ public CloseCombatFactory(WeaponConstraintsValidator validator, CriticalityStrat } @Override - public Action create(Fighter fighter, String[] arguments) { + public Action create(PlayableFighter fighter, String[] arguments) { if (arguments.length < 1) { throw new IllegalArgumentException("Invalid close combat arguments"); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFailed.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFailed.java index a254fa126..62b48ebd4 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFailed.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatFailed.java @@ -19,7 +19,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.closeCombat; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; @@ -27,9 +27,9 @@ * Result for critical failure for weapon cast */ public final class CloseCombatFailed implements ActionResult { - private final Fighter caster; + private final PlayableFighter caster; - public CloseCombatFailed(Fighter caster) { + public CloseCombatFailed(PlayableFighter caster) { this.caster = caster; } @@ -39,7 +39,7 @@ public int action() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatSuccess.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatSuccess.java index e5e36e98c..61f25dcbc 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatSuccess.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatSuccess.java @@ -21,7 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.castable.weapon.CastableWeapon; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; @@ -35,12 +35,12 @@ * Result for successfully weapon cast */ public final class CloseCombatSuccess implements ActionResult { - private final Fighter caster; + private final PlayableFighter caster; private final CastableWeapon weapon; private final FightCell target; private final boolean critical; - public CloseCombatSuccess(Fighter caster, CastableWeapon weapon, FightCell target, boolean critical) { + public CloseCombatSuccess(PlayableFighter caster, CastableWeapon weapon, FightCell target, boolean critical) { this.caster = caster; this.weapon = weapon; this.target = target; @@ -53,7 +53,7 @@ public int action() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return caster; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistry.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistry.java index b0315c58e..a4e942e0c 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistry.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistry.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.factory; import fr.quatrevieux.araknemu.game.fight.exception.FightException; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; import fr.quatrevieux.araknemu.game.fight.turn.action.cast.CastActionFactory; @@ -32,14 +32,14 @@ /** * Registry of all fight actions factories */ -public final class FightActionsFactoryRegistry implements ActionsFactory { - private final CastActionFactory castFactory; - private final FightActionFactory closeCombatFactory; - private final MoveActionFactory moveFactory; +public final class FightActionsFactoryRegistry implements ActionsFactory { + private final CastActionFactory castFactory; + private final FightActionFactory closeCombatFactory; + private final MoveActionFactory moveFactory; - private final Map> factories = new EnumMap<>(ActionType.class); + private final Map> factories = new EnumMap<>(ActionType.class); - public FightActionsFactoryRegistry(MoveActionFactory moveFactory, CastActionFactory castFactory, FightActionFactory closeCombatFactory) { + public FightActionsFactoryRegistry(MoveActionFactory moveFactory, CastActionFactory castFactory, FightActionFactory closeCombatFactory) { this.moveFactory = moveFactory; this.castFactory = castFactory; this.closeCombatFactory = closeCombatFactory; @@ -50,7 +50,7 @@ public FightActionsFactoryRegistry(MoveActionFactory moveFactory, CastA } @Override - public Action create(Fighter fighter, ActionType action, String[] arguments) { + public Action create(PlayableFighter fighter, ActionType action, String[] arguments) { if (!factories.containsKey(action)) { throw new FightException("Fight action " + action + " not found"); } @@ -59,21 +59,21 @@ public Action create(Fighter fighter, ActionType action, String[] arguments) { } @Override - public CastActionFactory cast() { + public CastActionFactory cast() { return castFactory; } @Override - public FightActionFactory closeCombat() { + public FightActionFactory closeCombat() { return closeCombatFactory; } @Override - public MoveActionFactory move() { + public MoveActionFactory move() { return moveFactory; } - private void register(FightActionFactory factory) { + private void register(FightActionFactory factory) { factories.put(factory.type(), factory); } } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/Move.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/Move.java index d515597b5..9d034a5e8 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/Move.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/Move.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.move; import fr.arakne.utils.maps.path.Path; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.Turn; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; @@ -34,11 +34,11 @@ * Move the fighter */ public final class Move implements Action { - private final Fighter fighter; + private final PlayableFighter fighter; private final Path path; private final FightPathValidator[] validators; - public Move(Fighter fighter, Path path, FightPathValidator[] validators) { + public Move(PlayableFighter fighter, Path path, FightPathValidator[] validators) { this.fighter = fighter; this.path = path; this.validators = validators; @@ -69,7 +69,7 @@ public ActionResult start() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return fighter; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFactory.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFactory.java index 40b4740c9..154f44b63 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFactory.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFactory.java @@ -20,7 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.action.move; import fr.arakne.utils.maps.path.Path; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; @@ -29,7 +29,7 @@ /** * Factory for move action */ -public final class MoveFactory implements MoveActionFactory { +public final class MoveFactory implements MoveActionFactory { private final FightPathValidator[] validators; public MoveFactory(FightPathValidator[] validators) { @@ -37,7 +37,7 @@ public MoveFactory(FightPathValidator[] validators) { } @Override - public Action create(Fighter fighter, String[] arguments) { + public Action create(PlayableFighter fighter, String[] arguments) { if (arguments.length < 1) { throw new IllegalArgumentException("Invalid move arguments"); } @@ -51,7 +51,7 @@ public ActionType type() { } @Override - public Move create(Fighter performer, Path path) { + public Move create(PlayableFighter performer, Path path) { return new Move(performer, path, validators); } } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFailed.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFailed.java index b84de7683..66595efdf 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFailed.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveFailed.java @@ -22,7 +22,7 @@ import fr.arakne.utils.maps.constant.Direction; import fr.arakne.utils.maps.path.Path; import fr.arakne.utils.maps.path.PathStep; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; @@ -33,14 +33,14 @@ * He'll lose all its MP, and some AP */ public final class MoveFailed implements MoveResult { - private final Fighter performer; + private final PlayableFighter performer; private final int lostActionPoints; /** * @param performer The current fighter * @param lostActionPoints Number of lost action points */ - public MoveFailed(Fighter performer, int lostActionPoints) { + public MoveFailed(PlayableFighter performer, int lostActionPoints) { this.performer = performer; this.lostActionPoints = lostActionPoints; } @@ -74,7 +74,7 @@ public Path path() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return performer; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveSuccess.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveSuccess.java index 6679467fa..2cd0fc518 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveSuccess.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveSuccess.java @@ -21,7 +21,7 @@ import fr.arakne.utils.maps.constant.Direction; import fr.arakne.utils.maps.path.Path; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; @@ -33,14 +33,14 @@ * A path can be truncated due to enemies on path, which will also result to a MoveSuccess result */ public final class MoveSuccess implements MoveResult { - private final Fighter performer; + private final PlayableFighter performer; private final Path path; /** * @param performer The current fighter which perform the action * @param path The new path */ - public MoveSuccess(Fighter performer, Path path) { + public MoveSuccess(PlayableFighter performer, Path path) { this.performer = performer; this.path = path; } @@ -66,7 +66,7 @@ public int lostActionPoints() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return performer; } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java index ce6b4b6f0..202dfb908 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java @@ -25,6 +25,7 @@ import fr.quatrevieux.araknemu.data.constant.Characteristic; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.action.move.Move; import fr.quatrevieux.araknemu.game.fight.turn.action.move.MoveFailed; @@ -54,7 +55,7 @@ public TackleValidator(int[] ignoredStates) { @Override public MoveResult validate(Move move, MoveResult result) { - final Fighter performer = move.performer(); + final PlayableFighter performer = move.performer(); // Ignore tackle if he has at least on of those states if (performer.states().hasOne(ignoredStates)) { diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrder.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrder.java index 4502aa649..e46859c81 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrder.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrder.java @@ -20,6 +20,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.order; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.team.FightTeam; import fr.quatrevieux.araknemu.util.Asserter; import org.checkerframework.checker.nullness.util.NullnessUtil; @@ -34,9 +35,9 @@ */ public final class AlternateTeamFighterOrder implements FighterOrderStrategy { @Override - public List compute(List teams) { - final List> fightersByTeam = computeTeamsOrder(teams); - final List orderedFighters = new ArrayList<>(); + public List compute(List teams) { + final List> fightersByTeam = computeTeamsOrder(teams); + final List orderedFighters = new ArrayList<>(); boolean hasChanges; @@ -44,7 +45,7 @@ public List compute(List teams) { hasChanges = false; // Poll the next fighter on each teams - for (Queue fighters : fightersByTeam) { + for (Queue fighters : fightersByTeam) { if (!fighters.isEmpty()) { orderedFighters.add(fighters.remove()); hasChanges = true; @@ -55,17 +56,21 @@ public List compute(List teams) { return orderedFighters; } - private List> computeTeamsOrder(List teams) { - final List> fightersByTeam = new ArrayList<>(); + private List> computeTeamsOrder(List teams) { + final List> fightersByTeam = new ArrayList<>(); for (FightTeam team : teams) { // Sort team fighters by their initiative desc - final Queue fighters = new PriorityQueue<>( + final Queue fighters = new PriorityQueue<>( Asserter.castPositive(team.fighters().size()), (f1, f2) -> f2.characteristics().initiative() - f1.characteristics().initiative() ); - fighters.addAll(team.fighters()); + for (Fighter fighter : team.fighters()) { + if (fighter instanceof PlayableFighter) { + fighters.add((PlayableFighter) fighter); + } + } fightersByTeam.add(fighters); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/FighterOrderStrategy.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/FighterOrderStrategy.java index 09463a05e..c798e9523 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/FighterOrderStrategy.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/order/FighterOrderStrategy.java @@ -19,7 +19,7 @@ package fr.quatrevieux.araknemu.game.fight.turn.order; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.team.FightTeam; import java.util.List; @@ -33,5 +33,5 @@ public interface FighterOrderStrategy { * * @param teams The fight teams */ - public List compute(List teams); + public List compute(List teams); } diff --git a/src/main/java/fr/quatrevieux/araknemu/game/handler/fight/PerformTurnAction.java b/src/main/java/fr/quatrevieux/araknemu/game/handler/fight/PerformTurnAction.java index a2d26d4ce..7faf6b421 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/handler/fight/PerformTurnAction.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/handler/fight/PerformTurnAction.java @@ -21,7 +21,7 @@ import fr.quatrevieux.araknemu.core.network.exception.ErrorPacket; import fr.quatrevieux.araknemu.core.network.parser.PacketHandler; -import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; import fr.quatrevieux.araknemu.network.game.GameSession; @@ -36,7 +36,7 @@ public final class PerformTurnAction implements PacketHandler ref = new AtomicReference<>(); fight.dispatcher().add(FighterRemoved.class, ref::set); - Fighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); + PlayableFighter fighter = new PlayerFighter(makeSimpleGamePlayer(10)); fighterList.joinTurnList(fighter, fight.map().get(146)); assertContains(fighter, fighterList.all()); @@ -178,4 +183,22 @@ void alive() throws SQLException { assertFalse(fighterList.alive().collect(Collectors.toList()).contains(fighter)); assertContains(fighter, fighterList.all()); } + + @Test + void dispatch() { + class Foo {} + AtomicInteger ai = new AtomicInteger(); + + player.fighter().dispatcher().add(Foo.class, foo -> ai.incrementAndGet()); + other.fighter().dispatcher().add(Foo.class, foo -> ai.incrementAndGet()); + + fight.dispatchToAll(new Foo()); + assertEquals(2, ai.get()); + + other.fighter().move(null); // Remove from fight + + ai.set(0); + fight.dispatchToAll(new Foo()); + assertEquals(1, ai.get()); + } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalTest.java index 0d2e6052b..b78e3910b 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/FunctionalTest.java @@ -36,6 +36,7 @@ import fr.quatrevieux.araknemu.game.fight.exception.FightException; import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.state.ActiveState; @@ -208,7 +209,7 @@ public int action() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return fighter1; } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/AiBaseCase.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/AiBaseCase.java index 0795c6821..29d4e50cd 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/AiBaseCase.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/AiBaseCase.java @@ -32,6 +32,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.simulation.CastSimulation; import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldCell; import fr.quatrevieux.araknemu.game.fight.map.FightCell; @@ -59,11 +60,11 @@ import static org.junit.jupiter.api.Assertions.fail; public class AiBaseCase extends FightBaseCase { - protected Fighter fighter; + protected PlayableFighter fighter; protected Fight fight; protected AbstractAiBuilderFactory actionFactory; - protected ActionGenerator action; + protected ActionGenerator action; protected FighterAI ai; protected FightTurn turn; @@ -94,7 +95,7 @@ public void configureFight(Consumer configurator) { ai.start(turn = fight.turnList().current().get()); if (action == null && actionFactory != null) { - GeneratorBuilder aiBuilder = new GeneratorBuilder<>(); + GeneratorBuilder aiBuilder = new GeneratorBuilder<>(); actionFactory.configure(aiBuilder, fighter); action = aiBuilder.build(); } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAITest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAITest.java index f74b2c725..205a37e42 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAITest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/FighterAITest.java @@ -28,6 +28,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.action.logic.NullGenerator; import fr.quatrevieux.araknemu.game.fight.ai.util.AIHelper; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; import fr.quatrevieux.araknemu.game.fight.state.PlacementState; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; @@ -42,7 +43,7 @@ import static org.junit.jupiter.api.Assertions.*; class FighterAITest extends FightBaseCase { - private Fighter fighter; + private PlayableFighter fighter; private Fight fight; private Fighter enemy; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/DummyGenerator.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/DummyGenerator.java index 74212e78b..7f45c64a5 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/DummyGenerator.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/DummyGenerator.java @@ -21,6 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.AI; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.Turn; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; @@ -53,7 +54,7 @@ public int action() { } @Override - public Fighter performer() { + public PlayableFighter performer() { return null; } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapterTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapterTest.java index bedc641c7..95128d806 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapterTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/action/FightAiActionFactoryAdapterTest.java @@ -24,6 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.ai.proxy.ProxyBattlefield; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; import fr.quatrevieux.araknemu.game.fight.turn.action.cast.Cast; @@ -38,7 +39,7 @@ class FightAiActionFactoryAdapterTest extends FightBaseCase { private FightAiActionFactoryAdapter factory; private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; @Override @BeforeEach diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactoryTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactoryTest.java index 6cc429e93..bfbb74b76 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactoryTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/ChainAiFactoryTest.java @@ -24,6 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.action.ActionGenerator; import fr.quatrevieux.araknemu.game.fight.ai.action.logic.NullGenerator; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -33,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertSame; class ChainAiFactoryTest extends FightBaseCase { - private Fighter fighter; + private PlayableFighter fighter; @BeforeEach @Override diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java index 038dd57ac..ce9026a45 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/factory/MonsterAiFactoryTest.java @@ -25,6 +25,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.simulation.Simulator; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; import fr.quatrevieux.araknemu.game.fight.module.AiModule; import fr.quatrevieux.araknemu.game.monster.MonsterService; @@ -56,14 +57,14 @@ void createNotAMonster() { @Test void createSuccess() { - assertTrue(factory.create(fight.team(1).fighters().stream().findFirst().get()).isPresent()); + assertTrue(factory.create((PlayableFighter) fight.team(1).fighters().stream().findFirst().get()).isPresent()); } @Test void createSuccessWithInvocation() throws SQLException { dataSet.pushMonsterTemplateInvocations(); - Fighter fighter = new InvocationFighter( + PlayableFighter fighter = new InvocationFighter( -1, container.get(MonsterService.class).load(36).get(3), fight.team(1), @@ -79,6 +80,6 @@ void createSuccessWithInvocation() throws SQLException { void createInvalidAiType() { factory = new MonsterAiFactory(); - assertThrows(IllegalArgumentException.class, () -> factory.create(fight.team(1).fighters().stream().findFirst().get())); + assertThrows(IllegalArgumentException.class, () -> factory.create((PlayableFighter) fight.team(1).fighters().stream().findFirst().get())); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/util/PredicatesTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/util/PredicatesTest.java index 4089700de..8a12d00bb 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/util/PredicatesTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/ai/util/PredicatesTest.java @@ -21,6 +21,7 @@ import fr.quatrevieux.araknemu.game.fight.ai.AiBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -35,7 +36,7 @@ void hasEnemyInRangeSuccess() { .addEnemy(b -> b.cell(135)) ); - assertTrue(Predicates.hasEnemyInRange().test(ai)); + assertTrue(Predicates.hasEnemyInRange().test(ai)); } @Test @@ -48,7 +49,7 @@ void hasEnemyInRangeWithoutAttackSpells() throws NoSuchFieldException, IllegalAc removeSpell(3); - assertFalse(Predicates.hasEnemyInRange().test(ai)); + assertFalse(Predicates.hasEnemyInRange().test(ai)); } @Test @@ -58,7 +59,7 @@ void hasEnemyInRangeTooFar() { .addEnemy(b -> b.cell(256)) ); - assertFalse(Predicates.hasEnemyInRange().test(ai)); + assertFalse(Predicates.hasEnemyInRange().test(ai)); } @Test @@ -69,7 +70,7 @@ void hasAllies() { .addAlly(b -> b.cell(125)) ); - assertTrue(Predicates.hasAllies().test(ai)); + assertTrue(Predicates.hasAllies().test(ai)); configureFight(fb -> fb .addSelf(b -> b.cell(123)) @@ -78,14 +79,14 @@ void hasAllies() { .addAlly(b -> b.cell(125)) ); - assertTrue(Predicates.hasAllies().test(ai)); + assertTrue(Predicates.hasAllies().test(ai)); configureFight(fb -> fb .addSelf(b -> b.cell(123)) .addEnemy(b -> b.cell(135)) ); - assertFalse(Predicates.hasAllies().test(ai)); + assertFalse(Predicates.hasAllies().test(ai)); } @Test @@ -95,8 +96,8 @@ void hasLessThanPercentLife() { .addEnemy(b -> b.cell(256)) ); - assertFalse(Predicates.hasLessThanPercentLife(10).test(ai)); - assertTrue(Predicates.hasLessThanPercentLife(50).test(ai)); - assertTrue(Predicates.hasLessThanPercentLife(51).test(ai)); + assertFalse(Predicates.hasLessThanPercentLife(10).test(ai)); + assertTrue(Predicates.hasLessThanPercentLife(50).test(ai)); + assertTrue(Predicates.hasLessThanPercentLife(51).test(ai)); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java index 3ffc5bba2..278fc20cb 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/CastScopeTest.java @@ -24,6 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.spell.Spell; @@ -489,7 +490,7 @@ void replaceTargetChaining() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); @@ -521,7 +522,7 @@ void replaceTargetChainingWithRecursionOnFirstTarget() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); @@ -554,7 +555,7 @@ void replaceTargetChainingWithRecursionOnMiddleTarget() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); @@ -587,7 +588,7 @@ void removeTargetWithReplaceTargetChain() { Mockito.when(spell.constraints()).thenReturn(constraints); Mockito.when(constraints.freeCell()).thenReturn(false); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); CastScope scope = FightCastScope.simple(spell, fighters.get(0), fight.map().get(263), Collections.singletonList(effect)); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java index f01c585da..ff37e896b 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/FunctionalTest.java @@ -30,6 +30,7 @@ import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldObject; @@ -518,7 +519,7 @@ void switchOnAttackWithChaining() { fight.state(PlacementState.class).startFight(); fight.turnList().start(); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); castNormal(440, fight.map().get(271)); // Sacrifice fighters.get(0).turn().stop(); @@ -559,7 +560,7 @@ void switchOnAttackWithSpellReturn() { fight.state(PlacementState.class).startFight(); fight.turnList().start(); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); castNormal(440, fight.map().get(271)); // Sacrifice castNormal(4, fight.map().get(328)); // Renvoi de Sort @@ -648,7 +649,7 @@ void switchOnAttackAndReflectDamage() { fight.state(PlacementState.class).startFight(); fight.turnList().start(); - List fighters = fight.turnList().fighters(); + List fighters = fight.turnList().fighters(); castNormal(440, fight.map().get(271)); // Sacrifice fighters.get(0).turn().stop(); @@ -1077,10 +1078,10 @@ void boostSpellDamage() { assertEquals(51, fighters.get(0).spells().get(171).effects().get(0).min()); assertEquals(53, fighters.get(0).spells().get(171).effects().get(0).max()); - fighters.get(0).turn().stop(); - fighters.get(1).turn().stop(); - fighters.get(0).turn().stop(); - fighters.get(1).turn().stop(); + getFighter(0).turn().stop(); + getFighter(1).turn().stop(); + getFighter(0).turn().stop(); + getFighter(1).turn().stop(); castFromSpellList(171, fighters.get(1).cell()); // Flèche punitive damage = current - fighters.get(1).life().current(); @@ -1253,7 +1254,7 @@ void glyphShouldDisappearOnCasterDie() { .addEnemy(fb -> fb.cell(325)) ); - Fighter caster = fight.turnList().currentFighter(); + PlayableFighter caster = fight.turnList().currentFighter(); castNormal(17, fight.map().get(169)); // Glyphe agressif diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/damage/StealLifeHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/damage/StealLifeHandlerTest.java index 1385132f5..bbc27d373 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/damage/StealLifeHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/damage/StealLifeHandlerTest.java @@ -36,6 +36,7 @@ import fr.quatrevieux.araknemu.game.spell.effect.area.CircleArea; import fr.quatrevieux.araknemu.game.spell.effect.target.SpellEffectTarget; import fr.quatrevieux.araknemu.network.game.out.fight.action.ActionEffect; +import io.github.artsok.RepeatedIfExceptionsTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -268,7 +269,7 @@ void applyWithAreaMultipleFighters() { /** * #56 : Suicide with steel life will not heal */ - @Test + @RepeatedIfExceptionsTest void applySuicide() { SpellEffect effect = Mockito.mock(SpellEffect.class); Spell spell = Mockito.mock(Spell.class); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java index 0b25e7e3d..007b3de62 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/MonsterInvocationHandlerTest.java @@ -21,6 +21,8 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; +import fr.quatrevieux.araknemu.game.fight.ai.FighterAI; +import fr.quatrevieux.araknemu.game.fight.ai.factory.AiFactory; import fr.quatrevieux.araknemu.game.fight.castable.CastScope; import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; @@ -28,6 +30,7 @@ import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; +import fr.quatrevieux.araknemu.game.fight.module.AiModule; import fr.quatrevieux.araknemu.game.monster.MonsterService; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -56,6 +59,7 @@ public void setUp() throws Exception { dataSet.pushMonsterTemplateInvocations().pushMonsterSpellsInvocations().pushRewardItems(); fight = createFight(); + fight.register(new AiModule(container.get(AiFactory.class))); fight.nextState(); caster = player.fighter(); @@ -81,7 +85,7 @@ void handle() { FightCastScope scope = makeCastScope(caster, spell, effect, fight.map().get(123)); handler.handle(scope, scope.effects().get(0)); - FighterData invoc = fight.map().get(123).fighter(); + Fighter invoc = fight.map().get(123).fighter(); assertInstanceOf(InvocationFighter.class, invoc); assertContains(invoc, fight.fighters().all()); @@ -89,6 +93,7 @@ void handle() { assertSame(caster.team(), invoc.team()); assertEquals(1, invoc.level()); assertEquals(36, ((InvocationFighter) invoc).monster().id()); + assertInstanceOf(FighterAI.class, invoc.attachment(FighterAI.class)); requestStack.assertAll( new FighterTurnOrder(fight.turnList()), diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java index 769060d1e..5b08ccacb 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/effect/handler/invocations/StaticInvocationHandlerTest.java @@ -21,11 +21,15 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; +import fr.quatrevieux.araknemu.game.fight.ai.FighterAI; +import fr.quatrevieux.araknemu.game.fight.ai.factory.AiFactory; import fr.quatrevieux.araknemu.game.fight.castable.FightCastScope; +import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.FighterFactory; -import fr.quatrevieux.araknemu.game.fight.fighter.invocation.InvocationFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.StaticInvocationFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; +import fr.quatrevieux.araknemu.game.fight.module.AiModule; import fr.quatrevieux.araknemu.game.monster.MonsterService; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -39,6 +43,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -55,6 +60,7 @@ public void setUp() throws Exception { dataSet.pushMonsterTemplateInvocations().pushMonsterSpellsInvocations().pushRewardItems(); fight = createFight(); + fight.register(new AiModule(container.get(AiFactory.class))); fight.nextState(); caster = player.fighter(); @@ -80,18 +86,20 @@ void handle() { FightCastScope scope = makeCastScope(caster, spell, effect, fight.map().get(123)); handler.handle(scope, scope.effects().get(0)); - FighterData invoc = fight.map().get(123).fighter(); + Fighter invoc = fight.map().get(123).fighter(); - assertInstanceOf(InvocationFighter.class, invoc); + assertInstanceOf(StaticInvocationFighter.class, invoc); assertContains(invoc, fight.fighters().all()); assertFalse(fight.turnList().fighters().contains(invoc)); assertSame(caster.team(), invoc.team()); assertEquals(1, invoc.level()); - assertEquals(36, ((InvocationFighter) invoc).monster().id()); + assertEquals(36, ((StaticInvocationFighter) invoc).monster().id()); requestStack.assertAll( new ActionEffect(185, caster, "+" + invoc.sprite()) ); + + assertNull(invoc.attachment(FighterAI.class)); } @Test diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/spell/SpellConstraintsValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/spell/SpellConstraintsValidatorTest.java index c30334812..ce0dbde8b 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/spell/SpellConstraintsValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/spell/SpellConstraintsValidatorTest.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -37,7 +38,7 @@ class SpellConstraintsValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private SpellConstraintsValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/ApCostValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/ApCostValidatorTest.java index 016373266..0533c8f71 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/ApCostValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/ApCostValidatorTest.java @@ -22,6 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.network.game.out.info.Error; @@ -36,7 +37,7 @@ class ApCostValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private ApCostValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java index a0174304a..2633567ac 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/InvocationCountValidatorTest.java @@ -24,6 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffEffect; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.order.AlternateTeamFighterOrder; import fr.quatrevieux.araknemu.game.spell.Spell; @@ -40,7 +41,7 @@ class InvocationCountValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private InvocationCountValidator validator; @@ -61,7 +62,7 @@ public void setUp() throws Exception { @Test void maxInvocReached() { Spell spell = Mockito.mock(Spell.class); - Fighter invoc = Mockito.mock(Fighter.class); + PlayableFighter invoc = Mockito.mock(PlayableFighter.class); Mockito.when(invoc.invoker()).thenReturn(fighter); fight.turnList().add(invoc); @@ -79,7 +80,7 @@ void maxInvocReached() { @Test void maxInvocReachedWithMultipleInvoc() { Spell spell = Mockito.mock(Spell.class); - Fighter invoc = Mockito.mock(Fighter.class); + PlayableFighter invoc = Mockito.mock(PlayableFighter.class); Mockito.when(invoc.invoker()).thenReturn(fighter); // Add 4 invoc @@ -139,7 +140,7 @@ void success() { @Test void successWithMultipleInvoc() {Spell spell = Mockito.mock(Spell.class); - Fighter invoc = Mockito.mock(Fighter.class); + PlayableFighter invoc = Mockito.mock(PlayableFighter.class); Mockito.when(invoc.invoker()).thenReturn(fighter); fight.turnList().add(invoc); @@ -156,7 +157,7 @@ void success() { @Test void ignoreNotInvocationSpell() { Spell spell = Mockito.mock(Spell.class); - Fighter invoc = Mockito.mock(Fighter.class); + PlayableFighter invoc = Mockito.mock(PlayableFighter.class); Mockito.when(invoc.invoker()).thenReturn(fighter); fight.turnList().add(invoc); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineLaunchValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineLaunchValidatorTest.java index 12d63b91e..cba38e80d 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineLaunchValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineLaunchValidatorTest.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -37,7 +38,7 @@ class LineLaunchValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private LineLaunchValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineOfSightValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineOfSightValidatorTest.java index 5229b7550..08a6d9fd4 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineOfSightValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/LineOfSightValidatorTest.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -37,7 +38,7 @@ class LineOfSightValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private LineOfSightValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/RangeValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/RangeValidatorTest.java index a588cfe87..bd28e33ed 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/RangeValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/RangeValidatorTest.java @@ -24,6 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -38,7 +39,7 @@ class RangeValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private RangeValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/SpellLaunchValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/SpellLaunchValidatorTest.java index b2c538c7b..561170dcf 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/SpellLaunchValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/SpellLaunchValidatorTest.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.castable.spell.LaunchedSpells; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -40,7 +41,7 @@ */ class SpellLaunchValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private SpellLaunchValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/StatesValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/StatesValidatorTest.java index 370328c06..157218d76 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/StatesValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/StatesValidatorTest.java @@ -22,6 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -39,7 +40,7 @@ class StatesValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private StatesValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/TargetCellValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/TargetCellValidatorTest.java index 989b79b6a..219744871 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/TargetCellValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/validator/TargetCellValidatorTest.java @@ -22,6 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.spell.Spell; import fr.quatrevieux.araknemu.game.spell.SpellConstraints; @@ -36,7 +37,7 @@ class TargetCellValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private TargetCellValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/weapon/WeaponConstraintsValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/weapon/WeaponConstraintsValidatorTest.java index 45844c2bc..2cde0f245 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/weapon/WeaponConstraintsValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/castable/weapon/WeaponConstraintsValidatorTest.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.item.ItemService; import fr.quatrevieux.araknemu.game.item.type.Weapon; @@ -39,7 +40,7 @@ class WeaponConstraintsValidatorTest extends FightBaseCase { private Fight fight; - private Fighter fighter; + private PlayableFighter fighter; private FightTurn turn; private WeaponConstraintsValidator validator; diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellListTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellListTest.java new file mode 100644 index 000000000..44acf1857 --- /dev/null +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/EmptySpellListTest.java @@ -0,0 +1,49 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2023 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.fighter; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class EmptySpellListTest { + @Test + void get() { + assertThrows(NoSuchElementException.class, () -> EmptySpellList.INSTANCE.get(0)); + } + + @Test + void has() { + assertFalse(EmptySpellList.INSTANCE.has(0)); + } + + @Test + void iterator() { + assertIterableEquals(EmptySpellList.INSTANCE, new ArrayList<>()); + } + + @Test + void boost() { + EmptySpellList.INSTANCE.boost(0, null, 0); // do nothing + } +} diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighterTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighterTest.java new file mode 100644 index 000000000..8e8679278 --- /dev/null +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/fighter/invocation/StaticInvocationFighterTest.java @@ -0,0 +1,327 @@ +/* + * This file is part of Araknemu. + * + * Araknemu is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Araknemu is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Araknemu. If not, see . + * + * Copyright (c) 2017-2022 Vincent Quatrevieux + */ + +package fr.quatrevieux.araknemu.game.fight.fighter.invocation; + +import fr.arakne.utils.maps.constant.Direction; +import fr.quatrevieux.araknemu.core.event.Listener; +import fr.quatrevieux.araknemu.game.fight.Fight; +import fr.quatrevieux.araknemu.game.fight.FightBaseCase; +import fr.quatrevieux.araknemu.game.fight.castable.effect.buff.BuffList; +import fr.quatrevieux.araknemu.game.fight.castable.spell.LaunchedSpells; +import fr.quatrevieux.araknemu.game.fight.exception.FightException; +import fr.quatrevieux.araknemu.game.fight.fighter.EmptySpellList; +import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.States; +import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterHidden; +import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterInitialized; +import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterMoved; +import fr.quatrevieux.araknemu.game.fight.fighter.event.FighterVisible; +import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighterSprite; +import fr.quatrevieux.araknemu.game.fight.team.FightTeam; +import fr.quatrevieux.araknemu.game.monster.Monster; +import fr.quatrevieux.araknemu.game.monster.MonsterService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class StaticInvocationFighterTest extends FightBaseCase { + private StaticInvocationFighter fighter; + private FightTeam team; + private Fight fight; + + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + dataSet + .pushMonsterTemplates() + .pushMonsterTemplateInvocations() + .pushMonsterSpellsInvocations() + .pushMonsterSpells() + ; + + fight = createFight(); + team = fight.team(0); + + MonsterService service = container.get(MonsterService.class); + fighter = new StaticInvocationFighter(-5, service.load(36).get(1), team, player.fighter()); + } + + @Test + void values() { + assertSame(team, fighter.team()); + assertEquals(-5, fighter.id()); + assertEquals(Direction.SOUTH_EAST, fighter.orientation()); + assertFalse(fighter.dead()); + assertThrows(FightException.class, fighter::weapon); + assertInstanceOf(BuffList.class, fighter.buffs()); + assertInstanceOf(States.class, fighter.states()); + assertTrue(fighter.ready()); + assertEquals(1, fighter.level()); + assertInstanceOf(Monster.class, fighter.monster()); + assertEquals(36, fighter.monster().id()); + assertSame(player.fighter(), fighter.invoker()); + assertTrue(fighter.invoked()); + assertInstanceOf(EmptySpellList.class, fighter.spells()); + } + + @Test + void equals() throws SQLException { + assertEquals(fighter, fighter); + assertEquals(fighter.hashCode(), fighter.hashCode()); + assertNotEquals(fighter, makePlayerFighter(gamePlayer())); + + MonsterFighter other = new MonsterFighter( + -2, + container.get(MonsterService.class).load(36).all().get(0), + team + ); + + assertNotEquals(fighter, other); + } + + @Test + void attachments() { + fighter.attach("key", 42); + assertSame(42, fighter.attachment("key")); + + LaunchedSpells launchedSpells = new LaunchedSpells(); + + fighter.attach(launchedSpells); + assertSame(launchedSpells, fighter.attachment(LaunchedSpells.class)); + } + + @Test + void orientation() { + assertEquals(Direction.SOUTH_EAST, fighter.orientation()); + + fighter.setOrientation(Direction.NORTH_EAST); + assertEquals(Direction.NORTH_EAST, fighter.orientation()); + } + + @Test + void init() throws Exception { + Fight fight = createFight(); + + AtomicReference ref = new AtomicReference<>(); + fight.dispatcher().add(FighterInitialized.class, ref::set); + + fighter.joinFight(fight, fight.map().get(123)); + fighter.init(); + + assertSame(fighter, ref.get().fighter()); + } + + @Test + void dead() throws Exception { + Fight fight = createFight(); + + fighter.joinFight(fight, fight.map().get(123)); + fighter.init(); + assertFalse(fighter.dead()); + + fighter.life().alter(fighter, -10000); + + assertTrue(fighter.dead()); + } + + @Test + void joinFight() throws Exception { + Fight fight = createFight(); + + assertFalse(fighter.isOnFight()); + + fighter.joinFight(fight, fight.map().get(123)); + + assertSame(fight, fighter.fight()); + assertSame(fight.map().get(123), fighter.cell()); + assertSame(fighter, fighter.cell().fighter()); + assertTrue(fighter.isOnFight()); + } + + @Test + void joinFightAlreadyJoinedShouldRaisedException() throws Exception { + Fight fight = createFight(); + + fighter.joinFight(fight, fight.map().get(123)); + assertThrows(IllegalStateException.class, () -> fighter.joinFight(fight, fight.map().get(123))); + } + + @Test + void sprite() throws Exception { + Fight fight = createFight(); + fighter.joinFight(fight, fight.map().get(123)); + + assertInstanceOf(MonsterFighterSprite.class, fighter.sprite()); + assertEquals("123;1;0;-5;36;-2;1566^100;1;-1;-1;-1;0,0,0,0;45;5;3;25;0;-12;6;-50;15;15;0", fighter.sprite().toString()); + } + + @Test + void moveFirstTime() throws Exception { + Fight fight = createFight(); + + fighter.move(fight.map().get(123)); + + assertSame(fight.map().get(123), fighter.cell()); + assertSame(fighter, fight.map().get(123).fighter()); + } + + @Test + void moveWillLeaveLastCell() throws Exception { + Fight fight = createFight(); + + fighter.move(fight.map().get(123)); + fighter.move(fight.map().get(124)); + + assertSame(fight.map().get(124), fighter.cell()); + assertSame(fighter, fight.map().get(124).fighter()); + + assertFalse(fight.map().get(123).hasFighter()); + } + + @Test + void moveRemoveCell() throws Exception { + Fight fight = createFight(); + + fighter.move(fight.map().get(123)); + fighter.move(null); + + assertThrows(IllegalStateException.class, fighter::cell); + assertFalse(fight.map().get(123).hasFighter()); + } + + @Test + void moveShouldDispatchFighterMoved() { + fighter.joinFight(fight, fight.map().get(123)); + + AtomicReference ref = new AtomicReference<>(); + fight.dispatcher().add(FighterMoved.class, ref::set); + + fighter.move(fight.map().get(126)); + + assertSame(fighter, ref.get().fighter()); + assertSame(fight.map().get(126), ref.get().cell()); + } + + @Test + void moveShouldNotDispatchFighterMovedWhenNullCellIsGiven() { + fighter.joinFight(fight, fight.map().get(123)); + + AtomicReference ref = new AtomicReference<>(); + fight.dispatcher().add(FighterMoved.class, ref::set); + + fighter.move(null); + + assertNull(ref.get()); + } + + @Test + void spells() { + assertIterableEquals(fighter.spells(), new ArrayList<>()); + } + + @Test + void dispatcher() { + Object event = new Object(); + + AtomicReference ref = new AtomicReference<>(); + fighter.dispatcher().add(Object.class, ref::set); + + fighter.dispatch(event); + + assertSame(event, ref.get()); + } + + @Test + void hidden() throws Exception { + Fight fight = createFight(); + fighter.joinFight(fight, fight.map().get(123)); + + final List events = new ArrayList<>(); + + fight.dispatcher().add(new Listener() { + @Override + public void on(FighterHidden event) { + events.add(event); + } + + @Override + public Class event() { + return FighterHidden.class; + } + }); + fight.dispatcher().add(new Listener() { + @Override + public void on(FighterVisible event) { + events.add(event); + } + + @Override + public Class event() { + return FighterVisible.class; + } + }); + + Fighter caster = Mockito.mock(Fighter.class); + + assertFalse(fighter.hidden()); + fighter.setHidden(caster, true); + + assertTrue(fighter.hidden()); + assertEquals(1, events.size()); + assertEquals(fighter, FighterHidden.class.cast(events.get(0)).fighter()); + assertEquals(caster, FighterHidden.class.cast(events.get(0)).caster()); + + fighter.setHidden(caster, true); + assertEquals(1, events.size()); + assertTrue(fighter.hidden()); + + fighter.setHidden(caster, false); + assertEquals(2, events.size()); + assertFalse(fighter.hidden()); + assertEquals(fighter, FighterVisible.class.cast(events.get(1)).fighter()); + assertEquals(caster, FighterVisible.class.cast(events.get(1)).caster()); + + fighter.setHidden(caster, false); + assertEquals(2, events.size()); + assertFalse(fighter.hidden()); + } + + @Test + void isPlaying() { + assertFalse(fighter.isPlaying()); + } +} diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java index 3739ae079..f555683ba 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/FightTurnListTest.java @@ -23,6 +23,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter; import fr.quatrevieux.araknemu.game.fight.turn.event.NextTurnInitiated; import fr.quatrevieux.araknemu.game.fight.turn.event.TurnListChanged; @@ -283,9 +284,9 @@ void add() throws NoSuchFieldException, IllegalAccessException { assertSame(player.fighter(), turnList.currentFighter()); - Fighter f1 = Mockito.mock(Fighter.class); - Fighter f2 = Mockito.mock(Fighter.class); - Fighter f3 = Mockito.mock(Fighter.class); + PlayableFighter f1 = Mockito.mock(PlayableFighter.class); + PlayableFighter f2 = Mockito.mock(PlayableFighter.class); + PlayableFighter f3 = Mockito.mock(PlayableFighter.class); turnList.add(f1); assertSame(player.fighter(), turnList.currentFighter()); diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastTest.java index 564adfba7..ae7a8eea9 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/CastTest.java @@ -26,6 +26,7 @@ import fr.quatrevieux.araknemu.game.fight.castable.validator.CastConstraintValidator; import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.module.CommonEffectsModule; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; @@ -51,7 +52,7 @@ class CastTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; @Override @BeforeEach diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFoundTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFoundTest.java index 512c108ef..17518414a 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFoundTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/cast/SpellNotFoundTest.java @@ -22,6 +22,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.module.CommonEffectsModule; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; @@ -36,7 +37,7 @@ class SpellNotFoundTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; @Override @BeforeEach diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatTest.java index f6510f289..cfc77ad14 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/closeCombat/CloseCombatTest.java @@ -26,6 +26,7 @@ import fr.quatrevieux.araknemu.game.fight.exception.FightException; import fr.quatrevieux.araknemu.game.fight.fighter.ActiveFighter; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.module.CommonEffectsModule; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; @@ -45,7 +46,7 @@ class CloseCombatTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; private CloseCombat action; @Override diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistryTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistryTest.java index 66d91b3ab..27ad2a418 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistryTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/factory/FightActionsFactoryRegistryTest.java @@ -24,6 +24,7 @@ import fr.quatrevieux.araknemu.game.fight.castable.spell.SpellConstraintsValidator; import fr.quatrevieux.araknemu.game.fight.exception.FightException; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionType; import fr.quatrevieux.araknemu.game.fight.turn.action.cast.Cast; import fr.quatrevieux.araknemu.game.fight.turn.action.cast.CastFactory; @@ -40,7 +41,7 @@ class FightActionsFactoryRegistryTest extends FightBaseCase { private Fight fight; private FightActionsFactoryRegistry factory; - private Fighter fighter; + private PlayableFighter fighter; @Override @BeforeEach diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveTest.java index 7d91d30d1..b57d7d8ba 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/MoveTest.java @@ -26,6 +26,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; import fr.arakne.utils.maps.constant.Direction; @@ -44,7 +45,7 @@ class MoveTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; @Override @BeforeEach diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnBattlefieldObjectValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnBattlefieldObjectValidatorTest.java index ea328108a..797fb0f43 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnBattlefieldObjectValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnBattlefieldObjectValidatorTest.java @@ -25,6 +25,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.BattlefieldObject; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; @@ -45,7 +46,7 @@ class StopOnBattlefieldObjectValidatorTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; private StopOnBattlefieldObjectValidator validator; @Override diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java index 683981f81..d2dab6502 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java @@ -25,6 +25,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.move.Move; @@ -44,7 +45,7 @@ class StopOnEnemyValidatorTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; private StopOnEnemyValidator validator; @Override diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java index c8cb52968..18caefe32 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java @@ -28,6 +28,7 @@ import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.move.Move; @@ -57,7 +58,7 @@ class TackleValidatorTest extends FightBaseCase { private Fight fight; private FightTurn turn; - private Fighter fighter; + private PlayableFighter fighter; private TackleValidator validator; @Override diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java index 2b9b37879..d0d4e336d 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/order/AlternateTeamFighterOrderTest.java @@ -33,6 +33,7 @@ import fr.quatrevieux.araknemu.game.fight.fighter.FighterLife; import fr.quatrevieux.araknemu.game.fight.fighter.FighterSpellList; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.fighter.States; import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation; import fr.quatrevieux.araknemu.game.fight.map.FightCell; @@ -120,7 +121,7 @@ public void join(Fighter fighter) throws JoinFightException { public void kick(Fighter fighter) {} } - class FighterStub implements Fighter { + class FighterStub implements PlayableFighter { final private int id; final private int init; @@ -304,7 +305,7 @@ public FighterData invoker() { @Test void computeWithTwoFighters() { - List fighters = strategy.compute( + List fighters = strategy.compute( Arrays.asList( new TeamStub(Arrays.asList(new FighterStub(1, 100))), new TeamStub(Arrays.asList(new FighterStub(2, 500))) @@ -318,7 +319,7 @@ void computeWithTwoFighters() { @Test void computeWithMultipleFightersWithOnePerTeam() { - List fighters = strategy.compute( + List fighters = strategy.compute( Arrays.asList( new TeamStub(Arrays.asList(new FighterStub(1, 100))), new TeamStub(Arrays.asList(new FighterStub(2, 500))), @@ -338,7 +339,7 @@ void computeWithMultipleFightersWithOnePerTeam() { @Test void computeWithMultipleFightersWithTwoTeamOfSameSize() { - List fighters = strategy.compute( + List fighters = strategy.compute( Arrays.asList( new TeamStub(Arrays.asList( new FighterStub(1, 100), @@ -364,7 +365,7 @@ void computeWithMultipleFightersWithTwoTeamOfSameSize() { @Test void computeWithMultipleFightersWithTwoTeamWithDifferentSizeWillSetFighterOfBiggestTeamAtTheEnd() { - List fighters = strategy.compute( + List fighters = strategy.compute( Arrays.asList( new TeamStub(Arrays.asList( new FighterStub(1, 100), diff --git a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java index a658af4f1..e1b5a4da2 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/listener/fight/turn/action/SendFightActionTest.java @@ -26,6 +26,7 @@ import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.action.Action; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; import fr.quatrevieux.araknemu.game.fight.turn.action.event.FightActionStarted; @@ -198,7 +199,7 @@ void whenSecretAndMonsterFighterShouldSendNothing() throws Exception { fight = createPvmFight(); listener = new SendFightAction(fight); - Fighter monster = new ArrayList<>(fight.team(1).fighters()).get(0); + PlayableFighter monster = (PlayableFighter) new ArrayList<>(fight.team(1).fighters()).get(0); monster.setHidden(monster, true); requestStack.clear(); diff --git a/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/FightActionTest.java b/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/FightActionTest.java index 4e27e93e8..5b54f9d87 100644 --- a/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/FightActionTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/network/game/out/fight/action/FightActionTest.java @@ -20,6 +20,7 @@ package fr.quatrevieux.araknemu.network.game.out.fight.action; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.ActionResult; import org.junit.jupiter.api.Test; @@ -40,8 +41,8 @@ public int action() { } @Override - public Fighter performer() { - Fighter fighter = Mockito.mock(Fighter.class); + public PlayableFighter performer() { + PlayableFighter fighter = Mockito.mock(PlayableFighter.class); Mockito.when(fighter.id()).thenReturn(123); return fighter; @@ -83,8 +84,8 @@ public int action() { } @Override - public Fighter performer() { - Fighter fighter = Mockito.mock(Fighter.class); + public PlayableFighter performer() { + PlayableFighter fighter = Mockito.mock(PlayableFighter.class); Mockito.when(fighter.id()).thenReturn(123); return fighter; From 44ddf5d3587120080894acf5706bd8a987ef6ae2 Mon Sep 17 00:00:00 2001 From: Vincent Quatrevieux Date: Thu, 15 Jun 2023 18:32:33 +0200 Subject: [PATCH 3/3] feat(fight): Ignore tackle on static invocations (#27) --- .../move/validators/StopOnEnemyValidator.java | 2 ++ .../move/validators/TackleValidator.java | 1 + .../validators/StopOnEnemyValidatorTest.java | 34 +++++++++++++++++++ .../move/validators/TackleValidatorTest.java | 34 +++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidator.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidator.java index c492742b3..db1ebd51e 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidator.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidator.java @@ -22,6 +22,7 @@ import fr.arakne.utils.maps.constant.Direction; import fr.arakne.utils.maps.path.Decoder; import fr.arakne.utils.maps.path.PathStep; +import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.map.FightMap; import fr.quatrevieux.araknemu.game.fight.turn.action.move.Move; @@ -49,6 +50,7 @@ public MoveResult validate(Move move, MoveResult result) { decoder.nextCellByDirection(step.cell(), direction) .map(FightCell::fighter) .filter(fighter -> !fighter.team().equals(move.performer().team())) + .filter(fighter -> fighter instanceof PlayableFighter) .isPresent() ) { // Truncate the path until the current cell (index + 1 because the argument is a size) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java index 202dfb908..b82922ffa 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidator.java @@ -73,6 +73,7 @@ public MoveResult validate(Move move, MoveResult result) { escapeProbability *= decoder.nextCellByDirection(currentCell, direction) .map(FightCell::fighter) .filter(fighter -> !fighter.team().equals(performer.team())) + .filter(fighter -> fighter instanceof PlayableFighter) .filter(fighter -> !fighter.states().hasOne(ignoredStates)) .map(adjacentEnemy -> computeTackle(performer, adjacentEnemy)) .orElse(1d) diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java index d2dab6502..64d7af6d3 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/StopOnEnemyValidatorTest.java @@ -22,10 +22,12 @@ import fr.arakne.utils.maps.path.Decoder; import fr.arakne.utils.maps.path.Path; import fr.arakne.utils.maps.path.PathStep; +import fr.quatrevieux.araknemu.data.constant.Characteristic; import fr.quatrevieux.araknemu.game.fight.Fight; import fr.quatrevieux.araknemu.game.fight.FightBaseCase; import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.StaticInvocationFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.move.Move; @@ -33,6 +35,7 @@ import fr.quatrevieux.araknemu.game.fight.turn.action.move.MoveSuccess; import fr.arakne.utils.maps.constant.Direction; import fr.quatrevieux.araknemu.game.fight.turn.order.AlternateTeamFighterOrder; +import fr.quatrevieux.araknemu.game.monster.MonsterService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -109,6 +112,37 @@ void validatePathWithEnnemy() throws SQLException { assertEquals(213, result2.target().id()); } + @Test + void validatePathWithEnnemyNotPlayableShouldBeIgnored() throws SQLException { + dataSet.pushMonsterTemplateInvocations(); + + Path path = new Path( + fight.map().decoder(), + Arrays.asList( + new PathStep(fight.map().get(185), Direction.EAST), + new PathStep(fight.map().get(199), Direction.SOUTH_WEST), + new PathStep(fight.map().get(213), Direction.SOUTH_WEST), + new PathStep(fight.map().get(227), Direction.NORTH_WEST) + ) + ); + + StaticInvocationFighter invoc = new StaticInvocationFighter( + -50, + container.get(MonsterService.class).load(282).get(5), + other.fighter().team(), + other.fighter() + ); + fight.fighters().join(invoc, fight.map().get(198)); + invoc.init(); + + Move move = new Move(turn.fighter(), path, new FightPathValidator[0]); + + MoveResult result = new MoveSuccess(fighter, path); + MoveResult result2 = validator.validate(move, result); + + assertSame(result, result2); + } + @Test void validatePathWithEnnemyOnLastStepShouldDoNothing() throws SQLException { Path path = new Path( diff --git a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java index 18caefe32..ba9b122c6 100644 --- a/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/game/fight/turn/action/move/validators/TackleValidatorTest.java @@ -29,6 +29,7 @@ import fr.quatrevieux.araknemu.game.fight.fighter.Fighter; import fr.quatrevieux.araknemu.game.fight.fighter.FighterData; import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter; +import fr.quatrevieux.araknemu.game.fight.fighter.invocation.StaticInvocationFighter; import fr.quatrevieux.araknemu.game.fight.map.FightCell; import fr.quatrevieux.araknemu.game.fight.turn.FightTurn; import fr.quatrevieux.araknemu.game.fight.turn.action.move.Move; @@ -36,6 +37,7 @@ import fr.quatrevieux.araknemu.game.fight.turn.action.move.MoveResult; import fr.quatrevieux.araknemu.game.fight.turn.action.move.MoveSuccess; import fr.quatrevieux.araknemu.game.fight.turn.order.AlternateTeamFighterOrder; +import fr.quatrevieux.araknemu.game.monster.MonsterService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -170,6 +172,38 @@ void validatePathWithEnnemyOnFirstStepWithMoreAgilityShouldBlockAndRemoveAP() th assertEquals(185, result2.target().id()); } + @Test + void validatePathWithStaticEnnemyOnFirstStepShouldBeIgnored() throws SQLException { + dataSet.pushMonsterTemplateInvocations(); + + Path path = new Path( + fight.map().decoder(), + Arrays.asList( + new PathStep(fight.map().get(185), Direction.EAST), + new PathStep(fight.map().get(199), Direction.SOUTH_WEST), + new PathStep(fight.map().get(213), Direction.SOUTH_WEST), + new PathStep(fight.map().get(227), Direction.NORTH_WEST) + ) + ); + + StaticInvocationFighter invoc = new StaticInvocationFighter( + -50, + container.get(MonsterService.class).load(282).get(5), + other.fighter().team(), + other.fighter() + ); + fight.fighters().join(invoc, fight.map().get(170)); + invoc.init(); + invoc.characteristics().alter(Characteristic.AGILITY, 500); + + Move move = new Move(turn.fighter(), path, new FightPathValidator[0]); + + MoveResult result = new MoveSuccess(fighter, path); + MoveResult result2 = validator.validate(move, result); + + assertSame(result, result2); + } + @Test void validateWithRootedStateShouldIgnoreTackle() throws SQLException { fighter.states().push(TackleValidator.STATE_ROOTED);