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/misc.xml b/.idea/misc.xml index e7a7ee4e1a8bb936f74453926c8d1206f86e405b..f33e38f0f5d3f09852522d1e2b2b2325f91a3785 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -7,7 +7,7 @@ </list> </option> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="openjdk-21" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="21" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/out" /> </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/README.md b/README.md index 69625de7934d607289e90646606803cc8faefb41..36649891de9120708f42d1e77509733f2abd6a23 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ ## Hier könnte ihre Werbung stehn + +### Known issues: + - Videos sometimes don't load in Windows 11 especially on weaker systems + - SQL server is very slow (thanks Oracle) diff --git a/pom.xml b/pom.xml index 231758b8295c2602c5156431d7eec666619df078..00cecae4b603bb2ef7a769e8effa5db5010b47d5 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> @@ -51,6 +65,43 @@ <version>19.0.2.1</version> </dependency> + <dependency> + <groupId>com.jtransc</groupId> + <artifactId>jtransc-rt</artifactId> + <version>0.5.0-ALPHA4</version> + </dependency> + + <!--<dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>4.3.24.RELEASE</version> + </dependency>--> + + <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> <build> diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java index 3dc79401a4a89941e5bcffa4b07dacbb45c14817..be1256f441fa09604694e890557db0bd53131531 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CommunityMapController.java @@ -49,7 +49,7 @@ public class CommunityMapController implements Initializable { // TODO: create map preview @FXML - private void backButton() { // for some reason compiler doesn't recognize method usage when 'back' is used as method name. Any other method name works however + private void backButton() { parent.getChildren().clear(); parent.getChildren().add(new SceneLoader().loadScene("MapForge")); } diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/CreateAccountController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CreateAccountController.java new file mode 100644 index 0000000000000000000000000000000000000000..826cb76c7ba083c1cd0608fe5d6d83e28ef68733 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/CreateAccountController.java @@ -0,0 +1,86 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; +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.Label; +import javafx.scene.control.RadioButton; +import javafx.scene.control.TextField; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.VBox; + +import java.net.URL; +import java.util.ResourceBundle; + +public class CreateAccountController implements Initializable { + @FXML + private VBox parent; + @FXML + private RadioButton local; + @FXML + private ToggleGroup statistics; + @FXML + private TextField playerName, password; + @FXML + private Label errorMessage, passwordLabel; + + String selectedButton; + SceneLoader sceneLoader = new SceneLoader(); + Persistence persistence = Persistence.getInstance(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + getSelected(); + } + + private void getSelected() { + statistics.selectedToggleProperty().addListener((observableValue, toggle, t1) -> { + if (statistics.getSelectedToggle() != null) { + RadioButton selectedToggle = (RadioButton) statistics.getSelectedToggle(); + selectedButton = selectedToggle.getText(); + System.out.println(selectedButton); + } + if (local.isSelected()) { + password.setEditable(false); + password.setText(""); + passwordLabel.setStyle("-fx-text-fill: rgba(0, 0, 0, 0.3)"); + password.setStyle("-fx-border-color: rgba(0, 0, 0, 0.3)"); + } else { + passwordLabel.setStyle("-fx-text-fill: black"); + password.setEditable(true); + password.setStyle("-fx-border-color: black"); + } + }); + } + + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } + + @FXML + private void create() { + AccountType accountType; + if (selectedButton.equals("Local")) { + accountType = AccountType.LOCAL; + } else { + accountType = AccountType.ONLINE; + } + try { + persistence.createAccount(playerName.getText(), password.getText(), accountType); + persistence.resetPlayerStatistics(); + persistence.loadPlayerStatistics(); + switchScene("MainMenu"); + } catch (DatabaseException e) { + errorMessage.setText(e.getMessage()); + } + } + + @FXML + private void back() { + switchScene("PlayerCreateScene"); + } +} 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 1743c0963b8d10d5aaaba03cfc159bb23a31553f..96304c946ce51211f11fec18c3d44e508d751931 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java @@ -2,6 +2,10 @@ package de.hdm_stuttgart.battlearena.Controller; import de.hdm_stuttgart.battlearena.Controller.Utilities.ScreenClasses; import de.hdm_stuttgart.battlearena.Controller.Utilities.ScreenDimensionCalculator; +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; @@ -56,11 +60,15 @@ public class GameSceneController implements Initializable { InputHandler inputHandler = InputHandler.getInstance(); + RuntimeInfo runtimeInfo = RuntimeInfo.getInstance(); + + GameMode gameMode = runtimeInfo.getGameMode(); + IEntity player; IEntity enemy; - EntityClass playerClass = EntityClass.HUMAN; - EntityClass enemyClass = EntityClass.HUMAN; + EntityClass playerOneClass = runtimeInfo.getPlayerOneClass(); + EntityClass playerTwoClass = runtimeInfo.getPlayerTwoClass(); TileManager tileManager; @@ -72,7 +80,7 @@ public class GameSceneController implements Initializable { "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 1 1 2 2 4 3 3 1 4 3 3 3 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 " + @@ -85,7 +93,7 @@ public class GameSceneController implements Initializable { "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 = 5; + int diffTileCount = 6; int scaledTileSize = 48; @@ -139,11 +147,20 @@ public class GameSceneController implements Initializable { graphicsContext2D = canvas2D.getGraphicsContext2D(); graphicsContext2D.setImageSmoothing(false); - player = EntityFactory.createEntity(EntityType.PLAYER, graphicsContext2D, inputHandler, playerClass, this); - enemy = EntityFactory.createEntity(EntityType.ENEMY_PLAYER, graphicsContext2D, inputHandler, enemyClass, this); + 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) { @@ -160,18 +177,25 @@ public class GameSceneController implements Initializable { 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; } @@ -179,4 +203,4 @@ public class GameSceneController implements Initializable { public int getScaledTileSize() { return scaledTileSize; } -} \ No newline at end of file +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java index 2c4472104e35751cedb56601d0b5f6b13f72e278..6a99c538617e193578e4a80332c60baa7c0bcf5e 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/IntroController.java @@ -1,6 +1,7 @@ package de.hdm_stuttgart.battlearena.Controller; import de.hdm_stuttgart.battlearena.Controller.Utilities.CreateMediaPlayer; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; @@ -8,6 +9,8 @@ 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; @@ -27,6 +30,8 @@ public class IntroController implements Initializable { 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) { @@ -59,10 +64,9 @@ public class IntroController implements Initializable { } private void videoEnd() { -// TODO: check if player exists try { mediaPlayer.dispose(); - introParent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/PlayerCreateScene.fxml")))); + introParent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/LoadingScreen.fxml")))); } catch (IOException e) { throw new RuntimeException(); } diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/LoadingScreenController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/LoadingScreenController.java new file mode 100644 index 0000000000000000000000000000000000000000..a7aa8a685f37286da95ba3edda224fc8c78f30d4 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/LoadingScreenController.java @@ -0,0 +1,143 @@ +package de.hdm_stuttgart.battlearena.Controller; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; +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.ThreadStartup1; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ThreadStartup2; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.geometry.Rectangle2D; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; +import javafx.scene.layout.BorderPane; +import javafx.stage.Screen; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.net.URL; +import java.util.*; + +public class LoadingScreenController implements Initializable { + @FXML + private Label tips; + @FXML + private BorderPane parent; + @FXML + private ImageView logo, throbber; + + boolean isReady = false; + private int counter = 0; + private boolean statsLoaded = false; + private final String[] loadingTips = { + "Did you know, that since 2009, Martin isn't on the FBI list?", + "BattleArena is actually derived from the combination of the words 'Battle' and 'Arena'.", + "Yannik ist over 1,80m tall.", + "Electricity is a vital part to play this game.", + "There is a typo in one of the tips.", + "Over 1000 people play games every day.", + "A lot of people believe Nikola Tesla was the first to invent electricity but some clouds beat him to it.", + "Monkeys usually don't have keys.", + "While you're reading this, you've wasted 2 seconds.", + "If you die, you're dead.", + "If you take damage, you loose hp.", + "Did you know that Java is also an Island?", + "This loading screen might never end.", + "Get the BattleArena Ultimate-Edition for only 420,69€.", + "To move left, press one of the keys on your keyboard.", + "To use the gravity-gun, close the game and start Half Life 2.", + "Buying this game was a good decision! (no refunds)." + }; + + private final List<String> shuffledTips = Arrays.asList(loadingTips); + private static final Logger log = LogManager.getLogger(Persistence.class); + Rectangle2D screen = Screen.getPrimary().getVisualBounds(); + ThreadStartup1 thread1 = new ThreadStartup1(); + ThreadStartup2 thread2 = new ThreadStartup2(); + Persistence persistence = Persistence.getInstance(); + + Thread tipsThread = new Thread(() -> { + try { + setLoadingTips(); + } catch (InterruptedException e) { + log.info("Data finished loading"); + } + }); + + Thread loadingDataThread = new Thread(() -> { + try { + Thread.sleep(4000); + loadData(); + } catch (IOException e) { + throw new RuntimeException(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + Collections.shuffle(shuffledTips); + setImages(); + + tipsThread.start(); + thread1.start(); + + boolean threadOneIsRunning = true, threadTwoIsRunning = false; + while (!isReady) { + if (!thread1.isAlive() && threadOneIsRunning) { + thread2.start(); + threadTwoIsRunning = true; + threadOneIsRunning = false; + } + if (!thread2.isAlive() && threadTwoIsRunning) { + isReady = true; + } + } + loadingDataThread.start(); + } + + private void setImages() { + logo.setTranslateY(screen.getHeight() * 0.08); + System.out.println(screen.getHeight()); + logo.setFitWidth(screen.getWidth() * 0.3); + throbber.setFitWidth(screen.getWidth() * 0.07); + logo.setPreserveRatio(true); + throbber.setPreserveRatio(true); + } + + private void setLoadingTips() throws InterruptedException { + while (!statsLoaded && counter < loadingTips.length) { + String nextTip = shuffledTips.get(counter); + Platform.runLater(() -> tips.setText(nextTip)); // JavaFX method to queue a task that needs to be executed on the JavaFX application thread (update ui components) + counter++; + +// check if statsLoaded is still false before sleeping + if (!statsLoaded) { + if (nextTip.length() > 60) { + Thread.sleep(6000); + } else { + Thread.sleep(3500); + } + setLoadingTips(); + } + } + } + + private void loadData() throws IOException { + if (persistence.getAccount().getAccountType() != AccountType.NONE) { + try { + persistence.loadPlayerStatistics(); + statsLoaded = true; + } catch (DatabaseException e) { + log.error(e); + } + } + + Platform.runLater(tipsThread::interrupt); + parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/MenuBorderPane.fxml")))); + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/LoginController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/LoginController.java new file mode 100644 index 0000000000000000000000000000000000000000..6e3fd79dd026c1b1db894041b1782058cd819ab8 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/LoginController.java @@ -0,0 +1,55 @@ +package de.hdm_stuttgart.battlearena.Controller; + +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.Exceptions.ParserException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.Parser; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.VBox; + +import java.security.NoSuchAlgorithmException; + +public class LoginController { + @FXML + private VBox parent; + @FXML + private TextField playerName, password; + @FXML + private Label errorMessage; + + SceneLoader sceneLoader = new SceneLoader(); + Persistence persistence = Persistence.getInstance(); + + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } + + @FXML + private void login() { + errorMessage.setText("Loading an eternity because of slow SQL server..."); + thread.start(); + } + + Thread thread = new Thread(() -> { + try { + persistence.login(playerName.getText(), password.getText()); + persistence.loadPlayerStatistics(); + Platform.runLater(() -> switchScene("MainMenu")); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (DatabaseException e) { + Platform.runLater(() -> errorMessage.setText(e.getMessage())); + } + }); + + @FXML + private void back() { + thread.interrupt(); + switchScene("PlayerCreateScene"); + } +} 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 c71e7fc4804f06df9f0249a24e102b057c55ba7a..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,6 +1,8 @@ package de.hdm_stuttgart.battlearena.Controller; 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; @@ -17,6 +19,7 @@ public class MainMenuController implements Initializable { @FXML private Button exitButton; private final SceneLoader sceneLoader = new SceneLoader(); + private final Persistence persistence = Persistence.getInstance(); private void switchScene(String name) { parent.getChildren().clear(); @@ -44,7 +47,9 @@ public class MainMenuController implements Initializable { } @FXML - private void exit() { + private void exit() throws DatabaseException { + persistence.savePlayerStatistics(); + persistence.saveSettings(); Stage stage = (Stage) exitButton.getScene().getWindow(); stage.close(); } diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java index 7f57a6dd566a493f12e2c9ffdea4772df823f130..784361391329dab062e1c64e5aee944381861ff1 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MapForgeController.java @@ -2,6 +2,8 @@ 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; @@ -13,6 +15,7 @@ public class MapForgeController { @FXML private VBox parent; SceneLoader sceneLoader = new SceneLoader(); + private final Persistence persistence = Persistence.getInstance(); @FXML private void mapEditorScene() { @@ -30,13 +33,9 @@ public class MapForgeController { } @FXML - private void updateMapScene() { - try { - parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/PlayerCreateScene.fxml")))); - MusicPlayerSingleton.getInstance().getMediaPlayer().dispose(); - } catch (IOException e) { - throw new RuntimeException(); - } + private void updateMapScene() throws DatabaseException { + persistence.updateCoreMaps(); +// TODO: set message label if update was successful or not } @FXML 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 index 47fa1988d8563ef57198d22de1ddc62e8a73ce27..7ae68807db90c91640c155306f900445949eb5ca 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/MenuBorderPaneController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/MenuBorderPaneController.java @@ -3,6 +3,8 @@ 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.ENUMs.AccountType; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Persistence; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.geometry.Rectangle2D; @@ -32,17 +34,22 @@ public class MenuBorderPaneController implements Initializable { private final SceneLoader sceneLoader = new SceneLoader(); private MediaPlayer musicPlayer, mediaPlayer; private MediaView mediaView; - private final String[] videoFiles = {"allMyFellas", "wooOOoo", "myMind", "dogCheese", "gta", "cat", "bobama", "roomba", "firework", "cheezburger", - "kangaroo", "lifeCouldBeMonke", "imNotYou", "parkingTickets", "russianKid", "rejectHumanity", "horse", "catSitting", "pablo", "holyCrap", - "lessGoo", "sadCat", "basketball", "msPuff", "=D", "banana", "chaCha", "async", "sadHorse", "minecraftCat", "muecke", "top10Cats", "dog", - "pot", "mineCraftCat2", "bear", "pancake", "frog", "gtfo", "carl", "dog2", "slippery", "wolf", "legCat", "sad", "waaahhh"}; + private final String[] videoFiles = {"depression", "allMyFellas", "wooOOoo", "myMind", "dogCheese", "gta", "cat", "bobama", "roomba", "firework", "cheezburger", + "kangaroo", "lifeCouldBeMonke", "seal", "rolling", "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")); + if (Persistence.getInstance().getAccount().getAccountType() == AccountType.NONE) { + center.getChildren().add(sceneLoader.loadScene("PlayerCreateScene")); + } else { + 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); @@ -107,6 +114,7 @@ public class MenuBorderPaneController implements Initializable { 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/PlaceholderController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlaceholderController.java new file mode 100644 index 0000000000000000000000000000000000000000..a018d9e82ae12e61b22762484397f479597ff0c1 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlaceholderController.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 PlaceholderController 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/PlayerCreateController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayerCreateController.java index 68dfd4029aad7452c5d19d82fdfcaec3f0e8435e..56f73045145a2c36b567f177e7423cd86f0bcd07 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayerCreateController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/PlayerCreateController.java @@ -1,51 +1,34 @@ package de.hdm_stuttgart.battlearena.Controller; -import de.hdm_stuttgart.battlearena.Controller.Utilities.CreateMediaPlayer; +import de.hdm_stuttgart.battlearena.Controller.Utilities.SceneLoader; 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 javafx.scene.layout.VBox; +import javafx.stage.Stage; -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; +public class PlayerCreateController { @FXML - private Button button; - private MediaPlayer mediaPlayer, musicPlayer; + private VBox parent; - @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'"); + SceneLoader sceneLoader = new SceneLoader(); - 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); + private void switchScene(String name) { + parent.getChildren().clear(); + parent.getChildren().add(sceneLoader.loadScene(name)); + } - 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(); - } - }); + @FXML + private void createScene() { + switchScene("CreateAccount"); + } + + @FXML + private void loginScene() { + switchScene("Login"); + } + + @FXML + private void exit() { + Stage stage = (Stage) parent.getScene().getWindow(); + stage.close(); } } diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java index a3c7526665111d073af465d5c74599952442b63b..836c9cf9df4f8f17b7633fac1c0867d9b00bac02 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SettingsController.java @@ -2,6 +2,7 @@ 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; @@ -17,14 +18,16 @@ public class SettingsController implements Initializable { @FXML private VBox parent; @FXML - private Slider musicVolume, sfxVolume; + private Slider musicSlider, sfxSlider; SceneLoader sceneLoader = new SceneLoader(); - public double music; + private int musicVolume, sfxVolume; MusicPlayerSingleton musicPlayer = MusicPlayerSingleton.getInstance(); + Persistence persistence = Persistence.getInstance(); @Override public void initialize(URL url, ResourceBundle resourceBundle) { setMusicVolume(); + setSfxVolume(); } @FXML @@ -35,22 +38,34 @@ public class SettingsController implements Initializable { @FXML private void backButton() { + switchScene("MainMenu"); + } + + @FXML + private void account() { + switchScene("PlayerCreateScene"); + } + + private void switchScene(String name) { parent.getChildren().clear(); - parent.getChildren().add(sceneLoader.loadScene("MainMenu")); + parent.getChildren().add(sceneLoader.loadScene(name)); } private void setMusicVolume() { -// need a runtime database to save volume - musicVolume.valueProperty().addListener((observableValue, oldValue, newValue) -> { - setMusic(musicVolume); - System.out.println(music); + 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 setMusic(Slider slider) { - slider.valueProperty().addListener(((observableValue, oldValue, newValue) -> { - music = newValue.doubleValue() / 100; - musicPlayer.getMediaPlayer().setVolume(music); + 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 index 226c55739e694653d84fc674d240ff5667a5e980..5276d92651d747ed1ad42b757b0d3c3fde9c241a 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/SkinSelectionController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/SkinSelectionController.java @@ -1,5 +1,6 @@ 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; @@ -53,11 +54,7 @@ public class SkinSelectionController implements Initializable { @FXML private void gameScene() { - try { -// MusicPlayerSingleton.getInstance().getMediaPlayer().dispose(); - parent.getScene().setRoot(FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/GameScene.fxml")))); - } catch (IOException e) { - throw new RuntimeException(); - } + 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 index 009c8a94b5f4a68c3c1b21ddcf194621be698a9c..ee8ccd517fc9c48f3178e792d136dba3f20783e8 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/StatisticsController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/StatisticsController.java @@ -1,6 +1,7 @@ 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; @@ -23,6 +24,8 @@ public class StatisticsController implements Initializable { private PieChart kd, wl; SceneLoader sceneLoader = new SceneLoader(); + Persistence persistence = Persistence.getInstance(); + public void mainMenuScene() { parent.getChildren().clear(); parent.getChildren().add(sceneLoader.loadScene("MainMenu")); @@ -30,17 +33,27 @@ public class StatisticsController implements Initializable { @Override public void initialize(URL url, ResourceBundle resourceBundle) { - iniPieChartkd(); - iniPieChartwl(); + 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() { + public void iniPieChartKD() { ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList( - new PieChart.Data("Kills", 20), - new PieChart.Data("Deaths", 12)); + new PieChart.Data("Kills", persistence.getStatistics().getKills()), + new PieChart.Data("Deaths", persistence.getStatistics().getDeaths())); pieChartData.forEach(data -> data.nameProperty().bind( @@ -52,11 +65,11 @@ public class StatisticsController implements Initializable { kd.getData().addAll(pieChartData); } - public void iniPieChartwl() { + public void iniPieChartWL() { ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList( - new PieChart.Data("Wins", 3), - new PieChart.Data("Losses", 5)); + new PieChart.Data("Wins", persistence.getStatistics().getGamesWon()), + new PieChart.Data("Losses", persistence.getStatistics().getGamesLost())); pieChartData.forEach(data -> data.nameProperty().bind( 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 index b129d469320cdd8549e234a3a5d6fae8901187ea..8e59516428834ab48bf7a9b2cfebb1760ad63308 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ButtonTransition.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/Utilities/ButtonTransition.java @@ -1,6 +1,7 @@ package de.hdm_stuttgart.battlearena.Controller.Utilities; import javafx.animation.ScaleTransition; +import javafx.application.Platform; import javafx.scene.control.Button; import javafx.scene.control.skin.ButtonSkin; import javafx.util.Duration; @@ -13,14 +14,20 @@ public class ButtonTransition extends ButtonSkin { fadeIn.setNode(button); fadeIn.setToX(1.1); fadeIn.setToY(1.1); - button.setOnMouseEntered(e -> fadeIn.playFromStart()); + +// this ensures that any JavaFX related code is run on the JavaFX application thread + button.setOnMouseEntered(e -> { + Platform.runLater(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.setOnMouseExited(e -> { + Platform.runLater(fadeOut::playFromStart); + }); button.setScaleX(1.0); button.setScaleY(1.0); diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Main/Driver.java b/src/main/java/de/hdm_stuttgart/battlearena/Main/Driver.java new file mode 100644 index 0000000000000000000000000000000000000000..66f93ada9d0e18cccb86262356517c4f79d881e3 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Main/Driver.java @@ -0,0 +1,75 @@ +package de.hdm_stuttgart.battlearena.Main; + + +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; + +import java.util.Objects; + +public class Driver extends Application { + + private static final Logger log = LogManager.getLogger(Driver.class); + Rectangle2D screen = Screen.getPrimary().getVisualBounds(); + + InputHandler inputHandler = InputHandler.getInstance(); + + SoundManager soundManager = new SoundManager(); + + @Override + public void start(Stage stage) throws Exception { + +// loading font in start() because CSS can't handle whitespace in folder names + Font.loadFont(getClass().getResourceAsStream("/fonts/StarshipShadow.ttf"), 50); + Font.loadFont(getClass().getResourceAsStream("/fonts/AmaticSC-Bold.ttf"), 50); + Font.loadFont(getClass().getResourceAsStream("/fonts/Arthemis-mLA22.ttf"), 50); + Font.loadFont(getClass().getResourceAsStream("/fonts/ShadowsIntoLight-Regular.ttf"), 50); + + Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("/fxml/LoadingScreen.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); + + stage.setOnCloseRequest(event -> { + if (soundManager != null) { + soundManager.stopMusic(); + } + }); + + stage.show(); + log.debug("Project started successfully!"); + +// Exiting program if an exception occurs +// Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { +// log.error(throwable.getMessage()); +// System.exit(1); +// }); + } +} \ No newline at end of file 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 1925554e2b86d0efcb4b469b1ca2d799c6ecaec0..77261800125e391620b0facc16c47a6ee3217f79 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Main/Main.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Main/Main.java @@ -1,59 +1,9 @@ package de.hdm_stuttgart.battlearena.Main; -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; - -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 class Main { public static void main(String[] args) { - launch(args); - } - - @Override - public void start(Stage stage) throws Exception { -// 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/MenuBorderPane.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); - - stage.show(); - log.debug("Project started successfully!"); + Application.launch(Driver.class, args); } -} \ No newline at end of file +} 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/ENUMs/AccountType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/AccountType.java new file mode 100644 index 0000000000000000000000000000000000000000..4ddb26cd2de6356b40b45af16dad0b9dfeb7f4d8 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/AccountType.java @@ -0,0 +1,9 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs; + +public enum AccountType { + + NONE, + LOCAL, + ONLINE + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/MapType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/MapType.java new file mode 100644 index 0000000000000000000000000000000000000000..8403ea2c46b21e5b8349917316f7414eb1a74710 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/MapType.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs; + +public enum MapType { + + COREMAP, + COMMUNITYMAP + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/ThreadStatus.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/ThreadStatus.java new file mode 100644 index 0000000000000000000000000000000000000000..48ef20b9c36ce3e1758460adb489b643a7175c8e --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ENUMs/ThreadStatus.java @@ -0,0 +1,10 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs; + +public enum ThreadStatus { + + RUNNING, + FAILED, + FINISHED, + NONE + +} 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..0b6bb2a2974338947bbbd2a7f299ef52077dfd59 --- /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.ENUMs.MapType; +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/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..9291ee84f4f5721980c84957f9e7f58532f46e8c --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Persistence.java @@ -0,0 +1,480 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.MapType; +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.security.NoSuchAlgorithmException; +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; + private 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(); + Parser.playerStatsValid(statistics); + } else { + statistics = db.getStatistics(account.getPlayerName()); + Parser.playerStatsValid(statistics); + } + 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()); + } + catch (ParserException e) { + throw new RuntimeException("Player statistics data corrupted!"); + } + } + + 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 void saveSettings(){ + try{ + gsonHandler.saveSettings(settings); + } + catch(Exception e){ + log.error(e); + } + } + + public void savePlayerStatistics() throws DatabaseException{ //on shutdown of game + try { + Parser.playerStatsValid(statistics); + 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 saveCreatedMap(MapData map, boolean doUpload) throws DatabaseException { + String part1 = ""; + 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); + log.info("Newly created map stored successfully in JSON!"); + } + catch(Exception e){ + log.error(e); + if(e.getMessage().contains("Identical map already saved")){ + part1 = e.getMessage(); + } + } + if(doUpload) { + 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(part1 + "\nNo connection to SQL server! Saving to SQL communityMap server failed!"); + } else if (e.getMessage().contains("ORA-00001")) { + throw new DatabaseException(part1 + "\nMap already existing on communityMaps server!\n Look for mapID: " + map.getMapID()); + } else { + throw new DatabaseException(part1 + "\nUnknown 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; only update stats in RAM, not in persistence (run savePlayerStatistics() method at end of program to save stats to persistence) + try { + Parser.playerStatsValid(new PlayerStatistics(0, 0, kills, deaths, blocksDestroyed, gameTime)); //temp instance of PLayerStatistics to validate new values + statistics.addKills(kills); + statistics.addDeaths(deaths); + statistics.addGameTime(gameTime); + statistics.addBlocksDestroyed(blocksDestroyed); + if(gameWon){ + statistics.addGamesWon(); + } + else{ + statistics.addGamesLost(); + } + log.info("Statistics successfully updated!"); + } + catch(Exception e){ + log.error(e); + } + } + + 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{ //eigentlich ü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); + } + } + + public void login(String userName, String password) throws NoSuchAlgorithmException, RuntimeException, DatabaseException { + try { + String hash = HashGenerator.hashAndHex(password); + if (hash.equals(db.checkCredentials(userName))) { + account = new PlayerAccount(userName, hash, AccountType.ONLINE); + gsonHandler.saveAccount(account); + log.info("Login successful!"); + } else { + throw new DatabaseException("Wrong password!"); + } + } + catch (GSONException | SQLException e) { + throw new RuntimeException(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..ae1e60649de3d31e4a1b99e70de92a9bfbfe0c53 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/PlayerAccount.java @@ -0,0 +1,30 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; + +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..38ae10a6052607adc5c2279eb8058f1da8107551 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/RuntimeInfo.java @@ -0,0 +1,159 @@ +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.ENUMs.ThreadStatus; +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; + + //Stats Tracking during Gameplay + private int kills; + private int deaths; + private int blocksDestroyed; + private int gameTime; + private boolean gameWon; + + + + + + + private RuntimeInfo(){}; + + public static RuntimeInfo getInstance(){ + return runtimeInfoSingleton; + } + + 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; + } + + public String getMapDataGame() { + return mapDataGame; + } + + public int getKills() { + return kills; + } + + public void setKills(int kills) { + this.kills = kills; + } + + public void addKill() { + kills = kills + 1; + } + + public int getDeaths() { + return deaths; + } + + public void setDeaths(int deaths) { + this.deaths = deaths; + } + + public void addDeath() { + deaths = deaths + 1; + } + + public int getBlocksDestroyed() { + return blocksDestroyed; + } + + public void setBlocksDestroyed(int blocksDestroyed) { + this.blocksDestroyed = blocksDestroyed; + } + + public void addBlockDestroyed() { + blocksDestroyed = blocksDestroyed + 1; + } + + public int getGameTime() { + return gameTime; + } + + public void setGameTime(int gameTime) { + this.gameTime = gameTime; + } + + public void addGameTime() { + gameTime = gameTime + 1; + } + + public boolean isGameWon() { + return gameWon; + } + + public void setGameWon(boolean gameWon) { + this.gameWon = gameWon; + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadCreateAcc.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadCreateAcc.java new file mode 100644 index 0000000000000000000000000000000000000000..e7f37c6deec9db193b2f3ac8410cf28cbf44b202 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadCreateAcc.java @@ -0,0 +1,42 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadCreateAcc extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadCreateAcc.class); + private String playerName; + private String password; + private AccountType type; + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadCreateAccMsg(""); + threadsInstance.setThreadCreateAcc(ThreadStatus.RUNNING); + persistenceInst.createAccount(playerName, password, type); + log.info("Create account thread finished successfully!"); + threadsInstance.setThreadCreateAcc(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadCreateAccMsg(e.getMessage()); + log.info("Create account thread failed!"); + threadsInstance.setThreadCreateAcc(ThreadStatus.FAILED); + } + } + + public void startThread(String playerName, String password, AccountType type){ + this.playerName = playerName; + this.password = password; + this.type = type; + start(); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadDLCommMap.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadDLCommMap.java new file mode 100644 index 0000000000000000000000000000000000000000..76bf3c0ebcc16150b3e34d907faaf0b5c33794e7 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadDLCommMap.java @@ -0,0 +1,37 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadDLCommMap extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadDLCommMap.class); + private String mapID; + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadDLCommMapMsg(""); + threadsInstance.setThreadDLCommMap(ThreadStatus.RUNNING); + persistenceInst.getCommunityMap(mapID); + log.info("Download Community-Map thread finished successfully!"); + threadsInstance.setThreadDLCommMap(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadDLCommMapMsg(e.getMessage()); + log.info("Download Community-Map thread failed!"); + threadsInstance.setThreadDLCommMap(ThreadStatus.FAILED); + } + } + + public void startThread(String mapID){ + this.mapID = mapID; + start(); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadGetMapList.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadGetMapList.java new file mode 100644 index 0000000000000000000000000000000000000000..0062eaf71c227ed5aa6614307e6024357f691560 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadGetMapList.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadGetMapList extends Thread { + + private static final Logger log = LogManager.getLogger(ThreadGetMapList.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadCommMapListMsg(""); + threadsInstance.setThreadCommMapList(ThreadStatus.RUNNING); + persistenceInst.createRemoteCommunityMapsList(); + log.info("Retrieving Community-Map-List thread finished successfully!"); + threadsInstance.setThreadCommMapList(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadCommMapListMsg(e.getMessage()); + log.info("Retrieving Community-Map-List thread failed!"); + threadsInstance.setThreadCommMapList(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadLogin.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadLogin.java new file mode 100644 index 0000000000000000000000000000000000000000..b6bb5e6c7c647dfe372702933672eead65c56b02 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadLogin.java @@ -0,0 +1,39 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadLogin extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadLogin.class); + private String userName; + private String password; + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadLoginMsg(""); + threadsInstance.setThreadLogin(ThreadStatus.RUNNING); + persistenceInst.login(userName, password); + log.info("Login thread finished successfully!"); + threadsInstance.setThreadLogin(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadLoginMsg(e.getMessage()); + log.info("Login thread failed!"); + threadsInstance.setThreadLogin(ThreadStatus.FAILED); + } + } + + public void startThread(String userName, String password){ + this.userName = userName; + this.password = password; + start(); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadRstStats.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadRstStats.java new file mode 100644 index 0000000000000000000000000000000000000000..c815c70fc73043c305ddad9e575ac662207a50ac --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadRstStats.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadRstStats extends Thread { + + private static final Logger log = LogManager.getLogger(ThreadRstStats.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadRstStatsMsg(""); + threadsInstance.setThreadRstStats(ThreadStatus.RUNNING); + persistenceInst.resetPlayerStatistics(); + log.info("Reset Player-Statistics thread finished successfully!"); + threadsInstance.setThreadRstStats(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadRstStatsMsg(e.getMessage()); + log.info("Reset Player-Statistics thread failed!"); + threadsInstance.setThreadRstStats(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadSaveCommMap.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadSaveCommMap.java new file mode 100644 index 0000000000000000000000000000000000000000..47877f48acc768333279887fd1a899bdb046ac65 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadSaveCommMap.java @@ -0,0 +1,39 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadSaveCommMap extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadSaveCommMap.class); + private MapData map; + private boolean doUpload; + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadSaveCommMapMsg(""); + threadsInstance.setThreadSaveCommMap(ThreadStatus.RUNNING); + persistenceInst.saveCreatedMap(map, doUpload); + log.info("Uploading Community-Map thread finished successfully!"); + threadsInstance.setThreadSaveCommMap(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadSaveCommMapMsg(e.getMessage()); + log.info("Uploading Community-Map thread failed!"); + threadsInstance.setThreadSaveCommMap(ThreadStatus.FAILED); + } + } + + public void startThread(MapData map, boolean doUpload){ //user can check box to optionally publish map on SQL server + this.map = map; + this.doUpload = doUpload; + start(); + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadSaveStats.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadSaveStats.java new file mode 100644 index 0000000000000000000000000000000000000000..3b6c425300db7c7790908c47e36e2282e788b33e --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadSaveStats.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadSaveStats extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadSaveStats.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadSaveStatsMsg(""); + threadsInstance.setThreadSaveStats(ThreadStatus.RUNNING); + persistenceInst.savePlayerStatistics(); + log.info("Save Player-Statistics thread finished successfully!"); + threadsInstance.setThreadSaveStats(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadSaveStatsMsg(e.getMessage()); + log.info("Save Player-Statistics thread failed!"); + threadsInstance.setThreadSaveStats(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup1.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup1.java new file mode 100644 index 0000000000000000000000000000000000000000..3b8016b8ed5629b16ef2d949f6fc9a0376f51ad1 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup1.java @@ -0,0 +1,36 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadStartup1 extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadStartup1.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadStartup1Msg(""); + threadsInstance.setThreadStartup1(ThreadStatus.RUNNING); + persistenceInst.loadSettings(); + persistenceInst.loadCoreMaps(); + persistenceInst.loadCommunityMaps(); + persistenceInst.verifyAppSettings(); + persistenceInst.verifyCoreMaps(); + persistenceInst.verifyCommunityMaps(); + log.info("Startup routine part1 complete!"); + threadsInstance.setThreadStartup1(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadStartup1Msg(e.getMessage()); + log.info("Startup routine part1 failed!"); + threadsInstance.setThreadStartup1(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup2.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup2.java new file mode 100644 index 0000000000000000000000000000000000000000..50ba60bf4edc9c10f56ed27e7833a65ae3e808d6 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup2.java @@ -0,0 +1,35 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadStartup2 extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadStartup2.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadStartup2Msg(""); + threadsInstance.setThreadStartup2(ThreadStatus.RUNNING); + persistenceInst.loadPlayerAccount(); + if(persistenceInst.getAccount().getAccountType() != AccountType.NONE){ + persistenceInst.verifyPlayerAccount(); + } + log.info("Startup routine part2 complete!"); + threadsInstance.setThreadStartup2(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadStartup2Msg(e.getMessage()); + log.info("Startup routine part2 failed!"); + threadsInstance.setThreadStartup2(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup3.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup3.java new file mode 100644 index 0000000000000000000000000000000000000000..738c4add7276cc2706a23204b0b7daef94e51975 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadStartup3.java @@ -0,0 +1,35 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.AccountType; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadStartup3 extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadStartup3.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadStartup3Msg(""); + threadsInstance.setThreadStartup3(ThreadStatus.RUNNING); + persistenceInst.loadPlayerStatistics(); + if(persistenceInst.getAccount().getAccountType() != AccountType.NONE){ + persistenceInst.verifyPlayerAccount(); + } + log.info("Startup routine part3 complete!"); + threadsInstance.setThreadStartup3(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadStartup3Msg(e.getMessage()); + log.info("Startup routine part3 failed!"); + threadsInstance.setThreadStartup3(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadUpdateMaps.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadUpdateMaps.java new file mode 100644 index 0000000000000000000000000000000000000000..f0bc303975da0e08d54330a3331e9dca7bee1577 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadUpdateMaps.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadUpdateMaps extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadUpdateMaps.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadUpdateMapsMsg(""); + threadsInstance.setThreadUpdateMaps(ThreadStatus.RUNNING); + persistenceInst.updateCoreMaps(); + log.info("Update Core-Maps thread finished successfully!"); + threadsInstance.setThreadUpdateMaps(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadUpdateMapsMsg(e.getMessage()); + log.info("Update Core-Maps thread failed!"); + threadsInstance.setThreadUpdateMaps(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadUpdateStats.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadUpdateStats.java new file mode 100644 index 0000000000000000000000000000000000000000..44ae6fe13e20f599800784e95dc6b0bd9a8ca9b7 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/ThreadUpdateStats.java @@ -0,0 +1,37 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ThreadUpdateStats extends Thread{ + + private static final Logger log = LogManager.getLogger(ThreadUpdateStats.class); + + @Override + public void run() { + + Persistence persistenceInst = Persistence.getInstance(); + RuntimeInfo runtimeInfoInst = RuntimeInfo.getInstance(); + Threads threadsInstance = Threads.getInstance(); + + try { + threadsInstance.setThreadUpdateStatsMsg(""); + threadsInstance.setThreadUpdateStats(ThreadStatus.RUNNING); + persistenceInst.updatePlayerStatistics(runtimeInfoInst.getKills(), runtimeInfoInst.getDeaths(), runtimeInfoInst.getGameTime(), runtimeInfoInst.getBlocksDestroyed(), runtimeInfoInst.isGameWon()); + runtimeInfoInst.setKills(0); + runtimeInfoInst.setDeaths(0); + runtimeInfoInst.setGameTime(0); + runtimeInfoInst.setBlocksDestroyed(0); + runtimeInfoInst.setGameWon(false); + log.info("Update statistics thread finished successfully!"); + threadsInstance.setThreadUpdateStats(ThreadStatus.FINISHED); + } catch (Exception e) { + log.error(e); + threadsInstance.setThreadUpdateStatsMsg(e.getMessage()); + log.info("Update statistics thread failed!"); + threadsInstance.setThreadUpdateStats(ThreadStatus.FAILED); + } + } + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Threads.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Threads.java new file mode 100644 index 0000000000000000000000000000000000000000..ebf4876b70d047545985366e5983fdd7438a97ec --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/DataStorage/Classes/Threads.java @@ -0,0 +1,237 @@ +package de.hdm_stuttgart.battlearena.Model.DataStorage.Classes; + +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs.ThreadStatus; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class Threads { + + private static final Logger log = LogManager.getLogger(Threads.class); + private static final Threads threadsSingleton = new Threads(); + + //Thread Status-Updates + private ThreadStatus threadStartup1; + private String threadStartup1Msg; + private ThreadStatus threadStartup2; + private String threadStartup2Msg; + private ThreadStatus threadStartup3; + private String threadStartup3Msg; + private ThreadStatus threadUpdateMaps; + private String threadUpdateMapsMsg; + private ThreadStatus threadUpdateStats; + private String threadUpdateStatsMsg; + private ThreadStatus threadDLCommMap; + private String threadDLCommMapMsg; + private ThreadStatus threadSaveCommMap; + private String threadSaveCommMapMsg; + private ThreadStatus threadCommMapList; + private String threadCommMapListMsg; + private ThreadStatus threadRstStats; + private String threadRstStatsMsg; + private ThreadStatus threadSaveStats; + private String threadSaveStatsMsg; + private ThreadStatus threadCreateAcc; + private String threadCreateAccMsg; + private ThreadStatus threadLogin; + private String threadLoginMsg; + + + + private Threads(){}; + public static Threads getInstance(){ + return threadsSingleton; + } + + public ThreadStatus getThreadStartup1() { + return threadStartup1; + } + + public void setThreadStartup1(ThreadStatus threadStartup1) { + this.threadStartup1 = threadStartup1; + } + + public String getThreadStartup1Msg() { + return threadStartup1Msg; + } + + public void setThreadStartup1Msg(String threadStartup1Msg) { + this.threadStartup1Msg = threadStartup1Msg; + } + + public ThreadStatus getThreadStartup2() { + return threadStartup2; + } + + public void setThreadStartup2(ThreadStatus threadStartup2) { + this.threadStartup2 = threadStartup2; + } + + public String getThreadStartup2Msg() { + return threadStartup2Msg; + } + + public void setThreadStartup2Msg(String threadStartup2Msg) { + this.threadStartup2Msg = threadStartup2Msg; + } + + public ThreadStatus getThreadUpdateMaps() { + return threadUpdateMaps; + } + + public ThreadStatus getThreadStartup3() { + return threadStartup3; + } + + public void setThreadStartup3(ThreadStatus threadStartup3) { + this.threadStartup3 = threadStartup3; + } + + public String getThreadStartup3Msg() { + return threadStartup3Msg; + } + + public void setThreadStartup3Msg(String threadStartup3Msg) { + this.threadStartup3Msg = threadStartup3Msg; + } + + public void setThreadUpdateMaps(ThreadStatus threadUpdateMaps) { + this.threadUpdateMaps = threadUpdateMaps; + } + + public String getThreadUpdateMapsMsg() { + return threadUpdateMapsMsg; + } + + public void setThreadUpdateMapsMsg(String threadUpdateMapsMsg) { + this.threadUpdateMapsMsg = threadUpdateMapsMsg; + } + + public ThreadStatus getThreadUpdateStats() { + return threadUpdateStats; + } + + public void setThreadUpdateStats(ThreadStatus threadUpdateStats) { + this.threadUpdateStats = threadUpdateStats; + } + + public String getThreadUpdateStatsMsg() { + return threadUpdateStatsMsg; + } + + public void setThreadUpdateStatsMsg(String threadUpdateStatsMsg) { + this.threadUpdateStatsMsg = threadUpdateStatsMsg; + } + + public ThreadStatus getThreadDLCommMap() { + return threadDLCommMap; + } + + public void setThreadDLCommMap(ThreadStatus threadDLCommMap) { + this.threadDLCommMap = threadDLCommMap; + } + + public String getThreadDLCommMapMsg() { + return threadDLCommMapMsg; + } + + public void setThreadDLCommMapMsg(String threadDLCommMapMsg) { + this.threadDLCommMapMsg = threadDLCommMapMsg; + } + + public ThreadStatus getThreadSaveCommMap() { + return threadSaveCommMap; + } + + public void setThreadSaveCommMap(ThreadStatus threadSaveCommMap) { + this.threadSaveCommMap = threadSaveCommMap; + } + + public String getThreadSaveCommMapMsg() { + return threadSaveCommMapMsg; + } + + public void setThreadSaveCommMapMsg(String threadSaveCommMapMsg) { + this.threadSaveCommMapMsg = threadSaveCommMapMsg; + } + + public ThreadStatus getThreadCommMapList() { + return threadCommMapList; + } + + public void setThreadCommMapList(ThreadStatus threadCommMapList) { + this.threadCommMapList = threadCommMapList; + } + + public String getThreadCommMapListMsg() { + return threadCommMapListMsg; + } + + public void setThreadCommMapListMsg(String threadCommMapListMsg) { + this.threadCommMapListMsg = threadCommMapListMsg; + } + + public ThreadStatus getThreadRstStats() { + return threadRstStats; + } + + public void setThreadRstStats(ThreadStatus threadRstStats) { + this.threadRstStats = threadRstStats; + } + + public String getThreadRstStatsMsg() { + return threadRstStatsMsg; + } + + public void setThreadRstStatsMsg(String threadRstStatsMsg) { + this.threadRstStatsMsg = threadRstStatsMsg; + } + + public ThreadStatus getThreadSaveStats() { + return threadSaveStats; + } + + public void setThreadSaveStats(ThreadStatus threadSaveStats) { + this.threadSaveStats = threadSaveStats; + } + + public String getThreadSaveStatsMsg() { + return threadSaveStatsMsg; + } + + public void setThreadSaveStatsMsg(String threadSaveStatsMsg) { + this.threadSaveStatsMsg = threadSaveStatsMsg; + } + + public ThreadStatus getThreadCreateAcc() { + return threadCreateAcc; + } + + public void setThreadCreateAcc(ThreadStatus threadCreateAcc) { + this.threadCreateAcc = threadCreateAcc; + } + + public String getThreadCreateAccMsg() { + return threadCreateAccMsg; + } + + public void setThreadCreateAccMsg(String threadCreateAccMsg) { + this.threadCreateAccMsg = threadCreateAccMsg; + } + + public ThreadStatus getThreadLogin() { + return threadLogin; + } + + public void setThreadLogin(ThreadStatus threadLogin) { + this.threadLogin = threadLogin; + } + + public String getThreadLoginMsg() { + return threadLoginMsg; + } + + public void setThreadLoginMsg(String threadLoginMsg) { + this.threadLoginMsg = threadLoginMsg; + } + +} 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/EntityFactory.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java index d5b4b382213c197e503a598e855940aa18821998..2e49bcaca57667a7fbea0431ff0fe8c91b356ac5 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java @@ -1,5 +1,6 @@ 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; @@ -12,13 +13,14 @@ 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) { + 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); - } else if (entityType == EntityType.ENEMY_PLAYER) { + return new Player(gameScene, inputHandler, entityClass, gameSceneController, playerMode); + } else if (entityType == EntityType.NETWORK_PLAYER_TWO) { log.debug("Entity " + entityType + " created"); - return new EnemyHandler(); + return new NetworkPlayerTwo(); } throw new IllegalArgumentException ("Entity type not supported " + entityType); 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 index 3e8560772b2e9f049e217bdeca99c30c24150e11..108c4c2037dbcb53d090dc19a59b9b79450d6b68 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityType.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityType.java @@ -2,5 +2,6 @@ package de.hdm_stuttgart.battlearena.Model.Entity; public enum EntityType { PLAYER, - ENEMY_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 92ca5b53906697c1bad96c2cbb59524b7bc2c40b..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 @@ -12,19 +12,23 @@ public interface IEntity { void updateEntityMovement(GameSceneController gameScene); + void checkHealTile(IEntity entity, GraphicsContext graphicsContext); + void attack(IEntity entity, GraphicsContext graphicsContext); void updateEntityWalkAnimation(); void renderEntity(GraphicsContext graphicsContext); - BoundingBox getBoxCollider(); + void healPlayer(int heal); + + BoundingBox getBoxCollider(); EntityDirection getEntityDirection(); int getEntitySpeed(); - int gotHit(int damageDone); + void gotHit(int damageDone); int getMapPosX(); diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/NetworkPlayerTwo.java similarity index 75% rename from src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java rename to src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/NetworkPlayerTwo.java index c8fc714cc5aa2eefe30e616b5211fe76e6457ff2..d045a108bf051f2e40573e084199808f2edbc630 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/NetworkPlayerTwo.java @@ -9,9 +9,9 @@ import javafx.scene.paint.Color; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -class EnemyHandler implements IEntity{ +class NetworkPlayerTwo implements IEntity{ - private static final Logger log = LogManager.getLogger(EnemyHandler.class); + private static final Logger log = LogManager.getLogger(NetworkPlayerTwo.class); private final BoundingBox boxCollider = new BoundingBox(300, 200, 48, 48); @@ -36,6 +36,11 @@ class EnemyHandler implements IEntity{ } + @Override + public void checkHealTile(IEntity entity, GraphicsContext graphicsContext) { + + } + @Override public void attack(IEntity entity, GraphicsContext graphicsContext) { @@ -52,6 +57,12 @@ class EnemyHandler implements IEntity{ 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; @@ -68,9 +79,9 @@ class EnemyHandler implements IEntity{ } @Override - public int gotHit(int damageDone) { - log.debug(health); - return health -= damageDone; + public void gotHit(int damageDone) { + log.debug("Network player health: " + health); + health -= damageDone; } @Override 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 fffccf712e14e8a655bbc72622fae7e4c0d5d3b8..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,8 +1,10 @@ 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; @@ -16,6 +18,8 @@ class Player implements IEntity { private static final Logger log = LogManager.getLogger(Player.class); + private final PlayerMode PLAYER_MODE; + InputHandler inputHandler; CollisionHandler collisionHandler = new CollisionHandler(); @@ -51,17 +55,24 @@ class Player implements IEntity { private int mapPosX; private int mapPosY; + + private int lastMapPosX; + private int lastMapPosY; + private int playerSpeed; private EntityDirection playerDirection; - private int health = 10; - private int damage = 1; + private int health; + private int maxPlayerHealth; + private int damage; - public Player(GraphicsContext gameScene, InputHandler inputHandler, EntityClass entityClass, GameSceneController gameSceneController) { + 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(); @@ -70,13 +81,45 @@ class Player implements IEntity { @Override public void initializeEntity() { scaledTileSize = gameSceneController.getScaledTileSize(); - mapPosX = 60; - mapPosY = 60; - boxCollider = new BoundingBox(mapPosX+15,mapPosY+10, playerWidth, playerHeight); - playerSpeed = 5; + 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 { @@ -99,19 +142,19 @@ class Player implements IEntity { } private void loadHumanSprites() { - 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"))); + 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/HumanDown01.png"))); - directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + 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"))); @@ -132,15 +175,15 @@ class Player implements IEntity { } private void loadSentinelsSprites() { - directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown01.png"))); - directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + 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"))); @@ -151,57 +194,99 @@ class Player implements IEntity { @Override public void updateEntityMovement(GameSceneController gameScene) { - 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 { - playerDirection = EntityDirection.RIGHT; - } - - boolean isWalkableTile = collisionHandler.handleMapCollision(this, scaledTileSize, gameSceneController); - - int lastMapPosX = mapPosX; - int 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; + 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 isEntityCollision = boxCollider.intersects(gameScene.getEnemy().getBoxCollider()); - //boolean isEntityCollision = collisionHandler.handleBoxCollision(boxCollider, gameScene.getEnemy().getBoxCollider()); - - 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; + 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(); } + } + } - boxCollider = new BoundingBox(mapPosX+15,mapPosY+10, playerWidth, playerHeight); + 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; + } + } + } - updateEntityWalkAnimation(); + 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); } } @@ -209,47 +294,82 @@ class Player implements IEntity { 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()){ + 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); + 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); + 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), + hitBox = new BoundingBox(mapPosX - attackWidth, mapPosY + ((double) playerHeight / 2), attackRange, attackWidth); - graphicsContext.strokeRect(mapPosX-attackWidth, mapPosY+((double) playerHeight /2), + graphicsContext.strokeRect(mapPosX - attackWidth, mapPosY + ((double) playerHeight / 2), attackRange, attackWidth); - graphicsContext.drawImage(swordLeft, mapPosX-8, mapPosY+8, 32, 32); + 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), + hitBox = new BoundingBox(mapPosX + playerWidth + attackWidth, mapPosY + ((double) playerHeight / 2), attackRange, attackWidth); - graphicsContext.strokeRect(mapPosX+playerWidth+attackWidth, mapPosY+((double) playerHeight /2), + graphicsContext.strokeRect(mapPosX + playerWidth + attackWidth, mapPosY + ((double) playerHeight / 2), attackRange, attackWidth); - graphicsContext.drawImage(swordRight, mapPosX+playerWidth+8, mapPosY+8, 32, 32); + 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; } } } @@ -274,7 +394,7 @@ class Player implements IEntity { Image playerSprite = null; //for debugging collision - graphicsContext.strokeRect(mapPosX+15,mapPosY+10, playerWidth, playerHeight); + graphicsContext.strokeRect(mapPosX + 15, mapPosY + 10, playerWidth, playerHeight); switch (playerDirection) { case UP: @@ -314,6 +434,22 @@ class Player implements IEntity { 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; @@ -329,11 +465,6 @@ class Player implements IEntity { return playerSpeed; } - @Override - public int gotHit(int damageDone) { - return health -= damageDone; - } - @Override public int getMapPosX() { return mapPosX; 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 8dfd2f3d3d51063e409488e71a25814030ed2f68..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 @@ -18,26 +18,51 @@ public class InputHandler { 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 SPACE: + 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; } } @@ -57,8 +82,24 @@ public class InputHandler { case D: moveRight = false; break; - case SPACE: + 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; } } @@ -81,4 +122,24 @@ public class InputHandler { 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 c7fd6bc3ad273c2e2667a9398a33c94764947ea7..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 @@ -10,11 +10,12 @@ class BackgroundTile implements ITile{ private static final Logger log = LogManager.getLogger(BackgroundTile.class); private final Image tileSprite; - private final boolean isWalkable; + private final boolean isWalkable, isDestructible; - public BackgroundTile(Image tileSprite, boolean isWalkable) { + public BackgroundTile(Image tileSprite, boolean isWalkable, boolean isDestructible) { this.tileSprite = tileSprite; this.isWalkable = isWalkable; + this.isDestructible = isDestructible; } @Override @@ -22,6 +23,11 @@ class BackgroundTile implements ITile{ log.debug("Collision type: " + isWalkable + " returned."); return isWalkable; } + @Override + public boolean getDestruction() { + log.debug("Collision type: " + isDestructible + " returned."); + return isWalkable; + } @Override public Image getTileSprite() { 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 f33750bed5ede99e059da2a7fb4e31f33bb735ad..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 @@ -4,5 +4,6 @@ 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/TileFactory.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactory.java index 842781646eb4c59e1ba537d172414c7437b498b2..0da1a1558d0e6888a73fa456d3dd81f021d936fc 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactory.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileFactory.java @@ -9,13 +9,19 @@ public class TileFactory { private static final Logger log = LogManager.getLogger(TileFactory.class); - public static ITile createTile(TileType tileType, Image tileSprite) { - if (tileType == TileType.WALKABLE) { - log.debug("Tile with type: " + tileType + " created."); - return new BackgroundTile(tileSprite, true); - } else if (tileType == TileType.NON_WALKABLE) { - log.debug("Tile with type: " + tileType + " created."); - return new BackgroundTile(tileSprite, false); + 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!"); 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 480478d51823c0a4992de930e4eea5f2b73f82d8..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 @@ -14,7 +14,7 @@ public class TileManager { private final GraphicsContext graphicsContext2D; private final ITile[] tileSet; - private final int[][] tileMap; + public static int[][] tileMap; private final int horizontalTileCount; private final int verticalTileCount; @@ -34,16 +34,18 @@ public class TileManager { private void createTiles() { try { - tileSet[0] = TileFactory.createTile(TileType.WALKABLE, + 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, + 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, + 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, + 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, + 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); } 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 index 17e95c7e93fc890a5f993cc53b7eb6cfd1f4bd6b..efe35788d26be5839df9efee6934ce54ec2c0d63 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileType.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Map/TileType.java @@ -2,5 +2,8 @@ package de.hdm_stuttgart.battlearena.Model.Map; public enum TileType { WALKABLE, - NON_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 index 87189a54b8a83db73c96f74eee8e46702322b5f4..23b1c65ccd218152576cc9c7d366e68c65d1c591 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Client.java @@ -12,7 +12,6 @@ public class Client { private PrintWriter out; private BufferedReader in; - private static final Logger log = LogManager.getLogger(Client.class); public void startConnection(String ip, int port) throws IOException { @@ -24,7 +23,7 @@ public class Client { 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); + // log.info("Sent coordinates: " + message); String resp = in.readLine(); return convertStringToArray(resp); } @@ -42,7 +41,6 @@ public class Client { return result; } - public void stopConnection() throws IOException { in.close(); out.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 67529ff1e0e3eb4cc9f2b0f01ef637a2190415e7..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 @@ -11,48 +11,57 @@ public class ConnectionHandler { private static int pX = 0; private static int pY = 0; - private int enemyX; - private int enemyY; + 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 static void main(String[] args) throws IOException, InterruptedException { + public void startHandler() throws IOException, InterruptedException { Client client = new Client(); - client.startConnection("localhost", 4444); - while (true){ - int[] cords = client.sendcords(coordinates); - System.out.println("Enemy X: " + cords[0]); - System.out.println("Enemy Y: " + cords[1]); - System.out.println("Your PlayerID is " + cords[2]); - pX++; - pY++; - playerID = cords[2]; - //Assign the Values to the message to send: - coordinates[0] = pX; - coordinates[1] = pY; - coordinates[2] = playerID; - - TimeUnit.SECONDS.sleep(1); - } + client.startConnection(ipaddress, 4444); + + ConnectionThread connectionthread = new ConnectionThread(client); + connectionthread.start(); - //stop the connection: - //client.stopConnection(); } - class ConnectionThread implements Runnable { - public void run() { + private static class ConnectionThread extends Thread { + private final Client client; + + public ConnectionThread(Client client) { + this.client = client; + } + public void run() { try { - Thread.sleep(250); - } catch (InterruptedException e){ - log.error("Error in Thread.sleep()"); + 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; } @@ -72,17 +81,12 @@ public class ConnectionHandler { public int getEnemyX() { return enemyX; } - - public void setEnemyX(int enemyX) { - this.enemyX = enemyX; - } - public int getEnemyY() { return enemyY; } - public void setEnemyY(int enemyY) { - this.enemyY = enemyY; + public static void setIpaddress(String ipaddress) { + ConnectionHandler.ipaddress = ipaddress; } } 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 index e9226a37ba2b57a3d708a2f022e243b8f66d68da..fddc2fae68590bac4fc51d13f466b7bd8684012c 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Multiplayer/Server.java @@ -23,18 +23,28 @@ public class Server { 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); + } */ - public static void main(String[] args) throws IOException { + //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("localhost",4444); + server.start(ipaddress,4444); } - public void start(String localhost, int port) throws IOException { + 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(); } @@ -132,7 +142,7 @@ public class Server { } catch (IOException e) { throw new RuntimeException(e); } - }, 0, 250, TimeUnit.MILLISECONDS); + }, 0, 50, TimeUnit.MILLISECONDS); } } @@ -145,4 +155,10 @@ public class Server { } } + 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/Model/Sound/ISoundManager.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/ISoundManager.java new file mode 100644 index 0000000000000000000000000000000000000000..7f31c780e19380b4f58e02ab5a854d8b25ea2019 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/ISoundManager.java @@ -0,0 +1,16 @@ +package de.hdm_stuttgart.battlearena.Model.Sound; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.nio.file.Path; +import java.util.List; + +public interface ISoundManager { + + + + void playSoundEffect() throws InterruptedException, MalformedURLException; //plays sound effects only + + List<Path> getFilePathsFromResources(Path folderPath) throws IOException; // gets file-paths in a Folder as a list + +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/MusicType.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/MusicType.java new file mode 100644 index 0000000000000000000000000000000000000000..b7d5924e85a9559d88db4bf4a295fd235fc2aa5b --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/MusicType.java @@ -0,0 +1,16 @@ +package de.hdm_stuttgart.battlearena.Model.Sound; + +public enum MusicType { + MENU("src/main/resources/sound/music/menu"), + OPTIONS("src/main/resources/sound/music/options"), + GAME("src/main/resources/sound/music/game"); + + private String path; + MusicType(String path){ + this.path = path; + } + + public String getPath(){ + return path; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/SFX.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/SFX.java new file mode 100644 index 0000000000000000000000000000000000000000..4c4dae812049378d829bd1a0c1d6d3504e350530 --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/SFX.java @@ -0,0 +1,17 @@ +package de.hdm_stuttgart.battlearena.Model.Sound; + +public enum SFX { + GRASS("/sound/sfx/steps/grass"), + STONE("/sound/sfx/steps/stone"), + COLLISION("/sound/sfx/collision"), + ATTACK("/sound/sfx/attack"); + + private String path; + SFX(String path){ + this.path = path; + } + + public String getPath(){ + return path; + } +} diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/SoundManager.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/SoundManager.java new file mode 100644 index 0000000000000000000000000000000000000000..41af98775814a73c36d2b5273f29540449d2bbbb --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Sound/SoundManager.java @@ -0,0 +1,85 @@ +package de.hdm_stuttgart.battlearena.Model.Sound; + + +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import javafx.scene.media.AudioClip; + + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class SoundManager implements ISoundManager { + private static final Logger log = LogManager.getLogger(SoundManager.class); + + + private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5); + private final List<SFX> soundEffectsRunning = new ArrayList<>(); + private MediaPlayer mediaPlayer; + + private final boolean stopLoop = false; + private List<Path> walkingSFXPaths; + + //Todo Make music play + public void playMusic(MusicType musicType) throws IOException { + Path pathTypeOfMusic = Paths.get(musicType.getPath()); + List<Path> musicPaths = getFilePathsFromResources(pathTypeOfMusic); + Random random = new Random(); + int min = 0; + int max = musicPaths.size() - 1; + int randomIndex = random.nextInt(max - min + 1 ) + min; + String randomMusic = musicPaths.get(randomIndex).toString(); + String normalizedPath = Paths.get(randomMusic).toString().replace('\\', '/'); + String resource = normalizedPath.substring(18); + log.info(resource); + Thread thread = new Thread(() -> { + Media media = new Media(getClass().getResource(resource).toExternalForm()); + mediaPlayer = new MediaPlayer(media); + mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE); + mediaPlayer.play(); + log.info("Music is playing"); + + }); + thread.setDaemon(true); + thread.start(); + } + + public void stopMusic(){ + if (mediaPlayer != null) { + mediaPlayer.dispose(); // Dispose of the MediaPlayer instance + } + } + + @Override + public void playSoundEffect() throws InterruptedException, MalformedURLException { + + } + + + + public List<Path> getFilePathsFromResources(Path folderPath) throws IOException { + List<Path> result; + try (Stream<Path> walk = Files.walk(folderPath)) { + result = walk.filter(Files::isRegularFile) + .collect(Collectors.toList()); + } + return result; + } + +} 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 8a3132800c32f2c5b0c2bb3dabef96a0aae98b5d..f0029279f9b345c8bca30dd1ea57552d991b6c83 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -3,15 +3,25 @@ module gui { requires javafx.fxml; requires javafx.media; requires org.apache.logging.log4j; + requires java.desktop; + 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; + opens de.hdm_stuttgart.battlearena to javafx.fxml; + opens de.hdm_stuttgart.battlearena.Model.Sound to javafx.media; + opens de.hdm_stuttgart.battlearena.Controller.Utilities to javafx.fxml; + opens de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.ENUMs 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/sound/sfx/Footsteps, Human, Dirty Ground, Walk SND62078.wav b/src/main/resources/Footsteps, Human, Dirty Ground, Walk SND62078.wav similarity index 100% rename from src/main/resources/sound/sfx/Footsteps, Human, Dirty Ground, Walk SND62078.wav rename to src/main/resources/Footsteps, Human, Dirty Ground, Walk SND62078.wav 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/AmaticSC-Bold.ttf b/src/main/resources/fonts/AmaticSC-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..63cd7ae5be0bce367f8c0aa0e30702d065680923 Binary files /dev/null and b/src/main/resources/fonts/AmaticSC-Bold.ttf differ diff --git a/src/main/resources/fonts/AmaticSC-Regular.ttf b/src/main/resources/fonts/AmaticSC-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b860368bec2246d3c268c075167c9d7333d454d0 Binary files /dev/null and b/src/main/resources/fonts/AmaticSC-Regular.ttf differ diff --git a/src/main/resources/fonts/Arthemis-mLA22.ttf b/src/main/resources/fonts/Arthemis-mLA22.ttf new file mode 100644 index 0000000000000000000000000000000000000000..165d0d21fda6832a71ff683dcfafe042a5d2d016 Binary files /dev/null and b/src/main/resources/fonts/Arthemis-mLA22.ttf differ diff --git a/src/main/resources/fonts/ShadowsIntoLight-Regular.ttf b/src/main/resources/fonts/ShadowsIntoLight-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d20640513b188b6627c3b11383721eba624f1b26 Binary files /dev/null and b/src/main/resources/fonts/ShadowsIntoLight-Regular.ttf differ diff --git a/src/main/resources/fxml/CreateAccount.fxml b/src/main/resources/fxml/CreateAccount.fxml new file mode 100644 index 0000000000000000000000000000000000000000..b75267745fd38367a38728324cf4b7a0aefa720c --- /dev/null +++ b/src/main/resources/fxml/CreateAccount.fxml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.RadioButton?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.control.ToggleGroup?> +<?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.CreateAccountController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <VBox alignment="CENTER" VBox.vgrow="ALWAYS"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Tracking statistics:" /> + <HBox alignment="CENTER" spacing="30.0" VBox.vgrow="ALWAYS"> + <children> + <RadioButton fx:id="local" mnemonicParsing="false" text="Local"> + <toggleGroup> + <ToggleGroup fx:id="statistics" /> + </toggleGroup> + </RadioButton> + <RadioButton mnemonicParsing="false" text="Online" toggleGroup="$statistics" /> + </children> + </HBox> + </children> + </VBox> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Player Name:" /> + <TextField fx:id="playerName" alignment="CENTER" /> + <Label fx:id="passwordLabel" text="Password:" /> + <TextField fx:id="password" alignment="CENTER" /> + <Label fx:id="errorMessage" /> + <Button mnemonicParsing="false" onAction="#create" text="Create" /> + <Button mnemonicParsing="false" onAction="#back" text="Back" /> + <Pane VBox.vgrow="ALWAYS" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/LoadingScreen.fxml b/src/main/resources/fxml/LoadingScreen.fxml new file mode 100644 index 0000000000000000000000000000000000000000..4e242f48920d3c22e5351886ead0da65eaa80b44 --- /dev/null +++ b/src/main/resources/fxml/LoadingScreen.fxml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.shape.Rectangle?> +<?import javafx.scene.text.Font?> + +<BorderPane id="loadingScreen" 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.LoadingScreenController"> + <bottom> + <HBox alignment="BOTTOM_CENTER" BorderPane.alignment="BOTTOM_CENTER"> + <children> + <Rectangle arcHeight="5.0" arcWidth="5.0" fill="#ffffff00" height="180.0" stroke="TRANSPARENT" strokeType="INSIDE" width="180.0" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets bottom="50.0" left="50.0" right="50.0" /> + </HBox.margin> + </Rectangle> + <Pane HBox.hgrow="ALWAYS" /> + <Label fx:id="tips" alignment="CENTER" contentDisplay="CENTER" text="If you see this, then something went wrong lmao" textFill="WHITE" wrapText="true"> + <font> + <Font name="Helvetica Neue LT Com 53 Extended" size="40.0" /> + </font> + <HBox.margin> + <Insets bottom="50.0" /> + </HBox.margin> + </Label> + <Pane HBox.hgrow="ALWAYS" /> + <ImageView fx:id="throbber" fitHeight="180.0" fitWidth="180.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../textures/images/throbber.gif" /> + </image> + <HBox.margin> + <Insets bottom="50.0" left="50.0" right="50.0" /> + </HBox.margin> + </ImageView> + </children> + <BorderPane.margin> + <Insets /> + </BorderPane.margin> + </HBox> + </bottom> + <center> + <ImageView fx:id="logo" fitHeight="800.0" fitWidth="900.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER"> + <image> + <Image url="@../textures/images/logo_transparent.png" /> + </image> + </ImageView> + </center> +</BorderPane> diff --git a/src/main/resources/fxml/Login.fxml b/src/main/resources/fxml/Login.fxml new file mode 100644 index 0000000000000000000000000000000000000000..a63c7c127ff2c30d0499ffc963851e061324bf58 --- /dev/null +++ b/src/main/resources/fxml/Login.fxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?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="20.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.hdm_stuttgart.battlearena.Controller.LoginController"> + <children> + <Pane VBox.vgrow="ALWAYS" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Login with existing online account" /> + <Pane VBox.vgrow="ALWAYS" /> + <Pane VBox.vgrow="ALWAYS" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Player Name:" /> + <TextField fx:id="playerName" alignment="CENTER" /> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Password:" /> + <TextField fx:id="password" alignment="CENTER" /> + <Label fx:id="errorMessage" /> + <Button mnemonicParsing="false" onAction="#login" text="Login" /> + <Button mnemonicParsing="false" onAction="#back" text="Back" /> + <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/MultiplayerCreate.fxml b/src/main/resources/fxml/MultiplayerCreate.fxml index 3cf21a91e290fca2da1b2516320c1feb50a99cee..f95e2126f13aee4f89541b835ef2c90ffbbc7d9b 100644 --- a/src/main/resources/fxml/MultiplayerCreate.fxml +++ b/src/main/resources/fxml/MultiplayerCreate.fxml @@ -47,7 +47,7 @@ <Insets top="20.0" /> </VBox.margin> </AnchorPane> - <Button mnemonicParsing="false" text="Start" /> + <Button mnemonicParsing="false" onAction="#start" text="Start" /> <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> <Pane VBox.vgrow="ALWAYS" /> <Pane VBox.vgrow="ALWAYS" /> diff --git a/src/main/resources/fxml/Placeholder.fxml b/src/main/resources/fxml/Placeholder.fxml new file mode 100644 index 0000000000000000000000000000000000000000..5b08cde3dfdf168d0e09cc1f005c3f62ac8e09c5 --- /dev/null +++ b/src/main/resources/fxml/Placeholder.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.PlaceholderController"> + <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/PlayerCreateScene.fxml b/src/main/resources/fxml/PlayerCreateScene.fxml index 1563facf396815b701f237fdab3dd7e3769c7951..9a7e5e347bd49fc7a87467f5700922cbf3fdb937 100644 --- a/src/main/resources/fxml/PlayerCreateScene.fxml +++ b/src/main/resources/fxml/PlayerCreateScene.fxml @@ -1,28 +1,17 @@ <?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.Pane?> <?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> +<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.PlayerCreateController"> + <children> + <Pane prefHeight="200.0" prefWidth="200.0" /> + <Button mnemonicParsing="false" onAction="#createScene" text="Create Account" /> + <Button mnemonicParsing="false" onAction="#loginScene" text="Login" /> + <Pane prefHeight="200.0" prefWidth="200.0" /> + <Button mnemonicParsing="false" onAction="#exit" text="Exit" /> + <Pane prefHeight="200.0" prefWidth="200.0" /> + </children> +</VBox> diff --git a/src/main/resources/fxml/Settings.fxml b/src/main/resources/fxml/Settings.fxml index 6cab6585ef8f19e015fc3645684934a599ee9aec..3f84b3167228690e174a053e4d5ba4128fc44e72 100644 --- a/src/main/resources/fxml/Settings.fxml +++ b/src/main/resources/fxml/Settings.fxml @@ -15,19 +15,20 @@ <VBox alignment="CENTER" VBox.vgrow="ALWAYS"> <children> <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Music volume:" /> - <Slider fx:id="musicVolume" blockIncrement="25.0" majorTickUnit="100.0" minorTickCount="1" prefHeight="14.0" prefWidth="480.0" showTickLabels="true" value="75.0" VBox.vgrow="NEVER" /> + <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="sfxVolume" blockIncrement="25.0" majorTickUnit="100.0" minorTickCount="1" prefHeight="14.0" prefWidth="480.0" showTickLabels="true" value="75.0" /> + <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="#account" text="Account" /> <Button mnemonicParsing="false" onAction="#creditScene" text="Credits" /> <Button mnemonicParsing="false" onAction="#backButton" text="Back" /> </children> diff --git a/src/main/resources/fxml/Statistics.fxml b/src/main/resources/fxml/Statistics.fxml index 6c98b4e5e5aa7e8efd880b6945b8c7091aa04d32..42b8646af9788053e25149e8a04a9d3d8f0bfb1f 100644 --- a/src/main/resources/fxml/Statistics.fxml +++ b/src/main/resources/fxml/Statistics.fxml @@ -7,11 +7,11 @@ <?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"> +<VBox fx:id="parent" alignment="CENTER" 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.StatisticsController"> <children> - <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="30.0" VBox.vgrow="ALWAYS"> + <HBox alignment="CENTER" prefHeight="411.0" prefWidth="677.0" spacing="30.0" VBox.vgrow="ALWAYS"> <children> - <VBox alignment="CENTER_RIGHT" prefHeight="200.0" prefWidth="100.0" spacing="10.0" HBox.hgrow="ALWAYS"> + <VBox alignment="CENTER_RIGHT" spacing="10.0" HBox.hgrow="ALWAYS"> <children> <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Kills:" /> <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Deaths:" /> @@ -21,7 +21,7 @@ <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"> + <VBox alignment="CENTER_LEFT" 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" /> @@ -38,11 +38,11 @@ <children> <PieChart fx:id="kd" minHeight="-Infinity" minWidth="-Infinity" VBox.vgrow="ALWAYS"> <VBox.margin> - <Insets bottom="-200.0" /> + <Insets bottom="-200.0" top="-250.0" /> </VBox.margin></PieChart> <PieChart fx:id="wl" minHeight="-Infinity" minWidth="-Infinity" VBox.vgrow="ALWAYS"> <VBox.margin> - <Insets top="-40.0" /> + <Insets bottom="-250.0" top="-40.0" /> </VBox.margin></PieChart> </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..f7d371619fa1db8dd4701e6607908135293b820c --- /dev/null +++ b/src/main/resources/player/appSettings.json @@ -0,0 +1,4 @@ +{ + "sfxVolume": 100, + "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..4db3d0788fb3ff0fe8d593e5baed84279916821b --- /dev/null +++ b/src/main/resources/player/playerStatsLocal.json @@ -0,0 +1,8 @@ +{ + "gamesLost": 0, + "gamesWon": 0, + "kills": 0, + "deaths": 0, + "blocksDestroyed": 0, + "gameTime": 0 +} \ No newline at end of file diff --git a/src/main/resources/sound/music/cocBackgroundMusicTest.mp3 b/src/main/resources/sound/music/cocBackgroundMusicTest.mp3 index e916ecb6c0b6487e9bcb8ca6c3d54f6259eac9dc..fe39b45659600de8eb2ed2bdac281444be461261 100644 Binary files a/src/main/resources/sound/music/cocBackgroundMusicTest.mp3 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 index 4abd8f438011630e16506118234837906d3ceb37..5669e8017883014e447765a405c6ec3b208db5bb 100644 Binary files a/src/main/resources/sound/music/constructionJazz.mp3 and b/src/main/resources/sound/music/constructionJazz.mp3 differ diff --git a/src/main/resources/sound/music/musicPlaceholder.mp3 b/src/main/resources/sound/music/game/musicPlaceholder.mp3 similarity index 100% rename from src/main/resources/sound/music/musicPlaceholder.mp3 rename to src/main/resources/sound/music/game/musicPlaceholder.mp3 diff --git a/src/main/resources/sound/music/menu/musicPlaceholder.wav b/src/main/resources/sound/music/menu/musicPlaceholder.wav new file mode 100644 index 0000000000000000000000000000000000000000..e10258b8b48d0253ca1a3141482ee600c96d58e9 Binary files /dev/null and b/src/main/resources/sound/music/menu/musicPlaceholder.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 1.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 1.wav new file mode 100644 index 0000000000000000000000000000000000000000..fb7dc6572c0c0232ddd17049a0801d8de0ef0035 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 1.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 10.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 10.wav new file mode 100644 index 0000000000000000000000000000000000000000..7edaf5417e8f65c81092fbae60f309d0c469ae44 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 10.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 11.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 11.wav new file mode 100644 index 0000000000000000000000000000000000000000..52dbe6393a2855313ab661be65b0cfa8c85838c8 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 11.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 12.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 12.wav new file mode 100644 index 0000000000000000000000000000000000000000..24f9a5f098b6f55465cfbe41edac6324985396b2 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 12.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 13.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 13.wav new file mode 100644 index 0000000000000000000000000000000000000000..ead5ebf730e986b5300ae859cb7804d9c5025bc6 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 13.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 14.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 14.wav new file mode 100644 index 0000000000000000000000000000000000000000..128c1d579f44bace7190a3c855673eee901c98ec Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 14.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 15.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 15.wav new file mode 100644 index 0000000000000000000000000000000000000000..e2c2c54985afc50b3f3f1de45b6dd68ae8c0db00 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 15.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 16.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 16.wav new file mode 100644 index 0000000000000000000000000000000000000000..b28f00628e321a05293fa07c73503abc9cc9ec37 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 16.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 17.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 17.wav new file mode 100644 index 0000000000000000000000000000000000000000..6481be5c73f1137e3b10f8483819292d3376056b Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 17.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 18.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 18.wav new file mode 100644 index 0000000000000000000000000000000000000000..f828b12669df1b8a01a4956cc178bd0bed24243d Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 18.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 19.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 19.wav new file mode 100644 index 0000000000000000000000000000000000000000..4e2be3515c1fdfc95226033cf304f56be65a5b6c Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 19.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 2.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 2.wav new file mode 100644 index 0000000000000000000000000000000000000000..87570339d853042dd6dc4fcbd7b871ec3afcee34 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 2.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 20.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 20.wav new file mode 100644 index 0000000000000000000000000000000000000000..85a71f7d9764cae6a3220c38393336cf320cb284 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 20.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 3.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 3.wav new file mode 100644 index 0000000000000000000000000000000000000000..ba37dc8a23965323887983518a5e9274ff1938f6 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 3.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 4.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 4.wav new file mode 100644 index 0000000000000000000000000000000000000000..e3acb0eb0e6d900fa67fc2500c06be7ab0383d16 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 4.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 5.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 5.wav new file mode 100644 index 0000000000000000000000000000000000000000..dabe68f4c735ded390aa3de52d293e31ef0b4967 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 5.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 6.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 6.wav new file mode 100644 index 0000000000000000000000000000000000000000..ce9dd0eb336d5129f78ceac527e28f60f39b554f Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 6.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 7.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 7.wav new file mode 100644 index 0000000000000000000000000000000000000000..71e061472f1fddae9fbaa2ae5a186a71f078a008 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 7.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 8.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 8.wav new file mode 100644 index 0000000000000000000000000000000000000000..9b8538a47aaa357ffcbe6bc8223809584be19e2c Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 8.wav differ diff --git a/src/main/resources/sound/sfx/steps/grass/steps - Track 9.wav b/src/main/resources/sound/sfx/steps/grass/steps - Track 9.wav new file mode 100644 index 0000000000000000000000000000000000000000..6ea17cb32406c61630d7975713742719070d3ef6 Binary files /dev/null and b/src/main/resources/sound/sfx/steps/grass/steps - Track 9.wav differ diff --git a/src/main/resources/styles/style.css b/src/main/resources/styles/style.css index 1f2a2030a2e67b98cb0869b5cf205d74b8cc9bca..938f7693c3a76d53bf9a90102efe2633d34cfb66 100644 --- a/src/main/resources/styles/style.css +++ b/src/main/resources/styles/style.css @@ -4,22 +4,43 @@ } #button { - -fx-text-fill: black; + -fx-text-fill: #454545; } .root { - -fx-font-family: "Starship Shadow"; + -fx-font-family: "Arthemis"; -fx-text-fill: white; -fx-background-color: black; + -fx-font-size: 50 px; +} + +#tips { + -fx-font-family: "Amatic SC Bold"; + -fx-font-size: 40 px; } +#loadingScreen { + -fx-background-color: radial-gradient(focus-distance 0% , center 50% 50% , radius 45% , #a31c31, #542b27); +} + +.text-field { + -fx-background-color: transparent; + -fx-text-fill: black; + -fx-border-color: black; + -fx-border-width: 0 0 2 0; + -fx-prompt-text-fill: rgba(0, 0, 0, 0.5); + -fx-font-family: "Shadows Into Light"; +} + + #mainMenu{ -fx-background-image: url("../textures/images/background.png"); -fx-background-size: cover; } #gameTitle { - -fx-font-size: 100; + -fx-font-size: 100 px; + -fx-font-family: "Starship Shadow"; } #gameScene { @@ -35,6 +56,7 @@ #btnLeft { -fx-skin: none; + -fx-text-fill: #7a7a7a; } .accordion { diff --git a/src/main/resources/textures/images/logo_transparent.png b/src/main/resources/textures/images/logo_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..4aa46908f9c28d66b837bfc3d073aab080759127 Binary files /dev/null and b/src/main/resources/textures/images/logo_transparent.png differ diff --git a/src/main/resources/textures/images/logo_transparent_alt.png b/src/main/resources/textures/images/logo_transparent_alt.png new file mode 100644 index 0000000000000000000000000000000000000000..817ba0a2f3103c351277b8598614836c377ce058 Binary files /dev/null and b/src/main/resources/textures/images/logo_transparent_alt.png differ diff --git a/src/main/resources/textures/images/throbber.gif b/src/main/resources/textures/images/throbber.gif new file mode 100644 index 0000000000000000000000000000000000000000..45caf1ef603429f181feebcc5505f4b01f512728 Binary files /dev/null and b/src/main/resources/textures/images/throbber.gif 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/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/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/videos/allMyFellas.mp4 b/src/main/resources/videos/allMyFellas.mp4 index 4234d4da1c07a7e775bced2e4e44c2329c8be972..5371bd89089430d7fa4e467da0e857743a9cdd0b 100644 Binary files a/src/main/resources/videos/allMyFellas.mp4 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 index a1fab12d8d746424ae6390ca6fe9eadef6136d62..4fef92ce7683b37e7e5dd01c5d6561fdaef4310c 100644 Binary files a/src/main/resources/videos/async.mp4 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 index 3d856e404f8b52494492d7a5150f17c7b7e951ec..389d4987f86aa037d333fc7f2c84ecf9d1bc02f8 100644 Binary files a/src/main/resources/videos/banana.mp4 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 index 789d9579969084c45b1592f8e1abc1d6c6599edb..067fcfbcc003a71f39c03b43e1882ceda9e9869c 100644 Binary files a/src/main/resources/videos/basketball.mp4 and b/src/main/resources/videos/basketball.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 index be5ae85619580861cdde91884d74fc44541c127b..28007e146999a02253044e4423819e80ec590c22 100644 Binary files a/src/main/resources/videos/catSitting.mp4 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 index 4557a204bace6e377f812860ca794cf57dba63ad..700b233f8ce39926076fd7870bd6920d603c8d23 100644 Binary files a/src/main/resources/videos/chaCha.mp4 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 index 28c72a6ebeb79d0d858e060ff98e0458d909e4f1..4910d355b7ef46d080954028c2c9376ba7993a92 100644 Binary files a/src/main/resources/videos/cheezburger.mp4 and b/src/main/resources/videos/cheezburger.mp4 differ diff --git a/src/main/resources/videos/credits.mp4 b/src/main/resources/videos/credits.mp4 index cffe4eaf38603cdd817e4957f7a9b717a0578232..410d261aba44faf7e6f2ba606393f76ba1ba526f 100644 Binary files a/src/main/resources/videos/credits.mp4 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 index 863031c0550b6745e167db051bd702e0827b5b32..2f291192b17204d93730dede0be6a24f1fa26066 100644 Binary files a/src/main/resources/videos/dog.mp4 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 index 23cb49a3eedc11cfbcfa4a26d539bbfbef8f67ac..4500f7ae5c2e9d8d1ba8a06fdfb60a0cc47f2d7b 100644 Binary files a/src/main/resources/videos/dog2.mp4 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 index d94d1edf882ca1c57e220ec967b06f897309e106..eb24b7b5f7b5d2eb6a72dcb0b3ac1d3281cd789b 100644 Binary files a/src/main/resources/videos/dogCheese.mp4 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 index f102aa72a92bbe1989cf66c03785bcd937f1d3f7..706941c2cde672b81881056aa759308d67f433c0 100644 Binary files a/src/main/resources/videos/firework.mp4 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 index 33462dcdf3a19edb59598e3320ced6c32f68ad88..e411b29309d38ffa3421e36ed3e9a3f4e9f9ad39 100644 Binary files a/src/main/resources/videos/frog.mp4 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 index 91a1eaa78366adbb3686a07594417fd9c8832126..68821d3565f0efcc9995b2f7afaa220b9ca786eb 100644 Binary files a/src/main/resources/videos/gameboy.mp4 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 index 135416e7b63fc25ed1e3e2b744c6d14a78692b99..a60bade2b34051ffd295a22de564a6476adbe8fc 100644 Binary files a/src/main/resources/videos/gamecube.mp4 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 index c207c9177e116fde566d8bcd0d3a481d28574609..0259ca609572a35adb34f9c7293d49c9e97e37b8 100644 Binary files a/src/main/resources/videos/gta.mp4 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 index 130f80032f69150a59fc7f41746a8cb1370f9738..536961ae8a9414f7b16ac646d4ceb0844d13a23f 100644 Binary files a/src/main/resources/videos/gtfo.mp4 and b/src/main/resources/videos/gtfo.mp4 differ diff --git a/src/main/resources/videos/horse.mp4 b/src/main/resources/videos/horse.mp4 index c9b0cbe5d6b7f5e0d43345e26879225a922339fa..d4f6f7429a9f49344bf63f6602ac35131338b2a0 100644 Binary files a/src/main/resources/videos/horse.mp4 and b/src/main/resources/videos/horse.mp4 differ diff --git a/src/main/resources/videos/kangaroo.mp4 b/src/main/resources/videos/kangaroo.mp4 index 9aec93f34ff0d3dfeaea5aa21f9a74e33634c88f..3cff449b6180fcbdbe367da02416525331ae94af 100644 Binary files a/src/main/resources/videos/kangaroo.mp4 and b/src/main/resources/videos/kangaroo.mp4 differ diff --git a/src/main/resources/videos/minecraftCat2.mp4 b/src/main/resources/videos/minecraftCat2.mp4 index c510f7f42abce6847dce87197d2cb2697e3882df..1e9366af84a9aa9f363655de9b313cab98e77fba 100644 Binary files a/src/main/resources/videos/minecraftCat2.mp4 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 index c6d5f3c2e7f390276d22b26e46f462bb1e281d98..980756e7cd8fa4c3c00d5a246ad179b143c1fae1 100644 Binary files a/src/main/resources/videos/monke.mp4 and b/src/main/resources/videos/monke.mp4 differ diff --git a/src/main/resources/videos/muecke.mp4 b/src/main/resources/videos/muecke.mp4 index 57c8641e7c2c4628f953d579c6f8acc9319e4207..c146f51e85f55df05f872781e4cfb09d5b222b87 100644 Binary files a/src/main/resources/videos/muecke.mp4 and b/src/main/resources/videos/muecke.mp4 differ diff --git a/src/main/resources/videos/rejectHumanity.mp4 b/src/main/resources/videos/rejectHumanity.mp4 index ed006e08e75d76092c2ff9b7a7e89601cc822b32..6c2a377ca00e8f9381095c76661e5de75902b4f0 100644 Binary files a/src/main/resources/videos/rejectHumanity.mp4 and b/src/main/resources/videos/rejectHumanity.mp4 differ diff --git a/src/main/resources/videos/rolling.mp4 b/src/main/resources/videos/rolling.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..07dd01a89cbc742e3a449aa8dae9c99b3f631e43 Binary files /dev/null and b/src/main/resources/videos/rolling.mp4 differ diff --git a/src/main/resources/videos/roomba.mp4 b/src/main/resources/videos/roomba.mp4 index a8d2a9615476bb273b967f99bc007fde2a695d63..65a1e5aebe700b1b720182bf9ceaff3e6e160f88 100644 Binary files a/src/main/resources/videos/roomba.mp4 and b/src/main/resources/videos/roomba.mp4 differ diff --git a/src/main/resources/videos/sad.mp4 b/src/main/resources/videos/sad.mp4 index fd3307de97c5c66f01f35f0274b58d87ced537b5..1868f52e473cad115b0dbe455c642211e5c50e81 100644 Binary files a/src/main/resources/videos/sad.mp4 and b/src/main/resources/videos/sad.mp4 differ diff --git a/src/main/resources/videos/sadHorse.mp4 b/src/main/resources/videos/sadHorse.mp4 index c71f56706fdc239f72875d6206c91a4d40f80b46..dc6901a500652632c29c51d500b369044118ee58 100644 Binary files a/src/main/resources/videos/sadHorse.mp4 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 index 816308c9ae733e457266bf412df8301ef1bdd957..b26ecb1ceda0d65050f5244c98e76af43c717558 100644 Binary files a/src/main/resources/videos/slippery.mp4 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 index 9d96aebfc39a033d379d613070c97e6122f8a175..158c13874cb0cd60ddbc9903b2658d4c0cfd2ded 100644 Binary files a/src/main/resources/videos/sony.mp4 and b/src/main/resources/videos/sony.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