Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix exceptions from v0.11 logs #358

Merged
merged 8 commits into from
Jul 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
public class ErrorPacket extends HandlingException implements WritePacket {
private final Object packet;

public ErrorPacket(String message, Object packet) {
super(message);
this.packet = packet;
}

public ErrorPacket(Object packet) {
this.packet = packet;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

import java.io.IOException;
import java.util.function.Consumer;

/**
Expand Down Expand Up @@ -66,6 +67,14 @@ public boolean handleException(Throwable cause) {
return false;
}

// Ignore connection reset errors
if (
cause instanceof IOException
&& ("Connection reset by peer".equals(cause.getMessage()) || "Connexion ré-initialisée par le correspondant".equals(cause.getMessage()))
) {
return false;
}

logger.error(NETWORK_ERROR_MARKER, "[{}] Uncaught exception", session, cause);

if (cause.getCause() != null) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/fr/quatrevieux/araknemu/game/GameModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ private void configureServices(ContainerConfigurator configurator) {
new PvmRewardsGenerator(
// Issue #192 (https://github.com/Arakne/Araknemu/issues/192) : Perform SynchronizeLife before AddExperience
// to ensure that level up (which trigger restore life) is performed after life synchronisation
Arrays.asList(new SynchronizeLife(), new AddExperience(), new AddKamas(), new AddItems(container.get(ItemService.class))),
Arrays.asList(new SynchronizeLife(), new AddExperience(), new AddKamas(), new AddItems(container.get(ItemService.class), container.get(Logger.class))),
Arrays.asList(new SetDead(), new ReturnToSavePosition()),
Arrays.asList(
new PvmXpProvider(container.get(GameConfiguration.class).fight().xpRate()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ public void push(Action action) {
* End an action which is successfully terminated
*
* @param actionId The action to end
* @return true if the action was ended, false if there is no pending action with this id
*/
public void end(int actionId) {
gameActions.end(actionId);
public boolean end(int actionId) {
return gameActions.end(actionId);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,21 @@ public void push(Action action) {
* End an action which is successfully terminated
*
* @param actionId The action to end
*
* @return true if the action was ended, false if there is no pending action with this id
*/
public void end(int actionId) {
public boolean end(int actionId) {
final BlockingAction current = this.current;

if (current == null || current.id() != actionId) {
throw new NoSuchElementException("The action ID do not corresponds");
return false;
}

current.end();
this.current = null;

runNextAction();
return true;
}

/**
Expand Down
24 changes: 23 additions & 1 deletion src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -158,6 +159,8 @@ public FightState state() {

/**
* Get the current fight state if the type corresponds
*
* @see Fight#ifState(Class, Consumer) for safe access
*/
@Pure
@SuppressWarnings("unchecked")
Expand All @@ -169,6 +172,25 @@ public <T extends FightState> T state(Class<T> type) {
return (T) statesFlow.current();
}

/**
* Execute the consumer if the current state is the given type
*
* @return true if the state is the given type, false otherwise
*
* @see Fight#state(Class) for unsafe access
*/
@SuppressWarnings("unchecked")
public <T extends FightState> boolean ifState(Class<T> type, Consumer<T> consumer) {
final FightState state = statesFlow.current();

if (!type.isInstance(state)) {
return false;
}

consumer.accept((T) state);
return true;
}

/**
* Start the next fight state
*/
Expand Down Expand Up @@ -412,7 +434,7 @@ public void run() {
executorLock.lock();

if (!alive) {
logger.warn("Cannot run task " + action.getClass().toString() + " on dead fight");
logger.warn("Cannot run task " + action.toString() + " on dead fight");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import fr.quatrevieux.araknemu.game.fight.ai.memory.AiMemory;
import fr.quatrevieux.araknemu.game.fight.ai.memory.MemoryKey;
import fr.quatrevieux.araknemu.game.fight.ai.util.AIHelper;
import fr.quatrevieux.araknemu.game.fight.exception.FightException;
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
import fr.quatrevieux.araknemu.game.fight.fighter.FighterData;
import fr.quatrevieux.araknemu.game.fight.fighter.PlayableFighter;
Expand Down Expand Up @@ -109,7 +110,10 @@ public void run() {
);

if (action.isPresent()) {
currentTurn.perform(action.get());
if (!currentTurn.perform(action.get())) {
throw new FightException("The AI has generated an invalid action + " + action.get());
}

currentTurn.later(() -> fight.schedule(this, Duration.ofMillis(800)));
stop = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public boolean active() {
}

@Override
public void perform(Action action) throws FightException {
public boolean perform(Action action) throws FightException {
throw new UnsupportedOperationException("This is a proxy turn");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import fr.quatrevieux.araknemu.game.item.ItemService;
import fr.quatrevieux.araknemu.game.player.inventory.PlayerInventory;
import org.apache.logging.log4j.Logger;

/**
* Add the dropped items to the fighter
*/
public final class AddItems implements DropRewardAction {
private final ItemService service;
private final Logger logger;

public AddItems(ItemService service) {
public AddItems(ItemService service, Logger logger) {
this.service = service;
this.logger = logger;
}

@Override
Expand All @@ -54,7 +57,11 @@ public void onPlayer(PlayerFighter fighter) {

reward.items().forEach((itemId, quantity) -> {
for (int q = 0; q < quantity; ++q) {
inventory.add(service.create(itemId));
try {
inventory.add(service.create(itemId));
} catch (Exception e) {
logger.error("Failed to create reward item " + itemId, e);
}
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public void stop() {
}

@Override
public void perform(FightAction action) throws FightException {
public boolean perform(FightAction action) throws FightException {
if (!active.get()) {
throw new FightException("Turn is not active");
}
Expand All @@ -151,9 +151,7 @@ public void perform(FightAction action) throws FightException {
throw new FightException("The fighter is dead");
}

if (!actionHandler.start(action)) {
throw new FightException("Cannot start the action");
}
return actionHandler.start(action);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ public interface Turn<A extends Action> {
* Perform a fight action
*
* @param action The action to perform
* @return true if the action is successfully performed, or false if the action cannot be performed
*/
public void perform(A action) throws FightException;
public boolean perform(A action) throws FightException;

/**
* Execute the action when the current is terminated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@

package fr.quatrevieux.araknemu.game.handler;

import fr.quatrevieux.araknemu.core.network.exception.CloseImmediately;
import fr.quatrevieux.araknemu.core.network.exception.ErrorPacket;
import fr.quatrevieux.araknemu.core.network.parser.Packet;
import fr.quatrevieux.araknemu.core.network.parser.PacketHandler;
import fr.quatrevieux.araknemu.game.fight.Fight;
import fr.quatrevieux.araknemu.game.fight.fighter.player.PlayerFighter;
import fr.quatrevieux.araknemu.network.game.GameSession;
import fr.quatrevieux.araknemu.network.game.out.basic.Noop;

/**
* Base type for packet handlers that require the player to be in a fight
*
* @param <P> Packet to handler
* @param <P> Packet to handle
* @see GameSession#fighter() will be set
*/
public abstract class AbstractFightingPacketHandler<P extends Packet> implements PacketHandler<GameSession, P> {
Expand All @@ -38,14 +39,16 @@
final PlayerFighter fighter = session.fighter();

if (fighter == null) {
throw new CloseImmediately("Not in fight");
handleNotInFight(session, packet);
return;

Check warning on line 43 in src/main/java/fr/quatrevieux/araknemu/game/handler/AbstractFightingPacketHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/fr/quatrevieux/araknemu/game/handler/AbstractFightingPacketHandler.java#L42-L43

Added lines #L42 - L43 were not covered by tests
}

fighter.fight().execute(() -> {
final PlayerFighter currentFighter = session.fighter();

// The player has left the fight before the execution of the action
if (currentFighter == null) {
handleNotInFight(session, packet);

Check warning on line 51 in src/main/java/fr/quatrevieux/araknemu/game/handler/AbstractFightingPacketHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/fr/quatrevieux/araknemu/game/handler/AbstractFightingPacketHandler.java#L51

Added line #L51 was not covered by tests
return;
}

Expand All @@ -66,4 +69,17 @@
* @param packet The packet to handle
*/
protected abstract void handle(GameSession session, Fight fight, PlayerFighter fighter, P packet) throws Exception;

/**
* Handle the packet when the player is not in a fight
*
* By default, will close the session immediately.
* Override this method to change the behavior.
*
* @param session The session
* @param packet The received packet
*/
protected void handleNotInFight(GameSession session, P packet) {
throw new ErrorPacket("Not in fight", new Noop());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@

package fr.quatrevieux.araknemu.game.handler;

import fr.quatrevieux.araknemu.core.network.exception.CloseImmediately;
import fr.quatrevieux.araknemu.core.network.exception.ErrorPacket;
import fr.quatrevieux.araknemu.core.network.parser.Packet;
import fr.quatrevieux.araknemu.core.network.parser.PacketHandler;
import fr.quatrevieux.araknemu.network.game.GameSession;
import fr.quatrevieux.araknemu.network.game.out.basic.Noop;

/**
* Switch between handler when the current player is in fight or exploring
Expand All @@ -49,7 +50,7 @@ public void handle(GameSession session, P packet) throws Exception {
} else if (session.exploration() != null) {
exploringHandler.handle(session, packet);
} else {
throw new CloseImmediately("The player should be in exploration or fight");
throw new ErrorPacket("The player should be in exploration or fight", new Noop());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,19 @@
final FightCell targetCell = fight.map().get(packet.cellId());

try {
fight
.state(PlacementState.class)
.changePlace(fighter, targetCell)
;
final boolean validState = fight.ifState(PlacementState.class, state -> state.changePlace(fighter, targetCell));

if (!validState) {
session.send(new ChangeFighterPlaceError());
}
} catch (FightException e) {
throw new ErrorPacket(new ChangeFighterPlaceError());
final String message = e.getMessage();

if (message != null) {
throw new ErrorPacket(message, new ChangeFighterPlaceError());
} else {
throw new ErrorPacket(new ChangeFighterPlaceError());

Check warning on line 57 in src/main/java/fr/quatrevieux/araknemu/game/handler/fight/ChangeFighterStartPlace.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/fr/quatrevieux/araknemu/game/handler/fight/ChangeFighterStartPlace.java#L57

Added line #L57 was not covered by tests
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,22 @@ public void handle(GameSession session, Fight fight, PlayerFighter fighter, Kick

if (!fighter.isTeamLeader() || packet.fighterId() == fighter.id()) {
// @todo Im error ?
throw new ErrorPacket(new Noop());
throw new ErrorPacket("Cannot kick himself, or if not leader", new Noop());
}

boolean success = false;

for (Fighter teammate : fighter.team().fighters()) {
if (teammate.id() == packet.fighterId()) {
fighter.fight().state(PlacementState.class).kick(teammate);
return;
success = fight.ifState(PlacementState.class, state -> state.kick(teammate));
break;
}
}

// @todo Im error ?
session.send(new Noop());
if (!success) {
// @todo Im error ?
session.send(new Noop());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
public final class LeaveFight extends AbstractFightingPacketHandler<LeaveFightRequest> {
@Override
public void handle(GameSession session, Fight fight, PlayerFighter fighter, LeaveFightRequest packet) {
fight.state(LeavableState.class).leave(fighter);
fight.ifState(LeavableState.class, state -> state.leave(fighter));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public void handle(GameSession session, Fight fight, PlayerFighter fighter, Game
try {
final FightTurn turn = fighter.turn();

turn.perform(fighter.fight().actions().create(fighter, ActionType.byId(packet.type()), packet.arguments()));
if (!turn.perform(fighter.fight().actions().create(fighter, ActionType.byId(packet.type()), packet.arguments()))) {
session.send(new NoneAction());
}
} catch (Exception e) {
throw new ErrorPacket(new NoneAction(), e);
}
Expand Down
Loading
Loading