diff --git a/.idea/.gitignore b/.idea/.gitignore index 13566b81b018ad684f3a35fee301741b2734c8f4..2fd2e631a061da0fd9d009491ab696e69f18960a 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -6,3 +6,5 @@ # Datasource local storage ignored files /dataSources/ /dataSources.local.xml +/misc.xml + diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000000000000000000000000000000000000..f07edf43fd5a289e4b6ae3c41e745c07417fb94b --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="DataSourceManagerImpl" format="xml" multifile-model="true"> + <data-source source="LOCAL" name="battleArena@battlearena.database.windows.net" uuid="7b1fc391-14cb-46cf-a8a0-29c091f02047"> + <driver-ref>azure.ms</driver-ref> + <synchronize>true</synchronize> + <jdbc-driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</jdbc-driver> + <jdbc-url>jdbc:sqlserver://battlearena.database.windows.net:1433;database=battleArena;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;</jdbc-url> + <working-dir>$ProjectFileDir$</working-dir> + </data-source> + </component> +</project> \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000000000000000000000000000000000000..8641bbfdf2e2a8e1ae8a5ddca2037e037e9e7899 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="SqlDialectMappings"> + <file url="file://$PROJECT_DIR$/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_Oracle.sql" dialect="AZURE" /> + <file url="PROJECT" dialect="AZURE" /> + </component> +</project> \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/CHANGELOG +++ /dev/null @@ -1 +0,0 @@ - diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..d259abe54736dbb6cefa66fcecb72b757a599991 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +## [Unreleased] + +### Added +- + +### Fixed +- + +### Changed +- + + +### Removed +- + +##[v.v.v] - dd.mm.yyyy + +### Added diff --git a/README.md b/README.md index 69625de7934d607289e90646606803cc8faefb41..d351a7e1c76dec53336acb562d9f67b5c8075daf 100644 --- a/README.md +++ b/README.md @@ -1 +1,4 @@ ## Hier könnte ihre Werbung stehn + +### Known issues + - Videos sometimes don't load in windows 11 especially on weaker systems diff --git a/pom.xml b/pom.xml index 84f196c852f94f49f4560d3990bc245e517036e7..0aa2d946850d6708836ac61c921226ba1f3bbd57 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,20 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <version>5.10.0</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <version>5.8.0</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> @@ -63,6 +77,28 @@ <version>4.3.24.RELEASE</version> </dependency>--> + <groupId>com.oracle.database.jdbc</groupId> + <artifactId>ojdbc11</artifactId> + <version>23.3.0.23.09</version> + </dependency> + + <dependency> + <groupId>com.microsoft.sqlserver</groupId> + <artifactId>mssql-jdbc</artifactId> + <version>12.4.2.jre11</version> + </dependency> + + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.10.1</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>RELEASE</version> + <scope>test</scope> + </dependency> </dependencies> diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java new file mode 100644 index 0000000000000000000000000000000000000000..be1256f441fa09604694e890557db0bd53131531 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java @@ -0,0 +1,73 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.geometry.Rectangle2D; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.VBox; +import javafx.stage.Screen; + +import java.net.URL; +import java.util.ResourceBundle; + +public class CommunityMapController implements Initializable { + @FXML + private VBox parent; + @FXML + private TableView<DataItem> tableView; + @FXML + private TableColumn<DataItem, String> name; + + Rectangle2D screen = Screen.getPrimary().getVisualBounds(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + tableView.setOnMouseClicked(mouseEvent -> System.out.println(tableView.getWidth())); + setTableView(); + } + + private void setTableView() { + tableView.setMinHeight(screen.getHeight() * 0.69); + tableView.setMinWidth(screen.getWidth() * 0.66); + + name.setCellValueFactory(new PropertyValueFactory<>("name")); + ObservableList<DataItem> data = FXCollections.observableArrayList( + new DataItem("Item A"), + new DataItem("Item B"), + new DataItem("Item C") + ); + + tableView.setItems(data); + } + +// TODO: create map preview + + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(new SceneLoader().loadScene("MapForge")); + } + +// test values TODO: replace with db + public static class DataItem { + private final SimpleStringProperty name; + + public DataItem(String name) { + this.name = new SimpleStringProperty(name); + } + + public String getName() { + return name.get(); + } + + public SimpleStringProperty nameProperty() { + return name; + } + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/CreditsController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CreditsController.java new file mode 100644 index 0000000000000000000000000000000000000000..bd8d67fc8262984ee946d5890286b10d08f2c77f --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CreditsController.java @@ -0,0 +1,54 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.CreateMediaPlayer; +import de.hdm_stuttgart.battlearena.Controller.Utilities.MusicPlayerSingleton; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Cursor; +import javafx.scene.layout.BorderPane; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + +public class CreditsController implements Initializable { + @FXML + private BorderPane parent; + @FXML + private MediaView mediaView; + private MediaPlayer mediaPlayer; + private final File file = new File("src/main/resources/videos/credits.mp4"); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + parent.setStyle("-fx-background-color: black;"); + parent.setCursor(Cursor.NONE); + createMediaPlayer(); + MusicPlayerSingleton.getInstance().getMediaPlayer().dispose(); + } + + private void createMediaPlayer() { + mediaPlayer = new CreateMediaPlayer().getMediaPlayer(mediaView, file, true, parent); + mediaView.setMediaPlayer(mediaPlayer); + + mediaPlayer.setOnEndOfMedia(this::videoEnd); + + parent.setOnMouseClicked(mouseEvent -> videoEnd()); + } + + private void videoEnd() { + try { +// I don't know how to return to the options scene, so it just goes back to the main menu :( + mediaPlayer.dispose(); + parent.getChildren().clear(); + parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/MenuBorderPane.fxml")))); + } catch (IOException e) { + throw new RuntimeException(); + } + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/GameMode.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/GameMode.java new file mode 100644 index 0000000000000000000000000000000000000000..1979fc24fa3fbaf955b93b4b53942edfd080080c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/GameMode.java @@ -0,0 +1,6 @@ +package de.hdm_stuttgart.battlearena.Controller.Enum; + +public enum GameMode { + LOCAL, + NETWORK +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/GameState.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/GameState.java new file mode 100644 index 0000000000000000000000000000000000000000..1ea713b41a90fa593348760d6a6be8c9f0ed1a62 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/GameState.java @@ -0,0 +1,9 @@ +package de.hdm_stuttgart.battlearena.Controller.Enum; + +public enum GameState { + MENU, + PAUSE, + PLAYING, + LOST, + WON +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/PlayerMode.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/PlayerMode.java new file mode 100644 index 0000000000000000000000000000000000000000..fb864e26dcdce0777bc7301cfeb51007063ba46f --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Enum/PlayerMode.java @@ -0,0 +1,6 @@ +package de.hdm_stuttgart.battlearena.Controller.Enum; + +public enum PlayerMode { + PLAYER_ONE, + PLAYER_TWO +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java index 5b490adc8bf54a93797c501e974081b25cbc9b7b..dc9b88e85c746bab7c651e5a6baae246eb4b94c4 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java @@ -1,10 +1,135 @@ package de.hdm_stuttgart.battlearena.Controller; +import de.hdm_stuttgart.battlearena.Controller.Enum.GameMode; +import de.hdm_stuttgart.battlearena.Controller.Enum.GameState; +import de.hdm_stuttgart.battlearena.Controller.Enum.PlayerMode; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.RuntimeInfo; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityClass; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityFactory; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityType; +import de.hdm_stuttgart.battlearena.Model.Entity.IEntity; +import de.hdm_stuttgart.battlearena.Model.Inputs.InputHandler; +import de.hdm_stuttgart.battlearena.Model.Map.TileManager; + +import javafx.animation.AnimationTimer; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; + import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -public class GameSceneController { +import java.net.URL; +import java.util.ResourceBundle; + +public class GameSceneController implements Initializable { private static final Logger log = LogManager.getLogger(GameSceneController.class); + @FXML + private Canvas canvas2D; + + private GraphicsContext graphicsContext2D; + + InputHandler inputHandler = InputHandler.getInstance(); + + RuntimeInfo runtimeInfo = RuntimeInfo.getInstance(); + + GameMode gameMode = runtimeInfo.getGameMode(); + + IEntity player; + IEntity enemy; + + EntityClass playerOneClass = runtimeInfo.getPlayerOneClass(); + EntityClass playerTwoClass = runtimeInfo.getPlayerTwoClass(); + + TileManager tileManager; + + //map data + String mapString = "4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 " + + "4 1 2 1 1 1 1 2 2 2 1 1 1 1 1 1 1 3 " + + "4 2 1 1 1 1 1 2 2 2 1 1 1 1 2 1 1 3 " + + "4 1 1 1 2 2 4 3 3 1 4 3 3 3 3 2 2 3 " + + "4 1 1 1 2 2 4 1 1 1 1 1 1 1 3 1 2 3 " + + "4 1 1 1 2 2 4 1 3 3 3 1 1 1 3 2 2 3 " + + "4 1 1 1 2 2 4 1 1 1 1 1 1 1 3 2 1 3 " + + "4 1 5 1 2 2 4 3 3 1 4 3 3 3 3 2 1 3 " + + "4 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1 3 " + + "4 1 1 1 2 2 4 3 3 1 3 3 3 3 3 2 1 3 " + + "4 1 1 1 1 2 4 3 3 1 3 3 3 3 3 1 1 3 " + + "4 1 1 1 1 2 4 3 3 1 3 3 3 3 3 2 2 3 " + + "4 1 1 1 1 1 4 3 3 1 3 3 3 3 3 1 2 3 " + + "4 1 2 1 1 1 1 2 2 2 1 1 1 1 1 1 1 3 " + + "4 1 1 2 1 1 1 2 2 2 1 1 1 1 1 1 1 3 " + + "4 1 1 1 2 2 4 3 3 1 3 3 3 3 3 2 2 3 " + + "4 1 1 1 2 2 4 3 3 1 3 3 3 3 3 2 2 3 " + + "4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"; + int horizontalTileCount = 18; + int verticalTileCount = 18; + int diffTileCount = 6; + int scaledTileSize = 48; + + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + graphicsContext2D = canvas2D.getGraphicsContext2D(); + graphicsContext2D.setImageSmoothing(false); + + player = EntityFactory.createEntity(EntityType.PLAYER, graphicsContext2D, inputHandler, + playerOneClass, this, PlayerMode.PLAYER_ONE); + if (gameMode == GameMode.NETWORK) { + enemy = EntityFactory.createEntity(EntityType.NETWORK_PLAYER_TWO, graphicsContext2D, inputHandler, + playerTwoClass, this, PlayerMode.PLAYER_TWO); + } else { + enemy = EntityFactory.createEntity(EntityType.PLAYER, graphicsContext2D, inputHandler, + playerTwoClass, this, PlayerMode.PLAYER_TWO); + } + + tileManager = new TileManager(graphicsContext2D, diffTileCount, horizontalTileCount, verticalTileCount, mapString); + + runtimeInfo.setGameState(GameState.PLAYING); + + AnimationTimer gameLoop = new AnimationTimer() { + @Override + public void handle(long l) { + graphicsContext2D.clearRect(0, 0, canvas2D.getWidth(), canvas2D.getHeight()); + renderContent(graphicsContext2D); + updateContent(); + } + }; + gameLoop.start(); + log.debug("Game loop started"); + } + + private void updateContent() { + player.updateEntityMovement(this); + enemy.updateEntityMovement(this); + player.attack(enemy, graphicsContext2D); + enemy.attack(player, graphicsContext2D); + } + + private void renderContent(GraphicsContext graphicsContext) { + tileManager.renderMap(); + player.renderEntity(graphicsContext); + enemy.renderEntity(graphicsContext); + player.checkHealTile(player, graphicsContext2D); + enemy.checkHealTile(enemy, graphicsContext2D); + } + + public IEntity getEnemy() { + return enemy; + } + + public IEntity getPlayer() { + return player; + } + + public TileManager getTileManager() { + return tileManager; + } + + public int getScaledTileSize() { + return scaledTileSize; + } } diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java new file mode 100644 index 0000000000000000000000000000000000000000..0ee284ce321557aafe682c4accff45c12625da6c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java @@ -0,0 +1,110 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.CreateMediaPlayer; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.DatabaseException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.StartupThread; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Cursor; +import javafx.scene.layout.BorderPane; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + +public class IntroController implements Initializable { + + @FXML + private MediaView mediaView; + @FXML + private BorderPane introParent; + private final String fileName = "src/main/resources/videos/"; + // nextVideo() will iterate through this array so the next video will be played TODO: change the videos to non memes lmao + private final String[] videos = {"sony.mp4", "gamecube.mp4", "gameboy.mp4", "monke.mp4"}; + private File file = new File(fileName + videos[0]); + private int counter = 0; + private MediaPlayer mediaPlayer; + private final Persistence persistence = Persistence.getInstance(); + private static final Logger log = LogManager.getLogger(Persistence.class); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + introParent.setStyle("-fx-background-color: black;"); + introParent.setCursor(Cursor.NONE); + createMediaPlayer(); + new StartupThread().run(); + } + + private void createMediaPlayer() { +// initializing this.mediaPlayer + mediaPlayer = new CreateMediaPlayer().getMediaPlayer(mediaView, file, true, introParent); + mediaView.setMediaPlayer(mediaPlayer); + + mediaPlayer.setOnEndOfMedia(() -> { + if (counter == videos.length - 1) { + try { + videoEnd(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + nextVideo(); + } + }); + +// TODO: make any button pressed work + introParent.setOnMouseClicked((mouseEvent) -> { + if (counter == videos.length - 1) { + try { + videoEnd(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + nextVideo(); + } + }); + } + + private void videoEnd() throws IOException { + boolean isStartUp = true, noAccount = false, statsLoaded = false; + while (isStartUp) { + try { + persistence.loadPlayerAccount(); + persistence.verifyPlayerAccount(); + mediaPlayer.dispose(); + isStartUp = false; + } catch (DatabaseException e) { + noAccount = true; +// TODO: reset player account if account fails to load in loadPlayerAccount() + } + if (noAccount) { + introParent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/PlayerCreateScene.fxml")))); + } + } + while (!statsLoaded) { // while loop because Martin said so + try { + persistence.loadPlayerStatistics(); + statsLoaded = true; + } catch (DatabaseException e) { + log.error(e); + } + } + introParent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/MenuBorderPane.fxml")))); + } + + private void nextVideo() { + mediaPlayer.dispose(); + file = new File(fileName + videos[counter + 1]); + counter++; + createMediaPlayer(); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/LocalCreateController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/LocalCreateController.java new file mode 100644 index 0000000000000000000000000000000000000000..69b2cb5b336306ffa11e72ad169745d1c83c9cd4 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/LocalCreateController.java @@ -0,0 +1,44 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.TitledPane; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.VBox; + +import java.net.URL; +import java.util.ResourceBundle; + +public class LocalCreateController implements Initializable { + @FXML + private VBox parent; + @FXML + private TitledPane roundsTitledPane; + @FXML + private ToggleGroup rounds; + private final SceneLoader sceneLoader = new SceneLoader(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + rounds.selectedToggleProperty().addListener((observableValue, oldToggle, newToggle) -> { + if (rounds.getSelectedToggle() != null) { + ToggleButton selected = (ToggleButton) rounds.getSelectedToggle(); + roundsTitledPane.setText(selected.getText()); + } + }); + } + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("Play")); + } + + @FXML + private void skinSelectionScene() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("SkinSelection")); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MainMenuController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MainMenuController.java index 4fa73f1d596e95461bfb44775fdb526efc4377f3..83a6d92e8b0dbe60af7cbbbe09a263afdb51a6b5 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MainMenuController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MainMenuController.java @@ -1,4 +1,67 @@ package de.hdm_stuttgart.battlearena.Controller; -public class MainMenuController { +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.DatabaseException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.layout.VBox; +import javafx.stage.Screen; +import javafx.stage.Stage; + +import java.net.URL; +import java.util.ResourceBundle; + +public class MainMenuController implements Initializable { + @FXML + private VBox parent; + @FXML + private Button exitButton; + private final SceneLoader sceneLoader = new SceneLoader(); + private final Persistence persistence = Persistence.getInstance(); + + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } + + @FXML + private void playScene() { + switchScene("Play"); + } + + @FXML + private void mapScene() { + switchScene("MapForge"); + } + + @FXML + private void statisticsScene() { + switchScene("Statistics"); + } + + @FXML + private void settingsScene() { + switchScene("Settings"); + } + + @FXML + private void exit() throws DatabaseException { + persistence.savePlayerStatistics(); + persistence.saveSettings(); + Stage stage = (Stage) exitButton.getScene().getWindow(); + stage.close(); + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + Screen screen = Screen.getPrimary(); + if (screen.getDpi() >= 119) { + parent.setSpacing(30); + parent.setStyle("-fx-font-size: 40"); + } else { + parent.setStyle("-fx-font-size: 50"); + } + } } diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java new file mode 100644 index 0000000000000000000000000000000000000000..784361391329dab062e1c64e5aee944381861ff1 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java @@ -0,0 +1,50 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.MusicPlayerSingleton; +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.DatabaseException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.layout.VBox; + +import java.io.IOException; +import java.util.Objects; + +public class MapForgeController { + @FXML + private VBox parent; + SceneLoader sceneLoader = new SceneLoader(); + private final Persistence persistence = Persistence.getInstance(); + + @FXML + private void mapEditorScene() { + try { + parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/PlayerCreateScene.fxml")))); + MusicPlayerSingleton.getInstance().getMediaPlayer().dispose(); + } catch (IOException e) { + throw new RuntimeException(); + } + } + + @FXML + private void communityMapScene() { + switchScene("CommunityMaps"); + } + + @FXML + private void updateMapScene() throws DatabaseException { + persistence.updateCoreMaps(); +// TODO: set message label if update was successful or not + } + + @FXML + private void backButton() { + switchScene("MainMenu"); + } + + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapSelectionController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapSelectionController.java new file mode 100644 index 0000000000000000000000000000000000000000..d821334354bd487632d52077ffa4a3c21f6a1914 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapSelectionController.java @@ -0,0 +1,72 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.MusicPlayerSingleton; +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.MapData; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.RuntimeInfo; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.VBox; +import javafx.scene.text.Text; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Objects; +import java.util.ResourceBundle; + +public class MapSelectionController implements Initializable { + @FXML + private VBox boxBox, parent; + @FXML + private Text selectedMapText; + + private int selectedMap; + + private final SceneLoader sceneLoader = new SceneLoader(); + + private final ArrayList<MapData> coreMaps = Persistence.getInstance().getCoreMaps(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + ToggleGroup group = new ToggleGroup(); + + for (int i = 0; i < coreMaps.size(); i++) { + ToggleButton toggleButton = new ToggleButton(coreMaps.get(i).getMapName()); + toggleButton.setToggleGroup(group); + boxBox.getChildren().add(toggleButton); + } + + group.selectedToggleProperty().addListener((observableValue, oldToggle, newToggle) -> { + if (group.getSelectedToggle() != null) { + ToggleButton selected = (ToggleButton) group.getSelectedToggle(); + selectedMap = boxBox.getChildren().indexOf(selected); + System.out.println(selectedMap); + String value = selected.getText(); + selectedMapText.setText(value); + System.out.println(value); + } + }); + } + + @FXML + private void gameScene() { + try { + RuntimeInfo.getInstance().setGameMap(coreMaps.get(selectedMap)); + MusicPlayerSingleton.getInstance().getMediaPlayer().dispose(); + parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/GameScene.fxml")))); + } catch (IOException e) { + throw new RuntimeException(); + } + } + + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("SkinSelection")); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MenuBorderPaneController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MenuBorderPaneController.java new file mode 100644 index 0000000000000000000000000000000000000000..392326c31e7e700ca491b955e92531d125bf9e5f --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MenuBorderPaneController.java @@ -0,0 +1,117 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.CreateMediaPlayer; +import de.hdm_stuttgart.battlearena.Controller.Utilities.MusicPlayerSingleton; +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.geometry.Rectangle2D; +import javafx.scene.control.Button; +import javafx.scene.image.ImageView; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.StackPane; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; +import javafx.stage.Screen; + +import java.io.File; +import java.net.URL; +import java.util.*; + +public class MenuBorderPaneController implements Initializable { + @FXML + private BorderPane parent; + @FXML + private Button btnRight, btnLeft; + @FXML + private ImageView imgLeft, imgRight; + @FXML + private StackPane center; + private int musicCounter = 1, videoCounter = 0; + private final SceneLoader sceneLoader = new SceneLoader(); + private MediaPlayer musicPlayer, mediaPlayer; + private MediaView mediaView; + private final String[] videoFiles = {"depression", "allMyFellas", "wooOOoo", "myMind", "dogCheese", "gta", "cat", "bobama", "roomba", "firework", "cheezburger", + "kangaroo", "lifeCouldBeMonke", "seal", "imNotYou", "parkingTickets", "russianKid", "rejectHumanity", "horse", "catSitting", "pablo", "holyCrap", + "lessGoo", "sadCat", "basketball", "yoinkySploinky", "msPuff", "=D", "banana", "chaCha", "async", "sadHorse", "minecraftCat", "muecke", "top10Cats", "dog", + "pot", "mineCraftCat2", "catEating", "catJump", "bear", "pancake", "frog", "gtfo", "carl", "dog2", "slippery", "wolf", "legCat", "sad", "waaahhh"}; + + List<String> shuffledVideos = Arrays.asList(videoFiles); + + Rectangle2D screen = Screen.getPrimary().getVisualBounds(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + center.getChildren().add(sceneLoader.loadScene("MainMenu")); +// set size for rusty gear image depending on screen resolution + final double imageWidth = screen.getWidth() / 6; + imgRight.setFitWidth(imageWidth); + imgRight.setPreserveRatio(true); + imgLeft.setFitWidth(imageWidth); + imgLeft.setPreserveRatio(true); + + backgroundMusic("cocBackgroundMusicTest.mp3"); + easterEgg(); + +// shuffle meme order + Collections.shuffle(shuffledVideos); + } + + private void easterEgg() { + btnRight.setOnMouseClicked(mouseEvent -> { + System.out.println(center.getWidth()); + musicCounter++; + switch (musicCounter) { + case 5: + musicPlayer.dispose(); + backgroundMusic("spongeBob.mp3"); + break; + case 12: + musicPlayer.dispose(); + backgroundMusic("stadiumRave.mp3"); + break; + case 20: + musicPlayer.dispose(); + backgroundMusic("wii.mp3"); + break; + } + }); + + btnLeft.setOnMouseClicked(mouseEvent -> { +// make background music continue play after there is no meme left + if (!musicPlayer.isAutoPlay()) { + musicPlayer.play(); + } + +// if a meme is already running, current mediaPlayer will be removed + if (mediaPlayer != null) { + mediaPlayer.dispose(); + center.getChildren().remove(mediaView); + } + + if (videoCounter < videoFiles.length) { + String nextVideo = shuffledVideos.get(videoCounter); + musicPlayer.stop(); + mediaPlayer = new CreateMediaPlayer().getMediaPlayer(mediaView, new File("src/main/resources/videos/" + nextVideo + ".mp4"), false); + mediaView = new MediaView(mediaPlayer); + center.getChildren().add(mediaView); + mediaPlayer.setOnEndOfMedia(() -> { + center.getChildren().remove(mediaView); + musicPlayer.play(); + }); + } + videoCounter++; + }); + } + + private void backgroundMusic(String file) { + Media media = new Media(new File("src/main/resources/sound/music/" + file).toURI().toString()); + musicPlayer = new MediaPlayer(media); + musicPlayer.setVolume((double) Persistence.getInstance().getSettings().getMusicVolume() / 100); + musicPlayer.setCycleCount(MediaPlayer.INDEFINITE); + musicPlayer.play(); + MusicPlayerSingleton.getInstance().setMediaPlayer(musicPlayer); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerController.java new file mode 100644 index 0000000000000000000000000000000000000000..181688fec0dda599c2b0f7e6b08177dc93913e80 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerController.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.fxml.FXML; +import javafx.scene.layout.VBox; + +public class MultiplayerController { + @FXML + private VBox parent; + private final SceneLoader sceneLoader = new SceneLoader(); + + @FXML + private void multiplayerCreateScene() { + switchScene("MultiplayerCreate"); + } + + @FXML + private void multiplayerJoinScene() { + switchScene("MultiplayerJoin"); + } + + @FXML + private void backButton() { + switchScene("Play"); + } + + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerCreateController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerCreateController.java new file mode 100644 index 0000000000000000000000000000000000000000..6db97dfe730df0204ee53741f896e596fce5ebfe --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerCreateController.java @@ -0,0 +1,17 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.fxml.FXML; +import javafx.scene.layout.VBox; + +public class MultiplayerCreateController { + @FXML + private VBox parent; + private final SceneLoader sceneLoader = new SceneLoader(); + + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("Multiplayer")); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerJoinController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerJoinController.java new file mode 100644 index 0000000000000000000000000000000000000000..0aefd1003845e6971d2a025ba5d13c48cf257a33 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MultiplayerJoinController.java @@ -0,0 +1,17 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.fxml.FXML; +import javafx.scene.layout.VBox; + +public class MultiplayerJoinController { + @FXML + private VBox parent; + private final SceneLoader sceneLoader = new SceneLoader(); + + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("Multiplayer")); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayController.java new file mode 100644 index 0000000000000000000000000000000000000000..eae49e623cc42da45d01a9e19f7d0432c920ae59 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayController.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.fxml.FXML; +import javafx.scene.layout.VBox; + +public class PlayController { + @FXML + private VBox parent; + private final SceneLoader sceneLoader = new SceneLoader(); + + @FXML + private void backButton() { + switchScene("MainMenu"); + } + + @FXML + private void localScene() { + switchScene("LocalCreate"); + } + + @FXML + private void multiplayerScene() { + switchScene("Multiplayer"); + } + + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayerCreateController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayerCreateController.java new file mode 100644 index 0000000000000000000000000000000000000000..68dfd4029aad7452c5d19d82fdfcaec3f0e8435e --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayerCreateController.java @@ -0,0 +1,51 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.CreateMediaPlayer; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.layout.BorderPane; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + +public class PlayerCreateController implements Initializable { + @FXML + private BorderPane parent; + @FXML + private MediaView mediaView; + @FXML + private Button button; + private MediaPlayer mediaPlayer, musicPlayer; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + File file = new File("src/main/resources/videos/construction.mp4"); + mediaPlayer = new CreateMediaPlayer().getMediaPlayer(mediaView, file, true, parent); + mediaView.setMediaPlayer(mediaPlayer); + mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE); + parent.setStyle("-fx-font-size: 50; -fx-text-fill: white; -fx-font-family: 'Arial Black'"); + + Media musicMedia = new Media(new File("src/main/resources/sound/music/constructionJazz.mp3").toURI().toString()); + musicPlayer = new MediaPlayer(musicMedia); + musicPlayer.setCycleCount(MediaPlayer.INDEFINITE); + musicPlayer.setAutoPlay(true); + + button.setOnMouseClicked(mouseEvent -> { + try { + mediaPlayer.dispose(); + musicPlayer.dispose(); + parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/MenuBorderPane.fxml")))); + } catch (IOException e) { + throw new RuntimeException(); + } + }); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java new file mode 100644 index 0000000000000000000000000000000000000000..a04eb1c6d84b615f3eff95b33d86485cb0ef5b51 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java @@ -0,0 +1,62 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.MusicPlayerSingleton; +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.Slider; +import javafx.scene.layout.VBox; + +import java.io.IOException; +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + +public class SettingsController implements Initializable { + @FXML + private VBox parent; + @FXML + private Slider musicSlider, sfxSlider; + SceneLoader sceneLoader = new SceneLoader(); + private int musicVolume, sfxVolume; + MusicPlayerSingleton musicPlayer = MusicPlayerSingleton.getInstance(); + Persistence persistence = Persistence.getInstance(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + setMusicVolume(); + setSfxVolume(); + } + + @FXML + private void creditScene() throws IOException { + parent.getChildren().clear(); + parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/credits.fxml")))); + } + + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("MainMenu")); + } + + private void setMusicVolume() { + musicSlider.setValue(persistence.getSettings().getMusicVolume()); + musicSlider.valueProperty().addListener((observableValue, oldValue, newValue) -> { + musicVolume = newValue.intValue(); + persistence.getSettings().setMusicVolume(musicVolume); + musicPlayer.getMediaPlayer().setVolume((double) musicVolume / 100); + }); + } + + private void setSfxVolume(){ + sfxSlider.setValue(persistence.getSettings().getSfxVolume()); + sfxSlider.valueProperty().addListener(((observableValue, oldValue, newValue) -> { + sfxVolume = newValue.intValue(); + persistence.getSettings().setSfxVolume(sfxVolume); +// sfxPlayer.getMediaPlayer().setVolume((double) sfxVolume / 100); + })); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SkinSelectionController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SkinSelectionController.java new file mode 100644 index 0000000000000000000000000000000000000000..9e27cab1e0a87b52e01a1ea63b84ba6cf6b46006 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SkinSelectionController.java @@ -0,0 +1,62 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.MusicPlayerSingleton; +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.geometry.Rectangle2D; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; +import javafx.stage.Screen; + +import java.io.IOException; +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + +public class SkinSelectionController implements Initializable { + @FXML + private VBox parent; + @FXML + private ToggleGroup selectionButton; + @FXML + private ImageView selection1, selection2, selection3; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + selectionButton.selectedToggleProperty().addListener((observableValue, oldToggle, newToggle) -> { + if (selectionButton.getSelectedToggle() != null) { + ToggleButton selected = (ToggleButton) selectionButton.getSelectedToggle(); + String value = selected.getText(); + System.out.println(value); + } + }); + setImageWidth(selection1, selection2, selection3); + } + + private void setImageWidth(ImageView... imageViews) { // the ... allows for zero or more arguments seperated by a comma, will pass argument as an array + Rectangle2D screen = Screen.getPrimary().getVisualBounds(); + final double imageWidth = screen.getWidth() * 0.2; + for (ImageView image : imageViews) { + image.setFitWidth(imageWidth); + image.setPreserveRatio(true); + } + } + + @FXML + private void backButton() { + parent.getChildren().clear(); + parent.getChildren().add(new SceneLoader().loadScene("LocalCreate")); + } + + @FXML + private void gameScene() { + + + parent.getChildren().clear(); + parent.getChildren().add(new SceneLoader().loadScene("MapSelection")); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/StatisticsController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/StatisticsController.java new file mode 100644 index 0000000000000000000000000000000000000000..ee8ccd517fc9c48f3178e792d136dba3f20783e8 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/StatisticsController.java @@ -0,0 +1,84 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import javafx.beans.binding.Bindings; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.PieChart; +import javafx.scene.layout.VBox; +import javafx.scene.text.Text; + +import java.net.URL; +import java.util.ResourceBundle; + +public class StatisticsController implements Initializable { + + @FXML + private Text blocks, deaths, gameTime, gamesLost, gamesWon, kills; + @FXML + private VBox parent; + @FXML + private PieChart kd, wl; + SceneLoader sceneLoader = new SceneLoader(); + + Persistence persistence = Persistence.getInstance(); + + public void mainMenuScene() { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene("MainMenu")); + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + iniPieChartKD(); + iniPieChartWL(); + kd.setLegendVisible(false); + wl.setLegendVisible(false); + setLabels(); + } + + private void setLabels() { + kills.setText(String.valueOf(persistence.getStatistics().getKills())); + gamesWon.setText(Integer.toString(persistence.getStatistics().getGamesWon())); + gamesLost.setText(String.valueOf(persistence.getStatistics().getGamesLost())); + gameTime.setText(Integer.toString(persistence.getStatistics().getGameTimeInHours())); + deaths.setText(String.valueOf(persistence.getStatistics().getDeaths())); + blocks.setText(Integer.toString(persistence.getStatistics().getBlocksDestroyed())); + } + + public void iniPieChartKD() { + ObservableList<PieChart.Data> pieChartData = + FXCollections.observableArrayList( + new PieChart.Data("Kills", persistence.getStatistics().getKills()), + new PieChart.Data("Deaths", persistence.getStatistics().getDeaths())); + + pieChartData.forEach(data -> + data.nameProperty().bind( + Bindings.concat( + data.getName(), ": ", data.pieValueProperty() + ) + ) + ); + kd.getData().addAll(pieChartData); + } + + public void iniPieChartWL() { + ObservableList<PieChart.Data> pieChartData = + FXCollections.observableArrayList( + new PieChart.Data("Wins", persistence.getStatistics().getGamesWon()), + new PieChart.Data("Losses", persistence.getStatistics().getGamesLost())); + + pieChartData.forEach(data -> + data.nameProperty().bind( + Bindings.concat( + data.getName(), ": ", data.pieValueProperty() + ) + ) + ); + wl.getData().addAll(pieChartData); + } +} + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ButtonTransition.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ButtonTransition.java new file mode 100644 index 0000000000000000000000000000000000000000..b129d469320cdd8549e234a3a5d6fae8901187ea --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ButtonTransition.java @@ -0,0 +1,29 @@ +package de.hdm_stuttgart.battlearena.Controller.Utilities; + +import javafx.animation.ScaleTransition; +import javafx.scene.control.Button; +import javafx.scene.control.skin.ButtonSkin; +import javafx.util.Duration; + +public class ButtonTransition extends ButtonSkin { + public ButtonTransition(Button button) { + super(button); +// set transition for mouse hovering over button + final ScaleTransition fadeIn = new ScaleTransition(Duration.millis(150)); + fadeIn.setNode(button); + fadeIn.setToX(1.1); + fadeIn.setToY(1.1); + button.setOnMouseEntered(e -> fadeIn.playFromStart()); + +// set transition for mouse exiting buttonButtonTransitionScale + final ScaleTransition fadeOut = new ScaleTransition(Duration.millis(150)); + fadeOut.setNode(button); + fadeOut.setToX(1.0); + fadeOut.setToY(1.0); + button.setOnMouseExited(e -> fadeOut.playFromStart()); + + button.setScaleX(1.0); + button.setScaleY(1.0); + } +} + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/CreateMediaPlayer.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/CreateMediaPlayer.java new file mode 100644 index 0000000000000000000000000000000000000000..4bf6c165db835d9908078118b40628cbfbc2350a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/CreateMediaPlayer.java @@ -0,0 +1,25 @@ +package de.hdm_stuttgart.battlearena.Controller.Utilities; + +import javafx.scene.layout.BorderPane; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; + +import java.io.File; + +public class CreateMediaPlayer { + public MediaPlayer getMediaPlayer(MediaView mediaView, File file, boolean isFullscreen, BorderPane... parent) { + Media media = new Media(file.toURI().toString()); + MediaPlayer mediaPlayer = new MediaPlayer(media); + +// resizing once the scenes has been loaded to get width and height property + if (isFullscreen) { + mediaPlayer.setOnReady(() -> { + mediaView.fitWidthProperty().bind(parent[0].getScene().widthProperty()); + mediaView.fitHeightProperty().bind(parent[0].getScene().heightProperty()); + }); + } + mediaPlayer.setAutoPlay(true); + return mediaPlayer; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/MusicPlayerSingleton.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/MusicPlayerSingleton.java new file mode 100644 index 0000000000000000000000000000000000000000..df8991982ff1b19ed4442b9e541b85b1d27397a4 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/MusicPlayerSingleton.java @@ -0,0 +1,23 @@ +package de.hdm_stuttgart.battlearena.Controller.Utilities; +import javafx.scene.media.MediaPlayer; + +public class MusicPlayerSingleton { +// creating a singleton, so it can be stopped from other controller classes + private static final MusicPlayerSingleton instance = new MusicPlayerSingleton(); + private MediaPlayer mediaPlayer; + + private MusicPlayerSingleton() {} + + public static MusicPlayerSingleton getInstance() { + return instance; + } + + public MediaPlayer getMediaPlayer() { + return mediaPlayer; + } + + public void setMediaPlayer(MediaPlayer mediaPlayer) { + this.mediaPlayer = mediaPlayer; + } +} + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SceneLoader.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/SceneLoader.java similarity index 93% rename from src/main/java/de/hdm_stuttgart/battlearena/Controller/SceneLoader.java rename to src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/SceneLoader.java index 0d5a04ef5789505821f173c05997a43313b8b33d..8c0e8b4a9487316777dd42b0823e07b737386208 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SceneLoader.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/SceneLoader.java @@ -1,4 +1,4 @@ -package de.hdm_stuttgart.battlearena.Controller; +package de.hdm_stuttgart.battlearena.Controller.Utilities; import javafx.fxml.FXMLLoader; import javafx.scene.layout.Pane; diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ScreenClasses.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ScreenClasses.java new file mode 100644 index 0000000000000000000000000000000000000000..469d628a724f3761c23b14fc85f602966e3d0720 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ScreenClasses.java @@ -0,0 +1,28 @@ +package de.hdm_stuttgart.battlearena.Controller.Utilities; + +public enum ScreenClasses { +// enums have a range because the screen calculations are not precise, especially with screen scaling in the OS settings + INCH27(26, 28), + INCH24(23, 25), + INCH13_SURFACE(12, 14); + + final int lBound, uBound; + + ScreenClasses(int lBound, int uBound) { + this.lBound = lBound; + this.uBound = uBound; + } + + public static ScreenClasses inRange(int inches) { + for (ScreenClasses screens : ScreenClasses.values()) { + if (screens.isInRange(inches)) { + return screens; + } + } + return null; + } + + private boolean isInRange(int inches) { + return inches >= lBound && inches <= uBound; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ScreenDimensionCalculator.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ScreenDimensionCalculator.java new file mode 100644 index 0000000000000000000000000000000000000000..4dee18cfe414ec04cc2323954e0ae0d77a128902 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ScreenDimensionCalculator.java @@ -0,0 +1,12 @@ +package de.hdm_stuttgart.battlearena.Controller.Utilities; + +public class ScreenDimensionCalculator { + public double calculateDiagonalInches(double width, double height, double dpi) { + double diagonalPixels = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); + double diagonalInches = diagonalPixels / dpi; + System.out.println("diagonal pixels: " + diagonalPixels); + System.out.println("width: " + width); + System.out.println("height: " + height); + return diagonalInches; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ToggleButtonTransition.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ToggleButtonTransition.java new file mode 100644 index 0000000000000000000000000000000000000000..94d51e4b2524cc0428678adadcf57b01e61dd643 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ToggleButtonTransition.java @@ -0,0 +1,49 @@ +package de.hdm_stuttgart.battlearena.Controller.Utilities; + +import javafx.animation.FadeTransition; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.skin.ToggleButtonSkin; +import javafx.util.Duration; + +public class ToggleButtonTransition extends ToggleButtonSkin { + private final FadeTransition fadeIn; + private final FadeTransition fadeOut; + + public ToggleButtonTransition(ToggleButton toggleButton) { + super(toggleButton); + + fadeIn = new FadeTransition(Duration.millis(150)); + fadeIn.setNode(toggleButton); + fadeIn.setToValue(1); + + fadeOut = new FadeTransition(Duration.millis(150)); + fadeOut.setNode(toggleButton); + fadeOut.setToValue(0.5); + + toggleButton.setOnMouseEntered(e -> fadeIn.playFromStart()); + toggleButton.setOnMouseExited(e -> { + if (!toggleButton.isSelected()) { + fadeOut.playFromStart(); + } + }); + + toggleButton.selectedProperty().addListener((observable, oldValue, newValue) -> { + if (newValue) { + fadeIn.playFromStart(); + fadeOut.setToValue(0.5); // Set fadeOut back to the default value + } else { + fadeOut.playFromStart(); + toggleButton.setOpacity(0.5); + } + }); + + // Set the initial opacity based on the initial selected state + toggleButton.setOpacity(toggleButton.isSelected() ? 1.0 : 0.5); + + } +} + + + + + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Main/Main.java b/src/main/java/de/hdm_stuttgart/battlearena/Main/Main.java index c0b72d22f39968742ba6e171b09cac77ad2c673d..dd93c23719f1f4cb260c6b9da8a0f1f1fac2b475 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Main/Main.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Main/Main.java @@ -1,14 +1,22 @@ package de.hdm_stuttgart.battlearena.Main; + import de.hdm_stuttgart.battlearena.Model.Sound.MusicType; import de.hdm_stuttgart.battlearena.Model.Sound.SFX; import de.hdm_stuttgart.battlearena.Model.Sound.SoundManager; +import de.hdm_stuttgart.battlearena.Model.Inputs.InputHandler; + import javafx.application.Application; import javafx.fxml.FXMLLoader; +import javafx.geometry.Rectangle2D; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.image.Image; +import javafx.scene.text.Font; +import javafx.stage.Screen; import javafx.stage.Stage; +import javafx.stage.StageStyle; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -17,6 +25,9 @@ import java.util.Objects; public class Main extends Application { private static final Logger log = LogManager.getLogger(Main.class); + Rectangle2D screen = Screen.getPrimary().getVisualBounds(); + + InputHandler inputHandler = InputHandler.getInstance(); public static void main(String[] args) { launch(args); @@ -24,23 +35,37 @@ public class Main extends Application { @Override public void start(Stage stage) throws Exception { - final FXMLLoader loader = new FXMLLoader(); - Parent root = loader.load(getClass().getResourceAsStream("/fxml/MainMenu.fxml")); + +// loading font in start() because CSS can't handle whitespace in folder names + Font.loadFont(getClass().getResourceAsStream("/fonts/StarshipShadow.ttf"), 50); + +// TODO: revert back to intro scene + Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/Intro.fxml"))); Scene scene = new Scene(root); + scene.setOnKeyPressed(inputHandler::handleKeyPress); + scene.setOnKeyReleased(inputHandler::handleKeyRelease); + stage.setTitle("BattleArena"); + stage.getIcons().add(new Image("file:src/main/resources/textures/images/icon.png")); + stage.setScene(scene); + stage.minHeightProperty().setValue(400); + stage.minWidthProperty().setValue(600); + stage.setMaximized(true); + stage.setWidth(screen.getWidth()); + stage.setHeight(screen.getHeight()); + stage.initStyle(StageStyle.UNDECORATED); + scene.getStylesheets().add(Objects.requireNonNull(this.getClass().getResource("/styles/style.css")).toExternalForm()); stage.setScene(scene); SoundManager soundManager = new SoundManager(); stage.setOnCloseRequest(event -> { - // Add logic here to stop media playback gracefully when the stage closes if (soundManager != null) { soundManager.stopMusic(); } - // Other cleanup tasks if needed }); soundManager.playMusic(MusicType.GAME); diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AccountType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AccountType.java new file mode 100644 index 0000000000000000000000000000000000000000..145d7a4f6f54bad787231fc80b276a2abaae261b --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AccountType.java @@ -0,0 +1,9 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +public enum AccountType { + + NONE, + LOCAL, + ONLINE + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AppSettings.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AppSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..710cf9ca3be97bbf21ff8aa00304dff1f8c19b87 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AppSettings.java @@ -0,0 +1,30 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +public class AppSettings { + + private int sfxVolume; //values from 0 to 100 (volume in percent) + private int musicVolume; //values from 0 to 100 (volume in percent) + + + public AppSettings(int sfxVolume, int musicVolume) { + this.sfxVolume = sfxVolume; + this.musicVolume = musicVolume; + } + + public void setSfxVolume(int sfxVolume) { + this.sfxVolume = sfxVolume; + } + + public int getSfxVolume() { + return sfxVolume; + } + + public void setMusicVolume(int musicVolume) { + this.musicVolume = musicVolume; + } + + public int getMusicVolume() { + return musicVolume; + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AzureDB.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AzureDB.java new file mode 100644 index 0000000000000000000000000000000000000000..f75e8d1d4f322ef6b6c6302549337ea8b2a550b4 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/AzureDB.java @@ -0,0 +1,271 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.CryptoUtils; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.CryptoException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.SQLException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.sql.*; +import java.util.ArrayList; + +/*this class is only here for showcasing the interchangeability of the DBMS. AzureDB could be used as fallback database when primary database is unreachable*/ + +public class AzureDB implements ISQLDataBase { + + private static String user=""; + private static String password=""; + private static String[] parts= new String[2]; + static File encryptedFile = new File("src\\main\\resources\\database\\AzureDB_logindetails"); + private static final Logger log = LogManager.getLogger(OracleDB.class); + + public static void getLoginData() throws CryptoException { + parts = CryptoUtils.decrypt(encryptedFile); + user = parts[0]; + password = parts[1]; + //log.info("AzureDB_logindetails: user: " + user + " password: " + password); + } + + @Override + public Connection connect() throws SQLException { + try { + getLoginData(); + String url = "jdbc:sqlserver://battlearena.database.windows.net;encrypt=true;user=" + user + ";password=" + password + ";databaseName=battleArena;"; + Connection connection = DriverManager.getConnection(url); + //log.info("Database connection test" + connection.getCatalog()); + connection.setAutoCommit(true); + + log.info("Connecting to SQL database ..."); + + return connection; + } + catch(Exception e){ + log.error(e); + throw new SQLException("SQL connection error! " + e.getMessage()); + } + } + + @Override + public ArrayList<MapData> getCoreMaps() throws SQLException { + try(Connection connection = connect()) { + ArrayList<MapData> newMaps = new ArrayList<MapData>(); + String sql = "SELECT * FROM CoreMaps"; + PreparedStatement stmt = connection.prepareStatement(sql); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + + while(rs.next()){ + newMaps.add(new MapData(rs.getString("map_id"), rs.getString("map_name"), rs.getInt("map_width"), rs.getInt("map_height"), rs.getString("map_data"))); + } + rs.close(); + stmt.close(); + log.info("Core-Maps retrieved successfully from SQL server!"); + return newMaps; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving Core-Maps from SQL server! " + e.getMessage()); + } + } + + @Override + public ArrayList<MapInfo> getCommunityMapsList() throws SQLException { + try(Connection connection = connect()) { + ArrayList<MapInfo> tempList = new ArrayList<MapInfo>(); + String sql = "SELECT map_id, map_name, map_width, map_height, map_downloads FROM communitymaps"; + PreparedStatement stmt = connection.prepareStatement(sql); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + + while(rs.next()){ + tempList.add(new MapInfo(rs.getString("map_id"), rs.getString("map_name"), rs.getInt("map_width"), rs.getInt("map_height"), rs.getInt("map_downloads"))); + } + rs.close(); + stmt.close(); + log.info("Community-Map names retrieved successfully from SQL server!"); + return tempList; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving Community-Map names from SQL server! " + e.getMessage()); + } + } + + @Override + public PlayerStatistics getStatistics(String playerName) throws SQLException { + try(Connection connection = connect()) { + String sql = "SELECT games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time FROM players WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, playerName); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + if(rs.next() == false){ //if no data matches + throw new SQLException("No match on SQL database!"); + } + PlayerStatistics stats = new PlayerStatistics(0, 0, 0, 0, 0, 0); + while(rs.next()) { + stats = new PlayerStatistics(rs.getInt("games_won"), rs.getInt("games_lost"), rs.getInt("kills"), rs.getInt("deaths"), rs.getInt("blocks_destroyed"), rs.getInt("ingame_time")); + } + rs.close(); + stmt.close(); + log.info("Player statistics retrieved successfully from SQL server!"); + return stats; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving player statistics from SQL server! " + e.getMessage()); + } + } + + @Override + public MapData getCommunityMapByID(String mapID) throws SQLException { + try(Connection connection = connect()) { + String sql = "SELECT * FROM communitymaps WHERE map_ID = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, mapID); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + MapData mapChosen = new MapData("", "",0,0, ""); + if(rs.next() == false){ //if no data matches + throw new SQLException("No match on SQL database!"); + } + while(rs.next()) { + mapChosen = new MapData(rs.getString("map_id"), rs.getString("map_name"), rs.getInt("map_width"), rs.getInt("map_height"), rs.getString("map_data")); + } + rs.close(); + stmt.close(); + log.info("Community-Map retrieved successfully from SQL server!"); + + String sql2 = "UPDATE communitymaps SET map_downloads = map_downloads + 1 WHERE map_id = ?"; + PreparedStatement stmt2 = connection.prepareStatement(sql2); + stmt2.setString(1, mapID); + stmt2.executeQuery(); + log.info("Sending SQL statement to update Download-Counter for downloaded map."); + stmt2.close(); + + return mapChosen; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving Community-Map from SQL server! " + e.getMessage()); + } + } + + @Override + public String checkCredentials(String playerName) throws SQLException { + try(Connection connection = connect()) { + String sql = "SELECT player_pw FROM players WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, playerName); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + + String password = ""; + while(rs.next()) { + password = rs.getString("player_pw"); + } + rs.close(); + stmt.close(); + log.info("Player credentials retrieved successfully from SQL server!"); + return password; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving retrieving player credentials from SQL server! " + e.getMessage()); + } + } + + @Override + public void uploadCommunityMap(MapData map) throws SQLException { + try(Connection connection = connect()) { + String sql = "INSERT INTO communitymaps (map_id, map_name, map_width, map_height, map_data, map_downloads) VALUES (?, ?, ?, ?, ?, 0)"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, map.getMapID()); + stmt.setString(2, map.getMapName()); + stmt.setInt(3, map.getMapWidth()); + stmt.setInt(4, map.getMapHeight()); + stmt.setString(5, map.getMapData()); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Community-Map uploaded successfully to SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error uploading created Community-Map to SQL server! " + e.getMessage()); + } + } + + @Override + public void createPlayer(String playerName, String playerPW) throws SQLException { + try(Connection connection = connect()) { + String sql = "INSERT INTO players (player_name, player_pw, games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time) VALUES (?, ?, 0, 0, 0, 0, 0, 0)"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, playerName); + stmt.setString(2, playerPW); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Online account created successfully on SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error creating online account on SQL server! " + e.getMessage()); + } + } + + @Override + public void updatePlayerStats(PlayerStatistics stats, PlayerAccount account) throws SQLException { + try(Connection connection = connect()) { + String sql = "UPDATE players SET games_won = ?, games_lost = ?, kills = ?, deaths = ?, blocks_destroyed = ?, ingame_time = ? WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setInt(1, stats.getGamesWon()); + stmt.setInt(2, stats.getGamesLost()); + stmt.setInt(3, stats.getKills()); + stmt.setInt(4, stats.getDeaths()); + stmt.setInt(5, stats.getBlocksDestroyed()); + stmt.setInt(6, stats.getGameTime()); + stmt.setString(7, account.getPlayerName()); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Player statistics updated successfully on SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error updating player statistics on SQL server! " + e.getMessage()); + } + } + + @Override + public void resetPlayerStats(PlayerAccount account) throws SQLException{ //verification of player credentials necessary beforehand (use methode "verifyAccountData" in "Persistence.java) + try(Connection connection = connect()) { + String sql = "UPDATE players SET games_won = 0, games_lost = 0, kills = 0, deaths = 0, blocks_destroyed = 0, ingame_time = 0 WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, account.getPlayerName()); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Player statistics reset successfully on SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error resetting player statistics on SQL server! " + e.getMessage()); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/CryptoException.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/CryptoException.java new file mode 100644 index 0000000000000000000000000000000000000000..1bb0c30885d3d243bf25ff82449b3c33fc7dc72b --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/CryptoException.java @@ -0,0 +1,7 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions; + +public class CryptoException extends Exception{ + public CryptoException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/DatabaseException.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/DatabaseException.java new file mode 100644 index 0000000000000000000000000000000000000000..57a4b7f978103f55a4a83525db1353be7b1fe4fb --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/DatabaseException.java @@ -0,0 +1,12 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions; + +public class DatabaseException extends Exception{ + + public DatabaseException() {} + + public DatabaseException(String message2) + { + super(message2); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/GSONException.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/GSONException.java new file mode 100644 index 0000000000000000000000000000000000000000..f16aa2d2831903fca6ccbd1555c798b53132f872 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/GSONException.java @@ -0,0 +1,12 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions; + +public class GSONException extends Exception{ + + public GSONException() {} + + public GSONException(String message2) + { + super(message2); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/ParserException.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/ParserException.java new file mode 100644 index 0000000000000000000000000000000000000000..27bd887ed9a7b5cb604d63e2194c818c91cae56a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/ParserException.java @@ -0,0 +1,12 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions; + +public class ParserException extends Exception{ + + public ParserException() {} + + public ParserException(String message2) + { + super(message2); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/SQLException.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/SQLException.java new file mode 100644 index 0000000000000000000000000000000000000000..adbdfa7fac0321fd39687bd957c7f05f542aaaa9 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Exceptions/SQLException.java @@ -0,0 +1,12 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions; + +public class SQLException extends Exception{ + + public SQLException() {} + + public SQLException(String message2) + { + super(message2); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/GsonHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/GsonHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..308b553a68422590c8a0619baa336e91ee513bb2 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/GsonHandler.java @@ -0,0 +1,149 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.GSONException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.FileReader; +import java.io.FileWriter; +import java.lang.reflect.Type; +import java.util.ArrayList; + +public class GsonHandler { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + private static final Logger log = LogManager.getLogger(GsonHandler.class); + Type mapDataType = new TypeToken<ArrayList<MapData>>(){}.getType(); + Type playerStatsType = new TypeToken<PlayerStatistics>(){}.getType(); + Type settingsType = new TypeToken<AppSettings>(){}.getType(); + Type accountType = new TypeToken<PlayerAccount>(){}.getType(); + + private final String filePathCoreMaps = "src/main/resources/maps/coreMaps.json"; + private final String filePathCommunityMaps = "src/main/resources/maps/communityMaps.json"; + private final String filePathPlayerStats = "src/main/resources/player/playerStatsLocal.json"; + private final String filePathPlayerAccount = "src/main/resources/player/playerAccount.json"; + private final String filePathSettings = "src/main/resources/player/appSettings.json"; + + public ArrayList<MapData> loadMaps(MapType type) throws GSONException { + String filePath; + if(type == MapType.COREMAP){ + filePath = filePathCoreMaps; + } + else{ + filePath = filePathCommunityMaps; + } + try (FileReader reader = new FileReader(filePath)) { + ArrayList<MapData> maps = gson.fromJson(reader, mapDataType); + log.info("GSON - Maps successfully loaded from JSON!"); + return maps; + } catch (Exception e) { + log.info(e); + if(type == MapType.COREMAP){ + log.info("GSON - Loading Core-Maps from JSON failed!"); + throw new GSONException("Loading Core-Maps from JSON failed!"); + } + else{ + log.info("GSON - Loading Community-Maps from JSON failed!"); + throw new GSONException("Loading Community-Maps from JSON failed!"); + } + } + } + + public void saveMaps(ArrayList<MapData> maps, MapType type) throws GSONException { + String filePath; + if(type == MapType.COREMAP){ + filePath = filePathCoreMaps; + } + else{ + filePath = filePathCommunityMaps; + } + try (FileWriter writer = new FileWriter(filePath)) { + gson.toJson(maps, writer); + log.info("GSON - Maps successfully saved to JSON!"); + } catch (Exception e) { + log.info(e); + if(type == MapType.COREMAP){ + log.info("GSON - Saving Core-Maps to JSON failed!"); + throw new GSONException("Saving Core-Maps to JSON failed!"); + } + else{ + log.info("GSON - Saving Community-Maps to JSON failed!"); + throw new GSONException("Saving Community-Maps to JSON failed!"); + } + } + } + + public PlayerStatistics loadStats() throws GSONException { + try (FileReader reader = new FileReader(filePathPlayerStats)) { + PlayerStatistics stats = gson.fromJson(reader, playerStatsType); + log.info("GSON - Player statistics successfully loaded from JSON!"); + return stats; + } catch (Exception e) { + log.info(e); + log.info("GSON - Loading player statistics from JSON failed!"); + throw new GSONException("Loading player statistics from JSON failed!"); + } + } + + public void saveStats(PlayerStatistics stats) throws GSONException { + try (FileWriter writer = new FileWriter(filePathPlayerStats)) { + gson.toJson(stats, writer); + log.info("GSON - Player statistics successfully saved to JSON!"); + } catch (Exception e) { + log.info(e); + log.info("GSON - Saving player statistics to JSON failed!"); + throw new GSONException("Saving player statistics to JSON failed!"); + } + } + + public AppSettings loadSettings() throws GSONException { + try (FileReader reader = new FileReader(filePathSettings)) { + AppSettings settings = gson.fromJson(reader, settingsType); + log.info("GSON - Settings successfully loaded from JSON!"); + return settings; + } catch (Exception e) { + log.info(e); + log.info("GSON - Loading settings from JSON failed!"); + throw new GSONException("Loading settings from JSON failed!"); + } + } + + public void saveSettings(AppSettings settings) throws GSONException { + try (FileWriter writer = new FileWriter(filePathSettings)) { + gson.toJson(settings, writer); + log.info("GSON - Settings successfully saved to JSON!"); + } catch (Exception e) { + log.info(e); + log.info("GSON - Saving settings to JSON failed!"); + throw new GSONException("Saving settings to JSON failed!"); + } + } + + public PlayerAccount loadAccount() throws GSONException { + try (FileReader reader = new FileReader(filePathPlayerAccount)) { + PlayerAccount account = gson.fromJson(reader, accountType); + log.info("GSON - Player account information successfully loaded from JSON!"); + return account; + } catch (Exception e) { + log.info(e); + log.info("GSON - Loading player account information from JSON failed!"); + throw new GSONException("Loading player account information from JSON failed!"); + } + } + + public void saveAccount(PlayerAccount account) throws GSONException { + try (FileWriter writer = new FileWriter(filePathPlayerAccount)) { + gson.toJson(account, writer); + log.info("GSON - Player account information successfully saved to JSON!"); + } catch (Exception e) { + log.info(e); + log.info("GSON - Saving player account information to JSON failed!"); + throw new GSONException("Saving player account information to JSON failed!"); + } + } + + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ISQLDataBase.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ISQLDataBase.java new file mode 100644 index 0000000000000000000000000000000000000000..7a169c9b21d76b2a7eba64b8899dbb5e397b22cb --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ISQLDataBase.java @@ -0,0 +1,24 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.SQLException; + +import java.sql.Connection; +import java.util.ArrayList; + +public interface ISQLDataBase { + + //Establish Connection + Connection connect() throws SQLException; + + //CRUD Operations in SQL + ArrayList<MapData> getCoreMaps() throws SQLException; + ArrayList<MapInfo> getCommunityMapsList() throws SQLException; + MapData getCommunityMapByID(String mapID) throws SQLException; + void uploadCommunityMap(MapData map) throws SQLException; + void createPlayer(String playerName, String playerPW) throws SQLException; + String checkCredentials(String playerName) throws SQLException; + PlayerStatistics getStatistics(String playerName) throws SQLException; + void updatePlayerStats(PlayerStatistics stats, PlayerAccount account) throws SQLException; + void resetPlayerStats(PlayerAccount account) throws SQLException; + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapData.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapData.java new file mode 100644 index 0000000000000000000000000000000000000000..2a88a714ec211cc081dfb511673568de0d2ba6fd --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapData.java @@ -0,0 +1,38 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +public class MapData { + private String mapID; + private String mapName; + private int mapWidth; //included for future use (to allow maps of different size) + private int mapHeight; //included for future use (to allow maps of different size) + private String mapData; + + protected MapData(String mapID, String mapName, int mapWidth, int mapHeight, String mapData) { + this.mapID = mapID; + this.mapName = mapName; + this.mapWidth = mapWidth; + this.mapHeight = mapHeight; + this.mapData = mapData; + } + + public String getMapID() { + return mapID; + } + + public String getMapName() { + return mapName; + } + + public int getMapWidth() { + return mapWidth; + } + + public int getMapHeight() { + return mapHeight; + } + + public String getMapData() { + return mapData; + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapInfo.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..17fcfdfc65a8777e255f3501ed59e103bfb13f3b --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapInfo.java @@ -0,0 +1,40 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +public class MapInfo { + + private String mapID; + private String mapName; + private int mapWidth; //included for future use (to allow maps of different size) + private int mapHeight; //included for future use (to allow maps of different size) + private int mapDownloads; //only used for communityMapsList + + protected MapInfo(String mapID, String mapName, int mapWidth, int mapHeight, int mapDownloads) { + this.mapID = mapID; + this.mapName = mapName; + this.mapWidth = mapWidth; + this.mapHeight = mapHeight; + this.mapDownloads = mapDownloads; + } + + public String getMapID() { + return mapID; + } + + public String getMapName() { + return mapName; + } + + public int getMapWidth() { + return mapWidth; + } + + public int getMapHeight() { + return mapHeight; + } + + public int getMapDownloads() { + return mapDownloads; + } + +} + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapType.java new file mode 100644 index 0000000000000000000000000000000000000000..d7738b3c5205d4f217e2a27f0e88578cc34f6fa1 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/MapType.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +public enum MapType { + + COREMAP, + COMMUNITYMAP + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/OracleDB.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/OracleDB.java new file mode 100644 index 0000000000000000000000000000000000000000..856fe24df247e972c4ed074ddddce4fd1f71a1ce --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/OracleDB.java @@ -0,0 +1,272 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.CryptoUtils; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.CryptoException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.SQLException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.sql.*; +import java.util.ArrayList; + +import oracle.jdbc.pool.OracleDataSource; + +public class OracleDB implements ISQLDataBase { + + private static String user=""; + private static String password=""; + private static String[] parts= new String[2]; + static File encryptedFile = new File("src\\main\\resources\\database\\OracleDB_logindetails"); + private static final Logger log = LogManager.getLogger(OracleDB.class); + + public static void getLoginData() throws CryptoException { + parts = CryptoUtils.decrypt(encryptedFile); + user = parts[0]; + password = parts[1]; + //log.info("OracleDB_logindetails: user: " + user + " password: " + password); + } + + @Override + public Connection connect() throws SQLException { + try { + getLoginData(); + OracleDataSource ods = new OracleDataSource(); + ods.setURL("jdbc:oracle:thin:@(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.eu-frankfurt-1.oraclecloud.com))(connect_data=(service_name=g093caf2cf1fea4_battlearena_high.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))"); + ods.setUser(user); + ods.setPassword(password); + Connection conn = ods.getConnection(); + + log.info("Connecting to SQL database ..."); + + return conn; + } + catch(Exception e){ + log.error(e); + throw new SQLException("SQL connection error! " + e.getMessage()); + } + } + + @Override + public ArrayList<MapData> getCoreMaps() throws SQLException { + try(Connection connection = connect()) { + ArrayList<MapData> newMaps = new ArrayList<MapData>(); + String sql = "SELECT * FROM battlearenadata.coremaps"; + PreparedStatement stmt = connection.prepareStatement(sql); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + + while(rs.next()){ + newMaps.add(new MapData(rs.getString("map_id"), rs.getString("map_name"), rs.getInt("map_width"), rs.getInt("map_height"), rs.getString("map_data"))); + } + rs.close(); + stmt.close(); + log.info("Core-Maps retrieved successfully from SQL server!"); + return newMaps; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving Core-Maps from SQL server! " + e.getMessage()); + } + } + + @Override + public ArrayList<MapInfo> getCommunityMapsList() throws SQLException { + try(Connection connection = connect()) { + ArrayList<MapInfo> tempList = new ArrayList<MapInfo>(); + String sql = "SELECT map_id, map_name, map_width, map_height, map_downloads FROM battlearenadata.communitymaps"; + PreparedStatement stmt = connection.prepareStatement(sql); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + + while(rs.next()){ + tempList.add(new MapInfo(rs.getString("map_id"), rs.getString("map_name"), rs.getInt("map_width"), rs.getInt("map_height"), rs.getInt("map_downloads"))); + } + rs.close(); + stmt.close(); + log.info("Community-Map names retrieved successfully from SQL server!"); + return tempList; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving Community-Map names from SQL server! " + e.getMessage()); + } + } + + @Override + public PlayerStatistics getStatistics(String playerName) throws SQLException { + try(Connection connection = connect()) { + String sql = "SELECT games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time FROM battlearenadata.players WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, playerName); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + if(rs.next() == false){ //if no data matches + throw new SQLException("No match on SQL database!"); + } + PlayerStatistics stats = new PlayerStatistics(0, 0, 0, 0, 0, 0); + while(rs.next()) { + stats = new PlayerStatistics(rs.getInt("games_won"), rs.getInt("games_lost"), rs.getInt("kills"), rs.getInt("deaths"), rs.getInt("blocks_destroyed"), rs.getInt("ingame_time")); + } + rs.close(); + stmt.close(); + log.info("Player statistics retrieved successfully from SQL server!"); + return stats; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving player statistics from SQL server! " + e.getMessage()); + } + } + + @Override + public MapData getCommunityMapByID(String mapID) throws SQLException { + try(Connection connection = connect()) { + String sql = "SELECT * FROM battlearenadata.communitymaps WHERE map_ID = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, mapID); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + MapData mapChosen = new MapData("", "",0,0, ""); + if(rs.next() == false){ //if no data matches + throw new SQLException("No match on SQL database!"); + } + while(rs.next()) { + mapChosen = new MapData(rs.getString("map_id"), rs.getString("map_name"), rs.getInt("map_width"), rs.getInt("map_height"), rs.getString("map_data")); + } + rs.close(); + stmt.close(); + log.info("Community-Map retrieved successfully from SQL server!"); + + String sql2 = "UPDATE battlearenadata.communitymaps SET map_downloads = map_downloads + 1 WHERE map_id = ?"; + PreparedStatement stmt2 = connection.prepareStatement(sql2); + stmt2.setString(1, mapID); + stmt2.executeQuery(); + log.info("Sending SQL statement to update Download-Counter for downloaded map!"); + stmt2.close(); + + return mapChosen; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving Community-Map from SQL server! " + e.getMessage()); + } + } + + @Override + public String checkCredentials(String playerName) throws SQLException { + try(Connection connection = connect()) { + String sql = "SELECT player_pw FROM battlearenadata.players WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, playerName); + + log.info("Sending SQL statement."); + ResultSet rs = stmt.executeQuery(); + + String password = ""; + while(rs.next()) { + password = rs.getString("player_pw"); + } + rs.close(); + stmt.close(); + log.info("Player credentials retrieved successfully from SQL server!"); + return password; + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error retrieving retrieving player credentials from SQL server! " + e.getMessage()); + } + } + + @Override + public void uploadCommunityMap(MapData map) throws SQLException { + try(Connection connection = connect()) { + String sql = "INSERT INTO battlearenadata.communitymaps (map_id, map_name, map_width, map_height, map_data, map_downloads) VALUES (?, ?, ?, ?, ?, 0)"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, map.getMapID()); + stmt.setString(2, map.getMapName()); + stmt.setInt(3, map.getMapWidth()); + stmt.setInt(4, map.getMapHeight()); + stmt.setString(5, map.getMapData()); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Community-Map uploaded successfully to SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error uploading created Community-Map to SQL server! " + e.getMessage()); + } + } + + @Override + public void createPlayer(String playerName, String playerPW) throws SQLException { + try(Connection connection = connect()) { + String sql = "INSERT INTO battlearenadata.players (player_name, player_pw, games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time) VALUES (?, ?, 0, 0, 0, 0, 0, 0)"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, playerName); + stmt.setString(2, playerPW); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Online account created successfully on SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error creating online account on SQL server! " + e.getMessage()); + } + } + + @Override + public void updatePlayerStats(PlayerStatistics stats, PlayerAccount account) throws SQLException { + try(Connection connection = connect()) { + String sql = "UPDATE battlearenadata.players SET games_won = ?, games_lost = ?, kills = ?, deaths = ?, blocks_destroyed = ?, ingame_time = ? WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setInt(1, stats.getGamesWon()); + stmt.setInt(2, stats.getGamesLost()); + stmt.setInt(3, stats.getKills()); + stmt.setInt(4, stats.getDeaths()); + stmt.setInt(5, stats.getBlocksDestroyed()); + stmt.setInt(6, stats.getGameTime()); + stmt.setString(7, account.getPlayerName()); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Player statistics updated successfully on SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error updating player statistics on SQL server! " + e.getMessage()); + } + } + + @Override + public void resetPlayerStats(PlayerAccount account) throws SQLException{ //verification of player credentials necessary beforehand (use methode "verifyAccountData" in "Persistence.java) + try(Connection connection = connect()) { + String sql = "UPDATE battlearenadata.players SET games_won = 0, games_lost = 0, kills = 0, deaths = 0, blocks_destroyed = 0, ingame_time = 0 WHERE player_name = ?"; + PreparedStatement stmt = connection.prepareStatement(sql); + stmt.setString(1, account.getPlayerName()); + + log.info("Sending SQL statement."); + stmt.executeQuery(); + + stmt.close(); + log.info("Player statistics reset successfully on SQL server!"); + } + catch(Exception e){ + log.error(e); + throw new SQLException("Error resetting player statistics on SQL server! " + e.getMessage()); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Persistence.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Persistence.java new file mode 100644 index 0000000000000000000000000000000000000000..638529da884c6bd83ae1f34bf67c653b6c73b89e --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Persistence.java @@ -0,0 +1,473 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.GSONException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.ParserException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.SQLException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.HashGenerator; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.DatabaseException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.Parser; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import java.util.ArrayList; + +public class Persistence { + + private static final Logger log = LogManager.getLogger(Persistence.class); + private static final Persistence persistenceSingleton = new Persistence(); + private final GsonHandler gsonHandler = new GsonHandler(); + protected OracleDB db = new OracleDB(); //evtl. Methoden von OracleDB static machen und von GSON Handler ; "protected" for testing purposes to showcase Mockito tests + private ArrayList<MapData> coreMaps; + private ArrayList<MapData> communityMaps; + private PlayerStatistics statistics; + private PlayerAccount account; + private AppSettings settings; + protected ArrayList<MapInfo> communityMapsListRemote; //for community map browser + + + + private Persistence (){} + + public static Persistence getInstance(){ + return persistenceSingleton; + } + + public ArrayList<MapData> getCoreMaps() { + return coreMaps; + } + + public ArrayList<MapData> getCommunityMaps() { + return communityMaps; + } + + public PlayerStatistics getStatistics() { + return statistics; + } + + public PlayerAccount getAccount() { + return account; + } + + public AppSettings getSettings() { + return settings; + } + + public ArrayList<MapInfo> getCommunityMapsListRemote() { + return communityMapsListRemote; + } + + public void loadPlayerAccount() throws DatabaseException { + try { + account = gsonHandler.loadAccount(); + log.info("Player account successfully loaded!"); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException("Loading player account data from local storage failed!"); + } + } + + public void loadPlayerStatistics() throws DatabaseException { + try { + if (account.getAccountType() == AccountType.LOCAL) { + statistics = gsonHandler.loadStats(); + } else { + statistics = db.getStatistics(account.getPlayerName()); + } + log.info("Player statistics successfully loaded!"); + } + catch(SQLException e){ + log.error(e); + if(e.getMessage().contains("ORA-17868") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException("No connection to SQL server!"); + } + else{ + throw new DatabaseException("Unknown Database Error. Retrieving statistics from SQL server failed!"); + } + } + catch(GSONException e){ + log.error(e); + throw new DatabaseException(e.getMessage()); + } + } + + public void loadCoreMaps() throws DatabaseException { + try { + coreMaps = gsonHandler.loadMaps(MapType.COREMAP); + log.info("Core-Maps successfully loaded from file!"); + //createCoreMapsList(); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException("Loading core maps from local storage failed!"); + } + } + + public void loadCommunityMaps() throws DatabaseException { + try { + communityMaps = gsonHandler.loadMaps(MapType.COMMUNITYMAP); + log.info("Community-Maps successfully loaded from file!"); + //createLocalCommunityMapsList(); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException("Loading community maps from local storage failed!"); + } + } + + public void loadSettings() throws DatabaseException { + try { + settings = gsonHandler.loadSettings(); + log.info("Application settings successfully loaded from file!"); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException("Loading settings from local storage failed!"); + } + } + + public void updateCoreMaps() throws DatabaseException { + try { + coreMaps = db.getCoreMaps(); + gsonHandler.saveMaps(coreMaps, MapType.COREMAP); + //createCoreMapsList(); + log.info("Core-Maps successfully updated from SQL-Server!"); + } + catch(Exception e){ + log.error(e); + if(e.getMessage().contains("ORA-17868") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException("No connection to SQL server!"); + } + else{ + throw new DatabaseException("Unknown Database Error. Retrieving Core-Map update failed!"); + } + } + } + + public void getCommunityMap(String mapID) throws DatabaseException { + for(int i = 0; communityMaps.size() > i; i++){ + if(communityMaps.get(i).getMapID().equals(mapID)){ + throw new DatabaseException("Identical map already saved locally. See map name: " + communityMaps.get(i).getMapID()); + } + } + try { + communityMaps.add(db.getCommunityMapByID(mapID)); + gsonHandler.saveMaps(communityMaps, MapType.COMMUNITYMAP); + //createLocalCommunityMapsList(); + log.info("Community Map successfully retrieved from SQL-Server!"); + } + catch(Exception e){ + log.error(e); + if(e.getMessage().contains("ORA-17868") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException("No connection to SQL server!"); + } + else if(e.getMessage().equals("No match on Database!")){ + throw new DatabaseException("No map existing for mapID: " + mapID); + } + else{ + throw new DatabaseException("Unknown Database Error. Retrieving Community-Map failed!"); + } + } + } + +/* public MapData getGameMap(String mapSelected, boolean choseCoremaps) throws DatabaseException{ + String mapID = mapSelected.substring(mapSelected.indexOf("(") + 1, mapSelected.length() - 1); + if (choseCoremaps) { + for (int index = 0; index < coreMaps.size(); index++) { + if (coreMaps.get(index).getMapID().equals(mapID)) { + return coreMaps.get(index); + } + } + } else { + for (int index = 0; index < communityMaps.size(); index++) { + if (communityMaps.get(index).getMapID().equals(mapID)) { + return coreMaps.get(index); + } + } + } + throw new DatabaseException("Database error - Map not found!"); + }*/ + + public void saveSettings(){ + try{ + gsonHandler.saveSettings(settings); + } + catch(Exception e){ + log.error(e); + } + } + + public void savePlayerStatistics() throws DatabaseException{ //on shutdown of game + try { + if (account.getAccountType() == AccountType.LOCAL) { + gsonHandler.saveStats(statistics); + } else if (account.getAccountType() == AccountType.ONLINE) { + db.updatePlayerStats(statistics, account); + } + log.info("Statistics successfully saved!"); + } + catch(Exception e){ + log.error(e); + } + } + + public void saveCreatedMapLocally(MapData map) throws DatabaseException { + try { + for(int i = 0; communityMaps.size() > i; i++){ + if(communityMaps.get(i).getMapID().equals(map.getMapID())){ + throw new DatabaseException("Identical map already saved locally. See map name: " + communityMaps.get(i).getMapID()); + } + } + communityMaps.add(map); + gsonHandler.saveMaps(communityMaps, MapType.COMMUNITYMAP); + //createLocalCommunityMapsList(); + log.info("Newly created map stored successfully in JSON!"); + } + catch(Exception e){ + log.error(e); + if(e.getMessage().contains("Identical map already saved") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException(e.getMessage()); + } + else{ + throw new DatabaseException("Unknown Database Error. Saving newly created Community-Map locally failed!"); + } + } + } + + public void uploadCreatedMap(MapData map) throws DatabaseException { + try { + db.uploadCommunityMap(map); + log.info("Newly created Community-Map successfully published!"); + } + catch(Exception e){ + log.error(e); + if(e.getMessage().contains("ORA-17868") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException("No connection to SQL server!"); + } + else if(e.getMessage().contains("ORA-00001")){ + throw new DatabaseException("Map already existing on communityMaps server!\n Look for mapID: " + map.getMapID()); + } + else{ + throw new DatabaseException("Unknown Database Error. Saving to SQL communityMap server failed!"); + } + } + } + + public void updatePlayerStatistics(int kills, int deaths, int gameTime, int blocksDestroyed, boolean gameWon) throws DatabaseException{ //after game round + statistics.addKills(kills); + statistics.addDeaths(deaths); + statistics.addGameTime(gameTime); + statistics.addBlocksDestroyed(blocksDestroyed); + if(gameWon){ + statistics.addGamesWon(); + } + else{ + statistics.addGamesLost(); + } + log.info("Statistics successfully updated!"); + } + + public void createAccount(String playerName, String password, AccountType type) throws DatabaseException { + try { + Parser.usernameValid(playerName); + if(type == AccountType.LOCAL) { + account = new PlayerAccount(playerName, "", type); + } + else if(type == AccountType.ONLINE) { + Parser.passwordValid(password); + String hashedPassword = HashGenerator.hashAndHex(password); + db.createPlayer(playerName, hashedPassword); + account = new PlayerAccount(playerName, hashedPassword, type); + } + else{ + throw new DatabaseException("Corrupted Account-Type. Please restart game."); + } + gsonHandler.saveAccount(account); + log.info("Player account successfully created!"); + } + catch(ParserException e){ + log.error(e); + throw new DatabaseException(e.getMessage()); + } + catch(SQLException e){ + log.error(e); + if(e.getMessage().contains("ORA-17868") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException("No connection to SQL server! Do you want to create a local account?"); + } + else if(e.getMessage().equals("ORA-00001")){ + throw new DatabaseException("Player name already taken. Please change name, use local account or login with existing account!"); + } + else{ + throw new DatabaseException("Connection to SQL server failed! Do you want to create a local account?"); + } + } + catch(Exception e){ + log.error(e); + throw new DatabaseException("Error creating account. Please restart game or download game files again."); + } + } + + public void createRemoteCommunityMapsList(){ //for Map-Browser + try { + communityMapsListRemote = db.getCommunityMapsList(); + log.info("MapList successfully retrieved from server!"); + //log.info(communityMapsListRemote.get(0).getMapName()); //for testing purposes + } + catch(Exception e){ + log.error(e); + } + } + + public void verifyPlayerAccount() throws DatabaseException { + try { + if (account.getAccountType() == AccountType.NONE) { + throw new DatabaseException("Must create playerAccount first!"); + } else if (account.getAccountType() == AccountType.LOCAL) { + Parser.usernameValid(account.getPlayerName()); + } else if (account.getAccountType() == AccountType.ONLINE) { + Parser.usernameValid(account.getPlayerName()); + Parser.sha1HexHashValid(account.getAccountPassword()); + if (!(account.getAccountPassword().equals(db.checkCredentials(account.getPlayerName())))){ + throw new DatabaseException("Locally stored password does not match online password. Please reenter credentials!"); + } + } + else{ //überflüssig, da GSON schon beim laden der Daten meckern würde, wenn er den Accounttype nicht finden kann + throw new DatabaseException("AccountType invalid - accountData corrupted! Please create new Account or login with existing!"); + } + log.info("Player account successfully verified!"); + } + catch(ParserException e){ + log.error(e); + throw new DatabaseException(e.getMessage()); + } + catch(SQLException e){ + log.error(e); + if(e.getMessage().contains("ORA-17868") | e.getMessage().contains("ORA-01017")){ + throw new DatabaseException("No connection to SQL server! Do you want to continue without tracking statistics?"); + } + else if(e.getMessage().contains("No match on SQL database!")){ + throw new DatabaseException("No entry for player name " + account.getPlayerName() + " on SQL server. Please create account or login with different username!"); + } + else{ + throw new DatabaseException("Connection to SQL server failed! Do you want to continue without tracking statistics"); + } + } + catch(Exception e){ + log.error(e); + throw new DatabaseException("Loading player account data from local storage failed! Please create new account!"); + } + } + + public void verifyCoreMaps() throws DatabaseException{ + try { + for (int i = 0; coreMaps.size() > i; i++) { + Parser.mapDataValid(coreMaps.get(i).getMapData()); + Parser.mapNameValid(coreMaps.get(i).getMapName()); + Parser.sha1HexHashValid(coreMaps.get(i).getMapID()); + if(!HashGenerator.hashAndHex(coreMaps.get(i).getMapData()).equals(coreMaps.get(i).getMapID())){ + throw new DatabaseException("mapData Hash does not match mapID!"); + } + } + log.info("Core-Maps data is valid!"); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException(e.getMessage()); + } + } + + public void verifyCommunityMaps() throws DatabaseException{ + try { + for (int i = 0; communityMaps.size() > i; i++) { + Parser.mapDataValid(communityMaps.get(i).getMapData()); + Parser.mapNameValid(communityMaps.get(i).getMapName()); + Parser.sha1HexHashValid(communityMaps.get(i).getMapID()); + if(!HashGenerator.hashAndHex(communityMaps.get(i).getMapData()).equals(communityMaps.get(i).getMapID())){ + throw new DatabaseException("mapData Hash does not match mapID!"); + } + } + log.info("Community-Maps data is valid!"); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException(e.getMessage()); + } + } + + public void verifyAppSettings() throws DatabaseException{ + try { + Parser.volumeValid(settings.getSfxVolume()); + Parser.volumeValid(settings.getMusicVolume()); + log.info("Settings data is valid!"); + } + catch(Exception e){ + log.error(e); + throw new DatabaseException(e.getMessage()); + } + } + + public void resetPlayerAccount() throws DatabaseException{ + try{ + account = new PlayerAccount("", "", AccountType.NONE); + gsonHandler.saveAccount(account); + log.info("Player account successfully reset!"); + } + catch(Exception e){ + log.error(e); + } + } + + public void resetPlayerStatistics() throws DatabaseException{ + try { + if (account.getAccountType() == AccountType.LOCAL) { + statistics = new PlayerStatistics(0, 0, 0, 0, 0, 0); + gsonHandler.saveStats(statistics); + } else if (account.getAccountType() == AccountType.ONLINE) { + verifyPlayerAccount(); + db.resetPlayerStats(account); + statistics = new PlayerStatistics(0, 0, 0, 0, 0, 0); + } + log.info("Player statistics successfully reset on local storage!"); + } + catch(Exception e){ + log.error(e); + } + } + + public void resetSettings(){ + try { + settings = new AppSettings(50, 50); + gsonHandler.saveSettings(settings); + } + catch(Exception e){ + log.error(e); + } + } + + public void resetCoreMaps(){ + try { + coreMaps = new ArrayList<MapData>(); + coreMaps.add(new MapData("09a02b54d05b5b7ebc29a4383ca12d3dda846b72", "Arena1", 18, 18, "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + coreMaps.add(new MapData("0ab15557ab6dc4be60dfe6a9b0288bac3036bd97", "Arena2", 18, 18, "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + gsonHandler.saveMaps(coreMaps, MapType.COREMAP); + log.info("Core maps successfully reset on local storage!"); + } + catch(Exception e){ + log.error(e); + } + } + + public void resetCommunityMaps(){ + try { + communityMaps = new ArrayList<MapData>(); + communityMaps.add(new MapData("fbf44184867512faecc195ae75ca55d5ab7bad2d", "Arena3", 18, 18, "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + communityMaps.add(new MapData("1c23b362fd666c5fb7ed60ca611b17246424e49f", "Arena4", 18, 18, "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 4 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + gsonHandler.saveMaps(communityMaps, MapType.COMMUNITYMAP); + log.info("Community maps successfully reset on local storage!"); + } + catch(Exception e){ + log.error(e); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerAccount.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerAccount.java new file mode 100644 index 0000000000000000000000000000000000000000..a028edd30e66fc1116615efb7764503e3746469a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerAccount.java @@ -0,0 +1,28 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +public class PlayerAccount { + + private String playerName; + private String accountPassword; //only used for Online-Account; "" for local account + private AccountType accountType; + + + public PlayerAccount(String playerName, String accountPassword, AccountType accountType) { + this.playerName = playerName; + this.accountPassword = accountPassword; + this.accountType = accountType; + } + + public String getPlayerName() { + return playerName; + } + + public String getAccountPassword() { + return accountPassword; + } + + public AccountType getAccountType() { + return accountType; + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerStatistics.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerStatistics.java new file mode 100644 index 0000000000000000000000000000000000000000..4f8783f2ee9afb7e50e038047615d63f4eaa8d20 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerStatistics.java @@ -0,0 +1,78 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class PlayerStatistics { + private static final Logger log = LogManager.getLogger(PlayerStatistics.class); + + private int gamesLost = 0; + private int gamesWon = 0; + private int kills = 0; + private int deaths = 0; + private int blocksDestroyed = 0; + private int gameTime = 0; //in seconds + + public PlayerStatistics(int gamesLost, int gamesWon, int kills, int deaths, int blocksDestroyed, int gameTime) { + this.gamesLost = gamesLost; + this.gamesWon = gamesWon; + this.kills = kills; + this.deaths = deaths; + this.blocksDestroyed = blocksDestroyed; + this.gameTime = gameTime; + } + + + public int getGamesLost() { + return gamesLost; + } + + protected void addGamesLost() { + gamesLost = gamesLost + 1; + } + + public int getGamesWon() { + return gamesWon; + } + + protected void addGamesWon() { + gamesWon = gamesWon + 1; + } + + public int getKills() { + return kills; + } + + protected void addKills(int kills) { + this.kills = this.kills + kills; + } + + public int getDeaths() { + return deaths; + } + + protected void addDeaths(int deaths) { + this.deaths = this.deaths + deaths; + } + + public int getBlocksDestroyed() { + return blocksDestroyed; + } + + protected void addBlocksDestroyed(int blocksDestroyed) { + this.blocksDestroyed = this.blocksDestroyed + blocksDestroyed; + } + + public int getGameTime() { + return gameTime; + } + + public int getGameTimeInHours(){ + return gameTime / 3600; + } + + protected void addGameTime(int gameTime) { + this.gameTime = this.gameTime + gameTime; + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/RuntimeInfo.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/RuntimeInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..14d1a3995c5cc6e831b18324cd91f745b58bdc1b --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/RuntimeInfo.java @@ -0,0 +1,91 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Controller.Enum.GameMode; +import de.hdm_stuttgart.battlearena.Controller.Enum.GameState; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.ParserException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.HashGenerator; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.Parser; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityClass; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class RuntimeInfo { + + private static final Logger log = LogManager.getLogger(RuntimeInfo.class); + private static final RuntimeInfo runtimeInfoSingleton = new RuntimeInfo(); + private String mapDataGame; + private MapData mapGame; + private boolean offlineMode; //if Account-Type is online but no SQL connection: start game without stats tracking + private GameState gameState = GameState.MENU; //Default value: MENU + private GameMode gameMode = GameMode.LOCAL; //Default value: LOCAL + + //Default value: HUMAN + private EntityClass playerOneClass = EntityClass.HUMAN; + private EntityClass playerTwoClass = EntityClass.HUMAN; + + + private RuntimeInfo(){}; + + public static RuntimeInfo getInstance(){ + return runtimeInfoSingleton; + } + + public String getMapDataGame() { + return mapDataGame; + } + + public MapData generateMap(String mapName, String mapData) throws ParserException { + try { + Parser.mapDataValid(mapData); + Parser.mapNameValid(mapName); + return new MapData(HashGenerator.hashAndHex(mapData), mapName, 18, 18, mapData); + } + catch(Exception e){ + log.error(e); + throw new ParserException(e.getMessage()); + } + } + + public void setGameMap(MapData mapSelected){ //Create Game Scene Dropdown list directly gives reference to selected map + try { + mapGame = mapSelected; + mapDataGame = mapSelected.getMapData(); + } + catch(Exception e){ + log.error(e); + } + } + + public GameState getGameState() { + return gameState; + } + + public void setGameState(GameState gameState) { + this.gameState = gameState; + } + + public GameMode getGameMode() { + return gameMode; + } + + public void setGameMode(GameMode gameMode) { + this.gameMode = gameMode; + } + + public EntityClass getPlayerOneClass() { + return playerOneClass; + } + + public void setPlayerOneClass(EntityClass playerOneClass) { + this.playerOneClass = playerOneClass; + } + + public EntityClass getPlayerTwoClass() { + return playerTwoClass; + } + + public void setPlayerTwoClass(EntityClass playerTwoClass) { + this.playerTwoClass = playerTwoClass; + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/StartupThread.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/StartupThread.java new file mode 100644 index 0000000000000000000000000000000000000000..a7ad2fddfea2cc499a0de9994f1bfe2b193f87aa --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/StartupThread.java @@ -0,0 +1,28 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class StartupThread extends Thread{ + + private static final Logger log = LogManager.getLogger(StartupThread.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + + try { + persistenceInst.loadSettings(); + persistenceInst.loadCoreMaps(); + persistenceInst.loadCommunityMaps(); + persistenceInst.verifyAppSettings(); + persistenceInst.verifyCoreMaps(); + persistenceInst.verifyCommunityMaps(); + log.info("Startup routine part1 complete!"); + } catch (Exception e) { + log.error(e); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/CryptoUtils.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/CryptoUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..757543af9f7227b44495bed77f991b06ca34716a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/CryptoUtils.java @@ -0,0 +1,159 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.CryptoException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.*; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import java.nio.charset.StandardCharsets; + + +public class CryptoUtils{ + private static String parts[] = new String[2]; + private static final String ALGORITHM = "AES"; + private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; + private static String key = "Peters Olivenöl"; + private static String encrypted_as_word = "encrypted;"; + private static boolean alreadyencrypted = false; + private static boolean multipleencryptions = false; + private static int encryptionreturn; + + private static final Logger log = LogManager.getLogger(CryptoUtils.class); + + + public static int encrypt(File inputFile, boolean multipleencryptions) throws CryptoException { + alreadyencrypted = check_if_file_already_encrypted(inputFile); + if(multipleencryptions){ + doCrypto(Cipher.ENCRYPT_MODE, key, inputFile); + log.info("This File can be encrypted multiple times"); + return encryptionreturn = 0; + } + else if(!alreadyencrypted && !multipleencryptions){ + doCrypto(Cipher.ENCRYPT_MODE, key, inputFile); + log.info("This File can only be encryptet once and this is now!"); + return encryptionreturn = 1; + }else { + log.info("This file is already encrypted and doesnt need to be encrypted anymore! " + inputFile); + return encryptionreturn = 2; + } + } + + public static String[] decrypt(File inputFile) throws CryptoException { + doCrypto(Cipher.DECRYPT_MODE, key, inputFile); + return parts; + } + + private static String[] doCrypto(int cipherMode, String key, File inputFile) throws CryptoException { + try { + Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + cipher.init(cipherMode, secretKey); + + FileInputStream inputStream = new FileInputStream(inputFile); + byte[] inputBytes = new byte[(int) inputFile.length()]; + inputStream.read(inputBytes); //liest from inputstream into BufferArray + + byte[] outputBytes = cipher.doFinal(inputBytes); + + String completeString = new String(outputBytes, StandardCharsets.UTF_8); + //log.info("completeString/outputBytes: " + completeString); + parts = completeString.split(";"); + + if(cipherMode == Cipher.ENCRYPT_MODE){ + FileOutputStream outputStream = new FileOutputStream(inputFile); + outputStream.write(outputBytes);//outputBytes + outputStream.close(); + multipleencryptions = true; + } + inputStream.close(); + + } catch (NoSuchPaddingException | NoSuchAlgorithmException + | InvalidKeyException | BadPaddingException + | IllegalBlockSizeException | IOException ex) { + throw new CryptoException("Error encrypting/decrypting file", ex); + } + return parts; + } + public static boolean check_if_file_already_encrypted(File inputFile){ + String filename = inputFile.getName(); + //log.info("filename: " + filename); + if(filename.contains(encrypted_as_word)){ + return alreadyencrypted =true; + } + inputFile.renameTo(new File("src\\main\\resources\\database\\" + encrypted_as_word + filename)); + return alreadyencrypted = false; + } + + /*public static String[] doCrypto(int cipherMode, String key, File inputFile) throws CryptoException { + try { + + String filename = inputFile.getName(); + //String encrypted_as_word = "encrypted;"; + byte[] encryptet_as_word_as_bytes = encrypted_as_word.getBytes(); + + Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + cipher.init(cipherMode, secretKey); + + FileInputStream inputStream = new FileInputStream(inputFile); + byte[] inputBytes = new byte[(int) inputFile.length()]; + inputStream.read(inputBytes); //liest from inputstream into BufferArray + + String inputbytes = new String(inputBytes, StandardCharsets.UTF_8); + String[] wellencrypted = inputbytes.split(";"); + + log.info("encrypted_as_word.substring(0,encrypted_as_word.length()-1): " + encrypted_as_word.substring(0,encrypted_as_word.length()-1)); + + if(wellencrypted[0].equals(encrypted_as_word.substring(0,encrypted_as_word.length()-1))){ + wellencrypted = Arrays.copyOfRange(wellencrypted,1,wellencrypted.length); + inputBytes = wellencrypted[0].getBytes(); + log.info("Das Wort encrypted ist enthalten!"); + log.info("inputBytes: " + new String(inputBytes, StandardCharsets.UTF_8)); + + } + log.info("wellencrypted[0]: " +wellencrypted[0]); + log.info("wel[0]: " + wel[0]); + log.info("inputbytes: " + inputbytes); + log.info("inputBytes: " + new String(inputBytes, StandardCharsets.UTF_8)); + + byte[] outputBytes = cipher.doFinal(inputBytes); + + + String completeString = new String(outputBytes, StandardCharsets.UTF_8); + log.info("completeString/outputBytes: " + completeString); + parts = completeString.split(";"); + + if(cipherMode == Cipher.ENCRYPT_MODE){ + FileOutputStream outputStream = new FileOutputStream(inputFile); + ByteArrayOutputStream outputStream12 = new ByteArrayOutputStream( ); + outputStream12.write(encryptet_as_word_as_bytes); + outputStream12.write(outputBytes); + byte combined[] = outputStream12.toByteArray( ); + String combinedbytes = new String(combined, StandardCharsets.UTF_8); + log.info("combined: " + combinedbytes); + + + outputStream.write(combined);//outputBytes + + outputStream.close(); + } + + inputStream.close(); + + } catch (NoSuchPaddingException | NoSuchAlgorithmException + | InvalidKeyException | BadPaddingException + | IllegalBlockSizeException | IOException ex) { + throw new CryptoException("Error encrypting/decrypting file", ex); + } + return parts; + }*/ +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/HashGenerator.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/HashGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..b6bead225f6a2d53dd83766c6af73a6204be0afc --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/HashGenerator.java @@ -0,0 +1,26 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class HashGenerator { + + private static final Logger log = LogManager.getLogger(HashGenerator.class); + + public static String hashAndHex(String input) throws NoSuchAlgorithmException { + //Generates SHA1 Hash from input string and converts bytes from hash to hexadecimal resulting in hexadecimal String + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + byte[] sha1Hash = sha1.digest((input).getBytes()); + String result = ""; + for (int i=0; i < sha1Hash.length; i++) { + result += + Integer.toString( ( sha1Hash[i] & 0xff ) + 0x100, 16).substring( 1 ); + } + return result; + } + + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/Parser.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/Parser.java new file mode 100644 index 0000000000000000000000000000000000000000..b7a04381a3f69ba1c3083c64986b73794d6ac51c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/Parser.java @@ -0,0 +1,361 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.ParserException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.PlayerStatistics; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Parser { + + /* + Includes public static Parser methods for: + -username + password fields when creating account or logging in with existing credentials + -map name, when creating map + -IP-address field when joining game + -Map-name or map-ID, when searching for a map + -Parser for mapData from newly created map (length, formatting (spaces), tile-types, border-tiles etc.) + */ + + public static void usernameValid(String username) throws ParserException { + int minUsernameLength = 4; + int maxUsernameLength = 40; + + if(username.length() < minUsernameLength){ + throw new ParserException("Username too short! Min length is " + minUsernameLength + " characters."); + } + if(username.length() > maxUsernameLength){ + throw new ParserException("Username too long! Max length is " + maxUsernameLength + " characters."); + } + + Pattern pat = Pattern.compile("[^a-z0-9_-]", Pattern.CASE_INSENSITIVE); + Matcher mat = pat.matcher(username); + boolean result = mat.find(); + if(result){ + throw new ParserException("Forbidden characters used! Only user letters A-Z or numbers 0-9 or symbols '-' or '_' !"); + } + } + + public static void passwordValid(String password) throws ParserException { + int minPasswordLength = 4; + int maxPasswordLength = 40; + + if(password.length() < minPasswordLength){ + throw new ParserException("Password too short! Min length is " + minPasswordLength + " characters."); + } + if(password.length() > maxPasswordLength){ + throw new ParserException("Password too long! Max length is " + maxPasswordLength + " characters."); + } + + Pattern pat = Pattern.compile("[^a-z0-9_-]", Pattern.CASE_INSENSITIVE); + Matcher mat = pat.matcher(password); + boolean result = mat.find(); + if(result){ + throw new ParserException("Forbidden characters used! Only user letters A-Z or numbers 0-9 or symbols '-' or '_' !"); + } + } + + public static void mapNameValid(String mapName) throws ParserException { + int minMapNameLength = 4; + int maxMapNameLength = 30; + + if(mapName.length() < minMapNameLength){ + throw new ParserException("Map-Name too short! Min length is " + minMapNameLength + " characters."); + } + if(mapName.length() > maxMapNameLength){ + throw new ParserException("Map-Name too long! Max length is " + maxMapNameLength + " characters."); + } + + Pattern pat = Pattern.compile("[^a-z0-9_-]", Pattern.CASE_INSENSITIVE); + Matcher mat = pat.matcher(mapName); + boolean result = mat.find(); + if(result){ + throw new ParserException("Forbidden characters used! Only user letters A-Z or numbers 0-9 or symbols '-' or '_' !"); + } + } + + public static void sha1HexHashValid(String mapID) throws ParserException { + int hashLength = 40; + + if(mapID.length() != hashLength){ + throw new ParserException("SHA1 hash length not correct. Must have length of " + hashLength + " characters!"); + } + + Pattern pat = Pattern.compile("[^a-f0-9]"); //maybe make case-insensitive -> letters can be uppercase and still be valid hex number + Matcher mat = pat.matcher(mapID); + boolean result = mat.find(); + if(result){ + throw new ParserException("Forbidden characters used! SHA1 hash only consists out of letters a-f and/or numbers 0-9!"); + } + } + + public static void ipAddressValid(String address) throws ParserException { + + int addressMinLength = 7; + int addressMaxLength = 15; + int addressLength = address.length(); + int octetMinDecValue = 0; + int octetMaxDecValue = 255; + + if(address.equals("localhost")){ + return; + } + + if(addressLength > addressMaxLength){ + throw new ParserException("IP-Address too long. Must have maximum length of " + addressMaxLength + " characters including octet dividers (.) !"); + } + + if(addressLength < addressMinLength){ + throw new ParserException("IP-Address too short. Must have minimum length of " + addressMinLength + " characters including octet dividers (.) !"); + } + + if(address.charAt(0) == '.' | address.charAt(addressLength - 1) == '.'){ + throw new ParserException("IP-Address must not start nor end with octet dividers (.) !"); + } + + int counter = 0; + for(int i = 0; addressLength > i ; i++){ + if(address.charAt(i) == '.'){ + counter++; + } + } + if(counter != 3){ + throw new ParserException("IP-Address must contain exactly 3 octet dividers (.) !"); + } + + for(int i = 0; addressLength > i ; i++){ + if(address.charAt(i) == '.' && address.charAt(i + 1) == '.'){ + throw new ParserException("IP-Address must not contain two or more consecutive dividers (.) without number in between!"); + } + } + + Pattern pat = Pattern.compile("[^0-9.]"); + for(int i = 0; addressLength > i ; i++){ + Matcher mat = pat.matcher(address.substring(i, i+1)); + boolean result = mat.find(); + if(result){ + throw new ParserException("IP address must consist out of numbers 0-9 and separators (.) !"); + } + } + + counter = 0; + int[] positions = new int[4]; + positions[0] = 0; + for(int i = 0; addressLength > i ; i++){ + if(address.charAt(i) == '.'){ + counter++; + positions[counter] = i + 1; + } + } + for(int i = 0; positions.length > i; i++){ + if(positions.length - 1 > i) { + if (Integer.parseInt(address.substring(positions[i], positions[i + 1] - 1)) > octetMaxDecValue) { + throw new ParserException("Octets of IP-address must not exceed 255!"); + } + } + else{ + if (Integer.parseInt(address.substring(positions[i], addressLength)) > octetMaxDecValue) { + throw new ParserException("Octets of IP-address must not exceed 255!"); + } + } + } + } + + public static void mapDataValid(String mapData) throws ParserException { + + //values could be handed to method (Instance of MapData Class) + int actualMapDataLength = mapData.length(); + int mapWidth = 18; //Tiles + int mapHeight = 18; //Tiles + int spacesAmount = (mapHeight * mapWidth) - 1; //space used as separator + int totalTilesAmount = mapHeight * mapWidth; + int borderTilesAmount = (2 * mapWidth) + (2 * (mapHeight - 2)); + int spawnTilesAmount = 4; + int fieldTilesAmount = totalTilesAmount - borderTilesAmount - spawnTilesAmount; + int maxTileNumberDigits = 2; //Tile-Numbers are max 2 digits: 10 to 29 + int minTileNumberDigits = 1; //Tile-Numbers are min 1 digit: 0 to 9 + int minTileNumber = 0; + int maxTileNumber = 29; + int walkableTileMinNumber = 0; + int walkableTileMaxNumber = 9; + int indestructibleTileMinNumber = 10; + int indestructibleTileMaxNumber = 19; + int destructibleTileMinNumber = 20; + int destructibleTileMaxNumber = 29; + int maxMapDataLength = spacesAmount + borderTilesAmount * Integer.toString(indestructibleTileMaxNumber).length() + spawnTilesAmount * Integer.toString(walkableTileMaxNumber).length() + fieldTilesAmount * Integer.toString(destructibleTileMaxNumber).length(); //"Integer.toString(destructibleTileMaxNumber).length()" results in number of digits of destructibleTileMaxNumber + int minMapDataLength = spacesAmount + borderTilesAmount * Integer.toString(indestructibleTileMinNumber).length() + spawnTilesAmount * Integer.toString(walkableTileMinNumber).length() + fieldTilesAmount * Integer.toString(walkableTileMinNumber).length(); + + if(actualMapDataLength > maxMapDataLength){ + throw new ParserException("Map-Data corrupted - mapData String must not exceed length of " + maxMapDataLength + " chars including spaces for " + mapWidth + "x" + mapHeight + " Tiles map!"); + } + + if(actualMapDataLength < minMapDataLength){ + throw new ParserException("Map-Data corrupted - minimum length of mapData String must be " + minMapDataLength + " chars including spaces for " + mapWidth + "x" + mapHeight + " Tiles map!"); + } + + if(mapData.charAt(0) == ' ' | mapData.charAt(actualMapDataLength - 1) == ' '){ + throw new ParserException("Map-Data corrupted - must not start nor end with space!"); + } + + for(int i = 0; actualMapDataLength > i ; i++){ + if(mapData.charAt(i) == ' ' && mapData.charAt(i + 1) == ' '){ + throw new ParserException("Map-Data corrupted - must not contain two or more consecutive spaces without number in between!"); + } + } + + int counter = 0; + for(int i = 0; i < actualMapDataLength; i++){ + if((mapData.charAt(i) == ' ')){ + counter++; + } + } + if(counter != spacesAmount){ + throw new ParserException("Map-Data corrupted - number of spaces must be " + spacesAmount + "!"); + } + + Pattern pat = Pattern.compile("[^0-9 ]"); + for(int i = 0; actualMapDataLength > i ; i++){ + Matcher mat = pat.matcher(mapData.substring(i, i+1)); + boolean result = mat.find(); + if(result){ + throw new ParserException("Map-Data corrupted - must consist out of numbers 0-9 and space as separator!"); + } + } + + counter = 0; + int[] positions = new int[totalTilesAmount]; + positions[0] = 0; + for(int i = 0; actualMapDataLength > i ; i++){ + if(mapData.charAt(i) == ' '){ + counter++; + positions[counter] = i + 1; + } + } + for(int i = 0; positions.length > i; i++){ + if(positions.length - 1 > i) { + if (Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) > maxTileNumber | Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) < minTileNumber) { + throw new ParserException("Map-Data corrupted - Tile number must be between " + minTileNumber + " and " + maxTileNumber + "!"); + } + } + else{ + if (Integer.parseInt(mapData.substring(positions[i], actualMapDataLength)) > maxTileNumber | Integer.parseInt(mapData.substring(positions[i], actualMapDataLength)) < minTileNumber) { + throw new ParserException("Map-Data corrupted - Tile number must be between " + minTileNumber + " and " + maxTileNumber + "!"); + } + } + } + + //Alternative code for checking if tile number is between minTileNumber and maxTileNumber: + + /* + String combinedNumbers = ""; + for(int i = 0; i < actualMapDataLength - 1; i++){ + if(mapData.charAt(i+1) == ' '){ + combinedNumbers = combinedNumbers + mapData.charAt(i); + if((Integer.parseInt(combinedNumbers) > maxTileNumber) | (Integer.parseInt(combinedNumbers) < minTileNumber)){ + throw new ParserException("Map-Data corrupted - Tile number must be between " + minTileNumber + " and " + maxTileNumber + "!"); + } + combinedNumbers = ""; + if(i < actualMapDataLength - 1){ + i++; + } + } + else if(i >= actualMapDataLength - 2){ + combinedNumbers = combinedNumbers + mapData.charAt(i) + mapData.charAt(i+1); + if((Integer.parseInt(combinedNumbers) > maxTileNumber) | (Integer.parseInt(combinedNumbers) < minTileNumber)){ + throw new ParserException("Map-Data corrupted - Tile number must be between " + minTileNumber + " and " + maxTileNumber + "!"); + } + } + else{ + combinedNumbers = combinedNumbers + mapData.charAt(i); + } + } + */ + + //corner Tiles included + for(int i = 0; i < mapWidth; i++){ + if(Integer.parseInt(mapData.substring(positions[i], positions[i+1] - 1)) > indestructibleTileMaxNumber | Integer.parseInt(mapData.substring(positions[i], positions[i+1] - 1)) < indestructibleTileMinNumber){ + throw new ParserException("Map-Data corrupted - Top-Line must be border tiles!"); + } + } + + //corner Tiles included + for(int i = positions.length - mapWidth; i < positions.length; i++){ + if(positions.length - 1 > i) { + if (Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) > indestructibleTileMaxNumber | Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) < indestructibleTileMinNumber) { + throw new ParserException("Map-Data corrupted - Bottom-Line must be border tiles!"); + } + } + else{ + if (Integer.parseInt(mapData.substring(positions[i], actualMapDataLength)) > indestructibleTileMaxNumber | Integer.parseInt(mapData.substring(positions[i], actualMapDataLength)) < indestructibleTileMinNumber) { + throw new ParserException("Map-Data corrupted - Bottom-Line must be border tiles!"); + } + } + } + + //corner Tiles excluded + for(int i = mapWidth; i < positions.length - mapWidth; i = i + mapWidth){ + if(i % mapWidth == 0 && Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) > indestructibleTileMaxNumber | Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) < indestructibleTileMinNumber){ + throw new ParserException("Map-Data corrupted - Left Edge must be border tiles!"); + } + } + + //corner Tiles excluded + for(int i = mapWidth - 1; i < positions.length - mapWidth; i = i + mapWidth){ + if((i + 1) % mapWidth == 0 && Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) > indestructibleTileMaxNumber | Integer.parseInt(mapData.substring(positions[i], positions[i + 1] - 1)) < indestructibleTileMinNumber){ + throw new ParserException("Map-Data corrupted - Right Edge must be border tiles!"); + } + } + + if(Integer.parseInt(mapData.substring(positions[mapWidth + 1], positions[mapWidth + 2] - 1)) < walkableTileMinNumber | Integer.parseInt(mapData.substring(positions[mapWidth + 1], positions[mapWidth + 2] - 1)) > walkableTileMaxNumber){ + throw new ParserException("Map-Data corrupted - Player spawn top left must use walkable tile!"); + } + + if(Integer.parseInt(mapData.substring(positions[(mapWidth*2) - 2], positions[(mapWidth*2) - 1] - 1)) < walkableTileMinNumber | Integer.parseInt(mapData.substring(positions[(mapWidth*2) - 2], positions[(mapWidth*2) - 1] - 1)) > walkableTileMaxNumber){ + throw new ParserException("Map-Data corrupted - Player spawn top right must use walkable tile!"); + } + + if(Integer.parseInt(mapData.substring(positions[positions.length - (mapWidth*2) + 1], positions[positions.length - (mapWidth*2) + 2] - 1)) < walkableTileMinNumber | Integer.parseInt(mapData.substring(positions[positions.length - (mapWidth*2) + 1], positions[positions.length - (mapWidth*2) + 2] - 1)) > walkableTileMaxNumber) { + throw new ParserException("Map-Data corrupted - Player spawn bottom left must use walkable tile!"); + } + + if(Integer.parseInt(mapData.substring(positions[positions.length - mapWidth - 2], positions[positions.length - mapWidth - 1] - 1)) < walkableTileMinNumber | Integer.parseInt(mapData.substring(positions[positions.length - mapWidth - 2], positions[positions.length - mapWidth - 1] - 1)) > walkableTileMaxNumber){ + throw new ParserException("Map-Data corrupted - Player spawn bottom right must use walkable tile!"); + } + } + + public static void playerStatsValid(PlayerStatistics stats) throws ParserException{ + + if(stats.getGamesLost() < 0){ + throw new ParserException("Player statistics data corrupted - Minimum value for lost games is 0!"); + } + + if(stats.getGamesWon() < 0){ + throw new ParserException("Player statistics data corrupted - Minimum value for won games is 0!"); + } + + if(stats.getKills() < 0){ + throw new ParserException("Player statistics data corrupted - Minimum value for kills is 0!"); + } + + if(stats.getDeaths() < 0){ + throw new ParserException("Player statistics data corrupted - Minimum value for deaths is 0!"); + } + + if(stats.getBlocksDestroyed() < 0){ + throw new ParserException("Player statistics data corrupted - Minimum value for destroyed blocks is 0!"); + } + + if(stats.getGameTime() < 0){ + throw new ParserException("Player statistics data corrupted - Minimum value for ingame time is 0 seconds!"); + } + } + + public static void volumeValid(int volume) throws ParserException{ + + if(volume > 100 | volume < 0){ + throw new ParserException("Volume must be between 0 and 100!"); + } + + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_AzureDB.sql b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_AzureDB.sql new file mode 100644 index 0000000000000000000000000000000000000000..bd3b7cc0344912f98142b0a01760952356a327b7 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_AzureDB.sql @@ -0,0 +1,83 @@ +--Note: DDL to be run as admin on MsSQL (AzureDB); +--Backup SQL only for CoreMaps Download + + +DROP TABLE coremaps; +DROP TABLE communitymaps; +DROP TABLE players; + +CREATE TABLE coremaps( + map_id CHAR(40) NOT NULL UNIQUE, --SHA1 hash is 40 chars length in hex + map_name VARCHAR(30) NOT NULL, + map_width INTEGER NOT NULL, + map_height INTEGER NOT NULL, + map_data VARCHAR(1082) NOT NULL UNIQUE); --allows for map size up to 19x19 (when using double digit numbers for tiles) + +CREATE TABLE communitymaps( + map_id CHAR(40) NOT NULL UNIQUE, --SHA1 hash is 40 chars length in hex + map_name VARCHAR(30) NOT NULL, + map_width INTEGER NOT NULL, + map_height INTEGER NOT NULL, + map_data VARCHAR(1082) NOT NULL UNIQUE, --allows for map size up to 19x19 (when using double digit numbers for tiles) + map_downloads INTEGER NOT NULL); + +CREATE TABLE players( + player_name VARCHAR(40) NOT NULL UNIQUE, --Player name is PlayerID + player_pw VARCHAR(40) NOT NULL, + games_won INTEGER NOT NULL, + games_lost INTEGER NOT NULL, + kills INTEGER NOT NULL, + deaths INTEGER NOT NULL, + blocks_destroyed INTEGER NOT NULL, + ingame_time INTEGER NOT NULL); + + +INSERT INTO coremaps (map_id, map_name, map_width, map_height, map_data) +VALUES ('09a02b54d05b5b7ebc29a4383ca12d3dda846b72', + 'Arena1', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12'); + +INSERT INTO coremaps (map_id, map_name, map_width, map_height, map_data) +VALUES ('0ab15557ab6dc4be60dfe6a9b0288bac3036bd97', + 'Arena2', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12'); + +INSERT INTO communitymaps (map_id, map_name, map_width, map_height, map_data, map_downloads) +VALUES ('fbf44184867512faecc195ae75ca55d5ab7bad2d', + 'Arena3', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12', + 0); + +INSERT INTO communitymaps (map_id, map_name, map_width, map_height, map_data, map_downloads) +VALUES ('1c23b362fd666c5fb7ed60ca611b17246424e49f', + 'Arena4', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 4 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12', + 0); + +INSERT INTO players (player_name, player_pw, games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time) +VALUES ('Player1', + '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', --Hash of password "password" + 18, + 0, + 80, + 0, + 140, + 5000); + +INSERT INTO players (player_name, player_pw, games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time) +VALUES ('Player2', + '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', --Hash of password "password" + 15, + 3, + 50, + 5, + 110, + 6000); \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_Oracle.sql b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_Oracle.sql new file mode 100644 index 0000000000000000000000000000000000000000..22de38024bc74b449f2ca80e2afa3cc063aea840 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Scripts/DDL_Script_Oracle.sql @@ -0,0 +1,100 @@ +--Note: DDL to be run as admin on OracleDB; Passwords for user accounts are not included and must be inserted before execution + +DROP TABLE battlearenadata.coremaps; +DROP TABLE battlearenadata.communitymaps; +DROP TABLE battlearenadata.players; + +DROP USER battlearenaplayer; +DROP USER battlearenadata; + +CREATE USER battlearenaplayer IDENTIFIED BY "insertPasswordHere"; +CREATE USER battlearenadata IDENTIFIED BY "insertPasswordHere"; + +GRANT CONNECT TO battlearenaplayer; + +CREATE TABLE battlearenadata.coremaps( + map_id CHAR(40) NOT NULL UNIQUE, --SHA1 hash is 40 chars length in hex + map_name VARCHAR(30) NOT NULL, + map_width INTEGER NOT NULL, + map_height INTEGER NOT NULL, + map_data VARCHAR(1082) NOT NULL UNIQUE); --allows for map size up to 19x19 (when using double digit numbers for tiles) + +CREATE TABLE battlearenadata.communitymaps( + map_id CHAR(40) NOT NULL UNIQUE, --SHA1 hash is 40 chars length in hex + map_name VARCHAR(30) NOT NULL, + map_width INTEGER NOT NULL, + map_height INTEGER NOT NULL, + map_data VARCHAR(1082) NOT NULL UNIQUE, --allows for map size up to 19x19 (when using double digit numbers for tiles) + map_downloads INTEGER NOT NULL); + +CREATE TABLE battlearenadata.players( + player_name VARCHAR(40) NOT NULL UNIQUE, --Player name is PlayerID + player_pw VARCHAR(40) NOT NULL, + games_won INTEGER NOT NULL, + games_lost INTEGER NOT NULL, + kills INTEGER NOT NULL, + deaths INTEGER NOT NULL, + blocks_destroyed INTEGER NOT NULL, + ingame_time INTEGER NOT NULL); + +ALTER USER battlearenadata QUOTA 500M ON coremaps; +ALTER USER battlearenadata QUOTA 500M ON communitymaps; +ALTER USER battlearenadata QUOTA 500M ON players; + +INSERT INTO battlearenadata.coremaps (map_id, map_name, map_width, map_height, map_data) +VALUES ('09a02b54d05b5b7ebc29a4383ca12d3dda846b72', + 'Arena1', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12'); + +INSERT INTO battlearenadata.coremaps (map_id, map_name, map_width, map_height, map_data) +VALUES ('0ab15557ab6dc4be60dfe6a9b0288bac3036bd97', + 'Arena2', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12'); + +INSERT INTO battlearenadata.communitymaps (map_id, map_name, map_width, map_height, map_data, map_downloads) +VALUES ('fbf44184867512faecc195ae75ca55d5ab7bad2d', + 'Arena3', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12', + 0); + +INSERT INTO battlearenadata.communitymaps (map_id, map_name, map_width, map_height, map_data, map_downloads) +VALUES ('1c23b362fd666c5fb7ed60ca611b17246424e49f', + 'Arena4', + 18, + 18, + '12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 4 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12', + 0); + +INSERT INTO battlearenadata.players (player_name, player_pw, games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time) +VALUES ('Player1', + '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', --Hash of password "password" + 18, + 0, + 80, + 0, + 140, + 5000); + +INSERT INTO battlearenadata.players (player_name, player_pw, games_won, games_lost, kills, deaths, blocks_destroyed, ingame_time) +VALUES ('Player2', + '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', --Hash of password "password" + 15, + 3, + 50, + 5, + 110, + 6000); + +GRANT SELECT ON battlearenadata.coremaps TO battlearenaplayer; + +GRANT SELECT, INSERT ON battlearenadata.communitymaps TO battlearenaplayer; + +GRANT SELECT, INSERT, UPDATE ON battlearenadata.players TO battlearenaplayer; + +GRANT UPDATE (map_downloads) ON battlearenadata.communitymaps TO battlearenaplayer; \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/CollisionHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/CollisionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..9d860c1af101e6002e51c846e70d219cee7772e1 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/CollisionHandler.java @@ -0,0 +1,69 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +import de.hdm_stuttgart.battlearena.Controller.GameSceneController; +import de.hdm_stuttgart.battlearena.Model.Map.ITile; + +import javafx.geometry.BoundingBox; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class CollisionHandler { + + private static final Logger log = LogManager.getLogger(CollisionHandler.class); + + public CollisionHandler() { + log.debug("CollisionHandler initialized"); + } + + public boolean handleBoxCollision(BoundingBox colliderA, BoundingBox colliderB) { + return colliderA.getMaxX() > colliderB.getMinX() && + colliderA.getMinX() < colliderB.getMaxX() && + colliderA.getMaxY() > colliderB.getMinY() && + colliderA.getMinY() < colliderB.getMaxY(); + } + + public boolean handleMapCollision(IEntity entity, int scaledTileSize, GameSceneController gameSceneController) { + int playerLeftX = (int) (entity.getBoxCollider().getMinX()); + int playerRightX = (int) (entity.getBoxCollider().getMinX() + entity.getBoxCollider().getWidth()); + int playerTopY = (int) (entity.getBoxCollider().getMinY()); + int playerBottomY = (int) (entity.getBoxCollider().getMinY() + entity.getBoxCollider().getHeight()); + + int leftColumn = playerLeftX / scaledTileSize; + int rightColumn = playerRightX / scaledTileSize; + int topRow = playerTopY / scaledTileSize; + int bottomRow = playerBottomY / scaledTileSize; + + int nextPlayerTop = (playerTopY - entity.getEntitySpeed()) / scaledTileSize; + int nextPlayerBottom = (playerBottomY + entity.getEntitySpeed()) / scaledTileSize; + int nextPlayerLeft = (playerLeftX - entity.getEntitySpeed()) / scaledTileSize; + int nextPlayerRight = (playerRightX + entity.getEntitySpeed()) / scaledTileSize; + + int[][] tileMap = gameSceneController.getTileManager().getTileMap(); + ITile[] tileSet = gameSceneController.getTileManager().getTileSet(); + int tileOne; + int tileTwo; + + switch (entity.getEntityDirection()) { + case UP: + tileOne = tileMap[nextPlayerTop][leftColumn]; + tileTwo = tileMap[nextPlayerTop][rightColumn]; + return tileSet[tileOne].getCollision() || tileSet[tileTwo].getCollision(); + case DOWN: + tileOne = tileMap[nextPlayerBottom][leftColumn]; + tileTwo = tileMap[nextPlayerBottom][rightColumn]; + return tileSet[tileOne].getCollision() || tileSet[tileTwo].getCollision(); + case LEFT: + tileOne = tileMap[topRow][nextPlayerLeft]; + tileTwo = tileMap[bottomRow][nextPlayerLeft]; + return tileSet[tileOne].getCollision() || tileSet[tileTwo].getCollision(); + case RIGHT: + tileOne = tileMap[topRow][nextPlayerRight]; + tileTwo = tileMap[bottomRow][nextPlayerRight]; + return tileSet[tileOne].getCollision() || tileSet[tileTwo].getCollision(); + default: + return true; + } + } + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java deleted file mode 100644 index ea46bb6f0ff8235e038455fde192db494e789f94..0000000000000000000000000000000000000000 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package de.hdm_stuttgart.battlearena.Model.Entity; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -public class EnemyHandler { - - private static final Logger log = LogManager.getLogger(EnemyHandler.class); - -} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java new file mode 100644 index 0000000000000000000000000000000000000000..03b800acd74ad72318dee1df4dbf6528c53bf6d6 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +public enum EntityClass { + HUMAN, + HIGH_BORN, + LOW_BORN, + SENTINELS +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityDirection.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityDirection.java new file mode 100644 index 0000000000000000000000000000000000000000..c86d3e0e25d51cf090cede9ef3a3167745be7d0a --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityDirection.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +public enum EntityDirection { + UP, + DOWN, + LEFT, + RIGHT +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..2e49bcaca57667a7fbea0431ff0fe8c91b356ac5 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java @@ -0,0 +1,29 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +import de.hdm_stuttgart.battlearena.Controller.Enum.PlayerMode; +import de.hdm_stuttgart.battlearena.Controller.GameSceneController; +import de.hdm_stuttgart.battlearena.Model.Inputs.InputHandler; + +import javafx.scene.canvas.GraphicsContext; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class EntityFactory { + + private static final Logger log = LogManager.getLogger(EntityFactory.class); + + public static IEntity createEntity(EntityType entityType, GraphicsContext gameScene, InputHandler inputHandler, + EntityClass entityClass, GameSceneController gameSceneController, PlayerMode playerMode) { + if (entityType == EntityType.PLAYER) { + log.debug("Entity " + entityType + " created"); + return new Player(gameScene, inputHandler, entityClass, gameSceneController, playerMode); + } else if (entityType == EntityType.NETWORK_PLAYER_TWO) { + log.debug("Entity " + entityType + " created"); + return new NetworkPlayerTwo(); + } + + throw new IllegalArgumentException ("Entity type not supported " + entityType); + } + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityType.java new file mode 100644 index 0000000000000000000000000000000000000000..108c4c2037dbcb53d090dc19a59b9b79450d6b68 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityType.java @@ -0,0 +1,7 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +public enum EntityType { + PLAYER, + NETWORK_PLAYER_TWO, + LOKAL_PLAYER_TWO +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java index fd7bbc62dab3dc4952f7a50958d25bb42cf95b5a..f98ddeb7452f60866c2dfe661dff29162c0004b7 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java @@ -1,4 +1,37 @@ package de.hdm_stuttgart.battlearena.Model.Entity; +import de.hdm_stuttgart.battlearena.Controller.GameSceneController; +import javafx.geometry.BoundingBox; +import javafx.scene.canvas.GraphicsContext; + public interface IEntity { -} + + void initializeEntity(); + + void loadEntitySprites(); + + void updateEntityMovement(GameSceneController gameScene); + + void checkHealTile(IEntity entity, GraphicsContext graphicsContext); + + void attack(IEntity entity, GraphicsContext graphicsContext); + + void updateEntityWalkAnimation(); + + void renderEntity(GraphicsContext graphicsContext); + + void healPlayer(int heal); + + BoundingBox getBoxCollider(); + + EntityDirection getEntityDirection(); + + int getEntitySpeed(); + + void gotHit(int damageDone); + + int getMapPosX(); + + int getMapPosY(); + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/NetworkPlayerTwo.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/NetworkPlayerTwo.java new file mode 100644 index 0000000000000000000000000000000000000000..d045a108bf051f2e40573e084199808f2edbc630 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/NetworkPlayerTwo.java @@ -0,0 +1,97 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +import de.hdm_stuttgart.battlearena.Controller.GameSceneController; + +import javafx.geometry.BoundingBox; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +class NetworkPlayerTwo implements IEntity{ + + private static final Logger log = LogManager.getLogger(NetworkPlayerTwo.class); + + private final BoundingBox boxCollider = new BoundingBox(300, 200, 48, 48); + + private EntityDirection entityDirection = EntityDirection.DOWN; + + private int entitySpeed = 3; + + private int health = 10; + + @Override + public void initializeEntity() { + + } + + @Override + public void loadEntitySprites() { + + } + + @Override + public void updateEntityMovement(GameSceneController gameScene) { + + } + + @Override + public void checkHealTile(IEntity entity, GraphicsContext graphicsContext) { + + } + + @Override + public void attack(IEntity entity, GraphicsContext graphicsContext) { + + } + + @Override + public void updateEntityWalkAnimation() { + + } + + @Override + public void renderEntity(GraphicsContext graphicsContext) { + graphicsContext.setFill(Color.BLACK); + graphicsContext.fillRect(300, 200, 48, 48); + } + + @Override + public void healPlayer(int heal) { + log.info("Network player health: " + health); + health -= heal; + } + + @Override + public BoundingBox getBoxCollider() { + return boxCollider; + } + + @Override + public EntityDirection getEntityDirection() { + return entityDirection; + } + + @Override + public int getEntitySpeed() { + return 3; + } + + @Override + public void gotHit(int damageDone) { + log.debug("Network player health: " + health); + health -= damageDone; + } + + @Override + public int getMapPosX() { + return 0; + } + + @Override + public int getMapPosY() { + return 0; + } + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java index 0384286b6f19eb3b2cd302cd23687b741eef2722..0eaf4b2ca5c23f540e284e5ef6e80bf1be36037f 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java @@ -1,10 +1,478 @@ package de.hdm_stuttgart.battlearena.Model.Entity; +import de.hdm_stuttgart.battlearena.Controller.Enum.PlayerMode; +import de.hdm_stuttgart.battlearena.Controller.GameSceneController; +import de.hdm_stuttgart.battlearena.Model.Inputs.InputHandler; + +import de.hdm_stuttgart.battlearena.Model.Map.TileManager; +import javafx.geometry.BoundingBox; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.Image; + import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -public class Player implements IEntity { +import java.util.Objects; + +class Player implements IEntity { private static final Logger log = LogManager.getLogger(Player.class); -} + private final PlayerMode PLAYER_MODE; + + InputHandler inputHandler; + CollisionHandler collisionHandler = new CollisionHandler(); + + GraphicsContext gameScene; + + GameSceneController gameSceneController; + + private BoundingBox boxCollider; + + private Image directionDownOne, + directionDownTwo, + directionUpOne, + directionUpTwo, + directionLeftOne, + directionLeftTwo, + directionRightOne, + directionRightTwo; + + private Image swordDown, + swordUp, + swordLeft, + swordRight; + + private final EntityClass entityClass; + + private int spriteCounter = 0; + private int spriteNumber = 1; + + private final int playerWidth = 19; + private final int playerHeight = 35; + + private int scaledTileSize; + + private int mapPosX; + private int mapPosY; + + private int lastMapPosX; + private int lastMapPosY; + + private int playerSpeed; + private EntityDirection playerDirection; + + private int health; + private int maxPlayerHealth; + private int damage; + + public Player(GraphicsContext gameScene, InputHandler inputHandler, EntityClass entityClass, + GameSceneController gameSceneController, PlayerMode PLAYER_MODE) { + this.gameScene = gameScene; + this.inputHandler = inputHandler; + this.entityClass = entityClass; + this.gameSceneController = gameSceneController; + this.PLAYER_MODE = PLAYER_MODE; + + initializeEntity(); + loadEntitySprites(); + } + + @Override + public void initializeEntity() { + scaledTileSize = gameSceneController.getScaledTileSize(); + if (PLAYER_MODE == PlayerMode.PLAYER_ONE) { + mapPosX = 60; + mapPosY = 60; + } else if (PLAYER_MODE == PlayerMode.PLAYER_TWO) { + mapPosX = 760; + mapPosY = 735; + } + + initializePlayerStats(); + + boxCollider = new BoundingBox(mapPosX + 15, mapPosY + 10, playerWidth, playerHeight); + playerDirection = EntityDirection.DOWN; + } + + //Values result from balancing + private void initializePlayerStats() { + if (entityClass == EntityClass.HUMAN) { + maxPlayerHealth = 50; + health = 50; + damage = 5; + playerSpeed = 5; + } else if (entityClass == EntityClass.HIGH_BORN) { + maxPlayerHealth = 100; + health = 75; + damage = 2; + playerSpeed = 3; + } else if (entityClass == EntityClass.LOW_BORN) { + maxPlayerHealth = 10; + health = 10; + damage = 10; + playerSpeed = 7; + } else { + maxPlayerHealth = 40; + health = 15; + damage = 7; + playerSpeed = 5; + } + } + + @Override + public void loadEntitySprites() { + try { + if (entityClass == EntityClass.HUMAN) { + loadHumanSprites(); + loadWeaponSprites(); + } else if (entityClass == EntityClass.HIGH_BORN) { + loadHighBornSprites(); + loadWeaponSprites(); + } else if (entityClass == EntityClass.LOW_BORN) { + loadLowBornSprites(); + loadWeaponSprites(); + } else { + loadSentinelsSprites(); + loadWeaponSprites(); + } + } catch (Exception e) { + log.error(e); + } + } + + private void loadHumanSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanDown00.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanDown01.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanUp00.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanUp01.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanLeft00.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanLeft01.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanRight00.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/human/HumanRight01.png"))); + } + + private void loadHighBornSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/high_born/HighBornDown00.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/high_born/HighBornDown01.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadLowBornSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown01.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadSentinelsSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/sentinels/SentinelDown00.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/sentinels/SentinelDown01.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadWeaponSprites() { + swordUp = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordUp.png"))); + swordDown = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordDown.png"))); + swordLeft = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordLeft.png"))); + swordRight = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordRight.png"))); + } + + @Override + public void updateEntityMovement(GameSceneController gameScene) { + if (PLAYER_MODE == PlayerMode.PLAYER_ONE) { + if (inputHandler.isMoveUp() || inputHandler.isMoveDown() || inputHandler.isMoveLeft() || inputHandler.isMoveRight()) { + if (inputHandler.isMoveUp()) { + playerDirection = EntityDirection.UP; + } else if (inputHandler.isMoveDown()) { + playerDirection = EntityDirection.DOWN; + } else if (inputHandler.isMoveLeft()) { + playerDirection = EntityDirection.LEFT; + } else if (inputHandler.isMoveRight()) { + playerDirection = EntityDirection.RIGHT; + } + + boolean isWalkableTile = collisionHandler.handleMapCollision(this, scaledTileSize, gameSceneController); + + performEntityMovement(isWalkableTile); + + boolean isEntityCollision = boxCollider.intersects(gameScene.getEnemy().getBoxCollider()); + //boolean isEntityCollision = collisionHandler.handleBoxCollision(boxCollider, gameScene.getEnemy().getBoxCollider()); + + performEntityCollision(isEntityCollision); + + updateEntityWalkAnimation(); + } + } else if (PLAYER_MODE == PlayerMode.PLAYER_TWO) { + if (inputHandler.isSdMoveUp() || inputHandler.isSdMoveDown() || inputHandler.isSdMoveLeft() || inputHandler.isSdMoveRight()) { + if (inputHandler.isSdMoveUp()) { + playerDirection = EntityDirection.UP; + } else if (inputHandler.isSdMoveDown()) { + playerDirection = EntityDirection.DOWN; + } else if (inputHandler.isSdMoveLeft()) { + playerDirection = EntityDirection.LEFT; + } else if (inputHandler.isSdMoveRight()) { + playerDirection = EntityDirection.RIGHT; + } + + boolean isWalkableTile = collisionHandler.handleMapCollision(this, scaledTileSize, gameSceneController); + + performEntityMovement(isWalkableTile); + + boolean isEntityCollision = boxCollider.intersects(gameScene.getPlayer().getBoxCollider()); + //boolean isEntityCollision = collisionHandler.handleBoxCollision(boxCollider, gameScene.getEnemy().getBoxCollider()); + + performEntityCollision(isEntityCollision); + + updateEntityWalkAnimation(); + } + } + } + + private void performEntityMovement(boolean isWalkableTile) { + lastMapPosX = mapPosX; + lastMapPosY = mapPosY; + + if (isWalkableTile) { + switch (playerDirection) { + case UP: + mapPosY -= playerSpeed; + break; + case DOWN: + mapPosY += playerSpeed; + break; + case LEFT: + mapPosX -= playerSpeed; + break; + case RIGHT: + mapPosX += playerSpeed; + } + } + } + + private void performEntityCollision(boolean isEntityCollision) { + if (isEntityCollision) { + if (playerDirection == EntityDirection.UP) { + mapPosY = lastMapPosY + 30; + } else if (playerDirection == EntityDirection.DOWN) { + mapPosY = lastMapPosY - 30; + } else if (playerDirection == EntityDirection.LEFT) { + mapPosX = lastMapPosX + 30; + } else { + mapPosX = lastMapPosX - 30; + } + } + + boxCollider = new BoundingBox(mapPosX + 15, mapPosY + 10, playerWidth, playerHeight); + } + @Override + public void checkHealTile(IEntity entity, GraphicsContext graphicsContext){ + int xTile = entity.getMapPosX() / gameSceneController.getScaledTileSize(); + int yTile = entity.getMapPosY() / gameSceneController.getScaledTileSize(); + if(TileManager.tileMap[yTile][xTile +1 ] == 5){ + entity.healPlayer(1); + TileManager.tileMap[yTile][xTile +1] = 2; + log.info("Healed +1: " + health); + } + } + + @Override + public void attack(IEntity entity, GraphicsContext graphicsContext) { + BoundingBox hitBox; + + int xTile = mapPosX / gameSceneController.getScaledTileSize(); + int yTile = mapPosY / gameSceneController.getScaledTileSize(); + //log.info(xTile); + //log.info(yTile); + //int xTile = (int) (Math.random() * (18 - 1)); //Get xTile Coordinate +1 /-1 of playerTile + //int yTile = (int) (Math.random() * (18 - 1)); //Get yTile Coordinate +1 /-1 of playerTile + double dropChance = 0.5; + double randomDropChance = Math.random() * 1; + //log.info(randomDropChance); + + //Added and subtracted numbers from variables are the pixel insets of the player sprite + + int attackRange = 30; + int attackWidth = 10; + + if (inputHandler.isAttack() && PLAYER_MODE == PlayerMode.PLAYER_ONE || + inputHandler.isSdAttack() && PLAYER_MODE == PlayerMode.PLAYER_TWO) { + if (playerDirection == EntityDirection.UP) { + hitBox = new BoundingBox(mapPosX + playerWidth, mapPosY - 10, attackWidth, attackRange); + graphicsContext.strokeRect(mapPosX + playerWidth, mapPosY - 10, attackWidth, attackRange); + graphicsContext.drawImage(swordUp, mapPosX + 8, mapPosY - 10, 32, 32); + if (hitBox.intersects(entity.getBoxCollider())) { + entity.gotHit(damage); + graphicsContext.strokeText("Hit", 10, 10); + + if (((TileManager.tileMap[xTile][yTile] == 3) && randomDropChance > dropChance)|| + ((TileManager.tileMap[xTile][yTile] == 1) && randomDropChance > dropChance)) + TileManager.tileMap[yTile-1][xTile+1] = 5; + //TileManager.tileMap[yTile-2][xTile] = 5; + //TileManager.tileMap[yTile-3][xTile] = 5; + } + } else if (playerDirection == EntityDirection.DOWN) { + hitBox = new BoundingBox(mapPosX + playerWidth, mapPosY + playerHeight, attackWidth, attackRange); + graphicsContext.strokeRect(mapPosX + playerWidth, mapPosY + playerHeight, attackWidth, attackRange); + graphicsContext.drawImage(swordDown, mapPosX + 8, mapPosY + playerHeight, 32, 32); + if (hitBox.intersects(entity.getBoxCollider())) { + entity.gotHit(damage); + graphicsContext.strokeText("Hit", 10, 10); + + if (((TileManager.tileMap[xTile][yTile] == 3) && randomDropChance > dropChance)|| + ((TileManager.tileMap[xTile][yTile] == 1) && randomDropChance > dropChance)) + TileManager.tileMap[yTile-1][xTile+1] = 5; + //TileManager.tileMap[yTile-2][xTile] = 5; + //TileManager.tileMap[yTile-3][xTile] = 5; + } + } else if (playerDirection == EntityDirection.LEFT) { + hitBox = new BoundingBox(mapPosX - attackWidth, mapPosY + ((double) playerHeight / 2), + attackRange, attackWidth); + graphicsContext.strokeRect(mapPosX - attackWidth, mapPosY + ((double) playerHeight / 2), + attackRange, attackWidth); + graphicsContext.drawImage(swordLeft, mapPosX - 8, mapPosY + 8, 32, 32); + if (hitBox.intersects(entity.getBoxCollider())) { + entity.gotHit(damage); + graphicsContext.strokeText("Hit", 10, 10); + + if (((TileManager.tileMap[xTile][yTile] == 3) && randomDropChance > dropChance)|| + ((TileManager.tileMap[xTile][yTile] == 1) && randomDropChance > dropChance)) + TileManager.tileMap[yTile-1][xTile+1] = 5; + //TileManager.tileMap[yTile-2][xTile] = 5; + //TileManager.tileMap[yTile-3][xTile] = 5; + } + } else { + hitBox = new BoundingBox(mapPosX + playerWidth + attackWidth, mapPosY + ((double) playerHeight / 2), + attackRange, attackWidth); + graphicsContext.strokeRect(mapPosX + playerWidth + attackWidth, mapPosY + ((double) playerHeight / 2), + attackRange, attackWidth); + graphicsContext.drawImage(swordRight, mapPosX + playerWidth + 8, mapPosY + 8, 32, 32); + if (hitBox.intersects(entity.getBoxCollider())) { + entity.gotHit(damage); + graphicsContext.strokeText("Hit", 10, 10); + + if (((TileManager.tileMap[xTile][yTile] == 3) && randomDropChance > dropChance)|| + ((TileManager.tileMap[xTile][yTile] == 1) && randomDropChance > dropChance)) + TileManager.tileMap[yTile-1][xTile+1] = 5; + //TileManager.tileMap[yTile-2][xTile] = 5; + //TileManager.tileMap[yTile-3][xTile] = 5; + } + } + } + } + + @Override + public void updateEntityWalkAnimation() { + spriteCounter++; + + if (spriteCounter > 10) { + if (spriteNumber == 1) { + spriteNumber = 2; + } else if (spriteNumber == 2) { + spriteNumber = 1; + } + spriteCounter = 0; + } + } + + @Override + public void renderEntity(GraphicsContext graphicsContext) { + Image playerSprite = null; + + //for debugging collision + graphicsContext.strokeRect(mapPosX + 15, mapPosY + 10, playerWidth, playerHeight); + + switch (playerDirection) { + case UP: + if (spriteNumber == 1) { + playerSprite = directionUpOne; + } + if (spriteNumber == 2) { + playerSprite = directionUpTwo; + } + break; + case DOWN: + if (spriteNumber == 1) { + playerSprite = directionDownOne; + } + if (spriteNumber == 2) { + playerSprite = directionDownTwo; + } + break; + case LEFT: + if (spriteNumber == 1) { + playerSprite = directionLeftOne; + } + if (spriteNumber == 2) { + playerSprite = directionLeftTwo; + } + break; + case RIGHT: + if (spriteNumber == 1) { + playerSprite = directionRightOne; + } + if (spriteNumber == 2) { + playerSprite = directionRightTwo; + } + break; + } + + graphicsContext.drawImage(playerSprite, mapPosX, mapPosY, 48, 48); + } + + @Override + public void gotHit(int damageDone) { + health -= damageDone; + } + @Override + public void healPlayer(int healthRegenerated) { + int regeneratedHealth = health + healthRegenerated; + + if (regeneratedHealth < maxPlayerHealth) { + health += healthRegenerated; + } else { + health = maxPlayerHealth; + } + log.info(health); + } + + @Override + public BoundingBox getBoxCollider() { + return boxCollider; + } + + @Override + public EntityDirection getEntityDirection() { + return playerDirection; + } + + @Override + public int getEntitySpeed() { + return playerSpeed; + } + + @Override + public int getMapPosX() { + return mapPosX; + } + + @Override + public int getMapPosY() { + return mapPosY; + } + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Inputs/InputHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Inputs/InputHandler.java index 5772a4785203b4a51e58738825772f37c11816b3..a66f47e852aac620010f786bbff62a0700292535 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Inputs/InputHandler.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Inputs/InputHandler.java @@ -1,5 +1,8 @@ package de.hdm_stuttgart.battlearena.Model.Inputs; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; + import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; @@ -7,4 +10,136 @@ public class InputHandler { private static final Logger log = LogManager.getLogger(InputHandler.class); -} + private static final InputHandler inputHandler = new InputHandler(); + + private InputHandler(){} + + public static InputHandler getInstance() { + return inputHandler; + } + + //Local Player/Player one controls + private boolean moveUp, moveDown, moveLeft, moveRight, attack; + + //Local player two controls + private boolean sdMoveUp, sdMoveDown, sdMoveLeft, sdMoveRight, sdAttack; + + public void handleKeyPress(KeyEvent event) { + KeyCode code = event.getCode(); + + switch (code) { + case W: + moveUp = true; + log.debug("Player move up"); + break; + case S: + moveDown = true; + log.debug("Player move down"); + break; + case A: + moveLeft = true; + log.debug("Player move left"); + break; + case D: + moveRight = true; + log.debug("Player move right"); + break; + case E: + attack = true; + log.debug("Player attack"); + break; + case UP: + sdMoveUp = true; + break; + case DOWN: + sdMoveDown = true; + break; + case LEFT: + sdMoveLeft = true; + break; + case RIGHT: + sdMoveRight = true; + break; + case MINUS: + sdAttack = true; + break; + } + } + + public void handleKeyRelease(KeyEvent event) { + KeyCode code = event.getCode(); + + switch (code) { + case W: + moveUp = false; + break; + case S: + moveDown = false; + break; + case A: + moveLeft = false; + break; + case D: + moveRight = false; + break; + case E: + attack = false; + break; + case UP: + sdMoveUp = false; + break; + case DOWN: + sdMoveDown = false; + break; + case LEFT: + sdMoveLeft = false; + break; + case RIGHT: + sdMoveRight = false; + break; + case MINUS: + sdAttack = false; + break; + } + } + + public boolean isMoveUp() { + return moveUp; + } + + public boolean isMoveDown() { + return moveDown; + } + + public boolean isMoveLeft() { + return moveLeft; + } + + public boolean isMoveRight() { + return moveRight; + } + + public boolean isAttack() { + return attack; + } + + public boolean isSdMoveUp() { + return sdMoveUp; + } + + public boolean isSdMoveDown() { + return sdMoveDown; + } + + public boolean isSdMoveLeft() { + return sdMoveLeft; + } + + public boolean isSdMoveRight() { + return sdMoveRight; + } + + public boolean isSdAttack() { + return sdAttack; + } +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/BackgroundTile.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/BackgroundTile.java index 0a702580fe7a00095752ce2f6141f25caa8a0344..b17fb79d9742336e3d008bce528846433d1db394 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/BackgroundTile.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/BackgroundTile.java @@ -1,10 +1,37 @@ package de.hdm_stuttgart.battlearena.Model.Map; +import javafx.scene.image.Image; + import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -public class BackgroundTile implements ITile{ +class BackgroundTile implements ITile{ private static final Logger log = LogManager.getLogger(BackgroundTile.class); -} + private final Image tileSprite; + private final boolean isWalkable, isDestructible; + + public BackgroundTile(Image tileSprite, boolean isWalkable, boolean isDestructible) { + this.tileSprite = tileSprite; + this.isWalkable = isWalkable; + this.isDestructible = isDestructible; + } + + @Override + public boolean getCollision() { + log.debug("Collision type: " + isWalkable + " returned."); + return isWalkable; + } + @Override + public boolean getDestruction() { + log.debug("Collision type: " + isDestructible + " returned."); + return isWalkable; + } + + @Override + public Image getTileSprite() { + log.debug("Image returned"); + return tileSprite; + } +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/ITile.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/ITile.java index 4364ed78f3face5dcca4f183e62c11b13e43a9fd..58f711083e43f6be1046bd4d394adf7a3b6e8825 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/ITile.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/ITile.java @@ -1,4 +1,9 @@ package de.hdm_stuttgart.battlearena.Model.Map; +import javafx.scene.image.Image; + public interface ITile { -} + boolean getCollision(); + boolean getDestruction(); + Image getTileSprite(); +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactorie.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactorie.java deleted file mode 100644 index 8409dac4ecfd80fb60f0d9fad2337efbfad775af..0000000000000000000000000000000000000000 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactorie.java +++ /dev/null @@ -1,10 +0,0 @@ -package de.hdm_stuttgart.battlearena.Model.Map; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -public class TileFactorie { - - private static final Logger log = LogManager.getLogger(TileFactorie.class); - -} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactory.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0da1a1558d0e6888a73fa456d3dd81f021d936fc --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactory.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Model.Map; + +import javafx.scene.image.Image; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class TileFactory { + + private static final Logger log = LogManager.getLogger(TileFactory.class); + + public static ITile createTile(TileType tileType, TileType tileType2, Image tileSprite) { + if (tileType == TileType.WALKABLE && tileType2 == TileType.DESTRUCTIBLE) { + log.info("Tile with type: " + tileType + " " + tileType2 + " created."); + return new BackgroundTile(tileSprite, true, true); + }else if (tileType == TileType.WALKABLE && tileType2 == TileType.NON_DESTRUCTIBLE) { + log.info("Tile with type: " + tileType + " " + tileType2 +" created."); + return new BackgroundTile(tileSprite, true, false); + }else if (tileType == TileType.NON_WALKABLE && tileType2 == TileType.DESTRUCTIBLE) { + log.info("Tile with type: " + tileType + " " + tileType2 +" created."); + return new BackgroundTile(tileSprite, false, true); + }else if (tileType == TileType.NON_WALKABLE && tileType2 == TileType.NON_DESTRUCTIBLE) { + log.info("Tile with type: " + tileType + " " + tileType2 +" created."); + return new BackgroundTile(tileSprite, false, false); + } + + log.error("TileType: " + tileType + " not supported!"); + throw new IllegalArgumentException("TileType: " + tileType + " not supported!"); + } + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileManager.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileManager.java index c57a773e4dec2aeb5b0b7da0adfeedb0b6d537e2..0ac687dab223e1933fe99bbf42db3dfd3ed8b8b5 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileManager.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileManager.java @@ -1,10 +1,93 @@ package de.hdm_stuttgart.battlearena.Model.Map; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.image.Image; + import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import java.util.Objects; + public class TileManager { private static final Logger log = LogManager.getLogger(TileManager.class); -} + private final GraphicsContext graphicsContext2D; + private final ITile[] tileSet; + public static int[][] tileMap; + + private final int horizontalTileCount; + private final int verticalTileCount; + + public TileManager(GraphicsContext graphicsContext2D, int diffTileCount, + int horizontalTileCount, int verticalTileCount, String mapString) { + this.graphicsContext2D = graphicsContext2D; + this.horizontalTileCount = horizontalTileCount; + this.verticalTileCount = verticalTileCount; + + tileSet = new BackgroundTile[diffTileCount]; + tileMap = new int[horizontalTileCount][verticalTileCount]; + + createTiles(); + generateMap(mapString, horizontalTileCount, verticalTileCount); + } + + private void createTiles() { + try { + tileSet[0] = TileFactory.createTile(TileType.WALKABLE, TileType.NON_DESTRUCTIBLE, + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/map/Grass01.png")))); + tileSet[1] = TileFactory.createTile(TileType.WALKABLE, TileType.NON_DESTRUCTIBLE, + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/map/Grass02.png")))); + tileSet[2] = TileFactory.createTile(TileType.WALKABLE, TileType.NON_DESTRUCTIBLE, + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/map/Grass04.png")))); + tileSet[3] = TileFactory.createTile(TileType.NON_WALKABLE, TileType.DESTRUCTIBLE, + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/map/Stone01.png")))); + tileSet[4] = TileFactory.createTile(TileType.NON_WALKABLE, TileType.DESTRUCTIBLE, + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/map/Stone02.png")))); + tileSet[5] = TileFactory.createTile(TileType.WALKABLE,TileType.NON_DESTRUCTIBLE, + new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/map/finalheart.png")))); + } catch (Exception e) { + log.error(e); + } + } + + private void generateMap(String mapString, int horizontalTileCount, int verticalTileCount) { + String[] tileSet = mapString.split(" "); + + int stringIndex = 0; + + for (int column = 0; column < horizontalTileCount; column++) { + for (int row = 0; row < verticalTileCount; row++) { + tileMap[column][row] = Integer.parseInt(tileSet[stringIndex]); + stringIndex++; + } + } + } + + public void renderMap() { + int currentTile; + int scaledTileSize = 48; //todo: later replace "48" with value from gameScene. + int tilePosX; + int tilePosY; + + for (int mapColumn = 0; mapColumn < horizontalTileCount; mapColumn++) { + for (int mapRow = 0; mapRow < verticalTileCount; mapRow++) { + currentTile = tileMap[mapRow][mapColumn]; + + tilePosX = mapColumn * scaledTileSize; + tilePosY = mapRow * scaledTileSize; + + graphicsContext2D.drawImage(tileSet[currentTile].getTileSprite(), tilePosX, tilePosY, + scaledTileSize, scaledTileSize); + } + } + } + + public int[][] getTileMap() { + return tileMap; + } + + public ITile[] getTileSet() { + return tileSet; + } +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileType.java new file mode 100644 index 0000000000000000000000000000000000000000..efe35788d26be5839df9efee6934ce54ec2c0d63 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileType.java @@ -0,0 +1,9 @@ +package de.hdm_stuttgart.battlearena.Model.Map; + +public enum TileType { + WALKABLE, + NON_WALKABLE, + DESTRUCTIBLE, + NON_DESTRUCTIBLE + +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java new file mode 100644 index 0000000000000000000000000000000000000000..23b1c65ccd218152576cc9c7d366e68c65d1c591 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java @@ -0,0 +1,49 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.*; +import java.io.*; +import java.util.Arrays; + +public class Client { + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + private static final Logger log = LogManager.getLogger(Client.class); + + public void startConnection(String ip, int port) throws IOException { + clientSocket = new Socket(ip, port); + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + } + + public int[] sendcords(int[] cords) throws IOException { + String message = String.join(",", Arrays.stream(cords).mapToObj(String::valueOf).toArray(String[]::new)); + out.println(message); + // log.info("Sent coordinates: " + message); + String resp = in.readLine(); + return convertStringToArray(resp); + } + + public static int[] convertStringToArray(String inputString) { + // Remove brackets and split by comma + String[] parts = inputString.substring(1, inputString.length() - 1).split(","); + + // Convert each part to integer + int[] result = new int[parts.length]; + for (int i = 0; i < parts.length; i++) { + result[i] = Integer.parseInt(parts[i].trim()); + } + + return result; + } + + public void stopConnection() throws IOException { + in.close(); + out.close(); + clientSocket.close(); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java index 46f156fc3c49ee8bcd85faf981b21d939ff8794f..b47419daa11eea14e292ecab5dac7e0ae483f2b6 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/ConnectionHandler.java @@ -1,21 +1,92 @@ package de.hdm_stuttgart.battlearena.Model.Multiplayer; -import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -public class ConnectionHandler { +import java.io.IOException; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; - private int playerX; - private int playerY; +public class ConnectionHandler { + private static int pX = 0; + private static int pY = 0; + private static int enemyX = 0; + private static int enemyY = 0; + private static int playerID = 0; + private static int[] coordinates = {pX,pY,playerID}; + private static String ipaddress = "localhost"; private static final Logger log = LogManager.getLogger(ConnectionHandler.class); - public int getPlayerX() { - return playerX; + public void startHandler() throws IOException, InterruptedException { + + Client client = new Client(); + client.startConnection(ipaddress, 4444); + + ConnectionThread connectionthread = new ConnectionThread(client); + connectionthread.start(); + } - public int getPlayerY() { - return playerY; + private static class ConnectionThread extends Thread { + private final Client client; + + public ConnectionThread(Client client) { + this.client = client; + } + + public void run() { + try { + while (!Thread.interrupted()) { + int[] cords = client.sendcords(coordinates); + enemyX = cords[0]; + enemyY = cords[1]; + // System.out.println("Enemy X: " + enemyX); + // System.out.println("Enemy Y: " + enemyY); + // System.out.println("Your PlayerID is " + cords[2]); + playerID = cords[2]; + // Assign the Values to the message to send: + coordinates[0] = pX; + coordinates[1] = pY; + coordinates[2] = playerID; + + Thread.sleep(16); + } + } catch (InterruptedException | IOException e) { + e.printStackTrace(); // Handle the exception as needed + } + } } + public int getPlayerID() { + return playerID; + } + + public int getpX() { + return pX; + } + + public void setpX(int pX) { + this.pX = pX; + } + + public int getpY() { + return pY; + } + + public void setpY(int pY) { + this.pY = pY; + } + + public int getEnemyX() { + return enemyX; + } + public int getEnemyY() { + return enemyY; + } + + public static void setIpaddress(String ipaddress) { + ConnectionHandler.ipaddress = ipaddress; + } } + diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/GameServer.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/GameServer.java deleted file mode 100644 index 973e79975fd426959a3b4942f100e6c9b94166cc..0000000000000000000000000000000000000000 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/GameServer.java +++ /dev/null @@ -1,163 +0,0 @@ -package de.hdm_stuttgart.battlearena.Model.Multiplayer; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; - -public class GameServer { - - private static final Logger log = LogManager.getLogger(GameServer.class); - - private ServerSocket socket; - private int numPlayers; - private int maxPlayers; - private Socket p1Socket; - private Socket p2Socket; - private ReadFromClient p1ReadRunnable; - private ReadFromClient p2ReadRunnable; - private WriteToClient p1WriteRunnable; - private WriteToClient p2WriteRunnable; - - private double p1x, p1y, p2x, p2y; - - public GameServer() { - System.out.println("========= GAME SERVER ========="); - numPlayers = 0; - maxPlayers = 2; - - p1x = 100; - p1y = 400; - - p2x = 490; - p2y = 400; - - try { - socket = new ServerSocket(45371); - } catch (IOException ex) { - System.out.println("IOException from Game Server constructor!"); - } - } - - public void acceptConnections(){ - try { - System.out.println("Waiting for conection..."); - while (numPlayers < maxPlayers){ - Socket s = socket.accept(); - DataInputStream in = new DataInputStream(s.getInputStream()); - DataOutputStream out = new DataOutputStream(s.getOutputStream()); - - numPlayers++; - out.writeInt(numPlayers); - System.out.println("Player #"+ numPlayers + "has connected."); - - ReadFromClient rfc = new ReadFromClient(numPlayers, in); - WriteToClient wtc = new WriteToClient(numPlayers, out); - - if(numPlayers == 1) { - p1Socket = s; - p1ReadRunnable = rfc; - p1WriteRunnable = wtc; - } else { - p2Socket = s; - p2ReadRunnable = rfc; - p2WriteRunnable = wtc; - p1WriteRunnable.sendStartMsg(); - p2WriteRunnable.sendStartMsg(); - Thread readThread1 = new Thread(p1ReadRunnable); - Thread readThread2 = new Thread(p2ReadRunnable); - readThread1.start(); - readThread2.start(); - Thread writeThread1 = new Thread(p1WriteRunnable); - Thread writeThread2 = new Thread(p2WriteRunnable); - writeThread1.start(); - writeThread2.start(); - } - - } - - System.out.println("No longer accepting connections"); - - }catch (IOException ex){ - System.out.println("IOException from acceptConnect"); - } - } - - private class ReadFromClient implements Runnable { - private int playerID; - private DataInputStream dataIn; - - public ReadFromClient( int pid, DataInputStream in) { - playerID = pid; - dataIn = in; - System.out.println("RFC" + playerID + "Runnable created"); - } - - public void run() { - try { - while (true) { - if(playerID == 1){ - p1x = dataIn.readDouble(); - p1y = dataIn.readDouble(); - } else { - p2x = dataIn.readDouble(); - p2y = dataIn.readDouble(); - } - } - }catch (IOException ex){ - System.out.println("IOException from RFC run()"); - } - } - } - - private class WriteToClient implements Runnable { - private int playerID; - private DataOutputStream dataOut; - - public WriteToClient(int pid, DataOutputStream out) { - playerID = pid; - dataOut = out; - System.out.println("WTC" + playerID + "Runnable created"); - } - - public void run() { - try { - while(true) { - if(playerID == 1) { - dataOut.writeDouble(p2x); - dataOut.writeDouble(p2y); - dataOut.flush(); - } else { - dataOut.writeDouble(p1x); - dataOut.writeDouble(p1y); - dataOut.flush(); - } - try { - Thread.sleep(25); - } catch(InterruptedException ex){ - System.out.println("InterruptedException from WTC run()"); - } - } - } catch (IOException ex) { - System.out.println("IOException from WTC run()"); - } - } - - public void sendStartMsg() { - try { - dataOut.writeUTF("We now have 2 players. Go!"); - } catch (IOException ex) { - System.out.println("IOException from sendStartMsg()"); - } - } - } - - public static void main(String[] args) { - GameServer gs = new GameServer(); - gs.acceptConnections(); - } -} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java new file mode 100644 index 0000000000000000000000000000000000000000..fddc2fae68590bac4fc51d13f466b7bd8684012c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java @@ -0,0 +1,164 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.*; +import java.io.*; +import java.util.Arrays; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class Server { + + private static final Logger log = LogManager.getLogger(Server.class); + private ServerSocket serverSocket; + private static boolean isServerRunning = true; + private static int px; + private static int py; + + private static int enemyx = 0; + private static int enemyy = 0; + private static int playerID; + private static int playercount = 0; + private static int[] cords; + private static int[] returncords = {enemyx,enemyy,playerID}; + private boolean started = false; + private static String ipaddress = "localhost"; + +//Uncomment these lines to test the server starting manually: + /* public static void main(String[] args) throws IOException { //main method for testing purposes + Server server = new Server(); + log.info("server starting..."); + server.start(ipaddress, 4444); + } */ + + //use this method to start the server from another class + public void startServer() throws IOException { + Server server = new Server(); + log.info("server starting..."); + server.start(ipaddress,4444); + } + + public void start(String host_ip, int port) throws IOException { + serverSocket = new ServerSocket(port); + log.info("server started!"); + started = true; + while (true){ + new ServerHandler(serverSocket.accept()).start(); + } + } + + private static class ServerHandler extends Thread { + private final Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + public ServerHandler(Socket socket) { + this.clientSocket = socket; + } + + public void run() { + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + executorService.scheduleAtFixedRate(() -> { + try { + BufferedReader localIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + PrintWriter localOut = new PrintWriter(clientSocket.getOutputStream(), true); + + String inputLine = localIn.readLine(); + + if (inputLine != null) { + // Assuming that the input line is a comma-separated list of integers + String[] coordinates = inputLine.split(","); + cords = new int[coordinates.length]; + for (int i = 0; i < coordinates.length; i++) { + cords[i] = Integer.parseInt(coordinates[i]); + } + + //first connect of a client: + if(playercount == 0){ + //first player to connect + playercount++; + returncords[2] = 1; + + } else if(playercount == 1){ + //second player to connect + if(cords[2] == 1){ + returncords[2] = 1; + } else { + playercount++; + returncords[2] = 2; + } + + } else if(playercount == 2){ + + //check which client has connected + if (cords[2] == 1) { //player + px = cords[0]; + py = cords[1]; + + //set the cords to return: + returncords[0] = enemyx; + returncords[1] = enemyy; + + //set playerID: + returncords[2] = 1; + + } else if(cords[2] == 2) { //enemy + enemyx = cords[0]; + enemyy = cords[1]; + + //set the cords to return: + returncords[0] = px; + returncords[1] = py; + + //set playerID: + returncords[2] = 2; + + } + } + + localOut.println(Arrays.toString(returncords)); + localOut.flush(); + } + + log.info("Player X / Y : " + px + " / " + py + " Enemy X / Y : " + enemyx + " / " + enemyy); + + + //check if server was shut down: + if (!isServerRunning) { + executorService.shutdown(); + try { + if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { + executorService.shutdownNow(); + } + } catch (InterruptedException e) { + log.error("Error waiting for executor service termination: " + e.getMessage()); + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + }, 0, 50, TimeUnit.MILLISECONDS); + } + } + + public void stopServer() { + isServerRunning = false; + try { + serverSocket.close(); // Close the server socket to break out of accept() in the main thread + } catch (IOException e) { + log.error("Error closing server socket: " + e.getMessage()); + } + } + + public boolean isStarted() { + return started; + } + public static void setIpaddress(String ipaddress) { + Server.ipaddress = ipaddress; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/TestMap.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/TestMap.java new file mode 100644 index 0000000000000000000000000000000000000000..f6d7fdf0800d787b23fb6df532afdb898733d53c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/TestMap.java @@ -0,0 +1,113 @@ +package de.hdm_stuttgart.battlearena.Model.Multiplayer; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import java.util.concurrent.TimeUnit; + +import java.io.IOException; + +public class TestMap extends Application { + private static final int SQUARE_SIZE = 50; + private static Rectangle square; + private static Rectangle enemy; + private Color color = Color.BLACK; + + @Override + public void start(Stage primaryStage) throws IOException, InterruptedException { + + ConnectionHandler handler = new ConnectionHandler(); + handler.startHandler(); + + TimeUnit.SECONDS.sleep(1); + + square = new Rectangle(SQUARE_SIZE, SQUARE_SIZE, color); + enemy = new Rectangle(SQUARE_SIZE, SQUARE_SIZE, color); + + Pane root = new Pane(); + root.getChildren().add(square); + root.getChildren().add(enemy); + + Scene scene = new Scene(root, 400, 400); + + scene.setOnKeyPressed(event -> handleKeyPress(event.getCode(), handler)); + + primaryStage.setTitle("Player #" + handler.getPlayerID()); + primaryStage.setScene(scene); + primaryStage.show(); + + if(handler.getPlayerID() == 1){ + square.setX(50); + square.setY(50); + enemy.setX(200); + enemy.setY(50); + } else if(handler.getPlayerID() == 2){ + square.setX(200); + square.setY(50); + enemy.setX(50); + enemy.setY(50); + } + + UpdateThread update = new UpdateThread(handler); + update.start(); + + } + + private void handleKeyPress(KeyCode code, ConnectionHandler handler) { + switch (code) { + case UP: + square.setY(square.getY() - 20); + handler.setpY(handler.getpY() - 20); + break; + case DOWN: + square.setY(square.getY() + 20); + handler.setpY(handler.getpY() + 20); + break; + case LEFT: + square.setX(square.getX() - 20); + handler.setpX(handler.getpX() - 20); + break; + case RIGHT: + square.setX(square.getX() + 20); + handler.setpX(handler.getpX() + 20); + break; + } + } + + private static class UpdateThread extends Thread { + private final ConnectionHandler handler; + + private UpdateThread(ConnectionHandler handler) { + this.handler = handler; + } + + public void run() { + while (true){ + + handler.setpX((int) square.getX()); + handler.setpY((int) square.getY()); + + //receive cords + enemy.setX(handler.getEnemyX()); + enemy.setY(handler.getEnemyY()); + + + try { + Thread.sleep(16); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + + } + } + + public static void main(String[] args) throws IOException { + launch(args); + } +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Persistance/DataBase.java b/src/main/java/de/hdm_stuttgart/battlearena/Persistance/DataBase.java deleted file mode 100644 index e766e18264ef67496e300c52199eae616e794db6..0000000000000000000000000000000000000000 --- a/src/main/java/de/hdm_stuttgart/battlearena/Persistance/DataBase.java +++ /dev/null @@ -1,10 +0,0 @@ -package de.hdm_stuttgart.battlearena.Persistance; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -public class DataBase implements IDataBase{ - - private static final Logger log = LogManager.getLogger(DataBase.class); - -} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Persistance/IDataBase.java b/src/main/java/de/hdm_stuttgart/battlearena/Persistance/IDataBase.java deleted file mode 100644 index 17187e8f1400a7d8e1af04e9e33392998a38246c..0000000000000000000000000000000000000000 --- a/src/main/java/de/hdm_stuttgart/battlearena/Persistance/IDataBase.java +++ /dev/null @@ -1,4 +0,0 @@ -package de.hdm_stuttgart.battlearena.Persistance; - -public interface IDataBase { -} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index a9c717ba06cb5d374558234cda58149a7f3b725c..7d57d90079bcd4b9ff8631f05ffffbd948a8236f 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -8,6 +8,24 @@ module gui { opens de.hdm_stuttgart.battlearena to javafx.fxml; opens de.hdm_stuttgart.battlearena.Model.Sound to javafx.media; + + requires java.sql; + requires com.google.gson; + requires com.oracle.database.jdbc; + requires java.naming; + + + opens de.hdm_stuttgart.battlearena to javafx.fxml; + opens de.hdm_stuttgart.battlearena.Controller to javafx.fxml; + opens de.hdm_stuttgart.battlearena.Model.DataStorage.Classes to com.google.gson; + opens de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions to com.google.gson; + opens de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities to com.google.gson; + exports de.hdm_stuttgart.battlearena.Main; exports de.hdm_stuttgart.battlearena.Controller; -} + exports de.hdm_stuttgart.battlearena.Model.Entity; + exports de.hdm_stuttgart.battlearena.Model.Inputs; + exports de.hdm_stuttgart.battlearena.Model.Map; + exports de.hdm_stuttgart.battlearena.Controller.Utilities; + opens de.hdm_stuttgart.battlearena.Controller.Utilities to javafx.fxml; +} \ No newline at end of file diff --git a/src/main/resources/database/AzureDB_logindetails b/src/main/resources/database/AzureDB_logindetails new file mode 100644 index 0000000000000000000000000000000000000000..88e4927a50d6dbc1bdf561cf31ab96067cc6286c --- /dev/null +++ b/src/main/resources/database/AzureDB_logindetails @@ -0,0 +1 @@ +��z����%�\<��$�d<iA�pA5��ś]\&q<��#����ߤVr \ No newline at end of file diff --git a/src/main/resources/database/OracleDB_logindetails b/src/main/resources/database/OracleDB_logindetails new file mode 100644 index 0000000000000000000000000000000000000000..231cb64d34a6d7c284298e353721a36b706e58d5 Binary files /dev/null and b/src/main/resources/database/OracleDB_logindetails differ diff --git a/src/main/resources/database/document.encrypted b/src/main/resources/database/document.encrypted new file mode 100644 index 0000000000000000000000000000000000000000..837a9fbcf781d32fe5ecb8608ad6a314235ba395 Binary files /dev/null and b/src/main/resources/database/document.encrypted differ diff --git a/src/main/resources/database/encrypted;encryptiondecryptiontestFile.txt b/src/main/resources/database/encrypted;encryptiondecryptiontestFile.txt new file mode 100644 index 0000000000000000000000000000000000000000..575b3c72b847f7e1e6e83c5d02a75fe9c5906c67 --- /dev/null +++ b/src/main/resources/database/encrypted;encryptiondecryptiontestFile.txt @@ -0,0 +1 @@ +Hier steht ein Testtext. \ No newline at end of file diff --git a/src/main/resources/database/encryptiondecryptiontestFile.txt b/src/main/resources/database/encryptiondecryptiontestFile.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b7d67bb3df7989061607a0fd4a1869f4fbdda21 --- /dev/null +++ b/src/main/resources/database/encryptiondecryptiontestFile.txt @@ -0,0 +1 @@ +èkæÝ9z"²œÓF'ÙøŒ®[4]ÙqŠð(/ \ No newline at end of file diff --git a/src/main/resources/de/hdm_stuttgart/battlearena/config.properties b/src/main/resources/de/hdm_stuttgart/battlearena/config.properties index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dbd084cebdb997732b0b641b24d6d1d4a64c1c55 100644 --- a/src/main/resources/de/hdm_stuttgart/battlearena/config.properties +++ b/src/main/resources/de/hdm_stuttgart/battlearena/config.properties @@ -0,0 +1,3 @@ +url=jdbc:sqlserver://battlearena.database.windows.net:1433;database=battleArena;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30; +user=battleArenaAdmin@battlearena; +password=krassesRPGGame23# diff --git a/src/main/resources/fonts/StarshipInline.ttf b/src/main/resources/fonts/StarshipInline.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b738337f8929807e42f3eab6ca17b629b9dd9346 Binary files /dev/null and b/src/main/resources/fonts/StarshipInline.ttf differ diff --git a/src/main/resources/fonts/StarshipInlineGrunge.ttf b/src/main/resources/fonts/StarshipInlineGrunge.ttf new file mode 100644 index 0000000000000000000000000000000000000000..717585cf29071695d9a23cc8c28cacea0108c8d0 Binary files /dev/null and b/src/main/resources/fonts/StarshipInlineGrunge.ttf differ diff --git a/src/main/resources/fonts/StarshipShadow.ttf b/src/main/resources/fonts/StarshipShadow.ttf new file mode 100644 index 0000000000000000000000000000000000000000..87b1a315517048dea5ef414f248a124a9d36c0fb Binary files /dev/null and b/src/main/resources/fonts/StarshipShadow.ttf differ diff --git a/src/main/resources/fonts/StarshipShadowInline.ttf b/src/main/resources/fonts/StarshipShadowInline.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e31a30c5608773cb0ca00947d946cf767df4df1c Binary files /dev/null and b/src/main/resources/fonts/StarshipShadowInline.ttf differ diff --git a/src/main/resources/fxml/CommunityMaps.fxml b/src/main/resources/fxml/CommunityMaps.fxml new file mode 100644 index 0000000000000000000000000000000000000000..4c421873024cca71de548b0cf6ba3498472f6594 --- /dev/null +++ b/src/main/resources/fxml/CommunityMaps.fxml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.scene.control.TableView?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" stylesheets="@../styles/style.css" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.CommunityMapController"> + <children> + <TableView fx:id="tableView" editable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" VBox.vgrow="ALWAYS"> + <columns> + <TableColumn editable="false" prefWidth="75.0" text="ID" /> + <TableColumn fx:id="name" editable="false" prefWidth="75.0" text="Name" /> + <TableColumn editable="false" prefWidth="75.0" text="Width" /> + <TableColumn editable="false" prefWidth="75.0" text="Height" /> + <TableColumn editable="false" prefWidth="75.0" text="Downloads" /> + </columns> + <columnResizePolicy> + <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> + </columnResizePolicy> + </TableView> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="20.0" VBox.vgrow="ALWAYS"> + <children> + <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> + <Button mnemonicParsing="false" text="Load" /> + </children> + </HBox> + </children> +</VBox> diff --git a/src/main/resources/fxml/Credits.fxml b/src/main/resources/fxml/Credits.fxml new file mode 100644 index 0000000000000000000000000000000000000000..d676f90ba0a604995e51dfa5c8ff51d3dd485aa7 --- /dev/null +++ b/src/main/resources/fxml/Credits.fxml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.media.MediaView?> + + +<BorderPane fx:id="parent" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.CreditsController"> + <center> + <MediaView fx:id="mediaView" fitHeight="200.0" fitWidth="200.0" BorderPane.alignment="CENTER" /> + </center> +</BorderPane> diff --git a/src/main/resources/fxml/GameScene.fxml b/src/main/resources/fxml/GameScene.fxml index b8a97acf0ac20383de9eb2086ae9b0c3e6e370a3..f046db58280a8ea339f035b1879ac8e6e73b8115 100644 --- a/src/main/resources/fxml/GameScene.fxml +++ b/src/main/resources/fxml/GameScene.fxml @@ -1,8 +1,15 @@ <?xml version="1.0" encoding="UTF-8"?> +<?import javafx.scene.canvas.Canvas?> <?import javafx.scene.layout.AnchorPane?> - - -<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.GameSceneController"> - +<?import javafx.scene.layout.StackPane?> + +<AnchorPane prefHeight="864.0" prefWidth="864.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.GameSceneController"> + <children> + <StackPane prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <Canvas fx:id="canvas2D" height="864.0" width="864.0" /> + </children> + </StackPane> + </children> </AnchorPane> diff --git a/src/main/resources/fxml/Intro.fxml b/src/main/resources/fxml/Intro.fxml new file mode 100644 index 0000000000000000000000000000000000000000..fb0cfbc611000de77a25e8fd74afdaeb358e7c82 --- /dev/null +++ b/src/main/resources/fxml/Intro.fxml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.media.MediaView?> + +<BorderPane fx:id="introParent" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.IntroController"> + <center> + <MediaView fx:id="mediaView" fitHeight="200.0" fitWidth="200.0" BorderPane.alignment="CENTER" /> + </center> +</BorderPane> diff --git a/src/main/resources/fxml/LocalCreate.fxml b/src/main/resources/fxml/LocalCreate.fxml new file mode 100644 index 0000000000000000000000000000000000000000..f100d9b68a8eab3fc0d6554e02f8cbd29cd16373 --- /dev/null +++ b/src/main/resources/fxml/LocalCreate.fxml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Accordion?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.RadioButton?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.TitledPane?> +<?import javafx.scene.control.ToggleButton?> +<?import javafx.scene.control.ToggleGroup?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.LocalCreateController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <HBox alignment="TOP_CENTER" spacing="20.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Rounds:" /> + <Accordion> + <panes> + <TitledPane fx:id="roundsTitledPane" text="Select"> + <content> + <ScrollPane minViewportHeight="40.0"> + <content> + <VBox fx:id="boxBox"> + <children> + <ToggleButton mnemonicParsing="false" styleClass="roundsButton" text="1"> + <toggleGroup> + <ToggleGroup fx:id="rounds" /> + </toggleGroup> + <VBox.margin> + <Insets /> + </VBox.margin> + </ToggleButton> + <ToggleButton mnemonicParsing="false" styleClass="roundsButton" text="2" toggleGroup="$rounds" /> + <ToggleButton mnemonicParsing="false" styleClass="roundsButton" text="3" toggleGroup="$rounds" /> + </children> + </VBox> + </content> + </ScrollPane> + </content> + </TitledPane> + </panes> + </Accordion> + </children> + <VBox.margin> + <Insets /> + </VBox.margin> + </HBox> + <HBox alignment="TOP_CENTER" maxWidth="-Infinity" minWidth="-Infinity" prefHeight="25.0" prefWidth="213.0" spacing="20.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Time:" /> + <Accordion> + <panes> + <TitledPane animated="false" text="Select"> + <content> + <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" /> + </content> + </TitledPane> + </panes> + </Accordion> + </children> + </HBox> + <HBox alignment="TOP_CENTER" spacing="10.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Players:" /> + <RadioButton mnemonicParsing="false" selected="true" text="2"> + <toggleGroup> + <ToggleGroup fx:id="group31" /> + </toggleGroup> + </RadioButton> + <RadioButton mnemonicParsing="false" text="3" toggleGroup="$group31" /> + <RadioButton mnemonicParsing="false" text="4" toggleGroup="$group31" /> + </children> + </HBox> + <HBox alignment="TOP_CENTER" spacing="10.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text:" /> + <RadioButton mnemonicParsing="false" text="Yes"> + <toggleGroup> + <ToggleGroup fx:id="group1" /> + </toggleGroup> + </RadioButton> + <RadioButton mnemonicParsing="false" selected="true" text="No" toggleGroup="$group1" /> + </children> + </HBox> + <HBox alignment="TOP_CENTER" spacing="10.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text:" /> + <RadioButton mnemonicParsing="false" text="Yes"> + <toggleGroup> + <ToggleGroup fx:id="group2" /> + </toggleGroup> + </RadioButton> + <RadioButton mnemonicParsing="false" selected="true" text="No" toggleGroup="$group2" /> + </children> + </HBox> + <HBox alignment="TOP_CENTER" spacing="10.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text:" /> + <RadioButton mnemonicParsing="false" text="Yes"> + <toggleGroup> + <ToggleGroup fx:id="group3" /> + </toggleGroup> + </RadioButton> + <RadioButton mnemonicParsing="false" selected="true" text="No" toggleGroup="$group3" /> + </children> + </HBox> + <Button mnemonicParsing="false" onAction="#skinSelectionScene" text="Start" /> + <Button mnemonicParsing="false" onAction="#backButton" text="Back"> + <VBox.margin> + <Insets bottom="50.0" /> + </VBox.margin> + </Button> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/MainMenu.fxml b/src/main/resources/fxml/MainMenu.fxml index 593ebfedde7527d354af67c063ffcfc078a2472e..39b45c2b7b94147fc779dda696f89e11fafa9e44 100644 --- a/src/main/resources/fxml/MainMenu.fxml +++ b/src/main/resources/fxml/MainMenu.fxml @@ -1,23 +1,25 @@ <?xml version="1.0" encoding="UTF-8"?> +<?import javafx.geometry.Insets?> <?import javafx.scene.control.Button?> -<?import javafx.scene.layout.AnchorPane?> -<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.Pane?> <?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> - -<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MainMenuController"> - <children> - <BorderPane prefHeight="400.0" prefWidth="600.0"> - <center> - <VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="30.0" BorderPane.alignment="CENTER"> - <children> - <Button mnemonicParsing="false" text="Button" /> - <Button mnemonicParsing="false" text="Button" /> - <Button mnemonicParsing="false" text="Button" /> - </children> - </VBox> - </center> - </BorderPane> - </children> -</AnchorPane> +<VBox fx:id="parent" alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="50.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MainMenuController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <Text id="gameTitle" strokeType="OUTSIDE" strokeWidth="0.0" text="Battlearena" /> + <Button mnemonicParsing="false" onAction="#playScene" text="Play" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets top="20.0" /> + </VBox.margin> + </Button> + <Button mnemonicParsing="false" onAction="#mapScene" text="Map Forge" VBox.vgrow="ALWAYS" /> + <Button mnemonicParsing="false" onAction="#statisticsScene" text="Statistics" VBox.vgrow="ALWAYS" /> + <Button mnemonicParsing="false" onAction="#settingsScene" text="Settings" /> + <Button fx:id="exitButton" alignment="CENTER" mnemonicParsing="false" onAction="#exit" text="Exit" /> + <Pane VBox.vgrow="ALWAYS" /> + <Pane layoutX="10.0" layoutY="395.0" VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/MapForge.fxml b/src/main/resources/fxml/MapForge.fxml new file mode 100644 index 0000000000000000000000000000000000000000..3c5265a067cce738ee950498e6b592adee6cb6d8 --- /dev/null +++ b/src/main/resources/fxml/MapForge.fxml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="50.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MapForgeController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <Button mnemonicParsing="false" onAction="#mapEditorScene" text="Map Editor" /> + <Button mnemonicParsing="false" onAction="#communityMapScene" text="Community Maps" /> + <Button mnemonicParsing="false" onAction="#updateMapScene" text="Update Core Maps" /> + <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> + <Pane VBox.vgrow="ALWAYS" /> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/MapSelection.fxml b/src/main/resources/fxml/MapSelection.fxml new file mode 100644 index 0000000000000000000000000000000000000000..1be6734bac78aa59dd7db7a771411adfd64dd828 --- /dev/null +++ b/src/main/resources/fxml/MapSelection.fxml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Accordion?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.TitledPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MapSelectionController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <HBox alignment="TOP_CENTER" spacing="20.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Maps:" /> + <Accordion> + <panes> + <TitledPane fx:id="roundsTitledPane" text="Select"> + <content> + <ScrollPane minViewportHeight="40.0"> + <content> + <VBox fx:id="boxBox" /> + </content> + </ScrollPane> + </content> + </TitledPane> + </panes> + </Accordion> + </children> + <VBox.margin> + <Insets /> + </VBox.margin> + </HBox> + <HBox alignment="TOP_CENTER" maxWidth="-Infinity" minWidth="-Infinity" prefHeight="25.0" prefWidth="213.0" spacing="20.0"> + <children> + <Text fx:id="selectedMapText" strokeType="OUTSIDE" strokeWidth="0.0" /> + </children> + </HBox> + <Button mnemonicParsing="false" onAction="#gameScene" text="Start" /> + <Button mnemonicParsing="false" onAction="#backButton" text="Back"> + <VBox.margin> + <Insets bottom="50.0" /> + </VBox.margin> + </Button> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/MenuBorderPane.fxml b/src/main/resources/fxml/MenuBorderPane.fxml new file mode 100644 index 0000000000000000000000000000000000000000..ed87f4119563968953eef9ff3013783e8ce18a5e --- /dev/null +++ b/src/main/resources/fxml/MenuBorderPane.fxml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.StackPane?> +<?import javafx.scene.text.Font?> + +<BorderPane id="mainMenu" fx:id="parent" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MenuBorderPaneController"> + <right> + <Button fx:id="btnRight" mnemonicParsing="false" prefWidth="111.0" BorderPane.alignment="BOTTOM_CENTER"> + <graphic> + <ImageView fx:id="imgRight" fitHeight="845.0" fitWidth="799.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../textures/images/gear_with_shadow.png" /> + </image> + </ImageView> + </graphic> + </Button> + </right> + <left> + <Button fx:id="btnLeft" contentDisplay="TOP" mnemonicParsing="false" text=":)" BorderPane.alignment="BOTTOM_CENTER"> + <graphic> + <ImageView fx:id="imgLeft" fitHeight="904.0" fitWidth="856.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../textures/images/dont_delete_or_ui_will_break.png" /> + </image> + </ImageView> + </graphic> + <font> + <Font name="System Bold" size="30.0" /> + </font> + </Button> + </left> + <center> + <StackPane fx:id="center" BorderPane.alignment="CENTER" /> + </center> +</BorderPane> diff --git a/src/main/resources/fxml/Multiplayer.fxml b/src/main/resources/fxml/Multiplayer.fxml new file mode 100644 index 0000000000000000000000000000000000000000..6746b48025b1335c72d967e59be21c3a22fd70fb --- /dev/null +++ b/src/main/resources/fxml/Multiplayer.fxml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="50.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MultiplayerController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <Button mnemonicParsing="false" onAction="#multiplayerCreateScene" text="Create" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets top="20.0" /> + </VBox.margin> + </Button> + <Button mnemonicParsing="false" onAction="#multiplayerJoinScene" text="Join" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets /> + </VBox.margin> + </Button> + <Button alignment="CENTER" mnemonicParsing="false" onAction="#backButton" text="Back"> + <VBox.margin> + <Insets /> + </VBox.margin> + </Button> + <Pane VBox.vgrow="ALWAYS" /> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/MultiplayerCreate.fxml b/src/main/resources/fxml/MultiplayerCreate.fxml new file mode 100644 index 0000000000000000000000000000000000000000..f95e2126f13aee4f89541b835ef2c90ffbbc7d9b --- /dev/null +++ b/src/main/resources/fxml/MultiplayerCreate.fxml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.RadioButton?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MultiplayerCreateController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <HBox alignment="TOP_CENTER" spacing="20.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text:" /> + <TextField /> + </children> + <VBox.margin> + <Insets top="50.0" /> + </VBox.margin> + </HBox> + <HBox alignment="TOP_CENTER" maxWidth="-Infinity" minWidth="-Infinity" prefHeight="25.0" prefWidth="213.0" spacing="20.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text:" /> + <TextField /> + </children> + </HBox> + <HBox alignment="TOP_CENTER" spacing="10.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text:" /> + <RadioButton mnemonicParsing="false" text="Yes" /> + <RadioButton mnemonicParsing="false" text="No" /> + </children> + </HBox> + <AnchorPane minHeight="-Infinity" prefHeight="39.0" prefWidth="600.0"> + <children> + <VBox alignment="TOP_CENTER" layoutX="250.0" prefHeight="200.0" prefWidth="100.0" AnchorPane.leftAnchor="250.0" AnchorPane.rightAnchor="250.0"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + </children> + </VBox> + </children> + <VBox.margin> + <Insets top="20.0" /> + </VBox.margin> + </AnchorPane> + <Button mnemonicParsing="false" onAction="#start" text="Start" /> + <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> + <Pane VBox.vgrow="ALWAYS" /> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/MultiplayerJoin.fxml b/src/main/resources/fxml/MultiplayerJoin.fxml new file mode 100644 index 0000000000000000000000000000000000000000..117cf38cd7ba79fb3f41209f4a4b869e4a11e889 --- /dev/null +++ b/src/main/resources/fxml/MultiplayerJoin.fxml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="50.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.MultiplayerJoinController"> + <children> + <Pane maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="IP Adress:" /> + <TextField maxWidth="-Infinity" /> + <Button mnemonicParsing="false" text="Connect" VBox.vgrow="ALWAYS" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="[Error Message]" /> + <Pane maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" /> + <Button alignment="CENTER" mnemonicParsing="false" onAction="#backButton" text="Back" /> + <Pane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="20.0" VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/Play.fxml b/src/main/resources/fxml/Play.fxml new file mode 100644 index 0000000000000000000000000000000000000000..a4cbce23e49949a94521f25dd1b898423ae67e2a --- /dev/null +++ b/src/main/resources/fxml/Play.fxml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.PlayController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <Button mnemonicParsing="false" onAction="#localScene" text="Local" /> + <Button mnemonicParsing="false" onAction="#multiplayerScene" text="Multiplayer" /> + <Button alignment="CENTER" mnemonicParsing="false" onAction="#backButton" text="Back" /> + <Pane VBox.vgrow="ALWAYS" /> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/PlayerCreateScene.fxml b/src/main/resources/fxml/PlayerCreateScene.fxml new file mode 100644 index 0000000000000000000000000000000000000000..5200c6495466b6bf62772664a6f3a093ac2f5453 --- /dev/null +++ b/src/main/resources/fxml/PlayerCreateScene.fxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.StackPane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.media.MediaView?> +<?import javafx.scene.text.Text?> + +<BorderPane fx:id="parent" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.PlayerCreateController"> + <center> + <StackPane BorderPane.alignment="CENTER"> + <children> + <MediaView fx:id="mediaView" fitHeight="200.0" fitWidth="200.0" /> + <VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="10.0"> + <children> + <Text fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="WELCOME!" /> + <Text fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="This page is still under construction" /> + <Text fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="please have some patience" /> + <Text fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Thank you" /> + <Button fx:id="button" mnemonicParsing="false" text="Get me out of here" /> + </children> + </VBox> + </children> + </StackPane> + </center> +</BorderPane> diff --git a/src/main/resources/fxml/Settings.fxml b/src/main/resources/fxml/Settings.fxml new file mode 100644 index 0000000000000000000000000000000000000000..7b8950fc2664c2e1e041ce2d05b7b46986f01d64 --- /dev/null +++ b/src/main/resources/fxml/Settings.fxml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Slider?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.SettingsController"> + <children> + <HBox alignment="CENTER"> + <children> + <VBox alignment="TOP_CENTER" spacing="10.0"> + <children> + <VBox alignment="CENTER" VBox.vgrow="ALWAYS"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Music volume:" /> + <Slider fx:id="musicSlider" blockIncrement="25.0" majorTickUnit="100.0" minorTickCount="1" prefHeight="14.0" prefWidth="480.0" showTickLabels="true" value="75.0" VBox.vgrow="NEVER" /> + </children> + </VBox> + <VBox alignment="CENTER" VBox.vgrow="ALWAYS"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="SFX volume:" /> + <Slider fx:id="sfxSlider" blockIncrement="25.0" majorTickUnit="100.0" minorTickCount="1" prefHeight="14.0" prefWidth="480.0" showTickLabels="true" value="75.0" /> + </children> + </VBox> + </children> + </VBox> + </children> + </HBox> + <Button mnemonicParsing="false" onAction="#creditScene" text="Credits" /> + <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/SkinSelection.fxml b/src/main/resources/fxml/SkinSelection.fxml new file mode 100644 index 0000000000000000000000000000000000000000..b98b91af38434be6169c8cdfead739ef20587460 --- /dev/null +++ b/src/main/resources/fxml/SkinSelection.fxml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ToggleButton?> +<?import javafx.scene.control.ToggleGroup?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> + +<VBox fx:id="parent" alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.SkinSelectionController"> + <children> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="40.0"> + <children> + <ToggleButton contentDisplay="TOP" mnemonicParsing="false" styleClass="skinSelection" text="Elias"> + <graphic> + <ImageView fx:id="selection1" fitHeight="700.0" fitWidth="700.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../textures/images/elias.png" /> + </image> + </ImageView> + </graphic> + <toggleGroup> + <ToggleGroup fx:id="selectionButton" /> + </toggleGroup> + </ToggleButton> + <ToggleButton contentDisplay="TOP" mnemonicParsing="false" styleClass="skinSelection" text="Erzan" toggleGroup="$selectionButton"> + <graphic> + <ImageView fx:id="selection2" fitHeight="700.0" fitWidth="700.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../textures/images/erzan.png" /> + </image> + </ImageView> + </graphic> + </ToggleButton> + <ToggleButton contentDisplay="TOP" mnemonicParsing="false" styleClass="skinSelection" text="Martin" toggleGroup="$selectionButton"> + <graphic> + <ImageView fx:id="selection3" fitHeight="700.0" fitWidth="700.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../textures/images/martin.png" /> + </image> + </ImageView> + </graphic> + </ToggleButton> + </children> + </HBox> + <Button mnemonicParsing="false" onAction="#gameScene" text="Start" /> + <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/Statistics.fxml b/src/main/resources/fxml/Statistics.fxml new file mode 100644 index 0000000000000000000000000000000000000000..6c98b4e5e5aa7e8efd880b6945b8c7091aa04d32 --- /dev/null +++ b/src/main/resources/fxml/Statistics.fxml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.chart.PieChart?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Text?> + +<VBox fx:id="parent" alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="50.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.StatisticsController"> + <children> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="30.0" VBox.vgrow="ALWAYS"> + <children> + <VBox alignment="CENTER_RIGHT" prefHeight="200.0" prefWidth="100.0" spacing="10.0" HBox.hgrow="ALWAYS"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Kills:" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Deaths:" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Blocks Destroyed:" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Games won:" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Games lost:" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Ingame time:" /> + </children> + </VBox> + <VBox alignment="CENTER_LEFT" prefHeight="200.0" prefWidth="100.0" spacing="10.0" HBox.hgrow="ALWAYS"> + <children> + <Text fx:id="kills" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + <Text fx:id="deaths" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + <Text fx:id="blocks" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + <Text fx:id="gamesWon" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + <Text fx:id="gamesLost" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + <Text fx:id="gameTime" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> + </children> + <HBox.margin> + <Insets /> + </HBox.margin> + </VBox> + <VBox prefHeight="200.0" prefWidth="100.0" HBox.hgrow="ALWAYS"> + <children> + <PieChart fx:id="kd" minHeight="-Infinity" minWidth="-Infinity" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets bottom="-200.0" /> + </VBox.margin></PieChart> + <PieChart fx:id="wl" minHeight="-Infinity" minWidth="-Infinity" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets top="-40.0" /> + </VBox.margin></PieChart> + </children> + </VBox> + </children> + </HBox> + <Button mnemonicParsing="false" onAction="#mainMenuScene" text="Back" /> + </children> +</VBox> diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 6fb857169bf3b818c95f9a1a9ada8ad3b39b0d58..9a77de28c30d210dadfd85f28a594d9e5621d9c8 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -16,6 +16,7 @@ </Logger> <Root level="info"> <AppenderRef ref="STDOUT"/> + <AppenderRef ref="A1"/> </Root> </Loggers> </Configuration> \ No newline at end of file diff --git a/src/main/resources/maps/communityMaps.json b/src/main/resources/maps/communityMaps.json new file mode 100644 index 0000000000000000000000000000000000000000..9c99ec44154627bf856e8eff30053efa9d624f9f --- /dev/null +++ b/src/main/resources/maps/communityMaps.json @@ -0,0 +1,16 @@ +[ + { + "mapID": "fbf44184867512faecc195ae75ca55d5ab7bad2d", + "mapName": "Arena3", + "mapWidth": 18, + "mapHeight": 18, + "mapData": "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12" + }, + { + "mapID": "1c23b362fd666c5fb7ed60ca611b17246424e49f", + "mapName": "Arena4", + "mapWidth": 18, + "mapHeight": 18, + "mapData": "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 4 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12" + } +] \ No newline at end of file diff --git a/src/main/resources/maps/coreMaps.json b/src/main/resources/maps/coreMaps.json new file mode 100644 index 0000000000000000000000000000000000000000..ba63b040f5afc06edf39a660e0cd815b3bb7963b --- /dev/null +++ b/src/main/resources/maps/coreMaps.json @@ -0,0 +1,16 @@ +[ + { + "mapID": "09a02b54d05b5b7ebc29a4383ca12d3dda846b72", + "mapName": "Arena1", + "mapWidth": 18, + "mapHeight": 18, + "mapData": "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12" + }, + { + "mapID": "0ab15557ab6dc4be60dfe6a9b0288bac3036bd97", + "mapName": "Arena2", + "mapWidth": 18, + "mapHeight": 18, + "mapData": "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12" + } +] \ No newline at end of file diff --git a/src/main/resources/player/appSettings.json b/src/main/resources/player/appSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..ec5bc62a909f2065d81be4cfd6c494b9e10715fb --- /dev/null +++ b/src/main/resources/player/appSettings.json @@ -0,0 +1,4 @@ +{ + "sfxVolume": 50, + "musicVolume": 0 +} \ No newline at end of file diff --git a/src/main/resources/player/playerAccount.json b/src/main/resources/player/playerAccount.json new file mode 100644 index 0000000000000000000000000000000000000000..60070b6ed6a4c8153907eaf7e737e2e997fb3377 --- /dev/null +++ b/src/main/resources/player/playerAccount.json @@ -0,0 +1,5 @@ +{ + "playerName": "Player1", + "accountPassword": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + "accountType": "LOCAL" +} \ No newline at end of file diff --git a/src/main/resources/player/playerStatsLocal.json b/src/main/resources/player/playerStatsLocal.json new file mode 100644 index 0000000000000000000000000000000000000000..e51de779c74b6c93fe347b5bf263508c23fff2c9 --- /dev/null +++ b/src/main/resources/player/playerStatsLocal.json @@ -0,0 +1,8 @@ +{ + "gamesLost": 5, + "gamesWon": 9, + "kills": 30, + "deaths": 20, + "blocksDestroyed": 200, + "gameTime": 3966480 +} \ No newline at end of file diff --git a/src/main/resources/sound/music/cocBackgroundMusicTest.mp3 b/src/main/resources/sound/music/cocBackgroundMusicTest.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..fe39b45659600de8eb2ed2bdac281444be461261 Binary files /dev/null and b/src/main/resources/sound/music/cocBackgroundMusicTest.mp3 differ diff --git a/src/main/resources/sound/music/constructionJazz.mp3 b/src/main/resources/sound/music/constructionJazz.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5669e8017883014e447765a405c6ec3b208db5bb Binary files /dev/null and b/src/main/resources/sound/music/constructionJazz.mp3 differ diff --git a/src/main/resources/sound/music/spongeBob.mp3 b/src/main/resources/sound/music/spongeBob.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..cd919cc16ea0c103c0cc1c095f4a19ce5c88960c Binary files /dev/null and b/src/main/resources/sound/music/spongeBob.mp3 differ diff --git a/src/main/resources/sound/music/stadiumRave.mp3 b/src/main/resources/sound/music/stadiumRave.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..990274fd88b95bfc5fe584184f838cbc54c2dbdc Binary files /dev/null and b/src/main/resources/sound/music/stadiumRave.mp3 differ diff --git a/src/main/resources/sound/music/wii.mp3 b/src/main/resources/sound/music/wii.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..8b471420a2a4fbb8ff28b6ff2f8cfee463670097 Binary files /dev/null and b/src/main/resources/sound/music/wii.mp3 differ diff --git a/src/main/resources/styles/style.css b/src/main/resources/styles/style.css new file mode 100644 index 0000000000000000000000000000000000000000..e676c8daadf56536c73d3bf8dd515a7c5a7533cd --- /dev/null +++ b/src/main/resources/styles/style.css @@ -0,0 +1,184 @@ +* { + -fx-dark-brown: #3c2014; + -fx-brown: #956233; +} + +#button { + -fx-text-fill: #454545; +} + +.root { + -fx-font-family: "Starship Shadow"; + -fx-text-fill: white; + -fx-background-color: black; +} + +#mainMenu{ + -fx-background-image: url("../textures/images/background.png"); + -fx-background-size: cover; +} + +#gameTitle { + -fx-font-size: 100; +} + +.button { + -fx-text-fill: -fx-brown; + -fx-background-color: none; + -fx-skin: "de.hdm_stuttgart.battlearena.Controller.Utilities.ButtonTransition"; +} + +#btnLeft { + -fx-skin: none; + -fx-text-fill: white; +} + +.accordion { + -fx-font-size: 30; +} + +.titled-pane:focused > .title > .arrow-button > .arrow { + -fx-effect: null; +} + +.accordion .titled-pane > *.content{ + -fx-background-color: transparent ; + -fx-border-width: 0; +} + +.accordion .titled-pane > .title { + -fx-background-color: transparent; + -fx-border-width: 0; +} + +.scroll-pane > .viewport { + -fx-background-color: none; +} + +.scroll-pane { + -fx-background-color: transparent; +} + +/*scroll pane scroll bar*/ +.scroll-pane .scroll-bar:horizontal .track, +.scroll-pane .scroll-bar:vertical .track { + -fx-background-color: -fx-dark-brown; + -fx-border-color: none; + -fx-background-radius: 1em; + -fx-border-radius: 1em; +} + +/* The increment and decrement button CSS class of scrollbar */ +.scroll-pane .scroll-bar:vertical .increment-button , +.scroll-pane .scroll-bar:vertical .decrement-button { + -fx-background-color: transparent; + -fx-background-radius: 0em; + -fx-padding:0 12 0 0; +} + +.scroll-pane .scroll-bar .increment-arrow, +.scroll-pane .scroll-bar .decrement-arrow { + -fx-shape: " "; + -fx-padding: 0; +} + +/* The main scrollbar **thumb** CSS class which we drag every time (movable) */ +.scroll-pane .scroll-bar:horizontal .thumb, +.scroll-pane .scroll-bar:vertical .thumb { + -fx-background-color: white; + -fx-background-insets: 2, 0, 0; + -fx-background-radius: 1em; +} + +#boxBox { + -fx-background-color: none; +} + +/* https://dx.dragan.ba/javafx-radiobutton-custom-css/ */ +.radio-button .radio { + -fx-border-width: 1px; + -fx-border-color: -fx-dark-brown; + -fx-background-color: none; + -fx-background-image: null; + -fx-border-radius: 15px; + -fx-padding: 3px; +} + +.radio-button .dot { + -fx-padding: 8px; +} + +.radio-button:selected .dot { + -fx-background-color: -fx-dark-brown; + -fx-background-insets: 0; +} + +.slider .track { + -fx-background-color: rgba(0, 0, 0, 0.5); + -fx-pref-height: 0.2em; + } + +.slider .thumb { + -fx-pref-height: 0.6em; + -fx-pref-width: 0.4em; + -fx-background-color: -fx-brown; +} + +.toggle-button { + -fx-skin: "de.hdm_stuttgart.battlearena.Controller.Utilities.ToggleButtonTransition"; + -fx-background-color: none; +} + +.skinSelection:pressed { + -fx-background-color: rgba(255, 255, 255, 0.3); +} + +.table-view { + -fx-background-color: transparent; +} + +.table-view .column-header { + -fx-background-color: -fx-brown; +} + +.table-view .table-cell{ + -fx-font-size: 30; + -fx-alignment: center; +} + +.table-row-cell { + -fx-background-color: rgba(0, 0, 0, 0.2); +} + +.table-row-cell:hover { + -fx-background-color: rgba(0, 0, 0, 0.1); +} + +.table-row-cell:selected { + -fx-background-color: rgba(255, 255, 255, 0.3); +} + +.chart { + -fx-pref-width: 600; + -fx-pref-height: 620; + -fx-min-width: 600; + -fx-min-height: 620; + -fx-max-width: 916; + -fx-max-height: 620; +} + +.chart-pie { + -fx-border-color: black; +} + +.chart-pie-label { + -fx-font-size: 0.7em; +} + +.chart-legend { + -fx-background-color: rgba(60, 32, 20, 0.2); +} + +.default-color0.chart-pie {-fx-pie-color: transparent;} +.default-color1.chart-pie {-fx-pie-color: transparent;} +.default-color2.chart-pie {-fx-pie-color: transparent;} diff --git a/src/main/resources/textures/images/background.png b/src/main/resources/textures/images/background.png new file mode 100644 index 0000000000000000000000000000000000000000..cfecaea36ac9953b10720b8cee301e0501b75064 Binary files /dev/null and b/src/main/resources/textures/images/background.png differ diff --git a/src/main/resources/textures/images/dont_delete_or_ui_will_break.png b/src/main/resources/textures/images/dont_delete_or_ui_will_break.png new file mode 100644 index 0000000000000000000000000000000000000000..271b72c9c2ea827a6a7b74b5612f4eba34b9253d Binary files /dev/null and b/src/main/resources/textures/images/dont_delete_or_ui_will_break.png differ diff --git a/src/main/resources/textures/images/elias.png b/src/main/resources/textures/images/elias.png new file mode 100644 index 0000000000000000000000000000000000000000..92a45fea76f21bc5eadeef287d5126c8a1278ef7 Binary files /dev/null and b/src/main/resources/textures/images/elias.png differ diff --git a/src/main/resources/textures/images/erzan.png b/src/main/resources/textures/images/erzan.png new file mode 100644 index 0000000000000000000000000000000000000000..2101d8665fa6cfe21d1eb1d94a4da796034f71c9 Binary files /dev/null and b/src/main/resources/textures/images/erzan.png differ diff --git a/src/main/resources/textures/images/gear_with_shadow.png b/src/main/resources/textures/images/gear_with_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..7dad227dd915ca1907589a15b55cecd734d03cb9 Binary files /dev/null and b/src/main/resources/textures/images/gear_with_shadow.png differ diff --git a/src/main/resources/textures/images/icon.png b/src/main/resources/textures/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ec952db144b1681f2e7ce5954f1ffaeda29fab71 Binary files /dev/null and b/src/main/resources/textures/images/icon.png differ diff --git a/src/main/resources/textures/images/martin.png b/src/main/resources/textures/images/martin.png new file mode 100644 index 0000000000000000000000000000000000000000..fdaa4de0ea064ae8da30cc1a1e97799db9cb20aa Binary files /dev/null and b/src/main/resources/textures/images/martin.png differ diff --git a/src/main/resources/textures/images/rusty_metal.png b/src/main/resources/textures/images/rusty_metal.png new file mode 100644 index 0000000000000000000000000000000000000000..2b2ff5687299d78376613202e79447537f36ec9e Binary files /dev/null and b/src/main/resources/textures/images/rusty_metal.png differ diff --git a/src/main/resources/textures/images/vintage_paper_with_drawings.png b/src/main/resources/textures/images/vintage_paper_with_drawings.png new file mode 100644 index 0000000000000000000000000000000000000000..862a0ac453b013ad66807f109c987c1c85dbaae9 Binary files /dev/null and b/src/main/resources/textures/images/vintage_paper_with_drawings.png differ diff --git a/src/main/resources/textures/map/Grass01.png b/src/main/resources/textures/map/Grass01.png new file mode 100644 index 0000000000000000000000000000000000000000..e835d4676d2f80105626ece4d99b485a30b289fe Binary files /dev/null and b/src/main/resources/textures/map/Grass01.png differ diff --git a/src/main/resources/textures/map/Grass02.png b/src/main/resources/textures/map/Grass02.png new file mode 100644 index 0000000000000000000000000000000000000000..144fad81f75b681454b58768081394cb40aaeead Binary files /dev/null and b/src/main/resources/textures/map/Grass02.png differ diff --git a/src/main/resources/textures/map/Grass04.png b/src/main/resources/textures/map/Grass04.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce012b5eac6c41488efe96c5f66eb43c28c98ce Binary files /dev/null and b/src/main/resources/textures/map/Grass04.png differ diff --git a/src/main/resources/textures/map/Stone01.png b/src/main/resources/textures/map/Stone01.png new file mode 100644 index 0000000000000000000000000000000000000000..b6cf13f66633060803264739b889f64c32877a0e Binary files /dev/null and b/src/main/resources/textures/map/Stone01.png differ diff --git a/src/main/resources/textures/map/Stone02.png b/src/main/resources/textures/map/Stone02.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac41bee77062960aa2d8cfc921f66e45de629ba Binary files /dev/null and b/src/main/resources/textures/map/Stone02.png differ diff --git a/src/main/resources/textures/map/finalheart.png b/src/main/resources/textures/map/finalheart.png new file mode 100644 index 0000000000000000000000000000000000000000..b861b145ceb949abdd7222a2679fe8e10756340f Binary files /dev/null and b/src/main/resources/textures/map/finalheart.png differ diff --git a/src/main/resources/textures/map/mapPlaceholder.png b/src/main/resources/textures/map/mapPlaceholder.png deleted file mode 100644 index ca3f707dff2cf59fbcf284b896a786fafa5e9180..0000000000000000000000000000000000000000 Binary files a/src/main/resources/textures/map/mapPlaceholder.png and /dev/null differ diff --git a/src/main/resources/textures/player/HumanDown01.png b/src/main/resources/textures/player/HumanDown01.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8c9024a240bfec9f28cdecffff3060d3eb769e Binary files /dev/null and b/src/main/resources/textures/player/HumanDown01.png differ diff --git a/src/main/resources/textures/player/HumanDown02.png b/src/main/resources/textures/player/HumanDown02.png new file mode 100644 index 0000000000000000000000000000000000000000..3a96754826bed31e6baad1d519a71c2e97680821 Binary files /dev/null and b/src/main/resources/textures/player/HumanDown02.png differ diff --git a/src/main/resources/textures/player/downOne.png b/src/main/resources/textures/player/downOne.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e261cc01b3a32bf937536716162ec5c61d0d50 Binary files /dev/null and b/src/main/resources/textures/player/downOne.png differ diff --git a/src/main/resources/textures/player/downTwo.png b/src/main/resources/textures/player/downTwo.png new file mode 100644 index 0000000000000000000000000000000000000000..9a14543c8d06be035ea8048428faeaa218faec32 Binary files /dev/null and b/src/main/resources/textures/player/downTwo.png differ diff --git a/src/main/resources/textures/player/high_born/HighBornDown00.png b/src/main/resources/textures/player/high_born/HighBornDown00.png new file mode 100644 index 0000000000000000000000000000000000000000..b87b19b2ffe1ce2048c6d8bc96d1e4a66fd4c4af Binary files /dev/null and b/src/main/resources/textures/player/high_born/HighBornDown00.png differ diff --git a/src/main/resources/textures/player/high_born/HighBornDown01.png b/src/main/resources/textures/player/high_born/HighBornDown01.png new file mode 100644 index 0000000000000000000000000000000000000000..787b4603347dac4b2d5f2c1063b3e3a3551fed4a Binary files /dev/null and b/src/main/resources/textures/player/high_born/HighBornDown01.png differ diff --git a/src/main/resources/textures/player/human/HumanDown00.png b/src/main/resources/textures/player/human/HumanDown00.png new file mode 100644 index 0000000000000000000000000000000000000000..980612cb998a80e7710798fbd2f8a81791ef7322 Binary files /dev/null and b/src/main/resources/textures/player/human/HumanDown00.png differ diff --git a/src/main/resources/textures/player/human/HumanDown01.png b/src/main/resources/textures/player/human/HumanDown01.png new file mode 100644 index 0000000000000000000000000000000000000000..54792ff64f25e5c6e48e35f90502ff2d7fea9893 Binary files /dev/null and b/src/main/resources/textures/player/human/HumanDown01.png differ diff --git a/src/main/resources/textures/player/human/HumanLeft00.png b/src/main/resources/textures/player/human/HumanLeft00.png new file mode 100644 index 0000000000000000000000000000000000000000..2d259ebb0c88259967e361c93138dd3367bcfe1b Binary files /dev/null and b/src/main/resources/textures/player/human/HumanLeft00.png differ diff --git a/src/main/resources/textures/player/human/HumanLeft01.png b/src/main/resources/textures/player/human/HumanLeft01.png new file mode 100644 index 0000000000000000000000000000000000000000..3e25fce1c897aa94297d73248a54b1c09700d8d2 Binary files /dev/null and b/src/main/resources/textures/player/human/HumanLeft01.png differ diff --git a/src/main/resources/textures/player/human/HumanRight00.png b/src/main/resources/textures/player/human/HumanRight00.png new file mode 100644 index 0000000000000000000000000000000000000000..f20b2b692e98c68bc6671b0294a3582b4de65f0b Binary files /dev/null and b/src/main/resources/textures/player/human/HumanRight00.png differ diff --git a/src/main/resources/textures/player/human/HumanRight01.png b/src/main/resources/textures/player/human/HumanRight01.png new file mode 100644 index 0000000000000000000000000000000000000000..ba2dd289825604b6730186ffb862592b2d94bb12 Binary files /dev/null and b/src/main/resources/textures/player/human/HumanRight01.png differ diff --git a/src/main/resources/textures/player/human/HumanUp00.png b/src/main/resources/textures/player/human/HumanUp00.png new file mode 100644 index 0000000000000000000000000000000000000000..bf2042d6a68463fa8c392c03d5cfaa973f9d1ae4 Binary files /dev/null and b/src/main/resources/textures/player/human/HumanUp00.png differ diff --git a/src/main/resources/textures/player/human/HumanUp01.png b/src/main/resources/textures/player/human/HumanUp01.png new file mode 100644 index 0000000000000000000000000000000000000000..c21f00058a48f3c99b1eeaae7f2d93f8baef1471 Binary files /dev/null and b/src/main/resources/textures/player/human/HumanUp01.png differ diff --git a/src/main/resources/textures/player/leftOne.png b/src/main/resources/textures/player/leftOne.png new file mode 100644 index 0000000000000000000000000000000000000000..13cc7b495f2647d10917ebda3046cd8af32f9553 Binary files /dev/null and b/src/main/resources/textures/player/leftOne.png differ diff --git a/src/main/resources/textures/player/leftTwo.png b/src/main/resources/textures/player/leftTwo.png new file mode 100644 index 0000000000000000000000000000000000000000..cbed81ae3a90ef128cb1bd913329c211c69030bd Binary files /dev/null and b/src/main/resources/textures/player/leftTwo.png differ diff --git a/src/main/resources/textures/player/rightOne.png b/src/main/resources/textures/player/rightOne.png new file mode 100644 index 0000000000000000000000000000000000000000..5d26f27d4b44906c9c17e0625329e56407c86d8d Binary files /dev/null and b/src/main/resources/textures/player/rightOne.png differ diff --git a/src/main/resources/textures/player/rightTwo.png b/src/main/resources/textures/player/rightTwo.png new file mode 100644 index 0000000000000000000000000000000000000000..7cf375e6ef6a51ed56f485a03bb5988e21a7ed37 Binary files /dev/null and b/src/main/resources/textures/player/rightTwo.png differ diff --git a/src/main/resources/textures/player/sentinels/SentinelDown00.png b/src/main/resources/textures/player/sentinels/SentinelDown00.png new file mode 100644 index 0000000000000000000000000000000000000000..c2fb803e03f3d459baeb4188975192ef83aa3b71 Binary files /dev/null and b/src/main/resources/textures/player/sentinels/SentinelDown00.png differ diff --git a/src/main/resources/textures/player/sentinels/SentinelDown01.png b/src/main/resources/textures/player/sentinels/SentinelDown01.png new file mode 100644 index 0000000000000000000000000000000000000000..bb87d3b89b7a54dd62fde0c509d9d0ae09e549c4 Binary files /dev/null and b/src/main/resources/textures/player/sentinels/SentinelDown01.png differ diff --git a/src/main/resources/textures/player/upOne.png b/src/main/resources/textures/player/upOne.png new file mode 100644 index 0000000000000000000000000000000000000000..0e3134b32646f8587e59c68a0c62a9c8697876e1 Binary files /dev/null and b/src/main/resources/textures/player/upOne.png differ diff --git a/src/main/resources/textures/player/upTwo.png b/src/main/resources/textures/player/upTwo.png new file mode 100644 index 0000000000000000000000000000000000000000..2f698853e288792ce6879baa96d7999552fd17fe Binary files /dev/null and b/src/main/resources/textures/player/upTwo.png differ diff --git a/src/main/resources/textures/weapons/SwordDown.png b/src/main/resources/textures/weapons/SwordDown.png new file mode 100644 index 0000000000000000000000000000000000000000..dba0a85781e2e79ac38fc7004e892f7db82e04b5 Binary files /dev/null and b/src/main/resources/textures/weapons/SwordDown.png differ diff --git a/src/main/resources/textures/weapons/SwordLeft.png b/src/main/resources/textures/weapons/SwordLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..f83bcf7fa199d1e4fd97352a9688a78b6a3df757 Binary files /dev/null and b/src/main/resources/textures/weapons/SwordLeft.png differ diff --git a/src/main/resources/textures/weapons/SwordRight.png b/src/main/resources/textures/weapons/SwordRight.png new file mode 100644 index 0000000000000000000000000000000000000000..35bf135d41218bbef6c6409ab4bc99efad373754 Binary files /dev/null and b/src/main/resources/textures/weapons/SwordRight.png differ diff --git a/src/main/resources/textures/weapons/SwordSwingDown.png b/src/main/resources/textures/weapons/SwordSwingDown.png new file mode 100644 index 0000000000000000000000000000000000000000..3d160e5d8d518ca696860cdc77a90b11d2e7aec8 Binary files /dev/null and b/src/main/resources/textures/weapons/SwordSwingDown.png differ diff --git a/src/main/resources/textures/weapons/SwordSwingLeft.png b/src/main/resources/textures/weapons/SwordSwingLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..75dd39ee517e0714684c979e9e5052096fda3eaf Binary files /dev/null and b/src/main/resources/textures/weapons/SwordSwingLeft.png differ diff --git a/src/main/resources/textures/weapons/SwordSwingRight.png b/src/main/resources/textures/weapons/SwordSwingRight.png new file mode 100644 index 0000000000000000000000000000000000000000..a78877e88fdb0b55ffa4b5bb77f036f00f8793c1 Binary files /dev/null and b/src/main/resources/textures/weapons/SwordSwingRight.png differ diff --git a/src/main/resources/textures/weapons/SwordSwingUp.png b/src/main/resources/textures/weapons/SwordSwingUp.png new file mode 100644 index 0000000000000000000000000000000000000000..62ece9f708265ca4b3a9238c8437999825070f71 Binary files /dev/null and b/src/main/resources/textures/weapons/SwordSwingUp.png differ diff --git a/src/main/resources/textures/weapons/SwordUp.png b/src/main/resources/textures/weapons/SwordUp.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6ba9f3c3170669b0e24a4bcda8ebad952f42ca Binary files /dev/null and b/src/main/resources/textures/weapons/SwordUp.png differ diff --git a/src/main/resources/videos/=D.mp4 b/src/main/resources/videos/=D.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a83c91d46b68617ecf3c40b8f91ab67f930e53b6 Binary files /dev/null and b/src/main/resources/videos/=D.mp4 differ diff --git a/src/main/resources/videos/allMyFellas.mp4 b/src/main/resources/videos/allMyFellas.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..5371bd89089430d7fa4e467da0e857743a9cdd0b Binary files /dev/null and b/src/main/resources/videos/allMyFellas.mp4 differ diff --git a/src/main/resources/videos/async.mp4 b/src/main/resources/videos/async.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..4fef92ce7683b37e7e5dd01c5d6561fdaef4310c Binary files /dev/null and b/src/main/resources/videos/async.mp4 differ diff --git a/src/main/resources/videos/banana.mp4 b/src/main/resources/videos/banana.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..389d4987f86aa037d333fc7f2c84ecf9d1bc02f8 Binary files /dev/null and b/src/main/resources/videos/banana.mp4 differ diff --git a/src/main/resources/videos/basketball.mp4 b/src/main/resources/videos/basketball.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..067fcfbcc003a71f39c03b43e1882ceda9e9869c Binary files /dev/null and b/src/main/resources/videos/basketball.mp4 differ diff --git a/src/main/resources/videos/bear.mp4 b/src/main/resources/videos/bear.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a74b90e33e6a40e197818a80d149c4626a3bed7d Binary files /dev/null and b/src/main/resources/videos/bear.mp4 differ diff --git a/src/main/resources/videos/bobama.mp4 b/src/main/resources/videos/bobama.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..2052b4d842a398ac1788025ed579c5054fdad680 Binary files /dev/null and b/src/main/resources/videos/bobama.mp4 differ diff --git a/src/main/resources/videos/carl.mp4 b/src/main/resources/videos/carl.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..54685a745086afb498765ff1e681655871e0225e Binary files /dev/null and b/src/main/resources/videos/carl.mp4 differ diff --git a/src/main/resources/videos/cat.mp4 b/src/main/resources/videos/cat.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..f9c8f30586069bb8c693e3278a33c7e0e0c274ce Binary files /dev/null and b/src/main/resources/videos/cat.mp4 differ diff --git a/src/main/resources/videos/catEating.mp4 b/src/main/resources/videos/catEating.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..530059520bc6a7ec848fca40e27371fac757171a Binary files /dev/null and b/src/main/resources/videos/catEating.mp4 differ diff --git a/src/main/resources/videos/catJump.mp4 b/src/main/resources/videos/catJump.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..cce5bdb3f5ecb0d515d9802848cd742d8b6bcb56 Binary files /dev/null and b/src/main/resources/videos/catJump.mp4 differ diff --git a/src/main/resources/videos/catSitting.mp4 b/src/main/resources/videos/catSitting.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..28007e146999a02253044e4423819e80ec590c22 Binary files /dev/null and b/src/main/resources/videos/catSitting.mp4 differ diff --git a/src/main/resources/videos/chaCha.mp4 b/src/main/resources/videos/chaCha.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..700b233f8ce39926076fd7870bd6920d603c8d23 Binary files /dev/null and b/src/main/resources/videos/chaCha.mp4 differ diff --git a/src/main/resources/videos/cheezburger.mp4 b/src/main/resources/videos/cheezburger.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..4910d355b7ef46d080954028c2c9376ba7993a92 Binary files /dev/null and b/src/main/resources/videos/cheezburger.mp4 differ diff --git a/src/main/resources/videos/construction.mp4 b/src/main/resources/videos/construction.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..0d313d3f92093732300fcfe69d27f6583c66cb99 Binary files /dev/null and b/src/main/resources/videos/construction.mp4 differ diff --git a/src/main/resources/videos/credits.mp4 b/src/main/resources/videos/credits.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..410d261aba44faf7e6f2ba606393f76ba1ba526f Binary files /dev/null and b/src/main/resources/videos/credits.mp4 differ diff --git a/src/main/resources/videos/depression.mp4 b/src/main/resources/videos/depression.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..9e282df3676adcb28bc15d9238025fe6b37d9fcb Binary files /dev/null and b/src/main/resources/videos/depression.mp4 differ diff --git a/src/main/resources/videos/dog.mp4 b/src/main/resources/videos/dog.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..2f291192b17204d93730dede0be6a24f1fa26066 Binary files /dev/null and b/src/main/resources/videos/dog.mp4 differ diff --git a/src/main/resources/videos/dog2.mp4 b/src/main/resources/videos/dog2.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..4500f7ae5c2e9d8d1ba8a06fdfb60a0cc47f2d7b Binary files /dev/null and b/src/main/resources/videos/dog2.mp4 differ diff --git a/src/main/resources/videos/dogCheese.mp4 b/src/main/resources/videos/dogCheese.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..eb24b7b5f7b5d2eb6a72dcb0b3ac1d3281cd789b Binary files /dev/null and b/src/main/resources/videos/dogCheese.mp4 differ diff --git a/src/main/resources/videos/firework.mp4 b/src/main/resources/videos/firework.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..706941c2cde672b81881056aa759308d67f433c0 Binary files /dev/null and b/src/main/resources/videos/firework.mp4 differ diff --git a/src/main/resources/videos/frog.mp4 b/src/main/resources/videos/frog.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..e411b29309d38ffa3421e36ed3e9a3f4e9f9ad39 Binary files /dev/null and b/src/main/resources/videos/frog.mp4 differ diff --git a/src/main/resources/videos/gameboy.mp4 b/src/main/resources/videos/gameboy.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..68821d3565f0efcc9995b2f7afaa220b9ca786eb Binary files /dev/null and b/src/main/resources/videos/gameboy.mp4 differ diff --git a/src/main/resources/videos/gamecube.mp4 b/src/main/resources/videos/gamecube.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a60bade2b34051ffd295a22de564a6476adbe8fc Binary files /dev/null and b/src/main/resources/videos/gamecube.mp4 differ diff --git a/src/main/resources/videos/gta.mp4 b/src/main/resources/videos/gta.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..0259ca609572a35adb34f9c7293d49c9e97e37b8 Binary files /dev/null and b/src/main/resources/videos/gta.mp4 differ diff --git a/src/main/resources/videos/gtfo.mp4 b/src/main/resources/videos/gtfo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..536961ae8a9414f7b16ac646d4ceb0844d13a23f Binary files /dev/null and b/src/main/resources/videos/gtfo.mp4 differ diff --git a/src/main/resources/videos/holyCrap.mp4 b/src/main/resources/videos/holyCrap.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1f294f38de16731b5f4f5261ebebd0b2356380f3 Binary files /dev/null and b/src/main/resources/videos/holyCrap.mp4 differ diff --git a/src/main/resources/videos/horse.mp4 b/src/main/resources/videos/horse.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d4f6f7429a9f49344bf63f6602ac35131338b2a0 Binary files /dev/null and b/src/main/resources/videos/horse.mp4 differ diff --git a/src/main/resources/videos/imNotYou.mp4 b/src/main/resources/videos/imNotYou.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ade7b0800c3a53b242182a065022a91475ac367e Binary files /dev/null and b/src/main/resources/videos/imNotYou.mp4 differ diff --git a/src/main/resources/videos/kangaroo.mp4 b/src/main/resources/videos/kangaroo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..3cff449b6180fcbdbe367da02416525331ae94af Binary files /dev/null and b/src/main/resources/videos/kangaroo.mp4 differ diff --git a/src/main/resources/videos/legCat.mp4 b/src/main/resources/videos/legCat.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..82644243c6fd83c051092f40337df516edf8f6d0 Binary files /dev/null and b/src/main/resources/videos/legCat.mp4 differ diff --git a/src/main/resources/videos/lessGoo.mp4 b/src/main/resources/videos/lessGoo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a90f7c54729bcd5c78ad95f490520d97fab10920 Binary files /dev/null and b/src/main/resources/videos/lessGoo.mp4 differ diff --git a/src/main/resources/videos/lifeCouldBeMonke.mp4 b/src/main/resources/videos/lifeCouldBeMonke.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..13f8bf59c6c1d068156d65e04cdacf19070066c9 Binary files /dev/null and b/src/main/resources/videos/lifeCouldBeMonke.mp4 differ diff --git a/src/main/resources/videos/minecraftCat.mp4 b/src/main/resources/videos/minecraftCat.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..27e80735688963c86e27d81c6da25200da5854aa Binary files /dev/null and b/src/main/resources/videos/minecraftCat.mp4 differ diff --git a/src/main/resources/videos/minecraftCat2.mp4 b/src/main/resources/videos/minecraftCat2.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1e9366af84a9aa9f363655de9b313cab98e77fba Binary files /dev/null and b/src/main/resources/videos/minecraftCat2.mp4 differ diff --git a/src/main/resources/videos/monke.mp4 b/src/main/resources/videos/monke.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..980756e7cd8fa4c3c00d5a246ad179b143c1fae1 Binary files /dev/null and b/src/main/resources/videos/monke.mp4 differ diff --git a/src/main/resources/videos/msPuff.mp4 b/src/main/resources/videos/msPuff.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..42c91ab4bc895be00b0704f7eb73cded4c896d4f Binary files /dev/null and b/src/main/resources/videos/msPuff.mp4 differ diff --git a/src/main/resources/videos/muecke.mp4 b/src/main/resources/videos/muecke.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..c146f51e85f55df05f872781e4cfb09d5b222b87 Binary files /dev/null and b/src/main/resources/videos/muecke.mp4 differ diff --git a/src/main/resources/videos/myMind.mp4 b/src/main/resources/videos/myMind.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..e4616242924e020b3f536320e51a434aad0cdc69 Binary files /dev/null and b/src/main/resources/videos/myMind.mp4 differ diff --git a/src/main/resources/videos/pablo.mp4 b/src/main/resources/videos/pablo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..b5d84444d5036bbb1c99cea570fb8a75e078c6f3 Binary files /dev/null and b/src/main/resources/videos/pablo.mp4 differ diff --git a/src/main/resources/videos/pancake.mp4 b/src/main/resources/videos/pancake.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..5bda0b20ea3bd71adbfa4d47ed90dfaf88dad5e1 Binary files /dev/null and b/src/main/resources/videos/pancake.mp4 differ diff --git a/src/main/resources/videos/parkingTickets.mp4 b/src/main/resources/videos/parkingTickets.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..cfebfc02ba32074f6415fe842956776a5cf09f3e Binary files /dev/null and b/src/main/resources/videos/parkingTickets.mp4 differ diff --git a/src/main/resources/videos/pepe.mp4 b/src/main/resources/videos/pepe.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..51a5f0763924b4c623ac2b198d50b272b4758b15 Binary files /dev/null and b/src/main/resources/videos/pepe.mp4 differ diff --git a/src/main/resources/videos/pot.mp4 b/src/main/resources/videos/pot.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1aa9d7a0ce192a769e5096bcaf549234778a84c5 Binary files /dev/null and b/src/main/resources/videos/pot.mp4 differ diff --git a/src/main/resources/videos/rejectHumanity.mp4 b/src/main/resources/videos/rejectHumanity.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..6c2a377ca00e8f9381095c76661e5de75902b4f0 Binary files /dev/null and b/src/main/resources/videos/rejectHumanity.mp4 differ diff --git a/src/main/resources/videos/roomba.mp4 b/src/main/resources/videos/roomba.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..65a1e5aebe700b1b720182bf9ceaff3e6e160f88 Binary files /dev/null and b/src/main/resources/videos/roomba.mp4 differ diff --git a/src/main/resources/videos/russianKid.mp4 b/src/main/resources/videos/russianKid.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..08a7fe2015e28dc08e1ca6fbe907e46f691cec21 Binary files /dev/null and b/src/main/resources/videos/russianKid.mp4 differ diff --git a/src/main/resources/videos/sad.mp4 b/src/main/resources/videos/sad.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1868f52e473cad115b0dbe455c642211e5c50e81 Binary files /dev/null and b/src/main/resources/videos/sad.mp4 differ diff --git a/src/main/resources/videos/sadCat.mp4 b/src/main/resources/videos/sadCat.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..6daceb2c5e67a7b328aa541cb4f076249ce1fdf5 Binary files /dev/null and b/src/main/resources/videos/sadCat.mp4 differ diff --git a/src/main/resources/videos/sadHorse.mp4 b/src/main/resources/videos/sadHorse.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..dc6901a500652632c29c51d500b369044118ee58 Binary files /dev/null and b/src/main/resources/videos/sadHorse.mp4 differ diff --git a/src/main/resources/videos/seal.mp4 b/src/main/resources/videos/seal.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..5f5f39382d212d1b1cf15a9eaf44fb90ee06e4f9 Binary files /dev/null and b/src/main/resources/videos/seal.mp4 differ diff --git a/src/main/resources/videos/slippery.mp4 b/src/main/resources/videos/slippery.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..b26ecb1ceda0d65050f5244c98e76af43c717558 Binary files /dev/null and b/src/main/resources/videos/slippery.mp4 differ diff --git a/src/main/resources/videos/sony.mp4 b/src/main/resources/videos/sony.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..158c13874cb0cd60ddbc9903b2658d4c0cfd2ded Binary files /dev/null and b/src/main/resources/videos/sony.mp4 differ diff --git a/src/main/resources/videos/top10Cats.mp4 b/src/main/resources/videos/top10Cats.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..9e0d5b532c067b4b7f5cb91402b91b71c9150261 Binary files /dev/null and b/src/main/resources/videos/top10Cats.mp4 differ diff --git a/src/main/resources/videos/waaahhh.mp4 b/src/main/resources/videos/waaahhh.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1cba56386170639d4ad38f06caf09a5520d743de Binary files /dev/null and b/src/main/resources/videos/waaahhh.mp4 differ diff --git a/src/main/resources/videos/wolf.mp4 b/src/main/resources/videos/wolf.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..353523836c06ad5601edb60be81a99ebc644675e Binary files /dev/null and b/src/main/resources/videos/wolf.mp4 differ diff --git a/src/main/resources/videos/wooOOoo.mp4 b/src/main/resources/videos/wooOOoo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..094c0d8df46be0db2aa87e3294d3fdfbf4ee4bd3 Binary files /dev/null and b/src/main/resources/videos/wooOOoo.mp4 differ diff --git a/src/main/resources/videos/yoinkySploinky.mp4 b/src/main/resources/videos/yoinkySploinky.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ea88b4578ccc74f0228669792b4266b9860e3f0c Binary files /dev/null and b/src/main/resources/videos/yoinkySploinky.mp4 differ diff --git a/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PersistenceTest.java b/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PersistenceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..79b599da6c201b66ffe5d1c21293f44b9ee244e4 --- /dev/null +++ b/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PersistenceTest.java @@ -0,0 +1,48 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.DatabaseException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.SQLException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.Before; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class PersistenceTest { + + private static final Logger log = LogManager.getLogger(PersistenceTest.class); + Persistence persistenceSingleton; + + OracleDB inst = new OracleDB(); + + @Before + public void setup() throws SQLException { + persistenceSingleton = Persistence.getInstance(); + persistenceSingleton.db = inst; + ArrayList<MapData> maps = new ArrayList<MapData>(); + maps.add(new MapData("09a02b54d05b5b7ebc29a4383ca12d3dda846b72", "Arena1", 18, 18, "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + maps.add(new MapData("0ab15557ab6dc4be60dfe6a9b0288bac3036bd97", "Arena2", 18, 18, "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + when(inst.getCoreMaps()).thenReturn(maps); + } + + @Test + void updateCoreMaps() throws RuntimeException, DatabaseException { + persistenceSingleton.updateCoreMaps(); + assertEquals("09a02b54d05b5b7ebc29a4383ca12d3dda846b72", persistenceSingleton.getCoreMaps().get(0).getMapID()); + assertEquals("0ab15557ab6dc4be60dfe6a9b0288bac3036bd97", persistenceSingleton.getCoreMaps().get(1).getMapID()); + } + + @Test + void loadPlayerStatistics() { + } + + + + +} \ No newline at end of file diff --git a/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/CryptoUtilsTest.java b/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/CryptoUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6fe7a78190c6e19cc745d4aaec49d281970665cf --- /dev/null +++ b/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/CryptoUtilsTest.java @@ -0,0 +1,101 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities; + +//import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.CryptoException; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.CryptoException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.*; + +import java.io.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class CryptoUtilsTest { + private static File encryptiondecryptiontestFile = new File("src\\main\\resources\\database\\encryptiondecryptiontestFile.txt"); + private static File encryptedtestFile = new File("src\\main\\resources\\database\\encrypted;encryptedtestFile.txt"); + private static boolean alreadyencrypted; + private static int encryptionreturn; + private static String text=""; + private static String[] parts; + private static String testtext = "Hier steht ein Testtext."; + private static boolean multipleencryptions = false; + private static final Logger log = LogManager.getLogger(CryptoUtilsTest.class); + + @BeforeEach + void beforeEachTest(TestInfo testInfo) { + log.info(() -> String.format("About to execute [%s]", + testInfo.getDisplayName())); + } + @AfterEach + void afterEachTest(TestInfo testInfo) { + log.info(() -> String.format("Finished executing [%s]", + testInfo.getDisplayName())); + } + @Test + void encryptDecryptiontest() throws IOException { + BufferedWriter writer = new BufferedWriter(new FileWriter(encryptiondecryptiontestFile)); + writer.write(testtext); + writer.close(); + try { + CryptoUtils.encrypt(encryptiondecryptiontestFile, true); + parts = CryptoUtils.decrypt(encryptiondecryptiontestFile); + text = parts[0]; + System.out.println(text); + } catch (CryptoException ex) { + System.out.println(ex.getMessage()); + ex.printStackTrace(); + } + assertEquals(testtext,text); + } + @RepeatedTest(3) + void repeatedCheckFileEncryptingMultipleTimes() throws IOException { + BufferedWriter writer = new BufferedWriter(new FileWriter(encryptiondecryptiontestFile)); + writer.write(testtext); + writer.close(); + try { + encryptionreturn = CryptoUtils.encrypt(encryptiondecryptiontestFile, true); + parts = CryptoUtils.decrypt(encryptiondecryptiontestFile); + text = parts[0]; + System.out.println(text); + } catch (CryptoException ex) { + System.out.println(ex.getMessage()); + ex.printStackTrace(); + } + assertEquals(encryptionreturn, 0); + assertEquals(testtext,text); //Change + } + @Test + void checkFileEncryptingOnce() throws IOException { + BufferedWriter writer = new BufferedWriter(new FileWriter(encryptiondecryptiontestFile)); + writer.write(testtext); + writer.close(); + try { + encryptionreturn = CryptoUtils.encrypt(encryptiondecryptiontestFile, false); + parts = CryptoUtils.decrypt(encryptiondecryptiontestFile); + text = parts[0]; + System.out.println(text); + } catch (CryptoException ex) { + System.out.println(ex.getMessage()); + ex.printStackTrace(); + } + assertEquals(encryptionreturn, 1); + assertEquals(testtext,text); //Change + } + @Test + void checkIfFileAlreadyEncrypted(){ + alreadyencrypted = CryptoUtils.check_if_file_already_encrypted(encryptedtestFile); + assertTrue(alreadyencrypted); + } + @Test + void checkIfFileNotYetEncrypted(){ + alreadyencrypted = CryptoUtils.check_if_file_already_encrypted(encryptiondecryptiontestFile); + assertFalse(alreadyencrypted); + } + @Test + void exceptionTestingFileNotFound() { + CryptoException exception = assertThrows(CryptoException.class, () -> + CryptoUtils.decrypt(new File("src/main/resources/database/thisFileShouldn'tExist"))); + assertEquals("Error encrypting/decrypting file", exception.getMessage()); + } +} diff --git a/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/ParserTest.java b/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/ParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6cbf6fc345bc7da7639d7b61c0299c9b89ac6930 --- /dev/null +++ b/src/test/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Utilities/ParserTest.java @@ -0,0 +1,269 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Exceptions.ParserException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.PlayerStatistics; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.*; +class ParserTest { + + @ParameterizedTest + @ValueSource(strings = {"Player1", + "Player2", + "0123456789012345678901234567890123456789"}) + void usernameValid(String test){ + assertDoesNotThrow(() -> Parser.usernameValid(test)); + } + + @Test + void usernameInvalid() { + ParserException testMe = assertThrows(ParserException.class, () -> Parser.usernameValid("lol")); + assertTrue(testMe.getMessage().contains("Username too short! Min length is 4 characters.")); + + testMe = assertThrows(ParserException.class, () -> Parser.usernameValid("01234567890123456789012345678901234567890")); + assertTrue(testMe.getMessage().contains("Username too long! Max length is 40 characters.")); + + testMe = assertThrows(ParserException.class, () -> Parser.usernameValid("SELECT * FROM")); + assertTrue(testMe.getMessage().contains("Forbidden characters used! Only user letters A-Z or numbers 0-9 or symbols '-' or '_' !")); + } + + @ParameterizedTest + @ValueSource(strings = {"pw123456", + "Passwort", + "0123456789012345678901234567890123456789"}) + void passwordValid(String test){ + assertDoesNotThrow(() -> Parser.passwordValid(test)); + } + + @Test + void passwordInvalid() { + ParserException testMe = assertThrows(ParserException.class, () -> Parser.passwordValid("lol")); + assertTrue(testMe.getMessage().contains("Password too short! Min length is 4 characters.")); + + testMe = assertThrows(ParserException.class, () -> Parser.passwordValid("01234567890123456789012345678901234567890")); + assertTrue(testMe.getMessage().contains("Password too long! Max length is 40 characters.")); + + testMe = assertThrows(ParserException.class, () -> Parser.passwordValid("SELECT * FROM")); + assertTrue(testMe.getMessage().contains("Forbidden characters used! Only user letters A-Z or numbers 0-9 or symbols '-' or '_' !")); + } + + @ParameterizedTest + @ValueSource(strings = {"012345678901234567890123456789", + "de_dust", + "Ziba-Tower"}) + void mapNameValid(String test){ + assertDoesNotThrow(() -> Parser.mapNameValid(test)); + } + + @Test + void mapNameInvalid() { + ParserException testMe = assertThrows(ParserException.class, () -> Parser.mapNameValid("lol")); + assertTrue(testMe.getMessage().contains("Map-Name too short! Min length is 4 characters.")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapNameValid("0123456789012345678901234567890")); + assertTrue(testMe.getMessage().contains("Map-Name too long! Max length is 30 characters.")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapNameValid("SELECT * FROM")); + assertTrue(testMe.getMessage().contains("Forbidden characters used! Only user letters A-Z or numbers 0-9 or symbols '-' or '_' !")); + } + + @ParameterizedTest + @ValueSource(strings = {"a593cafd1d061f0f463a2d2051bf4718aaaf5c48", + "e559d8fbb53b333f5839cb3c6c0c515395afe344", + "a593cafd1d061f0f463a2d2051bf4718aaaf5c48"}) + void sha1HashValid(String test){ + assertDoesNotThrow(() -> Parser.sha1HexHashValid(test)); + } + + @Test + void sha1HashInvalid() { + + ParserException testMe = assertThrows(ParserException.class, () -> Parser.sha1HexHashValid("01234567890123456789012345678901234567890")); + assertTrue(testMe.getMessage().contains("SHA1 hash length not correct. Must have length of 40 characters!")); + + testMe = assertThrows(ParserException.class, () -> Parser.sha1HexHashValid("012345678901234567890123456789012345678")); + assertTrue(testMe.getMessage().contains("SHA1 hash length not correct. Must have length of 40 characters!")); + + testMe = assertThrows(ParserException.class, () -> Parser.sha1HexHashValid("XYZ3cafd1d061f0f463a2d2051bf4718aaaf5c48")); + assertTrue(testMe.getMessage().contains("Forbidden characters used! SHA1 hash only consists out of letters a-f and/or numbers 0-9!")); + } + + @ParameterizedTest + @ValueSource(strings = {"255.255.255.255", + "0.0.0.0", + "12.12.12.1", + "localhost"}) + void ipAddressValid(String test){ + assertDoesNotThrow(() -> Parser.ipAddressValid(test)); + } + + @Test + void ipAddressInvalid() { + + ParserException testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("255.255.255.2555")); + assertTrue(testMe.getMessage().contains("IP-Address too long. Must have maximum length of 15 characters including octet dividers (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("0.0.12")); + assertTrue(testMe.getMessage().contains("IP-Address too short. Must have minimum length of 7 characters including octet dividers (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid(".25.255.25")); + assertTrue(testMe.getMessage().contains("IP-Address must not start nor end with octet dividers (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("25.255.25.")); + assertTrue(testMe.getMessage().contains("IP-Address must not start nor end with octet dividers (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("12.3.0.12.12")); + assertTrue(testMe.getMessage().contains("IP-Address must contain exactly 3 octet dividers (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("12.12..2")); + assertTrue(testMe.getMessage().contains("IP-Address must not contain two or more consecutive dividers (.) without number in between!")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("f1.12.12.12")); + assertTrue(testMe.getMessage().contains("IP address must consist out of numbers 0-9 and separators (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("12.12.12.1f")); + assertTrue(testMe.getMessage().contains("IP address must consist out of numbers 0-9 and separators (.) !")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("256.12.12.12")); + assertTrue(testMe.getMessage().contains("Octets of IP-address must not exceed 255!")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("12.12.12.256")); + assertTrue(testMe.getMessage().contains("Octets of IP-address must not exceed 255!")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("2500.12.12.12")); + assertTrue(testMe.getMessage().contains("Octets of IP-address must not exceed 255!")); + + testMe = assertThrows(ParserException.class, () -> Parser.ipAddressValid("12.12.12.2500")); + assertTrue(testMe.getMessage().contains("Octets of IP-address must not exceed 255!")); + } + + @ParameterizedTest + @ValueSource(strings = {"12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12", + "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12", + "12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12"}) + void mapDataValid(String test){ + assertDoesNotThrow(() -> Parser.mapDataValid(test)); + } + + @Test + void mapDataInvalid() { + ParserException testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - mapData String must not exceed length of 967 chars including spaces for 18x18 Tiles map!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("1 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 8 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - minimum length of mapData String must be 715 chars including spaces for 18x18 Tiles map!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid(" 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - must not start nor end with space!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 ")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - must not start nor end with space!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - must not contain two or more consecutive spaces without number in between!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - must not contain two or more consecutive spaces without number in between!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 13")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - number of spaces must be 323!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("10 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - number of spaces must be 323!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("a2 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - must consist out of numbers 0-9 and space as separator!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1d")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - must consist out of numbers 0-9 and space as separator!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("42 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Tile number must be between 0 and 29!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 42")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Tile number must be between 0 and 29!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("22 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Top-Line must be border tiles!")); + + //don't forget to reach minimum length with test String! Otherwise, wrong Exception will be thrown! + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 5 12 1 1 1 1 1 12 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Top-Line must be border tiles!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 22")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Bottom-Line must be border tiles!")); + + //don't forget to reach minimum length with test String! Otherwise, wrong Exception will be thrown! + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 12 1 1 1 1 1 1 1 1 12 8 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Bottom-Line must be border tiles!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 22 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Left Edge must be border tiles!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 22 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Left Edge must be border tiles!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 22 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Right Edge must be border tiles!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 22 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Right Edge must be border tiles!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 25 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Player spawn top left must use walkable tile!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 25 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Player spawn top right must use walkable tile!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 25 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Player spawn bottom left must use walkable tile!")); + + testMe = assertThrows(ParserException.class, () -> Parser.mapDataValid("12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 25 12 12 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 12")); + assertTrue(testMe.getMessage().contains("Map-Data corrupted - Player spawn bottom right must use walkable tile!")); + } + + @Test + void statsValid(){ + PlayerStatistics stats = new PlayerStatistics(0, 0, 0, 0, 0, 0); + assertDoesNotThrow(() -> Parser.playerStatsValid(stats)); + } + + @Test + void statsInvalid(){ + ParserException testMe = assertThrows(ParserException.class, () -> Parser.playerStatsValid(new PlayerStatistics(-1, 0, 0, 0, 0, 0))); + assertTrue(testMe.getMessage().contains("Player statistics data corrupted - Minimum value for lost games is 0!")); + + testMe = assertThrows(ParserException.class, () -> Parser.playerStatsValid(new PlayerStatistics(0, -1, 0, 0, 0, 0))); + assertTrue(testMe.getMessage().contains("Player statistics data corrupted - Minimum value for won games is 0!")); + + testMe = assertThrows(ParserException.class, () -> Parser.playerStatsValid(new PlayerStatistics(0, 0, -1, 0, 0, 0))); + assertTrue(testMe.getMessage().contains("Player statistics data corrupted - Minimum value for kills is 0!")); + + testMe = assertThrows(ParserException.class, () -> Parser.playerStatsValid(new PlayerStatistics(0, 0, 0, -1, 0, 0))); + assertTrue(testMe.getMessage().contains("Player statistics data corrupted - Minimum value for deaths is 0!")); + + testMe = assertThrows(ParserException.class, () -> Parser.playerStatsValid(new PlayerStatistics(0, 0, 0, 0, -1, 0))); + assertTrue(testMe.getMessage().contains("Player statistics data corrupted - Minimum value for destroyed blocks is 0!")); + + testMe = assertThrows(ParserException.class, () -> Parser.playerStatsValid(new PlayerStatistics(0, 0, 0, 0, 0, -1))); + assertTrue(testMe.getMessage().contains("Player statistics data corrupted - Minimum value for ingame time is 0 seconds!")); + } + + @ParameterizedTest + @ValueSource(ints = {0, 100, 50}) + void volumeValid(int test){ + assertDoesNotThrow(() -> Parser.volumeValid(test)); + } + + @Test + void volumeInvalid(){ + ParserException testMe = assertThrows(ParserException.class, () -> Parser.volumeValid(-1)); + assertTrue(testMe.getMessage().contains("Volume must be between 0 and 100!")); + + testMe = assertThrows(ParserException.class, () -> Parser.volumeValid(101)); + assertTrue(testMe.getMessage().contains("Volume must be between 0 and 100!")); + } + +} \ No newline at end of file