/** * {@inheritDoc} * * @param figureId The id of the {@link Figure}. * @param clientId The id of the {@link Figure}s {@link Client owner}. * @param targetFieldNotation The {@link Field#getNotation() notation} of the {@link Field} the * {@link Figure} wants to move to. * @param simpMessagingTemplate Template for sending websocket messages. * @throws MoveNotAllowedException */ @Override public void performMovement( String figureId, String clientId, String targetFieldNotation, SimpMessagingTemplate simpMessagingTemplate) throws MoveNotAllowedException { // Only the current player is allowed to do moves. // Fixes CCD2015-50 if (!clientId.equals(getCurrentPlayer().getId())) throw new MoveNotAllowedException(); List<Hexagon> possibleMovements = getPossibleFieldsToMove(figureId); // Throw an exception when the client ID does not match the figures owner id // or when the target field is not in the list of possible moves. if (possibleMovements .stream() .filter(hexagon -> hexagon.getNotation().equals(targetFieldNotation)) .count() == 0 || getFigures() .stream() // Only figures, that are sill active. .filter(hexagonFigure -> !hexagonFigure.isRemoved()) // Only figures equals to the given id .filter(hexagonFigure -> hexagonFigure.getId().equals(figureId)) // Only the clients figures .filter(hexagonFigure -> hexagonFigure.getClient().getId().equals(clientId)) .count() == 0) throw new MoveNotAllowedException(); HistoryEntry historyEntry = new HistoryEntry(); historyEntry.setPlayer(getCurrentPlayer()); // Remove a figure from the chessboard if there is a figure on the target field getFigures() .stream() // Only figures, that are sill active. // Fixes CCD2015-52 .filter(hexagonFigure -> !hexagonFigure.isRemoved()) // Only figures on the target hexagon .filter( hexagonFigure -> hexagonFigure.getPosition().getNotation().equals(targetFieldNotation)) .findFirst() .ifPresent( hexagonFigure -> { historyEntry .getChessboardEvents() .add( new FigureEvent() .setFigureId(hexagonFigure.getId()) .setEvent(FigureEvent.Event.REMOVED)); hexagonFigure.setRemoved(true); }); // Move our figure to the target field getFigures() .stream() // Only figures, that are sill active. .filter(hexagonFigure -> !hexagonFigure.isRemoved()) // Only figures on the source hexagon .filter(hexagonFigure -> hexagonFigure.getId().equals(figureId)) .findFirst() .ifPresent( hexagonFigure -> { historyEntry .getChessboardEvents() .add( new MovementEvent() .setFigureId(figureId) .setFromNotation(hexagonFigure.getPosition().getNotation()) .setToNotation(targetFieldNotation)); try { hexagonFigure.setPosition((Hexagon) getFieldByNotation(targetFieldNotation)); } catch (NotationNotFoundException e) { logger.error("", e); } }); // Add action to history getParentGame().getGameHistory().add(historyEntry); // Send event through websocket simpMessagingTemplate.convertAndSend("/game/" + getParentGame().getId(), historyEntry); // Change the active player and send it through websocket setCurrentPlayer(getCurrentPlayer().getNextClient()); checkIfCurrentPlayerIsDefeated(); while (getCurrentPlayer().isDefeated()) { setCurrentPlayer(getCurrentPlayer().getNextClient()); checkIfCurrentPlayerIsDefeated(); } getParentGame() .getPlayerList() .stream() .filter(client -> !client.isDefeated()) .forEach( client -> { PlayerChangedEvent playerChangedEvent = new PlayerChangedEvent().setItYouTurn(client.equals(getCurrentPlayer())); simpMessagingTemplate.convertAndSend( "/game/" + getParentGame().getId() + "/" + client.getId(), playerChangedEvent); }); }