From 3ab6b44638f0ac71ab79901dea27633fccf6ace0 Mon Sep 17 00:00:00 2001 From: Benjamin Feyer Date: Wed, 2 Oct 2024 16:46:44 +0200 Subject: [PATCH] Nr. 8, edited 'EditorState', 'ServerGameLogic' and 'ShipMapDTO' classes --- .../battleship/game/client/EditorState.java | 62 ++++++++++++++++++ .../game/server/ServerGameLogic.java | 65 ++++++++++++++++++- .../pp/battleship/model/dto/ShipMapDTO.java | 8 +++ 3 files changed, 134 insertions(+), 1 deletion(-) diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/EditorState.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/EditorState.java index 3e5b837e..02600b46 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/EditorState.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/EditorState.java @@ -10,12 +10,15 @@ import pp.battleship.message.client.MapMessage; import pp.battleship.model.Battleship; import pp.battleship.model.IntPoint; +import pp.battleship.model.Rotation; import pp.battleship.model.ShipMap; import pp.battleship.model.dto.ShipMapDTO; import java.io.File; import java.io.IOException; import java.lang.System.Logger.Level; +import java.util.ArrayList; +import java.util.List; import static pp.battleship.Resources.lookup; import static pp.battleship.model.Battleship.Status.INVALID_PREVIEW; @@ -238,6 +241,9 @@ public void loadMap(File file) throws IOException { final ShipMapDTO dto = ShipMapDTO.loadFrom(file); if (!dto.fits(logic.getDetails())) throw new IOException(lookup("map.doesnt.fit")); + if(!verifyMap(dto)){ + throw new IOException("Map is not valid"); + } ownMap().clear(); dto.getShips().forEach(ownMap()::add); harbor().clear(); @@ -245,6 +251,62 @@ public void loadMap(File file) throws IOException { selectedInHarbor = null; } + /** + * this method returns true, if the given map is valid (don't overlap or out of bound) + * + * @param dto the map + * @return true, if the map is valid + */ + private boolean verifyMap(ShipMapDTO dto){ //MapMessage msg, int playerID + int mapWidth = dto.getWidth(); + int mapHeight = dto.getHeight(); + return verifyBounds(dto,mapWidth,mapHeight) && verifyOverlap(dto); + } + + /** + * checks, whether a ship is out of the grid + * @param dto is the Map, where the ships are in + * @param mapWidth the width of the map + * @param mapHeight the height ig the map + * @return true, if all ships are in bound + */ + private boolean verifyBounds(ShipMapDTO dto, int mapWidth,int mapHeight){ + for(Battleship ship: dto.getShips()){ + int x = ship.getX(); + int y = ship.getY(); + Rotation r = ship.getRot(); + if(0 > x || 0> y || x> mapWidth|| y> mapHeight){ // tests, whether the nose of the ship is in the gri + return false; + } + int x2 = x + ship.getLength()* r.dx(); + int y2 = y + ship.getLength() * r.dy(); + if(0 > x2 || 0> y2 || x2> mapWidth|| y2> mapHeight){ //tests, whether the back of the ship is in the grid + return false; + } + } + return true; + } + + /** + * checks whether the ships overlap each other + * + * @param dto ist the map, where the ships are in + * @return true, if no ships overlap + */ + private boolean verifyOverlap(ShipMapDTO dto){ + List ships = dto.getShips(); + List shipsReduceList = new ArrayList<>(ships); + for(Battleship ship: ships){ //iterate through the list of all ships on the grid + shipsReduceList.remove(ship); // delete the current ship from the second list, so it will not test, if it colides with itself + for(Battleship battleship:shipsReduceList){ //iterates through the other ships + if(ship.collidesWith(battleship)){// tests, for all other remaining ships, if they collide with the current one + return false; // return false, if there is a collision + } + } + } + return true; + } + /** * Checks if the player's own map may be loaded from a file. * diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java index a5987fa1..6360ddf0 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java @@ -17,6 +17,7 @@ import pp.battleship.message.server.StartBattleMessage; import pp.battleship.model.Battleship; import pp.battleship.model.IntPoint; +import pp.battleship.model.Rotation; import java.lang.System.Logger; import java.lang.System.Logger.Level; @@ -142,10 +143,72 @@ public Player addPlayer(int id) { public void received(MapMessage msg, int from) { if (state != ServerState.SET_UP) LOGGER.log(Level.ERROR, "playerReady not allowed in {0}", state); //NON-NLS + else if(!verifyMap(msg,from)){ + LOGGER.log(Level.ERROR,"player submitted invalid map",state); + } else playerReady(getPlayerById(from), msg.getShips()); } + /** + * this method returns true, if the given map is valid (don't overlap or out of bound) + * + * @param msg the message, where the map is in + * @param playerID the player, who committed the map + * @return true, if the map is valid + */ + private boolean verifyMap(MapMessage msg, int playerID){ + int mapWidth = getPlayerById(playerID).getMap().getWidth(); + int mapHeight = getPlayerById(playerID).getMap().getHeight(); + return verifyBounds(msg,mapWidth,mapHeight) && verifyOverlap(msg); + } + + /** + * checks, whether a ship is out of the grid + * @param msg is the message, where the map is in + * @param mapWidth is the map width + * @param mapHeight is the map height + * @return true, if all ships are in bound + */ + private boolean verifyBounds(MapMessage msg, int mapWidth,int mapHeight){ + for(Battleship ship: msg.getShips()){ + int x = ship.getX(); + int y = ship.getY(); + Rotation r = ship.getRot(); + if(0 > x || 0> y || x> mapWidth|| y> mapHeight){ // checks, whether the nose is in the grid + return false; + } + int x2 = x + ship.getLength()* r.dx(); + int y2 = y + ship.getLength() * r.dy(); + if(0 > x2 || 0> y2 || x2> mapWidth|| y2> mapHeight){ // check, whether the back of the ship is in the grid + return false; + } + } + return true; + } + + /** + * checks whether the ships overlap each other + * + * @param msg is the message, where the map is in + * @return true, if no ships overlap + */ + private boolean verifyOverlap(MapMessage msg){ + List ships = msg.getShips(); // the list the first loop iterates through + List shipsReduceList = new ArrayList<>(ships); // the second list, holds the other remaining ships + for(Battleship ship: ships){ // iterates through the first list + shipsReduceList.remove(ship);//remove the current ship, so it doesn't check the collision with it self + for(Battleship battleship:shipsReduceList){ // iterates through the second list + if(ship.collidesWith(battleship)){ //if there is a collision, it returns false + return false; + } + } + } + return true; + + + } + /** * Handles the reception of a ShootMessage. * @@ -217,4 +280,4 @@ else if (selectedShip.isDestroyed()) { } } } -} +} \ No newline at end of file diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/model/dto/ShipMapDTO.java b/Projekte/battleship/model/src/main/java/pp/battleship/model/dto/ShipMapDTO.java index 9d53146c..14413551 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/model/dto/ShipMapDTO.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/model/dto/ShipMapDTO.java @@ -114,4 +114,12 @@ public static ShipMapDTO loadFrom(File file) throws IOException { throw new IOException(e.getLocalizedMessage()); } } + + public int getWidth(){ + return this.width; + } + + public int getHeight(){ + return this.height; + } }