From 6f02f04505b18d1822e57da0eaeef998fbd22f70 Mon Sep 17 00:00:00 2001 From: Martin <ms618@hdm-stuttgart.de> Date: Sun, 7 Jan 2024 22:57:12 +0100 Subject: [PATCH] Update: AzureDB.java (changed Exceptions) Update: OracleDB.java (changed Exceptions Update: Parser.java (renamed method) Update: Persistence.java (methods now public. Moved some methods from RuntimeInfo.java to Persistence.java) Update: RuntimeInfo.java (Moved methods from RuntimeInfo.java to Persistence.java) --- .../Model/DataStorage/Classes/AzureDB.java | 18 +-- .../Model/DataStorage/Classes/OracleDB.java | 18 +-- .../DataStorage/Classes/Persistence.java | 136 +++++++++++++----- .../DataStorage/Classes/RuntimeInfo.java | 111 +++----------- .../DataStorage/Classes/Utilities/Parser.java | 2 +- .../Classes/Utilities/ParserTest.java | 6 +- 6 files changed, 148 insertions(+), 143 deletions(-) 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 index 50c3ed17..b138e769 100644 --- 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 @@ -48,7 +48,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("SQL Connection Error"); + throw new SQLException("SQL Connection Error! " + e.getMessage()); } } @@ -72,7 +72,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving Coremaps"); + throw new SQLException("Error retrieving Coremaps! " + e.getMessage()); } } @@ -96,7 +96,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving community map names"); + throw new SQLException("Error retrieving community map names! " + e.getMessage()); } } @@ -131,7 +131,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving community map"); + throw new SQLException("Error retrieving community map! " + e.getMessage()); } } @@ -154,7 +154,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error uploading created community map"); + throw new SQLException("Error uploading created community map! " + e.getMessage()); } } @@ -174,7 +174,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error creating online account"); + throw new SQLException("Error creating online account! " + e.getMessage()); } } @@ -199,7 +199,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving retrieving player credentials"); + throw new SQLException("Error retrieving retrieving player credentials! " + e.getMessage()); } } @@ -226,7 +226,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving player statistics"); + throw new SQLException("Error retrieving player statistics! " + e.getMessage()); } } @@ -251,7 +251,7 @@ public class AzureDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error updating player statistics"); + throw new SQLException("Error updating player statistics! " + e.getMessage()); } } 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 index 44e2a5a1..070e42d3 100644 --- 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 @@ -47,7 +47,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("SQL connection error"); + throw new SQLException("SQL connection error! " + e.getMessage()); } } @@ -71,7 +71,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving coremaps"); + throw new SQLException("Error retrieving coremaps! " + e.getMessage()); } } @@ -95,7 +95,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving community map names"); + throw new SQLException("Error retrieving community map names! " + e.getMessage()); } } @@ -130,7 +130,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e.getMessage()); - throw new SQLException(e.getMessage()); + throw new SQLException("Error retrieving community map! " + e.getMessage()); } } @@ -153,7 +153,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error uploading created community map"); + throw new SQLException("Error uploading created community map! " + e.getMessage()); } } @@ -173,7 +173,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error creating online account"); + throw new SQLException("Error creating online account! " + e.getMessage()); } } @@ -198,7 +198,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving retrieving player credentials"); + throw new SQLException("Error retrieving retrieving player credentials! " + e.getMessage()); } } @@ -225,7 +225,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error retrieving player statistics"); + throw new SQLException("Error retrieving player statistics! " + e.getMessage()); } } @@ -250,7 +250,7 @@ public class OracleDB implements ISQLDataBase { } catch(Exception e){ log.error(e); - throw new SQLException("Error updating player statistics"); + throw new SQLException("Error updating player statistics! " + 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 index f6e45360..f2af47b5 100644 --- 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 @@ -1,7 +1,11 @@ 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; @@ -23,11 +27,11 @@ public class Persistence { private Persistence (){} - protected static Persistence getInstance(){ + public static Persistence getInstance(){ return persistenceSingleton; } - protected void loadCoreMaps() throws DatabaseException { + public void loadCoreMaps() throws DatabaseException { try { coreMaps = gsonHandler.loadMaps(MapType.COREMAP); log.info("Core-Maps successfully loaded from file"); @@ -38,7 +42,7 @@ public class Persistence { } } - protected void loadCommunityMaps() throws DatabaseException { + public void loadCommunityMaps() throws DatabaseException { try { communityMaps = gsonHandler.loadMaps(MapType.COMMUNITYMAP); log.info("Community-Maps successfully loaded from file"); @@ -49,7 +53,7 @@ public class Persistence { } } - protected void updateCoreMaps() throws DatabaseException { + public void updateCoreMaps() throws DatabaseException { try { coreMaps = db.getCoreMaps(); gsonHandler.saveMaps(coreMaps, MapType.COREMAP); @@ -66,7 +70,12 @@ public class Persistence { } } - protected void getCommunityMap(String mapID) throws DatabaseException { + 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); @@ -86,7 +95,7 @@ public class Persistence { } } - protected void saveCreatedMapLocally(MapData map) throws DatabaseException { + public void saveCreatedMapLocally(MapData map) throws DatabaseException { try { for(int i = 0; communityMaps.size() > i; i++){ if(communityMaps.get(i).getMapID().equals(map.getMapID())){ @@ -103,12 +112,12 @@ public class Persistence { throw new DatabaseException(e.getMessage()); } else{ - throw new DatabaseException("Unknown Database Error. Saving newly created Community-Map failed!"); + throw new DatabaseException("Unknown Database Error. Saving newly created Community-Map locally failed!"); } } } - protected void uploadCreatedMap(MapData map) throws DatabaseException { + public void uploadCreatedMap(MapData map) throws DatabaseException { try { db.uploadCommunityMap(map); log.info("Newly created Community-Map successfully published!"); @@ -127,7 +136,7 @@ public class Persistence { } } - protected void loadSettings() throws DatabaseException { + public void loadSettings() throws DatabaseException { try { settings = gsonHandler.loadSettings(); log.info("Application settings successfully loaded from file"); @@ -138,59 +147,120 @@ public class Persistence { } } - protected void createAccount(String name, String password, AccountType type) throws DatabaseException { + public void createAccount(String playerName, String password, AccountType type) throws DatabaseException { try { - - String hashedPassword = HashGenerator.hashAndHex(password); - - if(type == AccountType.ONLINE) { - try { - db.createPlayer(name, hashedPassword); - } catch (Exception e) { - log.error(e); - throw new DatabaseException("SQL Error"); - } + 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."); } - - account = new PlayerAccount(name, hashedPassword, type); GsonHandler gson = new GsonHandler(); gson.saveAccount(account); } + 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\n" + e.getMessage()); + throw new DatabaseException("Error creating account. Please restart game or download game files again."); } } - protected void loadPlayerAccount() throws DatabaseException { + public void loadPlayerAccount() throws DatabaseException { try { gsonHandler.loadAccount(); } catch(Exception e){ - log.error(e); + log.error(e); throw new DatabaseException("Loading player account data from local storage failed!"); } } - protected void loadPlayerStatistics() throws DatabaseException { + public void verifyPlayerAccount() throws DatabaseException { try { if (account.getAccountState() == AccountType.NONE) { throw new DatabaseException("Must create playerAccount first"); } else if (account.getAccountState() == AccountType.LOCAL) { - statistics = gsonHandler.loadStats(); - } else { - if(account.getPlayerName().equals(db.checkCredentials(account.getPlayerName()))){ //checks if local and remote password match to username - statistics = db.getStatistics(account.getPlayerName()); - } - else{ - throw new DatabaseException("Wrong Password"); + Parser.usernameValid(account.getPlayerName()); + } else if (account.getAccountState() == AccountType.ONLINE) { + Parser.usernameValid(account.getPlayerName()); + Parser.sha1HashValid(account.getAccountPassword()); + if (!(account.getAccountPassword().equals(db.checkCredentials(account.getPlayerName())))){ + throw new DatabaseException("Locally stored password does not match online password. Please renter credentials!"); } } + else{ + throw new DatabaseException("AccountType invalid - accountData corrupted! Please create new Account or login with existing!"); + } + } + 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 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 loadPlayerStatistics() throws DatabaseException { + try { + if (account.getAccountState() == AccountType.LOCAL) { + statistics = gsonHandler.loadStats(); + } else { + statistics = db.getStatistics(account.getPlayerName()); + } + } + 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 updatePlayerStatistics(){ + //check for account type and update statistics in RAM and persistence + } + } 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 index da42301d..6f9c89fe 100644 --- 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 @@ -1,23 +1,22 @@ 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.ParserException; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.HashGenerator; +import de.hdm_stuttgart.battlearena.Model.DataStorage.Classes.Utilities.Parser; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.ArrayList; -import java.util.LinkedHashMap; public class RuntimeInfo { private static final Logger log = LogManager.getLogger(RuntimeInfo.class); private static final RuntimeInfo runtimeInfoSingleton = new RuntimeInfo(); private final Persistence persistenceInst = Persistence.getInstance(); - private LinkedHashMap<String, String> mapNames; //????? protected ArrayList<String> coreMapsListLocal; //for drop-down list protected ArrayList<String> communityMapsListLocal; //for drop-down list protected ArrayList<MapInfo> communityMapsListRemote; //for community map browser protected String mapDataGame; - protected boolean startupComplete = false; private RuntimeInfo(){}; @@ -26,128 +25,64 @@ public class RuntimeInfo { return runtimeInfoSingleton; } - public boolean isStartupComplete() { - return startupComplete; - } - - public void setStartupComplete(boolean startupComplete) { - this.startupComplete = startupComplete; - } - - public void startupPhase1(){ - try { - persistenceInst.loadPlayerAccount(); //must be called before "loadPlayerStatistics()" - //wenn playerAccount type "none" ist, dann Create-Player scene und dafür noch eine "Create account" methode schreiben, die dann auch die Daten mit GSON speichert (verschlüsselt) - //nachdem Player Account erstellt hat, wird die Methode "startup()" neu gestartet - persistenceInst.loadPlayerStatistics(); - } - catch(Exception e){ - log.error(e); - } - } - - public void startupPhase2(){ - try { - persistenceInst.loadSettings(); - persistenceInst.loadCoreMaps(); - persistenceInst.loadCommunityMaps(); - } - catch(Exception e){ - log.error(e); - } - } - public String getMapDataGame() { return mapDataGame; } - public void uploadCreatedMap(MapData mapCreated) throws DatabaseException { - try { - persistenceInst.uploadCreatedMap(mapCreated); - } - catch(Exception e){ - log.error(e); - throw new DatabaseException(e.getMessage()); - } - } - - public void saveCreatedMap(MapData mapCreated) throws DatabaseException { + public MapData createMap(String mapName, String mapData) throws ParserException { try { - persistenceInst.saveCreatedMapLocally(mapCreated); + Parser.mapDataValid(mapData); + Parser.mapNameValid(mapName); + return new MapData(HashGenerator.hashAndHex(mapData), mapName, 19, 19, mapData); } catch(Exception e){ log.error(e); - throw new DatabaseException(e.getMessage()); + throw new ParserException(e.getMessage()); } } - private void setGameMap(String mapSelected, boolean choseCoremaps){ - mapSelected = mapSelected.substring(mapSelected.indexOf("(") + 1, mapSelected.length() - 1); + public void setGameMap(String mapSelected, boolean choseCoremaps){ + String mapID = mapSelected.substring(mapSelected.indexOf("(") + 1, mapSelected.length() - 1); if(choseCoremaps) { - for (int mapListIndex = 0; mapListIndex < persistenceInst.coreMaps.size(); mapListIndex++) { - if (persistenceInst.coreMaps.get(mapListIndex).getMapID().equals("mapSelected")) { - mapDataGame = persistenceInst.coreMaps.get(mapListIndex).getMapID(); + for (int index = 0; index < persistenceInst.coreMaps.size(); index++) { + if (persistenceInst.coreMaps.get(index).getMapID().equals(mapID)) { + mapDataGame = persistenceInst.coreMaps.get(index).getMapID(); } } } else { - for (int mapListIndex = 0; mapListIndex < persistenceInst.communityMaps.size(); mapListIndex++) { - if (persistenceInst.communityMaps.get(mapListIndex).getMapID().equals("mapSelected")) { - mapDataGame = persistenceInst.coreMaps.get(mapListIndex).getMapID(); + for (int index = 0; index < persistenceInst.communityMaps.size(); index++) { + if (persistenceInst.communityMaps.get(index).getMapID().equals(mapID)) { + mapDataGame = persistenceInst.coreMaps.get(index).getMapID(); } } } } - public void getCommunityMap(String mapID) throws DatabaseException { - for(int i = 0; persistenceInst.communityMaps.size() > i; i++){ - if(persistenceInst.communityMaps.get(i).getMapID().equals(mapID)){ - throw new DatabaseException("Identical map already saved locally. See map name: " + persistenceInst.communityMaps.get(i).getMapID()); - } - } - try { - persistenceInst.getCommunityMap(mapID); - } - catch(Exception e){ - log.error(e); - throw new DatabaseException(e.getMessage()); - } - } - - private void updateStats(String outcome, String kills, String deaths, int gameTime){ - //update PlayerStatistics - //update SQL - } - public void createCoreMapsList(){ //for dropdown list in "create" scene + coreMapsListLocal = new ArrayList<String>(); for(int i = 0; i < persistenceInst.coreMaps.size(); i++){ coreMapsListLocal.add(persistenceInst.coreMaps.get(i).getMapName() + " (" + persistenceInst.coreMaps.get(i).getMapID() + ")"); } } - public void createCommunityMapsListLocal(){ //for dropdown list in "create" scene - try { - for (int i = 0; i < persistenceInst.communityMaps.size(); i++) { - communityMapsListLocal.add(persistenceInst.communityMaps.get(i).getMapName() + " (" + persistenceInst.communityMaps.get(i).getMapID() + ")"); - } - } - catch (Exception e){ - log.info(e); + public void createLocalCommunityMapsList(){ //for dropdown list in "create" scene + communityMapsListLocal = new ArrayList<String>(); + for (int i = 0; i < persistenceInst.communityMaps.size(); i++) { + communityMapsListLocal.add(persistenceInst.communityMaps.get(i).getMapName() + " (" + persistenceInst.communityMaps.get(i).getMapID() + ")"); } } - //if no Data in JSON throw Exception and inform user - public void fetchCommunityMapListRemote(){ + public void createRemoteCommunityMapsList(){ //for Map-Browser try { communityMapsListRemote = persistenceInst.db.getCommunityMapsList(); log.info("MapList successfully retrieved from server!"); - log.info(communityMapsListRemote.get(0).getMapName()); //for testing purposes + //log.info(communityMapsListRemote.get(0).getMapName()); //for testing purposes } catch(Exception e){ log.error(e); } } - } 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 index f4e716fa..a061c289 100644 --- 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 @@ -67,7 +67,7 @@ public class Parser { } } - public static void mapIDValid(String mapID) throws ParserException { + public static void sha1HashValid(String mapID) throws ParserException { if(!(mapID.length() == 40)){ throw new ParserException("Map-ID length not correct. Must have length of 40 characters!"); 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 index 77b58ca1..e6810e41 100644 --- 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 @@ -74,16 +74,16 @@ class ParserTest { "e559d8fbb53b333f5839cb3c6c0c515395afe344", "a593cafd1d061f0f463a2d2051bf4718aaaf5c48"}) void mapIDValid(String test){ - assertDoesNotThrow(() -> Parser.mapIDValid(test)); + assertDoesNotThrow(() -> Parser.sha1HashValid(test)); } @Test void mapIDValidException() { - ParserException testMe = assertThrows(ParserException.class, () -> Parser.mapIDValid("jiaodjidsfjoisjdiofjsiofjidosfijsodfjisdfjoi")); + ParserException testMe = assertThrows(ParserException.class, () -> Parser.sha1HashValid("jiaodjidsfjoisjdiofjsiofjidosfijsodfjisdfjoi")); assertTrue(testMe.getMessage().contains("Map-ID length not correct. Must have length of 40 characters!")); - testMe = assertThrows(ParserException.class, () -> Parser.mapIDValid("XYZ3cafd1d061f0f463a2d2051bf4718aaaf5c48")); + testMe = assertThrows(ParserException.class, () -> Parser.sha1HashValid("XYZ3cafd1d061f0f463a2d2051bf4718aaaf5c48")); assertTrue(testMe.getMessage().contains("Forbidden characters used! Map ID only consists out of letters a-f and/or numbers 0-9!")); } -- GitLab