added server side map loading verification

This commit is contained in:
Johannes Schmelz 2024-10-06 00:18:36 +02:00
parent 1c99117ca0
commit 4fff32c13e

View File

@ -9,6 +9,7 @@ package pp.battleship.game.server;
import pp.battleship.BattleshipConfig; import pp.battleship.BattleshipConfig;
import pp.battleship.message.client.ClientInterpreter; import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage; import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage; import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage; import pp.battleship.message.server.EffectMessage;
@ -134,6 +135,7 @@ public class ServerGameLogic implements ClientInterpreter {
/** /**
* Handles the reception of a MapMessage. * Handles the reception of a MapMessage.
* Also tests if Map is in correct format
* *
* @param msg the received MapMessage * @param msg the received MapMessage
* @param from the ID of the sender client * @param from the ID of the sender client
@ -142,10 +144,59 @@ public class ServerGameLogic implements ClientInterpreter {
public void received(MapMessage msg, int from) { public void received(MapMessage msg, int from) {
if (state != ServerState.SET_UP) if (state != ServerState.SET_UP)
LOGGER.log(Level.ERROR, "playerReady not allowed in {0}", state); //NON-NLS LOGGER.log(Level.ERROR, "playerReady not allowed in {0}", state); //NON-NLS
else
playerReady(getPlayerById(from), msg.getShips()); Player cp = getPlayerById(from);
List<Battleship> ships = msg.getShips();
if (!validateShips(ships)) {
LOGGER.log(Level.ERROR, "Invalid ship placement by player {0}", from);
return;
}
playerReady(cp, ships);
} }
/**
* Validates a list of ships.
* Validates the list, that no ships are out of bounds or overlap with each other
*
* @param ships list of ships to validate
* @return {@code true} if all ships positions are valid, {@code false} otherwise
*/
private boolean validateShips(List<Battleship> ships) {
Set<IntPoint> occupiedPoints = new HashSet<>();
for (Battleship ship : ships) {
if (!isWithinBounds(ship)) {
return false;
}
for (int x = ship.getMinX(); x <= ship.getMaxX(); x++) {
for (int y = ship.getMinY(); y <= ship.getMaxY(); y++) {
IntPoint point = new IntPoint(x, y);
if (!occupiedPoints.add(point)) {
return false;
}
}
}
}
return true;
}
/**
* Test if a ship is inside the map
* @param ship the ship to validate
* @return {@code true} if a ship is within bounds, {@code false} otherwise
*/
private boolean isWithinBounds(Battleship ship) {
return ship.getMinX() >= 0 && ship.getMaxX() < config.getMapWidth() &&
ship.getMinY() >= 0 && ship.getMaxY() < config.getMapHeight();
}
/** /**
* Handles the reception of a ShootMessage. * Handles the reception of a ShootMessage.
* *