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