Просмотр исходного кода

Configuration rework

Renamed several configurations with proper names.
Added OWNER library (same as Login Server) for better properties
handling.
Reduced static code and split configurations on own classes (actually
interfaces).
Moved configurations to proper files.
Added Server configurations.
Added Database configurations.
Added Castle configurations.
Added Clan configurations.
Added Clan Hall configurations.
Added Fortress configurations.
Added Seven Sings configurations.
Added TvT Event configurations.
Added NPC configurations.
Added Olympiad configurations.
Added Flood Protector configurations.
Added Fort Siege configurations.
Added General configurations.
Added Gracia Seeds configurations.
Added Grand Boss configurations.
Added Hex Id configurations.
Added Id Factory configurations.
Added PvP configurations.
Added Rates configurations.
Added Siege configurations.
Added Territory War configurations.
Added Vitality configurations.
Adding Color, Control Tower, File Converter, Flame Tower, Hex Id, IP
Limit, Item Chance Holder, Item Holder, Key-Value, Location, Minutes 2
Milliseconds, Pattern, Seconds 2 Milliseconds, Server List Type and
Skill Holder converters.
Removed generic Feature configurations.
Added Item, Skill, Location, Pattern and Key-Value converters.
Configurations use hot reload, check each to see interval (20 min in
most of them).

Code review: HorridoJoho
Testing: HD321kbps, Zoey76
Zoey76 5 лет назад
Родитель
Сommit
01543e66c2
100 измененных файлов с 6562 добавлено и 4289 удалено
  1. 6 5
      .gitignore
  2. 6 0
      pom.xml
  3. 6 5
      src/main/java/com/l2jserver/gameserver/FortUpdater.java
  4. 43 39
      src/main/java/com/l2jserver/gameserver/GameServer.java
  5. 24 4
      src/main/java/com/l2jserver/gameserver/GeoData.java
  6. 7 6
      src/main/java/com/l2jserver/gameserver/ItemsAutoDestroy.java
  7. 58 23
      src/main/java/com/l2jserver/gameserver/LoginServerThread.java
  8. 22 20
      src/main/java/com/l2jserver/gameserver/RecipeController.java
  9. 8 7
      src/main/java/com/l2jserver/gameserver/SevenSigns.java
  10. 34 30
      src/main/java/com/l2jserver/gameserver/SevenSignsFestival.java
  11. 7 5
      src/main/java/com/l2jserver/gameserver/Shutdown.java
  12. 26 21
      src/main/java/com/l2jserver/gameserver/ThreadPoolManager.java
  13. 13 12
      src/main/java/com/l2jserver/gameserver/ai/L2AttackableAI.java
  14. 2 2
      src/main/java/com/l2jserver/gameserver/ai/L2CharacterAI.java
  15. 3 3
      src/main/java/com/l2jserver/gameserver/ai/L2SummonAI.java
  16. 10 8
      src/main/java/com/l2jserver/gameserver/cache/HtmCache.java
  17. 4 3
      src/main/java/com/l2jserver/gameserver/cache/WarehouseCacheManager.java
  18. 135 0
      src/main/java/com/l2jserver/gameserver/config/CastleConfiguration.java
  19. 637 0
      src/main/java/com/l2jserver/gameserver/config/CharacterConfiguration.java
  20. 171 0
      src/main/java/com/l2jserver/gameserver/config/ClanConfiguration.java
  21. 211 0
      src/main/java/com/l2jserver/gameserver/config/ClanHallConfiguration.java
  22. 0 3724
      src/main/java/com/l2jserver/gameserver/config/Config.java
  23. 197 0
      src/main/java/com/l2jserver/gameserver/config/Configuration.java
  24. 277 0
      src/main/java/com/l2jserver/gameserver/config/CustomsConfiguration.java
  25. 64 0
      src/main/java/com/l2jserver/gameserver/config/DatabaseConfiguration.java
  26. 281 0
      src/main/java/com/l2jserver/gameserver/config/FloodProtectorConfiguration.java
  27. 470 0
      src/main/java/com/l2jserver/gameserver/config/FortSiegeConfiguration.java
  28. 103 0
      src/main/java/com/l2jserver/gameserver/config/FortressConfiguration.java
  29. 626 0
      src/main/java/com/l2jserver/gameserver/config/GeneralConfiguration.java
  30. 103 0
      src/main/java/com/l2jserver/gameserver/config/GeodataConfiguration.java
  31. 46 0
      src/main/java/com/l2jserver/gameserver/config/GraciaSeedsConfiguration.java
  32. 95 0
      src/main/java/com/l2jserver/gameserver/config/GrandBossConfiguration.java
  33. 52 0
      src/main/java/com/l2jserver/gameserver/config/HexIdConfiguration.java
  34. 175 0
      src/main/java/com/l2jserver/gameserver/config/IPConfigData.java
  35. 55 0
      src/main/java/com/l2jserver/gameserver/config/MMOConfiguration.java
  36. 195 0
      src/main/java/com/l2jserver/gameserver/config/NPCConfiguration.java
  37. 181 0
      src/main/java/com/l2jserver/gameserver/config/OlympiadConfiguration.java
  38. 0 195
      src/main/java/com/l2jserver/gameserver/config/PropertiesParser.java
  39. 63 0
      src/main/java/com/l2jserver/gameserver/config/PvPConfiguration.java
  40. 178 0
      src/main/java/com/l2jserver/gameserver/config/RatesConfiguration.java
  41. 90 0
      src/main/java/com/l2jserver/gameserver/config/ServerConfiguration.java
  42. 112 0
      src/main/java/com/l2jserver/gameserver/config/SevenSingsConfiguration.java
  43. 272 0
      src/main/java/com/l2jserver/gameserver/config/SiegeConfiguration.java
  44. 54 0
      src/main/java/com/l2jserver/gameserver/config/TelnetConfiguration.java
  45. 73 0
      src/main/java/com/l2jserver/gameserver/config/TerritoryWarConfiguration.java
  46. 158 0
      src/main/java/com/l2jserver/gameserver/config/TvTConfiguration.java
  47. 73 0
      src/main/java/com/l2jserver/gameserver/config/VitalityConfiguration.java
  48. 64 0
      src/main/java/com/l2jserver/gameserver/config/converter/ClassMasterSetting.java
  49. 79 0
      src/main/java/com/l2jserver/gameserver/config/converter/ClassMasterSettingConverter.java
  50. 42 0
      src/main/java/com/l2jserver/gameserver/config/converter/ColorConverter.java
  51. 51 0
      src/main/java/com/l2jserver/gameserver/config/converter/ControlTowerConverter.java
  52. 46 0
      src/main/java/com/l2jserver/gameserver/config/converter/FileConverter.java
  53. 57 0
      src/main/java/com/l2jserver/gameserver/config/converter/FlameTowerConverter.java
  54. 41 0
      src/main/java/com/l2jserver/gameserver/config/converter/HexIdConverter.java
  55. 58 0
      src/main/java/com/l2jserver/gameserver/config/converter/IPLimitConverter.java
  56. 44 0
      src/main/java/com/l2jserver/gameserver/config/converter/ItemChanceHolderConverter.java
  57. 44 0
      src/main/java/com/l2jserver/gameserver/config/converter/ItemHolderConverter.java
  58. 51 0
      src/main/java/com/l2jserver/gameserver/config/converter/LocationConverter.java
  59. 49 0
      src/main/java/com/l2jserver/gameserver/config/converter/MapIntegerFloatConverter.java
  60. 49 0
      src/main/java/com/l2jserver/gameserver/config/converter/MapIntegerIntegerConverter.java
  61. 42 0
      src/main/java/com/l2jserver/gameserver/config/converter/Minutes2MillisecondsConverter.java
  62. 48 0
      src/main/java/com/l2jserver/gameserver/config/converter/PatternConverter.java
  63. 42 0
      src/main/java/com/l2jserver/gameserver/config/converter/Seconds2MillisecondsConverter.java
  64. 78 0
      src/main/java/com/l2jserver/gameserver/config/converter/ServerListTypeConverter.java
  65. 44 0
      src/main/java/com/l2jserver/gameserver/config/converter/SkillHolderConverter.java
  66. 5 4
      src/main/java/com/l2jserver/gameserver/dao/factory/impl/DAOFactory.java
  67. 3 2
      src/main/java/com/l2jserver/gameserver/dao/impl/mysql/PetSkillSaveDAOMySQL.java
  68. 3 1
      src/main/java/com/l2jserver/gameserver/dao/impl/mysql/PlayerDAOMySQLImpl.java
  69. 3 2
      src/main/java/com/l2jserver/gameserver/dao/impl/mysql/PlayerSkillSaveDAOMySQLImpl.java
  70. 3 2
      src/main/java/com/l2jserver/gameserver/dao/impl/mysql/ServitorSkillSaveDAOMySQLImpl.java
  71. 4 3
      src/main/java/com/l2jserver/gameserver/dao/impl/mysql/SkillDAOMySQLImpl.java
  72. 3 2
      src/main/java/com/l2jserver/gameserver/data/json/ExperienceData.java
  73. 5 4
      src/main/java/com/l2jserver/gameserver/data/sql/impl/CharNameTable.java
  74. 4 3
      src/main/java/com/l2jserver/gameserver/data/sql/impl/CharSummonTable.java
  75. 4 3
      src/main/java/com/l2jserver/gameserver/data/sql/impl/ClanTable.java
  76. 3 2
      src/main/java/com/l2jserver/gameserver/data/sql/impl/NpcBufferTable.java
  77. 8 8
      src/main/java/com/l2jserver/gameserver/data/sql/impl/OfflineTradersTable.java
  78. 3 2
      src/main/java/com/l2jserver/gameserver/data/sql/impl/PetNameTable.java
  79. 3 2
      src/main/java/com/l2jserver/gameserver/data/sql/impl/TeleportLocationTable.java
  80. 3 2
      src/main/java/com/l2jserver/gameserver/data/xml/impl/BuyListData.java
  81. 0 5
      src/main/java/com/l2jserver/gameserver/data/xml/impl/EnchantSkillGroupsData.java
  82. 3 2
      src/main/java/com/l2jserver/gameserver/data/xml/impl/InitialEquipmentData.java
  83. 6 9
      src/main/java/com/l2jserver/gameserver/data/xml/impl/MultisellData.java
  84. 3 2
      src/main/java/com/l2jserver/gameserver/data/xml/impl/NpcData.java
  85. 5 4
      src/main/java/com/l2jserver/gameserver/data/xml/impl/PlayerXpPercentLostData.java
  86. 3 2
      src/main/java/com/l2jserver/gameserver/data/xml/impl/SkillTreesData.java
  87. 43 40
      src/main/java/com/l2jserver/gameserver/datatables/AugmentationData.java
  88. 10 9
      src/main/java/com/l2jserver/gameserver/datatables/BotReportTable.java
  89. 12 11
      src/main/java/com/l2jserver/gameserver/datatables/ItemTable.java
  90. 3 2
      src/main/java/com/l2jserver/gameserver/datatables/MerchantPriceConfigTable.java
  91. 3 2
      src/main/java/com/l2jserver/gameserver/datatables/SkillData.java
  92. 7 5
      src/main/java/com/l2jserver/gameserver/datatables/SpawnTable.java
  93. 6 4
      src/main/java/com/l2jserver/gameserver/engines/DocumentEngine.java
  94. 1 10
      src/main/java/com/l2jserver/gameserver/enums/IllegalActionPunishmentType.java
  95. 4 3
      src/main/java/com/l2jserver/gameserver/handler/CommunityBoardHandler.java
  96. 3 2
      src/main/java/com/l2jserver/gameserver/idfactory/CompactionIDFactory.java
  97. 12 11
      src/main/java/com/l2jserver/gameserver/idfactory/IdFactory.java
  98. 12 0
      src/main/java/com/l2jserver/gameserver/idfactory/IdFactoryType.java
  99. 3 2
      src/main/java/com/l2jserver/gameserver/idfactory/StackIDFactory.java
  100. 11 10
      src/main/java/com/l2jserver/gameserver/instancemanager/AntiFeedManager.java

+ 6 - 5
.gitignore

@@ -1,7 +1,8 @@
-/.project
-/.classpath
-/.settings/
-/.idea/
-/target/
+.project
+.classpath
+.settings/
+.idea/
+target/
 logs/
+test-output/
 hexid.txt

+ 6 - 0
pom.xml

@@ -15,6 +15,7 @@
 		<InMemoryJavaCompiler.version>1.3.0</InMemoryJavaCompiler.version>
 		<gson.version>2.8.5</gson.version>
 		<weupnp.version>0.1.4</weupnp.version>
+		<owner.version>1.0.10</owner.version>
 		<l2j-server-mmocore.version>2.6.1.0</l2j-server-mmocore.version>
 		<l2j-server-commons.version>2.6.1.1</l2j-server-commons.version>
 		<l2j-server-geo-driver.version>2.6.1.0</l2j-server-geo-driver.version>
@@ -107,6 +108,11 @@
 			<artifactId>weupnp</artifactId>
 			<version>${weupnp.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>org.aeonbits.owner</groupId>
+			<artifactId>owner-java8</artifactId>
+			<version>${owner.version}</version>
+		</dependency>
 		<!-- L2J -->
 		<dependency>
 			<groupId>org.bitbucket.l2jserver</groupId>

+ 6 - 5
src/main/java/com/l2jserver/gameserver/FortUpdater.java

@@ -18,10 +18,11 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.fortress;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.L2Clan;
 import com.l2jserver.gameserver.model.entity.Fort;
 import com.l2jserver.gameserver.model.itemcontainer.Inventory;
@@ -63,9 +64,9 @@ public class FortUpdater implements Runnable {
 					_fort.getOwnerClan().increaseBloodOathCount();
 					
 					if (_fort.getFortState() == 2) {
-						if (_clan.getWarehouse().getAdena() >= Config.FS_FEE_FOR_CASTLE) {
-							_clan.getWarehouse().destroyItemByItemId("FS_fee_for_Castle", Inventory.ADENA_ID, Config.FS_FEE_FOR_CASTLE, null, null);
-							_fort.getContractedCastle().addToTreasuryNoTax(Config.FS_FEE_FOR_CASTLE);
+						if (_clan.getWarehouse().getAdena() >= fortress().getFeeForCastle()) {
+							_clan.getWarehouse().destroyItemByItemId("FS_fee_for_Castle", Inventory.ADENA_ID, fortress().getFeeForCastle(), null, null);
+							_fort.getContractedCastle().addToTreasuryNoTax(fortress().getFeeForCastle());
 							_fort.raiseSupplyLvL();
 						} else {
 							_fort.setFortState(1, 0);
@@ -78,7 +79,7 @@ public class FortUpdater implements Runnable {
 					if ((_fort.getOwnerClan() == null) || (_fort.getOwnerClan() != _clan)) {
 						return;
 					}
-					if (_fort.getOwnedTime() > (Config.FS_MAX_OWN_TIME * 3600)) {
+					if (_fort.getOwnedTime() > (fortress().getMaxKeepTime() * 3600)) {
 						_fort.removeOwner(true);
 						_fort.setFortState(0, 0);
 					}

+ 43 - 39
src/main/java/com/l2jserver/gameserver/GameServer.java

@@ -18,6 +18,14 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.customs;
+import static com.l2jserver.gameserver.config.Configuration.database;
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static com.l2jserver.gameserver.config.Configuration.geodata;
+import static com.l2jserver.gameserver.config.Configuration.hexId;
+import static com.l2jserver.gameserver.config.Configuration.mmo;
+import static com.l2jserver.gameserver.config.Configuration.server;
+import static com.l2jserver.gameserver.config.Configuration.telnet;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import java.awt.Toolkit;
@@ -25,7 +33,6 @@ import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.nio.file.Paths;
 import java.util.Calendar;
 import java.util.logging.LogManager;
 
@@ -39,7 +46,6 @@ import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.commons.util.IPv4Filter;
 import com.l2jserver.commons.util.Util;
 import com.l2jserver.gameserver.cache.HtmCache;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.dao.factory.impl.DAOFactory;
 import com.l2jserver.gameserver.data.json.ExperienceData;
 import com.l2jserver.gameserver.data.sql.impl.AnnouncementsTable;
@@ -175,13 +181,13 @@ public final class GameServer {
 		final var serverLoadStart = System.currentTimeMillis();
 		printSection("Database");
 		ConnectionFactory.builder() //
-			.withDriver(Config.DATABASE_DRIVER) //
-			.withUrl(Config.DATABASE_URL) //
-			.withUser(Config.DATABASE_LOGIN) //
-			.withPassword(Config.DATABASE_PASSWORD) //
-			.withConnectionPool(Config.DATABASE_CONNECTION_POOL) //
-			.withMaxIdleTime(Config.DATABASE_MAX_IDLE_TIME) //
-			.withMaxPoolSize(Config.DATABASE_MAX_CONNECTIONS) //
+			.withDriver(database().getDriver()) //
+			.withUrl(database().getURL()) //
+			.withUser(database().getUser()) //
+			.withPassword(database().getPassword()) //
+			.withConnectionPool(database().getConnectionPool()) //
+			.withMaxIdleTime(database().getMaxIdleTime()) //
+			.withMaxPoolSize(database().getMaxConnections()) //
 			.build();
 		
 		DAOFactory.getInstance();
@@ -259,7 +265,7 @@ public final class GameServer {
 		printSection("Geodata");
 		GeoData.getInstance();
 		
-		if (Config.PATHFINDING > 0) {
+		if (geodata().getPathFinding() > 0) {
 			PathFinding.getInstance();
 		}
 		
@@ -304,7 +310,7 @@ public final class GameServer {
 		AirShipManager.getInstance();
 		GraciaSeedsManager.getInstance();
 		
-		ScriptEngineManager.getInstance().executeScriptList(new File(Config.DATAPACK_ROOT, "data/scripts.cfg"));
+		ScriptEngineManager.getInstance().executeScriptList(new File(server().getDatapackRoot(), "data/scripts.cfg"));
 		
 		SpawnTable.getInstance().load();
 		DayNightSpawnManager.getInstance().trim().notifyChangeMode();
@@ -326,11 +332,11 @@ public final class GameServer {
 		printSection("Quests");
 		QuestManager.getInstance().report();
 		
-		if (Config.SAVE_DROPPED_ITEM) {
+		if (general().saveDroppedItem()) {
 			ItemsOnGroundManager.getInstance();
 		}
 		
-		if ((Config.AUTODESTROY_ITEM_AFTER > 0) || (Config.HERB_AUTO_DESTROY_TIME > 0)) {
+		if ((general().getAutoDestroyDroppedItemAfter() > 0) || (general().getAutoDestroyHerbTime() > 0)) {
 			ItemsAutoDestroy.getInstance();
 		}
 		
@@ -340,7 +346,7 @@ public final class GameServer {
 		AutoSpawnHandler.getInstance();
 		FaenorScriptEngine.getInstance();
 		
-		if (Config.L2JMOD_ALLOW_WEDDING) {
+		if (customs().allowWedding()) {
 			CoupleManager.getInstance();
 		}
 		
@@ -348,7 +354,7 @@ public final class GameServer {
 		
 		AntiFeedManager.getInstance().registerEvent(AntiFeedManager.GAME_ID);
 		
-		if (Config.ALLOW_MAIL) {
+		if (general().allowMail()) {
 			MailManager.getInstance();
 		}
 		
@@ -361,11 +367,11 @@ public final class GameServer {
 		TvTManager.getInstance();
 		KnownListUpdateTaskManager.getInstance();
 		
-		if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS) {
+		if ((customs().offlineTradeEnable() || customs().offlineCraftEnable()) && customs().restoreOffliners()) {
 			OfflineTradersTable.getInstance().restoreOfflineTraders();
 		}
 		
-		if (Config.DEADLOCK_DETECTOR) {
+		if (general().deadLockDetector()) {
 			_deadDetectThread = new DeadLockDetector();
 			_deadDetectThread.setDaemon(true);
 			_deadDetectThread.start();
@@ -382,64 +388,62 @@ public final class GameServer {
 		LoginServerThread.getInstance().start();
 		
 		final SelectorConfig sc = new SelectorConfig();
-		sc.MAX_READ_PER_PASS = Config.MMO_MAX_READ_PER_PASS;
-		sc.MAX_SEND_PER_PASS = Config.MMO_MAX_SEND_PER_PASS;
-		sc.SLEEP_TIME = Config.MMO_SELECTOR_SLEEP_TIME;
-		sc.HELPER_BUFFER_COUNT = Config.MMO_HELPER_BUFFER_COUNT;
-		sc.TCP_NODELAY = Config.MMO_TCP_NODELAY;
+		sc.MAX_READ_PER_PASS = mmo().getMaxReadPerPass();
+		sc.MAX_SEND_PER_PASS = mmo().getMaxSendPerPass();
+		sc.SLEEP_TIME = mmo().getSleepTime();
+		sc.HELPER_BUFFER_COUNT = mmo().getHelperBufferCount();
+		sc.TCP_NODELAY = mmo().isTcpNoDelay();
 		
 		_gamePacketHandler = new L2GamePacketHandler();
 		_selectorThread = new SelectorThread<>(sc, _gamePacketHandler, _gamePacketHandler, _gamePacketHandler, new IPv4Filter());
 		
 		InetAddress bindAddress = null;
-		if (!Config.GAMESERVER_HOSTNAME.equals("*")) {
+		if (!server().getHost().equals("*")) {
 			try {
-				bindAddress = InetAddress.getByName(Config.GAMESERVER_HOSTNAME);
+				bindAddress = InetAddress.getByName(server().getHost());
 			} catch (UnknownHostException ex) {
 				LOG.warn("Bind address is invalid, using all avaliable IPs!", ex);
 			}
 		}
 		
 		try {
-			_selectorThread.openServerSocket(bindAddress, Config.PORT_GAME);
+			_selectorThread.openServerSocket(bindAddress, server().getPort());
 			_selectorThread.start();
-			LOG.info("Now listening on {}:{}", Config.GAMESERVER_HOSTNAME, Config.PORT_GAME);
+			LOG.info("Now listening on {}:{}", server().getHost(), server().getPort());
 		} catch (IOException ex) {
 			LOG.error("Failed to open server socket!", ex);
 			System.exit(1);
 		}
 		
-		if (Config.ENABLE_UPNP) {
+		if (server().enableUPnP()) {
 			printSection("UPnP");
-			UPnPService.getInstance().load(Config.PORT_GAME, "L2J Game Server");
+			UPnPService.getInstance().load(server().getPort(), "L2J Game Server");
 		}
 		
-		if (Config.TELNET_ENABLED) {
-			new Status(Config.TELNET_PORT, Config.TELNET_PASSWORD).start();
+		if (telnet().isEnabled()) {
+			new Status(telnet().getPort(), telnet().getPassword()).start();
 		} else {
 			LOG.info("Telnet server is currently disabled.");
 		}
 		
-		LOG.info("Maximum numbers of connected players {}.", Config.MAXIMUM_ONLINE_USERS);
-		LOG.info("Server {} loaded in {} seconds.", ServerNameDAO.getServer(Config.SERVER_ID), MILLISECONDS.toSeconds(System.currentTimeMillis() - serverLoadStart));
+		LOG.info("Maximum numbers of connected players {}.", server().getMaxOnlineUsers());
+		LOG.info("Server {} loaded in {} seconds.", ServerNameDAO.getServer(hexId().getServerID()), MILLISECONDS.toSeconds(System.currentTimeMillis() - serverLoadStart));
 	}
 	
 	public static void main(String[] args) throws Exception {
-		Config.load();
-		
-		final String dataPack = Util.parseArg(args, DATAPACK, true);
-		if (dataPack != null) {
-			Config.DATAPACK_ROOT = new File(dataPack);
+		final String datapackRoot = Util.parseArg(args, DATAPACK, true);
+		if (datapackRoot != null) {
+			server().setProperty("DatapackRoot", datapackRoot);
 		}
 		
 		final String scriptRoot = Util.parseArg(args, SCRIPT, true);
 		if (scriptRoot != null) {
-			Config.SCRIPT_ROOT = new File(scriptRoot);
+			server().setProperty("ScriptRoot", scriptRoot);
 		}
 		
 		final String geodata = Util.parseArg(args, GEODATA, true);
 		if (geodata != null) {
-			Config.GEODATA_PATH = Paths.get(geodata);
+			geodata().setProperty("GeoDataPath", geodata);
 		}
 		
 		gameServer = new GameServer();

+ 24 - 4
src/main/java/com/l2jserver/gameserver/GeoData.java

@@ -18,13 +18,16 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.geodata;
+
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.DoorData;
 import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.L2World;
@@ -53,22 +56,26 @@ public class GeoData {
 	
 	private static final int SPAWN_Z_DELTA_LIMIT = 100;
 	
+	private static final Map<String, Boolean> GEODATA_REGIONS = new HashMap<>();
+	
 	private final GeoDriver _driver = new GeoDriver();
 	
 	protected GeoData() {
+		loadGeodataRegions();
+		
 		int loadedRegions = 0;
 		try {
 			for (int regionX = L2World.TILE_X_MIN; regionX <= L2World.TILE_X_MAX; regionX++) {
 				for (int regionY = L2World.TILE_Y_MIN; regionY <= L2World.TILE_Y_MAX; regionY++) {
-					final Path geoFilePath = Config.GEODATA_PATH.resolve(String.format(FILE_NAME_FORMAT, regionX, regionY));
-					final Boolean loadFile = Config.GEODATA_REGIONS.get(regionX + "_" + regionY);
+					final Path geoFilePath = geodata().getGeoDataPath().toPath().resolve(String.format(FILE_NAME_FORMAT, regionX, regionY));
+					final Boolean loadFile = GEODATA_REGIONS.get(regionX + "_" + regionY);
 					if (loadFile != null) {
 						if (loadFile) {
 							LOG.info("Loading {}...", geoFilePath.getFileName());
 							_driver.loadRegion(geoFilePath, regionX, regionY);
 							loadedRegions++;
 						}
-					} else if (Config.TRY_LOAD_UNSPECIFIED_REGIONS && Files.exists(geoFilePath)) {
+					} else if (geodata().tryLoadUnspecifiedRegions() && Files.exists(geoFilePath)) {
 						try {
 							LOG.info("Loading {}...", geoFilePath.getFileName());
 							_driver.loadRegion(geoFilePath, regionX, regionY);
@@ -87,6 +94,19 @@ public class GeoData {
 		LOG.info("Loaded {} regions.", loadedRegions);
 	}
 	
+	private static void loadGeodataRegions() {
+		for (int regionX = L2World.TILE_X_MIN; regionX <= L2World.TILE_X_MAX; regionX++) {
+			for (int regionY = L2World.TILE_Y_MIN; regionY <= L2World.TILE_Y_MAX; regionY++) {
+				String key = regionX + "_" + regionY;
+				if (geodata().getIncludedRegions().contains(regionX + "_" + regionY)) {
+					GEODATA_REGIONS.put(key, true);
+				} else if (geodata().getExcludedRegions().contains(regionX + "_" + regionY)) {
+					GEODATA_REGIONS.put(key, false);
+				}
+			}
+		}
+	}
+	
 	public boolean hasGeoPos(int geoX, int geoY) {
 		return _driver.hasGeoPos(geoX, geoY);
 	}

+ 7 - 6
src/main/java/com/l2jserver/gameserver/ItemsAutoDestroy.java

@@ -18,10 +18,11 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.enums.ItemLocation;
 import com.l2jserver.gameserver.instancemanager.ItemsOnGroundManager;
 import com.l2jserver.gameserver.model.L2World;
@@ -58,27 +59,27 @@ public final class ItemsAutoDestroy {
 						L2World.getInstance().removeVisibleObject(item, item.getWorldRegion());
 						L2World.getInstance().removeObject(item);
 						_items.remove(item.getObjectId());
-						if (Config.SAVE_DROPPED_ITEM) {
+						if (general().saveDroppedItem()) {
 							ItemsOnGroundManager.getInstance().removeObject(item);
 						}
 					}
 				} else if (item.getItem().hasExImmediateEffect()) {
-					if ((curtime - item.getDropTime()) > Config.HERB_AUTO_DESTROY_TIME) {
+					if ((curtime - item.getDropTime()) > general().getAutoDestroyHerbTime()) {
 						L2World.getInstance().removeVisibleObject(item, item.getWorldRegion());
 						L2World.getInstance().removeObject(item);
 						_items.remove(item.getObjectId());
-						if (Config.SAVE_DROPPED_ITEM) {
+						if (general().saveDroppedItem()) {
 							ItemsOnGroundManager.getInstance().removeObject(item);
 						}
 					}
 				} else {
-					final long sleep = ((Config.AUTODESTROY_ITEM_AFTER == 0) ? 3600000 : Config.AUTODESTROY_ITEM_AFTER * 1000);
+					final long sleep = ((general().getAutoDestroyDroppedItemAfter() == 0) ? 3600000 : general().getAutoDestroyDroppedItemAfter() * 1000);
 					
 					if ((curtime - item.getDropTime()) > sleep) {
 						L2World.getInstance().removeVisibleObject(item, item.getWorldRegion());
 						L2World.getInstance().removeObject(item);
 						_items.remove(item.getObjectId());
-						if (Config.SAVE_DROPPED_ITEM) {
+						if (general().saveDroppedItem()) {
 							ItemsOnGroundManager.getInstance().removeObject(item);
 						}
 					}

+ 58 - 23
src/main/java/com/l2jserver/gameserver/LoginServerThread.java

@@ -18,7 +18,14 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static com.l2jserver.gameserver.config.Configuration.hexId;
+import static com.l2jserver.gameserver.config.Configuration.ip;
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -35,6 +42,7 @@ import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -46,7 +54,6 @@ import com.l2jserver.commons.network.BaseSendablePacket;
 import com.l2jserver.commons.security.crypt.NewCrypt;
 import com.l2jserver.commons.util.Rnd;
 import com.l2jserver.commons.util.Util;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.L2World;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.L2GameClient;
@@ -76,9 +83,17 @@ import com.l2jserver.gameserver.network.serverpackets.LoginFail;
 import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
 
 public class LoginServerThread extends Thread {
+	
 	protected static final Logger LOG = LoggerFactory.getLogger(LoginServerThread.class);
+	
 	protected static final Logger LOG_ACCOUNTING = LoggerFactory.getLogger("accounting");
 	
+	private static final String HEXID_FILE = "./config/hexid.txt";
+	
+	private static final int TEENAGER = 15;
+	
+	private static final int ADULT = 18;
+	
 	/** @see com.l2jserver.loginserver.L2LoginServer#PROTOCOL_REV */
 	private static final int REVISION = 0x0106;
 	private final String _hostname;
@@ -109,27 +124,25 @@ public class LoginServerThread extends Thread {
 	private final List<String> _subnets;
 	private final List<String> _hosts;
 	
-	/**
-	 * Instantiates a new login server thread.
-	 */
 	protected LoginServerThread() {
 		super("LoginServerThread");
-		_port = Config.GAME_SERVER_LOGIN_PORT;
-		_gamePort = Config.PORT_GAME;
-		_hostname = Config.GAME_SERVER_LOGIN_HOST;
-		_hexID = Config.HEX_ID;
-		if (_hexID == null) {
-			_requestID = Config.REQUEST_ID;
+		_port = server().getLoginPort();
+		_gamePort = server().getPort();
+		_hostname = server().getLoginHost();
+		if (hexId().getHexID() == null) {
 			_hexID = Util.generateHex(16);
+			_requestID = server().getRequestServerId();
+			hexId().setProperty("ServerID", String.valueOf(_requestID));
 		} else {
-			_requestID = Config.SERVER_ID;
+			_hexID = hexId().getHexID().toByteArray();
+			_requestID = hexId().getServerID();
 		}
-		_acceptAlternate = Config.ACCEPT_ALTERNATE_ID;
-		_reserveHost = Config.RESERVE_HOST_ON_LOGIN;
-		_subnets = Config.GAME_SERVER_SUBNETS;
-		_hosts = Config.GAME_SERVER_HOSTS;
+		_acceptAlternate = server().acceptAlternateId();
+		_reserveHost = server().reserveHostOnLogin();
+		_subnets = ip().getSubnets();
+		_hosts = ip().getHosts();
 		_waitingClients = new CopyOnWriteArrayList<>();
-		_maxPlayer = Config.MAXIMUM_ONLINE_USERS;
+		_maxPlayer = server().getMaxOnlineUsers();
 	}
 	
 	@Override
@@ -224,23 +237,23 @@ public class LoginServerThread extends Thread {
 							AuthResponse aresp = new AuthResponse(incoming);
 							int serverID = aresp.getServerId();
 							_serverName = aresp.getServerName();
-							Config.saveHexid(serverID, hexToString(_hexID));
+							saveHexid(serverID, hexToString(_hexID), HEXID_FILE);
 							LOG.info("Registered on login as Server {}: {}", serverID, _serverName);
 							ServerStatus st = new ServerStatus();
-							if (Config.SERVER_LIST_BRACKET) {
+							if (general().getServerListBrackets()) {
 								st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.ON);
 							} else {
 								st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.OFF);
 							}
-							st.addAttribute(ServerStatus.SERVER_TYPE, Config.SERVER_LIST_TYPE);
-							if (Config.SERVER_GMONLY) {
+							st.addAttribute(ServerStatus.SERVER_TYPE, general().getServerListType());
+							if (general().serverGMOnly()) {
 								st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
 							} else {
 								st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
 							}
-							if (Config.SERVER_LIST_AGE == 15) {
+							if (general().getServerListAge() == TEENAGER) {
 								st.addAttribute(ServerStatus.SERVER_AGE, ServerStatus.SERVER_AGE_15);
-							} else if (Config.SERVER_LIST_AGE == 18) {
+							} else if (general().getServerListAge() == ADULT) {
 								st.addAttribute(ServerStatus.SERVER_AGE, ServerStatus.SERVER_AGE_18);
 							} else {
 								st.addAttribute(ServerStatus.SERVER_AGE, ServerStatus.SERVER_AGE_ALL);
@@ -548,7 +561,7 @@ public class LoginServerThread extends Thread {
 	 */
 	public void sendServerType() {
 		ServerStatus ss = new ServerStatus();
-		ss.addAttribute(ServerStatus.SERVER_TYPE, Config.SERVER_LIST_TYPE);
+		ss.addAttribute(ServerStatus.SERVER_TYPE, general().getServerListType());
 		try {
 			sendPacket(ss);
 		} catch (IOException e) {
@@ -669,6 +682,28 @@ public class LoginServerThread extends Thread {
 		}
 	}
 	
+	/**
+	 * Save hexadecimal ID of the server in the L2Properties file.
+	 * @param serverId the ID of the server whose hexId to save
+	 * @param hexId the hexadecimal ID to store
+	 * @param fileName name of the L2Properties file
+	 */
+	public static void saveHexid(int serverId, String hexId, String fileName) {
+		try {
+			Properties hexSetting = new Properties();
+			File file = new File(fileName);
+			// Create a new empty file only if it doesn't exist
+			file.createNewFile();
+			try (OutputStream out = new FileOutputStream(file)) {
+				hexSetting.setProperty("ServerID", String.valueOf(serverId));
+				hexSetting.setProperty("HexID", hexId);
+				hexSetting.store(out, "the hexID to auth into login");
+			}
+		} catch (Exception ex) {
+			LOG.warn("Failed to save hex Id to {} file.", fileName, ex);
+		}
+	}
+	
 	/**
 	 * Gets the single instance of LoginServerThread.
 	 * @return single instance of LoginServerThread

+ 22 - 20
src/main/java/com/l2jserver/gameserver/RecipeController.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -26,7 +28,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Logger;
 
 import com.l2jserver.commons.util.Rnd;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.RecipeData;
 import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.enums.StatType;
@@ -85,19 +86,19 @@ public class RecipeController {
 		List<L2RecipeList> commonRecipes = Arrays.asList(manufacturer.getCommonRecipeBook());
 		
 		if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList)) {
-			Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
+			Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.");
 			return;
 		}
 		
 		// Check if manufacturer is under manufacturing store or private store.
-		if (Config.ALT_GAME_CREATION && _activeMakers.containsKey(manufacturer.getObjectId())) {
+		if (character().alternativeCrafting() && _activeMakers.containsKey(manufacturer.getObjectId())) {
 			player.sendPacket(SystemMessageId.CLOSE_STORE_WINDOW_AND_TRY_AGAIN);
 			return;
 		}
 		
 		final RecipeItemMaker maker = new RecipeItemMaker(manufacturer, recipeList, player);
 		if (maker._isValid) {
-			if (Config.ALT_GAME_CREATION) {
+			if (character().alternativeCrafting()) {
 				_activeMakers.put(manufacturer.getObjectId(), maker);
 				ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
 			} else {
@@ -122,12 +123,12 @@ public class RecipeController {
 		List<L2RecipeList> commonRecipes = Arrays.asList(player.getCommonRecipeBook());
 		
 		if (!dwarfRecipes.contains(recipeList) && !commonRecipes.contains(recipeList)) {
-			Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.", Config.DEFAULT_PUNISH);
+			Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " of account " + player.getAccountName() + " sent a false recipe id.");
 			return;
 		}
 		
 		// Check if player is busy (possible if alt game creation is enabled)
-		if (Config.ALT_GAME_CREATION && _activeMakers.containsKey(player.getObjectId())) {
+		if (character().alternativeCrafting() && _activeMakers.containsKey(player.getObjectId())) {
 			SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_S1);
 			sm.addItemName(recipeList.getItemId());
 			sm.addString("You are busy creating.");
@@ -137,7 +138,7 @@ public class RecipeController {
 		
 		final RecipeItemMaker maker = new RecipeItemMaker(player, recipeList, player);
 		if (maker._isValid) {
-			if (Config.ALT_GAME_CREATION) {
+			if (character().alternativeCrafting()) {
 				_activeMakers.put(player.getObjectId(), maker);
 				ThreadPoolManager.getInstance().scheduleGeneral(maker, 100);
 			} else {
@@ -246,7 +247,7 @@ public class RecipeController {
 			}
 			
 			// initial AltStatChange checks
-			if (Config.ALT_GAME_CREATION) {
+			if (character().alternativeCrafting()) {
 				calculateAltStatChange();
 			}
 			
@@ -260,7 +261,7 @@ public class RecipeController {
 		
 		@Override
 		public void run() {
-			if (!Config.IS_CRAFTING_ENABLED) {
+			if (!character().crafting()) {
 				_target.sendMessage("Item creation is currently disabled.");
 				abort();
 				return;
@@ -278,7 +279,7 @@ public class RecipeController {
 				return;
 			}
 			
-			if (Config.ALT_GAME_CREATION && !_activeMakers.containsKey(_player.getObjectId())) {
+			if (character().alternativeCrafting() && !_activeMakers.containsKey(_player.getObjectId())) {
 				if (_target != _player) {
 					_target.sendMessage("Manufacture aborted");
 					_player.sendMessage("Manufacture aborted");
@@ -290,7 +291,7 @@ public class RecipeController {
 				return;
 			}
 			
-			if (Config.ALT_GAME_CREATION && !_items.isEmpty()) {
+			if (character().alternativeCrafting() && !_items.isEmpty()) {
 				
 				if (!calculateStatUse(true, true)) {
 					return; // check stat use
@@ -301,7 +302,7 @@ public class RecipeController {
 				
 				// if still not empty, schedule another pass
 				if (!_items.isEmpty()) {
-					_delay = (int) (Config.ALT_GAME_CREATION_SPEED * _player.getMReuseRate(_skill) * GameTimeController.TICKS_PER_SECOND * GameTimeController.MILLIS_IN_TICK);
+					_delay = (int) (character().getCraftingSpeed() * _player.getMReuseRate(_skill) * GameTimeController.TICKS_PER_SECOND * GameTimeController.MILLIS_IN_TICK);
 					
 					// FIXME: please fix this packet to show crafting animation (somebody)
 					MagicSkillUse msk = new MagicSkillUse(_player, _skillId, _skillLevel, _delay, 0);
@@ -327,7 +328,7 @@ public class RecipeController {
 		}
 		
 		private void finishCrafting() {
-			if (!Config.ALT_GAME_CREATION) {
+			if (!character().alternativeCrafting()) {
 				calculateStatUse(false, true);
 			}
 			
@@ -456,7 +457,7 @@ public class RecipeController {
 					// we do not want to kill the player, so its CurrentHP must be greater than the reduce value
 					if (_player.getCurrentHp() <= modifiedValue) {
 						// rest (wait for HP)
-						if (Config.ALT_GAME_CREATION && isWait) {
+						if (character().alternativeCrafting() && isWait) {
 							_player.sendPacket(new SetupGauge(0, _delay));
 							ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
 						} else {
@@ -470,7 +471,7 @@ public class RecipeController {
 				} else if (statUse.getType() == StatType.MP) {
 					if (_player.getCurrentMp() < modifiedValue) {
 						// rest (wait for MP)
-						if (Config.ALT_GAME_CREATION && isWait) {
+						if (character().alternativeCrafting() && isWait) {
 							_player.sendPacket(new SetupGauge(0, _delay));
 							ThreadPoolManager.getInstance().scheduleGeneral(this, 100 + _delay);
 						} else {
@@ -550,7 +551,7 @@ public class RecipeController {
 			L2Item template = ItemTable.getInstance().getTemplate(itemId);
 			
 			// check that the current recipe has a rare production or not
-			if ((rareProdId != -1) && ((rareProdId == itemId) || Config.CRAFT_MASTERWORK)) {
+			if ((rareProdId != -1) && ((rareProdId == itemId) || character().craftMasterwork())) {
 				if (Rnd.get(100) < _recipeList.getRarity()) {
 					itemId = rareProdId;
 					itemCount = _recipeList.getRareCount();
@@ -603,7 +604,7 @@ public class RecipeController {
 				_target.sendPacket(sm);
 			}
 			
-			if (Config.ALT_GAME_CREATION) {
+			if (character().alternativeCrafting()) {
 				int recipeLevel = _recipeList.getLevel();
 				if (_exp < 0) {
 					_exp = template.getReferencePrice() * itemCount;
@@ -613,8 +614,8 @@ public class RecipeController {
 					_sp = _exp / 10;
 				}
 				if (itemId == rareProdId) {
-					_exp *= Config.ALT_GAME_CREATION_RARE_XPSP_RATE;
-					_sp *= Config.ALT_GAME_CREATION_RARE_XPSP_RATE;
+					_exp *= character().getCraftingRareXpRate();
+					_sp *= character().getCraftingRareSpRate();
 				}
 				
 				if (_exp < 0) {
@@ -631,7 +632,8 @@ public class RecipeController {
 				
 				// Added multiplication of Creation speed with XP/SP gain slower crafting -> more XP,
 				// faster crafting -> less XP you can use ALT_GAME_CREATION_XP_RATE/SP to modify XP/SP gained (default = 1)
-				_player.addExpAndSp((long) (_exp * Config.ALT_GAME_CREATION_XP_RATE * Config.ALT_GAME_CREATION_SPEED), (int) (_sp * Config.ALT_GAME_CREATION_SP_RATE * Config.ALT_GAME_CREATION_SPEED));
+				_player.addExpAndSp((long) (_exp * character().getCraftingXpRate() * character().getCraftingSpeed()), //
+					(int) (_sp * character().getCraftingSpRate() * character().getCraftingSpeed()));
 			}
 			updateMakeInfo(true); // success
 		}

+ 8 - 7
src/main/java/com/l2jserver/gameserver/SevenSigns.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.npc;
+import static com.l2jserver.gameserver.config.Configuration.sevenSings;
 import static com.l2jserver.gameserver.network.SystemMessageId.COMPETITION_PERIOD_BEGUN;
 import static com.l2jserver.gameserver.network.SystemMessageId.DAWN_OBTAINED_AVARICE;
 import static com.l2jserver.gameserver.network.SystemMessageId.DAWN_OBTAINED_GNOSIS;
@@ -47,7 +49,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.instancemanager.CastleManager;
 import com.l2jserver.gameserver.model.AutoSpawnHandler;
 import com.l2jserver.gameserver.model.AutoSpawnHandler.AutoSpawnInstance;
@@ -251,7 +252,7 @@ public class SevenSigns {
 			}
 			
 			if ((getSealOwner(SEAL_GNOSIS) == getCabalHighestScore()) && (getSealOwner(SEAL_GNOSIS) != CABAL_NULL)) {
-				if (!Config.ANNOUNCE_MAMMON_SPAWN) {
+				if (!npc().announceMammonSpawn()) {
 					blacksmithSpawn.setBroadcast(false);
 				}
 				
@@ -283,7 +284,7 @@ public class SevenSigns {
 			}
 			
 			if ((getSealOwner(SEAL_AVARICE) == getCabalHighestScore()) && (getSealOwner(SEAL_AVARICE) != CABAL_NULL)) {
-				if (!Config.ANNOUNCE_MAMMON_SPAWN) {
+				if (!npc().announceMammonSpawn()) {
 					merchantSpawn.setBroadcast(false);
 				}
 				
@@ -883,7 +884,7 @@ public class SevenSigns {
 			_signsDuskSealTotals.put(chosenSeal, _signsDuskSealTotals.get(chosenSeal) + 1);
 		}
 		
-		if (!Config.ALT_SEVENSIGNS_LAZY_UPDATE) {
+		if (!sevenSings().sevenSignsLazyUpdate()) {
 			saveSevenSignsStatus();
 		}
 		
@@ -908,7 +909,7 @@ public class SevenSigns {
 		
 		if (removeReward) {
 			_signsPlayerData.put(objectId, currPlayer);
-			if (!Config.ALT_SEVENSIGNS_LAZY_UPDATE) {
+			if (!sevenSings().sevenSignsLazyUpdate()) {
 				saveSevenSignsData(objectId);
 				saveSevenSignsStatus();
 			}
@@ -934,7 +935,7 @@ public class SevenSigns {
 		long totalAncientAdena = currPlayer.getLong("ancient_adena_amount") + calcAncientAdenaReward(blueCount, greenCount, redCount);
 		long totalContribScore = currPlayer.getLong("contribution_score") + contribScore;
 		
-		if (totalContribScore > Config.ALT_MAXIMUM_PLAYER_CONTRIB) {
+		if (totalContribScore > sevenSings().getMaxPlayerContrib()) {
 			return -1;
 		}
 		
@@ -954,7 +955,7 @@ public class SevenSigns {
 				break;
 		}
 		
-		if (!Config.ALT_SEVENSIGNS_LAZY_UPDATE) {
+		if (!sevenSings().sevenSignsLazyUpdate()) {
 			saveSevenSignsData(objectId);
 			saveSevenSignsStatus();
 		}

+ 34 - 30
src/main/java/com/l2jserver/gameserver/SevenSignsFestival.java

@@ -18,6 +18,11 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+import static com.l2jserver.gameserver.config.Configuration.clan;
+import static com.l2jserver.gameserver.config.Configuration.sevenSings;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -25,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,7 +37,6 @@ import org.slf4j.LoggerFactory;
 import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.commons.util.Rnd;
 import com.l2jserver.gameserver.ai.CtrlIntention;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.sql.impl.CharNameTable;
 import com.l2jserver.gameserver.data.sql.impl.ClanTable;
 import com.l2jserver.gameserver.datatables.SpawnTable;
@@ -82,7 +85,7 @@ public class SevenSignsFestival implements SpawnListener {
 	 * The monster swarm time is the time before the monsters swarm to the center of the arena, after they are spawned.<br>
 	 * The chest spawn time is for when the bonus festival chests spawn, usually towards the end of the festival.
 	 */
-	public static final long FESTIVAL_SIGNUP_TIME = Config.ALT_FESTIVAL_CYCLE_LENGTH - Config.ALT_FESTIVAL_LENGTH - 60000;
+	public static final long FESTIVAL_SIGNUP_TIME = sevenSings().getFestivalCycleLength() - sevenSings().getFestivalLength() - 60000;
 	
 	// Key Constants \\
 	private static final int FESTIVAL_MAX_OFFSET_X = 230;
@@ -833,7 +836,7 @@ public class SevenSignsFestival implements SpawnListener {
 	 * @return int maxLevel
 	 */
 	public static final int getMaxLevelForFestival(int festivalId) {
-		int maxLevel = Config.MAX_PLAYER_LEVEL;
+		int maxLevel = character().getMaxPlayerLevel();
 		
 		switch (festivalId) {
 			case SevenSignsFestival.FESTIVAL_LEVEL_MAX_31:
@@ -898,10 +901,11 @@ public class SevenSignsFestival implements SpawnListener {
 			return; // already started
 		}
 		_managerInstance = new FestivalManager();
-		setNextFestivalStart(Config.ALT_FESTIVAL_MANAGER_START + FESTIVAL_SIGNUP_TIME);
-		_managerScheduledTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(_managerInstance, Config.ALT_FESTIVAL_MANAGER_START, Config.ALT_FESTIVAL_CYCLE_LENGTH);
 		
-		LOG.info("The first Festival of Darkness cycle begins in {} minute(s).", TimeUnit.MILLISECONDS.toMinutes(Config.ALT_FESTIVAL_MANAGER_START));
+		setNextFestivalStart(sevenSings().getFestivalManagerStart() + FESTIVAL_SIGNUP_TIME);
+		_managerScheduledTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(_managerInstance, sevenSings().getFestivalManagerStart(), sevenSings().getFestivalCycleLength());
+		
+		LOG.info("The first Festival of Darkness cycle begins in {} minute(s).", MILLISECONDS.toMinutes(sevenSings().getFestivalManagerStart()));
 	}
 	
 	/**
@@ -1044,10 +1048,10 @@ public class SevenSignsFestival implements SpawnListener {
 		L2PcInstance player = L2World.getInstance().getPlayer(partyMemberName);
 		if (player != null) {
 			if (player.getClan() != null) {
-				player.getClan().addReputationScore(Config.FESTIVAL_WIN_POINTS, true);
+				player.getClan().addReputationScore(clan().getFestivalOfDarknessWin(), true);
 				SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.CLAN_MEMBER_C1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
 				sm.addString(partyMemberName);
-				sm.addInt(Config.FESTIVAL_WIN_POINTS);
+				sm.addInt(clan().getFestivalOfDarknessWin());
 				player.getClan().broadcastToOnlineMembers(sm);
 			}
 		} else {
@@ -1060,10 +1064,10 @@ public class SevenSignsFestival implements SpawnListener {
 						if (clanName != null) {
 							L2Clan clan = ClanTable.getInstance().getClanByName(clanName);
 							if (clan != null) {
-								clan.addReputationScore(Config.FESTIVAL_WIN_POINTS, true);
+								clan.addReputationScore(clan().getFestivalOfDarknessWin(), true);
 								SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.CLAN_MEMBER_C1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
 								sm.addString(partyMemberName);
-								sm.addInt(Config.FESTIVAL_WIN_POINTS);
+								sm.addInt(clan().getFestivalOfDarknessWin());
 								clan.broadcastToOnlineMembers(sm);
 							}
 						}
@@ -1153,7 +1157,7 @@ public class SevenSignsFestival implements SpawnListener {
 	}
 	
 	public void setNextCycleStart() {
-		_nextFestivalCycleStart = System.currentTimeMillis() + Config.ALT_FESTIVAL_CYCLE_LENGTH;
+		_nextFestivalCycleStart = System.currentTimeMillis() + sevenSings().getFestivalCycleLength();
 	}
 	
 	public void setNextFestivalStart(long milliFromNow) {
@@ -1313,7 +1317,7 @@ public class SevenSignsFestival implements SpawnListener {
 			setParticipants(oracle, festivalId, festivalParty);
 			
 			// Check on disconnect if min player in party
-			if ((festivalParty != null) && (festivalParty.getMemberCount() < Config.ALT_FESTIVAL_MIN_PLAYER)) {
+			if ((festivalParty != null) && (festivalParty.getMemberCount() < sevenSings().getFestivalMinPlayer())) {
 				updateParticipants(player, null); // under minimum count
 				festivalParty.removePartyMember(player, messageType.Expelled);
 			}
@@ -1599,7 +1603,7 @@ public class SevenSignsFestival implements SpawnListener {
 			
 			// Set the next start timers.
 			setNextCycleStart();
-			setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
+			setNextFestivalStart(sevenSings().getFestivalCycleLength() - FESTIVAL_SIGNUP_TIME);
 		}
 		
 		@Override
@@ -1612,7 +1616,7 @@ public class SevenSignsFestival implements SpawnListener {
 				
 				// If the next period is due to start before the end of this
 				// festival cycle, then don't run it.
-				if (SevenSigns.getInstance().getMilliToPeriodChange() < Config.ALT_FESTIVAL_CYCLE_LENGTH) {
+				if (SevenSigns.getInstance().getMilliToPeriodChange() < sevenSings().getFestivalCycleLength()) {
 					return;
 				} else if (getMinsToNextFestival() == 2) {
 					sendMessageToAll("Festival Guide", NpcStringId.THE_MAIN_EVENT_WILL_START_IN_2_MINUTES_PLEASE_REGISTER_NOW);
@@ -1640,8 +1644,8 @@ public class SevenSignsFestival implements SpawnListener {
 					if ((_duskFestivalParticipants.isEmpty() && _dawnFestivalParticipants.isEmpty())) {
 						try {
 							setNextCycleStart();
-							setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
-							wait(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
+							setNextFestivalStart(sevenSings().getFestivalCycleLength() - FESTIVAL_SIGNUP_TIME);
+							wait(sevenSings().getFestivalCycleLength() - FESTIVAL_SIGNUP_TIME);
 							for (L2DarknessFestival festivalInst : _festivalInstances.values()) {
 								if (!festivalInst._npcInsts.isEmpty()) {
 									festivalInst.unspawnMobs();
@@ -1673,16 +1677,16 @@ public class SevenSignsFestival implements SpawnListener {
 				// Prevent future signups while festival is in progress.
 				_festivalInitialized = true;
 				
-				setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH);
+				setNextFestivalStart(sevenSings().getFestivalCycleLength());
 				sendMessageToAll("Festival Guide", NpcStringId.THE_MAIN_EVENT_IS_NOW_STARTING);
 				
 				// Stand by for a short length of time before starting the festival.
 				try {
-					wait(Config.ALT_FESTIVAL_FIRST_SPAWN);
+					wait(sevenSings().getFestivalFirstSpawn());
 				} catch (InterruptedException e) {
 				}
 				
-				elapsedTime = Config.ALT_FESTIVAL_FIRST_SPAWN;
+				elapsedTime = sevenSings().getFestivalFirstSpawn();
 				
 				// Participants can now opt to increase the challenge, if desired.
 				_festivalInProgress = true;
@@ -1696,11 +1700,11 @@ public class SevenSignsFestival implements SpawnListener {
 				
 				// After a short time period, move all idle spawns to the center of the arena.
 				try {
-					wait(Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN);
+					wait(sevenSings().getFestivalFirstSwarm() - sevenSings().getFestivalFirstSpawn());
 				} catch (InterruptedException e) {
 				}
 				
-				elapsedTime += Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN;
+				elapsedTime += sevenSings().getFestivalFirstSwarm() - sevenSings().getFestivalFirstSpawn();
 				
 				for (L2DarknessFestival festivalInst : _festivalInstances.values()) {
 					festivalInst.moveMonstersToCenter();
@@ -1708,7 +1712,7 @@ public class SevenSignsFestival implements SpawnListener {
 				
 				// Stand by until the time comes for the second spawn.
 				try {
-					wait(Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM);
+					wait(sevenSings().getFestivalSecondSpawn() - sevenSings().getFestivalFirstSwarm());
 				} catch (InterruptedException e) {
 				}
 				
@@ -1717,7 +1721,7 @@ public class SevenSignsFestival implements SpawnListener {
 				for (L2DarknessFestival festivalInst : _festivalInstances.values()) {
 					festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN / 2, 2);
 					
-					long end = (Config.ALT_FESTIVAL_LENGTH - Config.ALT_FESTIVAL_SECOND_SPAWN) / 60000;
+					long end = (sevenSings().getFestivalLength() - sevenSings().getFestivalSecondSpawn()) / 60000;
 					if (end == 2) {
 						festivalInst.sendMessageToParticipants(NpcStringId.THE_FESTIVAL_OF_DARKNESS_WILL_END_IN_TWO_MINUTES);
 					} else {
@@ -1725,11 +1729,11 @@ public class SevenSignsFestival implements SpawnListener {
 					}
 				}
 				
-				elapsedTime += Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM;
+				elapsedTime += sevenSings().getFestivalSecondSpawn() - sevenSings().getFestivalFirstSwarm();
 				
 				// After another short time period, again move all idle spawns to the center of the arena.
 				try {
-					wait(Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN);
+					wait(sevenSings().getFestivalSecondSwarm() - sevenSings().getFestivalSecondSpawn());
 				} catch (InterruptedException e) {
 				}
 				
@@ -1737,11 +1741,11 @@ public class SevenSignsFestival implements SpawnListener {
 					festivalInst.moveMonstersToCenter();
 				}
 				
-				elapsedTime += Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN;
+				elapsedTime += sevenSings().getFestivalSecondSwarm() - sevenSings().getFestivalSecondSpawn();
 				
 				// Stand by until the time comes for the chests to be spawned.
 				try {
-					wait(Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM);
+					wait(sevenSings().getFestivalChestSpawn() - sevenSings().getFestivalSecondSwarm());
 				} catch (InterruptedException e) {
 				}
 				
@@ -1752,11 +1756,11 @@ public class SevenSignsFestival implements SpawnListener {
 					festivalInst.sendMessageToParticipants("The chests have spawned! Be quick, the festival will end soon."); // FIXME What is the correct npcString?
 				}
 				
-				elapsedTime += Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM;
+				elapsedTime += sevenSings().getFestivalChestSpawn() - sevenSings().getFestivalSecondSwarm();
 				
 				// Stand by and wait until it's time to end the festival.
 				try {
-					wait(Config.ALT_FESTIVAL_LENGTH - elapsedTime);
+					wait(sevenSings().getFestivalLength() - elapsedTime);
 				} catch (InterruptedException e) {
 				}
 				

+ 7 - 5
src/main/java/com/l2jserver/gameserver/Shutdown.java

@@ -18,6 +18,9 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.customs;
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.concurrent.TimeUnit;
 
 import org.slf4j.Logger;
@@ -25,7 +28,6 @@ import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.UPnPService;
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.sql.impl.ClanTable;
 import com.l2jserver.gameserver.data.sql.impl.OfflineTradersTable;
 import com.l2jserver.gameserver.datatables.BotReportTable;
@@ -180,7 +182,7 @@ public class Shutdown extends Thread {
 			}
 			
 			try {
-				if ((Config.OFFLINE_TRADE_ENABLE || Config.OFFLINE_CRAFT_ENABLE) && Config.RESTORE_OFFLINERS) {
+				if ((customs().offlineTradeEnable() || customs().offlineCraftEnable()) && customs().restoreOffliners()) {
 					OfflineTradersTable.getInstance().storeOffliners();
 					LOG.info("Offline Traders Table: Offline shops stored({}ms).", tc.getEstimatedTimeAndRestartCounter());
 				}
@@ -459,7 +461,7 @@ public class Shutdown extends Thread {
 		LOG.info("Cursed Weapons Manager: Data saved({}ms).", tc.getEstimatedTimeAndRestartCounter());
 		
 		// Save all manor data
-		if (!Config.ALT_MANOR_SAVE_ALL_ACTIONS) {
+		if (!general().manorSaveAllActions()) {
 			CastleManorManager.getInstance().storeMe();
 			LOG.info("Castle Manor Manager: Data saved({}ms).", tc.getEstimatedTimeAndRestartCounter());
 		}
@@ -476,7 +478,7 @@ public class Shutdown extends Thread {
 		LOG.info("Global Variables Manager: Variables saved({}ms).", tc.getEstimatedTimeAndRestartCounter());
 		
 		// Save items on ground before closing
-		if (Config.SAVE_DROPPED_ITEM) {
+		if (general().saveDroppedItem()) {
 			ItemsOnGroundManager.getInstance().saveInDb();
 			LOG.info("Items On Ground Manager: Data saved({}ms).", tc.getEstimatedTimeAndRestartCounter());
 			ItemsOnGroundManager.getInstance().cleanUp();
@@ -484,7 +486,7 @@ public class Shutdown extends Thread {
 		}
 		
 		// Save bot reports to database
-		if (Config.BOTREPORT_ENABLE) {
+		if (general().enableBotReportButton()) {
 			BotReportTable.getInstance().saveReportedCharData();
 			LOG.info("Bot Report Table: Successfully saved reports to database!");
 		}

+ 26 - 21
src/main/java/com/l2jserver/gameserver/ThreadPoolManager.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.lang.Thread.UncaughtExceptionHandler;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.RejectedExecutionException;
@@ -31,7 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.l2jserver.gameserver.config.Config;
+import com.l2jserver.gameserver.config.Configuration;
 import com.l2jserver.gameserver.util.StringUtil;
 
 /**
@@ -108,14 +110,14 @@ public class ThreadPoolManager {
 	}
 	
 	protected ThreadPoolManager() {
-		_effectsScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_P_EFFECTS, new PriorityThreadFactory("EffectsSTPool", Thread.NORM_PRIORITY));
-		_generalScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_P_GENERAL, new PriorityThreadFactory("GeneralSTPool", Thread.NORM_PRIORITY));
-		_eventScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.THREAD_E_EVENTS, new PriorityThreadFactory("EventSTPool", Thread.NORM_PRIORITY));
-		_ioPacketsThreadPool = new ThreadPoolExecutor(Config.IO_PACKET_THREAD_CORE_SIZE, Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("I/O Packet Pool", Thread.NORM_PRIORITY + 1));
-		_generalPacketsThreadPool = new ThreadPoolExecutor(Config.GENERAL_PACKET_THREAD_CORE_SIZE, Config.GENERAL_PACKET_THREAD_CORE_SIZE + 2, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Normal Packet Pool", Thread.NORM_PRIORITY + 1));
-		_generalThreadPool = new ThreadPoolExecutor(Config.GENERAL_THREAD_CORE_SIZE, Config.GENERAL_THREAD_CORE_SIZE + 2, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("General Pool", Thread.NORM_PRIORITY));
-		_aiScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.AI_MAX_THREAD, new PriorityThreadFactory("AISTPool", Thread.NORM_PRIORITY));
-		_eventThreadPool = new ThreadPoolExecutor(Config.EVENT_MAX_THREAD, Config.EVENT_MAX_THREAD + 2, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Event Pool", Thread.NORM_PRIORITY));
+		_effectsScheduledThreadPool = new ScheduledThreadPoolExecutor(general().getThreadPoolSizeEffects(), new PriorityThreadFactory("EffectsSTPool", Thread.NORM_PRIORITY));
+		_generalScheduledThreadPool = new ScheduledThreadPoolExecutor(general().getThreadPoolSizeGeneral(), new PriorityThreadFactory("GeneralSTPool", Thread.NORM_PRIORITY));
+		_eventScheduledThreadPool = new ScheduledThreadPoolExecutor(general().getThreadPoolSizeEvents(), new PriorityThreadFactory("EventSTPool", Thread.NORM_PRIORITY));
+		_ioPacketsThreadPool = new ThreadPoolExecutor(general().getUrgentPacketThreadCoreSize(), Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("I/O Packet Pool", Thread.NORM_PRIORITY + 1));
+		_generalPacketsThreadPool = new ThreadPoolExecutor(general().getGeneralPacketThreadCoreSize(), general().getGeneralPacketThreadCoreSize() + 2, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Normal Packet Pool", Thread.NORM_PRIORITY + 1));
+		_generalThreadPool = new ThreadPoolExecutor(general().getGeneralThreadCoreSize(), general().getGeneralThreadCoreSize() + 2, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("General Pool", Thread.NORM_PRIORITY));
+		_aiScheduledThreadPool = new ScheduledThreadPoolExecutor(general().getAiMaxThread(), new PriorityThreadFactory("AISTPool", Thread.NORM_PRIORITY));
+		_eventThreadPool = new ThreadPoolExecutor(general().getEventsMaxThread(), general().getEventsMaxThread() + 2, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Event Pool", Thread.NORM_PRIORITY));
 		
 		scheduleGeneralAtFixedRate(new PurgeTask(_effectsScheduledThreadPool, _generalScheduledThreadPool, _aiScheduledThreadPool, _eventThreadPool), 10, 5, TimeUnit.MINUTES);
 	}
@@ -520,21 +522,22 @@ public class ThreadPoolManager {
 			int count = ptf.getGroup().activeCount();
 			Thread[] threads = new Thread[count + 2];
 			ptf.getGroup().enumerate(threads);
-			StringUtil.append(sb, "General Packet Thread Pool:" + Config.EOL + "Tasks in the queue: ", String.valueOf(_generalPacketsThreadPool.getQueue().size()), Config.EOL + "Showing threads stack trace:" + Config.EOL + "There should be ", String.valueOf(count), " Threads" + Config.EOL);
+			StringUtil.append(sb, "General Packet Thread Pool:" + Configuration.EOL + "Tasks in the queue: ", String.valueOf(_generalPacketsThreadPool.getQueue().size()), Configuration.EOL + "Showing threads stack trace:" + Configuration.EOL + "There should be ", String.valueOf(count), " Threads"
+				+ Configuration.EOL);
 			for (Thread t : threads) {
 				if (t == null) {
 					continue;
 				}
 				
-				StringUtil.append(sb, t.getName(), Config.EOL);
+				StringUtil.append(sb, t.getName(), Configuration.EOL);
 				for (StackTraceElement ste : t.getStackTrace()) {
-					StringUtil.append(sb, ste.toString(), Config.EOL);
+					StringUtil.append(sb, ste.toString(), Configuration.EOL);
 				}
 			}
 		}
 		
 		sb.append("Packet Tp stack traces printed.");
-		sb.append(Config.EOL);
+		sb.append(Configuration.EOL);
 		return sb.toString();
 	}
 	
@@ -547,23 +550,24 @@ public class ThreadPoolManager {
 			int count = ptf.getGroup().activeCount();
 			Thread[] threads = new Thread[count + 2];
 			ptf.getGroup().enumerate(threads);
-			StringUtil.append(sb, "I/O Packet Thread Pool:" + Config.EOL + "Tasks in the queue: ", String.valueOf(_ioPacketsThreadPool.getQueue().size()), Config.EOL + "Showing threads stack trace:" + Config.EOL + "There should be ", String.valueOf(count), " Threads" + Config.EOL);
+			StringUtil.append(sb, "I/O Packet Thread Pool:" + Configuration.EOL + "Tasks in the queue: ", String.valueOf(_ioPacketsThreadPool.getQueue().size()), Configuration.EOL + "Showing threads stack trace:" + Configuration.EOL + "There should be ", String.valueOf(count), " Threads"
+				+ Configuration.EOL);
 			
 			for (Thread t : threads) {
 				if (t == null) {
 					continue;
 				}
 				
-				StringUtil.append(sb, t.getName(), Config.EOL);
+				StringUtil.append(sb, t.getName(), Configuration.EOL);
 				
 				for (StackTraceElement ste : t.getStackTrace()) {
-					StringUtil.append(sb, ste.toString(), Config.EOL);
+					StringUtil.append(sb, ste.toString(), Configuration.EOL);
 				}
 			}
 		}
 		
 		sb.append("Packet Tp stack traces printed.");
-		sb.append(Config.EOL);
+		sb.append(Configuration.EOL);
 		return sb.toString();
 	}
 	
@@ -576,23 +580,24 @@ public class ThreadPoolManager {
 			int count = ptf.getGroup().activeCount();
 			Thread[] threads = new Thread[count + 2];
 			ptf.getGroup().enumerate(threads);
-			StringUtil.append(sb, "General Thread Pool:" + Config.EOL + "Tasks in the queue: ", String.valueOf(_generalThreadPool.getQueue().size()), Config.EOL + "Showing threads stack trace:" + Config.EOL + "There should be ", String.valueOf(count), " Threads" + Config.EOL);
+			StringUtil.append(sb, "General Thread Pool:" + Configuration.EOL + "Tasks in the queue: ", String.valueOf(_generalThreadPool.getQueue().size()), Configuration.EOL + "Showing threads stack trace:" + Configuration.EOL + "There should be ", String.valueOf(count), " Threads"
+				+ Configuration.EOL);
 			
 			for (Thread t : threads) {
 				if (t == null) {
 					continue;
 				}
 				
-				StringUtil.append(sb, t.getName(), Config.EOL);
+				StringUtil.append(sb, t.getName(), Configuration.EOL);
 				
 				for (StackTraceElement ste : t.getStackTrace()) {
-					StringUtil.append(sb, ste.toString(), Config.EOL);
+					StringUtil.append(sb, ste.toString(), Configuration.EOL);
 				}
 			}
 		}
 		
 		sb.append("Packet Tp stack traces printed.");
-		sb.append(Config.EOL);
+		sb.append(Configuration.EOL);
 		return sb.toString();
 	}
 	

+ 13 - 12
src/main/java/com/l2jserver/gameserver/ai/L2AttackableAI.java

@@ -21,6 +21,8 @@ package com.l2jserver.gameserver.ai;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+import static com.l2jserver.gameserver.config.Configuration.customs;
+import static com.l2jserver.gameserver.config.Configuration.npc;
 
 import java.util.Collection;
 import java.util.List;
@@ -35,7 +37,6 @@ import com.l2jserver.commons.util.Rnd;
 import com.l2jserver.gameserver.GameTimeController;
 import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.sql.impl.TerritoryTable;
 import com.l2jserver.gameserver.enums.AISkillScope;
 import com.l2jserver.gameserver.enums.AIType;
@@ -231,7 +232,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 				return GeoData.getInstance().canSeeTarget(me, player); // Los Check
 			}
 			// Check if the L2MonsterInstance target is aggressive
-			if ((target instanceof L2MonsterInstance) && Config.GUARD_ATTACK_AGGRO_MOB) {
+			if ((target instanceof L2MonsterInstance) && npc().guardAttackAggroMob()) {
 				return (((L2MonsterInstance) target).isAggressive() && GeoData.getInstance().canSeeTarget(me, target));
 			}
 			
@@ -266,13 +267,13 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 				return false;
 			}
 			
-			// depending on config, do not allow mobs to attack _new_ players in peacezones,
-			// unless they are already following those players from outside the peacezone.
-			if (!Config.ALT_MOB_AGRO_IN_PEACEZONE && target.isInsideZone(ZoneId.PEACE)) {
+			// depending on config, do not allow mobs to attack _new_ players in peace zones,
+			// unless they are already following those players from outside the peace zone.
+			if (!npc().mobAggroInPeaceZone() && target.isInsideZone(ZoneId.PEACE)) {
 				return false;
 			}
 			
-			if (me.isChampion() && Config.L2JMOD_CHAMPION_PASSIVE) {
+			if (me.isChampion() && customs().championPassive()) {
 				return false;
 			}
 			
@@ -316,7 +317,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 				} else {
 					if (npc.getSpawn() != null) {
 						final Location loc = npc.getSpawn().getLocation(npc);
-						final int range = Config.MAX_DRIFT_RANGE;
+						final int range = npc().getMaxDriftRange();
 						
 						if (!npc.isInsideRadius(loc, range + range, true, false)) {
 							intention = AI_INTENTION_ACTIVE;
@@ -573,7 +574,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 			int x1 = 0;
 			int y1 = 0;
 			int z1 = 0;
-			final int range = Config.MAX_DRIFT_RANGE;
+			final int range = npc().getMaxDriftRange();
 			
 			for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.BUFF)) {
 				if (cast(sk)) {
@@ -804,7 +805,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 			_chaosTime++;
 			if (npc instanceof L2RaidBossInstance) {
 				if (!((L2MonsterInstance) npc).hasMinions()) {
-					if (_chaosTime > Config.RAID_CHAOS_TIME) {
+					if (_chaosTime > npc().getRaidChaosTime()) {
 						if (Rnd.get(100) <= (100 - ((npc.getCurrentHp() * 100) / npc.getMaxHp()))) {
 							aggroReconsider();
 							_chaosTime = 0;
@@ -812,7 +813,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 						}
 					}
 				} else {
-					if (_chaosTime > Config.RAID_CHAOS_TIME) {
+					if (_chaosTime > npc().getRaidChaosTime()) {
 						if (Rnd.get(100) <= (100 - ((npc.getCurrentHp() * 200) / npc.getMaxHp()))) {
 							aggroReconsider();
 							_chaosTime = 0;
@@ -821,7 +822,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 					}
 				}
 			} else if (npc instanceof L2GrandBossInstance) {
-				if (_chaosTime > Config.GRAND_CHAOS_TIME) {
+				if (_chaosTime > npc().getGrandChaosTime()) {
 					double chaosRate = 100 - ((npc.getCurrentHp() * 300) / npc.getMaxHp());
 					if (((chaosRate <= 10) && (Rnd.get(100) <= 10)) || ((chaosRate > 10) && (Rnd.get(100) <= chaosRate))) {
 						aggroReconsider();
@@ -830,7 +831,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable {
 					}
 				}
 			} else {
-				if (_chaosTime > Config.MINION_CHAOS_TIME) {
+				if (_chaosTime > npc().getMinionChaosTime()) {
 					if (Rnd.get(100) <= (100 - ((npc.getCurrentHp() * 200) / npc.getMaxHp()))) {
 						aggroReconsider();
 						_chaosTime = 0;

+ 2 - 2
src/main/java/com/l2jserver/gameserver/ai/L2CharacterAI.java

@@ -27,6 +27,7 @@ import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_INTERACT;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_MOVE_TO;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_PICK_UP;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
+import static com.l2jserver.gameserver.config.Configuration.geodata;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -35,7 +36,6 @@ import com.l2jserver.commons.util.Rnd;
 import com.l2jserver.gameserver.GameTimeController;
 import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.enums.ItemLocation;
 import com.l2jserver.gameserver.instancemanager.WalkingManager;
 import com.l2jserver.gameserver.model.L2Object;
@@ -888,7 +888,7 @@ public class L2CharacterAI extends AbstractAI {
 		
 		// If pathfinding enabled the creature will go to the destination or it will go to the nearest obstacle.
 		final Location destination;
-		if (Config.PATHFINDING > 0) {
+		if (geodata().getPathFinding() > 0) {
 			destination = GeoData.getInstance().moveCheck(_actor.getX(), _actor.getY(), _actor.getZ(), posX, posY, posZ, _actor.getInstanceId());
 		} else {
 			destination = new Location(posX, posY, posZ, _actor.getInstanceId());

+ 3 - 3
src/main/java/com/l2jserver/gameserver/ai/L2SummonAI.java

@@ -21,13 +21,13 @@ package com.l2jserver.gameserver.ai;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;
 import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;
+import static com.l2jserver.gameserver.config.Configuration.geodata;
 
 import java.util.concurrent.Future;
 
 import com.l2jserver.commons.util.Rnd;
 import com.l2jserver.gameserver.GeoData;
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Summon;
@@ -50,10 +50,10 @@ public class L2SummonAI extends L2PlayableAI implements Runnable {
 	
 	@Override
 	protected void onIntentionAttack(L2Character target) {
-		if ((Config.PATHFINDING > 0) && (PathFinding.getInstance().findPath(_actor.getX(), _actor.getY(), _actor.getZ(), target.getX(), target.getY(), target.getZ(), _actor.getInstanceId(), true) == null)) {
+		if ((geodata().getPathFinding() > 0) && //
+			(PathFinding.getInstance().findPath(_actor.getX(), _actor.getY(), _actor.getZ(), target.getX(), target.getY(), target.getZ(), _actor.getInstanceId(), true) == null)) {
 			return;
 		}
-		
 		super.onIntentionAttack(target);
 	}
 	

+ 10 - 8
src/main/java/com/l2jserver/gameserver/cache/HtmCache.java

@@ -18,6 +18,9 @@
  */
 package com.l2jserver.gameserver.cache;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -29,7 +32,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.util.file.filter.HTMLFilter;
 
 /**
@@ -43,7 +45,7 @@ public class HtmCache {
 	
 	private static final HTMLFilter HTML_FILTER = new HTMLFilter();
 	
-	private static final Map<String, String> HTML_CACHE = Config.LAZY_CACHE ? new ConcurrentHashMap<>() : new HashMap<>();
+	private static final Map<String, String> HTML_CACHE = general().lazyCache() ? new ConcurrentHashMap<>() : new HashMap<>();
 	
 	private int _loadedFiles;
 	
@@ -54,11 +56,11 @@ public class HtmCache {
 	}
 	
 	public void reload() {
-		reload(Config.DATAPACK_ROOT);
+		reload(server().getDatapackRoot());
 	}
 	
 	public void reload(File f) {
-		if (!Config.LAZY_CACHE) {
+		if (!general().lazyCache()) {
 			LOG.info("Html cache start...");
 			parseDir(f);
 			LOG.info(String.format("%.3f", getMemoryUsage()) + " megabytes on " + getLoadedFiles() + " files loaded");
@@ -127,10 +129,10 @@ public class HtmCache {
 	public String getHtm(String prefix, String path) {
 		final var newPath = Objects.firstNonNull(prefix, "") + path;
 		var content = HTML_CACHE.get(newPath);
-		if (Config.LAZY_CACHE && (content == null)) {
-			content = loadFile(new File(Config.DATAPACK_ROOT, newPath));
+		if (general().lazyCache() && (content == null)) {
+			content = loadFile(new File(server().getDatapackRoot(), newPath));
 			if (content == null) {
-				content = loadFile(new File(Config.SCRIPT_ROOT, newPath));
+				content = loadFile(new File(server().getScriptRoot(), newPath));
 			}
 		}
 		return content;
@@ -145,7 +147,7 @@ public class HtmCache {
 	 * @return {@code true} if the path targets a HTM or HTML file, {@code false} otherwise.
 	 */
 	public boolean isLoadable(String path) {
-		return HTML_FILTER.accept(new File(Config.DATAPACK_ROOT, path));
+		return HTML_FILTER.accept(new File(server().getDatapackRoot(), path));
 	}
 	
 	public static HtmCache getInstance() {

+ 4 - 3
src/main/java/com/l2jserver/gameserver/cache/WarehouseCacheManager.java

@@ -18,19 +18,20 @@
  */
 package com.l2jserver.gameserver.cache;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 
 /**
  * @author -Nemesiss-
  */
 public class WarehouseCacheManager {
+	
 	protected final Map<L2PcInstance, Long> _cachedWh = new ConcurrentHashMap<>();
-	protected final long _cacheTime = Config.WAREHOUSE_CACHE_TIME * 60000L;
 	
 	protected WarehouseCacheManager() {
 		ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new CacheScheduler(), 120000, 60000);
@@ -49,7 +50,7 @@ public class WarehouseCacheManager {
 		public void run() {
 			long cTime = System.currentTimeMillis();
 			for (L2PcInstance pc : _cachedWh.keySet()) {
-				if ((cTime - _cachedWh.get(pc)) > _cacheTime) {
+				if ((cTime - _cachedWh.get(pc)) > general().getWarehouseCacheTime()) {
 					pc.clearWarehouse();
 					_cachedWh.remove(pc);
 				}

+ 135 - 0
src/main/java/com/l2jserver/gameserver/config/CastleConfiguration.java

@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.HOURS;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Castle Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/castle.properties",
+	"classpath:config/castle.properties"
+})
+@HotReload(value = 1, unit = HOURS, type = ASYNC)
+public interface CastleConfiguration extends Config, Reloadable {
+	
+	@Key("SiegeHourList")
+	List<Integer> getSiegeHourList();
+	
+	@Key("TeleportFunctionFeeRatio")
+	Long getTeleportFunctionFeeRatio();
+	
+	@Key("TeleportFunctionFeeLvl1")
+	Integer getTeleportFunctionFeeLvl1();
+	
+	@Key("TeleportFunctionFeeLvl2")
+	Integer getTeleportFunctionFeeLvl2();
+	
+	@Key("SupportFunctionFeeRatio")
+	Long getSupportFunctionFeeRatio();
+	
+	@Key("SupportFeeLvl1")
+	Integer getSupportFeeLvl1();
+	
+	@Key("SupportFeeLvl2")
+	Integer getSupportFeeLvl2();
+	
+	@Key("MpRegenerationFunctionFeeRatio")
+	Long getMpRegenerationFunctionFeeRatio();
+	
+	@Key("MpRegenerationFeeLvl1")
+	Integer getMpRegenerationFeeLvl1();
+	
+	@Key("MpRegenerationFeeLvl2")
+	Integer getMpRegenerationFeeLvl2();
+	
+	@Key("HpRegenerationFunctionFeeRatio")
+	Long getHpRegenerationFunctionFeeRatio();
+	
+	@Key("HpRegenerationFeeLvl1")
+	Integer getHpRegenerationFeeLvl1();
+	
+	@Key("HpRegenerationFeeLvl2")
+	Integer getHpRegenerationFeeLvl2();
+	
+	@Key("ExpRegenerationFunctionFeeRatio")
+	Long getExpRegenerationFunctionFeeRatio();
+	
+	@Key("ExpRegenerationFeeLvl1")
+	Integer getExpRegenerationFeeLvl1();
+	
+	@Key("ExpRegenerationFeeLvl2")
+	Integer getExpRegenerationFeeLvl2();
+	
+	@Key("OuterDoorUpgradePriceLvl2")
+	Integer getOuterDoorUpgradePriceLvl2();
+	
+	@Key("OuterDoorUpgradePriceLvl3")
+	Integer getOuterDoorUpgradePriceLvl3();
+	
+	@Key("OuterDoorUpgradePriceLvl5")
+	Integer getOuterDoorUpgradePriceLvl5();
+	
+	@Key("InnerDoorUpgradePriceLvl2")
+	Integer getInnerDoorUpgradePriceLvl2();
+	
+	@Key("InnerDoorUpgradePriceLvl3")
+	Integer getInnerDoorUpgradePriceLvl3();
+	
+	@Key("InnerDoorUpgradePriceLvl5")
+	Integer getInnerDoorUpgradePriceLvl5();
+	
+	@Key("WallUpgradePriceLvl2")
+	Integer getWallUpgradePriceLvl2();
+	
+	@Key("WallUpgradePriceLvl3")
+	Integer getWallUpgradePriceLvl3();
+	
+	@Key("WallUpgradePriceLvl5")
+	Integer getWallUpgradePriceLvl5();
+	
+	@Key("TrapUpgradePriceLvl1")
+	Integer getTrapUpgradePriceLvl1();
+	
+	@Key("TrapUpgradePriceLvl2")
+	Integer getTrapUpgradePriceLvl2();
+	
+	@Key("TrapUpgradePriceLvl3")
+	Integer getTrapUpgradePriceLvl3();
+	
+	@Key("TrapUpgradePriceLvl4")
+	Integer getTrapUpgradePriceLvl4();
+	
+	@Key("AllowRideWyvernAlways")
+	Boolean allowRideWyvernAlways();
+	
+	@Key("AllowRideWyvernDuringSiege")
+	Boolean allowRideWyvernDuringSiege();
+}

+ 637 - 0
src/main/java/com/l2jserver/gameserver/config/CharacterConfiguration.java

@@ -0,0 +1,637 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.ClassMasterSetting;
+import com.l2jserver.gameserver.config.converter.ClassMasterSettingConverter;
+import com.l2jserver.gameserver.config.converter.MapIntegerIntegerConverter;
+import com.l2jserver.gameserver.config.converter.PatternConverter;
+import com.l2jserver.gameserver.config.converter.Seconds2MillisecondsConverter;
+
+/**
+ * Character Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/character.properties",
+	"classpath:config/character.properties"
+})
+@HotReload(value = 5, unit = MINUTES, type = ASYNC)
+public interface CharacterConfiguration extends Config, Reloadable {
+	
+	// Statistics
+	@Key("Delevel")
+	Boolean delevel();
+	
+	@Key("DecreaseSkillOnDelevel")
+	Boolean decreaseSkillOnDelevel();
+	
+	@Key("WeightLimit")
+	Integer getWeightLimit();
+	
+	@Key("RunSpeedBoost")
+	Integer getRunSpeedBoost();
+	
+	@Key("DeathPenaltyChance")
+	Integer getDeathPenaltyChance();
+	
+	@Key("RespawnRestoreCP")
+	Double getRespawnRestoreCP();
+	
+	@Key("RespawnRestoreHP")
+	Double getRespawnRestoreHP();
+	
+	@Key("RespawnRestoreMP")
+	Double getRespawnRestoreMP();
+	
+	@Key("HpRegenMultiplier")
+	Double getHpRegenMultiplier();
+	
+	@Key("MpRegenMultiplier")
+	Double getMpRegenMultiplier();
+	
+	@Key("CpRegenMultiplier")
+	Double getCpRegenMultiplier();
+	
+	// Skills & Effects
+	
+	@Key("ModifySkillDuration")
+	Boolean modifySkillDuration();
+	
+	@Key("SkillDuration")
+	@ConverterClass(MapIntegerIntegerConverter.class)
+	Map<Integer, Integer> getSkillDuration();
+	
+	@Key("ModifySkillReuse")
+	Boolean modifySkillReuse();
+	
+	@Key("SkillReuse")
+	@ConverterClass(MapIntegerIntegerConverter.class)
+	Map<Integer, Integer> getSkillReuse();
+	
+	@Key("AutoLearnSkills")
+	Boolean autoLearnSkills();
+	
+	@Key("AutoLearnForgottenScrollSkills")
+	Boolean autoLearnForgottenScrollSkills();
+	
+	@Key("AutoLootHerbs")
+	Boolean autoLootHerbs();
+	
+	@Key("MaxBuffAmount")
+	Integer getMaxBuffAmount();
+	
+	@Key("MaxTriggeredBuffAmount")
+	Integer getMaxTriggeredBuffAmount();
+	
+	@Key("MaxDanceAmount")
+	Integer getMaxDanceAmount();
+	
+	@Key("DanceCancelBuff")
+	Boolean danceCancelBuff();
+	
+	@Key("DanceConsumeAdditionalMP")
+	Boolean danceConsumeAdditionalMP();
+	
+	@Key("StoreDances")
+	Boolean storeDances();
+	
+	@Key("AutoLearnDivineInspiration")
+	Boolean autoLearnDivineInspiration();
+	
+	@Key("CancelByHit")
+	String cancelByHit();
+	
+	default Boolean cancelBow() {
+		return cancelByHit().equalsIgnoreCase("all") || cancelByHit().equalsIgnoreCase("bow");
+	}
+	
+	default Boolean cancelCast() {
+		return cancelByHit().equalsIgnoreCase("all") || cancelByHit().equalsIgnoreCase("cast");
+	}
+	
+	@Key("MagicFailures")
+	Boolean magicFailures();
+	
+	@Key("PlayerFakeDeathUpProtection")
+	Integer getPlayerFakeDeathUpProtection();
+	
+	@Key("StoreSkillCooltime")
+	Boolean storeSkillCooltime();
+	
+	@Key("SubclassStoreSkillCooltime")
+	Boolean subclassStoreSkillCooltime();
+	
+	@Key("ShieldBlocks")
+	Boolean shieldBlocks();
+	
+	@Key("PerfectShieldBlockRate")
+	Integer getPerfectShieldBlockRate();
+	
+	@Key("EffectTickRatio")
+	Integer getEffectTickRatio();
+	
+	// Class, Sub-class and skill learning
+	
+	@Key("AllowClassMasters")
+	Boolean allowClassMasters();
+	
+	@Key("ConfigClassMaster")
+	@ConverterClass(ClassMasterSettingConverter.class)
+	ClassMasterSetting getClassMaster();
+	
+	@Key("AllowEntireTree")
+	Boolean allowEntireTree();
+	
+	@Key("AlternateClassMaster")
+	Boolean alternateClassMaster();
+	
+	@Key("LifeCrystalNeeded")
+	Boolean lifeCrystalNeeded();
+	
+	@Key("EnchantSkillSpBookNeeded")
+	Boolean enchantSkillSpBookNeeded();
+	
+	@Key("DivineInspirationSpBookNeeded")
+	Boolean divineInspirationSpBookNeeded();
+	
+	@Key("SkillLearn")
+	Boolean skillLearn();
+	
+	@Key("SubclassWithoutQuests")
+	Boolean subclassWithoutQuests();
+	
+	@Key("SubclassEverywhere")
+	Boolean subclassEverywhere();
+	
+	@Key("TransformationWithoutQuest")
+	Boolean transformationWithoutQuest();
+	
+	@Key("FeeDeleteTransferSkills")
+	Integer getFeeDeleteTransferSkills();
+	
+	@Key("FeeDeleteSubClassSkills")
+	Integer getFeeDeleteSubClassSkills();
+	
+	// Summons
+	
+	@Key("SummonStoreSkillCooltime")
+	Boolean summonStoreSkillCooltime();
+	
+	@Key("RestoreServitorOnReconnect")
+	Boolean restoreServitorOnReconnect();
+	
+	@Key("RestorePetOnReconnect")
+	Boolean restorePetOnReconnect();
+	
+	// Limits
+	
+	@Key("MaxExpBonus")
+	Double getMaxExpBonus();
+	
+	@Key("MaxSpBonus")
+	Double getMaxSpBonus();
+	
+	@Key("MaxRunSpeed")
+	Integer getMaxRunSpeed();
+	
+	@Key("MaxPCritRate")
+	Integer getMaxPCritRate();
+	
+	@Key("MaxMCritRate")
+	Integer getMaxMCritRate();
+	
+	@Key("MaxPAtkSpeed")
+	Integer getMaxPAtkSpeed();
+	
+	@Key("MaxMAtkSpeed")
+	Integer getMaxMAtkSpeed();
+	
+	@Key("MaxEvasion")
+	Integer getMaxEvasion();
+	
+	@Key("MinAbnormalStateSuccessRate")
+	Integer getMinAbnormalStateSuccessRate();
+	
+	@Key("MaxAbnormalStateSuccessRate")
+	Integer getMaxAbnormalStateSuccessRate();
+	
+	@Key("MaxPlayerLevel")
+	Integer getMaxPlayerLevel();
+	
+	@Key("MaxPetLevel")
+	Integer getMaxPetLevel();
+	
+	@Key("MaxSubclass")
+	Integer getMaxSubclass();
+	
+	@Key("BaseSubclassLevel")
+	Integer getBaseSubclassLevel();
+	
+	@Key("MaxSubclassLevel")
+	Integer getMaxSubclassLevel();
+	
+	@Key("MaxPvtStoreSellSlotsDwarf")
+	Integer getMaxPvtStoreSellSlotsDwarf();
+	
+	@Key("MaxPvtStoreSellSlotsOther")
+	Integer getMaxPvtStoreSellSlotsOther();
+	
+	@Key("MaxPvtStoreBuySlotsDwarf")
+	Integer getMaxPvtStoreBuySlotsDwarf();
+	
+	@Key("MaxPvtStoreBuySlotsOther")
+	Integer getMaxPvtStoreBuySlotsOther();
+	
+	@Key("MaximumSlotsForNoDwarf")
+	Integer getMaximumSlotsForNoDwarf();
+	
+	@Key("MaximumSlotsForDwarf")
+	Integer getMaximumSlotsForDwarf();
+	
+	@Key("MaximumSlotsForGMPlayer")
+	Integer getMaximumSlotsForGMPlayer();
+	
+	@Key("MaximumSlotsForQuestItems")
+	Integer getMaximumSlotsForQuestItems();
+	
+	@Key("MaximumWarehouseSlotsForDwarf")
+	Integer getMaximumWarehouseSlotsForDwarf();
+	
+	@Key("MaximumWarehouseSlotsForNoDwarf")
+	Integer getMaximumWarehouseSlotsForNoDwarf();
+	
+	@Key("MaximumWarehouseSlotsForClan")
+	Integer getMaximumWarehouseSlotsForClan();
+	
+	@Key("MaximumFreightSlots")
+	Integer getMaximumFreightSlots();
+	
+	@Key("FreightPrice")
+	Integer getFreightPrice();
+	
+	@Key("NpcTalkBlockingTime")
+	Integer getNpcTalkBlockingTime();
+	
+	// Enchanting
+	
+	@Key("EnchantChanceElementStone")
+	Integer getEnchantChanceElementStone();
+	
+	@Key("EnchantChanceElementCrystal")
+	Integer getEnchantChanceElementCrystal();
+	
+	@Key("EnchantChanceElementJewel")
+	Integer getEnchantChanceElementJewel();
+	
+	@Key("EnchantChanceElementEnergy")
+	Integer getEnchantChanceElementEnergy();
+	
+	@Key("EnchantBlacklist")
+	Set<Integer> getEnchantBlacklist();
+	
+	// Augmenting
+	
+	@Key("AugmentationNGSkillChance")
+	Integer getAugmentationNGSkillChance();
+	
+	@Key("AugmentationMidSkillChance")
+	Integer getAugmentationMidSkillChance();
+	
+	@Key("AugmentationHighSkillChance")
+	Integer getAugmentationHighSkillChance();
+	
+	@Key("AugmentationTopSkillChance")
+	Integer getAugmentationTopSkillChance();
+	
+	@Key("AugmentationAccSkillChance")
+	Integer getAugmentationAccSkillChance();
+	
+	@Key("AugmentationBaseStatChance")
+	Integer getAugmentationBaseStatChance();
+	
+	@Key("AugmentationNGGlowChance")
+	Integer getAugmentationNGGlowChance();
+	
+	@Key("AugmentationMidGlowChance")
+	Integer getAugmentationMidGlowChance();
+	
+	@Key("AugmentationHighGlowChance")
+	Integer getAugmentationHighGlowChance();
+	
+	@Key("AugmentationTopGlowChance")
+	Integer getAugmentationTopGlowChance();
+	
+	@Key("RetailLikeAugmentation")
+	Boolean retailLikeAugmentation();
+	
+	@Key("RetailLikeAugmentationNoGradeChance")
+	List<Integer> getRetailLikeAugmentationNoGradeChance();
+	
+	@Key("RetailLikeAugmentationMidGradeChance")
+	List<Integer> getRetailLikeAugmentationMidGradeChance();
+	
+	@Key("RetailLikeAugmentationHighGradeChance")
+	List<Integer> getRetailLikeAugmentationHighGradeChance();
+	
+	@Key("RetailLikeAugmentationTopGradeChance")
+	List<Integer> getRetailLikeAugmentationTopGradeChance();
+	
+	@Key("RetailLikeAugmentationAccessory")
+	Boolean retailLikeAugmentationAccessory();
+	
+	@Key("AugmentationBlacklist")
+	Set<Integer> getAugmentationBlacklist();
+	
+	@Key("AllowAugmentPvPItems")
+	Boolean allowAugmentPvPItems();
+	
+	// Karma
+	
+	@Key("KarmaPlayerCanBeKilledInPeaceZone")
+	Boolean karmaPlayerCanBeKilledInPeaceZone();
+	
+	@Key("KarmaPlayerCanUseGK")
+	Boolean karmaPlayerCanUseGK();
+	
+	@Key("KarmaPlayerCanTeleport")
+	Boolean karmaPlayerCanTeleport();
+	
+	@Key("KarmaPlayerCanShop")
+	Boolean karmaPlayerCanShop();
+	
+	@Key("KarmaPlayerCanTrade")
+	Boolean karmaPlayerCanTrade();
+	
+	@Key("KarmaPlayerCanUseWareHouse")
+	Boolean karmaPlayerCanUseWareHouse();
+	
+	// Fame
+	
+	@Key("MaxPersonalFamePoints")
+	Integer getMaxPersonalFamePoints();
+	
+	@Key("FortressZoneFameTaskFrequency")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getFortressZoneFameTaskFrequency();
+	
+	@Key("FortressZoneFameAquirePoints")
+	Integer getFortressZoneFameAquirePoints();
+	
+	@Key("CastleZoneFameTaskFrequency")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getCastleZoneFameTaskFrequency();
+	
+	@Key("CastleZoneFameAquirePoints")
+	Integer getCastleZoneFameAquirePoints();
+	
+	@Key("FameForDeadPlayers")
+	Boolean fameForDeadPlayers();
+	
+	// Crafting
+	
+	@Key("Crafting")
+	Boolean crafting();
+	
+	@Key("CraftMasterwork")
+	Boolean craftMasterwork();
+	
+	@Key("DwarfRecipeLimit")
+	Integer getDwarfRecipeLimit();
+	
+	@Key("CommonRecipeLimit")
+	Integer getCommonRecipeLimit();
+	
+	@Key("AlternativeCrafting")
+	Boolean alternativeCrafting();
+	
+	@Key("CraftingSpeed")
+	Double getCraftingSpeed();
+	
+	@Key("CraftingXpRate")
+	Double getCraftingXpRate();
+	
+	@Key("CraftingSpRate")
+	Double getCraftingSpRate();
+	
+	@Key("CraftingRareXpRate")
+	Double getCraftingRareXpRate();
+	
+	@Key("CraftingRareSpRate")
+	Double getCraftingRareSpRate();
+	
+	@Key("BlacksmithUseRecipes")
+	Boolean blacksmithUseRecipes();
+	
+	@Key("StoreRecipeShopList")
+	Boolean storeRecipeShopList();
+	
+	// Clan
+	
+	@Key("ClanLeaderDateChange")
+	Integer getClanLeaderDateChange();
+	
+	@Key("ClanLeaderHourChange")
+	String getClanLeaderHourChange();
+	
+	@Key("ClanLeaderInstantActivation")
+	Boolean clanLeaderInstantActivation();
+	
+	@Key("DaysBeforeJoinAClan")
+	Integer getDaysBeforeJoinAClan();
+	
+	@Key("DaysBeforeCreateAClan")
+	Integer getDaysBeforeCreateAClan();
+	
+	@Key("DaysToPassToDissolveAClan")
+	Integer getDaysToPassToDissolveAClan();
+	
+	@Key("DaysBeforeJoiningAllianceAfterLeaving")
+	Integer getDaysBeforeJoiningAllianceAfterLeaving();
+	
+	@Key("DaysBeforeJoinAllyWhenDismissed")
+	Integer getDaysBeforeJoinAllyWhenDismissed();
+	
+	@Key("DaysBeforeAcceptNewClanWhenDismissed")
+	Integer getDaysBeforeAcceptNewClanWhenDismissed();
+	
+	@Key("DaysBeforeCreateNewAllyWhenDissolved")
+	Integer getDaysBeforeCreateNewAllyWhenDissolved();
+	
+	@Key("MaxNumOfClansInAlly")
+	Integer getMaxNumOfClansInAlly();
+	
+	@Key("MembersCanWithdrawFromClanWH")
+	Boolean membersCanWithdrawFromClanWH();
+	
+	@Key("RemoveCastleCirclets")
+	Boolean removeCastleCirclets();
+	
+	@Key("ClanMembersForWar")
+	Integer getClanMembersForWar();
+	
+	// Party
+	
+	@Key("PartyRange")
+	Integer getPartyRange();
+	
+	@Key("PartyRange2")
+	Integer getPartyRange2();
+	
+	@Key("LeavePartyLeader")
+	Boolean leavePartyLeader();
+	
+	// Initial
+	
+	@Key("InitialEquipmentEvent")
+	Boolean initialEquipmentEvent();
+	
+	@Key("StartingAdena")
+	Integer getStartingAdena();
+	
+	@Key("StartingLevel")
+	Integer getStartingLevel();
+	
+	@Key("StartingSP")
+	Integer getStartingSP();
+	
+	// Other
+	
+	@Key("MaxAdena")
+	Long getMaxAdena();
+	
+	@Key("AutoLoot")
+	Boolean autoLoot();
+	
+	@Key("AutoLootRaids")
+	Boolean autoLootRaids();
+	
+	@Key("RaidLootRightsInterval")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getRaidLootRightsInterval();
+	
+	@Key("RaidLootRightsCCSize")
+	Integer getRaidLootRightsCCSize();
+	
+	@Key("UnstuckInterval")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getUnstuckInterval();
+	
+	@Key("TeleportWatchdogTimeout")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getTeleportWatchdogTimeout();
+	
+	@Key("PlayerSpawnProtection")
+	Integer getPlayerSpawnProtection();
+	
+	@Key("PlayerSpawnProtectionAllowedItems")
+	Set<Integer> getPlayerSpawnProtectionAllowedItems();
+	
+	@Key("PlayerTeleportProtection")
+	Integer getPlayerTeleportProtection();
+	
+	@Key("RandomRespawnInTown")
+	Boolean randomRespawnInTown();
+	
+	@Key("OffsetOnTeleport")
+	Boolean offsetOnTeleport();
+	
+	@Key("MaxOffsetOnTeleport")
+	Integer getMaxOffsetOnTeleport();
+	
+	@Key("PetitioningAllowed")
+	Boolean petitioningAllowed();
+	
+	@Key("MaxPetitionsPerPlayer")
+	Integer getMaxPetitionsPerPlayer();
+	
+	@Key("MaxPetitionsPending")
+	Integer getMaxPetitionsPending();
+	
+	@Key("FreeTeleporting")
+	Boolean freeTeleporting();
+	
+	@Key("DeleteCharAfterDays")
+	Integer getDeleteCharAfterDays();
+	
+	@Key("ExponentXp")
+	Integer getExponentXp();
+	
+	@Key("ExponentSp")
+	Integer getExponentSp();
+	
+	@Key("PartyXpCutoffMethod")
+	String getPartyXpCutoffMethod();
+	
+	@Key("PartyXpCutoffPercent")
+	Double getPartyXpCutoffPercent();
+	
+	@Key("PartyXpCutoffLevel")
+	Integer getPartyXpCutoffLevel();
+	
+	@Key("PartyXpCutoffGaps")
+	@ConverterClass(MapIntegerIntegerConverter.class)
+	Map<Integer, Integer> getPartyXpCutoffGaps();
+	
+	@Key("PartyXpCutoffGapPercent")
+	List<Integer> getPartyXpCutoffGapPercent();
+	
+	@Key("Tutorial")
+	Boolean tutorial();
+	
+	@Key("ExpertisePenalty")
+	Boolean expertisePenalty();
+	
+	@Key("StoreUISettings")
+	Boolean storeUISettings();
+	
+	@Key("SilenceModeExclude")
+	Boolean silenceModeExclude();
+	
+	@Key("ValidateTriggerSkills")
+	Boolean validateTriggerSkills();
+	
+	@Key("PlayerNameTemplate")
+	@ConverterClass(PatternConverter.class)
+	Pattern getPlayerNameTemplate();
+	
+	@Key("PetNameTemplate")
+	@ConverterClass(PatternConverter.class)
+	Pattern getPetNameTemplate();
+	
+	@Key("ForbiddenNames")
+	Set<String> getForbiddenNames();
+	
+	@Key("CharMaxNumber")
+	Integer getCharMaxNumber();
+}

+ 171 - 0
src/main/java/com/l2jserver/gameserver/config/ClanConfiguration.java

@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.regex.Pattern;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.PatternConverter;
+
+/**
+ * Clan Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/clan.properties",
+	"classpath:config/clan.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface ClanConfiguration extends Config, Reloadable {
+	
+	@Key("ClanNameTemplate")
+	@ConverterClass(PatternConverter.class)
+	Pattern getClanNameTemplate();
+	
+	@Key("TakeFortPoints")
+	Integer getTakeFortPoints();
+	
+	@Key("TakeCastlePoints")
+	Integer getTakeCastlePoints();
+	
+	@Key("CastleDefendedPoints")
+	Integer getCastleDefendedPoints();
+	
+	@Key("FestivalOfDarknessWin")
+	Integer getFestivalOfDarknessWin();
+	
+	@Key("HeroPoints")
+	Integer getHeroPoints();
+	
+	@Key("CompleteAcademyMinPoints")
+	Integer getCompleteAcademyMinPoints();
+	
+	@Key("CompleteAcademyMaxPoints")
+	Integer getCompleteAcademyMaxPoints();
+	
+	@Key("KillBallistaPoints")
+	Integer getKillBallistaPoints();
+	
+	@Key("BloodAlliancePoints")
+	Integer getBloodAlliancePoints();
+	
+	@Key("BloodOathPoints")
+	Integer getBloodOathPoints();
+	
+	@Key("KnightsEpaulettePoints")
+	Integer getKnightsEpaulettePoints();
+	
+	@Key("1stRaidRankingPoints")
+	Integer get1stRaidRankingPoints();
+	
+	@Key("2ndRaidRankingPoints")
+	Integer get2ndRaidRankingPoints();
+	
+	@Key("3rdRaidRankingPoints")
+	Integer get3rdRaidRankingPoints();
+	
+	@Key("4thRaidRankingPoints")
+	Integer get4thRaidRankingPoints();
+	
+	@Key("5thRaidRankingPoints")
+	Integer get5thRaidRankingPoints();
+	
+	@Key("6thRaidRankingPoints")
+	Integer get6thRaidRankingPoints();
+	
+	@Key("7thRaidRankingPoints")
+	Integer get7thRaidRankingPoints();
+	
+	@Key("8thRaidRankingPoints")
+	Integer get8thRaidRankingPoints();
+	
+	@Key("9thRaidRankingPoints")
+	Integer get9thRaidRankingPoints();
+	
+	@Key("10thRaidRankingPoints")
+	Integer get10thRaidRankingPoints();
+	
+	@Key("UpTo50thRaidRankingPoints")
+	Integer getUpTo50thRaidRankingPoints();
+	
+	@Key("UpTo100thRaidRankingPoints")
+	Integer getUpTo100thRaidRankingPoints();
+	
+	@Key("ReputationScorePerKill")
+	Integer getReputationScorePerKill();
+	
+	@Key("LoseFortPoints")
+	Integer getLoseFortPoints();
+	
+	@Key("LoseCastlePoints")
+	Integer getLoseCastlePoints();
+	
+	@Key("CreateRoyalGuardCost")
+	Integer getCreateRoyalGuardCost();
+	
+	@Key("CreateKnightUnitCost")
+	Integer getCreateKnightUnitCost();
+	
+	@Key("ReinforceKnightUnitCost")
+	Integer getReinforceKnightUnitCost();
+	
+	@Key("ClanLevel6Cost")
+	Integer getClanLevel6Cost();
+	
+	@Key("ClanLevel7Cost")
+	Integer getClanLevel7Cost();
+	
+	@Key("ClanLevel8Cost")
+	Integer getClanLevel8Cost();
+	
+	@Key("ClanLevel9Cost")
+	Integer getClanLevel9Cost();
+	
+	@Key("ClanLevel10Cost")
+	Integer getClanLevel10Cost();
+	
+	@Key("ClanLevel11Cost")
+	Integer getClanLevel11Cost();
+	
+	@Key("ClanLevel6Requirement")
+	Integer getClanLevel6Requirement();
+	
+	@Key("ClanLevel7Requirement")
+	Integer getClanLevel7Requirement();
+	
+	@Key("ClanLevel8Requirement")
+	Integer getClanLevel8Requirement();
+	
+	@Key("ClanLevel9Requirement")
+	Integer getClanLevel9Requirement();
+	
+	@Key("ClanLevel10Requirement")
+	Integer getClanLevel10Requirement();
+	
+	@Key("ClanLevel11Requirement")
+	Integer getClanLevel11Requirement();
+}

+ 211 - 0
src/main/java/com/l2jserver/gameserver/config/ClanHallConfiguration.java

@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Clan Hall Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/clanhall.properties",
+	"classpath:config/clanhall.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface ClanHallConfiguration extends Config, Reloadable {
+	
+	@Key("TeleportFunctionFeeRatio")
+	Long getTeleportFunctionFeeRatio();
+	
+	@Key("TeleportFunctionFeeLvl1")
+	Integer getTeleportFunctionFeeLvl1();
+	
+	@Key("TeleportFunctionFeeLvl2")
+	Integer getTeleportFunctionFeeLvl2();
+	
+	@Key("SupportFunctionFeeRatio")
+	Long getSupportFunctionFeeRatio();
+	
+	@Key("SupportFeeLvl1")
+	Integer getSupportFeeLvl1();
+	
+	@Key("SupportFeeLvl2")
+	Integer getSupportFeeLvl2();
+	
+	@Key("SupportFeeLvl3")
+	Integer getSupportFeeLvl3();
+	
+	@Key("SupportFeeLvl4")
+	Integer getSupportFeeLvl4();
+	
+	@Key("SupportFeeLvl5")
+	Integer getSupportFeeLvl5();
+	
+	@Key("SupportFeeLvl6")
+	Integer getSupportFeeLvl6();
+	
+	@Key("SupportFeeLvl7")
+	Integer getSupportFeeLvl7();
+	
+	@Key("SupportFeeLvl8")
+	Integer getSupportFeeLvl8();
+	
+	@Key("MpRegenerationFunctionFeeRatio")
+	Long getMpRegenerationFunctionFeeRatio();
+	
+	@Key("MpRegenerationFeeLvl1")
+	Integer getMpRegenerationFeeLvl1();
+	
+	@Key("MpRegenerationFeeLvl2")
+	Integer getMpRegenerationFeeLvl2();
+	
+	@Key("MpRegenerationFeeLvl3")
+	Integer getMpRegenerationFeeLvl3();
+	
+	@Key("MpRegenerationFeeLvl4")
+	Integer getMpRegenerationFeeLvl4();
+	
+	@Key("MpRegenerationFeeLvl5")
+	Integer getMpRegenerationFeeLvl5();
+	
+	@Key("HpRegenerationFunctionFeeRatio")
+	Long getHpRegenerationFunctionFeeRatio();
+	
+	@Key("HpRegenerationFeeLvl1")
+	Integer getHpRegenerationFeeLvl1();
+	
+	@Key("HpRegenerationFeeLvl2")
+	Integer getHpRegenerationFeeLvl2();
+	
+	@Key("HpRegenerationFeeLvl3")
+	Integer getHpRegenerationFeeLvl3();
+	
+	@Key("HpRegenerationFeeLvl4")
+	Integer getHpRegenerationFeeLvl4();
+	
+	@Key("HpRegenerationFeeLvl5")
+	Integer getHpRegenerationFeeLvl5();
+	
+	@Key("HpRegenerationFeeLvl6")
+	Integer getHpRegenerationFeeLvl6();
+	
+	@Key("HpRegenerationFeeLvl7")
+	Integer getHpRegenerationFeeLvl7();
+	
+	@Key("HpRegenerationFeeLvl8")
+	Integer getHpRegenerationFeeLvl8();
+	
+	@Key("HpRegenerationFeeLvl9")
+	Integer getHpRegenerationFeeLvl9();
+	
+	@Key("HpRegenerationFeeLvl10")
+	Integer getHpRegenerationFeeLvl10();
+	
+	@Key("HpRegenerationFeeLvl11")
+	Integer getHpRegenerationFeeLvl11();
+	
+	@Key("HpRegenerationFeeLvl12")
+	Integer getHpRegenerationFeeLvl12();
+	
+	@Key("HpRegenerationFeeLvl13")
+	Integer getHpRegenerationFeeLvl13();
+	
+	@Key("ExpRegenerationFunctionFeeRatio")
+	Long getExpRegenerationFunctionFeeRatio();
+	
+	@Key("ExpRegenerationFeeLvl1")
+	Integer getExpRegenerationFeeLvl1();
+	
+	@Key("ExpRegenerationFeeLvl2")
+	Integer getExpRegenerationFeeLvl2();
+	
+	@Key("ExpRegenerationFeeLvl3")
+	Integer getExpRegenerationFeeLvl3();
+	
+	@Key("ExpRegenerationFeeLvl4")
+	Integer getExpRegenerationFeeLvl4();
+	
+	@Key("ExpRegenerationFeeLvl5")
+	Integer getExpRegenerationFeeLvl5();
+	
+	@Key("ExpRegenerationFeeLvl6")
+	Integer getExpRegenerationFeeLvl6();
+	
+	@Key("ExpRegenerationFeeLvl7")
+	Integer getExpRegenerationFeeLvl7();
+	
+	@Key("ItemCreationFunctionFeeRatio")
+	Long getItemCreationFunctionFeeRatio();
+	
+	@Key("ItemCreationFunctionFeeLvl1")
+	Integer getItemCreationFunctionFeeLvl1();
+	
+	@Key("ItemCreationFunctionFeeLvl2")
+	Integer getItemCreationFunctionFeeLvl2();
+	
+	@Key("ItemCreationFunctionFeeLvl3")
+	Integer getItemCreationFunctionFeeLvl3();
+	
+	@Key("CurtainFunctionFeeRatio")
+	Long getCurtainFunctionFeeRatio();
+	
+	@Key("CurtainFunctionFeeLvl1")
+	Integer getCurtainFunctionFeeLvl1();
+	
+	@Key("CurtainFunctionFeeLvl2")
+	Integer getCurtainFunctionFeeLvl2();
+	
+	@Key("FrontPlatformFunctionFeeLvl1")
+	Integer getFrontPlatformFunctionFeeLvl1();
+	
+	@Key("FrontPlatformFunctionFeeLvl2")
+	Integer getFrontPlatformFunctionFeeLvl2();
+	
+	@Key("FrontPlatformFunctionFeeRatio")
+	Long getFrontPlatformFunctionFeeRatio();
+	
+	@Key("MpBuffFree")
+	Boolean mpBuffFree();
+	
+	@Key("MinClanLevel")
+	Integer getMinClanLevel();
+	
+	@Key("MaxAttackers")
+	Integer getMaxAttackers();
+	
+	@Key("MaxFlagsPerClan")
+	Integer getMaxFlagsPerClan();
+	
+	@Key("EnableFame")
+	Boolean enableFame();
+	
+	@Key("FameAmount")
+	Integer getFameAmount();
+	
+	@Key("FameFrequency")
+	Integer getFameFrequency();
+}

+ 0 - 3724
src/main/java/com/l2jserver/gameserver/config/Config.java

@@ -1,3724 +0,0 @@
-/*
- * Copyright © 2004-2019 L2J Server
- *
- * This file is part of L2J Server.
- *
- * L2J Server is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * L2J Server is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.l2jserver.gameserver.config;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.math.BigInteger;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import com.l2jserver.gameserver.GameServer;
-import com.l2jserver.gameserver.enums.IllegalActionPunishmentType;
-import com.l2jserver.gameserver.model.L2World;
-import com.l2jserver.gameserver.model.holders.ItemHolder;
-import com.l2jserver.gameserver.model.itemcontainer.Inventory;
-import com.l2jserver.gameserver.util.FloodProtectorConfig;
-import com.l2jserver.gameserver.util.IXmlReader;
-import com.l2jserver.gameserver.util.StringUtil;
-import com.l2jserver.gameserver.util.Util;
-
-/**
- * This class loads all the game server related configurations from files.<br>
- * The files are usually located in config folder in server root folder.<br>
- * Each configuration has a default value (that should reflect retail behavior).
- */
-public final class Config {
-	private static final Logger LOG = LoggerFactory.getLogger(Config.class);
-	
-	/**
-	 * Informs(logs) the scripts being loaded.<BR>
-	 * Apply only when executing script from files.<BR>
-	 */
-	public static final boolean VERBOSE_LOADING = false;
-	
-	// --------------------------------------------------
-	// Constants
-	// --------------------------------------------------
-	public static final String EOL = System.lineSeparator();
-	
-	// --------------------------------------------------
-	// L2J Property File Definitions
-	// --------------------------------------------------
-	public static final String CHARACTER_CONFIG_FILE = "./config/Character.properties";
-	public static final String FEATURE_CONFIG_FILE = "./config/Feature.properties";
-	public static final String FORTSIEGE_CONFIGURATION_FILE = "./config/FortSiege.properties";
-	public static final String GENERAL_CONFIG_FILE = "./config/General.properties";
-	public static final String HEXID_FILE = "./config/hexid.txt";
-	public static final String ID_CONFIG_FILE = "./config/IdFactory.properties";
-	public static final String L2JMOD_CONFIG_FILE = "./config/L2JMods.properties";
-	public static final String LOGIN_CONFIGURATION_FILE = "./config/LoginServer.properties";
-	public static final String NPC_CONFIG_FILE = "./config/NPC.properties";
-	public static final String PVP_CONFIG_FILE = "./config/PVP.properties";
-	public static final String RATES_CONFIG_FILE = "./config/Rates.properties";
-	public static final String CONFIGURATION_FILE = "./config/Server.properties";
-	public static final String IP_CONFIG_FILE = "./config/ipconfig.xml";
-	public static final String SIEGE_CONFIGURATION_FILE = "./config/Siege.properties";
-	public static final String TW_CONFIGURATION_FILE = "./config/TerritoryWar.properties";
-	public static final String TELNET_FILE = "./config/Telnet.properties";
-	public static final String FLOOD_PROTECTOR_FILE = "./config/FloodProtector.properties";
-	public static final String MMO_CONFIG_FILE = "./config/MMO.properties";
-	public static final String OLYMPIAD_CONFIG_FILE = "./config/Olympiad.properties";
-	public static final String GRANDBOSS_CONFIG_FILE = "./config/GrandBoss.properties";
-	public static final String GRACIASEEDS_CONFIG_FILE = "./config/GraciaSeeds.properties";
-	public static final String CHAT_FILTER_FILE = "./config/chatfilter.txt";
-	public static final String EMAIL_CONFIG_FILE = "./config/Email.properties";
-	public static final String CH_SIEGE_FILE = "./config/ConquerableHallSiege.properties";
-	public static final String GEODATA_FILE = "./config/GeoData.properties";
-	// --------------------------------------------------
-	// L2J Variable Definitions
-	// --------------------------------------------------
-	public static boolean ALT_GAME_DELEVEL;
-	public static boolean DECREASE_SKILL_LEVEL;
-	public static double ALT_WEIGHT_LIMIT;
-	public static int RUN_SPD_BOOST;
-	public static int DEATH_PENALTY_CHANCE;
-	public static double RESPAWN_RESTORE_CP;
-	public static double RESPAWN_RESTORE_HP;
-	public static double RESPAWN_RESTORE_MP;
-	public static boolean ENABLE_MODIFY_SKILL_DURATION;
-	public static Map<Integer, Integer> SKILL_DURATION_LIST;
-	public static boolean ENABLE_MODIFY_SKILL_REUSE;
-	public static Map<Integer, Integer> SKILL_REUSE_LIST;
-	public static boolean AUTO_LEARN_SKILLS;
-	public static boolean AUTO_LEARN_FS_SKILLS;
-	public static boolean AUTO_LOOT_HERBS;
-	public static byte BUFFS_MAX_AMOUNT;
-	public static byte TRIGGERED_BUFFS_MAX_AMOUNT;
-	public static byte DANCES_MAX_AMOUNT;
-	public static boolean DANCE_CANCEL_BUFF;
-	public static boolean DANCE_CONSUME_ADDITIONAL_MP;
-	public static boolean ALT_STORE_DANCES;
-	public static boolean AUTO_LEARN_DIVINE_INSPIRATION;
-	public static boolean ALT_GAME_CANCEL_BOW;
-	public static boolean ALT_GAME_CANCEL_CAST;
-	public static boolean ALT_GAME_MAGICFAILURES;
-	public static int PLAYER_FAKEDEATH_UP_PROTECTION;
-	public static boolean STORE_SKILL_COOLTIME;
-	public static boolean SUBCLASS_STORE_SKILL_COOLTIME;
-	public static boolean SUMMON_STORE_SKILL_COOLTIME;
-	public static boolean ALT_GAME_SHIELD_BLOCKS;
-	public static int ALT_PERFECT_SHLD_BLOCK;
-	public static long EFFECT_TICK_RATIO;
-	public static boolean ALLOW_CLASS_MASTERS;
-	public static ClassMasterSettings CLASS_MASTER_SETTINGS;
-	public static boolean ALLOW_ENTIRE_TREE;
-	public static boolean ALTERNATE_CLASS_MASTER;
-	public static boolean LIFE_CRYSTAL_NEEDED;
-	public static boolean ES_SP_BOOK_NEEDED;
-	public static boolean DIVINE_SP_BOOK_NEEDED;
-	public static boolean ALT_GAME_SKILL_LEARN;
-	public static boolean ALT_GAME_SUBCLASS_WITHOUT_QUESTS;
-	public static boolean ALT_GAME_SUBCLASS_EVERYWHERE;
-	public static boolean ALLOW_TRANSFORM_WITHOUT_QUEST;
-	public static int FEE_DELETE_TRANSFER_SKILLS;
-	public static int FEE_DELETE_SUBCLASS_SKILLS;
-	public static boolean RESTORE_SERVITOR_ON_RECONNECT;
-	public static boolean RESTORE_PET_ON_RECONNECT;
-	public static double MAX_BONUS_EXP;
-	public static double MAX_BONUS_SP;
-	public static int MAX_RUN_SPEED;
-	public static int MAX_PCRIT_RATE;
-	public static int MAX_MCRIT_RATE;
-	public static int MAX_PATK_SPEED;
-	public static int MAX_MATK_SPEED;
-	public static int MAX_EVASION;
-	public static int MIN_ABNORMAL_STATE_SUCCESS_RATE;
-	public static int MAX_ABNORMAL_STATE_SUCCESS_RATE;
-	public static int MAX_PLAYER_LEVEL;
-	public static int MAX_PET_LEVEL;
-	public static byte MAX_SUBCLASS;
-	public static int BASE_SUBCLASS_LEVEL;
-	public static int MAX_SUBCLASS_LEVEL;
-	public static int MAX_PVTSTORESELL_SLOTS_DWARF;
-	public static int MAX_PVTSTORESELL_SLOTS_OTHER;
-	public static int MAX_PVTSTOREBUY_SLOTS_DWARF;
-	public static int MAX_PVTSTOREBUY_SLOTS_OTHER;
-	public static int INVENTORY_MAXIMUM_NO_DWARF;
-	public static int INVENTORY_MAXIMUM_DWARF;
-	public static int INVENTORY_MAXIMUM_GM;
-	public static int INVENTORY_MAXIMUM_QUEST_ITEMS;
-	public static int WAREHOUSE_SLOTS_DWARF;
-	public static int WAREHOUSE_SLOTS_NO_DWARF;
-	public static int WAREHOUSE_SLOTS_CLAN;
-	public static int ALT_FREIGHT_SLOTS;
-	public static int ALT_FREIGHT_PRICE;
-	public static boolean ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE;
-	public static boolean ALT_GAME_KARMA_PLAYER_CAN_SHOP;
-	public static boolean ALT_GAME_KARMA_PLAYER_CAN_TELEPORT;
-	public static boolean ALT_GAME_KARMA_PLAYER_CAN_USE_GK;
-	public static boolean ALT_GAME_KARMA_PLAYER_CAN_TRADE;
-	public static boolean ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE;
-	public static int MAX_PERSONAL_FAME_POINTS;
-	public static int FORTRESS_ZONE_FAME_TASK_FREQUENCY;
-	public static int FORTRESS_ZONE_FAME_AQUIRE_POINTS;
-	public static int CASTLE_ZONE_FAME_TASK_FREQUENCY;
-	public static int CASTLE_ZONE_FAME_AQUIRE_POINTS;
-	public static boolean FAME_FOR_DEAD_PLAYERS;
-	public static boolean IS_CRAFTING_ENABLED;
-	public static boolean CRAFT_MASTERWORK;
-	public static int DWARF_RECIPE_LIMIT;
-	public static int COMMON_RECIPE_LIMIT;
-	public static boolean ALT_GAME_CREATION;
-	public static double ALT_GAME_CREATION_SPEED;
-	public static double ALT_GAME_CREATION_XP_RATE;
-	public static double ALT_GAME_CREATION_RARE_XPSP_RATE;
-	public static double ALT_GAME_CREATION_SP_RATE;
-	public static boolean ALT_BLACKSMITH_USE_RECIPES;
-	public static int ALT_CLAN_LEADER_DATE_CHANGE;
-	public static String ALT_CLAN_LEADER_HOUR_CHANGE;
-	public static boolean ALT_CLAN_LEADER_INSTANT_ACTIVATION;
-	public static int ALT_CLAN_JOIN_DAYS;
-	public static int ALT_CLAN_CREATE_DAYS;
-	public static int ALT_CLAN_DISSOLVE_DAYS;
-	public static int ALT_ALLY_JOIN_DAYS_WHEN_LEAVED;
-	public static int ALT_ALLY_JOIN_DAYS_WHEN_DISMISSED;
-	public static int ALT_ACCEPT_CLAN_DAYS_WHEN_DISMISSED;
-	public static int ALT_CREATE_ALLY_DAYS_WHEN_DISSOLVED;
-	public static int ALT_MAX_NUM_OF_CLANS_IN_ALLY;
-	public static int ALT_CLAN_MEMBERS_FOR_WAR;
-	public static boolean ALT_MEMBERS_CAN_WITHDRAW_FROM_CLANWH;
-	public static boolean REMOVE_CASTLE_CIRCLETS;
-	public static int ALT_PARTY_RANGE;
-	public static int ALT_PARTY_RANGE2;
-	public static boolean ALT_LEAVE_PARTY_LEADER;
-	public static boolean INITIAL_EQUIPMENT_EVENT;
-	public static long STARTING_ADENA;
-	public static int STARTING_LEVEL;
-	public static int STARTING_SP;
-	public static long MAX_ADENA;
-	public static boolean AUTO_LOOT;
-	public static boolean AUTO_LOOT_RAIDS;
-	public static int LOOT_RAIDS_PRIVILEGE_INTERVAL;
-	public static int LOOT_RAIDS_PRIVILEGE_CC_SIZE;
-	public static int UNSTUCK_INTERVAL;
-	public static int TELEPORT_WATCHDOG_TIMEOUT;
-	public static int PLAYER_SPAWN_PROTECTION;
-	public static List<Integer> SPAWN_PROTECTION_ALLOWED_ITEMS;
-	public static int PLAYER_TELEPORT_PROTECTION;
-	public static boolean RANDOM_RESPAWN_IN_TOWN_ENABLED;
-	public static boolean OFFSET_ON_TELEPORT_ENABLED;
-	public static int MAX_OFFSET_ON_TELEPORT;
-	public static boolean PETITIONING_ALLOWED;
-	public static int MAX_PETITIONS_PER_PLAYER;
-	public static int MAX_PETITIONS_PENDING;
-	public static boolean ALT_GAME_FREE_TELEPORT;
-	public static int DELETE_DAYS;
-	public static float ALT_GAME_EXPONENT_XP;
-	public static float ALT_GAME_EXPONENT_SP;
-	public static String PARTY_XP_CUTOFF_METHOD;
-	public static double PARTY_XP_CUTOFF_PERCENT;
-	public static int PARTY_XP_CUTOFF_LEVEL;
-	public static int[][] PARTY_XP_CUTOFF_GAPS;
-	public static int[] PARTY_XP_CUTOFF_GAP_PERCENTS;
-	public static boolean DISABLE_TUTORIAL;
-	public static boolean EXPERTISE_PENALTY;
-	public static boolean STORE_RECIPE_SHOPLIST;
-	public static boolean STORE_UI_SETTINGS;
-	public static Set<String> FORBIDDEN_NAMES;
-	public static boolean SILENCE_MODE_EXCLUDE;
-	public static boolean ALT_VALIDATE_TRIGGER_SKILLS;
-	
-	// --------------------------------------------------
-	// ClanHall Settings
-	// --------------------------------------------------
-	public static long CH_TELE_FEE_RATIO;
-	public static int CH_TELE1_FEE;
-	public static int CH_TELE2_FEE;
-	public static long CH_ITEM_FEE_RATIO;
-	public static int CH_ITEM1_FEE;
-	public static int CH_ITEM2_FEE;
-	public static int CH_ITEM3_FEE;
-	public static long CH_MPREG_FEE_RATIO;
-	public static int CH_MPREG1_FEE;
-	public static int CH_MPREG2_FEE;
-	public static int CH_MPREG3_FEE;
-	public static int CH_MPREG4_FEE;
-	public static int CH_MPREG5_FEE;
-	public static long CH_HPREG_FEE_RATIO;
-	public static int CH_HPREG1_FEE;
-	public static int CH_HPREG2_FEE;
-	public static int CH_HPREG3_FEE;
-	public static int CH_HPREG4_FEE;
-	public static int CH_HPREG5_FEE;
-	public static int CH_HPREG6_FEE;
-	public static int CH_HPREG7_FEE;
-	public static int CH_HPREG8_FEE;
-	public static int CH_HPREG9_FEE;
-	public static int CH_HPREG10_FEE;
-	public static int CH_HPREG11_FEE;
-	public static int CH_HPREG12_FEE;
-	public static int CH_HPREG13_FEE;
-	public static long CH_EXPREG_FEE_RATIO;
-	public static int CH_EXPREG1_FEE;
-	public static int CH_EXPREG2_FEE;
-	public static int CH_EXPREG3_FEE;
-	public static int CH_EXPREG4_FEE;
-	public static int CH_EXPREG5_FEE;
-	public static int CH_EXPREG6_FEE;
-	public static int CH_EXPREG7_FEE;
-	public static long CH_SUPPORT_FEE_RATIO;
-	public static int CH_SUPPORT1_FEE;
-	public static int CH_SUPPORT2_FEE;
-	public static int CH_SUPPORT3_FEE;
-	public static int CH_SUPPORT4_FEE;
-	public static int CH_SUPPORT5_FEE;
-	public static int CH_SUPPORT6_FEE;
-	public static int CH_SUPPORT7_FEE;
-	public static int CH_SUPPORT8_FEE;
-	public static long CH_CURTAIN_FEE_RATIO;
-	public static int CH_CURTAIN1_FEE;
-	public static int CH_CURTAIN2_FEE;
-	public static long CH_FRONT_FEE_RATIO;
-	public static int CH_FRONT1_FEE;
-	public static int CH_FRONT2_FEE;
-	public static boolean CH_BUFF_FREE;
-	// --------------------------------------------------
-	// Castle Settings
-	// --------------------------------------------------
-	public static long CS_TELE_FEE_RATIO;
-	public static int CS_TELE1_FEE;
-	public static int CS_TELE2_FEE;
-	public static long CS_MPREG_FEE_RATIO;
-	public static int CS_MPREG1_FEE;
-	public static int CS_MPREG2_FEE;
-	public static long CS_HPREG_FEE_RATIO;
-	public static int CS_HPREG1_FEE;
-	public static int CS_HPREG2_FEE;
-	public static long CS_EXPREG_FEE_RATIO;
-	public static int CS_EXPREG1_FEE;
-	public static int CS_EXPREG2_FEE;
-	public static long CS_SUPPORT_FEE_RATIO;
-	public static int CS_SUPPORT1_FEE;
-	public static int CS_SUPPORT2_FEE;
-	public static List<Integer> SIEGE_HOUR_LIST;
-	public static int OUTER_DOOR_UPGRADE_PRICE2;
-	public static int OUTER_DOOR_UPGRADE_PRICE3;
-	public static int OUTER_DOOR_UPGRADE_PRICE5;
-	public static int INNER_DOOR_UPGRADE_PRICE2;
-	public static int INNER_DOOR_UPGRADE_PRICE3;
-	public static int INNER_DOOR_UPGRADE_PRICE5;
-	public static int WALL_UPGRADE_PRICE2;
-	public static int WALL_UPGRADE_PRICE3;
-	public static int WALL_UPGRADE_PRICE5;
-	public static int TRAP_UPGRADE_PRICE1;
-	public static int TRAP_UPGRADE_PRICE2;
-	public static int TRAP_UPGRADE_PRICE3;
-	public static int TRAP_UPGRADE_PRICE4;
-	
-	// --------------------------------------------------
-	// Fortress Settings
-	// --------------------------------------------------
-	public static long FS_TELE_FEE_RATIO;
-	public static int FS_TELE1_FEE;
-	public static int FS_TELE2_FEE;
-	public static long FS_MPREG_FEE_RATIO;
-	public static int FS_MPREG1_FEE;
-	public static int FS_MPREG2_FEE;
-	public static long FS_HPREG_FEE_RATIO;
-	public static int FS_HPREG1_FEE;
-	public static int FS_HPREG2_FEE;
-	public static long FS_EXPREG_FEE_RATIO;
-	public static int FS_EXPREG1_FEE;
-	public static int FS_EXPREG2_FEE;
-	public static long FS_SUPPORT_FEE_RATIO;
-	public static int FS_SUPPORT1_FEE;
-	public static int FS_SUPPORT2_FEE;
-	public static int FS_BLOOD_OATH_COUNT;
-	public static int FS_UPDATE_FRQ;
-	public static int FS_MAX_SUPPLY_LEVEL;
-	public static int FS_FEE_FOR_CASTLE;
-	public static int FS_MAX_OWN_TIME;
-	// --------------------------------------------------
-	// Feature Settings
-	// --------------------------------------------------
-	public static int TAKE_FORT_POINTS;
-	public static int LOOSE_FORT_POINTS;
-	public static int TAKE_CASTLE_POINTS;
-	public static int LOOSE_CASTLE_POINTS;
-	public static int CASTLE_DEFENDED_POINTS;
-	public static int FESTIVAL_WIN_POINTS;
-	public static int HERO_POINTS;
-	public static int ROYAL_GUARD_COST;
-	public static int KNIGHT_UNIT_COST;
-	public static int KNIGHT_REINFORCE_COST;
-	public static int BALLISTA_POINTS;
-	public static int BLOODALLIANCE_POINTS;
-	public static int BLOODOATH_POINTS;
-	public static int KNIGHTSEPAULETTE_POINTS;
-	public static int REPUTATION_SCORE_PER_KILL;
-	public static int JOIN_ACADEMY_MIN_REP_SCORE;
-	public static int JOIN_ACADEMY_MAX_REP_SCORE;
-	public static int RAID_RANKING_1ST;
-	public static int RAID_RANKING_2ND;
-	public static int RAID_RANKING_3RD;
-	public static int RAID_RANKING_4TH;
-	public static int RAID_RANKING_5TH;
-	public static int RAID_RANKING_6TH;
-	public static int RAID_RANKING_7TH;
-	public static int RAID_RANKING_8TH;
-	public static int RAID_RANKING_9TH;
-	public static int RAID_RANKING_10TH;
-	public static int RAID_RANKING_UP_TO_50TH;
-	public static int RAID_RANKING_UP_TO_100TH;
-	public static int CLAN_LEVEL_6_COST;
-	public static int CLAN_LEVEL_7_COST;
-	public static int CLAN_LEVEL_8_COST;
-	public static int CLAN_LEVEL_9_COST;
-	public static int CLAN_LEVEL_10_COST;
-	public static int CLAN_LEVEL_11_COST;
-	public static int CLAN_LEVEL_6_REQUIREMENT;
-	public static int CLAN_LEVEL_7_REQUIREMENT;
-	public static int CLAN_LEVEL_8_REQUIREMENT;
-	public static int CLAN_LEVEL_9_REQUIREMENT;
-	public static int CLAN_LEVEL_10_REQUIREMENT;
-	public static int CLAN_LEVEL_11_REQUIREMENT;
-	public static boolean ALLOW_WYVERN_ALWAYS;
-	public static boolean ALLOW_WYVERN_DURING_SIEGE;
-	
-	// --------------------------------------------------
-	// General Settings
-	// --------------------------------------------------
-	public static boolean EVERYBODY_HAS_ADMIN_RIGHTS;
-	public static boolean SERVER_LIST_BRACKET;
-	public static int SERVER_LIST_TYPE;
-	public static int SERVER_LIST_AGE;
-	public static boolean SERVER_GMONLY;
-	public static boolean GM_HERO_AURA;
-	public static boolean GM_STARTUP_INVULNERABLE;
-	public static boolean GM_STARTUP_INVISIBLE;
-	public static boolean GM_STARTUP_SILENCE;
-	public static boolean GM_STARTUP_AUTO_LIST;
-	public static boolean GM_STARTUP_DIET_MODE;
-	public static boolean GM_ITEM_RESTRICTION;
-	public static boolean GM_SKILL_RESTRICTION;
-	public static boolean GM_TRADE_RESTRICTED_ITEMS;
-	public static boolean GM_RESTART_FIGHTING;
-	public static boolean GM_ANNOUNCER_NAME;
-	public static boolean GM_CRITANNOUNCER_NAME;
-	public static boolean GM_GIVE_SPECIAL_SKILLS;
-	public static boolean GM_GIVE_SPECIAL_AURA_SKILLS;
-	public static boolean GAMEGUARD_ENFORCE;
-	public static boolean GAMEGUARD_PROHIBITACTION;
-	public static boolean LOG_CHAT;
-	public static boolean LOG_AUTO_ANNOUNCEMENTS;
-	public static boolean LOG_ITEMS;
-	public static boolean LOG_ITEMS_SMALL_LOG;
-	public static boolean LOG_ITEM_ENCHANTS;
-	public static boolean LOG_SKILL_ENCHANTS;
-	public static boolean GMAUDIT;
-	public static boolean SKILL_CHECK_ENABLE;
-	public static boolean SKILL_CHECK_REMOVE;
-	public static boolean SKILL_CHECK_GM;
-	public static boolean DEBUG;
-	public static boolean DEBUG_INSTANCES;
-	public static boolean HTML_ACTION_CACHE_DEBUG;
-	public static boolean PACKET_HANDLER_DEBUG;
-	public static boolean DEVELOPER;
-	public static boolean NO_HANDLERS;
-	public static boolean NO_QUESTS;
-	public static boolean ALT_DEV_NO_SPAWNS;
-	public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
-	public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
-	public static int THREAD_P_EFFECTS;
-	public static int THREAD_P_GENERAL;
-	public static int THREAD_E_EVENTS;
-	public static int GENERAL_PACKET_THREAD_CORE_SIZE;
-	public static int IO_PACKET_THREAD_CORE_SIZE;
-	public static int GENERAL_THREAD_CORE_SIZE;
-	public static int AI_MAX_THREAD;
-	public static int EVENT_MAX_THREAD;
-	public static int CLIENT_PACKET_QUEUE_SIZE;
-	public static int CLIENT_PACKET_QUEUE_MAX_BURST_SIZE;
-	public static int CLIENT_PACKET_QUEUE_MAX_PACKETS_PER_SECOND;
-	public static int CLIENT_PACKET_QUEUE_MEASURE_INTERVAL;
-	public static int CLIENT_PACKET_QUEUE_MAX_AVERAGE_PACKETS_PER_SECOND;
-	public static int CLIENT_PACKET_QUEUE_MAX_FLOODS_PER_MIN;
-	public static int CLIENT_PACKET_QUEUE_MAX_OVERFLOWS_PER_MIN;
-	public static int CLIENT_PACKET_QUEUE_MAX_UNDERFLOWS_PER_MIN;
-	public static int CLIENT_PACKET_QUEUE_MAX_UNKNOWN_PER_MIN;
-	public static boolean DEADLOCK_DETECTOR;
-	public static int DEADLOCK_CHECK_INTERVAL;
-	public static boolean RESTART_ON_DEADLOCK;
-	public static boolean ALLOW_DISCARDITEM;
-	public static int AUTODESTROY_ITEM_AFTER;
-	public static int HERB_AUTO_DESTROY_TIME;
-	public static List<Integer> LIST_PROTECTED_ITEMS;
-	public static boolean DATABASE_CLEAN_UP;
-	public static long CONNECTION_CLOSE_TIME;
-	public static int CHAR_STORE_INTERVAL;
-	public static boolean LAZY_ITEMS_UPDATE;
-	public static boolean UPDATE_ITEMS_ON_CHAR_STORE;
-	public static boolean DESTROY_DROPPED_PLAYER_ITEM;
-	public static boolean DESTROY_EQUIPABLE_PLAYER_ITEM;
-	public static boolean SAVE_DROPPED_ITEM;
-	public static boolean EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD;
-	public static int SAVE_DROPPED_ITEM_INTERVAL;
-	public static boolean CLEAR_DROPPED_ITEM_TABLE;
-	public static boolean AUTODELETE_INVALID_QUEST_DATA;
-	public static boolean PRECISE_DROP_CALCULATION;
-	public static boolean MULTIPLE_ITEM_DROP;
-	public static boolean FORCE_INVENTORY_UPDATE;
-	public static boolean LAZY_CACHE;
-	public static boolean CACHE_CHAR_NAMES;
-	public static int MIN_NPC_ANIMATION;
-	public static int MAX_NPC_ANIMATION;
-	public static int MIN_MONSTER_ANIMATION;
-	public static int MAX_MONSTER_ANIMATION;
-	public static boolean ENABLE_FALLING_DAMAGE;
-	public static boolean GRIDS_ALWAYS_ON;
-	public static int GRID_NEIGHBOR_TURNON_TIME;
-	public static int GRID_NEIGHBOR_TURNOFF_TIME;
-	public static boolean MOVE_BASED_KNOWNLIST;
-	public static long KNOWNLIST_UPDATE_INTERVAL;
-	public static int PEACE_ZONE_MODE;
-	public static String DEFAULT_GLOBAL_CHAT;
-	public static String DEFAULT_TRADE_CHAT;
-	public static boolean ALLOW_WAREHOUSE;
-	public static boolean WAREHOUSE_CACHE;
-	public static int WAREHOUSE_CACHE_TIME;
-	public static boolean ALLOW_REFUND;
-	public static boolean ALLOW_MAIL;
-	public static boolean ALLOW_ATTACHMENTS;
-	public static boolean ALLOW_WEAR;
-	public static int WEAR_DELAY;
-	public static int WEAR_PRICE;
-	public static int INSTANCE_FINISH_TIME;
-	public static boolean RESTORE_PLAYER_INSTANCE;
-	public static boolean ALLOW_SUMMON_IN_INSTANCE;
-	public static int EJECT_DEAD_PLAYER_TIME;
-	public static boolean ALLOW_LOTTERY;
-	public static boolean ALLOW_RACE;
-	public static boolean ALLOW_WATER;
-	public static boolean ALLOW_RENTPET;
-	public static boolean ALLOWFISHING;
-	public static boolean ALLOW_BOAT;
-	public static int BOAT_BROADCAST_RADIUS;
-	public static boolean ALLOW_CURSED_WEAPONS;
-	public static boolean ALLOW_MANOR;
-	public static boolean ALLOW_PET_WALKERS;
-	public static boolean SERVER_NEWS;
-	public static boolean ENABLE_COMMUNITY_BOARD;
-	public static String BBS_DEFAULT;
-	public static boolean USE_SAY_FILTER;
-	public static String CHAT_FILTER_CHARS;
-	public static int[] BAN_CHAT_CHANNELS;
-	public static int ALT_OLY_START_TIME;
-	public static int ALT_OLY_MIN;
-	public static int ALT_OLY_MAX_BUFFS;
-	public static long ALT_OLY_CPERIOD;
-	public static long ALT_OLY_BATTLE;
-	public static long ALT_OLY_WPERIOD;
-	public static long ALT_OLY_VPERIOD;
-	public static int ALT_OLY_START_POINTS;
-	public static int ALT_OLY_WEEKLY_POINTS;
-	public static int ALT_OLY_CLASSED;
-	public static int ALT_OLY_NONCLASSED;
-	public static int ALT_OLY_TEAMS;
-	public static int ALT_OLY_REG_DISPLAY;
-	public static int[][] ALT_OLY_CLASSED_REWARD;
-	public static int[][] ALT_OLY_NONCLASSED_REWARD;
-	public static int[][] ALT_OLY_TEAM_REWARD;
-	public static int ALT_OLY_COMP_RITEM;
-	public static int ALT_OLY_MIN_MATCHES;
-	public static int ALT_OLY_GP_PER_POINT;
-	public static int ALT_OLY_HERO_POINTS;
-	public static int ALT_OLY_RANK1_POINTS;
-	public static int ALT_OLY_RANK2_POINTS;
-	public static int ALT_OLY_RANK3_POINTS;
-	public static int ALT_OLY_RANK4_POINTS;
-	public static int ALT_OLY_RANK5_POINTS;
-	public static int ALT_OLY_MAX_POINTS;
-	public static int ALT_OLY_DIVIDER_CLASSED;
-	public static int ALT_OLY_DIVIDER_NON_CLASSED;
-	public static int ALT_OLY_MAX_WEEKLY_MATCHES;
-	public static int ALT_OLY_MAX_WEEKLY_MATCHES_NON_CLASSED;
-	public static int ALT_OLY_MAX_WEEKLY_MATCHES_CLASSED;
-	public static int ALT_OLY_MAX_WEEKLY_MATCHES_TEAM;
-	public static boolean ALT_OLY_LOG_FIGHTS;
-	public static boolean ALT_OLY_SHOW_MONTHLY_WINNERS;
-	public static boolean ALT_OLY_ANNOUNCE_GAMES;
-	public static List<Integer> LIST_OLY_RESTRICTED_ITEMS;
-	public static int ALT_OLY_ENCHANT_LIMIT;
-	public static int ALT_OLY_WAIT_TIME;
-	public static int ALT_MANOR_REFRESH_TIME;
-	public static int ALT_MANOR_REFRESH_MIN;
-	public static int ALT_MANOR_APPROVE_TIME;
-	public static int ALT_MANOR_APPROVE_MIN;
-	public static int ALT_MANOR_MAINTENANCE_MIN;
-	public static boolean ALT_MANOR_SAVE_ALL_ACTIONS;
-	public static int ALT_MANOR_SAVE_PERIOD_RATE;
-	public static long ALT_LOTTERY_PRIZE;
-	public static long ALT_LOTTERY_TICKET_PRICE;
-	public static float ALT_LOTTERY_5_NUMBER_RATE;
-	public static float ALT_LOTTERY_4_NUMBER_RATE;
-	public static float ALT_LOTTERY_3_NUMBER_RATE;
-	public static long ALT_LOTTERY_2_AND_1_NUMBER_PRIZE;
-	public static boolean ALT_ITEM_AUCTION_ENABLED;
-	public static int ALT_ITEM_AUCTION_EXPIRED_AFTER;
-	public static long ALT_ITEM_AUCTION_TIME_EXTENDS_ON_BID;
-	public static int FS_TIME_ATTACK;
-	public static int FS_TIME_COOLDOWN;
-	public static int FS_TIME_ENTRY;
-	public static int FS_TIME_WARMUP;
-	public static int FS_PARTY_MEMBER_COUNT;
-	public static int RIFT_MIN_PARTY_SIZE;
-	public static int RIFT_SPAWN_DELAY;
-	public static int RIFT_MAX_JUMPS;
-	public static int RIFT_AUTO_JUMPS_TIME_MIN;
-	public static int RIFT_AUTO_JUMPS_TIME_MAX;
-	public static float RIFT_BOSS_ROOM_TIME_MUTIPLY;
-	public static int RIFT_ENTER_COST_RECRUIT;
-	public static int RIFT_ENTER_COST_SOLDIER;
-	public static int RIFT_ENTER_COST_OFFICER;
-	public static int RIFT_ENTER_COST_CAPTAIN;
-	public static int RIFT_ENTER_COST_COMMANDER;
-	public static int RIFT_ENTER_COST_HERO;
-	public static IllegalActionPunishmentType DEFAULT_PUNISH;
-	public static int DEFAULT_PUNISH_PARAM;
-	public static boolean ONLY_GM_ITEMS_FREE;
-	public static boolean JAIL_IS_PVP;
-	public static boolean JAIL_DISABLE_CHAT;
-	public static boolean JAIL_DISABLE_TRANSACTION;
-	public static boolean CUSTOM_SPAWNLIST_TABLE;
-	public static boolean SAVE_GMSPAWN_ON_CUSTOM;
-	public static boolean CUSTOM_NPC_DATA;
-	public static boolean CUSTOM_TELEPORT_TABLE;
-	public static boolean CUSTOM_NPCBUFFER_TABLES;
-	public static boolean CUSTOM_SKILLS_LOAD;
-	public static boolean CUSTOM_ITEMS_LOAD;
-	public static boolean CUSTOM_MULTISELL_LOAD;
-	public static boolean CUSTOM_BUYLIST_LOAD;
-	public static int ALT_BIRTHDAY_GIFT;
-	public static String ALT_BIRTHDAY_MAIL_SUBJECT;
-	public static String ALT_BIRTHDAY_MAIL_TEXT;
-	public static boolean ENABLE_BLOCK_CHECKER_EVENT;
-	public static int MIN_BLOCK_CHECKER_TEAM_MEMBERS;
-	public static boolean HBCE_FAIR_PLAY;
-	public static boolean HELLBOUND_WITHOUT_QUEST;
-	public static int PLAYER_MOVEMENT_BLOCK_TIME;
-	public static int NORMAL_ENCHANT_COST_MULTIPLIER;
-	public static int SAFE_ENCHANT_COST_MULTIPLIER;
-	public static boolean BOTREPORT_ENABLE;
-	public static String[] BOTREPORT_RESETPOINT_HOUR;
-	public static long BOTREPORT_REPORT_DELAY;
-	public static boolean BOTREPORT_ALLOW_REPORTS_FROM_SAME_CLAN_MEMBERS;
-	
-	// --------------------------------------------------
-	// FloodProtector Settings
-	// --------------------------------------------------
-	public static FloodProtectorConfig FLOOD_PROTECTOR_USE_ITEM;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_ROLL_DICE;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_FIREWORK;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_ITEM_PET_SUMMON;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_HERO_VOICE;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_GLOBAL_CHAT;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_SUBCLASS;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_DROP_ITEM;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_SERVER_BYPASS;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_MULTISELL;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_TRANSACTION;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_MANUFACTURE;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_MANOR;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_SENDMAIL;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_CHARACTER_SELECT;
-	public static FloodProtectorConfig FLOOD_PROTECTOR_ITEM_AUCTION;
-	// --------------------------------------------------
-	// L2JMods Settings
-	// --------------------------------------------------
-	public static boolean L2JMOD_CHAMPION_ENABLE;
-	public static boolean L2JMOD_CHAMPION_PASSIVE;
-	public static int L2JMOD_CHAMPION_FREQUENCY;
-	public static String L2JMOD_CHAMP_TITLE;
-	public static int L2JMOD_CHAMP_MIN_LVL;
-	public static int L2JMOD_CHAMP_MAX_LVL;
-	public static int L2JMOD_CHAMPION_HP;
-	public static float L2JMOD_CHAMPION_REWARDS_EXP_SP;
-	public static float L2JMOD_CHAMPION_REWARDS_CHANCE;
-	public static float L2JMOD_CHAMPION_REWARDS_AMOUNT;
-	public static float L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE;
-	public static float L2JMOD_CHAMPION_ADENAS_REWARDS_AMOUNT;
-	public static float L2JMOD_CHAMPION_HP_REGEN;
-	public static float L2JMOD_CHAMPION_ATK;
-	public static float L2JMOD_CHAMPION_SPD_ATK;
-	public static int L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE;
-	public static int L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE;
-	public static int L2JMOD_CHAMPION_REWARD_ID;
-	public static int L2JMOD_CHAMPION_REWARD_QTY;
-	public static boolean L2JMOD_CHAMPION_ENABLE_VITALITY;
-	public static boolean L2JMOD_CHAMPION_ENABLE_IN_INSTANCES;
-	public static boolean TVT_EVENT_ENABLED;
-	public static boolean TVT_EVENT_IN_INSTANCE;
-	public static String TVT_EVENT_INSTANCE_FILE;
-	public static String[] TVT_EVENT_INTERVAL;
-	public static int TVT_EVENT_PARTICIPATION_TIME;
-	public static int TVT_EVENT_RUNNING_TIME;
-	public static int TVT_EVENT_PARTICIPATION_NPC_ID;
-	public static int[] TVT_EVENT_PARTICIPATION_NPC_COORDINATES = new int[4];
-	public static int[] TVT_EVENT_PARTICIPATION_FEE = new int[2];
-	public static int TVT_EVENT_MIN_PLAYERS_IN_TEAMS;
-	public static int TVT_EVENT_MAX_PLAYERS_IN_TEAMS;
-	public static int TVT_EVENT_RESPAWN_TELEPORT_DELAY;
-	public static int TVT_EVENT_START_LEAVE_TELEPORT_DELAY;
-	public static String TVT_EVENT_TEAM_1_NAME;
-	public static int[] TVT_EVENT_TEAM_1_COORDINATES = new int[3];
-	public static String TVT_EVENT_TEAM_2_NAME;
-	public static int[] TVT_EVENT_TEAM_2_COORDINATES = new int[3];
-	public static List<int[]> TVT_EVENT_REWARDS;
-	public static boolean TVT_EVENT_TARGET_TEAM_MEMBERS_ALLOWED;
-	public static boolean TVT_EVENT_SCROLL_ALLOWED;
-	public static boolean TVT_EVENT_POTIONS_ALLOWED;
-	public static boolean TVT_EVENT_SUMMON_BY_ITEM_ALLOWED;
-	public static List<Integer> TVT_DOORS_IDS_TO_OPEN;
-	public static List<Integer> TVT_DOORS_IDS_TO_CLOSE;
-	public static boolean TVT_REWARD_TEAM_TIE;
-	public static byte TVT_EVENT_MIN_LVL;
-	public static byte TVT_EVENT_MAX_LVL;
-	public static int TVT_EVENT_EFFECTS_REMOVAL;
-	public static Map<Integer, Integer> TVT_EVENT_FIGHTER_BUFFS;
-	public static Map<Integer, Integer> TVT_EVENT_MAGE_BUFFS;
-	public static int TVT_EVENT_MAX_PARTICIPANTS_PER_IP;
-	public static boolean TVT_ALLOW_VOICED_COMMAND;
-	public static boolean L2JMOD_ALLOW_WEDDING;
-	public static int L2JMOD_WEDDING_PRICE;
-	public static boolean L2JMOD_WEDDING_PUNISH_INFIDELITY;
-	public static boolean L2JMOD_WEDDING_TELEPORT;
-	public static int L2JMOD_WEDDING_TELEPORT_PRICE;
-	public static int L2JMOD_WEDDING_TELEPORT_DURATION;
-	public static boolean L2JMOD_WEDDING_SAMESEX;
-	public static boolean L2JMOD_WEDDING_FORMALWEAR;
-	public static int L2JMOD_WEDDING_DIVORCE_COSTS;
-	public static boolean L2JMOD_HELLBOUND_STATUS;
-	public static boolean BANKING_SYSTEM_ENABLED;
-	public static int BANKING_SYSTEM_GOLDBARS;
-	public static int BANKING_SYSTEM_ADENA;
-	public static boolean L2JMOD_ENABLE_WAREHOUSESORTING_CLAN;
-	public static boolean L2JMOD_ENABLE_WAREHOUSESORTING_PRIVATE;
-	public static boolean OFFLINE_TRADE_ENABLE;
-	public static boolean OFFLINE_CRAFT_ENABLE;
-	public static boolean OFFLINE_MODE_IN_PEACE_ZONE;
-	public static boolean OFFLINE_MODE_NO_DAMAGE;
-	public static boolean RESTORE_OFFLINERS;
-	public static int OFFLINE_MAX_DAYS;
-	public static boolean OFFLINE_DISCONNECT_FINISHED;
-	public static boolean OFFLINE_SET_NAME_COLOR;
-	public static int OFFLINE_NAME_COLOR;
-	public static boolean OFFLINE_FAME;
-	public static boolean L2JMOD_ENABLE_MANA_POTIONS_SUPPORT;
-	public static boolean L2JMOD_DISPLAY_SERVER_TIME;
-	public static boolean WELCOME_MESSAGE_ENABLED;
-	public static String WELCOME_MESSAGE_TEXT;
-	public static int WELCOME_MESSAGE_TIME;
-	public static boolean L2JMOD_ANTIFEED_ENABLE;
-	public static boolean L2JMOD_ANTIFEED_DUALBOX;
-	public static boolean L2JMOD_ANTIFEED_DISCONNECTED_AS_DUALBOX;
-	public static int L2JMOD_ANTIFEED_INTERVAL;
-	public static boolean ANNOUNCE_PK_PVP;
-	public static boolean ANNOUNCE_PK_PVP_NORMAL_MESSAGE;
-	public static String ANNOUNCE_PK_MSG;
-	public static String ANNOUNCE_PVP_MSG;
-	public static boolean L2JMOD_CHAT_ADMIN;
-	public static boolean L2JMOD_MULTILANG_ENABLE;
-	public static List<String> L2JMOD_MULTILANG_ALLOWED = new ArrayList<>();
-	public static String L2JMOD_MULTILANG_DEFAULT;
-	public static boolean L2JMOD_MULTILANG_VOICED_ALLOW;
-	public static boolean L2JMOD_MULTILANG_SM_ENABLE;
-	public static List<String> L2JMOD_MULTILANG_SM_ALLOWED = new ArrayList<>();
-	public static boolean L2JMOD_MULTILANG_NS_ENABLE;
-	public static List<String> L2JMOD_MULTILANG_NS_ALLOWED = new ArrayList<>();
-	public static boolean L2WALKER_PROTECTION;
-	public static boolean L2JMOD_DEBUG_VOICE_COMMAND;
-	public static int L2JMOD_DUALBOX_CHECK_MAX_PLAYERS_PER_IP;
-	public static int L2JMOD_DUALBOX_CHECK_MAX_OLYMPIAD_PARTICIPANTS_PER_IP;
-	public static int L2JMOD_DUALBOX_CHECK_MAX_L2EVENT_PARTICIPANTS_PER_IP;
-	public static Map<Integer, Integer> L2JMOD_DUALBOX_CHECK_WHITELIST;
-	public static boolean L2JMOD_ALLOW_CHANGE_PASSWORD;
-	// --------------------------------------------------
-	// NPC Settings
-	// --------------------------------------------------
-	public static boolean ANNOUNCE_MAMMON_SPAWN;
-	public static boolean ALT_MOB_AGRO_IN_PEACEZONE;
-	public static boolean ALT_ATTACKABLE_NPCS;
-	public static boolean ALT_GAME_VIEWNPC;
-	public static int MAX_DRIFT_RANGE;
-	public static boolean DEEPBLUE_DROP_RULES;
-	public static boolean DEEPBLUE_DROP_RULES_RAID;
-	public static boolean SHOW_NPC_LVL;
-	public static boolean SHOW_CREST_WITHOUT_QUEST;
-	public static boolean ENABLE_RANDOM_ENCHANT_EFFECT;
-	public static int MIN_NPC_LVL_DMG_PENALTY;
-	public static Map<Integer, Float> NPC_DMG_PENALTY;
-	public static Map<Integer, Float> NPC_CRIT_DMG_PENALTY;
-	public static Map<Integer, Float> NPC_SKILL_DMG_PENALTY;
-	public static int MIN_NPC_LVL_MAGIC_PENALTY;
-	public static Map<Integer, Float> NPC_SKILL_CHANCE_PENALTY;
-	public static int DECAY_TIME_TASK;
-	public static int DEFAULT_CORPSE_TIME;
-	public static int SPOILED_CORPSE_EXTEND_TIME;
-	public static int CORPSE_CONSUME_SKILL_ALLOWED_TIME_BEFORE_DECAY;
-	public static boolean GUARD_ATTACK_AGGRO_MOB;
-	public static boolean ALLOW_WYVERN_UPGRADER;
-	public static List<Integer> LIST_PET_RENT_NPC;
-	public static double RAID_HP_REGEN_MULTIPLIER;
-	public static double RAID_MP_REGEN_MULTIPLIER;
-	public static double RAID_PDEFENCE_MULTIPLIER;
-	public static double RAID_MDEFENCE_MULTIPLIER;
-	public static double RAID_PATTACK_MULTIPLIER;
-	public static double RAID_MATTACK_MULTIPLIER;
-	public static double RAID_MINION_RESPAWN_TIMER;
-	public static Map<Integer, Integer> MINIONS_RESPAWN_TIME;
-	public static float RAID_MIN_RESPAWN_MULTIPLIER;
-	public static float RAID_MAX_RESPAWN_MULTIPLIER;
-	public static boolean RAID_DISABLE_CURSE;
-	public static int RAID_CHAOS_TIME;
-	public static int GRAND_CHAOS_TIME;
-	public static int MINION_CHAOS_TIME;
-	public static int INVENTORY_MAXIMUM_PET;
-	public static double PET_HP_REGEN_MULTIPLIER;
-	public static double PET_MP_REGEN_MULTIPLIER;
-	public static int DROP_ADENA_MIN_LEVEL_DIFFERENCE;
-	public static int DROP_ADENA_MAX_LEVEL_DIFFERENCE;
-	public static double DROP_ADENA_MIN_LEVEL_GAP_CHANCE;
-	public static int DROP_ITEM_MIN_LEVEL_DIFFERENCE;
-	public static int DROP_ITEM_MAX_LEVEL_DIFFERENCE;
-	public static double DROP_ITEM_MIN_LEVEL_GAP_CHANCE;
-	
-	// --------------------------------------------------
-	// PvP Settings
-	// --------------------------------------------------
-	public static boolean KARMA_DROP_GM;
-	public static boolean KARMA_AWARD_PK_KILL;
-	public static int KARMA_PK_LIMIT;
-	public static String KARMA_NONDROPPABLE_PET_ITEMS;
-	public static String KARMA_NONDROPPABLE_ITEMS;
-	public static int[] KARMA_LIST_NONDROPPABLE_PET_ITEMS;
-	public static int[] KARMA_LIST_NONDROPPABLE_ITEMS;
-	
-	// --------------------------------------------------
-	// Rate Settings
-	// --------------------------------------------------
-	public static float RATE_XP;
-	public static float RATE_SP;
-	public static float RATE_PARTY_XP;
-	public static float RATE_PARTY_SP;
-	public static float RATE_HB_TRUST_INCREASE;
-	public static float RATE_HB_TRUST_DECREASE;
-	public static float RATE_EXTRACTABLE;
-	public static int RATE_DROP_MANOR;
-	public static float RATE_QUEST_DROP;
-	public static float RATE_QUEST_REWARD;
-	public static float RATE_QUEST_REWARD_XP;
-	public static float RATE_QUEST_REWARD_SP;
-	public static float RATE_QUEST_REWARD_ADENA;
-	public static boolean RATE_QUEST_REWARD_USE_MULTIPLIERS;
-	public static float RATE_QUEST_REWARD_POTION;
-	public static float RATE_QUEST_REWARD_SCROLL;
-	public static float RATE_QUEST_REWARD_RECIPE;
-	public static float RATE_QUEST_REWARD_MATERIAL;
-	public static float RATE_DEATH_DROP_AMOUNT_MULTIPLIER;
-	public static float RATE_CORPSE_DROP_AMOUNT_MULTIPLIER;
-	public static float RATE_HERB_DROP_AMOUNT_MULTIPLIER;
-	public static float RATE_RAID_DROP_AMOUNT_MULTIPLIER;
-	public static float RATE_DEATH_DROP_CHANCE_MULTIPLIER;
-	public static float RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
-	public static float RATE_HERB_DROP_CHANCE_MULTIPLIER;
-	public static float RATE_RAID_DROP_CHANCE_MULTIPLIER;
-	public static Map<Integer, Float> RATE_DROP_AMOUNT_MULTIPLIER;
-	public static Map<Integer, Float> RATE_DROP_CHANCE_MULTIPLIER;
-	public static float RATE_KARMA_LOST;
-	public static float RATE_KARMA_EXP_LOST;
-	public static float RATE_SIEGE_GUARDS_PRICE;
-	public static float RATE_DROP_COMMON_HERBS;
-	public static float RATE_DROP_HP_HERBS;
-	public static float RATE_DROP_MP_HERBS;
-	public static float RATE_DROP_SPECIAL_HERBS;
-	public static int PLAYER_DROP_LIMIT;
-	public static int PLAYER_RATE_DROP;
-	public static int PLAYER_RATE_DROP_ITEM;
-	public static int PLAYER_RATE_DROP_EQUIP;
-	public static int PLAYER_RATE_DROP_EQUIP_WEAPON;
-	public static float PET_XP_RATE;
-	public static int PET_FOOD_RATE;
-	public static float SINEATER_XP_RATE;
-	public static int KARMA_DROP_LIMIT;
-	public static int KARMA_RATE_DROP;
-	public static int KARMA_RATE_DROP_ITEM;
-	public static int KARMA_RATE_DROP_EQUIP;
-	public static int KARMA_RATE_DROP_EQUIP_WEAPON;
-	
-	// --------------------------------------------------
-	// Seven Signs Settings
-	// --------------------------------------------------
-	public static boolean ALT_GAME_CASTLE_DAWN;
-	public static boolean ALT_GAME_CASTLE_DUSK;
-	public static boolean ALT_GAME_REQUIRE_CLAN_CASTLE;
-	public static int ALT_FESTIVAL_MIN_PLAYER;
-	public static int ALT_MAXIMUM_PLAYER_CONTRIB;
-	public static long ALT_FESTIVAL_MANAGER_START;
-	public static long ALT_FESTIVAL_LENGTH;
-	public static long ALT_FESTIVAL_CYCLE_LENGTH;
-	public static long ALT_FESTIVAL_FIRST_SPAWN;
-	public static long ALT_FESTIVAL_FIRST_SWARM;
-	public static long ALT_FESTIVAL_SECOND_SPAWN;
-	public static long ALT_FESTIVAL_SECOND_SWARM;
-	public static long ALT_FESTIVAL_CHEST_SPAWN;
-	public static double ALT_SIEGE_DAWN_GATES_PDEF_MULT;
-	public static double ALT_SIEGE_DUSK_GATES_PDEF_MULT;
-	public static double ALT_SIEGE_DAWN_GATES_MDEF_MULT;
-	public static double ALT_SIEGE_DUSK_GATES_MDEF_MULT;
-	public static boolean ALT_STRICT_SEVENSIGNS;
-	public static boolean ALT_SEVENSIGNS_LAZY_UPDATE;
-	public static int SSQ_DAWN_TICKET_QUANTITY;
-	public static int SSQ_DAWN_TICKET_PRICE;
-	public static int SSQ_DAWN_TICKET_BUNDLE;
-	public static int SSQ_MANORS_AGREEMENT_ID;
-	public static int SSQ_JOIN_DAWN_ADENA_FEE;
-	
-	// --------------------------------------------------
-	// Server Settings
-	// --------------------------------------------------
-	public static boolean ENABLE_UPNP;
-	public static int PORT_GAME;
-	public static int PORT_LOGIN;
-	public static String LOGIN_BIND_ADDRESS;
-	public static int LOGIN_TRY_BEFORE_BAN;
-	public static int LOGIN_BLOCK_AFTER_BAN;
-	public static String GAMESERVER_HOSTNAME;
-	public static String DATABASE_ENGINE;
-	public static String DATABASE_DRIVER;
-	public static String DATABASE_URL;
-	public static String DATABASE_LOGIN;
-	public static String DATABASE_PASSWORD;
-	public static String DATABASE_CONNECTION_POOL;
-	public static int DATABASE_MAX_CONNECTIONS;
-	public static int DATABASE_MAX_IDLE_TIME;
-	public static int MAXIMUM_ONLINE_USERS;
-	public static Pattern PLAYER_NAME_TEMPLATE;
-	public static Pattern PET_NAME_TEMPLATE;
-	public static Pattern CLAN_NAME_TEMPLATE;
-	public static int MAX_CHARACTERS_NUMBER_PER_ACCOUNT;
-	public static File DATAPACK_ROOT;
-	public static File SCRIPT_ROOT;
-	public static boolean ACCEPT_ALTERNATE_ID;
-	public static int REQUEST_ID;
-	public static boolean RESERVE_HOST_ON_LOGIN = false;
-	public static List<Integer> PROTOCOL_LIST;
-	public static boolean LOGIN_SERVER_SCHEDULE_RESTART;
-	public static long LOGIN_SERVER_SCHEDULE_RESTART_TIME;
-	
-	// --------------------------------------------------
-	// MMO Settings
-	// --------------------------------------------------
-	public static int MMO_SELECTOR_SLEEP_TIME;
-	public static int MMO_MAX_SEND_PER_PASS;
-	public static int MMO_MAX_READ_PER_PASS;
-	public static int MMO_HELPER_BUFFER_COUNT;
-	public static boolean MMO_TCP_NODELAY;
-	
-	// --------------------------------------------------
-	// Vitality Settings
-	// --------------------------------------------------
-	public static boolean ENABLE_VITALITY;
-	public static boolean RECOVER_VITALITY_ON_RECONNECT;
-	public static boolean ENABLE_DROP_VITALITY_HERBS;
-	public static float RATE_VITALITY_LEVEL_1;
-	public static float RATE_VITALITY_LEVEL_2;
-	public static float RATE_VITALITY_LEVEL_3;
-	public static float RATE_VITALITY_LEVEL_4;
-	public static float RATE_DROP_VITALITY_HERBS;
-	public static float RATE_RECOVERY_VITALITY_PEACE_ZONE;
-	public static float RATE_VITALITY_LOST;
-	public static float RATE_VITALITY_GAIN;
-	public static float RATE_RECOVERY_ON_RECONNECT;
-	public static int STARTING_VITALITY_POINTS;
-	
-	// --------------------------------------------------
-	// No classification assigned to the following yet
-	// --------------------------------------------------
-	public static int MAX_ITEM_IN_PACKET;
-	public static boolean CHECK_KNOWN;
-	public static int GAME_SERVER_LOGIN_PORT;
-	public static String GAME_SERVER_LOGIN_HOST;
-	public static List<String> GAME_SERVER_SUBNETS;
-	public static List<String> GAME_SERVER_HOSTS;
-	public static int PVP_NORMAL_TIME;
-	public static int PVP_PVP_TIME;
-	
-	public static enum IdFactoryType {
-		Compaction,
-		BitSet,
-		Stack
-	}
-	
-	public static IdFactoryType IDFACTORY_TYPE;
-	public static boolean BAD_ID_CHECKING;
-	
-	public static double ENCHANT_CHANCE_ELEMENT_STONE;
-	public static double ENCHANT_CHANCE_ELEMENT_CRYSTAL;
-	public static double ENCHANT_CHANCE_ELEMENT_JEWEL;
-	public static double ENCHANT_CHANCE_ELEMENT_ENERGY;
-	public static int[] ENCHANT_BLACKLIST;
-	public static int AUGMENTATION_NG_SKILL_CHANCE;
-	public static int AUGMENTATION_NG_GLOW_CHANCE;
-	public static int AUGMENTATION_MID_SKILL_CHANCE;
-	public static int AUGMENTATION_MID_GLOW_CHANCE;
-	public static int AUGMENTATION_HIGH_SKILL_CHANCE;
-	public static int AUGMENTATION_HIGH_GLOW_CHANCE;
-	public static int AUGMENTATION_TOP_SKILL_CHANCE;
-	public static int AUGMENTATION_TOP_GLOW_CHANCE;
-	public static int AUGMENTATION_BASESTAT_CHANCE;
-	public static int AUGMENTATION_ACC_SKILL_CHANCE;
-	public static boolean RETAIL_LIKE_AUGMENTATION;
-	public static int[] RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
-	public static int[] RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
-	public static int[] RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
-	public static int[] RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
-	public static boolean RETAIL_LIKE_AUGMENTATION_ACCESSORY;
-	public static int[] AUGMENTATION_BLACKLIST;
-	public static boolean ALT_ALLOW_AUGMENT_PVP_ITEMS;
-	public static double HP_REGEN_MULTIPLIER;
-	public static double MP_REGEN_MULTIPLIER;
-	public static double CP_REGEN_MULTIPLIER;
-	public static boolean TELNET_ENABLED;
-	public static int TELNET_PORT;
-	public static String TELNET_PASSWORD;
-	public static String TELNET_HOSTS;
-	public static boolean SHOW_LICENCE;
-	public static boolean ACCEPT_NEW_GAMESERVER;
-	public static int SERVER_ID;
-	public static byte[] HEX_ID;
-	public static boolean AUTO_CREATE_ACCOUNTS;
-	public static boolean FLOOD_PROTECTION;
-	public static int FAST_CONNECTION_LIMIT;
-	public static int NORMAL_CONNECTION_TIME;
-	public static int FAST_CONNECTION_TIME;
-	public static int MAX_CONNECTION_PER_IP;
-	
-	// GrandBoss Settings
-	
-	// Antharas
-	public static int ANTHARAS_WAIT_TIME;
-	public static int ANTHARAS_SPAWN_INTERVAL;
-	public static int ANTHARAS_SPAWN_RANDOM;
-	
-	// Valakas
-	public static int VALAKAS_WAIT_TIME;
-	public static int VALAKAS_SPAWN_INTERVAL;
-	public static int VALAKAS_SPAWN_RANDOM;
-	
-	// Baium
-	public static int BAIUM_SPAWN_INTERVAL;
-	public static int BAIUM_SPAWN_RANDOM;
-	
-	// Core
-	public static int CORE_SPAWN_INTERVAL;
-	public static int CORE_SPAWN_RANDOM;
-	
-	// Offen
-	public static int ORFEN_SPAWN_INTERVAL;
-	public static int ORFEN_SPAWN_RANDOM;
-	
-	// Queen Ant
-	public static int QUEEN_ANT_SPAWN_INTERVAL;
-	public static int QUEEN_ANT_SPAWN_RANDOM;
-	
-	// Beleth
-	public static int BELETH_MIN_PLAYERS;
-	public static int BELETH_SPAWN_INTERVAL;
-	public static int BELETH_SPAWN_RANDOM;
-	
-	// Gracia Seeds Settings
-	public static int SOD_TIAT_KILL_COUNT;
-	public static long SOD_STAGE_2_LENGTH;
-	
-	// chatfilter
-	public static List<String> FILTER_LIST;
-	
-	// Email
-	public static String EMAIL_SERVERINFO_NAME;
-	public static String EMAIL_SERVERINFO_ADDRESS;
-	public static boolean EMAIL_SYS_ENABLED;
-	public static String EMAIL_SYS_HOST;
-	public static int EMAIL_SYS_PORT;
-	public static boolean EMAIL_SYS_SMTP_AUTH;
-	public static String EMAIL_SYS_FACTORY;
-	public static boolean EMAIL_SYS_FACTORY_CALLBACK;
-	public static String EMAIL_SYS_USERNAME;
-	public static String EMAIL_SYS_PASSWORD;
-	public static String EMAIL_SYS_ADDRESS;
-	public static String EMAIL_SYS_SELECTQUERY;
-	public static String EMAIL_SYS_DBFIELD;
-	
-	// Conquerable Halls Settings
-	public static int CHS_CLAN_MINLEVEL;
-	public static int CHS_MAX_ATTACKERS;
-	public static int CHS_MAX_FLAGS_PER_CLAN;
-	public static boolean CHS_ENABLE_FAME;
-	public static int CHS_FAME_AMOUNT;
-	public static int CHS_FAME_FREQUENCY;
-	
-	// GeoData Settings
-	public static int PATHFINDING;
-	public static File PATHNODE_DIR;
-	public static String PATHFIND_BUFFERS;
-	public static float LOW_WEIGHT;
-	public static float MEDIUM_WEIGHT;
-	public static float HIGH_WEIGHT;
-	public static boolean ADVANCED_DIAGONAL_STRATEGY;
-	public static float DIAGONAL_WEIGHT;
-	public static int MAX_POSTFILTER_PASSES;
-	public static boolean DEBUG_PATH;
-	public static boolean FORCE_GEODATA;
-	public static int COORD_SYNCHRONIZE;
-	public static Path GEODATA_PATH;
-	public static boolean TRY_LOAD_UNSPECIFIED_REGIONS;
-	public static Map<String, Boolean> GEODATA_REGIONS;
-	
-	public static void load() {
-		FLOOD_PROTECTOR_USE_ITEM = new FloodProtectorConfig("UseItemFloodProtector");
-		FLOOD_PROTECTOR_ROLL_DICE = new FloodProtectorConfig("RollDiceFloodProtector");
-		FLOOD_PROTECTOR_FIREWORK = new FloodProtectorConfig("FireworkFloodProtector");
-		FLOOD_PROTECTOR_ITEM_PET_SUMMON = new FloodProtectorConfig("ItemPetSummonFloodProtector");
-		FLOOD_PROTECTOR_HERO_VOICE = new FloodProtectorConfig("HeroVoiceFloodProtector");
-		FLOOD_PROTECTOR_GLOBAL_CHAT = new FloodProtectorConfig("GlobalChatFloodProtector");
-		FLOOD_PROTECTOR_SUBCLASS = new FloodProtectorConfig("SubclassFloodProtector");
-		FLOOD_PROTECTOR_DROP_ITEM = new FloodProtectorConfig("DropItemFloodProtector");
-		FLOOD_PROTECTOR_SERVER_BYPASS = new FloodProtectorConfig("ServerBypassFloodProtector");
-		FLOOD_PROTECTOR_MULTISELL = new FloodProtectorConfig("MultiSellFloodProtector");
-		FLOOD_PROTECTOR_TRANSACTION = new FloodProtectorConfig("TransactionFloodProtector");
-		FLOOD_PROTECTOR_MANUFACTURE = new FloodProtectorConfig("ManufactureFloodProtector");
-		FLOOD_PROTECTOR_MANOR = new FloodProtectorConfig("ManorFloodProtector");
-		FLOOD_PROTECTOR_SENDMAIL = new FloodProtectorConfig("SendMailFloodProtector");
-		FLOOD_PROTECTOR_CHARACTER_SELECT = new FloodProtectorConfig("CharacterSelectFloodProtector");
-		FLOOD_PROTECTOR_ITEM_AUCTION = new FloodProtectorConfig("ItemAuctionFloodProtector");
-		
-		final PropertiesParser serverSettings = new PropertiesParser(CONFIGURATION_FILE);
-		
-		ENABLE_UPNP = serverSettings.getBoolean("EnableUPnP", true);
-		GAMESERVER_HOSTNAME = serverSettings.getString("GameserverHostname", "*");
-		PORT_GAME = serverSettings.getInt("GameserverPort", 7777);
-		
-		GAME_SERVER_LOGIN_PORT = serverSettings.getInt("LoginPort", 9014);
-		GAME_SERVER_LOGIN_HOST = serverSettings.getString("LoginHost", "127.0.0.1");
-		
-		REQUEST_ID = serverSettings.getInt("RequestServerID", 0);
-		ACCEPT_ALTERNATE_ID = serverSettings.getBoolean("AcceptAlternateID", true);
-		
-		DATABASE_ENGINE = serverSettings.getString("Database", "MySQL");
-		DATABASE_DRIVER = serverSettings.getString("Driver", "com.mysql.cj.jdbc.Driver");
-		DATABASE_URL = serverSettings.getString("URL", "jdbc:mysql://localhost/l2jgs?serverTimezone=UTC");
-		DATABASE_LOGIN = serverSettings.getString("Login", "root");
-		DATABASE_PASSWORD = serverSettings.getString("Password", "toor");
-		DATABASE_CONNECTION_POOL = serverSettings.getString("ConnectionPool", "HikariCP");
-		DATABASE_MAX_CONNECTIONS = serverSettings.getInt("MaximumDbConnections", 10);
-		DATABASE_MAX_IDLE_TIME = serverSettings.getInt("MaximumDbIdleTime", 0);
-		
-		try {
-			DATAPACK_ROOT = new File(serverSettings.getString("DatapackRoot", ".").replaceAll("\\\\", "/")).getCanonicalFile();
-		} catch (Exception ex) {
-			LOG.warn("Error setting datapack root!", ex);
-			DATAPACK_ROOT = new File(".");
-		}
-		
-		try {
-			SCRIPT_ROOT = new File(serverSettings.getString("ScriptRoot", "script").replaceAll("\\\\", "/")).getCanonicalFile();
-		} catch (Exception ex) {
-			LOG.warn("Error setting script root!", ex);
-			SCRIPT_ROOT = new File(".");
-		}
-		
-		PLAYER_NAME_TEMPLATE = Pattern.compile(serverSettings.getString("PlayerNameTemplate", "[a-zA-Z0-9]*"));
-		PET_NAME_TEMPLATE = Pattern.compile(serverSettings.getString("PetNameTemplate", "[a-zA-Z0-9]*"));
-		CLAN_NAME_TEMPLATE = Pattern.compile(serverSettings.getString("ClanNameTemplate", "[a-zA-Z0-9]*"));
-		
-		MAX_CHARACTERS_NUMBER_PER_ACCOUNT = serverSettings.getInt("CharMaxNumber", 7);
-		MAXIMUM_ONLINE_USERS = serverSettings.getInt("MaximumOnlineUsers", 100);
-		
-		String[] protocols = serverSettings.getString("AllowedProtocolRevisions", "267;268;271;273").split(";");
-		PROTOCOL_LIST = new ArrayList<>(protocols.length);
-		for (String protocol : protocols) {
-			try {
-				PROTOCOL_LIST.add(Integer.parseInt(protocol.trim()));
-			} catch (NumberFormatException e) {
-				LOG.warn("Wrong config protocol version: {}, skipped.", protocol);
-			}
-		}
-		
-		// Hosts and Subnets
-		IPConfigData ipcd = new IPConfigData();
-		GAME_SERVER_SUBNETS = ipcd.getSubnets();
-		GAME_SERVER_HOSTS = ipcd.getHosts();
-		
-		// Load Feature L2Properties file (if exists)
-		final PropertiesParser Feature = new PropertiesParser(FEATURE_CONFIG_FILE);
-		
-		CH_TELE_FEE_RATIO = Feature.getLong("ClanHallTeleportFunctionFeeRatio", 604800000);
-		CH_TELE1_FEE = Feature.getInt("ClanHallTeleportFunctionFeeLvl1", 7000);
-		CH_TELE2_FEE = Feature.getInt("ClanHallTeleportFunctionFeeLvl2", 14000);
-		CH_SUPPORT_FEE_RATIO = Feature.getLong("ClanHallSupportFunctionFeeRatio", 86400000);
-		CH_SUPPORT1_FEE = Feature.getInt("ClanHallSupportFeeLvl1", 2500);
-		CH_SUPPORT2_FEE = Feature.getInt("ClanHallSupportFeeLvl2", 5000);
-		CH_SUPPORT3_FEE = Feature.getInt("ClanHallSupportFeeLvl3", 7000);
-		CH_SUPPORT4_FEE = Feature.getInt("ClanHallSupportFeeLvl4", 11000);
-		CH_SUPPORT5_FEE = Feature.getInt("ClanHallSupportFeeLvl5", 21000);
-		CH_SUPPORT6_FEE = Feature.getInt("ClanHallSupportFeeLvl6", 36000);
-		CH_SUPPORT7_FEE = Feature.getInt("ClanHallSupportFeeLvl7", 37000);
-		CH_SUPPORT8_FEE = Feature.getInt("ClanHallSupportFeeLvl8", 52000);
-		CH_MPREG_FEE_RATIO = Feature.getLong("ClanHallMpRegenerationFunctionFeeRatio", 86400000);
-		CH_MPREG1_FEE = Feature.getInt("ClanHallMpRegenerationFeeLvl1", 2000);
-		CH_MPREG2_FEE = Feature.getInt("ClanHallMpRegenerationFeeLvl2", 3750);
-		CH_MPREG3_FEE = Feature.getInt("ClanHallMpRegenerationFeeLvl3", 6500);
-		CH_MPREG4_FEE = Feature.getInt("ClanHallMpRegenerationFeeLvl4", 13750);
-		CH_MPREG5_FEE = Feature.getInt("ClanHallMpRegenerationFeeLvl5", 20000);
-		CH_HPREG_FEE_RATIO = Feature.getLong("ClanHallHpRegenerationFunctionFeeRatio", 86400000);
-		CH_HPREG1_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl1", 700);
-		CH_HPREG2_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl2", 800);
-		CH_HPREG3_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl3", 1000);
-		CH_HPREG4_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl4", 1166);
-		CH_HPREG5_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl5", 1500);
-		CH_HPREG6_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl6", 1750);
-		CH_HPREG7_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl7", 2000);
-		CH_HPREG8_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl8", 2250);
-		CH_HPREG9_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl9", 2500);
-		CH_HPREG10_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl10", 3250);
-		CH_HPREG11_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl11", 3270);
-		CH_HPREG12_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl12", 4250);
-		CH_HPREG13_FEE = Feature.getInt("ClanHallHpRegenerationFeeLvl13", 5166);
-		CH_EXPREG_FEE_RATIO = Feature.getLong("ClanHallExpRegenerationFunctionFeeRatio", 86400000);
-		CH_EXPREG1_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl1", 3000);
-		CH_EXPREG2_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl2", 6000);
-		CH_EXPREG3_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl3", 9000);
-		CH_EXPREG4_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl4", 15000);
-		CH_EXPREG5_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl5", 21000);
-		CH_EXPREG6_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl6", 23330);
-		CH_EXPREG7_FEE = Feature.getInt("ClanHallExpRegenerationFeeLvl7", 30000);
-		CH_ITEM_FEE_RATIO = Feature.getLong("ClanHallItemCreationFunctionFeeRatio", 86400000);
-		CH_ITEM1_FEE = Feature.getInt("ClanHallItemCreationFunctionFeeLvl1", 30000);
-		CH_ITEM2_FEE = Feature.getInt("ClanHallItemCreationFunctionFeeLvl2", 70000);
-		CH_ITEM3_FEE = Feature.getInt("ClanHallItemCreationFunctionFeeLvl3", 140000);
-		CH_CURTAIN_FEE_RATIO = Feature.getLong("ClanHallCurtainFunctionFeeRatio", 604800000);
-		CH_CURTAIN1_FEE = Feature.getInt("ClanHallCurtainFunctionFeeLvl1", 2000);
-		CH_CURTAIN2_FEE = Feature.getInt("ClanHallCurtainFunctionFeeLvl2", 2500);
-		CH_FRONT_FEE_RATIO = Feature.getLong("ClanHallFrontPlatformFunctionFeeRatio", 259200000);
-		CH_FRONT1_FEE = Feature.getInt("ClanHallFrontPlatformFunctionFeeLvl1", 1300);
-		CH_FRONT2_FEE = Feature.getInt("ClanHallFrontPlatformFunctionFeeLvl2", 4000);
-		CH_BUFF_FREE = Feature.getBoolean("AltClanHallMpBuffFree", false);
-		SIEGE_HOUR_LIST = new ArrayList<>();
-		for (String hour : Feature.getString("SiegeHourList", "").split(",")) {
-			if (Util.isDigit(hour)) {
-				SIEGE_HOUR_LIST.add(Integer.parseInt(hour));
-			}
-		}
-		CS_TELE_FEE_RATIO = Feature.getLong("CastleTeleportFunctionFeeRatio", 604800000);
-		CS_TELE1_FEE = Feature.getInt("CastleTeleportFunctionFeeLvl1", 1000);
-		CS_TELE2_FEE = Feature.getInt("CastleTeleportFunctionFeeLvl2", 10000);
-		CS_SUPPORT_FEE_RATIO = Feature.getLong("CastleSupportFunctionFeeRatio", 604800000);
-		CS_SUPPORT1_FEE = Feature.getInt("CastleSupportFeeLvl1", 49000);
-		CS_SUPPORT2_FEE = Feature.getInt("CastleSupportFeeLvl2", 120000);
-		CS_MPREG_FEE_RATIO = Feature.getLong("CastleMpRegenerationFunctionFeeRatio", 604800000);
-		CS_MPREG1_FEE = Feature.getInt("CastleMpRegenerationFeeLvl1", 45000);
-		CS_MPREG2_FEE = Feature.getInt("CastleMpRegenerationFeeLvl2", 65000);
-		CS_HPREG_FEE_RATIO = Feature.getLong("CastleHpRegenerationFunctionFeeRatio", 604800000);
-		CS_HPREG1_FEE = Feature.getInt("CastleHpRegenerationFeeLvl1", 12000);
-		CS_HPREG2_FEE = Feature.getInt("CastleHpRegenerationFeeLvl2", 20000);
-		CS_EXPREG_FEE_RATIO = Feature.getLong("CastleExpRegenerationFunctionFeeRatio", 604800000);
-		CS_EXPREG1_FEE = Feature.getInt("CastleExpRegenerationFeeLvl1", 63000);
-		CS_EXPREG2_FEE = Feature.getInt("CastleExpRegenerationFeeLvl2", 70000);
-		
-		OUTER_DOOR_UPGRADE_PRICE2 = Feature.getInt("OuterDoorUpgradePriceLvl2", 3000000);
-		OUTER_DOOR_UPGRADE_PRICE3 = Feature.getInt("OuterDoorUpgradePriceLvl3", 4000000);
-		OUTER_DOOR_UPGRADE_PRICE5 = Feature.getInt("OuterDoorUpgradePriceLvl5", 5000000);
-		INNER_DOOR_UPGRADE_PRICE2 = Feature.getInt("InnerDoorUpgradePriceLvl2", 750000);
-		INNER_DOOR_UPGRADE_PRICE3 = Feature.getInt("InnerDoorUpgradePriceLvl3", 900000);
-		INNER_DOOR_UPGRADE_PRICE5 = Feature.getInt("InnerDoorUpgradePriceLvl5", 1000000);
-		WALL_UPGRADE_PRICE2 = Feature.getInt("WallUpgradePriceLvl2", 1600000);
-		WALL_UPGRADE_PRICE3 = Feature.getInt("WallUpgradePriceLvl3", 1800000);
-		WALL_UPGRADE_PRICE5 = Feature.getInt("WallUpgradePriceLvl5", 2000000);
-		TRAP_UPGRADE_PRICE1 = Feature.getInt("TrapUpgradePriceLvl1", 3000000);
-		TRAP_UPGRADE_PRICE2 = Feature.getInt("TrapUpgradePriceLvl2", 4000000);
-		TRAP_UPGRADE_PRICE3 = Feature.getInt("TrapUpgradePriceLvl3", 5000000);
-		TRAP_UPGRADE_PRICE4 = Feature.getInt("TrapUpgradePriceLvl4", 6000000);
-		
-		FS_TELE_FEE_RATIO = Feature.getLong("FortressTeleportFunctionFeeRatio", 604800000);
-		FS_TELE1_FEE = Feature.getInt("FortressTeleportFunctionFeeLvl1", 1000);
-		FS_TELE2_FEE = Feature.getInt("FortressTeleportFunctionFeeLvl2", 10000);
-		FS_SUPPORT_FEE_RATIO = Feature.getLong("FortressSupportFunctionFeeRatio", 86400000);
-		FS_SUPPORT1_FEE = Feature.getInt("FortressSupportFeeLvl1", 7000);
-		FS_SUPPORT2_FEE = Feature.getInt("FortressSupportFeeLvl2", 17000);
-		FS_MPREG_FEE_RATIO = Feature.getLong("FortressMpRegenerationFunctionFeeRatio", 86400000);
-		FS_MPREG1_FEE = Feature.getInt("FortressMpRegenerationFeeLvl1", 6500);
-		FS_MPREG2_FEE = Feature.getInt("FortressMpRegenerationFeeLvl2", 9300);
-		FS_HPREG_FEE_RATIO = Feature.getLong("FortressHpRegenerationFunctionFeeRatio", 86400000);
-		FS_HPREG1_FEE = Feature.getInt("FortressHpRegenerationFeeLvl1", 2000);
-		FS_HPREG2_FEE = Feature.getInt("FortressHpRegenerationFeeLvl2", 3500);
-		FS_EXPREG_FEE_RATIO = Feature.getLong("FortressExpRegenerationFunctionFeeRatio", 86400000);
-		FS_EXPREG1_FEE = Feature.getInt("FortressExpRegenerationFeeLvl1", 9000);
-		FS_EXPREG2_FEE = Feature.getInt("FortressExpRegenerationFeeLvl2", 10000);
-		FS_UPDATE_FRQ = Feature.getInt("FortressPeriodicUpdateFrequency", 360);
-		FS_BLOOD_OATH_COUNT = Feature.getInt("FortressBloodOathCount", 1);
-		FS_MAX_SUPPLY_LEVEL = Feature.getInt("FortressMaxSupplyLevel", 6);
-		FS_FEE_FOR_CASTLE = Feature.getInt("FortressFeeForCastle", 25000);
-		FS_MAX_OWN_TIME = Feature.getInt("FortressMaximumOwnTime", 168);
-		
-		ALT_GAME_CASTLE_DAWN = Feature.getBoolean("AltCastleForDawn", true);
-		ALT_GAME_CASTLE_DUSK = Feature.getBoolean("AltCastleForDusk", true);
-		ALT_GAME_REQUIRE_CLAN_CASTLE = Feature.getBoolean("AltRequireClanCastle", false);
-		ALT_FESTIVAL_MIN_PLAYER = Feature.getInt("AltFestivalMinPlayer", 5);
-		ALT_MAXIMUM_PLAYER_CONTRIB = Feature.getInt("AltMaxPlayerContrib", 1000000);
-		ALT_FESTIVAL_MANAGER_START = Feature.getLong("AltFestivalManagerStart", 120000);
-		ALT_FESTIVAL_LENGTH = Feature.getLong("AltFestivalLength", 1080000);
-		ALT_FESTIVAL_CYCLE_LENGTH = Feature.getLong("AltFestivalCycleLength", 2280000);
-		ALT_FESTIVAL_FIRST_SPAWN = Feature.getLong("AltFestivalFirstSpawn", 120000);
-		ALT_FESTIVAL_FIRST_SWARM = Feature.getLong("AltFestivalFirstSwarm", 300000);
-		ALT_FESTIVAL_SECOND_SPAWN = Feature.getLong("AltFestivalSecondSpawn", 540000);
-		ALT_FESTIVAL_SECOND_SWARM = Feature.getLong("AltFestivalSecondSwarm", 720000);
-		ALT_FESTIVAL_CHEST_SPAWN = Feature.getLong("AltFestivalChestSpawn", 900000);
-		ALT_SIEGE_DAWN_GATES_PDEF_MULT = Feature.getDouble("AltDawnGatesPdefMult", 1.1);
-		ALT_SIEGE_DUSK_GATES_PDEF_MULT = Feature.getDouble("AltDuskGatesPdefMult", 0.8);
-		ALT_SIEGE_DAWN_GATES_MDEF_MULT = Feature.getDouble("AltDawnGatesMdefMult", 1.1);
-		ALT_SIEGE_DUSK_GATES_MDEF_MULT = Feature.getDouble("AltDuskGatesMdefMult", 0.8);
-		ALT_STRICT_SEVENSIGNS = Feature.getBoolean("StrictSevenSigns", true);
-		ALT_SEVENSIGNS_LAZY_UPDATE = Feature.getBoolean("AltSevenSignsLazyUpdate", true);
-		
-		SSQ_DAWN_TICKET_QUANTITY = Feature.getInt("SevenSignsDawnTicketQuantity", 300);
-		SSQ_DAWN_TICKET_PRICE = Feature.getInt("SevenSignsDawnTicketPrice", 1000);
-		SSQ_DAWN_TICKET_BUNDLE = Feature.getInt("SevenSignsDawnTicketBundle", 10);
-		SSQ_MANORS_AGREEMENT_ID = Feature.getInt("SevenSignsManorsAgreementId", 6388);
-		SSQ_JOIN_DAWN_ADENA_FEE = Feature.getInt("SevenSignsJoinDawnFee", 50000);
-		
-		TAKE_FORT_POINTS = Feature.getInt("TakeFortPoints", 200);
-		LOOSE_FORT_POINTS = Feature.getInt("LooseFortPoints", 0);
-		TAKE_CASTLE_POINTS = Feature.getInt("TakeCastlePoints", 1500);
-		LOOSE_CASTLE_POINTS = Feature.getInt("LooseCastlePoints", 3000);
-		CASTLE_DEFENDED_POINTS = Feature.getInt("CastleDefendedPoints", 750);
-		FESTIVAL_WIN_POINTS = Feature.getInt("FestivalOfDarknessWin", 200);
-		HERO_POINTS = Feature.getInt("HeroPoints", 1000);
-		ROYAL_GUARD_COST = Feature.getInt("CreateRoyalGuardCost", 5000);
-		KNIGHT_UNIT_COST = Feature.getInt("CreateKnightUnitCost", 10000);
-		KNIGHT_REINFORCE_COST = Feature.getInt("ReinforceKnightUnitCost", 5000);
-		BALLISTA_POINTS = Feature.getInt("KillBallistaPoints", 30);
-		BLOODALLIANCE_POINTS = Feature.getInt("BloodAlliancePoints", 500);
-		BLOODOATH_POINTS = Feature.getInt("BloodOathPoints", 200);
-		KNIGHTSEPAULETTE_POINTS = Feature.getInt("KnightsEpaulettePoints", 20);
-		REPUTATION_SCORE_PER_KILL = Feature.getInt("ReputationScorePerKill", 1);
-		JOIN_ACADEMY_MIN_REP_SCORE = Feature.getInt("CompleteAcademyMinPoints", 190);
-		JOIN_ACADEMY_MAX_REP_SCORE = Feature.getInt("CompleteAcademyMaxPoints", 650);
-		RAID_RANKING_1ST = Feature.getInt("1stRaidRankingPoints", 1250);
-		RAID_RANKING_2ND = Feature.getInt("2ndRaidRankingPoints", 900);
-		RAID_RANKING_3RD = Feature.getInt("3rdRaidRankingPoints", 700);
-		RAID_RANKING_4TH = Feature.getInt("4thRaidRankingPoints", 600);
-		RAID_RANKING_5TH = Feature.getInt("5thRaidRankingPoints", 450);
-		RAID_RANKING_6TH = Feature.getInt("6thRaidRankingPoints", 350);
-		RAID_RANKING_7TH = Feature.getInt("7thRaidRankingPoints", 300);
-		RAID_RANKING_8TH = Feature.getInt("8thRaidRankingPoints", 200);
-		RAID_RANKING_9TH = Feature.getInt("9thRaidRankingPoints", 150);
-		RAID_RANKING_10TH = Feature.getInt("10thRaidRankingPoints", 100);
-		RAID_RANKING_UP_TO_50TH = Feature.getInt("UpTo50thRaidRankingPoints", 25);
-		RAID_RANKING_UP_TO_100TH = Feature.getInt("UpTo100thRaidRankingPoints", 12);
-		CLAN_LEVEL_6_COST = Feature.getInt("ClanLevel6Cost", 5000);
-		CLAN_LEVEL_7_COST = Feature.getInt("ClanLevel7Cost", 10000);
-		CLAN_LEVEL_8_COST = Feature.getInt("ClanLevel8Cost", 20000);
-		CLAN_LEVEL_9_COST = Feature.getInt("ClanLevel9Cost", 40000);
-		CLAN_LEVEL_10_COST = Feature.getInt("ClanLevel10Cost", 40000);
-		CLAN_LEVEL_11_COST = Feature.getInt("ClanLevel11Cost", 75000);
-		CLAN_LEVEL_6_REQUIREMENT = Feature.getInt("ClanLevel6Requirement", 30);
-		CLAN_LEVEL_7_REQUIREMENT = Feature.getInt("ClanLevel7Requirement", 50);
-		CLAN_LEVEL_8_REQUIREMENT = Feature.getInt("ClanLevel8Requirement", 80);
-		CLAN_LEVEL_9_REQUIREMENT = Feature.getInt("ClanLevel9Requirement", 120);
-		CLAN_LEVEL_10_REQUIREMENT = Feature.getInt("ClanLevel10Requirement", 140);
-		CLAN_LEVEL_11_REQUIREMENT = Feature.getInt("ClanLevel11Requirement", 170);
-		ALLOW_WYVERN_ALWAYS = Feature.getBoolean("AllowRideWyvernAlways", false);
-		ALLOW_WYVERN_DURING_SIEGE = Feature.getBoolean("AllowRideWyvernDuringSiege", true);
-		
-		// Load Character L2Properties file (if exists)
-		final PropertiesParser character = new PropertiesParser(CHARACTER_CONFIG_FILE);
-		
-		ALT_GAME_DELEVEL = character.getBoolean("Delevel", true);
-		DECREASE_SKILL_LEVEL = character.getBoolean("DecreaseSkillOnDelevel", true);
-		ALT_WEIGHT_LIMIT = character.getDouble("AltWeightLimit", 1);
-		RUN_SPD_BOOST = character.getInt("RunSpeedBoost", 0);
-		DEATH_PENALTY_CHANCE = character.getInt("DeathPenaltyChance", 20);
-		RESPAWN_RESTORE_CP = character.getDouble("RespawnRestoreCP", 0) / 100;
-		RESPAWN_RESTORE_HP = character.getDouble("RespawnRestoreHP", 65) / 100;
-		RESPAWN_RESTORE_MP = character.getDouble("RespawnRestoreMP", 0) / 100;
-		HP_REGEN_MULTIPLIER = character.getDouble("HpRegenMultiplier", 100) / 100;
-		MP_REGEN_MULTIPLIER = character.getDouble("MpRegenMultiplier", 100) / 100;
-		CP_REGEN_MULTIPLIER = character.getDouble("CpRegenMultiplier", 100) / 100;
-		ENABLE_MODIFY_SKILL_DURATION = character.getBoolean("EnableModifySkillDuration", false);
-		
-		// Create Map only if enabled
-		if (ENABLE_MODIFY_SKILL_DURATION) {
-			String[] propertySplit = character.getString("SkillDurationList", "").split(";");
-			SKILL_DURATION_LIST = new HashMap<>(propertySplit.length);
-			for (String skill : propertySplit) {
-				String[] skillSplit = skill.split(",");
-				if (skillSplit.length != 2) {
-					LOG.warn("[SkillDurationList]: invalid config property -> SkillDurationList {}", skill);
-				} else {
-					try {
-						SKILL_DURATION_LIST.put(Integer.parseInt(skillSplit[0]), Integer.parseInt(skillSplit[1]));
-					} catch (NumberFormatException nfe) {
-						if (!skill.isEmpty()) {
-							LOG.warn("[SkillDurationList]: invalid config property -> SkillList {}", skill);
-						}
-					}
-				}
-			}
-		}
-		ENABLE_MODIFY_SKILL_REUSE = character.getBoolean("EnableModifySkillReuse", false);
-		// Create Map only if enabled
-		if (ENABLE_MODIFY_SKILL_REUSE) {
-			String[] propertySplit = character.getString("SkillReuseList", "").split(";");
-			SKILL_REUSE_LIST = new HashMap<>(propertySplit.length);
-			for (String skill : propertySplit) {
-				String[] skillSplit = skill.split(",");
-				if (skillSplit.length != 2) {
-					LOG.warn("[SkillReuseList]: invalid config property -> SkillReuseList {}", skill);
-				} else {
-					try {
-						SKILL_REUSE_LIST.put(Integer.parseInt(skillSplit[0]), Integer.parseInt(skillSplit[1]));
-					} catch (NumberFormatException nfe) {
-						if (!skill.isEmpty()) {
-							LOG.warn("[SkillReuseList]: invalid config property -> SkillList {}", skill);
-						}
-					}
-				}
-			}
-		}
-		
-		AUTO_LEARN_SKILLS = character.getBoolean("AutoLearnSkills", false);
-		AUTO_LEARN_FS_SKILLS = character.getBoolean("AutoLearnForgottenScrollSkills", false);
-		AUTO_LOOT_HERBS = character.getBoolean("AutoLootHerbs", false);
-		BUFFS_MAX_AMOUNT = character.getByte("MaxBuffAmount", (byte) 20);
-		TRIGGERED_BUFFS_MAX_AMOUNT = character.getByte("MaxTriggeredBuffAmount", (byte) 12);
-		DANCES_MAX_AMOUNT = character.getByte("MaxDanceAmount", (byte) 12);
-		DANCE_CANCEL_BUFF = character.getBoolean("DanceCancelBuff", false);
-		DANCE_CONSUME_ADDITIONAL_MP = character.getBoolean("DanceConsumeAdditionalMP", true);
-		ALT_STORE_DANCES = character.getBoolean("AltStoreDances", false);
-		AUTO_LEARN_DIVINE_INSPIRATION = character.getBoolean("AutoLearnDivineInspiration", false);
-		ALT_GAME_CANCEL_BOW = character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("bow") || character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
-		ALT_GAME_CANCEL_CAST = character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("cast") || character.getString("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");
-		ALT_GAME_MAGICFAILURES = character.getBoolean("MagicFailures", true);
-		PLAYER_FAKEDEATH_UP_PROTECTION = character.getInt("PlayerFakeDeathUpProtection", 0);
-		STORE_SKILL_COOLTIME = character.getBoolean("StoreSkillCooltime", true);
-		SUBCLASS_STORE_SKILL_COOLTIME = character.getBoolean("SubclassStoreSkillCooltime", false);
-		SUMMON_STORE_SKILL_COOLTIME = character.getBoolean("SummonStoreSkillCooltime", true);
-		ALT_GAME_SHIELD_BLOCKS = character.getBoolean("AltShieldBlocks", false);
-		ALT_PERFECT_SHLD_BLOCK = character.getInt("AltPerfectShieldBlockRate", 10);
-		EFFECT_TICK_RATIO = character.getLong("EffectTickRatio", 666);
-		ALLOW_CLASS_MASTERS = character.getBoolean("AllowClassMasters", false);
-		ALLOW_ENTIRE_TREE = character.getBoolean("AllowEntireTree", false);
-		ALTERNATE_CLASS_MASTER = character.getBoolean("AlternateClassMaster", false);
-		if (ALLOW_CLASS_MASTERS || ALTERNATE_CLASS_MASTER) {
-			CLASS_MASTER_SETTINGS = new ClassMasterSettings(character.getString("ConfigClassMaster", ""));
-		}
-		LIFE_CRYSTAL_NEEDED = character.getBoolean("LifeCrystalNeeded", true);
-		ES_SP_BOOK_NEEDED = character.getBoolean("EnchantSkillSpBookNeeded", true);
-		DIVINE_SP_BOOK_NEEDED = character.getBoolean("DivineInspirationSpBookNeeded", true);
-		ALT_GAME_SKILL_LEARN = character.getBoolean("AltGameSkillLearn", false);
-		ALT_GAME_SUBCLASS_WITHOUT_QUESTS = character.getBoolean("AltSubClassWithoutQuests", false);
-		ALT_GAME_SUBCLASS_EVERYWHERE = character.getBoolean("AltSubclassEverywhere", false);
-		RESTORE_SERVITOR_ON_RECONNECT = character.getBoolean("RestoreServitorOnReconnect", true);
-		RESTORE_PET_ON_RECONNECT = character.getBoolean("RestorePetOnReconnect", true);
-		ALLOW_TRANSFORM_WITHOUT_QUEST = character.getBoolean("AltTransformationWithoutQuest", false);
-		FEE_DELETE_TRANSFER_SKILLS = character.getInt("FeeDeleteTransferSkills", 10000000);
-		FEE_DELETE_SUBCLASS_SKILLS = character.getInt("FeeDeleteSubClassSkills", 10000000);
-		ENABLE_VITALITY = character.getBoolean("EnableVitality", true);
-		RECOVER_VITALITY_ON_RECONNECT = character.getBoolean("RecoverVitalityOnReconnect", true);
-		STARTING_VITALITY_POINTS = character.getInt("StartingVitalityPoints", 20000);
-		MAX_BONUS_EXP = character.getDouble("MaxExpBonus", 3.5);
-		MAX_BONUS_SP = character.getDouble("MaxSpBonus", 3.5);
-		MAX_RUN_SPEED = character.getInt("MaxRunSpeed", 250);
-		MAX_PCRIT_RATE = character.getInt("MaxPCritRate", 500);
-		MAX_MCRIT_RATE = character.getInt("MaxMCritRate", 200);
-		MAX_PATK_SPEED = character.getInt("MaxPAtkSpeed", 1500);
-		MAX_MATK_SPEED = character.getInt("MaxMAtkSpeed", 1999);
-		MAX_EVASION = character.getInt("MaxEvasion", 250);
-		MIN_ABNORMAL_STATE_SUCCESS_RATE = character.getInt("MinAbnormalStateSuccessRate", 10);
-		MAX_ABNORMAL_STATE_SUCCESS_RATE = character.getInt("MaxAbnormalStateSuccessRate", 90);
-		MAX_PLAYER_LEVEL = character.getInt("MaxPlayerLevel", 85);
-		MAX_PET_LEVEL = character.getInt("MaxPetLevel", 86);
-		MAX_SUBCLASS = character.getByte("MaxSubclass", (byte) 3);
-		BASE_SUBCLASS_LEVEL = character.getInt("BaseSubclassLevel", 40);
-		MAX_SUBCLASS_LEVEL = character.getInt("MaxSubclassLevel", 80);
-		MAX_PVTSTORESELL_SLOTS_DWARF = character.getInt("MaxPvtStoreSellSlotsDwarf", 4);
-		MAX_PVTSTORESELL_SLOTS_OTHER = character.getInt("MaxPvtStoreSellSlotsOther", 3);
-		MAX_PVTSTOREBUY_SLOTS_DWARF = character.getInt("MaxPvtStoreBuySlotsDwarf", 5);
-		MAX_PVTSTOREBUY_SLOTS_OTHER = character.getInt("MaxPvtStoreBuySlotsOther", 4);
-		INVENTORY_MAXIMUM_NO_DWARF = character.getInt("MaximumSlotsForNoDwarf", 80);
-		INVENTORY_MAXIMUM_DWARF = character.getInt("MaximumSlotsForDwarf", 100);
-		INVENTORY_MAXIMUM_GM = character.getInt("MaximumSlotsForGMPlayer", 250);
-		INVENTORY_MAXIMUM_QUEST_ITEMS = character.getInt("MaximumSlotsForQuestItems", 100);
-		MAX_ITEM_IN_PACKET = Math.max(INVENTORY_MAXIMUM_NO_DWARF, Math.max(INVENTORY_MAXIMUM_DWARF, INVENTORY_MAXIMUM_GM));
-		WAREHOUSE_SLOTS_DWARF = character.getInt("MaximumWarehouseSlotsForDwarf", 120);
-		WAREHOUSE_SLOTS_NO_DWARF = character.getInt("MaximumWarehouseSlotsForNoDwarf", 100);
-		WAREHOUSE_SLOTS_CLAN = character.getInt("MaximumWarehouseSlotsForClan", 150);
-		ALT_FREIGHT_SLOTS = character.getInt("MaximumFreightSlots", 200);
-		ALT_FREIGHT_PRICE = character.getInt("FreightPrice", 1000);
-		ENCHANT_CHANCE_ELEMENT_STONE = character.getDouble("EnchantChanceElementStone", 50);
-		ENCHANT_CHANCE_ELEMENT_CRYSTAL = character.getDouble("EnchantChanceElementCrystal", 30);
-		ENCHANT_CHANCE_ELEMENT_JEWEL = character.getDouble("EnchantChanceElementJewel", 20);
-		ENCHANT_CHANCE_ELEMENT_ENERGY = character.getDouble("EnchantChanceElementEnergy", 10);
-		String[] notenchantable = character.getString("EnchantBlackList", "7816,7817,7818,7819,7820,7821,7822,7823,7824,7825,7826,7827,7828,7829,7830,7831,13293,13294,13296").split(",");
-		ENCHANT_BLACKLIST = new int[notenchantable.length];
-		for (int i = 0; i < notenchantable.length; i++) {
-			ENCHANT_BLACKLIST[i] = Integer.parseInt(notenchantable[i]);
-		}
-		Arrays.sort(ENCHANT_BLACKLIST);
-		
-		AUGMENTATION_NG_SKILL_CHANCE = character.getInt("AugmentationNGSkillChance", 15);
-		AUGMENTATION_NG_GLOW_CHANCE = character.getInt("AugmentationNGGlowChance", 0);
-		AUGMENTATION_MID_SKILL_CHANCE = character.getInt("AugmentationMidSkillChance", 30);
-		AUGMENTATION_MID_GLOW_CHANCE = character.getInt("AugmentationMidGlowChance", 40);
-		AUGMENTATION_HIGH_SKILL_CHANCE = character.getInt("AugmentationHighSkillChance", 45);
-		AUGMENTATION_HIGH_GLOW_CHANCE = character.getInt("AugmentationHighGlowChance", 70);
-		AUGMENTATION_TOP_SKILL_CHANCE = character.getInt("AugmentationTopSkillChance", 60);
-		AUGMENTATION_TOP_GLOW_CHANCE = character.getInt("AugmentationTopGlowChance", 100);
-		AUGMENTATION_BASESTAT_CHANCE = character.getInt("AugmentationBaseStatChance", 1);
-		AUGMENTATION_ACC_SKILL_CHANCE = character.getInt("AugmentationAccSkillChance", 0);
-		
-		RETAIL_LIKE_AUGMENTATION = character.getBoolean("RetailLikeAugmentation", true);
-		String[] array = character.getString("RetailLikeAugmentationNoGradeChance", "55,35,7,3").split(",");
-		RETAIL_LIKE_AUGMENTATION_NG_CHANCE = new int[array.length];
-		for (int i = 0; i < 4; i++) {
-			RETAIL_LIKE_AUGMENTATION_NG_CHANCE[i] = Integer.parseInt(array[i]);
-		}
-		array = character.getString("RetailLikeAugmentationMidGradeChance", "55,35,7,3").split(",");
-		RETAIL_LIKE_AUGMENTATION_MID_CHANCE = new int[array.length];
-		for (int i = 0; i < 4; i++) {
-			RETAIL_LIKE_AUGMENTATION_MID_CHANCE[i] = Integer.parseInt(array[i]);
-		}
-		array = character.getString("RetailLikeAugmentationHighGradeChance", "55,35,7,3").split(",");
-		RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE = new int[array.length];
-		for (int i = 0; i < 4; i++) {
-			RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE[i] = Integer.parseInt(array[i]);
-		}
-		array = character.getString("RetailLikeAugmentationTopGradeChance", "55,35,7,3").split(",");
-		RETAIL_LIKE_AUGMENTATION_TOP_CHANCE = new int[array.length];
-		for (int i = 0; i < 4; i++) {
-			RETAIL_LIKE_AUGMENTATION_TOP_CHANCE[i] = Integer.parseInt(array[i]);
-		}
-		RETAIL_LIKE_AUGMENTATION_ACCESSORY = character.getBoolean("RetailLikeAugmentationAccessory", true);
-		
-		array = character.getString("AugmentationBlackList", "6656,6657,6658,6659,6660,6661,6662,8191,10170,10314,13740,13741,13742,13743,13744,13745,13746,13747,13748,14592,14593,14594,14595,14596,14597,14598,14599,14600,14664,14665,14666,14667,14668,14669,14670,14671,14672,14801,14802,14803,14804,14805,14806,14807,14808,14809,15282,15283,15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,15299,16025,16026,21712,22173,22174,22175").split(",");
-		AUGMENTATION_BLACKLIST = new int[array.length];
-		
-		for (int i = 0; i < array.length; i++) {
-			AUGMENTATION_BLACKLIST[i] = Integer.parseInt(array[i]);
-		}
-		
-		Arrays.sort(AUGMENTATION_BLACKLIST);
-		ALT_ALLOW_AUGMENT_PVP_ITEMS = character.getBoolean("AltAllowAugmentPvPItems", false);
-		ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE = character.getBoolean("AltKarmaPlayerCanBeKilledInPeaceZone", false);
-		ALT_GAME_KARMA_PLAYER_CAN_SHOP = character.getBoolean("AltKarmaPlayerCanShop", true);
-		ALT_GAME_KARMA_PLAYER_CAN_TELEPORT = character.getBoolean("AltKarmaPlayerCanTeleport", true);
-		ALT_GAME_KARMA_PLAYER_CAN_USE_GK = character.getBoolean("AltKarmaPlayerCanUseGK", false);
-		ALT_GAME_KARMA_PLAYER_CAN_TRADE = character.getBoolean("AltKarmaPlayerCanTrade", true);
-		ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE = character.getBoolean("AltKarmaPlayerCanUseWareHouse", true);
-		MAX_PERSONAL_FAME_POINTS = character.getInt("MaxPersonalFamePoints", 100000);
-		FORTRESS_ZONE_FAME_TASK_FREQUENCY = character.getInt("FortressZoneFameTaskFrequency", 300);
-		FORTRESS_ZONE_FAME_AQUIRE_POINTS = character.getInt("FortressZoneFameAquirePoints", 31);
-		CASTLE_ZONE_FAME_TASK_FREQUENCY = character.getInt("CastleZoneFameTaskFrequency", 300);
-		CASTLE_ZONE_FAME_AQUIRE_POINTS = character.getInt("CastleZoneFameAquirePoints", 125);
-		FAME_FOR_DEAD_PLAYERS = character.getBoolean("FameForDeadPlayers", true);
-		IS_CRAFTING_ENABLED = character.getBoolean("CraftingEnabled", true);
-		CRAFT_MASTERWORK = character.getBoolean("CraftMasterwork", true);
-		DWARF_RECIPE_LIMIT = character.getInt("DwarfRecipeLimit", 50);
-		COMMON_RECIPE_LIMIT = character.getInt("CommonRecipeLimit", 50);
-		ALT_GAME_CREATION = character.getBoolean("AltGameCreation", false);
-		ALT_GAME_CREATION_SPEED = character.getDouble("AltGameCreationSpeed", 1);
-		ALT_GAME_CREATION_XP_RATE = character.getDouble("AltGameCreationXpRate", 1);
-		ALT_GAME_CREATION_SP_RATE = character.getDouble("AltGameCreationSpRate", 1);
-		ALT_GAME_CREATION_RARE_XPSP_RATE = character.getDouble("AltGameCreationRareXpSpRate", 2);
-		ALT_BLACKSMITH_USE_RECIPES = character.getBoolean("AltBlacksmithUseRecipes", true);
-		ALT_CLAN_LEADER_DATE_CHANGE = character.getInt("AltClanLeaderDateChange", 3);
-		if ((ALT_CLAN_LEADER_DATE_CHANGE < 1) || (ALT_CLAN_LEADER_DATE_CHANGE > 7)) {
-			LOG.warn("Wrong value specified for AltClanLeaderDateChange: {}", ALT_CLAN_LEADER_DATE_CHANGE);
-			ALT_CLAN_LEADER_DATE_CHANGE = 3;
-		}
-		ALT_CLAN_LEADER_HOUR_CHANGE = character.getString("AltClanLeaderHourChange", "00:00:00");
-		ALT_CLAN_LEADER_INSTANT_ACTIVATION = character.getBoolean("AltClanLeaderInstantActivation", false);
-		ALT_CLAN_JOIN_DAYS = character.getInt("DaysBeforeJoinAClan", 1);
-		ALT_CLAN_CREATE_DAYS = character.getInt("DaysBeforeCreateAClan", 10);
-		ALT_CLAN_DISSOLVE_DAYS = character.getInt("DaysToPassToDissolveAClan", 7);
-		ALT_ALLY_JOIN_DAYS_WHEN_LEAVED = character.getInt("DaysBeforeJoinAllyWhenLeaved", 1);
-		ALT_ALLY_JOIN_DAYS_WHEN_DISMISSED = character.getInt("DaysBeforeJoinAllyWhenDismissed", 1);
-		ALT_ACCEPT_CLAN_DAYS_WHEN_DISMISSED = character.getInt("DaysBeforeAcceptNewClanWhenDismissed", 1);
-		ALT_CREATE_ALLY_DAYS_WHEN_DISSOLVED = character.getInt("DaysBeforeCreateNewAllyWhenDissolved", 1);
-		ALT_MAX_NUM_OF_CLANS_IN_ALLY = character.getInt("AltMaxNumOfClansInAlly", 3);
-		ALT_CLAN_MEMBERS_FOR_WAR = character.getInt("AltClanMembersForWar", 15);
-		ALT_MEMBERS_CAN_WITHDRAW_FROM_CLANWH = character.getBoolean("AltMembersCanWithdrawFromClanWH", false);
-		REMOVE_CASTLE_CIRCLETS = character.getBoolean("RemoveCastleCirclets", true);
-		ALT_PARTY_RANGE = character.getInt("AltPartyRange", 1600);
-		ALT_PARTY_RANGE2 = character.getInt("AltPartyRange2", 1400);
-		ALT_LEAVE_PARTY_LEADER = character.getBoolean("AltLeavePartyLeader", false);
-		INITIAL_EQUIPMENT_EVENT = character.getBoolean("InitialEquipmentEvent", false);
-		STARTING_ADENA = character.getLong("StartingAdena", 0);
-		STARTING_LEVEL = character.getInt("StartingLevel", 1);
-		STARTING_SP = character.getInt("StartingSP", 0);
-		MAX_ADENA = character.getLong("MaxAdena", 99900000000L);
-		if (MAX_ADENA < 0) {
-			MAX_ADENA = Long.MAX_VALUE;
-		}
-		AUTO_LOOT = character.getBoolean("AutoLoot", false);
-		AUTO_LOOT_RAIDS = character.getBoolean("AutoLootRaids", false);
-		LOOT_RAIDS_PRIVILEGE_INTERVAL = character.getInt("RaidLootRightsInterval", 900) * 1000;
-		LOOT_RAIDS_PRIVILEGE_CC_SIZE = character.getInt("RaidLootRightsCCSize", 45);
-		UNSTUCK_INTERVAL = character.getInt("UnstuckInterval", 300);
-		TELEPORT_WATCHDOG_TIMEOUT = character.getInt("TeleportWatchdogTimeout", 0);
-		PLAYER_SPAWN_PROTECTION = character.getInt("PlayerSpawnProtection", 0);
-		String[] items = character.getString("PlayerSpawnProtectionAllowedItems", "").split(",");
-		SPAWN_PROTECTION_ALLOWED_ITEMS = new ArrayList<>(items.length);
-		for (String item : items) {
-			try {
-				if (!item.isEmpty()) {
-					SPAWN_PROTECTION_ALLOWED_ITEMS.add(Integer.parseInt(item));
-				}
-			} catch (NumberFormatException nfe) {
-				LOG.warn("Player Spawn Protection: Wrong Item ID passed: {}", item, nfe);
-			}
-		}
-		
-		PLAYER_TELEPORT_PROTECTION = character.getInt("PlayerTeleportProtection", 0);
-		RANDOM_RESPAWN_IN_TOWN_ENABLED = character.getBoolean("RandomRespawnInTownEnabled", true);
-		OFFSET_ON_TELEPORT_ENABLED = character.getBoolean("OffsetOnTeleportEnabled", true);
-		MAX_OFFSET_ON_TELEPORT = character.getInt("MaxOffsetOnTeleport", 50);
-		PETITIONING_ALLOWED = character.getBoolean("PetitioningAllowed", true);
-		MAX_PETITIONS_PER_PLAYER = character.getInt("MaxPetitionsPerPlayer", 5);
-		MAX_PETITIONS_PENDING = character.getInt("MaxPetitionsPending", 25);
-		ALT_GAME_FREE_TELEPORT = character.getBoolean("AltFreeTeleporting", false);
-		DELETE_DAYS = character.getInt("DeleteCharAfterDays", 7);
-		ALT_GAME_EXPONENT_XP = character.getFloat("AltGameExponentXp", 0);
-		ALT_GAME_EXPONENT_SP = character.getFloat("AltGameExponentSp", 0);
-		PARTY_XP_CUTOFF_METHOD = character.getString("PartyXpCutoffMethod", "highfive");
-		PARTY_XP_CUTOFF_PERCENT = character.getDouble("PartyXpCutoffPercent", 3);
-		PARTY_XP_CUTOFF_LEVEL = character.getInt("PartyXpCutoffLevel", 20);
-		final String[] gaps = character.getString("PartyXpCutoffGaps", "0,9;10,14;15,99").split(";");
-		PARTY_XP_CUTOFF_GAPS = new int[gaps.length][2];
-		for (int i = 0; i < gaps.length; i++) {
-			PARTY_XP_CUTOFF_GAPS[i] = new int[] {
-				Integer.parseInt(gaps[i].split(",")[0]),
-				Integer.parseInt(gaps[i].split(",")[1])
-			};
-		}
-		final String[] percents = character.getString("PartyXpCutoffGapPercent", "100;30;0").split(";");
-		PARTY_XP_CUTOFF_GAP_PERCENTS = new int[percents.length];
-		for (int i = 0; i < percents.length; i++) {
-			PARTY_XP_CUTOFF_GAP_PERCENTS[i] = Integer.parseInt(percents[i]);
-		}
-		DISABLE_TUTORIAL = character.getBoolean("DisableTutorial", false);
-		EXPERTISE_PENALTY = character.getBoolean("ExpertisePenalty", true);
-		STORE_RECIPE_SHOPLIST = character.getBoolean("StoreRecipeShopList", false);
-		STORE_UI_SETTINGS = character.getBoolean("StoreCharUiSettings", false);
-		FORBIDDEN_NAMES = new HashSet<>(Arrays.asList(character.getString("ForbiddenNames", "annou,ammou,amnou,anmou,anou,amou,announcements,announce").split(",")));
-		SILENCE_MODE_EXCLUDE = character.getBoolean("SilenceModeExclude", false);
-		ALT_VALIDATE_TRIGGER_SKILLS = character.getBoolean("AltValidateTriggerSkills", false);
-		PLAYER_MOVEMENT_BLOCK_TIME = character.getInt("NpcTalkBlockingTime", 0) * 1000;
-		
-		// Load Telnet L2Properties file (if exists)
-		final PropertiesParser telnetSettings = new PropertiesParser(TELNET_FILE);
-		TELNET_ENABLED = telnetSettings.getBoolean("EnableTelnet", false);
-		TELNET_PORT = telnetSettings.getInt("StatusPort", 54321);
-		TELNET_PASSWORD = telnetSettings.getString("StatusPW", null);
-		TELNET_HOSTS = telnetSettings.getString("ListOfHosts", "127.0.0.1,localhost");
-		
-		// MMO
-		final PropertiesParser mmoSettings = new PropertiesParser(MMO_CONFIG_FILE);
-		MMO_SELECTOR_SLEEP_TIME = mmoSettings.getInt("SleepTime", 20);
-		MMO_MAX_SEND_PER_PASS = mmoSettings.getInt("MaxSendPerPass", 12);
-		MMO_MAX_READ_PER_PASS = mmoSettings.getInt("MaxReadPerPass", 12);
-		MMO_HELPER_BUFFER_COUNT = mmoSettings.getInt("HelperBufferCount", 20);
-		MMO_TCP_NODELAY = mmoSettings.getBoolean("TcpNoDelay", false);
-		
-		// Load IdFactory L2Properties file (if exists)
-		final PropertiesParser IdFactory = new PropertiesParser(ID_CONFIG_FILE);
-		IDFACTORY_TYPE = IdFactory.getEnum("IDFactory", IdFactoryType.class, IdFactoryType.BitSet);
-		BAD_ID_CHECKING = IdFactory.getBoolean("BadIdChecking", true);
-		
-		// Load General L2Properties file (if exists)
-		final PropertiesParser General = new PropertiesParser(GENERAL_CONFIG_FILE);
-		EVERYBODY_HAS_ADMIN_RIGHTS = General.getBoolean("EverybodyHasAdminRights", false);
-		SERVER_LIST_BRACKET = General.getBoolean("ServerListBrackets", false);
-		SERVER_LIST_TYPE = getServerTypeId(General.getString("ServerListType", "Normal").split(","));
-		SERVER_LIST_AGE = General.getInt("ServerListAge", 0);
-		SERVER_GMONLY = General.getBoolean("ServerGMOnly", false);
-		GM_HERO_AURA = General.getBoolean("GMHeroAura", false);
-		GM_STARTUP_INVULNERABLE = General.getBoolean("GMStartupInvulnerable", false);
-		GM_STARTUP_INVISIBLE = General.getBoolean("GMStartupInvisible", false);
-		GM_STARTUP_SILENCE = General.getBoolean("GMStartupSilence", false);
-		GM_STARTUP_AUTO_LIST = General.getBoolean("GMStartupAutoList", false);
-		GM_STARTUP_DIET_MODE = General.getBoolean("GMStartupDietMode", false);
-		GM_ITEM_RESTRICTION = General.getBoolean("GMItemRestriction", true);
-		GM_SKILL_RESTRICTION = General.getBoolean("GMSkillRestriction", true);
-		GM_TRADE_RESTRICTED_ITEMS = General.getBoolean("GMTradeRestrictedItems", false);
-		GM_RESTART_FIGHTING = General.getBoolean("GMRestartFighting", true);
-		GM_ANNOUNCER_NAME = General.getBoolean("GMShowAnnouncerName", false);
-		GM_CRITANNOUNCER_NAME = General.getBoolean("GMShowCritAnnouncerName", false);
-		GM_GIVE_SPECIAL_SKILLS = General.getBoolean("GMGiveSpecialSkills", false);
-		GM_GIVE_SPECIAL_AURA_SKILLS = General.getBoolean("GMGiveSpecialAuraSkills", false);
-		GAMEGUARD_ENFORCE = General.getBoolean("GameGuardEnforce", false);
-		GAMEGUARD_PROHIBITACTION = General.getBoolean("GameGuardProhibitAction", false);
-		LOG_CHAT = General.getBoolean("LogChat", false);
-		LOG_AUTO_ANNOUNCEMENTS = General.getBoolean("LogAutoAnnouncements", false);
-		LOG_ITEMS = General.getBoolean("LogItems", false);
-		LOG_ITEMS_SMALL_LOG = General.getBoolean("LogItemsSmallLog", false);
-		LOG_ITEM_ENCHANTS = General.getBoolean("LogItemEnchants", false);
-		LOG_SKILL_ENCHANTS = General.getBoolean("LogSkillEnchants", false);
-		GMAUDIT = General.getBoolean("GMAudit", false);
-		SKILL_CHECK_ENABLE = General.getBoolean("SkillCheckEnable", false);
-		SKILL_CHECK_REMOVE = General.getBoolean("SkillCheckRemove", false);
-		SKILL_CHECK_GM = General.getBoolean("SkillCheckGM", true);
-		DEBUG = General.getBoolean("Debug", false);
-		DEBUG_INSTANCES = General.getBoolean("InstanceDebug", false);
-		HTML_ACTION_CACHE_DEBUG = General.getBoolean("HtmlActionCacheDebug", false);
-		PACKET_HANDLER_DEBUG = General.getBoolean("PacketHandlerDebug", false);
-		DEVELOPER = General.getBoolean("Developer", false);
-		NO_HANDLERS = General.getBoolean("NoHandlers", false) || Boolean.getBoolean("nohandlers");
-		NO_QUESTS = General.getBoolean("NoQuests", false) || Boolean.getBoolean("noquests");
-		ALT_DEV_NO_SPAWNS = General.getBoolean("AltDevNoSpawns", false) || Boolean.getBoolean("nospawns");
-		ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS = General.getBoolean("AltDevShowQuestsLoadInLogs", false);
-		ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS = General.getBoolean("AltDevShowScriptsLoadInLogs", false);
-		THREAD_P_EFFECTS = General.getInt("ThreadPoolSizeEffects", 10);
-		THREAD_P_GENERAL = General.getInt("ThreadPoolSizeGeneral", 13);
-		THREAD_E_EVENTS = General.getInt("ThreadPoolSizeEvents", 2);
-		IO_PACKET_THREAD_CORE_SIZE = General.getInt("UrgentPacketThreadCoreSize", 2);
-		GENERAL_PACKET_THREAD_CORE_SIZE = General.getInt("GeneralPacketThreadCoreSize", 4);
-		GENERAL_THREAD_CORE_SIZE = General.getInt("GeneralThreadCoreSize", 4);
-		AI_MAX_THREAD = General.getInt("AiMaxThread", 6);
-		EVENT_MAX_THREAD = General.getInt("EventsMaxThread", 5);
-		CLIENT_PACKET_QUEUE_SIZE = General.getInt("ClientPacketQueueSize", 0);
-		if (CLIENT_PACKET_QUEUE_SIZE == 0) {
-			CLIENT_PACKET_QUEUE_SIZE = MMO_MAX_READ_PER_PASS + 2;
-		}
-		CLIENT_PACKET_QUEUE_MAX_BURST_SIZE = General.getInt("ClientPacketQueueMaxBurstSize", 0);
-		if (CLIENT_PACKET_QUEUE_MAX_BURST_SIZE == 0) {
-			CLIENT_PACKET_QUEUE_MAX_BURST_SIZE = MMO_MAX_READ_PER_PASS + 1;
-		}
-		CLIENT_PACKET_QUEUE_MAX_PACKETS_PER_SECOND = General.getInt("ClientPacketQueueMaxPacketsPerSecond", 80);
-		CLIENT_PACKET_QUEUE_MEASURE_INTERVAL = General.getInt("ClientPacketQueueMeasureInterval", 5);
-		CLIENT_PACKET_QUEUE_MAX_AVERAGE_PACKETS_PER_SECOND = General.getInt("ClientPacketQueueMaxAveragePacketsPerSecond", 40);
-		CLIENT_PACKET_QUEUE_MAX_FLOODS_PER_MIN = General.getInt("ClientPacketQueueMaxFloodsPerMin", 2);
-		CLIENT_PACKET_QUEUE_MAX_OVERFLOWS_PER_MIN = General.getInt("ClientPacketQueueMaxOverflowsPerMin", 1);
-		CLIENT_PACKET_QUEUE_MAX_UNDERFLOWS_PER_MIN = General.getInt("ClientPacketQueueMaxUnderflowsPerMin", 1);
-		CLIENT_PACKET_QUEUE_MAX_UNKNOWN_PER_MIN = General.getInt("ClientPacketQueueMaxUnknownPerMin", 5);
-		DEADLOCK_DETECTOR = General.getBoolean("DeadLockDetector", true);
-		DEADLOCK_CHECK_INTERVAL = General.getInt("DeadLockCheckInterval", 20);
-		RESTART_ON_DEADLOCK = General.getBoolean("RestartOnDeadlock", false);
-		ALLOW_DISCARDITEM = General.getBoolean("AllowDiscardItem", true);
-		AUTODESTROY_ITEM_AFTER = General.getInt("AutoDestroyDroppedItemAfter", 600);
-		HERB_AUTO_DESTROY_TIME = General.getInt("AutoDestroyHerbTime", 60) * 1000;
-		String[] split = General.getString("ListOfProtectedItems", "0").split(",");
-		LIST_PROTECTED_ITEMS = new ArrayList<>(split.length);
-		for (String id : split) {
-			LIST_PROTECTED_ITEMS.add(Integer.parseInt(id));
-		}
-		DATABASE_CLEAN_UP = General.getBoolean("DatabaseCleanUp", true);
-		CONNECTION_CLOSE_TIME = General.getLong("ConnectionCloseTime", 60000);
-		CHAR_STORE_INTERVAL = General.getInt("CharacterDataStoreInterval", 15);
-		LAZY_ITEMS_UPDATE = General.getBoolean("LazyItemsUpdate", false);
-		UPDATE_ITEMS_ON_CHAR_STORE = General.getBoolean("UpdateItemsOnCharStore", false);
-		DESTROY_DROPPED_PLAYER_ITEM = General.getBoolean("DestroyPlayerDroppedItem", false);
-		DESTROY_EQUIPABLE_PLAYER_ITEM = General.getBoolean("DestroyEquipableItem", false);
-		SAVE_DROPPED_ITEM = General.getBoolean("SaveDroppedItem", false);
-		EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD = General.getBoolean("EmptyDroppedItemTableAfterLoad", false);
-		SAVE_DROPPED_ITEM_INTERVAL = General.getInt("SaveDroppedItemInterval", 60) * 60000;
-		CLEAR_DROPPED_ITEM_TABLE = General.getBoolean("ClearDroppedItemTable", false);
-		AUTODELETE_INVALID_QUEST_DATA = General.getBoolean("AutoDeleteInvalidQuestData", false);
-		PRECISE_DROP_CALCULATION = General.getBoolean("PreciseDropCalculation", true);
-		MULTIPLE_ITEM_DROP = General.getBoolean("MultipleItemDrop", true);
-		FORCE_INVENTORY_UPDATE = General.getBoolean("ForceInventoryUpdate", false);
-		LAZY_CACHE = General.getBoolean("LazyCache", true);
-		CACHE_CHAR_NAMES = General.getBoolean("CacheCharNames", true);
-		MIN_NPC_ANIMATION = General.getInt("MinNPCAnimation", 10);
-		MAX_NPC_ANIMATION = General.getInt("MaxNPCAnimation", 20);
-		MIN_MONSTER_ANIMATION = General.getInt("MinMonsterAnimation", 5);
-		MAX_MONSTER_ANIMATION = General.getInt("MaxMonsterAnimation", 20);
-		MOVE_BASED_KNOWNLIST = General.getBoolean("MoveBasedKnownlist", false);
-		KNOWNLIST_UPDATE_INTERVAL = General.getLong("KnownListUpdateInterval", 1250);
-		GRIDS_ALWAYS_ON = General.getBoolean("GridsAlwaysOn", false);
-		GRID_NEIGHBOR_TURNON_TIME = General.getInt("GridNeighborTurnOnTime", 1);
-		GRID_NEIGHBOR_TURNOFF_TIME = General.getInt("GridNeighborTurnOffTime", 90);
-		PEACE_ZONE_MODE = General.getInt("PeaceZoneMode", 0);
-		DEFAULT_GLOBAL_CHAT = General.getString("GlobalChat", "ON");
-		DEFAULT_TRADE_CHAT = General.getString("TradeChat", "ON");
-		ALLOW_WAREHOUSE = General.getBoolean("AllowWarehouse", true);
-		WAREHOUSE_CACHE = General.getBoolean("WarehouseCache", false);
-		WAREHOUSE_CACHE_TIME = General.getInt("WarehouseCacheTime", 15);
-		ALLOW_REFUND = General.getBoolean("AllowRefund", true);
-		ALLOW_MAIL = General.getBoolean("AllowMail", true);
-		ALLOW_ATTACHMENTS = General.getBoolean("AllowAttachments", true);
-		ALLOW_WEAR = General.getBoolean("AllowWear", true);
-		WEAR_DELAY = General.getInt("WearDelay", 5);
-		WEAR_PRICE = General.getInt("WearPrice", 10);
-		INSTANCE_FINISH_TIME = 1000 * General.getInt("DefaultFinishTime", 300);
-		RESTORE_PLAYER_INSTANCE = General.getBoolean("RestorePlayerInstance", false);
-		ALLOW_SUMMON_IN_INSTANCE = General.getBoolean("AllowSummonInInstance", false);
-		EJECT_DEAD_PLAYER_TIME = 1000 * General.getInt("EjectDeadPlayerTime", 60);
-		ALLOW_LOTTERY = General.getBoolean("AllowLottery", true);
-		ALLOW_RACE = General.getBoolean("AllowRace", true);
-		ALLOW_WATER = General.getBoolean("AllowWater", true);
-		ALLOW_RENTPET = General.getBoolean("AllowRentPet", false);
-		ALLOWFISHING = General.getBoolean("AllowFishing", true);
-		ALLOW_MANOR = General.getBoolean("AllowManor", true);
-		ALLOW_BOAT = General.getBoolean("AllowBoat", true);
-		BOAT_BROADCAST_RADIUS = General.getInt("BoatBroadcastRadius", 20000);
-		ALLOW_CURSED_WEAPONS = General.getBoolean("AllowCursedWeapons", true);
-		ALLOW_PET_WALKERS = General.getBoolean("AllowPetWalkers", true);
-		SERVER_NEWS = General.getBoolean("ShowServerNews", false);
-		ENABLE_COMMUNITY_BOARD = General.getBoolean("EnableCommunityBoard", true);
-		BBS_DEFAULT = General.getString("BBSDefault", "_bbshome");
-		USE_SAY_FILTER = General.getBoolean("UseChatFilter", false);
-		CHAT_FILTER_CHARS = General.getString("ChatFilterChars", "^_^");
-		String[] propertySplit4 = General.getString("BanChatChannels", "0;1;8;17").trim().split(";");
-		BAN_CHAT_CHANNELS = new int[propertySplit4.length];
-		try {
-			int i = 0;
-			for (String chatId : propertySplit4) {
-				BAN_CHAT_CHANNELS[i++] = Integer.parseInt(chatId);
-			}
-		} catch (NumberFormatException nfe) {
-			LOG.warn("Unable to load banned channels!", nfe);
-		}
-		ALT_MANOR_REFRESH_TIME = General.getInt("AltManorRefreshTime", 20);
-		ALT_MANOR_REFRESH_MIN = General.getInt("AltManorRefreshMin", 0);
-		ALT_MANOR_APPROVE_TIME = General.getInt("AltManorApproveTime", 4);
-		ALT_MANOR_APPROVE_MIN = General.getInt("AltManorApproveMin", 30);
-		ALT_MANOR_MAINTENANCE_MIN = General.getInt("AltManorMaintenanceMin", 6);
-		ALT_MANOR_SAVE_ALL_ACTIONS = General.getBoolean("AltManorSaveAllActions", false);
-		ALT_MANOR_SAVE_PERIOD_RATE = General.getInt("AltManorSavePeriodRate", 2);
-		ALT_LOTTERY_PRIZE = General.getLong("AltLotteryPrize", 50000);
-		ALT_LOTTERY_TICKET_PRICE = General.getLong("AltLotteryTicketPrice", 2000);
-		ALT_LOTTERY_5_NUMBER_RATE = General.getFloat("AltLottery5NumberRate", 0.6f);
-		ALT_LOTTERY_4_NUMBER_RATE = General.getFloat("AltLottery4NumberRate", 0.2f);
-		ALT_LOTTERY_3_NUMBER_RATE = General.getFloat("AltLottery3NumberRate", 0.2f);
-		ALT_LOTTERY_2_AND_1_NUMBER_PRIZE = General.getLong("AltLottery2and1NumberPrize", 200);
-		ALT_ITEM_AUCTION_ENABLED = General.getBoolean("AltItemAuctionEnabled", true);
-		ALT_ITEM_AUCTION_EXPIRED_AFTER = General.getInt("AltItemAuctionExpiredAfter", 14);
-		ALT_ITEM_AUCTION_TIME_EXTENDS_ON_BID = General.getInt("AltItemAuctionTimeExtendsOnBid", 0) * 1000;
-		FS_TIME_ATTACK = General.getInt("TimeOfAttack", 50);
-		FS_TIME_COOLDOWN = General.getInt("TimeOfCoolDown", 5);
-		FS_TIME_ENTRY = General.getInt("TimeOfEntry", 3);
-		FS_TIME_WARMUP = General.getInt("TimeOfWarmUp", 2);
-		FS_PARTY_MEMBER_COUNT = General.getInt("NumberOfNecessaryPartyMembers", 4);
-		if (FS_TIME_ATTACK <= 0) {
-			FS_TIME_ATTACK = 50;
-		}
-		if (FS_TIME_COOLDOWN <= 0) {
-			FS_TIME_COOLDOWN = 5;
-		}
-		if (FS_TIME_ENTRY <= 0) {
-			FS_TIME_ENTRY = 3;
-		}
-		if (FS_TIME_ENTRY <= 0) {
-			FS_TIME_ENTRY = 3;
-		}
-		if (FS_TIME_ENTRY <= 0) {
-			FS_TIME_ENTRY = 3;
-		}
-		RIFT_MIN_PARTY_SIZE = General.getInt("RiftMinPartySize", 5);
-		RIFT_MAX_JUMPS = General.getInt("MaxRiftJumps", 4);
-		RIFT_SPAWN_DELAY = General.getInt("RiftSpawnDelay", 10000);
-		RIFT_AUTO_JUMPS_TIME_MIN = General.getInt("AutoJumpsDelayMin", 480);
-		RIFT_AUTO_JUMPS_TIME_MAX = General.getInt("AutoJumpsDelayMax", 600);
-		RIFT_BOSS_ROOM_TIME_MUTIPLY = General.getFloat("BossRoomTimeMultiply", 1.5f);
-		RIFT_ENTER_COST_RECRUIT = General.getInt("RecruitCost", 18);
-		RIFT_ENTER_COST_SOLDIER = General.getInt("SoldierCost", 21);
-		RIFT_ENTER_COST_OFFICER = General.getInt("OfficerCost", 24);
-		RIFT_ENTER_COST_CAPTAIN = General.getInt("CaptainCost", 27);
-		RIFT_ENTER_COST_COMMANDER = General.getInt("CommanderCost", 30);
-		RIFT_ENTER_COST_HERO = General.getInt("HeroCost", 33);
-		DEFAULT_PUNISH = IllegalActionPunishmentType.findByName(General.getString("DefaultPunish", "KICK"));
-		DEFAULT_PUNISH_PARAM = General.getInt("DefaultPunishParam", 0);
-		ONLY_GM_ITEMS_FREE = General.getBoolean("OnlyGMItemsFree", true);
-		JAIL_IS_PVP = General.getBoolean("JailIsPvp", false);
-		JAIL_DISABLE_CHAT = General.getBoolean("JailDisableChat", true);
-		JAIL_DISABLE_TRANSACTION = General.getBoolean("JailDisableTransaction", false);
-		CUSTOM_SPAWNLIST_TABLE = General.getBoolean("CustomSpawnlistTable", false);
-		SAVE_GMSPAWN_ON_CUSTOM = General.getBoolean("SaveGmSpawnOnCustom", false);
-		CUSTOM_NPC_DATA = General.getBoolean("CustomNpcData", false);
-		CUSTOM_TELEPORT_TABLE = General.getBoolean("CustomTeleportTable", false);
-		CUSTOM_NPCBUFFER_TABLES = General.getBoolean("CustomNpcBufferTables", false);
-		CUSTOM_SKILLS_LOAD = General.getBoolean("CustomSkillsLoad", false);
-		CUSTOM_ITEMS_LOAD = General.getBoolean("CustomItemsLoad", false);
-		CUSTOM_MULTISELL_LOAD = General.getBoolean("CustomMultisellLoad", false);
-		CUSTOM_BUYLIST_LOAD = General.getBoolean("CustomBuyListLoad", false);
-		ALT_BIRTHDAY_GIFT = General.getInt("AltBirthdayGift", 22187);
-		ALT_BIRTHDAY_MAIL_SUBJECT = General.getString("AltBirthdayMailSubject", "Happy Birthday!");
-		ALT_BIRTHDAY_MAIL_TEXT = General.getString("AltBirthdayMailText", "Hello Adventurer!! Seeing as you're one year older now, I thought I would send you some birthday cheer :) Please find your birthday pack attached. May these gifts bring you joy and happiness on this very special day." + EOL
-			+ EOL + "Sincerely, Alegria");
-		ENABLE_BLOCK_CHECKER_EVENT = General.getBoolean("EnableBlockCheckerEvent", false);
-		MIN_BLOCK_CHECKER_TEAM_MEMBERS = General.getInt("BlockCheckerMinTeamMembers", 2);
-		if (MIN_BLOCK_CHECKER_TEAM_MEMBERS < 1) {
-			MIN_BLOCK_CHECKER_TEAM_MEMBERS = 1;
-		} else if (MIN_BLOCK_CHECKER_TEAM_MEMBERS > 6) {
-			MIN_BLOCK_CHECKER_TEAM_MEMBERS = 6;
-		}
-		HBCE_FAIR_PLAY = General.getBoolean("HBCEFairPlay", false);
-		HELLBOUND_WITHOUT_QUEST = General.getBoolean("HellboundWithoutQuest", false);
-		
-		NORMAL_ENCHANT_COST_MULTIPLIER = General.getInt("NormalEnchantCostMultipiler", 1);
-		SAFE_ENCHANT_COST_MULTIPLIER = General.getInt("SafeEnchantCostMultipiler", 5);
-		
-		BOTREPORT_ENABLE = General.getBoolean("EnableBotReportButton", false);
-		BOTREPORT_RESETPOINT_HOUR = General.getString("BotReportPointsResetHour", "00:00").split(":");
-		BOTREPORT_REPORT_DELAY = General.getInt("BotReportDelay", 30) * 60000;
-		BOTREPORT_ALLOW_REPORTS_FROM_SAME_CLAN_MEMBERS = General.getBoolean("AllowReportsFromSameClanMembers", false);
-		ENABLE_FALLING_DAMAGE = General.getBoolean("EnableFallingDamage", true);
-		
-		// Load FloodProtector L2Properties file
-		final PropertiesParser FloodProtectors = new PropertiesParser(FLOOD_PROTECTOR_FILE);
-		
-		loadFloodProtectorConfigs(FloodProtectors);
-		
-		// Load NPC L2Properties file (if exists)
-		final PropertiesParser NPC = new PropertiesParser(NPC_CONFIG_FILE);
-		
-		ANNOUNCE_MAMMON_SPAWN = NPC.getBoolean("AnnounceMammonSpawn", false);
-		ALT_MOB_AGRO_IN_PEACEZONE = NPC.getBoolean("AltMobAgroInPeaceZone", true);
-		ALT_ATTACKABLE_NPCS = NPC.getBoolean("AltAttackableNpcs", true);
-		ALT_GAME_VIEWNPC = NPC.getBoolean("AltGameViewNpc", false);
-		MAX_DRIFT_RANGE = NPC.getInt("MaxDriftRange", 300);
-		DEEPBLUE_DROP_RULES = NPC.getBoolean("UseDeepBlueDropRules", true);
-		DEEPBLUE_DROP_RULES_RAID = NPC.getBoolean("UseDeepBlueDropRulesRaid", true);
-		SHOW_NPC_LVL = NPC.getBoolean("ShowNpcLevel", false);
-		SHOW_CREST_WITHOUT_QUEST = NPC.getBoolean("ShowCrestWithoutQuest", false);
-		ENABLE_RANDOM_ENCHANT_EFFECT = NPC.getBoolean("EnableRandomEnchantEffect", false);
-		MIN_NPC_LVL_DMG_PENALTY = NPC.getInt("MinNPCLevelForDmgPenalty", 78);
-		NPC_DMG_PENALTY = parseConfigLine(NPC.getString("DmgPenaltyForLvLDifferences", "0.7, 0.6, 0.6, 0.55"));
-		NPC_CRIT_DMG_PENALTY = parseConfigLine(NPC.getString("CritDmgPenaltyForLvLDifferences", "0.75, 0.65, 0.6, 0.58"));
-		NPC_SKILL_DMG_PENALTY = parseConfigLine(NPC.getString("SkillDmgPenaltyForLvLDifferences", "0.8, 0.7, 0.65, 0.62"));
-		MIN_NPC_LVL_MAGIC_PENALTY = NPC.getInt("MinNPCLevelForMagicPenalty", 78);
-		NPC_SKILL_CHANCE_PENALTY = parseConfigLine(NPC.getString("SkillChancePenaltyForLvLDifferences", "2.5, 3.0, 3.25, 3.5"));
-		DECAY_TIME_TASK = NPC.getInt("DecayTimeTask", 5000);
-		DEFAULT_CORPSE_TIME = NPC.getInt("DefaultCorpseTime", 7);
-		SPOILED_CORPSE_EXTEND_TIME = NPC.getInt("SpoiledCorpseExtendTime", 10);
-		CORPSE_CONSUME_SKILL_ALLOWED_TIME_BEFORE_DECAY = NPC.getInt("CorpseConsumeSkillAllowedTimeBeforeDecay", 2000);
-		GUARD_ATTACK_AGGRO_MOB = NPC.getBoolean("GuardAttackAggroMob", false);
-		ALLOW_WYVERN_UPGRADER = NPC.getBoolean("AllowWyvernUpgrader", false);
-		String[] listPetRentNpc = NPC.getString("ListPetRentNpc", "30827").split(",");
-		LIST_PET_RENT_NPC = new ArrayList<>(listPetRentNpc.length);
-		for (String id : listPetRentNpc) {
-			LIST_PET_RENT_NPC.add(Integer.valueOf(id));
-		}
-		RAID_HP_REGEN_MULTIPLIER = NPC.getDouble("RaidHpRegenMultiplier", 100) / 100;
-		RAID_MP_REGEN_MULTIPLIER = NPC.getDouble("RaidMpRegenMultiplier", 100) / 100;
-		RAID_PDEFENCE_MULTIPLIER = NPC.getDouble("RaidPDefenceMultiplier", 100) / 100;
-		RAID_MDEFENCE_MULTIPLIER = NPC.getDouble("RaidMDefenceMultiplier", 100) / 100;
-		RAID_PATTACK_MULTIPLIER = NPC.getDouble("RaidPAttackMultiplier", 100) / 100;
-		RAID_MATTACK_MULTIPLIER = NPC.getDouble("RaidMAttackMultiplier", 100) / 100;
-		RAID_MIN_RESPAWN_MULTIPLIER = NPC.getFloat("RaidMinRespawnMultiplier", 1.0f);
-		RAID_MAX_RESPAWN_MULTIPLIER = NPC.getFloat("RaidMaxRespawnMultiplier", 1.0f);
-		RAID_MINION_RESPAWN_TIMER = NPC.getInt("RaidMinionRespawnTime", 300000);
-		final String[] propertySplit = NPC.getString("CustomMinionsRespawnTime", "").split(";");
-		MINIONS_RESPAWN_TIME = new HashMap<>(propertySplit.length);
-		for (String prop : propertySplit) {
-			String[] propSplit = prop.split(",");
-			if (propSplit.length != 2) {
-				LOG.warn("[CustomMinionsRespawnTime]: invalid config property -> CustomMinionsRespawnTime {}", prop);
-			}
-			
-			try {
-				MINIONS_RESPAWN_TIME.put(Integer.valueOf(propSplit[0]), Integer.valueOf(propSplit[1]));
-			} catch (NumberFormatException nfe) {
-				if (!prop.isEmpty()) {
-					LOG.warn("[CustomMinionsRespawnTime]: invalid config property -> CustomMinionsRespawnTime {}", prop);
-				}
-			}
-		}
-		
-		RAID_DISABLE_CURSE = NPC.getBoolean("DisableRaidCurse", false);
-		RAID_CHAOS_TIME = NPC.getInt("RaidChaosTime", 10);
-		GRAND_CHAOS_TIME = NPC.getInt("GrandChaosTime", 10);
-		MINION_CHAOS_TIME = NPC.getInt("MinionChaosTime", 10);
-		INVENTORY_MAXIMUM_PET = NPC.getInt("MaximumSlotsForPet", 12);
-		PET_HP_REGEN_MULTIPLIER = NPC.getDouble("PetHpRegenMultiplier", 100) / 100;
-		PET_MP_REGEN_MULTIPLIER = NPC.getDouble("PetMpRegenMultiplier", 100) / 100;
-		
-		DROP_ADENA_MIN_LEVEL_DIFFERENCE = NPC.getInt("DropAdenaMinLevelDifference", 8);
-		DROP_ADENA_MAX_LEVEL_DIFFERENCE = NPC.getInt("DropAdenaMaxLevelDifference", 15);
-		DROP_ADENA_MIN_LEVEL_GAP_CHANCE = NPC.getDouble("DropAdenaMinLevelGapChance", 10);
-		
-		DROP_ITEM_MIN_LEVEL_DIFFERENCE = NPC.getInt("DropItemMinLevelDifference", 5);
-		DROP_ITEM_MAX_LEVEL_DIFFERENCE = NPC.getInt("DropItemMaxLevelDifference", 10);
-		DROP_ITEM_MIN_LEVEL_GAP_CHANCE = NPC.getDouble("DropItemMinLevelGapChance", 10);
-		
-		// Load Rates L2Properties file (if exists)
-		final PropertiesParser RatesSettings = new PropertiesParser(RATES_CONFIG_FILE);
-		
-		RATE_XP = RatesSettings.getFloat("RateXp", 1);
-		RATE_SP = RatesSettings.getFloat("RateSp", 1);
-		RATE_PARTY_XP = RatesSettings.getFloat("RatePartyXp", 1);
-		RATE_PARTY_SP = RatesSettings.getFloat("RatePartySp", 1);
-		RATE_EXTRACTABLE = RatesSettings.getFloat("RateExtractable", 1);
-		RATE_DROP_MANOR = RatesSettings.getInt("RateDropManor", 1);
-		RATE_QUEST_DROP = RatesSettings.getFloat("RateQuestDrop", 1);
-		RATE_QUEST_REWARD = RatesSettings.getFloat("RateQuestReward", 1);
-		RATE_QUEST_REWARD_XP = RatesSettings.getFloat("RateQuestRewardXP", 1);
-		RATE_QUEST_REWARD_SP = RatesSettings.getFloat("RateQuestRewardSP", 1);
-		RATE_QUEST_REWARD_ADENA = RatesSettings.getFloat("RateQuestRewardAdena", 1);
-		RATE_QUEST_REWARD_USE_MULTIPLIERS = RatesSettings.getBoolean("UseQuestRewardMultipliers", false);
-		RATE_QUEST_REWARD_POTION = RatesSettings.getFloat("RateQuestRewardPotion", 1);
-		RATE_QUEST_REWARD_SCROLL = RatesSettings.getFloat("RateQuestRewardScroll", 1);
-		RATE_QUEST_REWARD_RECIPE = RatesSettings.getFloat("RateQuestRewardRecipe", 1);
-		RATE_QUEST_REWARD_MATERIAL = RatesSettings.getFloat("RateQuestRewardMaterial", 1);
-		RATE_HB_TRUST_INCREASE = RatesSettings.getFloat("RateHellboundTrustIncrease", 1);
-		RATE_HB_TRUST_DECREASE = RatesSettings.getFloat("RateHellboundTrustDecrease", 1);
-		
-		RATE_VITALITY_LEVEL_1 = RatesSettings.getFloat("RateVitalityLevel1", 1.5f);
-		RATE_VITALITY_LEVEL_2 = RatesSettings.getFloat("RateVitalityLevel2", 2);
-		RATE_VITALITY_LEVEL_3 = RatesSettings.getFloat("RateVitalityLevel3", 2.5f);
-		RATE_VITALITY_LEVEL_4 = RatesSettings.getFloat("RateVitalityLevel4", 3);
-		RATE_RECOVERY_VITALITY_PEACE_ZONE = RatesSettings.getFloat("RateRecoveryPeaceZone", 1);
-		RATE_VITALITY_LOST = RatesSettings.getFloat("RateVitalityLost", 1);
-		RATE_VITALITY_GAIN = RatesSettings.getFloat("RateVitalityGain", 1);
-		RATE_RECOVERY_ON_RECONNECT = RatesSettings.getFloat("RateRecoveryOnReconnect", 4);
-		RATE_KARMA_LOST = RatesSettings.getFloat("RateKarmaLost", -1);
-		if (RATE_KARMA_LOST == -1) {
-			RATE_KARMA_LOST = RATE_XP;
-		}
-		RATE_KARMA_EXP_LOST = RatesSettings.getFloat("RateKarmaExpLost", 1);
-		RATE_SIEGE_GUARDS_PRICE = RatesSettings.getFloat("RateSiegeGuardsPrice", 1);
-		PLAYER_DROP_LIMIT = RatesSettings.getInt("PlayerDropLimit", 3);
-		PLAYER_RATE_DROP = RatesSettings.getInt("PlayerRateDrop", 5);
-		PLAYER_RATE_DROP_ITEM = RatesSettings.getInt("PlayerRateDropItem", 70);
-		PLAYER_RATE_DROP_EQUIP = RatesSettings.getInt("PlayerRateDropEquip", 25);
-		PLAYER_RATE_DROP_EQUIP_WEAPON = RatesSettings.getInt("PlayerRateDropEquipWeapon", 5);
-		PET_XP_RATE = RatesSettings.getFloat("PetXpRate", 1);
-		PET_FOOD_RATE = RatesSettings.getInt("PetFoodRate", 1);
-		SINEATER_XP_RATE = RatesSettings.getFloat("SinEaterXpRate", 1);
-		KARMA_DROP_LIMIT = RatesSettings.getInt("KarmaDropLimit", 10);
-		KARMA_RATE_DROP = RatesSettings.getInt("KarmaRateDrop", 70);
-		KARMA_RATE_DROP_ITEM = RatesSettings.getInt("KarmaRateDropItem", 50);
-		KARMA_RATE_DROP_EQUIP = RatesSettings.getInt("KarmaRateDropEquip", 40);
-		KARMA_RATE_DROP_EQUIP_WEAPON = RatesSettings.getInt("KarmaRateDropEquipWeapon", 10);
-		
-		RATE_DEATH_DROP_AMOUNT_MULTIPLIER = RatesSettings.getFloat("DeathDropAmountMultiplier", 1);
-		RATE_CORPSE_DROP_AMOUNT_MULTIPLIER = RatesSettings.getFloat("CorpseDropAmountMultiplier", 1);
-		RATE_HERB_DROP_AMOUNT_MULTIPLIER = RatesSettings.getFloat("HerbDropAmountMultiplier", 1);
-		RATE_RAID_DROP_AMOUNT_MULTIPLIER = RatesSettings.getFloat("RaidDropAmountMultiplier", 1);
-		RATE_DEATH_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("DeathDropChanceMultiplier", 1);
-		RATE_CORPSE_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("CorpseDropChanceMultiplier", 1);
-		RATE_HERB_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("HerbDropChanceMultiplier", 1);
-		RATE_RAID_DROP_CHANCE_MULTIPLIER = RatesSettings.getFloat("RaidDropChanceMultiplier", 1);
-		String[] dropAmountMultiplier = RatesSettings.getString("DropAmountMultiplierByItemId", "").split(";");
-		RATE_DROP_AMOUNT_MULTIPLIER = new HashMap<>(dropAmountMultiplier.length);
-		if (!dropAmountMultiplier[0].isEmpty()) {
-			for (String item : dropAmountMultiplier) {
-				String[] itemSplit = item.split(",");
-				if (itemSplit.length != 2) {
-					LOG.warn("Config.load(): invalid config property -> RateDropItemsById {}", item);
-				} else {
-					try {
-						RATE_DROP_AMOUNT_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
-					} catch (NumberFormatException nfe) {
-						if (!item.isEmpty()) {
-							LOG.warn("Config.load(): invalid config property -> RateDropItemsById {}", item);
-						}
-					}
-				}
-			}
-		}
-		
-		String[] dropChanceMultiplier = RatesSettings.getString("DropChanceMultiplierByItemId", "").split(";");
-		RATE_DROP_CHANCE_MULTIPLIER = new HashMap<>(dropChanceMultiplier.length);
-		if (!dropChanceMultiplier[0].isEmpty()) {
-			for (String item : dropChanceMultiplier) {
-				String[] itemSplit = item.split(",");
-				if (itemSplit.length != 2) {
-					LOG.warn("Config.load(): invalid config property -> RateDropItemsById {}", item);
-				} else {
-					try {
-						RATE_DROP_CHANCE_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
-					} catch (NumberFormatException nfe) {
-						if (!item.isEmpty()) {
-							LOG.warn("Config.load(): invalid config property -> RateDropItemsById {}", item);
-						}
-					}
-				}
-			}
-		}
-		
-		// Load L2JMod L2Properties file (if exists)
-		final PropertiesParser L2JModSettings = new PropertiesParser(L2JMOD_CONFIG_FILE);
-		
-		L2JMOD_CHAMPION_ENABLE = L2JModSettings.getBoolean("ChampionEnable", false);
-		L2JMOD_CHAMPION_PASSIVE = L2JModSettings.getBoolean("ChampionPassive", false);
-		L2JMOD_CHAMPION_FREQUENCY = L2JModSettings.getInt("ChampionFrequency", -1);
-		L2JMOD_CHAMP_TITLE = L2JModSettings.getString("ChampionTitle", "Champion");
-		L2JMOD_CHAMP_MIN_LVL = L2JModSettings.getInt("ChampionMinLevel", 20);
-		L2JMOD_CHAMP_MAX_LVL = L2JModSettings.getInt("ChampionMaxLevel", 60);
-		L2JMOD_CHAMPION_HP = L2JModSettings.getInt("ChampionHp", 7);
-		L2JMOD_CHAMPION_HP_REGEN = L2JModSettings.getFloat("ChampionHpRegen", 1);
-		L2JMOD_CHAMPION_REWARDS_EXP_SP = L2JModSettings.getFloat("ChampionRewardsExpSp", 8);
-		L2JMOD_CHAMPION_REWARDS_CHANCE = L2JModSettings.getFloat("ChampionRewardsChance", 8);
-		L2JMOD_CHAMPION_REWARDS_AMOUNT = L2JModSettings.getFloat("ChampionRewardsAmount", 1);
-		L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE = L2JModSettings.getFloat("ChampionAdenasRewardsChance", 1);
-		L2JMOD_CHAMPION_ADENAS_REWARDS_AMOUNT = L2JModSettings.getFloat("ChampionAdenasRewardsAmount", 1);
-		L2JMOD_CHAMPION_ATK = L2JModSettings.getFloat("ChampionAtk", 1);
-		L2JMOD_CHAMPION_SPD_ATK = L2JModSettings.getFloat("ChampionSpdAtk", 1);
-		L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE = L2JModSettings.getInt("ChampionRewardLowerLvlItemChance", 0);
-		L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE = L2JModSettings.getInt("ChampionRewardHigherLvlItemChance", 0);
-		L2JMOD_CHAMPION_REWARD_ID = L2JModSettings.getInt("ChampionRewardItemID", 6393);
-		L2JMOD_CHAMPION_REWARD_QTY = L2JModSettings.getInt("ChampionRewardItemQty", 1);
-		L2JMOD_CHAMPION_ENABLE_VITALITY = L2JModSettings.getBoolean("ChampionEnableVitality", false);
-		L2JMOD_CHAMPION_ENABLE_IN_INSTANCES = L2JModSettings.getBoolean("ChampionEnableInInstances", false);
-		
-		TVT_EVENT_ENABLED = L2JModSettings.getBoolean("TvTEventEnabled", false);
-		TVT_EVENT_IN_INSTANCE = L2JModSettings.getBoolean("TvTEventInInstance", false);
-		TVT_EVENT_INSTANCE_FILE = L2JModSettings.getString("TvTEventInstanceFile", "coliseum.xml");
-		TVT_EVENT_INTERVAL = L2JModSettings.getString("TvTEventInterval", "20:00").split(",");
-		TVT_EVENT_PARTICIPATION_TIME = L2JModSettings.getInt("TvTEventParticipationTime", 3600);
-		TVT_EVENT_RUNNING_TIME = L2JModSettings.getInt("TvTEventRunningTime", 1800);
-		TVT_EVENT_PARTICIPATION_NPC_ID = L2JModSettings.getInt("TvTEventParticipationNpcId", 0);
-		
-		L2JMOD_ALLOW_WEDDING = L2JModSettings.getBoolean("AllowWedding", false);
-		L2JMOD_WEDDING_PRICE = L2JModSettings.getInt("WeddingPrice", 250000000);
-		L2JMOD_WEDDING_PUNISH_INFIDELITY = L2JModSettings.getBoolean("WeddingPunishInfidelity", true);
-		L2JMOD_WEDDING_TELEPORT = L2JModSettings.getBoolean("WeddingTeleport", true);
-		L2JMOD_WEDDING_TELEPORT_PRICE = L2JModSettings.getInt("WeddingTeleportPrice", 50000);
-		L2JMOD_WEDDING_TELEPORT_DURATION = L2JModSettings.getInt("WeddingTeleportDuration", 60);
-		L2JMOD_WEDDING_SAMESEX = L2JModSettings.getBoolean("WeddingAllowSameSex", false);
-		L2JMOD_WEDDING_FORMALWEAR = L2JModSettings.getBoolean("WeddingFormalWear", true);
-		L2JMOD_WEDDING_DIVORCE_COSTS = L2JModSettings.getInt("WeddingDivorceCosts", 20);
-		
-		L2JMOD_ENABLE_WAREHOUSESORTING_CLAN = L2JModSettings.getBoolean("EnableWarehouseSortingClan", false);
-		L2JMOD_ENABLE_WAREHOUSESORTING_PRIVATE = L2JModSettings.getBoolean("EnableWarehouseSortingPrivate", false);
-		
-		if (TVT_EVENT_PARTICIPATION_NPC_ID == 0) {
-			TVT_EVENT_ENABLED = false;
-			LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventParticipationNpcId");
-		} else {
-			String[] tvtNpcCoords = L2JModSettings.getString("TvTEventParticipationNpcCoordinates", "0,0,0").split(",");
-			if (tvtNpcCoords.length < 3) {
-				TVT_EVENT_ENABLED = false;
-				LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventParticipationNpcCoordinates");
-			} else {
-				TVT_EVENT_REWARDS = new ArrayList<>();
-				TVT_DOORS_IDS_TO_OPEN = new ArrayList<>();
-				TVT_DOORS_IDS_TO_CLOSE = new ArrayList<>();
-				TVT_EVENT_PARTICIPATION_NPC_COORDINATES = new int[4];
-				TVT_EVENT_TEAM_1_COORDINATES = new int[3];
-				TVT_EVENT_TEAM_2_COORDINATES = new int[3];
-				TVT_EVENT_PARTICIPATION_NPC_COORDINATES[0] = Integer.parseInt(tvtNpcCoords[0]);
-				TVT_EVENT_PARTICIPATION_NPC_COORDINATES[1] = Integer.parseInt(tvtNpcCoords[1]);
-				TVT_EVENT_PARTICIPATION_NPC_COORDINATES[2] = Integer.parseInt(tvtNpcCoords[2]);
-				if (tvtNpcCoords.length == 4) {
-					TVT_EVENT_PARTICIPATION_NPC_COORDINATES[3] = Integer.parseInt(tvtNpcCoords[3]);
-				}
-				TVT_EVENT_MIN_PLAYERS_IN_TEAMS = L2JModSettings.getInt("TvTEventMinPlayersInTeams", 1);
-				TVT_EVENT_MAX_PLAYERS_IN_TEAMS = L2JModSettings.getInt("TvTEventMaxPlayersInTeams", 20);
-				TVT_EVENT_MIN_LVL = L2JModSettings.getByte("TvTEventMinPlayerLevel", (byte) 1);
-				TVT_EVENT_MAX_LVL = L2JModSettings.getByte("TvTEventMaxPlayerLevel", (byte) 80);
-				TVT_EVENT_RESPAWN_TELEPORT_DELAY = L2JModSettings.getInt("TvTEventRespawnTeleportDelay", 20);
-				TVT_EVENT_START_LEAVE_TELEPORT_DELAY = L2JModSettings.getInt("TvTEventStartLeaveTeleportDelay", 20);
-				TVT_EVENT_EFFECTS_REMOVAL = L2JModSettings.getInt("TvTEventEffectsRemoval", 0);
-				TVT_EVENT_MAX_PARTICIPANTS_PER_IP = L2JModSettings.getInt("TvTEventMaxParticipantsPerIP", 0);
-				TVT_ALLOW_VOICED_COMMAND = L2JModSettings.getBoolean("TvTAllowVoicedInfoCommand", false);
-				TVT_EVENT_TEAM_1_NAME = L2JModSettings.getString("TvTEventTeam1Name", "Team1");
-				tvtNpcCoords = L2JModSettings.getString("TvTEventTeam1Coordinates", "0,0,0").split(",");
-				if (tvtNpcCoords.length < 3) {
-					TVT_EVENT_ENABLED = false;
-					LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventTeam1Coordinates");
-				} else {
-					TVT_EVENT_TEAM_1_COORDINATES[0] = Integer.parseInt(tvtNpcCoords[0]);
-					TVT_EVENT_TEAM_1_COORDINATES[1] = Integer.parseInt(tvtNpcCoords[1]);
-					TVT_EVENT_TEAM_1_COORDINATES[2] = Integer.parseInt(tvtNpcCoords[2]);
-					TVT_EVENT_TEAM_2_NAME = L2JModSettings.getString("TvTEventTeam2Name", "Team2");
-					tvtNpcCoords = L2JModSettings.getString("TvTEventTeam2Coordinates", "0,0,0").split(",");
-					if (tvtNpcCoords.length < 3) {
-						TVT_EVENT_ENABLED = false;
-						LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventTeam2Coordinates");
-					} else {
-						TVT_EVENT_TEAM_2_COORDINATES[0] = Integer.parseInt(tvtNpcCoords[0]);
-						TVT_EVENT_TEAM_2_COORDINATES[1] = Integer.parseInt(tvtNpcCoords[1]);
-						TVT_EVENT_TEAM_2_COORDINATES[2] = Integer.parseInt(tvtNpcCoords[2]);
-						tvtNpcCoords = L2JModSettings.getString("TvTEventParticipationFee", "0,0").split(",");
-						try {
-							TVT_EVENT_PARTICIPATION_FEE[0] = Integer.parseInt(tvtNpcCoords[0]);
-							TVT_EVENT_PARTICIPATION_FEE[1] = Integer.parseInt(tvtNpcCoords[1]);
-						} catch (NumberFormatException nfe) {
-							if (tvtNpcCoords.length > 0) {
-								LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventParticipationFee");
-							}
-						}
-						tvtNpcCoords = L2JModSettings.getString("TvTEventReward", "57,100000").split(";");
-						for (String reward : tvtNpcCoords) {
-							String[] rewardSplit = reward.split(",");
-							if (rewardSplit.length != 2) {
-								LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventReward {}", reward);
-							} else {
-								try {
-									TVT_EVENT_REWARDS.add(new int[] {
-										Integer.parseInt(rewardSplit[0]),
-										Integer.parseInt(rewardSplit[1])
-									});
-								} catch (NumberFormatException nfe) {
-									if (!reward.isEmpty()) {
-										LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventReward {}", reward);
-									}
-								}
-							}
-						}
-						
-						TVT_EVENT_TARGET_TEAM_MEMBERS_ALLOWED = L2JModSettings.getBoolean("TvTEventTargetTeamMembersAllowed", true);
-						TVT_EVENT_SCROLL_ALLOWED = L2JModSettings.getBoolean("TvTEventScrollsAllowed", false);
-						TVT_EVENT_POTIONS_ALLOWED = L2JModSettings.getBoolean("TvTEventPotionsAllowed", false);
-						TVT_EVENT_SUMMON_BY_ITEM_ALLOWED = L2JModSettings.getBoolean("TvTEventSummonByItemAllowed", false);
-						TVT_REWARD_TEAM_TIE = L2JModSettings.getBoolean("TvTRewardTeamTie", false);
-						tvtNpcCoords = L2JModSettings.getString("TvTDoorsToOpen", "").split(";");
-						for (String door : tvtNpcCoords) {
-							try {
-								TVT_DOORS_IDS_TO_OPEN.add(Integer.parseInt(door));
-							} catch (NumberFormatException nfe) {
-								if (!door.isEmpty()) {
-									LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTDoorsToOpen {}", door);
-								}
-							}
-						}
-						
-						tvtNpcCoords = L2JModSettings.getString("TvTDoorsToClose", "").split(";");
-						for (String door : tvtNpcCoords) {
-							try {
-								TVT_DOORS_IDS_TO_CLOSE.add(Integer.parseInt(door));
-							} catch (NumberFormatException nfe) {
-								if (!door.isEmpty()) {
-									LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTDoorsToClose {}", door);
-								}
-							}
-						}
-						
-						tvtNpcCoords = L2JModSettings.getString("TvTEventFighterBuffs", "").split(";");
-						if (!tvtNpcCoords[0].isEmpty()) {
-							TVT_EVENT_FIGHTER_BUFFS = new HashMap<>(tvtNpcCoords.length);
-							for (String skill : tvtNpcCoords) {
-								String[] skillSplit = skill.split(",");
-								if (skillSplit.length != 2) {
-									LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventFighterBuffs {}", skill);
-								} else {
-									try {
-										TVT_EVENT_FIGHTER_BUFFS.put(Integer.parseInt(skillSplit[0]), Integer.parseInt(skillSplit[1]));
-									} catch (NumberFormatException nfe) {
-										if (!skill.isEmpty()) {
-											LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventFighterBuffs {}", skill);
-										}
-									}
-								}
-							}
-						}
-						
-						tvtNpcCoords = L2JModSettings.getString("TvTEventMageBuffs", "").split(";");
-						if (!tvtNpcCoords[0].isEmpty()) {
-							TVT_EVENT_MAGE_BUFFS = new HashMap<>(tvtNpcCoords.length);
-							for (String skill : tvtNpcCoords) {
-								String[] skillSplit = skill.split(",");
-								if (skillSplit.length != 2) {
-									LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventMageBuffs {}", skill);
-								} else {
-									try {
-										TVT_EVENT_MAGE_BUFFS.put(Integer.parseInt(skillSplit[0]), Integer.parseInt(skillSplit[1]));
-									} catch (NumberFormatException nfe) {
-										if (!skill.isEmpty()) {
-											LOG.warn("TvTEventEngine[Config.load()]: invalid config property -> TvTEventMageBuffs {}", skill);
-										}
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-		
-		BANKING_SYSTEM_ENABLED = L2JModSettings.getBoolean("BankingEnabled", false);
-		BANKING_SYSTEM_GOLDBARS = L2JModSettings.getInt("BankingGoldbarCount", 1);
-		BANKING_SYSTEM_ADENA = L2JModSettings.getInt("BankingAdenaCount", 500000000);
-		
-		OFFLINE_TRADE_ENABLE = L2JModSettings.getBoolean("OfflineTradeEnable", false);
-		OFFLINE_CRAFT_ENABLE = L2JModSettings.getBoolean("OfflineCraftEnable", false);
-		OFFLINE_MODE_IN_PEACE_ZONE = L2JModSettings.getBoolean("OfflineModeInPeaceZone", false);
-		OFFLINE_MODE_NO_DAMAGE = L2JModSettings.getBoolean("OfflineModeNoDamage", false);
-		OFFLINE_SET_NAME_COLOR = L2JModSettings.getBoolean("OfflineSetNameColor", false);
-		OFFLINE_NAME_COLOR = Integer.decode("0x" + L2JModSettings.getString("OfflineNameColor", "808080"));
-		OFFLINE_FAME = L2JModSettings.getBoolean("OfflineFame", true);
-		RESTORE_OFFLINERS = L2JModSettings.getBoolean("RestoreOffliners", false);
-		OFFLINE_MAX_DAYS = L2JModSettings.getInt("OfflineMaxDays", 10);
-		OFFLINE_DISCONNECT_FINISHED = L2JModSettings.getBoolean("OfflineDisconnectFinished", true);
-		
-		L2JMOD_ENABLE_MANA_POTIONS_SUPPORT = L2JModSettings.getBoolean("EnableManaPotionSupport", false);
-		
-		L2JMOD_DISPLAY_SERVER_TIME = L2JModSettings.getBoolean("DisplayServerTime", false);
-		
-		WELCOME_MESSAGE_ENABLED = L2JModSettings.getBoolean("ScreenWelcomeMessageEnable", false);
-		WELCOME_MESSAGE_TEXT = L2JModSettings.getString("ScreenWelcomeMessageText", "Welcome to L2J server!");
-		WELCOME_MESSAGE_TIME = L2JModSettings.getInt("ScreenWelcomeMessageTime", 10) * 1000;
-		
-		L2JMOD_ANTIFEED_ENABLE = L2JModSettings.getBoolean("AntiFeedEnable", false);
-		L2JMOD_ANTIFEED_DUALBOX = L2JModSettings.getBoolean("AntiFeedDualbox", true);
-		L2JMOD_ANTIFEED_DISCONNECTED_AS_DUALBOX = L2JModSettings.getBoolean("AntiFeedDisconnectedAsDualbox", true);
-		L2JMOD_ANTIFEED_INTERVAL = L2JModSettings.getInt("AntiFeedInterval", 120) * 1000;
-		ANNOUNCE_PK_PVP = L2JModSettings.getBoolean("AnnouncePkPvP", false);
-		ANNOUNCE_PK_PVP_NORMAL_MESSAGE = L2JModSettings.getBoolean("AnnouncePkPvPNormalMessage", true);
-		ANNOUNCE_PK_MSG = L2JModSettings.getString("AnnouncePkMsg", "$killer has slaughtered $target");
-		ANNOUNCE_PVP_MSG = L2JModSettings.getString("AnnouncePvpMsg", "$killer has defeated $target");
-		
-		L2JMOD_CHAT_ADMIN = L2JModSettings.getBoolean("ChatAdmin", false);
-		
-		L2JMOD_MULTILANG_DEFAULT = L2JModSettings.getString("MultiLangDefault", "en");
-		L2JMOD_MULTILANG_ENABLE = L2JModSettings.getBoolean("MultiLangEnable", false);
-		String[] allowed = L2JModSettings.getString("MultiLangAllowed", L2JMOD_MULTILANG_DEFAULT).split(";");
-		L2JMOD_MULTILANG_ALLOWED = new ArrayList<>(allowed.length);
-		for (String lang : allowed) {
-			L2JMOD_MULTILANG_ALLOWED.add(lang);
-		}
-		
-		if (!L2JMOD_MULTILANG_ALLOWED.contains(L2JMOD_MULTILANG_DEFAULT)) {
-			LOG.warn("MultiLang[Config.load()]: default language: {} is not in allowed list !", L2JMOD_MULTILANG_DEFAULT);
-		}
-		
-		L2JMOD_HELLBOUND_STATUS = L2JModSettings.getBoolean("HellboundStatus", false);
-		L2JMOD_MULTILANG_VOICED_ALLOW = L2JModSettings.getBoolean("MultiLangVoiceCommand", true);
-		L2JMOD_MULTILANG_SM_ENABLE = L2JModSettings.getBoolean("MultiLangSystemMessageEnable", false);
-		allowed = L2JModSettings.getString("MultiLangSystemMessageAllowed", "").split(";");
-		L2JMOD_MULTILANG_SM_ALLOWED = new ArrayList<>(allowed.length);
-		for (String lang : allowed) {
-			if (!lang.isEmpty()) {
-				L2JMOD_MULTILANG_SM_ALLOWED.add(lang);
-			}
-		}
-		L2JMOD_MULTILANG_NS_ENABLE = L2JModSettings.getBoolean("MultiLangNpcStringEnable", false);
-		allowed = L2JModSettings.getString("MultiLangNpcStringAllowed", "").split(";");
-		L2JMOD_MULTILANG_NS_ALLOWED = new ArrayList<>(allowed.length);
-		for (String lang : allowed) {
-			if (!lang.isEmpty()) {
-				L2JMOD_MULTILANG_NS_ALLOWED.add(lang);
-			}
-		}
-		
-		L2WALKER_PROTECTION = L2JModSettings.getBoolean("L2WalkerProtection", false);
-		L2JMOD_DEBUG_VOICE_COMMAND = L2JModSettings.getBoolean("DebugVoiceCommand", false);
-		
-		L2JMOD_DUALBOX_CHECK_MAX_PLAYERS_PER_IP = L2JModSettings.getInt("DualboxCheckMaxPlayersPerIP", 0);
-		L2JMOD_DUALBOX_CHECK_MAX_OLYMPIAD_PARTICIPANTS_PER_IP = L2JModSettings.getInt("DualboxCheckMaxOlympiadParticipantsPerIP", 0);
-		L2JMOD_DUALBOX_CHECK_MAX_L2EVENT_PARTICIPANTS_PER_IP = L2JModSettings.getInt("DualboxCheckMaxL2EventParticipantsPerIP", 0);
-		String[] dualboxCheckWhiteList = L2JModSettings.getString("DualboxCheckWhitelist", "127.0.0.1,0").split(";");
-		L2JMOD_DUALBOX_CHECK_WHITELIST = new HashMap<>(dualboxCheckWhiteList.length);
-		for (String entry : dualboxCheckWhiteList) {
-			String[] entrySplit = entry.split(",");
-			if (entrySplit.length != 2) {
-				LOG.warn("DualboxCheck[Config.load()]: invalid config property -> DualboxCheckWhitelist {}", entry);
-			} else {
-				try {
-					int num = Integer.parseInt(entrySplit[1]);
-					num = (num == 0) ? -1 : num;
-					L2JMOD_DUALBOX_CHECK_WHITELIST.put(InetAddress.getByName(entrySplit[0]).hashCode(), num);
-				} catch (UnknownHostException e) {
-					LOG.warn("DualboxCheck[Config.load()]: invalid address -> DualboxCheckWhitelist {}", entrySplit[0]);
-				} catch (NumberFormatException e) {
-					LOG.warn("DualboxCheck[Config.load()]: invalid number -> DualboxCheckWhitelist {}", entrySplit[1]);
-				}
-			}
-		}
-		L2JMOD_ALLOW_CHANGE_PASSWORD = L2JModSettings.getBoolean("AllowChangePassword", false);
-		
-		// Load PvP L2Properties file (if exists)
-		final PropertiesParser PVPSettings = new PropertiesParser(PVP_CONFIG_FILE);
-		
-		KARMA_DROP_GM = PVPSettings.getBoolean("CanGMDropEquipment", false);
-		KARMA_AWARD_PK_KILL = PVPSettings.getBoolean("AwardPKKillPVPPoint", false);
-		KARMA_PK_LIMIT = PVPSettings.getInt("MinimumPKRequiredToDrop", 5);
-		KARMA_NONDROPPABLE_PET_ITEMS = PVPSettings.getString("ListOfPetItems", "2375,3500,3501,3502,4422,4423,4424,4425,6648,6649,6650,9882");
-		KARMA_NONDROPPABLE_ITEMS = PVPSettings.getString("ListOfNonDroppableItems", "57,1147,425,1146,461,10,2368,7,6,2370,2369,6842,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,7694,8181,5575,7694,9388,9389,9390");
-		
-		String[] karma = KARMA_NONDROPPABLE_PET_ITEMS.split(",");
-		KARMA_LIST_NONDROPPABLE_PET_ITEMS = new int[karma.length];
-		
-		for (int i = 0; i < karma.length; i++) {
-			KARMA_LIST_NONDROPPABLE_PET_ITEMS[i] = Integer.parseInt(karma[i]);
-		}
-		
-		karma = KARMA_NONDROPPABLE_ITEMS.split(",");
-		KARMA_LIST_NONDROPPABLE_ITEMS = new int[karma.length];
-		
-		for (int i = 0; i < karma.length; i++) {
-			KARMA_LIST_NONDROPPABLE_ITEMS[i] = Integer.parseInt(karma[i]);
-		}
-		
-		// sorting so binarySearch can be used later
-		Arrays.sort(KARMA_LIST_NONDROPPABLE_PET_ITEMS);
-		Arrays.sort(KARMA_LIST_NONDROPPABLE_ITEMS);
-		
-		PVP_NORMAL_TIME = PVPSettings.getInt("PvPVsNormalTime", 120000);
-		PVP_PVP_TIME = PVPSettings.getInt("PvPVsPvPTime", 60000);
-		
-		// Load Olympiad L2Properties file (if exists)
-		final PropertiesParser Olympiad = new PropertiesParser(OLYMPIAD_CONFIG_FILE);
-		
-		ALT_OLY_START_TIME = Olympiad.getInt("AltOlyStartTime", 18);
-		ALT_OLY_MIN = Olympiad.getInt("AltOlyMin", 0);
-		ALT_OLY_MAX_BUFFS = Olympiad.getInt("AltOlyMaxBuffs", 5);
-		ALT_OLY_CPERIOD = Olympiad.getLong("AltOlyCPeriod", 21600000);
-		ALT_OLY_BATTLE = Olympiad.getLong("AltOlyBattle", 300000);
-		ALT_OLY_WPERIOD = Olympiad.getLong("AltOlyWPeriod", 604800000);
-		ALT_OLY_VPERIOD = Olympiad.getLong("AltOlyVPeriod", 86400000);
-		ALT_OLY_START_POINTS = Olympiad.getInt("AltOlyStartPoints", 10);
-		ALT_OLY_WEEKLY_POINTS = Olympiad.getInt("AltOlyWeeklyPoints", 10);
-		ALT_OLY_CLASSED = Olympiad.getInt("AltOlyClassedParticipants", 11);
-		ALT_OLY_NONCLASSED = Olympiad.getInt("AltOlyNonClassedParticipants", 11);
-		ALT_OLY_TEAMS = Olympiad.getInt("AltOlyTeamsParticipants", 6);
-		ALT_OLY_REG_DISPLAY = Olympiad.getInt("AltOlyRegistrationDisplayNumber", 100);
-		ALT_OLY_CLASSED_REWARD = parseItemsList(Olympiad.getString("AltOlyClassedReward", "13722,50"));
-		ALT_OLY_NONCLASSED_REWARD = parseItemsList(Olympiad.getString("AltOlyNonClassedReward", "13722,40"));
-		ALT_OLY_TEAM_REWARD = parseItemsList(Olympiad.getString("AltOlyTeamReward", "13722,85"));
-		ALT_OLY_COMP_RITEM = Olympiad.getInt("AltOlyCompRewItem", 13722);
-		ALT_OLY_MIN_MATCHES = Olympiad.getInt("AltOlyMinMatchesForPoints", 15);
-		ALT_OLY_GP_PER_POINT = Olympiad.getInt("AltOlyGPPerPoint", 1000);
-		ALT_OLY_HERO_POINTS = Olympiad.getInt("AltOlyHeroPoints", 200);
-		ALT_OLY_RANK1_POINTS = Olympiad.getInt("AltOlyRank1Points", 100);
-		ALT_OLY_RANK2_POINTS = Olympiad.getInt("AltOlyRank2Points", 75);
-		ALT_OLY_RANK3_POINTS = Olympiad.getInt("AltOlyRank3Points", 55);
-		ALT_OLY_RANK4_POINTS = Olympiad.getInt("AltOlyRank4Points", 40);
-		ALT_OLY_RANK5_POINTS = Olympiad.getInt("AltOlyRank5Points", 30);
-		ALT_OLY_MAX_POINTS = Olympiad.getInt("AltOlyMaxPoints", 10);
-		ALT_OLY_DIVIDER_CLASSED = Olympiad.getInt("AltOlyDividerClassed", 5);
-		ALT_OLY_DIVIDER_NON_CLASSED = Olympiad.getInt("AltOlyDividerNonClassed", 5);
-		ALT_OLY_MAX_WEEKLY_MATCHES = Olympiad.getInt("AltOlyMaxWeeklyMatches", 70);
-		ALT_OLY_MAX_WEEKLY_MATCHES_NON_CLASSED = Olympiad.getInt("AltOlyMaxWeeklyMatchesNonClassed", 60);
-		ALT_OLY_MAX_WEEKLY_MATCHES_CLASSED = Olympiad.getInt("AltOlyMaxWeeklyMatchesClassed", 30);
-		ALT_OLY_MAX_WEEKLY_MATCHES_TEAM = Olympiad.getInt("AltOlyMaxWeeklyMatchesTeam", 10);
-		ALT_OLY_LOG_FIGHTS = Olympiad.getBoolean("AltOlyLogFights", false);
-		ALT_OLY_SHOW_MONTHLY_WINNERS = Olympiad.getBoolean("AltOlyShowMonthlyWinners", true);
-		ALT_OLY_ANNOUNCE_GAMES = Olympiad.getBoolean("AltOlyAnnounceGames", true);
-		String[] olyRestrictedItems = Olympiad.getString("AltOlyRestrictedItems", "6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,9388,9389,9390,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,20759,20775,20776,20777,20778,14774").split(",");
-		LIST_OLY_RESTRICTED_ITEMS = new ArrayList<>(olyRestrictedItems.length);
-		for (String id : olyRestrictedItems) {
-			LIST_OLY_RESTRICTED_ITEMS.add(Integer.parseInt(id));
-		}
-		ALT_OLY_ENCHANT_LIMIT = Olympiad.getInt("AltOlyEnchantLimit", -1);
-		ALT_OLY_WAIT_TIME = Olympiad.getInt("AltOlyWaitTime", 120);
-		
-		final File hexIdFile = new File(HEXID_FILE);
-		if (hexIdFile.exists()) {
-			final PropertiesParser hexId = new PropertiesParser(hexIdFile);
-			
-			if (hexId.containskey("ServerID") && hexId.containskey("HexID")) {
-				SERVER_ID = hexId.getInt("ServerID", 1);
-				try {
-					HEX_ID = new BigInteger(hexId.getString("HexID", null), 16).toByteArray();
-				} catch (Exception e) {
-					LOG.warn("Could not load HexID file ({}). Hopefully login will give us one.", HEXID_FILE);
-				}
-			} else {
-				LOG.warn("Could not load HexID file ({}). Hopefully login will give us one.", HEXID_FILE);
-			}
-		} else {
-			LOG.warn("Could not load HexID file ({}). Hopefully login will give us one.", HEXID_FILE);
-		}
-		
-		// Grand bosses
-		final PropertiesParser GrandBossSettings = new PropertiesParser(GRANDBOSS_CONFIG_FILE);
-		
-		ANTHARAS_WAIT_TIME = GrandBossSettings.getInt("AntharasWaitTime", 30);
-		ANTHARAS_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfAntharasSpawn", 264);
-		ANTHARAS_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfAntharasSpawn", 72);
-		
-		VALAKAS_WAIT_TIME = GrandBossSettings.getInt("ValakasWaitTime", 30);
-		VALAKAS_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfValakasSpawn", 264);
-		VALAKAS_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfValakasSpawn", 72);
-		
-		BAIUM_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfBaiumSpawn", 168);
-		BAIUM_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfBaiumSpawn", 48);
-		
-		CORE_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfCoreSpawn", 60);
-		CORE_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfCoreSpawn", 24);
-		
-		ORFEN_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfOrfenSpawn", 48);
-		ORFEN_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfOrfenSpawn", 20);
-		
-		QUEEN_ANT_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfQueenAntSpawn", 36);
-		QUEEN_ANT_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfQueenAntSpawn", 17);
-		
-		BELETH_SPAWN_INTERVAL = GrandBossSettings.getInt("IntervalOfBelethSpawn", 192);
-		BELETH_SPAWN_RANDOM = GrandBossSettings.getInt("RandomOfBelethSpawn", 148);
-		BELETH_MIN_PLAYERS = GrandBossSettings.getInt("BelethMinPlayers", 36);
-		
-		// Gracia Seeds
-		final PropertiesParser GraciaSeedsSettings = new PropertiesParser(GRACIASEEDS_CONFIG_FILE);
-		
-		// Seed of Destruction
-		SOD_TIAT_KILL_COUNT = GraciaSeedsSettings.getInt("TiatKillCountForNextState", 10);
-		SOD_STAGE_2_LENGTH = GraciaSeedsSettings.getLong("Stage2Length", 720) * 60000;
-		
-		try {
-			//@formatter:off
-				FILTER_LIST = Files.lines(Paths.get(CHAT_FILTER_FILE), StandardCharsets.UTF_8)
-					.map(String::trim)
-					.filter(line -> (!line.isEmpty() && (line.charAt(0) != '#')))
-					.collect(Collectors.toList());
-				//@formatter:on
-			LOG.info("Loaded {} filter words.", FILTER_LIST.size());
-		} catch (IOException ioe) {
-			LOG.warn("Error while loading chat filter words!", ioe);
-		}
-		
-		final PropertiesParser ClanHallSiege = new PropertiesParser(CH_SIEGE_FILE);
-		
-		CHS_MAX_ATTACKERS = ClanHallSiege.getInt("MaxAttackers", 500);
-		CHS_CLAN_MINLEVEL = ClanHallSiege.getInt("MinClanLevel", 4);
-		CHS_MAX_FLAGS_PER_CLAN = ClanHallSiege.getInt("MaxFlagsPerClan", 1);
-		CHS_ENABLE_FAME = ClanHallSiege.getBoolean("EnableFame", false);
-		CHS_FAME_AMOUNT = ClanHallSiege.getInt("FameAmount", 0);
-		CHS_FAME_FREQUENCY = ClanHallSiege.getInt("FameFrequency", 0);
-		
-		final PropertiesParser geoData = new PropertiesParser(GEODATA_FILE);
-		
-		try {
-			PATHNODE_DIR = new File(geoData.getString("PathnodeDirectory", "data/pathnode").replaceAll("\\\\", "/")).getCanonicalFile();
-		} catch (IOException e) {
-			LOG.warn("Error setting pathnode directory!", e);
-			PATHNODE_DIR = new File("data/pathnode");
-		}
-		
-		PATHFINDING = geoData.getInt("PathFinding", 0);
-		PATHFIND_BUFFERS = geoData.getString("PathFindBuffers", "100x6;128x6;192x6;256x4;320x4;384x4;500x2");
-		LOW_WEIGHT = geoData.getFloat("LowWeight", 0.5f);
-		MEDIUM_WEIGHT = geoData.getFloat("MediumWeight", 2);
-		HIGH_WEIGHT = geoData.getFloat("HighWeight", 3);
-		ADVANCED_DIAGONAL_STRATEGY = geoData.getBoolean("AdvancedDiagonalStrategy", true);
-		DIAGONAL_WEIGHT = geoData.getFloat("DiagonalWeight", 0.707f);
-		MAX_POSTFILTER_PASSES = geoData.getInt("MaxPostfilterPasses", 3);
-		DEBUG_PATH = geoData.getBoolean("DebugPath", false);
-		FORCE_GEODATA = geoData.getBoolean("ForceGeoData", true);
-		COORD_SYNCHRONIZE = geoData.getInt("CoordSynchronize", -1);
-		GEODATA_PATH = Paths.get(geoData.getString("GeoDataPath", "./data/geodata"));
-		TRY_LOAD_UNSPECIFIED_REGIONS = geoData.getBoolean("TryLoadUnspecifiedRegions", true);
-		GEODATA_REGIONS = new HashMap<>();
-		for (int regionX = L2World.TILE_X_MIN; regionX <= L2World.TILE_X_MAX; regionX++) {
-			for (int regionY = L2World.TILE_Y_MIN; regionY <= L2World.TILE_Y_MAX; regionY++) {
-				String key = regionX + "_" + regionY;
-				if (geoData.containskey(regionX + "_" + regionY)) {
-					GEODATA_REGIONS.put(key, geoData.getBoolean(key, false));
-				}
-			}
-		}
-	}
-	
-	/**
-	 * Set a new value to a config parameter.
-	 * @param pName the name of the parameter whose value to change
-	 * @param pValue the new value of the parameter
-	 * @return {@code true} if the value of the parameter was changed, {@code false} otherwise
-	 */
-	public static boolean setParameterValue(String pName, String pValue) {
-		switch (pName.trim().toLowerCase()) {
-			// rates.properties
-			case "ratexp":
-				RATE_XP = Float.parseFloat(pValue);
-				break;
-			case "ratesp":
-				RATE_SP = Float.parseFloat(pValue);
-				break;
-			case "ratepartyxp":
-				RATE_PARTY_XP = Float.parseFloat(pValue);
-				break;
-			case "rateextractable":
-				RATE_EXTRACTABLE = Float.parseFloat(pValue);
-				break;
-			case "ratedropadena":
-				RATE_DROP_AMOUNT_MULTIPLIER.put(Inventory.ADENA_ID, Float.parseFloat(pValue));
-				break;
-			case "ratedropmanor":
-				RATE_DROP_MANOR = Integer.parseInt(pValue);
-				break;
-			case "ratequestdrop":
-				RATE_QUEST_DROP = Float.parseFloat(pValue);
-				break;
-			case "ratequestreward":
-				RATE_QUEST_REWARD = Float.parseFloat(pValue);
-				break;
-			case "ratequestrewardxp":
-				RATE_QUEST_REWARD_XP = Float.parseFloat(pValue);
-				break;
-			case "ratequestrewardsp":
-				RATE_QUEST_REWARD_SP = Float.parseFloat(pValue);
-				break;
-			case "ratequestrewardadena":
-				RATE_QUEST_REWARD_ADENA = Float.parseFloat(pValue);
-				break;
-			case "usequestrewardmultipliers":
-				RATE_QUEST_REWARD_USE_MULTIPLIERS = Boolean.parseBoolean(pValue);
-				break;
-			case "ratequestrewardpotion":
-				RATE_QUEST_REWARD_POTION = Float.parseFloat(pValue);
-				break;
-			case "ratequestrewardscroll":
-				RATE_QUEST_REWARD_SCROLL = Float.parseFloat(pValue);
-				break;
-			case "ratequestrewardrecipe":
-				RATE_QUEST_REWARD_RECIPE = Float.parseFloat(pValue);
-				break;
-			case "ratequestrewardmaterial":
-				RATE_QUEST_REWARD_MATERIAL = Float.parseFloat(pValue);
-				break;
-			case "ratehellboundtrustincrease":
-				RATE_HB_TRUST_INCREASE = Float.parseFloat(pValue);
-				break;
-			case "ratehellboundtrustdecrease":
-				RATE_HB_TRUST_DECREASE = Float.parseFloat(pValue);
-				break;
-			case "ratevitalitylevel1":
-				RATE_VITALITY_LEVEL_1 = Float.parseFloat(pValue);
-				break;
-			case "ratevitalitylevel2":
-				RATE_VITALITY_LEVEL_2 = Float.parseFloat(pValue);
-				break;
-			case "ratevitalitylevel3":
-				RATE_VITALITY_LEVEL_3 = Float.parseFloat(pValue);
-				break;
-			case "ratevitalitylevel4":
-				RATE_VITALITY_LEVEL_4 = Float.parseFloat(pValue);
-				break;
-			case "raterecoverypeacezone":
-				RATE_RECOVERY_VITALITY_PEACE_ZONE = Float.parseFloat(pValue);
-				break;
-			case "ratevitalitylost":
-				RATE_VITALITY_LOST = Float.parseFloat(pValue);
-				break;
-			case "ratevitalitygain":
-				RATE_VITALITY_GAIN = Float.parseFloat(pValue);
-				break;
-			case "raterecoveryonreconnect":
-				RATE_RECOVERY_ON_RECONNECT = Float.parseFloat(pValue);
-				break;
-			case "ratekarmaexplost":
-				RATE_KARMA_EXP_LOST = Float.parseFloat(pValue);
-				break;
-			case "ratesiegeguardsprice":
-				RATE_SIEGE_GUARDS_PRICE = Float.parseFloat(pValue);
-				break;
-			case "ratecommonherbs":
-				RATE_DROP_COMMON_HERBS = Float.parseFloat(pValue);
-				break;
-			case "ratehpherbs":
-				RATE_DROP_HP_HERBS = Float.parseFloat(pValue);
-				break;
-			case "ratempherbs":
-				RATE_DROP_MP_HERBS = Float.parseFloat(pValue);
-				break;
-			case "ratespecialherbs":
-				RATE_DROP_SPECIAL_HERBS = Float.parseFloat(pValue);
-				break;
-			case "ratevitalityherbs":
-				RATE_DROP_VITALITY_HERBS = Float.parseFloat(pValue);
-				break;
-			case "playerdroplimit":
-				PLAYER_DROP_LIMIT = Integer.parseInt(pValue);
-				break;
-			case "playerratedrop":
-				PLAYER_RATE_DROP = Integer.parseInt(pValue);
-				break;
-			case "playerratedropitem":
-				PLAYER_RATE_DROP_ITEM = Integer.parseInt(pValue);
-				break;
-			case "playerratedropequip":
-				PLAYER_RATE_DROP_EQUIP = Integer.parseInt(pValue);
-				break;
-			case "playerratedropequipweapon":
-				PLAYER_RATE_DROP_EQUIP_WEAPON = Integer.parseInt(pValue);
-				break;
-			case "petxprate":
-				PET_XP_RATE = Float.parseFloat(pValue);
-				break;
-			case "petfoodrate":
-				PET_FOOD_RATE = Integer.parseInt(pValue);
-				break;
-			case "sineaterxprate":
-				SINEATER_XP_RATE = Float.parseFloat(pValue);
-				break;
-			case "karmadroplimit":
-				KARMA_DROP_LIMIT = Integer.parseInt(pValue);
-				break;
-			case "karmaratedrop":
-				KARMA_RATE_DROP = Integer.parseInt(pValue);
-				break;
-			case "karmaratedropitem":
-				KARMA_RATE_DROP_ITEM = Integer.parseInt(pValue);
-				break;
-			case "karmaratedropequip":
-				KARMA_RATE_DROP_EQUIP = Integer.parseInt(pValue);
-				break;
-			case "karmaratedropequipweapon":
-				KARMA_RATE_DROP_EQUIP_WEAPON = Integer.parseInt(pValue);
-				break;
-			case "autodestroydroppeditemafter":
-				AUTODESTROY_ITEM_AFTER = Integer.parseInt(pValue);
-				break;
-			case "destroyplayerdroppeditem":
-				DESTROY_DROPPED_PLAYER_ITEM = Boolean.parseBoolean(pValue);
-				break;
-			case "destroyequipableitem":
-				DESTROY_EQUIPABLE_PLAYER_ITEM = Boolean.parseBoolean(pValue);
-				break;
-			case "savedroppeditem":
-				SAVE_DROPPED_ITEM = Boolean.parseBoolean(pValue);
-				break;
-			case "emptydroppeditemtableafterload":
-				EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD = Boolean.parseBoolean(pValue);
-				break;
-			case "savedroppediteminterval":
-				SAVE_DROPPED_ITEM_INTERVAL = Integer.parseInt(pValue);
-				break;
-			case "cleardroppeditemtable":
-				CLEAR_DROPPED_ITEM_TABLE = Boolean.parseBoolean(pValue);
-				break;
-			case "precisedropcalculation":
-				PRECISE_DROP_CALCULATION = Boolean.parseBoolean(pValue);
-				break;
-			case "multipleitemdrop":
-				MULTIPLE_ITEM_DROP = Boolean.parseBoolean(pValue);
-				break;
-			case "lowweight":
-				LOW_WEIGHT = Float.parseFloat(pValue);
-				break;
-			case "mediumweight":
-				MEDIUM_WEIGHT = Float.parseFloat(pValue);
-				break;
-			case "highweight":
-				HIGH_WEIGHT = Float.parseFloat(pValue);
-				break;
-			case "advanceddiagonalstrategy":
-				ADVANCED_DIAGONAL_STRATEGY = Boolean.parseBoolean(pValue);
-				break;
-			case "diagonalweight":
-				DIAGONAL_WEIGHT = Float.parseFloat(pValue);
-				break;
-			case "maxpostfilterpasses":
-				MAX_POSTFILTER_PASSES = Integer.parseInt(pValue);
-				break;
-			case "coordsynchronize":
-				COORD_SYNCHRONIZE = Integer.parseInt(pValue);
-				break;
-			case "deletecharafterdays":
-				DELETE_DAYS = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuesize":
-				CLIENT_PACKET_QUEUE_SIZE = Integer.parseInt(pValue);
-				if (CLIENT_PACKET_QUEUE_SIZE == 0) {
-					CLIENT_PACKET_QUEUE_SIZE = MMO_MAX_READ_PER_PASS + 1;
-				}
-				break;
-			case "clientpacketqueuemaxburstsize":
-				CLIENT_PACKET_QUEUE_MAX_BURST_SIZE = Integer.parseInt(pValue);
-				if (CLIENT_PACKET_QUEUE_MAX_BURST_SIZE == 0) {
-					CLIENT_PACKET_QUEUE_MAX_BURST_SIZE = MMO_MAX_READ_PER_PASS;
-				}
-				break;
-			case "clientpacketqueuemaxpacketspersecond":
-				CLIENT_PACKET_QUEUE_MAX_PACKETS_PER_SECOND = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuemeasureinterval":
-				CLIENT_PACKET_QUEUE_MEASURE_INTERVAL = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuemaxaveragepacketspersecond":
-				CLIENT_PACKET_QUEUE_MAX_AVERAGE_PACKETS_PER_SECOND = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuemaxfloodspermin":
-				CLIENT_PACKET_QUEUE_MAX_FLOODS_PER_MIN = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuemaxoverflowspermin":
-				CLIENT_PACKET_QUEUE_MAX_OVERFLOWS_PER_MIN = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuemaxunderflowspermin":
-				CLIENT_PACKET_QUEUE_MAX_UNDERFLOWS_PER_MIN = Integer.parseInt(pValue);
-				break;
-			case "clientpacketqueuemaxunknownpermin":
-				CLIENT_PACKET_QUEUE_MAX_UNKNOWN_PER_MIN = Integer.parseInt(pValue);
-				break;
-			case "allowdiscarditem":
-				ALLOW_DISCARDITEM = Boolean.parseBoolean(pValue);
-				break;
-			case "allowrefund":
-				ALLOW_REFUND = Boolean.parseBoolean(pValue);
-				break;
-			case "allowwarehouse":
-				ALLOW_WAREHOUSE = Boolean.parseBoolean(pValue);
-				break;
-			case "allowwear":
-				ALLOW_WEAR = Boolean.parseBoolean(pValue);
-				break;
-			case "weardelay":
-				WEAR_DELAY = Integer.parseInt(pValue);
-				break;
-			case "wearprice":
-				WEAR_PRICE = Integer.parseInt(pValue);
-				break;
-			case "defaultfinishtime":
-				INSTANCE_FINISH_TIME = Integer.parseInt(pValue);
-				break;
-			case "restoreplayerinstance":
-				RESTORE_PLAYER_INSTANCE = Boolean.parseBoolean(pValue);
-				break;
-			case "allowsummonininstance":
-				ALLOW_SUMMON_IN_INSTANCE = Boolean.parseBoolean(pValue);
-				break;
-			case "ejectdeadplayertime":
-				EJECT_DEAD_PLAYER_TIME = Integer.parseInt(pValue);
-				break;
-			case "allowwater":
-				ALLOW_WATER = Boolean.parseBoolean(pValue);
-				break;
-			case "allowrentpet":
-				ALLOW_RENTPET = Boolean.parseBoolean(pValue);
-				break;
-			case "boatbroadcastradius":
-				BOAT_BROADCAST_RADIUS = Integer.parseInt(pValue);
-				break;
-			case "allowcursedweapons":
-				ALLOW_CURSED_WEAPONS = Boolean.parseBoolean(pValue);
-				break;
-			case "allowmanor":
-				ALLOW_MANOR = Boolean.parseBoolean(pValue);
-				break;
-			case "allowpetwalkers":
-				ALLOW_PET_WALKERS = Boolean.parseBoolean(pValue);
-				break;
-			case "enablecommunityboard":
-				ENABLE_COMMUNITY_BOARD = Boolean.parseBoolean(pValue);
-				break;
-			case "bbsdefault":
-				BBS_DEFAULT = pValue;
-				break;
-			case "showservernews":
-				SERVER_NEWS = Boolean.parseBoolean(pValue);
-				break;
-			case "shownpclevel":
-				SHOW_NPC_LVL = Boolean.parseBoolean(pValue);
-				break;
-			case "showcrestwithoutquest":
-				SHOW_CREST_WITHOUT_QUEST = Boolean.parseBoolean(pValue);
-				break;
-			case "forceinventoryupdate":
-				FORCE_INVENTORY_UPDATE = Boolean.parseBoolean(pValue);
-				break;
-			case "autodeleteinvalidquestdata":
-				AUTODELETE_INVALID_QUEST_DATA = Boolean.parseBoolean(pValue);
-				break;
-			case "maximumonlineusers":
-				MAXIMUM_ONLINE_USERS = Integer.parseInt(pValue);
-				break;
-			case "peacezonemode":
-				PEACE_ZONE_MODE = Integer.parseInt(pValue);
-				break;
-			case "checkknownlist":
-				CHECK_KNOWN = Boolean.parseBoolean(pValue);
-				break;
-			case "maxdriftrange":
-				MAX_DRIFT_RANGE = Integer.parseInt(pValue);
-				break;
-			case "usedeepbluedroprules":
-				DEEPBLUE_DROP_RULES = Boolean.parseBoolean(pValue);
-				break;
-			case "usedeepbluedroprulesraid":
-				DEEPBLUE_DROP_RULES_RAID = Boolean.parseBoolean(pValue);
-				break;
-			case "guardattackaggromob":
-				GUARD_ATTACK_AGGRO_MOB = Boolean.parseBoolean(pValue);
-				break;
-			case "maximumslotsfornodwarf":
-				INVENTORY_MAXIMUM_NO_DWARF = Integer.parseInt(pValue);
-				break;
-			case "maximumslotsfordwarf":
-				INVENTORY_MAXIMUM_DWARF = Integer.parseInt(pValue);
-				break;
-			case "maximumslotsforgmplayer":
-				INVENTORY_MAXIMUM_GM = Integer.parseInt(pValue);
-				break;
-			case "maximumslotsforquestitems":
-				INVENTORY_MAXIMUM_QUEST_ITEMS = Integer.parseInt(pValue);
-				break;
-			case "maximumwarehouseslotsfornodwarf":
-				WAREHOUSE_SLOTS_NO_DWARF = Integer.parseInt(pValue);
-				break;
-			case "maximumwarehouseslotsfordwarf":
-				WAREHOUSE_SLOTS_DWARF = Integer.parseInt(pValue);
-				break;
-			case "maximumwarehouseslotsforclan":
-				WAREHOUSE_SLOTS_CLAN = Integer.parseInt(pValue);
-				break;
-			case "enchantchanceelementstone":
-				ENCHANT_CHANCE_ELEMENT_STONE = Double.parseDouble(pValue);
-				break;
-			case "enchantchanceelementcrystal":
-				ENCHANT_CHANCE_ELEMENT_CRYSTAL = Double.parseDouble(pValue);
-				break;
-			case "enchantchanceelementjewel":
-				ENCHANT_CHANCE_ELEMENT_JEWEL = Double.parseDouble(pValue);
-				break;
-			case "enchantchanceelementenergy":
-				ENCHANT_CHANCE_ELEMENT_ENERGY = Double.parseDouble(pValue);
-				break;
-			case "augmentationngskillchance":
-				AUGMENTATION_NG_SKILL_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationngglowchance":
-				AUGMENTATION_NG_GLOW_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationmidskillchance":
-				AUGMENTATION_MID_SKILL_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationmidglowchance":
-				AUGMENTATION_MID_GLOW_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationhighskillchance":
-				AUGMENTATION_HIGH_SKILL_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationhighglowchance":
-				AUGMENTATION_HIGH_GLOW_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationtopskillchance":
-				AUGMENTATION_TOP_SKILL_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationtopglowchance":
-				AUGMENTATION_TOP_GLOW_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "augmentationbasestatchance":
-				AUGMENTATION_BASESTAT_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "hpregenmultiplier":
-				HP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
-				break;
-			case "mpregenmultiplier":
-				MP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
-				break;
-			case "cpregenmultiplier":
-				CP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
-				break;
-			case "raidhpregenmultiplier":
-				RAID_HP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
-				break;
-			case "raidmpregenmultiplier":
-				RAID_MP_REGEN_MULTIPLIER = Double.parseDouble(pValue);
-				break;
-			case "raidpdefencemultiplier":
-				RAID_PDEFENCE_MULTIPLIER = Double.parseDouble(pValue) / 100;
-				break;
-			case "raidmdefencemultiplier":
-				RAID_MDEFENCE_MULTIPLIER = Double.parseDouble(pValue) / 100;
-				break;
-			case "raidpattackmultiplier":
-				RAID_PATTACK_MULTIPLIER = Double.parseDouble(pValue) / 100;
-				break;
-			case "raidmattackmultiplier":
-				RAID_MATTACK_MULTIPLIER = Double.parseDouble(pValue) / 100;
-				break;
-			case "raidminionrespawntime":
-				RAID_MINION_RESPAWN_TIMER = Integer.parseInt(pValue);
-				break;
-			case "raidchaostime":
-				RAID_CHAOS_TIME = Integer.parseInt(pValue);
-				break;
-			case "grandchaostime":
-				GRAND_CHAOS_TIME = Integer.parseInt(pValue);
-				break;
-			case "minionchaostime":
-				MINION_CHAOS_TIME = Integer.parseInt(pValue);
-				break;
-			case "startingadena":
-				STARTING_ADENA = Long.parseLong(pValue);
-				break;
-			case "startinglevel":
-				STARTING_LEVEL = Byte.parseByte(pValue);
-				break;
-			case "startingsp":
-				STARTING_SP = Integer.parseInt(pValue);
-				break;
-			case "unstuckinterval":
-				UNSTUCK_INTERVAL = Integer.parseInt(pValue);
-				break;
-			case "teleportwatchdogtimeout":
-				TELEPORT_WATCHDOG_TIMEOUT = Integer.parseInt(pValue);
-				break;
-			case "playerspawnprotection":
-				PLAYER_SPAWN_PROTECTION = Integer.parseInt(pValue);
-				break;
-			case "playerfakedeathupprotection":
-				PLAYER_FAKEDEATH_UP_PROTECTION = Integer.parseInt(pValue);
-				break;
-			case "partyxpcutoffmethod":
-				PARTY_XP_CUTOFF_METHOD = pValue;
-				break;
-			case "partyxpcutoffpercent":
-				PARTY_XP_CUTOFF_PERCENT = Double.parseDouble(pValue);
-				break;
-			case "partyxpcutofflevel":
-				PARTY_XP_CUTOFF_LEVEL = Integer.parseInt(pValue);
-				break;
-			case "respawnrestorecp":
-				RESPAWN_RESTORE_CP = Double.parseDouble(pValue) / 100;
-				break;
-			case "respawnrestorehp":
-				RESPAWN_RESTORE_HP = Double.parseDouble(pValue) / 100;
-				break;
-			case "respawnrestoremp":
-				RESPAWN_RESTORE_MP = Double.parseDouble(pValue) / 100;
-				break;
-			case "maxpvtstoresellslotsdwarf":
-				MAX_PVTSTORESELL_SLOTS_DWARF = Integer.parseInt(pValue);
-				break;
-			case "maxpvtstoresellslotsother":
-				MAX_PVTSTORESELL_SLOTS_OTHER = Integer.parseInt(pValue);
-				break;
-			case "maxpvtstorebuyslotsdwarf":
-				MAX_PVTSTOREBUY_SLOTS_DWARF = Integer.parseInt(pValue);
-				break;
-			case "maxpvtstorebuyslotsother":
-				MAX_PVTSTOREBUY_SLOTS_OTHER = Integer.parseInt(pValue);
-				break;
-			case "storeskillcooltime":
-				STORE_SKILL_COOLTIME = Boolean.parseBoolean(pValue);
-				break;
-			case "subclassstoreskillcooltime":
-				SUBCLASS_STORE_SKILL_COOLTIME = Boolean.parseBoolean(pValue);
-				break;
-			case "announcemammonspawn":
-				ANNOUNCE_MAMMON_SPAWN = Boolean.parseBoolean(pValue);
-				break;
-			case "enablefallingdamage":
-				ENABLE_FALLING_DAMAGE = Boolean.parseBoolean(pValue);
-				break;
-			case "altgamecreation":
-				ALT_GAME_CREATION = Boolean.parseBoolean(pValue);
-				break;
-			case "altgamecreationspeed":
-				ALT_GAME_CREATION_SPEED = Double.parseDouble(pValue);
-				break;
-			case "altgamecreationxprate":
-				ALT_GAME_CREATION_XP_RATE = Double.parseDouble(pValue);
-				break;
-			case "altgamecreationrarexpsprate":
-				ALT_GAME_CREATION_RARE_XPSP_RATE = Double.parseDouble(pValue);
-				break;
-			case "altgamecreationsprate":
-				ALT_GAME_CREATION_SP_RATE = Double.parseDouble(pValue);
-				break;
-			case "altweightlimit":
-				ALT_WEIGHT_LIMIT = Double.parseDouble(pValue);
-				break;
-			case "altblacksmithuserecipes":
-				ALT_BLACKSMITH_USE_RECIPES = Boolean.parseBoolean(pValue);
-				break;
-			case "altgameskilllearn":
-				ALT_GAME_SKILL_LEARN = Boolean.parseBoolean(pValue);
-				break;
-			case "removecastlecirclets":
-				REMOVE_CASTLE_CIRCLETS = Boolean.parseBoolean(pValue);
-				break;
-			case "reputationscoreperkill":
-				REPUTATION_SCORE_PER_KILL = Integer.parseInt(pValue);
-				break;
-			case "altgamecancelbyhit":
-				ALT_GAME_CANCEL_BOW = pValue.equalsIgnoreCase("bow") || pValue.equalsIgnoreCase("all");
-				ALT_GAME_CANCEL_CAST = pValue.equalsIgnoreCase("cast") || pValue.equalsIgnoreCase("all");
-				break;
-			case "altshieldblocks":
-				ALT_GAME_SHIELD_BLOCKS = Boolean.parseBoolean(pValue);
-				break;
-			case "altperfectshieldblockrate":
-				ALT_PERFECT_SHLD_BLOCK = Integer.parseInt(pValue);
-				break;
-			case "delevel":
-				ALT_GAME_DELEVEL = Boolean.parseBoolean(pValue);
-				break;
-			case "magicfailures":
-				ALT_GAME_MAGICFAILURES = Boolean.parseBoolean(pValue);
-				break;
-			case "altmobagroinpeacezone":
-				ALT_MOB_AGRO_IN_PEACEZONE = Boolean.parseBoolean(pValue);
-				break;
-			case "altgameexponentxp":
-				ALT_GAME_EXPONENT_XP = Float.parseFloat(pValue);
-				break;
-			case "altgameexponentsp":
-				ALT_GAME_EXPONENT_SP = Float.parseFloat(pValue);
-				break;
-			case "allowclassmasters":
-				ALLOW_CLASS_MASTERS = Boolean.parseBoolean(pValue);
-				break;
-			case "allowentiretree":
-				ALLOW_ENTIRE_TREE = Boolean.parseBoolean(pValue);
-				break;
-			case "alternateclassmaster":
-				ALTERNATE_CLASS_MASTER = Boolean.parseBoolean(pValue);
-				break;
-			case "altpartyrange":
-				ALT_PARTY_RANGE = Integer.parseInt(pValue);
-				break;
-			case "altpartyrange2":
-				ALT_PARTY_RANGE2 = Integer.parseInt(pValue);
-				break;
-			case "altleavepartyleader":
-				ALT_LEAVE_PARTY_LEADER = Boolean.parseBoolean(pValue);
-				break;
-			case "craftingenabled":
-				IS_CRAFTING_ENABLED = Boolean.parseBoolean(pValue);
-				break;
-			case "craftmasterwork":
-				CRAFT_MASTERWORK = Boolean.parseBoolean(pValue);
-				break;
-			case "lifecrystalneeded":
-				LIFE_CRYSTAL_NEEDED = Boolean.parseBoolean(pValue);
-				break;
-			case "autoloot":
-				AUTO_LOOT = Boolean.parseBoolean(pValue);
-				break;
-			case "autolootraids":
-				AUTO_LOOT_RAIDS = Boolean.parseBoolean(pValue);
-				break;
-			case "autolootherbs":
-				AUTO_LOOT_HERBS = Boolean.parseBoolean(pValue);
-				break;
-			case "altkarmaplayercanbekilledinpeacezone":
-				ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE = Boolean.parseBoolean(pValue);
-				break;
-			case "altkarmaplayercanshop":
-				ALT_GAME_KARMA_PLAYER_CAN_SHOP = Boolean.parseBoolean(pValue);
-				break;
-			case "altkarmaplayercanusegk":
-				ALT_GAME_KARMA_PLAYER_CAN_USE_GK = Boolean.parseBoolean(pValue);
-				break;
-			case "altkarmaplayercanteleport":
-				ALT_GAME_KARMA_PLAYER_CAN_TELEPORT = Boolean.parseBoolean(pValue);
-				break;
-			case "altkarmaplayercantrade":
-				ALT_GAME_KARMA_PLAYER_CAN_TRADE = Boolean.parseBoolean(pValue);
-				break;
-			case "altkarmaplayercanusewarehouse":
-				ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE = Boolean.parseBoolean(pValue);
-				break;
-			case "maxpersonalfamepoints":
-				MAX_PERSONAL_FAME_POINTS = Integer.parseInt(pValue);
-				break;
-			case "fortresszonefametaskfrequency":
-				FORTRESS_ZONE_FAME_TASK_FREQUENCY = Integer.parseInt(pValue);
-				break;
-			case "fortresszonefameaquirepoints":
-				FORTRESS_ZONE_FAME_AQUIRE_POINTS = Integer.parseInt(pValue);
-				break;
-			case "castlezonefametaskfrequency":
-				CASTLE_ZONE_FAME_TASK_FREQUENCY = Integer.parseInt(pValue);
-				break;
-			case "castlezonefameaquirepoints":
-				CASTLE_ZONE_FAME_AQUIRE_POINTS = Integer.parseInt(pValue);
-				break;
-			case "altcastlefordawn":
-				ALT_GAME_CASTLE_DAWN = Boolean.parseBoolean(pValue);
-				break;
-			case "altcastlefordusk":
-				ALT_GAME_CASTLE_DUSK = Boolean.parseBoolean(pValue);
-				break;
-			case "altrequireclancastle":
-				ALT_GAME_REQUIRE_CLAN_CASTLE = Boolean.parseBoolean(pValue);
-				break;
-			case "altfreeteleporting":
-				ALT_GAME_FREE_TELEPORT = Boolean.parseBoolean(pValue);
-				break;
-			case "altsubclasswithoutquests":
-				ALT_GAME_SUBCLASS_WITHOUT_QUESTS = Boolean.parseBoolean(pValue);
-				break;
-			case "altsubclasseverywhere":
-				ALT_GAME_SUBCLASS_EVERYWHERE = Boolean.parseBoolean(pValue);
-				break;
-			case "altmemberscanwithdrawfromclanwh":
-				ALT_MEMBERS_CAN_WITHDRAW_FROM_CLANWH = Boolean.parseBoolean(pValue);
-				break;
-			case "dwarfrecipelimit":
-				DWARF_RECIPE_LIMIT = Integer.parseInt(pValue);
-				break;
-			case "commonrecipelimit":
-				COMMON_RECIPE_LIMIT = Integer.parseInt(pValue);
-				break;
-			case "championenable":
-				L2JMOD_CHAMPION_ENABLE = Boolean.parseBoolean(pValue);
-				break;
-			case "championfrequency":
-				L2JMOD_CHAMPION_FREQUENCY = Integer.parseInt(pValue);
-				break;
-			case "championminlevel":
-				L2JMOD_CHAMP_MIN_LVL = Integer.parseInt(pValue);
-				break;
-			case "championmaxlevel":
-				L2JMOD_CHAMP_MAX_LVL = Integer.parseInt(pValue);
-				break;
-			case "championhp":
-				L2JMOD_CHAMPION_HP = Integer.parseInt(pValue);
-				break;
-			case "championhpregen":
-				L2JMOD_CHAMPION_HP_REGEN = Float.parseFloat(pValue);
-				break;
-			case "championrewardsexpsp":
-				L2JMOD_CHAMPION_REWARDS_EXP_SP = Float.parseFloat(pValue);
-				break;
-			case "championrewardschance":
-				L2JMOD_CHAMPION_REWARDS_CHANCE = Float.parseFloat(pValue);
-				break;
-			case "championrewardsamount":
-				L2JMOD_CHAMPION_REWARDS_AMOUNT = Float.parseFloat(pValue);
-				break;
-			case "championadenasrewardschance":
-				L2JMOD_CHAMPION_ADENAS_REWARDS_CHANCE = Float.parseFloat(pValue);
-				break;
-			case "championadenasrewardsamount":
-				L2JMOD_CHAMPION_ADENAS_REWARDS_AMOUNT = Float.parseFloat(pValue);
-				break;
-			case "championatk":
-				L2JMOD_CHAMPION_ATK = Float.parseFloat(pValue);
-				break;
-			case "championspdatk":
-				L2JMOD_CHAMPION_SPD_ATK = Float.parseFloat(pValue);
-				break;
-			case "championrewardlowerlvlitemchance":
-				L2JMOD_CHAMPION_REWARD_LOWER_LVL_ITEM_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "championrewardhigherlvlitemchance":
-				L2JMOD_CHAMPION_REWARD_HIGHER_LVL_ITEM_CHANCE = Integer.parseInt(pValue);
-				break;
-			case "championrewarditemid":
-				L2JMOD_CHAMPION_REWARD_ID = Integer.parseInt(pValue);
-				break;
-			case "championrewarditemqty":
-				L2JMOD_CHAMPION_REWARD_QTY = Integer.parseInt(pValue);
-				break;
-			case "championenableininstances":
-				L2JMOD_CHAMPION_ENABLE_IN_INSTANCES = Boolean.parseBoolean(pValue);
-				break;
-			case "allowwedding":
-				L2JMOD_ALLOW_WEDDING = Boolean.parseBoolean(pValue);
-				break;
-			case "weddingprice":
-				L2JMOD_WEDDING_PRICE = Integer.parseInt(pValue);
-				break;
-			case "weddingpunishinfidelity":
-				L2JMOD_WEDDING_PUNISH_INFIDELITY = Boolean.parseBoolean(pValue);
-				break;
-			case "weddingteleport":
-				L2JMOD_WEDDING_TELEPORT = Boolean.parseBoolean(pValue);
-				break;
-			case "weddingteleportprice":
-				L2JMOD_WEDDING_TELEPORT_PRICE = Integer.parseInt(pValue);
-				break;
-			case "weddingteleportduration":
-				L2JMOD_WEDDING_TELEPORT_DURATION = Integer.parseInt(pValue);
-				break;
-			case "weddingallowsamesex":
-				L2JMOD_WEDDING_SAMESEX = Boolean.parseBoolean(pValue);
-				break;
-			case "weddingformalwear":
-				L2JMOD_WEDDING_FORMALWEAR = Boolean.parseBoolean(pValue);
-				break;
-			case "weddingdivorcecosts":
-				L2JMOD_WEDDING_DIVORCE_COSTS = Integer.parseInt(pValue);
-				break;
-			case "tvteventenabled":
-				TVT_EVENT_ENABLED = Boolean.parseBoolean(pValue);
-				break;
-			case "tvteventinterval":
-				TVT_EVENT_INTERVAL = pValue.split(",");
-				break;
-			case "tvteventparticipationtime":
-				TVT_EVENT_PARTICIPATION_TIME = Integer.parseInt(pValue);
-				break;
-			case "tvteventrunningtime":
-				TVT_EVENT_RUNNING_TIME = Integer.parseInt(pValue);
-				break;
-			case "tvteventparticipationnpcid":
-				TVT_EVENT_PARTICIPATION_NPC_ID = Integer.parseInt(pValue);
-				break;
-			case "enablewarehousesortingclan":
-				L2JMOD_ENABLE_WAREHOUSESORTING_CLAN = Boolean.parseBoolean(pValue);
-				break;
-			case "enablewarehousesortingprivate":
-				L2JMOD_ENABLE_WAREHOUSESORTING_PRIVATE = Boolean.parseBoolean(pValue);
-				break;
-			case "enablemanapotionsupport":
-				L2JMOD_ENABLE_MANA_POTIONS_SUPPORT = Boolean.parseBoolean(pValue);
-				break;
-			case "displayservertime":
-				L2JMOD_DISPLAY_SERVER_TIME = Boolean.parseBoolean(pValue);
-				break;
-			case "antifeedenable":
-				L2JMOD_ANTIFEED_ENABLE = Boolean.parseBoolean(pValue);
-				break;
-			case "antifeeddualbox":
-				L2JMOD_ANTIFEED_DUALBOX = Boolean.parseBoolean(pValue);
-				break;
-			case "antifeeddisconnectedasdualbox":
-				L2JMOD_ANTIFEED_DISCONNECTED_AS_DUALBOX = Boolean.parseBoolean(pValue);
-				break;
-			case "antifeedinterval":
-				L2JMOD_ANTIFEED_INTERVAL = 1000 * Integer.parseInt(pValue);
-				break;
-			case "cangmdropequipment":
-				KARMA_DROP_GM = Boolean.parseBoolean(pValue);
-				break;
-			case "awardpkkillpvppoint":
-				KARMA_AWARD_PK_KILL = Boolean.parseBoolean(pValue);
-				break;
-			case "minimumpkrequiredtodrop":
-				KARMA_PK_LIMIT = Integer.parseInt(pValue);
-				break;
-			case "pvpvsnormaltime":
-				PVP_NORMAL_TIME = Integer.parseInt(pValue);
-				break;
-			case "pvpvspvptime":
-				PVP_PVP_TIME = Integer.parseInt(pValue);
-				break;
-			case "globalchat":
-				DEFAULT_GLOBAL_CHAT = pValue;
-				break;
-			case "tradechat":
-				DEFAULT_TRADE_CHAT = pValue;
-				break;
-			default:
-				try {
-					// TODO: stupid GB configs...
-					if (!pName.startsWith("Interval_") && !pName.startsWith("Random_")) {
-						pName = pName.toUpperCase();
-					}
-					Field clazField = Config.class.getField(pName);
-					int modifiers = clazField.getModifiers();
-					// just in case :)
-					if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers) || Modifier.isFinal(modifiers)) {
-						throw new SecurityException("Cannot modify non public, non static or final config!");
-					}
-					
-					if (clazField.getType() == int.class) {
-						clazField.setInt(clazField, Integer.parseInt(pValue));
-					} else if (clazField.getType() == short.class) {
-						clazField.setShort(clazField, Short.parseShort(pValue));
-					} else if (clazField.getType() == byte.class) {
-						clazField.setByte(clazField, Byte.parseByte(pValue));
-					} else if (clazField.getType() == long.class) {
-						clazField.setLong(clazField, Long.parseLong(pValue));
-					} else if (clazField.getType() == float.class) {
-						clazField.setFloat(clazField, Float.parseFloat(pValue));
-					} else if (clazField.getType() == double.class) {
-						clazField.setDouble(clazField, Double.parseDouble(pValue));
-					} else if (clazField.getType() == boolean.class) {
-						clazField.setBoolean(clazField, Boolean.parseBoolean(pValue));
-					} else if (clazField.getType() == String.class) {
-						clazField.set(clazField, pValue);
-					} else {
-						return false;
-					}
-				} catch (NoSuchFieldException e) {
-					return false;
-				} catch (Exception e) {
-					LOG.warn("Unable to set parameter value!", e);
-					return false;
-				}
-		}
-		return true;
-	}
-	
-	/**
-	 * Save hexadecimal ID of the server in the L2Properties file.<br>
-	 * Check {@link #HEXID_FILE}.
-	 * @param serverId the ID of the server whose hexId to save
-	 * @param hexId the hexadecimal ID to store
-	 */
-	public static void saveHexid(int serverId, String hexId) {
-		Config.saveHexid(serverId, hexId, HEXID_FILE);
-	}
-	
-	/**
-	 * Save hexadecimal ID of the server in the L2Properties file.
-	 * @param serverId the ID of the server whose hexId to save
-	 * @param hexId the hexadecimal ID to store
-	 * @param fileName name of the L2Properties file
-	 */
-	public static void saveHexid(int serverId, String hexId, String fileName) {
-		try {
-			Properties hexSetting = new Properties();
-			File file = new File(fileName);
-			// Create a new empty file only if it doesn't exist
-			file.createNewFile();
-			try (OutputStream out = new FileOutputStream(file)) {
-				hexSetting.setProperty("ServerID", String.valueOf(serverId));
-				hexSetting.setProperty("HexID", hexId);
-				hexSetting.store(out, "the hexID to auth into login");
-			}
-		} catch (Exception e) {
-			LOG.warn("Failed to save hex id to {} file.", fileName, e);
-		}
-	}
-	
-	/**
-	 * Loads flood protector configurations.
-	 * @param properties the properties object containing the actual values of the flood protector configs
-	 */
-	private static void loadFloodProtectorConfigs(final PropertiesParser properties) {
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_USE_ITEM, "UseItem", 4);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_ROLL_DICE, "RollDice", 42);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_FIREWORK, "Firework", 42);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_ITEM_PET_SUMMON, "ItemPetSummon", 16);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_HERO_VOICE, "HeroVoice", 100);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_GLOBAL_CHAT, "GlobalChat", 5);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SUBCLASS, "Subclass", 20);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_DROP_ITEM, "DropItem", 10);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SERVER_BYPASS, "ServerBypass", 5);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_MULTISELL, "MultiSell", 1);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_TRANSACTION, "Transaction", 10);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_MANUFACTURE, "Manufacture", 3);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_MANOR, "Manor", 30);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_SENDMAIL, "SendMail", 100);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_CHARACTER_SELECT, "CharacterSelect", 30);
-		loadFloodProtectorConfig(properties, FLOOD_PROTECTOR_ITEM_AUCTION, "ItemAuction", 9);
-	}
-	
-	/**
-	 * Loads single flood protector configuration.
-	 * @param properties properties file reader
-	 * @param config flood protector configuration instance
-	 * @param configString flood protector configuration string that determines for which flood protector configuration should be read
-	 * @param defaultInterval default flood protector interval
-	 */
-	private static void loadFloodProtectorConfig(final PropertiesParser properties, final FloodProtectorConfig config, final String configString, final int defaultInterval) {
-		config.FLOOD_PROTECTION_INTERVAL = properties.getInt(StringUtil.concat("FloodProtector", configString, "Interval"), defaultInterval);
-		config.LOG_FLOODING = properties.getBoolean(StringUtil.concat("FloodProtector", configString, "LogFlooding"), false);
-		config.PUNISHMENT_LIMIT = properties.getInt(StringUtil.concat("FloodProtector", configString, "PunishmentLimit"), 0);
-		config.PUNISHMENT_TYPE = properties.getString(StringUtil.concat("FloodProtector", configString, "PunishmentType"), "none");
-		config.PUNISHMENT_TIME = properties.getInt(StringUtil.concat("FloodProtector", configString, "PunishmentTime"), 0) * 60000;
-	}
-	
-	public static int getServerTypeId(String[] serverTypes) {
-		int tType = 0;
-		for (String cType : serverTypes) {
-			switch (cType.trim().toLowerCase()) {
-				case "normal":
-					tType |= 0x01;
-					break;
-				case "relax":
-					tType |= 0x02;
-					break;
-				case "test":
-					tType |= 0x04;
-					break;
-				case "nolabel":
-					tType |= 0x08;
-					break;
-				case "restricted":
-					tType |= 0x10;
-					break;
-				case "event":
-					tType |= 0x20;
-					break;
-				case "free":
-					tType |= 0x40;
-					break;
-				default:
-					break;
-			}
-		}
-		return tType;
-	}
-	
-	public static final class ClassMasterSettings {
-		private final Map<Integer, List<ItemHolder>> _claimItems = new HashMap<>(3);
-		private final Map<Integer, List<ItemHolder>> _rewardItems = new HashMap<>(3);
-		private final Map<Integer, Boolean> _allowedClassChange = new HashMap<>(3);
-		
-		public ClassMasterSettings(String configLine) {
-			parseConfigLine(configLine.trim());
-		}
-		
-		private void parseConfigLine(String configLine) {
-			if (configLine.isEmpty()) {
-				return;
-			}
-			
-			final StringTokenizer st = new StringTokenizer(configLine, ";");
-			
-			while (st.hasMoreTokens()) {
-				// get allowed class change
-				final int job = Integer.parseInt(st.nextToken());
-				
-				_allowedClassChange.put(job, true);
-				
-				final List<ItemHolder> requiredItems = new ArrayList<>();
-				// parse items needed for class change
-				if (st.hasMoreTokens()) {
-					final StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
-					
-					while (st2.hasMoreTokens()) {
-						final StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
-						final int itemId = Integer.parseInt(st3.nextToken());
-						final int quantity = Integer.parseInt(st3.nextToken());
-						requiredItems.add(new ItemHolder(itemId, quantity));
-					}
-				}
-				
-				_claimItems.put(job, requiredItems);
-				
-				final List<ItemHolder> rewardItems = new ArrayList<>();
-				// parse gifts after class change
-				if (st.hasMoreTokens()) {
-					final StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
-					
-					while (st2.hasMoreTokens()) {
-						final StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
-						final int itemId = Integer.parseInt(st3.nextToken());
-						final int quantity = Integer.parseInt(st3.nextToken());
-						rewardItems.add(new ItemHolder(itemId, quantity));
-					}
-				}
-				
-				_rewardItems.put(job, rewardItems);
-			}
-		}
-		
-		public boolean isAllowed(int job) {
-			if ((_allowedClassChange == null) || !_allowedClassChange.containsKey(job)) {
-				return false;
-			}
-			return _allowedClassChange.get(job);
-		}
-		
-		public List<ItemHolder> getRewardItems(int job) {
-			return _rewardItems.get(job);
-		}
-		
-		public List<ItemHolder> getRequireItems(int job) {
-			return _claimItems.get(job);
-		}
-	}
-	
-	/**
-	 * @param line the string line to parse
-	 * @return a parsed float map
-	 */
-	private static Map<Integer, Float> parseConfigLine(String line) {
-		String[] propertySplit = line.split(",");
-		Map<Integer, Float> ret = new HashMap<>(propertySplit.length);
-		int i = 0;
-		for (String value : propertySplit) {
-			ret.put(i++, Float.parseFloat(value));
-		}
-		return ret;
-	}
-	
-	/**
-	 * Parse a config value from its string representation to a two-dimensional int array.<br>
-	 * The format of the value to be parsed should be as follows: "item1Id,item1Amount;item2Id,item2Amount;...itemNId,itemNAmount".
-	 * @param line the value of the parameter to parse
-	 * @return the parsed list or {@code null} if nothing was parsed
-	 */
-	private static int[][] parseItemsList(String line) {
-		final String[] propertySplit = line.split(";");
-		if (propertySplit.length == 0) {
-			// nothing to do here
-			return null;
-		}
-		
-		int i = 0;
-		String[] valueSplit;
-		final int[][] result = new int[propertySplit.length][];
-		int[] tmp;
-		for (String value : propertySplit) {
-			valueSplit = value.split(",");
-			if (valueSplit.length != 2) {
-				LOG.warn("parseItemsList[Config.load()]: invalid entry -> {}, should be itemId,itemNumber. Skipping to the next entry in the list.", valueSplit[0]);
-				continue;
-			}
-			
-			tmp = new int[2];
-			try {
-				tmp[0] = Integer.parseInt(valueSplit[0]);
-			} catch (NumberFormatException e) {
-				LOG.warn("parseItemsList[Config.load()]: invalid itemId -> {}, value must be an integer. Skipping to the next entry in the list.", valueSplit[0]);
-				continue;
-			}
-			try {
-				tmp[1] = Integer.parseInt(valueSplit[1]);
-			} catch (NumberFormatException e) {
-				LOG.warn("parseItemsList[Config.load()]: invalid item number -> {}, value must be an integer. Skipping to the next entry in the list.", valueSplit[1]);
-				continue;
-			}
-			result[i++] = tmp;
-		}
-		return result;
-	}
-	
-	private static class IPConfigData implements IXmlReader {
-		
-		private static final Logger LOG = LoggerFactory.getLogger(IPConfigData.class);
-		
-		private static final List<String> _subnets = new ArrayList<>(5);
-		
-		private static final List<String> _hosts = new ArrayList<>(5);
-		
-		public IPConfigData() {
-			load();
-		}
-		
-		@Override
-		public void load() {
-			GameServer.printSection("Network Configuration");
-			final File f = new File(IP_CONFIG_FILE);
-			if (f.exists()) {
-				LOG.info("Using existing ipconfig.xml.");
-				parseFile(new File(IP_CONFIG_FILE));
-			} else {
-				LOG.info("Using automatic network configuration.");
-				autoIpConfig();
-			}
-		}
-		
-		@Override
-		public void parseDocument(Document doc) {
-			NamedNodeMap attrs;
-			for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling()) {
-				if ("gameserver".equalsIgnoreCase(n.getNodeName())) {
-					for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) {
-						if ("define".equalsIgnoreCase(d.getNodeName())) {
-							attrs = d.getAttributes();
-							_subnets.add(attrs.getNamedItem("subnet").getNodeValue());
-							_hosts.add(attrs.getNamedItem("address").getNodeValue());
-							
-							if (_hosts.size() != _subnets.size()) {
-								LOG.warn("Failed to load {} file - subnets does not match server addresses.", IP_CONFIG_FILE);
-							}
-						}
-					}
-					
-					Node att = n.getAttributes().getNamedItem("address");
-					if (att == null) {
-						LOG.warn("Failed to load {} file - default server address is missing.", IP_CONFIG_FILE);
-						_hosts.add("127.0.0.1");
-					} else {
-						_hosts.add(att.getNodeValue());
-					}
-					_subnets.add("0.0.0.0/0");
-				}
-			}
-		}
-		
-		protected void autoIpConfig() {
-			String externalIp = "127.0.0.1";
-			try {
-				URL autoIp = new URL("http://ip1.dynupdate.no-ip.com:8245/");
-				try (BufferedReader in = new BufferedReader(new InputStreamReader(autoIp.openStream()))) {
-					externalIp = in.readLine();
-				}
-			} catch (IOException e) {
-				LOG.warn("Failed to connect to api.externalip.net please check your internet connection using 127.0.0.1!");
-				externalIp = "127.0.0.1";
-			}
-			
-			try {
-				Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
-				
-				while (niList.hasMoreElements()) {
-					NetworkInterface ni = niList.nextElement();
-					
-					if (!ni.isUp() || ni.isVirtual()) {
-						continue;
-					}
-					
-					if (!ni.isLoopback() && ((ni.getHardwareAddress() == null) || (ni.getHardwareAddress().length != 6))) {
-						continue;
-					}
-					
-					for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
-						if (ia.getAddress() instanceof Inet6Address) {
-							continue;
-						}
-						
-						final String hostAddress = ia.getAddress().getHostAddress();
-						final int subnetPrefixLength = ia.getNetworkPrefixLength();
-						final int subnetMaskInt = IntStream.rangeClosed(1, subnetPrefixLength).reduce((r, e) -> (r << 1) + 1).orElse(0) << (32 - subnetPrefixLength);
-						final int hostAddressInt = Arrays.stream(hostAddress.split("\\.")).mapToInt(Integer::parseInt).reduce((r, e) -> (r << 8) + e).orElse(0);
-						final int subnetAddressInt = hostAddressInt & subnetMaskInt;
-						final String subnetAddress = ((subnetAddressInt >> 24) & 0xFF) + "." + ((subnetAddressInt >> 16) & 0xFF) + "." + ((subnetAddressInt >> 8) & 0xFF) + "." + (subnetAddressInt & 0xFF);
-						final String subnet = subnetAddress + '/' + subnetPrefixLength;
-						if (!_subnets.contains(subnet) && !subnet.equals("0.0.0.0/0")) {
-							_subnets.add(subnet);
-							_hosts.add(hostAddress);
-							LOG.info("Adding new subnet: " + subnet + " address: " + hostAddress);
-						}
-					}
-				}
-				
-				// External host and subnet
-				_hosts.add(externalIp);
-				_subnets.add("0.0.0.0/0");
-				LOG.info("Adding new subnet: 0.0.0.0/0 address: {}", externalIp);
-			} catch (SocketException e) {
-				LOG.error("Configuration failed please manually configure ipconfig.xml", e);
-				System.exit(0);
-			}
-		}
-		
-		protected List<String> getSubnets() {
-			if (_subnets.isEmpty()) {
-				return Arrays.asList("0.0.0.0/0");
-			}
-			return _subnets;
-		}
-		
-		protected List<String> getHosts() {
-			if (_hosts.isEmpty()) {
-				return Arrays.asList("127.0.0.1");
-			}
-			return _hosts;
-		}
-	}
-}

+ 197 - 0
src/main/java/com/l2jserver/gameserver/config/Configuration.java

@@ -0,0 +1,197 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import org.aeonbits.owner.ConfigFactory;
+
+/**
+ * Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class Configuration {
+	
+	public static final String EOL = System.lineSeparator();
+	
+	private static final IPConfigData ipConfigData = new IPConfigData();
+	
+	private static final ServerConfiguration server = ConfigFactory.create(ServerConfiguration.class);
+	
+	private static final HexIdConfiguration hexId = ConfigFactory.create(HexIdConfiguration.class);
+	
+	private static final DatabaseConfiguration database = ConfigFactory.create(DatabaseConfiguration.class);
+	
+	private static final MMOConfiguration mmo = ConfigFactory.create(MMOConfiguration.class);
+	
+	private static final TelnetConfiguration telnet = ConfigFactory.create(TelnetConfiguration.class);
+	
+	private static final GeneralConfiguration general = ConfigFactory.create(GeneralConfiguration.class);
+	
+	private static final GeodataConfiguration geodata = ConfigFactory.create(GeodataConfiguration.class);
+	
+	private static final CharacterConfiguration character = ConfigFactory.create(CharacterConfiguration.class);
+	
+	private static final CastleConfiguration castle = ConfigFactory.create(CastleConfiguration.class);
+	
+	private static final ClanConfiguration clan = ConfigFactory.create(ClanConfiguration.class);
+	
+	private static final ClanHallConfiguration clanhall = ConfigFactory.create(ClanHallConfiguration.class);
+	
+	private static final FortressConfiguration fortress = ConfigFactory.create(FortressConfiguration.class);
+	
+	private static final SevenSingsConfiguration sevenSings = ConfigFactory.create(SevenSingsConfiguration.class);
+	
+	private static final TvTConfiguration tvt = ConfigFactory.create(TvTConfiguration.class);
+	
+	private static final NPCConfiguration npc = ConfigFactory.create(NPCConfiguration.class);
+	
+	private static final OlympiadConfiguration olympiad = ConfigFactory.create(OlympiadConfiguration.class);
+	
+	private static final SiegeConfiguration siege = ConfigFactory.create(SiegeConfiguration.class);
+	
+	private static final TerritoryWarConfiguration territoryWar = ConfigFactory.create(TerritoryWarConfiguration.class);
+	
+	private static final FortSiegeConfiguration fortSiege = ConfigFactory.create(FortSiegeConfiguration.class);
+	
+	private static final GrandBossConfiguration grandBoss = ConfigFactory.create(GrandBossConfiguration.class);
+	
+	private static final GraciaSeedsConfiguration graciaSeeds = ConfigFactory.create(GraciaSeedsConfiguration.class);
+	
+	private static final RatesConfiguration rates = ConfigFactory.create(RatesConfiguration.class);
+	
+	private static final VitalityConfiguration vitality = ConfigFactory.create(VitalityConfiguration.class);
+	
+	private static final PvPConfiguration pvp = ConfigFactory.create(PvPConfiguration.class);
+	
+	private static final CustomsConfiguration customs = ConfigFactory.create(CustomsConfiguration.class);
+	
+	private static final FloodProtectorConfiguration floodProtector = ConfigFactory.create(FloodProtectorConfiguration.class);
+	
+	private Configuration() {
+		// Do nothing.
+	}
+	
+	public static ServerConfiguration server() {
+		return server;
+	}
+	
+	public static HexIdConfiguration hexId() {
+		return hexId;
+	}
+	
+	public static DatabaseConfiguration database() {
+		return database;
+	}
+	
+	public static MMOConfiguration mmo() {
+		return mmo;
+	}
+	
+	public static TelnetConfiguration telnet() {
+		return telnet;
+	}
+	
+	public static GeneralConfiguration general() {
+		return general;
+	}
+	
+	public static GeodataConfiguration geodata() {
+		return geodata;
+	}
+	
+	public static CharacterConfiguration character() {
+		return character;
+	}
+	
+	public static CastleConfiguration castle() {
+		return castle;
+	}
+	
+	public static ClanConfiguration clan() {
+		return clan;
+	}
+	
+	public static ClanHallConfiguration clanhall() {
+		return clanhall;
+	}
+	
+	public static FortressConfiguration fortress() {
+		return fortress;
+	}
+	
+	public static SevenSingsConfiguration sevenSings() {
+		return sevenSings;
+	}
+	
+	public static TvTConfiguration tvt() {
+		return tvt;
+	}
+	
+	public static NPCConfiguration npc() {
+		return npc;
+	}
+	
+	public static OlympiadConfiguration olympiad() {
+		return olympiad;
+	}
+	
+	public static SiegeConfiguration siege() {
+		return siege;
+	}
+	
+	public static TerritoryWarConfiguration territoryWar() {
+		return territoryWar;
+	}
+	
+	public static FortSiegeConfiguration fortSiege() {
+		return fortSiege;
+	}
+	
+	public static GrandBossConfiguration grandBoss() {
+		return grandBoss;
+	}
+	
+	public static GraciaSeedsConfiguration graciaSeeds() {
+		return graciaSeeds;
+	}
+	
+	public static RatesConfiguration rates() {
+		return rates;
+	}
+	
+	public static VitalityConfiguration vitality() {
+		return vitality;
+	}
+	
+	public static PvPConfiguration pvp() {
+		return pvp;
+	}
+	
+	public static CustomsConfiguration customs() {
+		return customs;
+	}
+	
+	public static FloodProtectorConfiguration floodProtector() {
+		return floodProtector;
+	}
+	
+	public static IPConfigData ip() {
+		return ipConfigData;
+	}
+}

+ 277 - 0
src/main/java/com/l2jserver/gameserver/config/CustomsConfiguration.java

@@ -0,0 +1,277 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.ColorConverter;
+import com.l2jserver.gameserver.config.converter.IPLimitConverter;
+import com.l2jserver.gameserver.config.converter.Seconds2MillisecondsConverter;
+
+/**
+ * Customs Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/customs.properties",
+	"classpath:config/customs.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface CustomsConfiguration extends Config, Reloadable {
+	
+	@Key("ChampionEnable")
+	Boolean championEnable();
+	
+	@Key("ChampionPassive")
+	Boolean championPassive();
+	
+	@Key("ChampionFrequency")
+	Integer getChampionFrequency();
+	
+	@Key("ChampionTitle")
+	String getChampionTitle();
+	
+	@Key("ChampionMinLevel")
+	Integer getChampionMinLevel();
+	
+	@Key("ChampionMaxLevel")
+	Integer getChampionMaxLevel();
+	
+	@Key("ChampionHp")
+	Integer getChampionHp();
+	
+	@Key("ChampionHpRegen")
+	Double getChampionHpRegen();
+	
+	@Key("ChampionRewardsExpSp")
+	Double getChampionRewardsExpSp();
+	
+	@Key("ChampionRewardsChance")
+	Double getChampionRewardsChance();
+	
+	@Key("ChampionRewardsAmount")
+	Double getChampionRewardsAmount();
+	
+	@Key("ChampionAdenasRewardsChance")
+	Double getChampionAdenasRewardsChance();
+	
+	@Key("ChampionAdenasRewardsAmount")
+	Double getChampionAdenasRewardsAmount();
+	
+	@Key("ChampionAtk")
+	Float getChampionAtk();
+	
+	@Key("ChampionSpdAtk")
+	Float getChampionSpdAtk();
+	
+	@Key("ChampionRewardItemID")
+	Integer getChampionRewardItemID();
+	
+	@Key("ChampionRewardItemQty")
+	Integer getChampionRewardItemQty();
+	
+	@Key("ChampionRewardLowerLvlItemChance")
+	Integer getChampionRewardLowerLvlItemChance();
+	
+	@Key("ChampionRewardHigherLvlItemChance")
+	Integer getChampionRewardHigherLvlItemChance();
+	
+	@Key("ChampionEnableVitality")
+	Boolean championEnableVitality();
+	
+	@Key("ChampionEnableInInstances")
+	Boolean championEnableInInstances();
+	
+	@Key("AllowWedding")
+	Boolean allowWedding();
+	
+	@Key("WeddingPrice")
+	Integer getWeddingPrice();
+	
+	@Key("WeddingPunishInfidelity")
+	Boolean weddingPunishInfidelity();
+	
+	@Key("WeddingTeleport")
+	Boolean weddingTeleport();
+	
+	@Key("WeddingTeleportPrice")
+	Integer getWeddingTeleportPrice();
+	
+	@Key("WeddingTeleportDuration")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getWeddingTeleportDuration();
+	
+	@Key("WeddingAllowSameSex")
+	Boolean weddingAllowSameSex();
+	
+	@Key("WeddingFormalWear")
+	Boolean weddingFormalWear();
+	
+	@Key("WeddingDivorceCosts")
+	Integer getWeddingDivorceCosts();
+	
+	@Key("BankingEnabled")
+	Boolean bankingEnabled();
+	
+	@Key("BankingGoldbarCount")
+	Integer getBankingGoldbarCount();
+	
+	@Key("BankingAdenaCount")
+	Integer getBankingAdenaCount();
+	
+	@Key("EnableWarehouseSortingClan")
+	Boolean enableWarehouseSortingClan();
+	
+	@Key("EnableWarehouseSortingPrivate")
+	Boolean enableWarehouseSortingPrivate();
+	
+	@Key("OfflineTradeEnable")
+	Boolean offlineTradeEnable();
+	
+	@Key("OfflineCraftEnable")
+	Boolean offlineCraftEnable();
+	
+	@Key("OfflineModeInPeaceZone")
+	Boolean offlineModeInPeaceZone();
+	
+	@Key("OfflineModeNoDamage")
+	Boolean offlineModeNoDamage();
+	
+	@Key("OfflineSetNameColor")
+	Boolean offlineSetNameColor();
+	
+	@Key("OfflineNameColor")
+	@ConverterClass(ColorConverter.class)
+	Integer getOfflineNameColor();
+	
+	@Key("OfflineFame")
+	Boolean offlineFame();
+	
+	@Key("RestoreOffliners")
+	Boolean restoreOffliners();
+	
+	@Key("OfflineMaxDays")
+	Integer getOfflineMaxDays();
+	
+	@Key("OfflineDisconnectFinished")
+	Boolean offlineDisconnectFinished();
+	
+	@Key("EnableManaPotionSupport")
+	Boolean enableManaPotionSupport();
+	
+	@Key("DisplayServerTime")
+	Boolean displayServerTime();
+	
+	@Key("ScreenWelcomeMessageEnable")
+	Boolean screenWelcomeMessageEnable();
+	
+	@Key("ScreenWelcomeMessageText")
+	String getScreenWelcomeMessageText();
+	
+	@Key("ScreenWelcomeMessageTime")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getScreenWelcomeMessageTime();
+	
+	@Key("AntiFeedEnable")
+	Boolean antiFeedEnable();
+	
+	@Key("AntiFeedDualbox")
+	Boolean antiFeedDualbox();
+	
+	@Key("AntiFeedDisconnectedAsDualbox")
+	Boolean antiFeedDisconnectedAsDualbox();
+	
+	@Key("AntiFeedInterval")
+	Integer getAntiFeedInterval();
+	
+	@Key("AnnouncePkPvP")
+	Boolean announcePkPvP();
+	
+	@Key("AnnouncePkPvPNormalMessage")
+	Boolean announcePkPvPNormalMessage();
+	
+	@Key("AnnouncePkMsg")
+	String getAnnouncePkMsg();
+	
+	@Key("AnnouncePvpMsg")
+	String getAnnouncePvpMsg();
+	
+	@Key("ChatAdmin")
+	Boolean chatAdmin();
+	
+	@Key("HellboundStatus")
+	Boolean hellboundStatus();
+	
+	@Key("MultiLangEnable")
+	Boolean multiLangEnable();
+	
+	@Key("MultiLangDefault")
+	String getMultiLangDefault();
+	
+	@Key("MultiLangAllowed")
+	Set<String> getMultiLangAllowed();
+	
+	@Key("MultiLangVoiceCommand")
+	Boolean multiLangVoiceCommand();
+	
+	@Key("MultiLangSystemMessageEnable")
+	Boolean multiLangSystemMessageEnable();
+	
+	@Key("MultiLangSystemMessageAllowed")
+	List<String> getMultiLangSystemMessageAllowed();
+	
+	@Key("MultiLangNpcStringEnable")
+	Boolean multiLangNpcStringEnable();
+	
+	@Key("MultiLangNpcStringAllowed")
+	List<String> getMultiLangNpcStringAllowed();
+	
+	@Key("L2WalkerProtection")
+	Boolean l2WalkerProtection();
+	
+	@Key("DebugVoiceCommand")
+	Boolean debugVoiceCommand();
+	
+	@Key("DualboxCheckMaxPlayersPerIP")
+	Integer getDualboxCheckMaxPlayersPerIP();
+	
+	@Key("DualboxCheckMaxOlympiadParticipantsPerIP")
+	Integer getDualboxCheckMaxOlympiadParticipantsPerIP();
+	
+	@Key("DualboxCheckMaxL2EventParticipantsPerIP")
+	Integer getDualboxCheckMaxL2EventParticipantsPerIP();
+	
+	@Key("DualboxCheckWhitelist")
+	@ConverterClass(IPLimitConverter.class)
+	Map<Integer, Integer> getDualboxCheckWhitelist();
+	
+	@Key("AllowChangePassword")
+	Boolean allowChangePassword();
+}

+ 64 - 0
src/main/java/com/l2jserver/gameserver/config/DatabaseConfiguration.java

@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Database Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/database.properties",
+	"classpath:config/database.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface DatabaseConfiguration extends Config, Reloadable {
+	
+	@Key("Engine")
+	String getEngine();
+	
+	@Key("Driver")
+	String getDriver();
+	
+	@Key("URL")
+	String getURL();
+	
+	@Key("User")
+	String getUser();
+	
+	@Key("Password")
+	String getPassword();
+	
+	@Key("ConnectionPool")
+	String getConnectionPool();
+	
+	@Key("MaxConnections")
+	Integer getMaxConnections();
+	
+	@Key("MaxIdleTime")
+	Integer getMaxIdleTime();
+}

+ 281 - 0
src/main/java/com/l2jserver/gameserver/config/FloodProtectorConfiguration.java

@@ -0,0 +1,281 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Accessible;
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Flood Protector Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/floodprotector.properties",
+	"classpath:config/floodprotector.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface FloodProtectorConfiguration extends Config, Accessible, Reloadable {
+	
+	@Key("UseItemInterval")
+	Integer getUseItemInterval();
+	
+	@Key("UseItemLogFlooding")
+	Boolean useItemLogFlooding();
+	
+	@Key("UseItemPunishmentLimit")
+	Integer getUseItemPunishmentLimit();
+	
+	@Key("UseItemPunishmentType")
+	String getUseItemPunishmentType();
+	
+	@Key("UseItemPunishmentTime")
+	Integer getUseItemPunishmentTime();
+	
+	@Key("RollDiceInterval")
+	Integer getRollDiceInterval();
+	
+	@Key("RollDiceLogFlooding")
+	Boolean rollDiceLogFlooding();
+	
+	@Key("RollDicePunishmentLimit")
+	Integer getRollDicePunishmentLimit();
+	
+	@Key("RollDicePunishmentType")
+	String getRollDicePunishmentType();
+	
+	@Key("RollDicePunishmentTime")
+	Integer getRollDicePunishmentTime();
+	
+	@Key("FireworkInterval")
+	Integer getFireworkInterval();
+	
+	@Key("FireworkLogFlooding")
+	Boolean fireworkLogFlooding();
+	
+	@Key("FireworkPunishmentLimit")
+	Integer getFireworkPunishmentLimit();
+	
+	@Key("FireworkPunishmentType")
+	String getFireworkPunishmentType();
+	
+	@Key("FireworkPunishmentTime")
+	Integer getFireworkPunishmentTime();
+	
+	@Key("ItemPetSummonInterval")
+	Integer geItemPetSummonInterval();
+	
+	@Key("ItemPetSummonLogFlooding")
+	Boolean itemPetSummonLogFlooding();
+	
+	@Key("ItemPetSummonPunishmentLimit")
+	Integer getItemPetSummonPunishmentLimit();
+	
+	@Key("ItemPetSummonPunishmentType")
+	String getItemPetSummonPunishmentType();
+	
+	@Key("ItemPetSummonPunishmentTime")
+	Integer getItemPetSummonPunishmentTime();
+	
+	@Key("HeroVoiceInterval")
+	Integer getHeroVoiceInterval();
+	
+	@Key("HeroVoiceLogFlooding")
+	Boolean heroVoiceLogFlooding();
+	
+	@Key("HeroVoicePunishmentLimit")
+	Integer getHeroVoicePunishmentLimit();
+	
+	@Key("HeroVoicePunishmentType")
+	String getHeroVoicePunishmentType();
+	
+	@Key("HeroVoicePunishmentTime")
+	Integer getHeroVoicePunishmentTime();
+	
+	@Key("GlobalChatInterval")
+	Integer getGlobalChatInterval();
+	
+	@Key("GlobalChatLogFlooding")
+	Boolean globalChatLogFlooding();
+	
+	@Key("GlobalChatPunishmentLimit")
+	Integer getGlobalChatPunishmentLimit();
+	
+	@Key("GlobalChatPunishmentType")
+	String getGlobalChatPunishmentType();
+	
+	@Key("GlobalChatPunishmentTime")
+	Integer getGlobalChatPunishmentTime();
+	
+	@Key("SubclassInterval")
+	Integer getSubclassInterval();
+	
+	@Key("SubclassLogFlooding")
+	Boolean subclassLogFlooding();
+	
+	@Key("SubclassPunishmentLimit")
+	Integer getSubclassPunishmentLimit();
+	
+	@Key("SubclassPunishmentType")
+	String getSubclassPunishmentType();
+	
+	@Key("SubclassPunishmentTime")
+	Integer getSubclassPunishmentTime();
+	
+	@Key("DropItemInterval")
+	Integer getDropItemInterval();
+	
+	@Key("DropItemLogFlooding")
+	Boolean dropItemLogFlooding();
+	
+	@Key("DropItemPunishmentLimit")
+	Integer getDropItemPunishmentLimit();
+	
+	@Key("DropItemPunishmentType")
+	String getDropItemPunishmentType();
+	
+	@Key("DropItemPunishmentTime")
+	Integer getDropItemPunishmentTime();
+	
+	@Key("ServerBypassInterval")
+	Integer getServerBypassInterval();
+	
+	@Key("ServerBypassLogFlooding")
+	Boolean serverBypassLogFlooding();
+	
+	@Key("ServerBypassPunishmentLimit")
+	Integer getServerBypassPunishmentLimit();
+	
+	@Key("ServerBypassPunishmentType")
+	String getServerBypassPunishmentType();
+	
+	@Key("ServerBypassPunishmentTime")
+	Integer getServerBypassPunishmentTime();
+	
+	@Key("MultiSellInterval")
+	Integer getMultiSellInterval();
+	
+	@Key("MultiSellLogFlooding")
+	Boolean multiSellLogFlooding();
+	
+	@Key("MultiSellPunishmentLimit")
+	Integer getMultiSellPunishmentLimit();
+	
+	@Key("MultiSellPunishmentType")
+	String getMultiSellPunishmentType();
+	
+	@Key("MultiSellPunishmentTime")
+	Integer getMultiSellPunishmentTime();
+	
+	@Key("TransactionInterval")
+	Integer getTransactionInterval();
+	
+	@Key("TransactionLogFlooding")
+	Boolean transactionLogFlooding();
+	
+	@Key("TransactionPunishmentLimit")
+	Integer getTransactionPunishmentLimit();
+	
+	@Key("TransactionPunishmentType")
+	String getTransactionPunishmentType();
+	
+	@Key("TransactionPunishmentTime")
+	Integer getTransactionPunishmentTime();
+	
+	@Key("ManufactureInterval")
+	Integer getManufactureInterval();
+	
+	@Key("ManufactureLogFlooding")
+	Boolean manufactureLogFlooding();
+	
+	@Key("ManufacturePunishmentLimit")
+	Integer getManufacturePunishmentLimit();
+	
+	@Key("ManufacturePunishmentType")
+	String getManufacturePunishmentType();
+	
+	@Key("ManufacturePunishmentTime")
+	Integer getManufacturePunishmentTime();
+	
+	@Key("ManorInterval")
+	Integer getManorInterval();
+	
+	@Key("ManorLogFlooding")
+	Boolean manorLogFlooding();
+	
+	@Key("ManorPunishmentLimit")
+	Integer getManorPunishmentLimit();
+	
+	@Key("ManorPunishmentType")
+	String getManorPunishmentType();
+	
+	@Key("ManorPunishmentTime")
+	Integer getManorPunishmentTime();
+	
+	@Key("SendMailInterval")
+	Integer getSendMailInterval();
+	
+	@Key("SendMailLogFlooding")
+	Boolean sendMailLogFlooding();
+	
+	@Key("SendMailPunishmentLimit")
+	Integer getSendMailPunishmentLimit();
+	
+	@Key("SendMailPunishmentType")
+	String getSendMailPunishmentType();
+	
+	@Key("SendMailPunishmentTime")
+	Integer getSendMailPunishmentTime();
+	
+	@Key("CharacterSelectInterval")
+	Integer getCharacterSelectInterval();
+	
+	@Key("CharacterSelectLogFlooding")
+	Boolean characterSelectLogFlooding();
+	
+	@Key("CharacterSelectPunishmentLimit")
+	Integer getCharacterSelectPunishmentLimit();
+	
+	@Key("CharacterSelectPunishmentType")
+	String getCharacterSelectPunishmentType();
+	
+	@Key("CharacterSelectPunishmentTime")
+	Integer getCharacterSelectPunishmentTime();
+	
+	@Key("ItemAuctionInterval")
+	Integer getItemAuctionInterval();
+	
+	@Key("ItemAuctionLogFlooding")
+	Boolean itemAuctionLogFlooding();
+	
+	@Key("ItemAuctionPunishmentLimit")
+	Integer getItemAuctionPunishmentLimit();
+	
+	@Key("ItemAuctionPunishmentType")
+	String getItemAuctionPunishmentType();
+	
+	@Key("ItemAuctionPunishmentTime")
+	Integer getItemAuctionPunishmentTime();
+}

+ 470 - 0
src/main/java/com/l2jserver/gameserver/config/FortSiegeConfiguration.java

@@ -0,0 +1,470 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Accessible;
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Fort Siege Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/fortsiege.properties",
+	"classpath:config/fortsiege.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface FortSiegeConfiguration extends Config, Accessible, Reloadable {
+	
+	@Key("SiegeLength")
+	Long getSiegeLength();
+	
+	@Key("SuspiciousMerchantRespawnDelay")
+	Integer getSuspiciousMerchantRespawnDelay();
+	
+	@Key("CountDownLength")
+	Integer getCountDownLength();
+	
+	@Key("MaxFlags")
+	Integer getMaxFlags();
+	
+	@Key("SiegeClanMinLevel")
+	Integer getSiegeClanMinLevel();
+	
+	@Key("AttackerMaxClans")
+	Integer getAttackerMaxClans();
+	
+	@Key("JustToTerritory")
+	Boolean justToTerritory();
+	
+	@Key("ShantyCommander1")
+	String getShantyCommander1();
+	
+	@Key("ShantyCommander2")
+	String getShantyCommander2();
+	
+	@Key("ShantyCommander3")
+	String getShantyCommander3();
+	
+	@Key("ShantyFlag1")
+	String getShantyFlag1();
+	
+	@Key("ShantyFlag2")
+	String getShantyFlag2();
+	
+	@Key("ShantyFlag3")
+	String getShantyFlag3();
+	
+	@Key("SouthernCommander1")
+	String getSouthernCommander1();
+	
+	@Key("SouthernCommander2")
+	String getSouthernCommander2();
+	
+	@Key("SouthernCommander3")
+	String getSouthernCommander3();
+	
+	@Key("SouthernCommander4")
+	String getSouthernCommander4();
+	
+	@Key("SouthernFlag1")
+	String getSouthernFlag1();
+	
+	@Key("SouthernFlag2")
+	String getSouthernFlag2();
+	
+	@Key("SouthernFlag3")
+	String getSouthernFlag3();
+	
+	@Key("HiveCommander1")
+	String getHiveCommander1();
+	
+	@Key("HiveCommander2")
+	String getHiveCommander2();
+	
+	@Key("HiveCommander3")
+	String getHiveCommander3();
+	
+	@Key("HiveFlag1")
+	String getHiveFlag1();
+	
+	@Key("HiveFlag2")
+	String getHiveFlag2();
+	
+	@Key("HiveFlag3")
+	String getHiveFlag3();
+	
+	@Key("ValleyCommander1")
+	String getValleyCommander1();
+	
+	@Key("ValleyCommander2")
+	String getValleyCommander2();
+	
+	@Key("ValleyCommander3")
+	String getValleyCommander3();
+	
+	@Key("ValleyCommander4")
+	String getValleyCommander4();
+	
+	@Key("ValleyFlag1")
+	String getValleyFlag1();
+	
+	@Key("ValleyFlag2")
+	String getValleyFlag2();
+	
+	@Key("ValleyFlag3")
+	String getValleyFlag3();
+	
+	@Key("IvoryCommander1")
+	String getIvoryCommander1();
+	
+	@Key("IvoryCommander2")
+	String getIvoryCommander2();
+	
+	@Key("IvoryCommander3")
+	String getIvoryCommander3();
+	
+	@Key("IvoryFlag1")
+	String getIvoryFlag1();
+	
+	@Key("IvoryFlag2")
+	String getIvoryFlag2();
+	
+	@Key("IvoryFlag3")
+	String getIvoryFlag3();
+	
+	@Key("NarsellCommander1")
+	String getNarsellCommander1();
+	
+	@Key("NarsellCommander2")
+	String getNarsellCommander2();
+	
+	@Key("NarsellCommander3")
+	String getNarsellCommander3();
+	
+	@Key("NarsellFlag1")
+	String getNarsellFlag1();
+	
+	@Key("NarsellFlag2")
+	String getNarsellFlag2();
+	
+	@Key("NarsellFlag3")
+	String getNarsellFlag3();
+	
+	@Key("BayouCommander1")
+	String getBayouCommander1();
+	
+	@Key("BayouCommander2")
+	String getBayouCommander2();
+	
+	@Key("BayouCommander3")
+	String getBayouCommander3();
+	
+	@Key("BayouCommander4")
+	String getBayouCommander4();
+	
+	@Key("BayouFlag1")
+	String getBayouFlag1();
+	
+	@Key("BayouFlag2")
+	String getBayouFlag2();
+	
+	@Key("BayouFlag3")
+	String getBayouFlag3();
+	
+	@Key("WhiteSandsCommander1")
+	String getWhiteSandsCommander1();
+	
+	@Key("WhiteSandsCommander2")
+	String getWhiteSandsCommander2();
+	
+	@Key("WhiteSandsCommander3")
+	String getWhiteSandsCommander3();
+	
+	@Key("WhiteSandsFlag1")
+	String getWhiteSandsFlag1();
+	
+	@Key("WhiteSandsFlag2")
+	String getWhiteSandsFlag2();
+	
+	@Key("WhiteSandsFlag3")
+	String getWhiteSandsFlag3();
+	
+	@Key("BorderlandCommander1")
+	String getBorderlandCommander1();
+	
+	@Key("BorderlandCommander2")
+	String getBorderlandCommander2();
+	
+	@Key("BorderlandCommander3")
+	String getBorderlandCommander3();
+	
+	@Key("BorderlandCommander4")
+	String getBorderlandCommander4();
+	
+	@Key("BorderlandFlag1")
+	String getBorderlandFlag1();
+	
+	@Key("BorderlandFlag2")
+	String getBorderlandFlag2();
+	
+	@Key("BorderlandFlag3")
+	String getBorderlandFlag3();
+	
+	@Key("SwampCommander1")
+	String getSwampCommander1();
+	
+	@Key("SwampCommander2")
+	String getSwampCommander2();
+	
+	@Key("SwampCommander3")
+	String getSwampCommander3();
+	
+	@Key("SwampCommander4")
+	String getSwampCommander4();
+	
+	@Key("SwampFlag1")
+	String getSwampFlag1();
+	
+	@Key("SwampFlag2")
+	String getSwampFlag2();
+	
+	@Key("SwampFlag3")
+	String getSwampFlag3();
+	
+	@Key("ArchaicCommander1")
+	String getArchaicCommander1();
+	
+	@Key("ArchaicCommander2")
+	String getArchaicCommander2();
+	
+	@Key("ArchaicCommander3")
+	String getArchaicCommander3();
+	
+	@Key("ArchaicFlag1")
+	String getArchaicFlag1();
+	
+	@Key("ArchaicFlag2")
+	String getArchaicFlag2();
+	
+	@Key("ArchaicFlag3")
+	String getArchaicFlag3();
+	
+	@Key("FloranCommander1")
+	String getFloranCommander1();
+	
+	@Key("FloranCommander2")
+	String getFloranCommander2();
+	
+	@Key("FloranCommander3")
+	String getFloranCommander3();
+	
+	@Key("FloranCommander4")
+	String getFloranCommander4();
+	
+	@Key("FloranFlag1")
+	String getFloranFlag1();
+	
+	@Key("FloranFlag2")
+	String getFloranFlag2();
+	
+	@Key("FloranFlag3")
+	String getFloranFlag3();
+	
+	@Key("CloudMountainCommander1")
+	String getCloudMountainCommander1();
+	
+	@Key("CloudMountainCommander2")
+	String getCloudMountainCommander2();
+	
+	@Key("CloudMountainCommander3")
+	String getCloudMountainCommander3();
+	
+	@Key("CloudMountainCommander4")
+	String getCloudMountainCommander4();
+	
+	@Key("CloudMountainFlag1")
+	String getCloudMountainFlag1();
+	
+	@Key("CloudMountainFlag2")
+	String getCloudMountainFlag2();
+	
+	@Key("CloudMountainFlag3")
+	String getCloudMountainFlag3();
+	
+	@Key("TanorCommander1")
+	String getTanorCommander1();
+	
+	@Key("TanorCommander2")
+	String getTanorCommander2();
+	
+	@Key("TanorCommander3")
+	String getTanorCommander3();
+	
+	@Key("TanorFlag1")
+	String getTanorFlag1();
+	
+	@Key("TanorFlag2")
+	String getTanorFlag2();
+	
+	@Key("TanorFlag3")
+	String getTanorFlag3();
+	
+	@Key("DragonspineCommander1")
+	String getDragonspineCommander1();
+	
+	@Key("DragonspineCommander2")
+	String getDragonspineCommander2();
+	
+	@Key("DragonspineCommander3")
+	String getDragonspineCommander3();
+	
+	@Key("DragonspineFlag1")
+	String getDragonspineFlag1();
+	
+	@Key("DragonspineFlag2")
+	String getDragonspineFlag2();
+	
+	@Key("DragonspineFlag3")
+	String getDragonspineFlag3();
+	
+	@Key("AntharasCommander1")
+	String getAntharasCommander1();
+	
+	@Key("AntharasCommander2")
+	String getAntharasCommander2();
+	
+	@Key("AntharasCommander3")
+	String getAntharasCommander3();
+	
+	@Key("AntharasCommander4")
+	String getAntharasCommander4();
+	
+	@Key("AntharasFlag1")
+	String getAntharasFlag1();
+	
+	@Key("AntharasFlag2")
+	String getAntharasFlag2();
+	
+	@Key("AntharasFlag3")
+	String getAntharasFlag3();
+	
+	@Key("WesternCommander1")
+	String getWesternCommander1();
+	
+	@Key("WesternCommander2")
+	String getWesternCommander2();
+	
+	@Key("WesternCommander3")
+	String getWesternCommander3();
+	
+	@Key("WesternCommander4")
+	String getWesternCommander4();
+	
+	@Key("WesternFlag1")
+	String getWesternFlag1();
+	
+	@Key("WesternFlag2")
+	String getWesternFlag2();
+	
+	@Key("WesternFlag3")
+	String getWesternFlag3();
+	
+	@Key("HuntersCommander1")
+	String getHuntersCommander1();
+	
+	@Key("HuntersCommander2")
+	String getHuntersCommander2();
+	
+	@Key("HuntersCommander3")
+	String getHuntersCommander3();
+	
+	@Key("HuntersCommander4")
+	String getHuntersCommander4();
+	
+	@Key("HuntersFlag1")
+	String getHuntersFlag1();
+	
+	@Key("HuntersFlag2")
+	String getHuntersFlag2();
+	
+	@Key("HuntersFlag3")
+	String getHuntersFlag3();
+	
+	@Key("AaruCommander1")
+	String getAaruCommander1();
+	
+	@Key("AaruCommander2")
+	String getAaruCommander2();
+	
+	@Key("AaruCommander3")
+	String getAaruCommander3();
+	
+	@Key("AaruFlag1")
+	String getAaruFlag1();
+	
+	@Key("AaruFlag2")
+	String getAaruFlag2();
+	
+	@Key("AaruFlag3")
+	String getAaruFlag3();
+	
+	@Key("DemonCommander1")
+	String getDemonCommander1();
+	
+	@Key("DemonCommander2")
+	String getDemonCommander2();
+	
+	@Key("DemonCommander3")
+	String getDemonCommander3();
+	
+	@Key("DemonFlag1")
+	String getDemonFlag1();
+	
+	@Key("DemonFlag2")
+	String getDemonFlag2();
+	
+	@Key("DemonFlag3")
+	String getDemonFlag3();
+	
+	@Key("MonasticCommander1")
+	String getMonasticCommander1();
+	
+	@Key("MonasticCommander2")
+	String getMonasticCommander2();
+	
+	@Key("MonasticCommander3")
+	String getMonasticCommander3();
+	
+	@Key("MonasticFlag1")
+	String getMonasticFlag1();
+	
+	@Key("MonasticFlag2")
+	String getMonasticFlag2();
+	
+	@Key("MonasticFlag3")
+	String getMonasticFlag3();
+}

+ 103 - 0
src/main/java/com/l2jserver/gameserver/config/FortressConfiguration.java

@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.Minutes2MillisecondsConverter;
+
+/**
+ * Fortress Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/fortress.properties",
+	"classpath:config/fortress.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface FortressConfiguration extends Config, Reloadable {
+	
+	@Key("TeleportFunctionFeeRatio")
+	Long getTeleportFunctionFeeRatio();
+	
+	@Key("TeleportFunctionFeeLvl1")
+	Integer getTeleportFunctionFeeLvl1();
+	
+	@Key("TeleportFunctionFeeLvl2")
+	Integer getTeleportFunctionFeeLvl2();
+	
+	@Key("SupportFunctionFeeRatio")
+	Long getSupportFunctionFeeRatio();
+	
+	@Key("SupportFeeLvl1")
+	Integer getSupportFeeLvl1();
+	
+	@Key("SupportFeeLvl2")
+	Integer getSupportFeeLvl2();
+	
+	@Key("MpRegenerationFunctionFeeRatio")
+	Long getMpRegenerationFunctionFeeRatio();
+	
+	@Key("MpRegenerationFeeLvl1")
+	Integer getMpRegenerationFeeLvl1();
+	
+	@Key("MpRegenerationFeeLvl2")
+	Integer getMpRegenerationFeeLvl2();
+	
+	@Key("HpRegenerationFunctionFeeRatio")
+	Long getHpRegenerationFunctionFeeRatio();
+	
+	@Key("HpRegenerationFeeLvl1")
+	Integer getHpRegenerationFeeLvl1();
+	
+	@Key("HpRegenerationFeeLvl2")
+	Integer getHpRegenerationFeeLvl2();
+	
+	@Key("ExpRegenerationFunctionFeeRatio")
+	Long getExpRegenerationFunctionFeeRatio();
+	
+	@Key("ExpRegenerationFeeLvl1")
+	Integer getExpRegenerationFeeLvl1();
+	
+	@Key("ExpRegenerationFeeLvl2")
+	Integer getExpRegenerationFeeLvl2();
+	
+	@Key("PeriodicUpdateFrequency")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getPeriodicUpdateFrequency();
+	
+	@Key("BloodOathCount")
+	Integer getBloodOathCount();
+	
+	@Key("MaxSupplyLevel")
+	Integer getMaxSupplyLevel();
+	
+	@Key("FeeForCastle")
+	Integer getFeeForCastle();
+	
+	@Key("MaxKeepTime")
+	Integer getMaxKeepTime();
+}

+ 626 - 0
src/main/java/com/l2jserver/gameserver/config/GeneralConfiguration.java

@@ -0,0 +1,626 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.Set;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Mutable;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.Minutes2MillisecondsConverter;
+import com.l2jserver.gameserver.config.converter.Seconds2MillisecondsConverter;
+import com.l2jserver.gameserver.config.converter.ServerListTypeConverter;
+import com.l2jserver.gameserver.enums.IllegalActionPunishmentType;
+
+/**
+ * General Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/general.properties",
+	"classpath:config/general.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface GeneralConfiguration extends Config, Mutable, Reloadable {
+	
+	@Key("EverybodyHasAdminRights")
+	Boolean everybodyHasAdminRights();
+	
+	@Key("ServerListBrackets")
+	Boolean getServerListBrackets();
+	
+	@Key("ServerListType")
+	@ConverterClass(ServerListTypeConverter.class)
+	Integer getServerListType();
+	
+	@Key("ServerListAge")
+	Integer getServerListAge();
+	
+	@Key("ServerGMOnly")
+	Boolean serverGMOnly();
+	
+	@Key("GMHeroAura")
+	Boolean gmHeroAura();
+	
+	@Key("GMStartupInvulnerable")
+	Boolean gmStartupInvulnerable();
+	
+	@Key("GMStartupInvisible")
+	Boolean gmStartupInvisible();
+	
+	@Key("GMStartupSilence")
+	Boolean gmStartupSilence();
+	
+	@Key("GMStartupAutoList")
+	Boolean gmStartupAutoList();
+	
+	@Key("GMStartupDietMode")
+	Boolean gmStartupDietMode();
+	
+	@Key("GMItemRestriction")
+	Boolean gmItemRestriction();
+	
+	@Key("GMSkillRestriction")
+	Boolean gmSkillRestriction();
+	
+	@Key("GMTradeRestrictedItems")
+	Boolean gmTradeRestrictedItems();
+	
+	@Key("GMRestartFighting")
+	Boolean gmRestartFighting();
+	
+	@Key("GMShowAnnouncerName")
+	Boolean gmShowAnnouncerName();
+	
+	@Key("GMShowCritAnnouncerName")
+	Boolean gmShowCritAnnouncerName();
+	
+	@Key("GMGiveSpecialSkills")
+	Boolean gmGiveSpecialSkills();
+	
+	@Key("GMGiveSpecialAuraSkills")
+	Boolean gmGiveSpecialAuraSkills();
+	
+	@Key("GameGuardEnforce")
+	Boolean gameGuardEnforce();
+	
+	@Key("GameGuardProhibitAction")
+	Boolean gameGuardProhibitAction();
+	
+	@Key("LogChat")
+	Boolean logChat();
+	
+	@Key("LogAutoAnnouncements")
+	Boolean logAutoAnnouncements();
+	
+	@Key("LogItems")
+	Boolean logItems();
+	
+	@Key("LogItemsSmallLog")
+	Boolean logItemsSmallLog();
+	
+	@Key("LogItemEnchants")
+	Boolean logItemEnchants();
+	
+	@Key("LogSkillEnchants")
+	Boolean logSkillEnchants();
+	
+	@Key("GMAudit")
+	Boolean gmAudit();
+	
+	@Key("SkillCheckEnable")
+	Boolean skillCheckEnable();
+	
+	@Key("SkillCheckRemove")
+	Boolean skillCheckRemove();
+	
+	@Key("SkillCheckGM")
+	Boolean skillCheckGM();
+	
+	@Key("ThreadPoolSizeEffects")
+	Integer getThreadPoolSizeEffects();
+	
+	@Key("ThreadPoolSizeGeneral")
+	Integer getThreadPoolSizeGeneral();
+	
+	@Key("ThreadPoolSizeEvents")
+	Integer getThreadPoolSizeEvents();
+	
+	@Key("UrgentPacketThreadCoreSize")
+	Integer getUrgentPacketThreadCoreSize();
+	
+	@Key("GeneralPacketThreadCoreSize")
+	Integer getGeneralPacketThreadCoreSize();
+	
+	@Key("GeneralThreadCoreSize")
+	Integer getGeneralThreadCoreSize();
+	
+	@Key("AiMaxThread")
+	Integer getAiMaxThread();
+	
+	@Key("EventsMaxThread")
+	Integer getEventsMaxThread();
+	
+	@Key("DeadLockDetector")
+	Boolean deadLockDetector();
+	
+	@Key("DeadLockCheckInterval")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getDeadLockCheckInterval();
+	
+	@Key("RestartOnDeadlock")
+	Boolean restartOnDeadlock();
+	
+	@Key("ClientPacketQueueSize")
+	Integer getClientPacketQueueSize();
+	
+	@Key("ClientPacketQueueMaxBurstSize")
+	Integer getClientPacketQueueMaxBurstSize();
+	
+	@Key("ClientPacketQueueMaxPacketsPerSecond")
+	Integer getClientPacketQueueMaxPacketsPerSecond();
+	
+	@Key("ClientPacketQueueMeasureInterval")
+	Integer getClientPacketQueueMeasureInterval();
+	
+	@Key("ClientPacketQueueMaxAveragePacketsPerSecond")
+	Integer getClientPacketQueueMaxAveragePacketsPerSecond();
+	
+	@Key("ClientPacketQueueMaxFloodsPerMin")
+	Integer getClientPacketQueueMaxFloodsPerMin();
+	
+	@Key("ClientPacketQueueMaxOverflowsPerMin")
+	Integer getClientPacketQueueMaxOverflowsPerMin();
+	
+	@Key("ClientPacketQueueMaxUnderflowsPerMin")
+	Integer getClientPacketQueueMaxUnderflowsPerMin();
+	
+	@Key("ClientPacketQueueMaxUnknownPerMin")
+	Integer getClientPacketQueueMaxUnknownPerMin();
+	
+	@Key("AllowDiscardItem")
+	Boolean allowDiscardItem();
+	
+	@Key("AutoDestroyDroppedItemAfter")
+	Integer getAutoDestroyDroppedItemAfter();
+	
+	@Key("AutoDestroyHerbTime")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getAutoDestroyHerbTime();
+	
+	@Key("ProtectedItems")
+	Set<Integer> getProtectedItems();
+	
+	@Key("DatabaseCleanUp")
+	Boolean databaseCleanUp();
+	
+	@Key("ConnectionCloseTime")
+	Long getConnectionCloseTime();
+	
+	@Key("CharacterDataStoreInterval")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getCharacterDataStoreInterval();
+	
+	@Key("LazyItemsUpdate")
+	Boolean lazyItemsUpdate();
+	
+	@Key("UpdateItemsOnCharStore")
+	Boolean updateItemsOnCharStore();
+	
+	@Key("DestroyPlayerDroppedItem")
+	Boolean destroyPlayerDroppedItem();
+	
+	@Key("DestroyEquipableItem")
+	Boolean destroyEquipableItem();
+	
+	@Key("SaveDroppedItem")
+	Boolean saveDroppedItem();
+	
+	@Key("EmptyDroppedItemTableAfterLoad")
+	Boolean emptyDroppedItemTableAfterLoad();
+	
+	@Key("SaveDroppedItemInterval")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getSaveDroppedItemInterval();
+	
+	@Key("ClearDroppedItemTable")
+	Boolean clearDroppedItemTable();
+	
+	@Key("AutoDeleteInvalidQuestData")
+	Boolean autoDeleteInvalidQuestData();
+	
+	@Key("PreciseDropCalculation")
+	Boolean preciseDropCalculation();
+	
+	@Key("MultipleItemDrop")
+	Boolean multipleItemDrop();
+	
+	@Key("ForceInventoryUpdate")
+	Boolean forceInventoryUpdate();
+	
+	@Key("LazyCache")
+	Boolean lazyCache();
+	
+	@Key("CacheCharNames")
+	Boolean cacheCharNames();
+	
+	@Key("MinNPCAnimation")
+	Integer getMinNPCAnimation();
+	
+	@Key("MaxNPCAnimation")
+	Integer getMaxNPCAnimation();
+	
+	@Key("MinMonsterAnimation")
+	Integer getMinMonsterAnimation();
+	
+	@Key("MaxMonsterAnimation")
+	Integer getMaxMonsterAnimation();
+	
+	@Key("MoveBasedKnownList")
+	Boolean moveBasedKnownList();
+	
+	@Key("KnownListUpdateInterval")
+	Long getKnownListUpdateInterval();
+	
+	@Key("CheckKnownList")
+	Boolean checkKnownList();
+	
+	@Key("GridsAlwaysOn")
+	Boolean gridsAlwaysOn();
+	
+	@Key("GridNeighborTurnOnTime")
+	Integer getGridNeighborTurnOnTime();
+	
+	@Key("GridNeighborTurnOffTime")
+	Integer getGridNeighborTurnOffTime();
+	
+	@Key("EnableFallingDamage")
+	Boolean enableFallingDamage();
+	
+	@Key("PeaceZoneMode")
+	Integer getPeaceZoneMode();
+	
+	@Key("GlobalChat")
+	String getGlobalChat();
+	
+	@Key("TradeChat")
+	String getTradeChat();
+	
+	@Key("AllowWarehouse")
+	Boolean allowWarehouse();
+	
+	@Key("WarehouseCache")
+	Boolean warehouseCache();
+	
+	@Key("WarehouseCacheTime")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getWarehouseCacheTime();
+	
+	@Key("AllowRefund")
+	Boolean allowRefund();
+	
+	@Key("AllowMail")
+	Boolean allowMail();
+	
+	@Key("AllowAttachments")
+	Boolean allowAttachments();
+	
+	@Key("AllowWear")
+	Boolean allowWear();
+	
+	@Key("WearDelay")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getWearDelay();
+	
+	@Key("WearPrice")
+	Integer getWearPrice();
+	
+	@Key("RestorePlayerInstance")
+	Boolean restorePlayerInstance();
+	
+	@Key("AllowSummonInInstance")
+	Boolean allowSummonInInstance();
+	
+	@Key("EjectDeadPlayerTime")
+	Integer getEjectDeadPlayerTime();
+	
+	@Key("InstanceFinishTime")
+	Integer getInstanceFinishTime();
+	
+	@Key("AllowRace")
+	Boolean allowRace();
+	
+	@Key("AllowWater")
+	Boolean allowWater();
+	
+	@Key("AllowRentPet")
+	Boolean allowRentPet();
+	
+	@Key("AllowFishing")
+	Boolean allowFishing();
+	
+	@Key("AllowBoat")
+	Boolean allowBoat();
+	
+	@Key("BoatBroadcastRadius")
+	Integer getBoatBroadcastRadius();
+	
+	@Key("AllowCursedWeapons")
+	Boolean allowCursedWeapons();
+	
+	@Key("AllowPetWalkers")
+	Boolean allowPetWalkers();
+	
+	@Key("ShowServerNews")
+	Boolean showServerNews();
+	
+	@Key("EnableCommunityBoard")
+	Boolean enableCommunityBoard();
+	
+	@Key("BBSDefault")
+	String getBBSDefault();
+	
+	@Key("UseChatFilter")
+	Boolean useChatFilter();
+	
+	@Key("ChatFilterChars")
+	String getChatFilterChars();
+	
+	@Key("ChatFilter")
+	Set<String> getChatFilter();
+	
+	@Key("BanChatChannels")
+	Set<Integer> getBanChatChannels();
+	
+	@Key("AllowManor")
+	Boolean allowManor();
+	
+	@Key("ManorRefreshTime")
+	Integer getManorRefreshTime();
+	
+	@Key("ManorRefreshMin")
+	Integer getManorRefreshMin();
+	
+	@Key("ManorApproveTime")
+	Integer getManorApproveTime();
+	
+	@Key("ManorApproveMin")
+	Integer getManorApproveMin();
+	
+	@Key("ManorMaintenanceMin")
+	Integer getManorMaintenanceMin();
+	
+	@Key("ManorSaveAllActions")
+	Boolean manorSaveAllActions();
+	
+	@Key("ManorSavePeriodRate")
+	Integer getManorSavePeriodRate();
+	
+	@Key("AllowLottery")
+	Boolean allowLottery();
+	
+	@Key("LotteryPrize")
+	Long getLotteryPrize();
+	
+	@Key("LotteryTicketPrice")
+	Long getLotteryTicketPrice();
+	
+	@Key("Lottery5NumberRate")
+	Float getLottery5NumberRate();
+	
+	@Key("Lottery4NumberRate")
+	Float getLottery4NumberRate();
+	
+	@Key("Lottery3NumberRate")
+	Float getLottery3NumberRate();
+	
+	@Key("Lottery2and1NumberPrize")
+	Long getLottery2and1NumberPrize();
+	
+	@Key("ItemAuctionEnabled")
+	Boolean itemAuctionEnabled();
+	
+	@Key("ItemAuctionExpiredAfter")
+	Integer getItemAuctionExpiredAfter();
+	
+	@Key("ItemAuctionTimeExtendsOnBid")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getItemAuctionTimeExtendsOnBid();
+	
+	@Key("RiftMinPartySize")
+	Integer getRiftMinPartySize();
+	
+	@Key("MaxRiftJumps")
+	Integer getMaxRiftJumps();
+	
+	@Key("RiftSpawnDelay")
+	Integer getRiftSpawnDelay();
+	
+	@Key("AutoJumpsDelayMin")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getAutoJumpsDelayMin();
+	
+	@Key("AutoJumpsDelayMax")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getAutoJumpsDelayMax();
+	
+	@Key("BossRoomTimeMultiply")
+	Float getBossRoomTimeMultiply();
+	
+	@Key("RecruitCost")
+	Integer getRecruitCost();
+	
+	@Key("SoldierCost")
+	Integer getSoldierCost();
+	
+	@Key("OfficerCost")
+	Integer getOfficerCost();
+	
+	@Key("CaptainCost")
+	Integer getCaptainCost();
+	
+	@Key("CommanderCost")
+	Integer getCommanderCost();
+	
+	@Key("HeroCost")
+	Integer getHeroCost();
+	
+	@Key("TimeOfAttack")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getTimeOfAttack();
+	
+	@Key("TimeOfCoolDown")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getTimeOfCoolDown();
+	
+	@Key("TimeOfEntry")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getTimeOfEntry();
+	
+	@Key("TimeOfWarmUp")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getTimeOfWarmUp();
+	
+	// TODO(Zoey76): Move this four sepulchers to own configuration file.
+	@Key("NumberOfNecessaryPartyMembers")
+	Integer getNumberOfNecessaryPartyMembers();
+	
+	@Key("DefaultPunish")
+	IllegalActionPunishmentType getDefaultPunish();
+	
+	@Key("DefaultPunishParam")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getDefaultPunishParam();
+	
+	@Key("OnlyGMItemsFree")
+	Boolean onlyGMItemsFree();
+	
+	@Key("JailIsPvp")
+	Boolean jailIsPvp();
+	
+	@Key("JailDisableChat")
+	Boolean jailDisableChat();
+	
+	@Key("JailDisableTransaction")
+	Boolean jailDisableTransaction();
+	
+	@Key("NormalEnchantCostMultipiler")
+	Integer getNormalEnchantCostMultipiler();
+	
+	@Key("SafeEnchantCostMultipiler")
+	Integer getSafeEnchantCostMultipiler();
+	
+	@Key("CustomSpawnlistTable")
+	Boolean customSpawnlistTable();
+	
+	@Key("SaveGmSpawnOnCustom")
+	Boolean saveGmSpawnOnCustom();
+	
+	@Key("CustomNpcData")
+	Boolean customNpcData();
+	
+	@Key("CustomTeleportTable")
+	Boolean customTeleportTable();
+	
+	@Key("CustomNpcBufferTables")
+	Boolean customNpcBufferTables();
+	
+	@Key("CustomSkillsLoad")
+	Boolean customSkillsLoad();
+	
+	@Key("CustomItemsLoad")
+	Boolean customItemsLoad();
+	
+	@Key("CustomMultisellLoad")
+	Boolean customMultisellLoad();
+	
+	@Key("CustomBuyListLoad")
+	Boolean customBuyListLoad();
+	
+	@Key("BirthdayGift")
+	Integer getBirthdayGift();
+	
+	@Key("BirthdayMailSubject")
+	String getBirthdayMailSubject();
+	
+	@Key("BirthdayMailText")
+	String getBirthdayMailText();
+	
+	@Key("EnableBlockCheckerEvent")
+	Boolean enableBlockCheckerEvent();
+	
+	@Key("BlockCheckerMinTeamMembers")
+	Integer getBlockCheckerMinTeamMembers();
+	
+	@Key("HBCEFairPlay")
+	Boolean isHBCEFairPlay();
+	
+	@Key("HellboundWithoutQuest")
+	Boolean hellboundWithoutQuest();
+	
+	@Key("EnableBotReportButton")
+	Boolean enableBotReportButton();
+	
+	@Key("BotReportPointsResetHour")
+	String getBotReportPointsResetHour();
+	
+	@Key("BotReportDelay")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getBotReportDelay();
+	
+	@Key("AllowReportsFromSameClanMembers")
+	Boolean allowReportsFromSameClanMembers();
+	
+	@Key("Debug")
+	Boolean debug();
+	
+	@Key("InstanceDebug")
+	Boolean instanceDebug();
+	
+	@Key("HtmlActionCacheDebug")
+	Boolean htmlActionCacheDebug();
+	
+	@Key("PacketHandlerDebug")
+	Boolean packetHandlerDebug();
+	
+	@Key("Developer")
+	Boolean developer();
+	
+	@Key("NoHandlers")
+	Boolean noHandlers();
+	
+	@Key("NoQuests")
+	Boolean noQuests();
+	
+	@Key("NoSpawns")
+	Boolean noSpawns();
+	
+	@Key("ShowQuestsLoadInLogs")
+	Boolean showQuestsLoadInLogs();
+	
+	@Key("ShowScriptsLoadInLogs")
+	Boolean showScriptsLoadInLogs();
+}

+ 103 - 0
src/main/java/com/l2jserver/gameserver/config/GeodataConfiguration.java

@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.io.File;
+import java.util.List;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Mutable;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Geodata Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/geodata.properties",
+	"classpath:config/geodata.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface GeodataConfiguration extends Config, Mutable, Reloadable {
+	
+	/**
+	 * Pathfinding options:
+	 * <ul>
+	 * <li>0 = Disabled</li>
+	 * <li>1 = Enabled using path node files</li>
+	 * <li>2 = Enabled using geodata cells at runtime</li>
+	 * </ul>
+	 * @return
+	 */
+	@Key("PathFinding")
+	Integer getPathFinding();
+	
+	@Key("PathnodePath")
+	File getPathnodePath();
+	
+	@Key("PathFindBuffers")
+	String getPathFindBuffers();
+	
+	@Key("LowWeight")
+	Float getLowWeight();
+	
+	@Key("MediumWeight")
+	Float getMediumWeight();
+	
+	@Key("HighWeight")
+	Float getHighWeight();
+	
+	@Key("AdvancedDiagonalStrategy")
+	Boolean advancedDiagonalStrategy();
+	
+	@Key("DiagonalWeight")
+	Float getDiagonalWeight();
+	
+	@Key("MaxPostfilterPasses")
+	Integer getMaxPostfilterPasses();
+	
+	@Key("DebugPath")
+	Boolean debugPath();
+	
+	@Key("ForceGeoData")
+	Boolean forceGeoData();
+	
+	@Key("CoordSynchronize")
+	Integer getCoordSynchronize();
+	
+	@Key("GeoDataPath")
+	File getGeoDataPath();
+	
+	@Key("TryLoadUnspecifiedRegions")
+	Boolean tryLoadUnspecifiedRegions();
+	
+	@Separator(";")
+	@Key("IncludedRegions")
+	List<String> getIncludedRegions();
+	
+	@Separator(";")
+	@Key("ExcludedRegions")
+	List<String> getExcludedRegions();
+}

+ 46 - 0
src/main/java/com/l2jserver/gameserver/config/GraciaSeedsConfiguration.java

@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Gracia Seeds Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/graciaseeds.properties",
+	"classpath:config/graciaseeds.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface GraciaSeedsConfiguration extends Config, Reloadable {
+	
+	@Key("TiatKillCountForNextState")
+	Integer getTiatKillCountForNextState();
+	
+	@Key("Stage2Length")
+	Integer getStage2Length();
+}

+ 95 - 0
src/main/java/com/l2jserver/gameserver/config/GrandBossConfiguration.java

@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.Minutes2MillisecondsConverter;
+
+/**
+ * Grand Boss Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/grandboss.properties",
+	"classpath:config/grandboss.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface GrandBossConfiguration extends Config, Reloadable {
+	
+	@Key("AntharasWaitTime")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getAntharasWaitTime();
+	
+	@Key("IntervalOfAntharasSpawn")
+	Integer getIntervalOfAntharasSpawn();
+	
+	@Key("RandomOfAntharasSpawn")
+	Integer getRandomOfAntharasSpawn();
+	
+	@Key("ValakasWaitTime")
+	@ConverterClass(Minutes2MillisecondsConverter.class)
+	Integer getValakasWaitTime();
+	
+	@Key("IntervalOfValakasSpawn")
+	Integer getIntervalOfValakasSpawn();
+	
+	@Key("RandomOfValakasSpawn")
+	Integer getRandomOfValakasSpawn();
+	
+	@Key("IntervalOfBaiumSpawn")
+	Integer getIntervalOfBaiumSpawn();
+	
+	@Key("RandomOfBaiumSpawn")
+	Integer getRandomOfBaiumSpawn();
+	
+	@Key("IntervalOfCoreSpawn")
+	Integer getIntervalOfCoreSpawn();
+	
+	@Key("RandomOfCoreSpawn")
+	Integer getRandomOfCoreSpawn();
+	
+	@Key("IntervalOfOrfenSpawn")
+	Integer getIntervalOfOrfenSpawn();
+	
+	@Key("RandomOfOrfenSpawn")
+	Integer getRandomOfOrfenSpawn();
+	
+	@Key("IntervalOfQueenAntSpawn")
+	Integer getIntervalOfQueenAntSpawn();
+	
+	@Key("RandomOfQueenAntSpawn")
+	Integer getRandomOfQueenAntSpawn();
+	
+	@Key("IntervalOfBelethSpawn")
+	Integer getIntervalOfBelethSpawn();
+	
+	@Key("RandomOfBelethSpawn")
+	Integer getRandomOfBelethSpawn();
+	
+	@Key("BelethMinPlayers")
+	Integer getBelethMinPlayers();
+}

+ 52 - 0
src/main/java/com/l2jserver/gameserver/config/HexIdConfiguration.java

@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.math.BigInteger;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Mutable;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.HexIdConverter;
+
+/**
+ * Hex Id Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/hexid.txt",
+	"classpath:config/hexid.txt"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface HexIdConfiguration extends Config, Mutable, Reloadable {
+	
+	@Key("ServerID")
+	Integer getServerID();
+	
+	@Key("HexID")
+	@ConverterClass(HexIdConverter.class)
+	BigInteger getHexID();
+}

+ 175 - 0
src/main/java/com/l2jserver/gameserver/config/IPConfigData.java

@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.Inet6Address;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import com.l2jserver.gameserver.GameServer;
+import com.l2jserver.gameserver.util.IXmlReader;
+
+/**
+ * IP Config Data.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class IPConfigData implements IXmlReader {
+	
+	private static final Logger LOG = LoggerFactory.getLogger(IPConfigData.class);
+	
+	private static final String IP_CONFIG_FILE = "./config/ipconfig.xml";
+	
+	private final List<String> _subnets = new ArrayList<>(5);
+	
+	private final List<String> _hosts = new ArrayList<>(5);
+	
+	public IPConfigData() {
+		load();
+	}
+	
+	@Override
+	public void load() {
+		GameServer.printSection("Network Configuration");
+		final File f = new File(IP_CONFIG_FILE);
+		if (f.exists()) {
+			LOG.info("Using existing ipconfig.xml.");
+			parseFile(new File(IP_CONFIG_FILE));
+		} else {
+			LOG.info("Using automatic network configuration.");
+			autoIpConfig();
+		}
+	}
+	
+	@Override
+	public void parseDocument(Document doc) {
+		NamedNodeMap attrs;
+		for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling()) {
+			if ("gameserver".equalsIgnoreCase(n.getNodeName())) {
+				for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) {
+					if ("define".equalsIgnoreCase(d.getNodeName())) {
+						attrs = d.getAttributes();
+						_subnets.add(attrs.getNamedItem("subnet").getNodeValue());
+						_hosts.add(attrs.getNamedItem("address").getNodeValue());
+						
+						if (_hosts.size() != _subnets.size()) {
+							LOG.warn("Failed to load {} file - subnets does not match server addresses.", IP_CONFIG_FILE);
+						}
+					}
+				}
+				
+				Node att = n.getAttributes().getNamedItem("address");
+				if (att == null) {
+					LOG.warn("Failed to load {} file - default server address is missing.", IP_CONFIG_FILE);
+					_hosts.add("127.0.0.1");
+				} else {
+					_hosts.add(att.getNodeValue());
+				}
+				_subnets.add("0.0.0.0/0");
+			}
+		}
+	}
+	
+	protected void autoIpConfig() {
+		String externalIp = "127.0.0.1";
+		try {
+			URL autoIp = new URL("http://ip1.dynupdate.no-ip.com:8245/");
+			try (BufferedReader in = new BufferedReader(new InputStreamReader(autoIp.openStream()))) {
+				externalIp = in.readLine();
+			}
+		} catch (IOException e) {
+			LOG.warn("Failed to connect to api.externalip.net please check your internet connection using 127.0.0.1!");
+			externalIp = "127.0.0.1";
+		}
+		
+		try {
+			Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
+			
+			while (niList.hasMoreElements()) {
+				NetworkInterface ni = niList.nextElement();
+				
+				if (!ni.isUp() || ni.isVirtual()) {
+					continue;
+				}
+				
+				if (!ni.isLoopback() && ((ni.getHardwareAddress() == null) || (ni.getHardwareAddress().length != 6))) {
+					continue;
+				}
+				
+				for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
+					if (ia.getAddress() instanceof Inet6Address) {
+						continue;
+					}
+					
+					final String hostAddress = ia.getAddress().getHostAddress();
+					final int subnetPrefixLength = ia.getNetworkPrefixLength();
+					final int subnetMaskInt = IntStream.rangeClosed(1, subnetPrefixLength).reduce((r, e) -> (r << 1) + 1).orElse(0) << (32 - subnetPrefixLength);
+					final int hostAddressInt = Arrays.stream(hostAddress.split("\\.")).mapToInt(Integer::parseInt).reduce((r, e) -> (r << 8) + e).orElse(0);
+					final int subnetAddressInt = hostAddressInt & subnetMaskInt;
+					final String subnetAddress = ((subnetAddressInt >> 24) & 0xFF) + "." + ((subnetAddressInt >> 16) & 0xFF) + "." + ((subnetAddressInt >> 8) & 0xFF) + "." + (subnetAddressInt & 0xFF);
+					final String subnet = subnetAddress + '/' + subnetPrefixLength;
+					if (!_subnets.contains(subnet) && !subnet.equals("0.0.0.0/0")) {
+						_subnets.add(subnet);
+						_hosts.add(hostAddress);
+						LOG.info("Adding new subnet: " + subnet + " address: " + hostAddress);
+					}
+				}
+			}
+			
+			// External host and subnet
+			_hosts.add(externalIp);
+			_subnets.add("0.0.0.0/0");
+			LOG.info("Adding new subnet: 0.0.0.0/0 address: {}", externalIp);
+		} catch (SocketException e) {
+			LOG.error("Configuration failed please manually configure ipconfig.xml", e);
+			System.exit(0);
+		}
+	}
+	
+	public List<String> getSubnets() {
+		if (_subnets.isEmpty()) {
+			return List.of("0.0.0.0/0");
+		}
+		return _subnets;
+	}
+	
+	public List<String> getHosts() {
+		if (_hosts.isEmpty()) {
+			return List.of("127.0.0.1");
+		}
+		return _hosts;
+	}
+}

+ 55 - 0
src/main/java/com/l2jserver/gameserver/config/MMOConfiguration.java

@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * MMO Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/mmo.properties",
+	"classpath:config/mmo.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface MMOConfiguration extends Config, Reloadable {
+	
+	@Key("SleepTime")
+	Integer getSleepTime();
+	
+	@Key("MaxSendPerPass")
+	Integer getMaxSendPerPass();
+	
+	@Key("MaxReadPerPass")
+	Integer getMaxReadPerPass();
+	
+	@Key("HelperBufferCount")
+	Integer getHelperBufferCount();
+	
+	@Key("TcpNoDelay")
+	Boolean isTcpNoDelay();
+}

+ 195 - 0
src/main/java/com/l2jserver/gameserver/config/NPCConfiguration.java

@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.MapIntegerIntegerConverter;
+
+/**
+ * NPC Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/npc.properties",
+	"classpath:config/npc.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface NPCConfiguration extends Config, Reloadable {
+	
+	@Key("AnnounceMammonSpawn")
+	Boolean announceMammonSpawn();
+	
+	@Key("MobAggroInPeaceZone")
+	Boolean mobAggroInPeaceZone();
+	
+	@Key("AttackableNpcs")
+	Boolean attackableNpcs();
+	
+	@Key("ViewNpc")
+	Boolean viewNpc();
+	
+	@Key("MaxDriftRange")
+	Integer getMaxDriftRange();
+	
+	@Key("ShowNpcLevel")
+	Boolean showNpcLevel();
+	
+	@Key("ShowCrestWithoutQuest")
+	Boolean showCrestWithoutQuest();
+	
+	@Key("RandomEnchantEffect")
+	Boolean randomEnchantEffect();
+	
+	@Key("MinNPCLevelForDmgPenalty")
+	Integer getMinNPCLevelForDmgPenalty();
+	
+	@Key("DmgPenaltyForLvLDifferences")
+	List<Double> getDmgPenaltyForLvLDifferences();
+	
+	@Key("CritDmgPenaltyForLvLDifferences")
+	List<Double> getCritDmgPenaltyForLvLDifferences();
+	
+	@Key("SkillDmgPenaltyForLvLDifferences")
+	List<Double> getSkillDmgPenaltyForLvLDifferences();
+	
+	@Key("MinNPCLevelForMagicPenalty")
+	Integer getMinNPCLevelForMagicPenalty();
+	
+	@Key("SkillChancePenaltyForLvLDifferences")
+	List<Double> getSkillChancePenaltyForLvLDifferences();
+	
+	// Monsters
+	
+	@Key("DecayTimeTask")
+	Integer getDecayTimeTask();
+	
+	@Key("DefaultCorpseTime")
+	Integer getDefaultCorpseTime();
+	
+	@Key("SpoiledCorpseExtendTime")
+	Integer getSpoiledCorpseExtendTime();
+	
+	@Key("CorpseConsumeSkillAllowedTimeBeforeDecay")
+	Integer getCorpseConsumeSkillAllowedTimeBeforeDecay();
+	
+	// Guards
+	
+	@Key("GuardAttackAggroMob")
+	Boolean guardAttackAggroMob();
+	
+	// Pets
+	
+	@Key("AllowWyvernUpgrader")
+	Integer allowWyvernUpgrader();
+	
+	@Key("PetRentNPCs")
+	Set<Integer> getPetRentNPCs();
+	
+	@Key("MaximumSlotsForPet")
+	Integer getMaximumSlotsForPet();
+	
+	@Key("PetHpRegenMultiplier")
+	Double getPetHpRegenMultiplier();
+	
+	@Key("PetMpRegenMultiplier")
+	Double getPetMpRegenMultiplier();
+	
+	// Raid Bosses
+	
+	@Key("RaidHpRegenMultiplier")
+	Double getRaidHpRegenMultiplier();
+	
+	@Key("RaidMpRegenMultiplier")
+	Double getRaidMpRegenMultiplier();
+	
+	@Key("RaidPDefenceMultiplier")
+	Double getRaidPDefenceMultiplier();
+	
+	@Key("RaidMDefenceMultiplier")
+	Double getRaidMDefenceMultiplier();
+	
+	@Key("RaidPAttackMultiplier")
+	Double getRaidPAttackMultiplier();
+	
+	@Key("RaidMAttackMultiplier")
+	Double getRaidMAttackMultiplier();
+	
+	@Key("RaidMinRespawnMultiplier")
+	Double getRaidMinRespawnMultiplier();
+	
+	@Key("RaidMaxRespawnMultiplier")
+	Double getRaidMaxRespawnMultiplier();
+	
+	@Key("RaidMinionRespawnTime")
+	Long getRaidMinionRespawnTime();
+	
+	@Key("CustomMinionsRespawnTime")
+	@ConverterClass(MapIntegerIntegerConverter.class)
+	Map<Integer, Integer> getCustomMinionsRespawnTime();
+	
+	@Key("RaidCurse")
+	Boolean raidCurse();
+	
+	@Key("RaidChaosTime")
+	Integer getRaidChaosTime();
+	
+	@Key("GrandChaosTime")
+	Integer getGrandChaosTime();
+	
+	@Key("MinionChaosTime")
+	Integer getMinionChaosTime();
+	
+	// Drops
+	
+	@Key("UseDeepBlueDropRules")
+	Boolean useDeepBlueDropRules();
+	
+	@Key("UseDeepBlueDropRulesRaid")
+	Boolean useDeepBlueDropRulesRaid();
+	
+	@Key("DropAdenaMinLevelDifference")
+	Integer getDropAdenaMinLevelDifference();
+	
+	@Key("DropAdenaMaxLevelDifference")
+	Integer getDropAdenaMaxLevelDifference();
+	
+	@Key("DropAdenaMinLevelGapChance")
+	Integer getDropAdenaMinLevelGapChance();
+	
+	@Key("DropItemMinLevelDifference")
+	Integer getDropItemMinLevelDifference();
+	
+	@Key("DropItemMaxLevelDifference")
+	Integer getDropItemMaxLevelDifference();
+	
+	@Key("DropItemMinLevelGapChance")
+	Integer getDropItemMinLevelGapChance();
+}

+ 181 - 0
src/main/java/com/l2jserver/gameserver/config/OlympiadConfiguration.java

@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+import java.util.Set;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.ItemHolderConverter;
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+
+/**
+ * Olympiad Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/olympiad.properties",
+	"classpath:config/olympiad.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface OlympiadConfiguration extends Config, Reloadable {
+	
+	@Key("StartHour")
+	Integer getStartHour();
+	
+	@Key("StartMinute")
+	Integer getStartMinute();
+	
+	@Key("MaxBuffs")
+	Integer getMaxBuffs();
+	
+	@Key("CompetitionPeriod")
+	Integer getCompetitionPeriod();
+	
+	@Key("BattlePeriod")
+	Integer getBattlePeriod();
+	
+	@Key("WeeklyPeriod")
+	Integer getWeeklyPeriod();
+	
+	@Key("ValidationPeriod")
+	Integer getValidationPeriod();
+	
+	@Key("StartPoints")
+	Integer getStartPoints();
+	
+	@Key("WeeklyPoints")
+	Integer getWeeklyPoints();
+	
+	@Key("ClassedParticipants")
+	Integer getClassedParticipants();
+	
+	@Key("NonClassedParticipants")
+	Integer getNonClassedParticipants();
+	
+	@Key("TeamsParticipants")
+	Integer getTeamsParticipants();
+	
+	@Key("RegistrationDisplayNumber")
+	Integer getRegistrationDisplayNumber();
+	
+	@Separator(";")
+	@Key("ClassedReward")
+	@ConverterClass(ItemHolderConverter.class)
+	List<ItemHolder> getClassedReward();
+	
+	@Separator(";")
+	@Key("NonClassedReward")
+	@ConverterClass(ItemHolderConverter.class)
+	List<ItemHolder> getNonClassedReward();
+	
+	@Separator(";")
+	@Key("TeamReward")
+	@ConverterClass(ItemHolderConverter.class)
+	List<ItemHolder> getTeamReward();
+	
+	@Key("CompetitionRewardItem")
+	Integer getCompetitionRewardItem();
+	
+	@Key("MinMatchesForPoints")
+	Integer getMinMatchesForPoints();
+	
+	@Key("GPPerPoint")
+	Integer getGPPerPoint();
+	
+	@Key("HeroPoints")
+	Integer getHeroPoints();
+	
+	@Key("Rank1Points")
+	Integer getRank1Points();
+	
+	@Key("Rank2Points")
+	Integer getRank2Points();
+	
+	@Key("Rank3Points")
+	Integer getRank3Points();
+	
+	@Key("Rank4Points")
+	Integer getRank4Points();
+	
+	@Key("Rank5Points")
+	Integer getRank5Points();
+	
+	@Key("MaxPoints")
+	Integer getMaxPoints();
+	
+	@Key("ShowMonthlyWinners")
+	Boolean showMonthlyWinners();
+	
+	@Key("AnnounceGames")
+	Boolean announceGames();
+	
+	@Key("RestrictedItems")
+	Set<Integer> getRestrictedItems();
+	
+	@Key("EnchantLimit")
+	Integer getEnchantLimit();
+	
+	@Key("LogFights")
+	Boolean logFights();
+	
+	@Key("WaitTime")
+	Integer getWaitTime();
+	
+	@Key("DividerClassed")
+	Integer getDividerClassed();
+	
+	@Key("DividerNonClassed")
+	Integer getDividerNonClassed();
+	
+	@Key("MaxWeeklyMatches")
+	Integer getMaxWeeklyMatches();
+	
+	@Key("MaxWeeklyMatchesNonClassed")
+	Integer getMaxWeeklyMatchesNonClassed();
+	
+	@Key("MaxWeeklyMatchesClassed")
+	Integer getMaxWeeklyMatchesClassed();
+	
+	@Key("MaxWeeklyMatchesTeam")
+	Integer getMaxWeeklyMatchesTeam();
+	
+	@Key("CurrentCycle")
+	Integer getCurrentCycle();
+	
+	@Key("Period")
+	Integer getPeriod();
+	
+	@Key("OlympiadEnd")
+	Long getOlympiadEnd();
+	
+	@Key("ValidationEnd")
+	Long getValidationEnd();
+	
+	@Key("NextWeeklyChange")
+	Long getNextWeeklyChange();
+}

+ 0 - 195
src/main/java/com/l2jserver/gameserver/config/PropertiesParser.java

@@ -1,195 +0,0 @@
-/*
- * Copyright © 2004-2019 L2J Server
- * 
- * This file is part of L2J Server.
- * 
- * L2J Server is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * L2J Server is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.l2jserver.gameserver.config;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.Charset;
-import java.nio.file.Paths;
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Simplifies loading of property files and adds logging if a non existing property is requested.
- * @author NosBit
- */
-public final class PropertiesParser {
-	private static final Logger LOG = LoggerFactory.getLogger(PropertiesParser.class);
-	
-	private final Properties _properties = new Properties();
-	
-	private final File _file;
-	
-	public PropertiesParser(String name) {
-		this(Paths.get(name).toFile());
-	}
-	
-	public PropertiesParser(File file) {
-		_file = file;
-		try (FileInputStream fileInputStream = new FileInputStream(file);
-			InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, Charset.defaultCharset())) {
-			_properties.load(inputStreamReader);
-		} catch (Exception ex) {
-			LOG.warn("There was an error loading {} config!", _file.getAbsolutePath(), ex);
-		}
-	}
-	
-	public boolean containskey(String key) {
-		return _properties.containsKey(key);
-	}
-	
-	private String getValue(String key) {
-		String value = _properties.getProperty(key);
-		return value != null ? value.trim() : null;
-	}
-	
-	public boolean getBoolean(String key, boolean defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		if (value.equalsIgnoreCase("true")) {
-			return true;
-		} else if (value.equalsIgnoreCase("false")) {
-			return false;
-		} else {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"boolean\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public byte getByte(String key, byte defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Byte.parseByte(value);
-		} catch (NumberFormatException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"byte\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public short getShort(String key, short defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Short.parseShort(value);
-		} catch (NumberFormatException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"short\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public int getInt(String key, int defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Integer.parseInt(value);
-		} catch (NumberFormatException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"int\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public long getLong(String key, long defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Long.parseLong(value);
-		} catch (NumberFormatException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"long\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public float getFloat(String key, float defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Float.parseFloat(value);
-		} catch (NumberFormatException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"float\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public double getDouble(String key, double defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Double.parseDouble(value);
-		} catch (NumberFormatException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"double\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-	
-	public String getString(String key, String defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		return value;
-	}
-	
-	public <T extends Enum<T>> T getEnum(String key, Class<T> clazz, T defaultValue) {
-		String value = getValue(key);
-		if (value == null) {
-			LOG.warn("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
-			return defaultValue;
-		}
-		
-		try {
-			return Enum.valueOf(clazz, value);
-		} catch (IllegalArgumentException e) {
-			LOG.warn("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be enum value of \"" + clazz.getSimpleName() + "\" using default value: " + defaultValue);
-			return defaultValue;
-		}
-	}
-}

+ 63 - 0
src/main/java/com/l2jserver/gameserver/config/PvPConfiguration.java

@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.Set;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * PvP Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/pvp.properties",
+	"classpath:config/pvp.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface PvPConfiguration extends Config, Reloadable {
+	
+	@Key("CanGMDropEquipment")
+	Boolean canGMDropEquipment();
+	
+	@Key("PetItems")
+	Set<Integer> getPetItems();
+	
+	@Key("NonDroppableItems")
+	Set<Integer> getNonDroppableItems();
+	
+	@Key("MinimumPKRequiredToDrop")
+	Integer getMinimumPKRequiredToDrop();
+	
+	@Key("AwardPKKillPVPPoint")
+	Boolean awardPKKillPVPPoint();
+	
+	@Key("PvPVsNormalTime")
+	Integer getPvPVsNormalTime();
+	
+	@Key("PvPVsPvPTime")
+	Integer getPvPVsPvPTime();
+}

+ 178 - 0
src/main/java/com/l2jserver/gameserver/config/RatesConfiguration.java

@@ -0,0 +1,178 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.Map;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.MapIntegerFloatConverter;
+
+/**
+ * Rates Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/rates.properties",
+	"classpath:config/rates.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface RatesConfiguration extends Config, Reloadable {
+	
+	@Key("DeathDropAmountMultiplier")
+	Double getDeathDropAmountMultiplier();
+	
+	@Key("CorpseDropAmountMultiplier")
+	Double getCorpseDropAmountMultiplier();
+	
+	@Key("HerbDropAmountMultiplier")
+	Double getHerbDropAmountMultiplier();
+	
+	@Key("RaidDropAmountMultiplier")
+	Double getRaidDropAmountMultiplier();
+	
+	@Key("DeathDropChanceMultiplier")
+	Double getDeathDropChanceMultiplier();
+	
+	@Key("CorpseDropChanceMultiplier")
+	Double getCorpseDropChanceMultiplier();
+	
+	@Key("HerbDropChanceMultiplier")
+	Double getHerbDropChanceMultiplier();
+	
+	@Key("RaidDropChanceMultiplier")
+	Double getRaidDropChanceMultiplier();
+	
+	@Key("DropAmountMultiplierByItemId")
+	@ConverterClass(MapIntegerFloatConverter.class)
+	Map<Integer, Float> getDropAmountMultiplierByItemId();
+	
+	@Key("DropChanceMultiplierByItemId")
+	@ConverterClass(MapIntegerFloatConverter.class)
+	Map<Integer, Float> getDropChanceMultiplierByItemId();
+	
+	@Key("RateXp")
+	Float getRateXp();
+	
+	@Key("RateSp")
+	Float getRateSp();
+	
+	@Key("RatePartyXp")
+	Float getRatePartyXp();
+	
+	@Key("RatePartySp")
+	Float getRatePartySp();
+	
+	@Key("RateDropManor")
+	Integer getRateDropManor();
+	
+	@Key("RateKarmaLost")
+	Double getRateKarmaLost();
+	
+	@Key("RateKarmaExpLost")
+	Double getRateKarmaExpLost();
+	
+	@Key("RateSiegeGuardsPrice")
+	Double getRateSiegeGuardsPrice();
+	
+	@Key("RateExtractable")
+	Float getRateExtractable();
+	
+	@Key("RateHellboundTrustIncrease")
+	Float getRateHellboundTrustIncrease();
+	
+	@Key("RateHellboundTrustDecrease")
+	Float getRateHellboundTrustDecrease();
+	
+	@Key("RateQuestDrop")
+	Float getRateQuestDrop();
+	
+	@Key("RateQuestRewardXP")
+	Float getRateQuestRewardXP();
+	
+	@Key("RateQuestRewardSP")
+	Float getRateQuestRewardSP();
+	
+	@Key("RateQuestRewardAdena")
+	Float getRateQuestRewardAdena();
+	
+	@Key("UseQuestRewardMultipliers")
+	Boolean useQuestRewardMultipliers();
+	
+	@Key("RateQuestReward")
+	Float getRateQuestReward();
+	
+	@Key("RateQuestRewardPotion")
+	Float getRateQuestRewardPotion();
+	
+	@Key("RateQuestRewardScroll")
+	Float getRateQuestRewardScroll();
+	
+	@Key("RateQuestRewardRecipe")
+	Float getRateQuestRewardRecipe();
+	
+	@Key("RateQuestRewardMaterial")
+	Float getRateQuestRewardMaterial();
+	
+	@Key("PlayerDropLimit")
+	Integer getPlayerDropLimit();
+	
+	@Key("PlayerRateDrop")
+	Integer getPlayerRateDrop();
+	
+	@Key("PlayerRateDropItem")
+	Integer getPlayerRateDropItem();
+	
+	@Key("PlayerRateDropEquip")
+	Integer getPlayerRateDropEquip();
+	
+	@Key("PlayerRateDropEquipWeapon")
+	Integer getPlayerRateDropEquipWeapon();
+	
+	@Key("KarmaDropLimit")
+	Integer getKarmaDropLimit();
+	
+	@Key("KarmaRateDrop")
+	Integer getKarmaRateDrop();
+	
+	@Key("KarmaRateDropItem")
+	Integer getKarmaRateDropItem();
+	
+	@Key("KarmaRateDropEquip")
+	Integer getKarmaRateDropEquip();
+	
+	@Key("KarmaRateDropEquipWeapon")
+	Integer getKarmaRateDropEquipWeapon();
+	
+	@Key("PetXpRate")
+	Double getPetXpRate();
+	
+	@Key("PetFoodRate")
+	Integer getPetFoodRate();
+	
+	@Key("SinEaterXpRate")
+	Double getSinEaterXpRate();
+}

+ 90 - 0
src/main/java/com/l2jserver/gameserver/config/ServerConfiguration.java

@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.io.File;
+import java.util.Set;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Mutable;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.FileConverter;
+import com.l2jserver.gameserver.idfactory.IdFactoryType;
+
+/**
+ * Server Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/server.properties",
+	"classpath:config/server.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface ServerConfiguration extends Config, Mutable, Reloadable {
+	
+	@Key("EnableUPnP")
+	Boolean enableUPnP();
+	
+	@Key("LoginHost")
+	String getLoginHost();
+	
+	@Key("LoginPort")
+	Integer getLoginPort();
+	
+	@Key("Host")
+	String getHost();
+	
+	@Key("Port")
+	Integer getPort();
+	
+	@Key("RequestServerId")
+	Integer getRequestServerId();
+	
+	@Key("AcceptAlternateId")
+	Boolean acceptAlternateId();
+	
+	@Key("ReserveHostOnLogin")
+	Boolean reserveHostOnLogin();
+	
+	@Key("DatapackRoot")
+	@ConverterClass(FileConverter.class)
+	File getDatapackRoot();
+	
+	@Key("ScriptRoot")
+	File getScriptRoot();
+	
+	@Key("MaxOnlineUsers")
+	Integer getMaxOnlineUsers();
+	
+	@Key("AllowedProtocolRevisions")
+	Set<Integer> getAllowedProtocolRevisions();
+	
+	@Key("IdFactory")
+	IdFactoryType getIdFactory();
+	
+	@Key("BadIdChecking")
+	Boolean badIdChecking();
+}

+ 112 - 0
src/main/java/com/l2jserver/gameserver/config/SevenSingsConfiguration.java

@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Seven Sings Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/sevensings.properties",
+	"classpath:config/sevensings.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface SevenSingsConfiguration extends Config, Reloadable {
+	
+	@Key("RequireClanCastle")
+	Boolean requireClanCastle();
+	
+	@Key("CastleForDawn")
+	Boolean castleForDawn();
+	
+	@Key("CastleForDusk")
+	Boolean castleForDusk();
+	
+	@Key("FestivalMinPlayer")
+	Integer getFestivalMinPlayer();
+	
+	@Key("MaxPlayerContrib")
+	Integer getMaxPlayerContrib();
+	
+	@Key("FestivalManagerStart")
+	Integer getFestivalManagerStart();
+	
+	@Key("FestivalLength")
+	Integer getFestivalLength();
+	
+	@Key("FestivalCycleLength")
+	Integer getFestivalCycleLength();
+	
+	@Key("FestivalFirstSpawn")
+	Integer getFestivalFirstSpawn();
+	
+	@Key("FestivalFirstSwarm")
+	Integer getFestivalFirstSwarm();
+	
+	@Key("FestivalSecondSpawn")
+	Integer getFestivalSecondSpawn();
+	
+	@Key("FestivalSecondSwarm")
+	Integer getFestivalSecondSwarm();
+	
+	@Key("FestivalChestSpawn")
+	Integer getFestivalChestSpawn();
+	
+	@Key("DawnGatesPdefMult")
+	Double getDawnGatesPdefMult();
+	
+	@Key("DuskGatesPdefMult")
+	Double getDuskGatesPdefMult();
+	
+	@Key("DawnGatesMdefMult")
+	Double getDawnGatesMdefMult();
+	
+	@Key("DuskGatesMdefMult")
+	Double getDuskGatesMdefMult();
+	
+	@Key("StrictSevenSigns")
+	Boolean strictSevenSigns();
+	
+	@Key("SevenSignsLazyUpdate")
+	Boolean sevenSignsLazyUpdate();
+	
+	@Key("SevenSignsDawnTicketQuantity")
+	Integer getSevenSignsDawnTicketQuantity();
+	
+	@Key("SevenSignsDawnTicketPrice")
+	Integer getSevenSignsDawnTicketPrice();
+	
+	@Key("SevenSignsDawnTicketBundle")
+	Integer getSevenSignsDawnTicketBundle();
+	
+	@Key("SevenSignsManorsAgreementId")
+	Integer getSevenSignsManorsAgreementId();
+	
+	@Key("SevenSignsJoinDawnFee")
+	Integer getSevenSignsJoinDawnFee();
+}

+ 272 - 0
src/main/java/com/l2jserver/gameserver/config/SiegeConfiguration.java

@@ -0,0 +1,272 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.ControlTowerConverter;
+import com.l2jserver.gameserver.config.converter.FlameTowerConverter;
+import com.l2jserver.gameserver.model.TowerSpawn;
+
+/**
+ * Siege Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/siege.properties",
+	"classpath:config/siege.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface SiegeConfiguration extends Config, Reloadable {
+	
+	@Key("SiegeLength")
+	Integer getSiegeLength();
+	
+	@Key("MaxFlags")
+	Integer getMaxFlags();
+	
+	@Key("ClanMinLevel")
+	Integer getClanMinLevel();
+	
+	@Key("AttackerMaxClans")
+	Integer getAttackerMaxClans();
+	
+	@Key("DefenderMaxClans")
+	Integer getDefenderMaxClans();
+	
+	@Key("AttackerRespawn")
+	Integer getAttackerRespawn();
+	
+	@Key("BloodAllianceReward")
+	Integer getBloodAllianceReward();
+	
+	@Key("GludioFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getGludioFlameTower1();
+	
+	@Key("GludioFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getGludioFlameTower2();
+	
+	@Key("GludioControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGludioControlTower1();
+	
+	@Key("GludioControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGludioControlTower2();
+	
+	@Key("GludioControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGludioControlTower3();
+	
+	@Key("GludioMaxMercenaries")
+	Integer getGludioMaxMercenaries();
+	
+	@Key("GiranFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getGiranFlameTower1();
+	
+	@Key("GiranFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getGiranFlameTower2();
+	
+	@Key("GiranControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGiranControlTower1();
+	
+	@Key("GiranControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGiranControlTower2();
+	
+	@Key("GiranControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGiranControlTower3();
+	
+	@Key("GiranMaxMercenaries")
+	Integer getGiranMaxMercenaries();
+	
+	@Key("DionFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getDionFlameTower1();
+	
+	@Key("DionFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getDionFlameTower2();
+	
+	@Key("DionControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getDionControlTower1();
+	
+	@Key("DionControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getDionControlTower2();
+	
+	@Key("DionControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getDionControlTower3();
+	
+	@Key("DionMaxMercenaries")
+	Integer getDionMaxMercenaries();
+	
+	@Key("OrenFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getOrenFlameTower1();
+	
+	@Key("OrenFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getOrenFlameTower2();
+	
+	@Key("OrenControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getOrenControlTower1();
+	
+	@Key("OrenControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getOrenControlTower2();
+	
+	@Key("OrenControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getOrenControlTower3();
+	
+	@Key("OrenMaxMercenaries")
+	Integer getOrenMaxMercenaries();
+	
+	@Key("AdenFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getAdenFlameTower1();
+	
+	@Key("AdenFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn AdenFlameTower2();
+	
+	@Key("AdenControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getAdenControlTower1();
+	
+	@Key("AdenControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getAdenControlTower2();
+	
+	@Key("AdenControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getAdenControlTower3();
+	
+	@Key("AdenMaxMercenaries")
+	Integer getAdenMaxMercenaries();
+	
+	@Key("InnadrilFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getInnadrilFlameTower1();
+	
+	@Key("InnadrilFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getInnadrilFlameTower2();
+	
+	@Key("InnadrilControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getInnadrilControlTower1();
+	
+	@Key("InnadrilControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getInnadrilControlTower2();
+	
+	@Key("InnadrilControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getInnadrilControlTower3();
+	
+	@Key("InnadrilMaxMercenaries")
+	Integer getInnadrilMaxMercenaries();
+	
+	@Key("GoddardFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getGoddardFlameTower1();
+	
+	@Key("GoddardFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getGoddardFlameTower2();
+	
+	@Key("GoddardControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGoddardControlTower1();
+	
+	@Key("GoddardControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGoddardControlTower2();
+	
+	@Key("GoddardControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getGoddardControlTower3();
+	
+	@Key("GoddardMaxMercenaries")
+	Integer getGoddardMaxMercenaries();
+	
+	@Key("RuneFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getRuneFlameTower1();
+	
+	@Key("RuneFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getRuneFlameTower2();
+	
+	@Key("RuneControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getRuneControlTower1();
+	
+	@Key("RuneControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getRuneControlTower2();
+	
+	@Key("RuneControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getRuneControlTower3();
+	
+	@Key("RuneMaxMercenaries")
+	Integer getRuneMaxMercenaries();
+	
+	@Key("SchuttgartFlameTower1")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getSchuttgartFlameTower1();
+	
+	@Key("SchuttgartFlameTower2")
+	@ConverterClass(FlameTowerConverter.class)
+	TowerSpawn getSchuttgartFlameTower2();
+	
+	@Key("SchuttgartControlTower1")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getSchuttgartControlTower1();
+	
+	@Key("SchuttgartControlTower2")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getSchuttgartControlTower2();
+	
+	@Key("SchuttgartControlTower3")
+	@ConverterClass(ControlTowerConverter.class)
+	TowerSpawn getSchuttgartControlTower3();
+	
+	@Key("SchuttgartMaxMercenaries")
+	Integer getSchuttgartMaxMercenaries();
+}

+ 54 - 0
src/main/java/com/l2jserver/gameserver/config/TelnetConfiguration.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Telnet Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/telnet.properties",
+	"classpath:config/telnet.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface TelnetConfiguration extends Config, Reloadable {
+	
+	@Key("EnableTelnet")
+	Boolean isEnabled();
+	
+	@Key("Port")
+	Integer getPort();
+	
+	@Key("Password")
+	String getPassword();
+	
+	@Key("Hosts")
+	List<String> getHosts();
+}

+ 73 - 0
src/main/java/com/l2jserver/gameserver/config/TerritoryWarConfiguration.java

@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Territory War Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/territorywar.properties",
+	"classpath:config/territorywar.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface TerritoryWarConfiguration extends Config, Reloadable {
+	
+	@Key("WarLength")
+	Long getWarLength();
+	
+	@Key("ClanMinLevel")
+	Integer getClanMinLevel();
+	
+	@Key("PlayerMinLevel")
+	Integer getPlayerMinLevel();
+	
+	@Key("DefenderMaxClans")
+	Integer getDefenderMaxClans();
+	
+	@Key("DefenderMaxPlayers")
+	Integer getDefenderMaxPlayers();
+	
+	@Key("PlayerWithWardCanBeKilledInPeaceZone")
+	Boolean playerWithWardCanBeKilledInPeaceZone();
+	
+	@Key("SpawnWardsWhenTWIsNotInProgress")
+	Boolean spawnWardsWhenTWIsNotInProgress();
+	
+	@Key("ReturnWardsWhenTWStarts")
+	Boolean returnWardsWhenTWStarts();
+	
+	@Key("MinTerritoryBadgeForNobless")
+	Integer getMinTerritoryBadgeForNobless();
+	
+	@Key("MinTerritoryBadgeForStriders")
+	Integer getMinTerritoryBadgeForStriders();
+	
+	@Key("MinTerritoryBadgeForBigStrider")
+	Integer getMinTerritoryBadgeForBigStrider();
+}

+ 158 - 0
src/main/java/com/l2jserver/gameserver/config/TvTConfiguration.java

@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import java.util.List;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+import com.l2jserver.gameserver.config.converter.ItemHolderConverter;
+import com.l2jserver.gameserver.config.converter.LocationConverter;
+import com.l2jserver.gameserver.config.converter.Seconds2MillisecondsConverter;
+import com.l2jserver.gameserver.config.converter.SkillHolderConverter;
+import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+import com.l2jserver.gameserver.model.holders.SkillHolder;
+
+/**
+ * TvT Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/tvt.properties",
+	"classpath:config/tvt.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface TvTConfiguration extends Config, Reloadable {
+	
+	@Key("Enabled")
+	Boolean enabled();
+	
+	@Key("Instanced")
+	Boolean instanced();
+	
+	@Key("InstanceFile")
+	String getInstanceFile();
+	
+	@Key("Interval")
+	List<String> getInterval();
+	
+	@Key("ParticipationTime")
+	Integer getParticipationTime();
+	
+	@Key("RunningTime")
+	Integer getRunningTime();
+	
+	@Key("ParticipationNpcId")
+	Integer getParticipationNpcId();
+	
+	@Key("ParticipationFee")
+	@ConverterClass(ItemHolderConverter.class)
+	ItemHolder getParticipationFee();
+	
+	@Key("ParticipationNpcLoc")
+	@ConverterClass(LocationConverter.class)
+	Location getParticipationNpcLoc();
+	
+	@Key("MinPlayersInTeams")
+	Integer getMinPlayersInTeams();
+	
+	@Key("MaxPlayersInTeams")
+	Integer getMaxPlayersInTeams();
+	
+	@Key("MinPlayerLevel")
+	Integer getMinPlayerLevel();
+	
+	@Key("MaxPlayerLevel")
+	Integer getMaxPlayerLevel();
+	
+	@Key("RespawnTeleportDelay")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getRespawnTeleportDelay();
+	
+	@Key("StartLeaveTeleportDelay")
+	@ConverterClass(Seconds2MillisecondsConverter.class)
+	Integer getStartLeaveTeleportDelay();
+	
+	@Key("Team1Name")
+	String getTeam1Name();
+	
+	@Key("Team1Loc")
+	@ConverterClass(LocationConverter.class)
+	Location getTeam1Loc();
+	
+	@Key("Team2Name")
+	String getTeam2Name();
+	
+	@Key("Team2Loc")
+	@ConverterClass(LocationConverter.class)
+	Location getTeam2Loc();
+	
+	@Separator(";")
+	@Key("Reward")
+	@ConverterClass(ItemHolderConverter.class)
+	List<ItemHolder> getReward();
+	
+	@Key("AllowTargetTeamMember")
+	Boolean allowTargetTeamMember();
+	
+	@Key("AllowScroll")
+	Boolean allowScroll();
+	
+	@Key("AllowPotion")
+	Boolean allowPotion();
+	
+	@Key("AllowSummonByItem")
+	Boolean allowSummonByItem();
+	
+	@Key("DoorsToOpen")
+	List<Integer> getDoorsToOpen();
+	
+	@Key("DoorsToClose")
+	List<Integer> getDoorsToClose();
+	
+	@Key("RewardTeamTie")
+	Boolean rewardTeamTie();
+	
+	@Key("EffectsRemoval")
+	Integer getEffectsRemoval();
+	
+	@Separator(";")
+	@Key("FighterBuffs")
+	@ConverterClass(SkillHolderConverter.class)
+	List<SkillHolder> getFighterBuffs();
+	
+	@Separator(";")
+	@Key("MageBuffs")
+	@ConverterClass(SkillHolderConverter.class)
+	List<SkillHolder> getMageBuffs();
+	
+	@Key("MaxParticipantsPerIP")
+	Integer getMaxParticipantsPerIP();
+	
+	@Key("AllowVoicedInfoCommand")
+	Boolean allowVoicedInfoCommand();
+}

+ 73 - 0
src/main/java/com/l2jserver/gameserver/config/VitalityConfiguration.java

@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
+
+import org.aeonbits.owner.Config;
+import org.aeonbits.owner.Config.HotReload;
+import org.aeonbits.owner.Config.Sources;
+import org.aeonbits.owner.Reloadable;
+
+/**
+ * Vitality Configuration.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+@Sources({
+	"file:./config/vitality.properties",
+	"classpath:config/vitality.properties"
+})
+@HotReload(value = 20, unit = MINUTES, type = ASYNC)
+public interface VitalityConfiguration extends Config, Reloadable {
+	
+	@Key("Enabled")
+	Boolean enabled();
+	
+	@Key("RecoverVitalityOnReconnect")
+	Boolean recoverVitalityOnReconnect();
+	
+	@Key("StartingVitalityPoints")
+	Integer getStartingVitalityPoints();
+	
+	@Key("RateVitalityLevel1")
+	Float getRateVitalityLevel1();
+	
+	@Key("RateVitalityLevel2")
+	Float getRateVitalityLevel2();
+	
+	@Key("RateVitalityLevel3")
+	Float getRateVitalityLevel3();
+	
+	@Key("RateVitalityLevel4")
+	Float getRateVitalityLevel4();
+	
+	@Key("RateVitalityGain")
+	Float getRateVitalityGain();
+	
+	@Key("RateVitalityLost")
+	Float getRateVitalityLost();
+	
+	@Key("RateRecoveryPeaceZone")
+	Float getRateRecoveryPeaceZone();
+	
+	@Key("RateRecoveryOnReconnect")
+	Float getRateRecoveryOnReconnect();
+}

+ 64 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ClassMasterSetting.java

@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+
+/**
+ * Class Master Setting.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ClassMasterSetting {
+	
+	private final Map<Integer, List<ItemHolder>> claimItems = new HashMap<>(3);
+	
+	private final Map<Integer, List<ItemHolder>> rewardItems = new HashMap<>(3);
+	
+	private final Map<Integer, Boolean> allowedClassChange = new HashMap<>(3);
+	
+	public void addClaimItems(Integer job, List<ItemHolder> items) {
+		claimItems.put(job, items);
+	}
+	
+	public void addRewardItems(Integer job, List<ItemHolder> items) {
+		rewardItems.put(job, items);
+	}
+	
+	public void addAllowedClassChange(Integer job) {
+		allowedClassChange.put(job, true);
+	}
+	
+	public boolean isAllowed(int job) {
+		return allowedClassChange.getOrDefault(job, false);
+	}
+	
+	public List<ItemHolder> getRewardItems(int job) {
+		return rewardItems.getOrDefault(job, Collections.emptyList());
+	}
+	
+	public List<ItemHolder> getRequireItems(int job) {
+		return claimItems.getOrDefault(job, Collections.emptyList());
+	}
+}

+ 79 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ClassMasterSettingConverter.java

@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.aeonbits.owner.Converter;
+
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+
+/**
+ * Class Master Setting converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ClassMasterSettingConverter implements Converter<ClassMasterSetting> {
+	
+	@Override
+	public ClassMasterSetting convert(Method method, String input) {
+		final var classMasterSetting = new ClassMasterSetting();
+		input = input.trim();
+		if (input.isEmpty()) {
+			return classMasterSetting;
+		}
+		
+		final StringTokenizer st = new StringTokenizer(input, ";");
+		while (st.hasMoreTokens()) {
+			// get allowed class change
+			final int job = Integer.parseInt(st.nextToken());
+			classMasterSetting.addAllowedClassChange(job);
+			
+			final List<ItemHolder> requiredItems = new ArrayList<>();
+			// parse items needed for class change
+			if (st.hasMoreTokens()) {
+				final StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
+				while (st2.hasMoreTokens()) {
+					final StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
+					final int itemId = Integer.parseInt(st3.nextToken());
+					final int quantity = Integer.parseInt(st3.nextToken());
+					requiredItems.add(new ItemHolder(itemId, quantity));
+				}
+			}
+			classMasterSetting.addClaimItems(job, requiredItems);
+			
+			final List<ItemHolder> rewardItems = new ArrayList<>();
+			// parse gifts after class change
+			if (st.hasMoreTokens()) {
+				final StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");
+				while (st2.hasMoreTokens()) {
+					final StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");
+					final int itemId = Integer.parseInt(st3.nextToken());
+					final int quantity = Integer.parseInt(st3.nextToken());
+					rewardItems.add(new ItemHolder(itemId, quantity));
+				}
+			}
+			classMasterSetting.addRewardItems(job, rewardItems);
+		}
+		return classMasterSetting;
+	}
+}

+ 42 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ColorConverter.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Color Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ColorConverter implements Converter<Integer> {
+	
+	private static final Integer DEFAULT_COLOR = Integer.decode("0x808080");
+	
+	@Override
+	public Integer convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return DEFAULT_COLOR;
+		}
+		return Integer.decode("0x" + input);
+	}
+}

+ 51 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ControlTowerConverter.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.util.StringTokenizer;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.TowerSpawn;
+
+/**
+ * Control Tower Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ControlTowerConverter implements Converter<TowerSpawn> {
+	
+	@Override
+	public TowerSpawn convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		
+		final StringTokenizer st = new StringTokenizer(input, ",");
+		final int x = Integer.parseInt(st.nextToken());
+		final int y = Integer.parseInt(st.nextToken());
+		final int z = Integer.parseInt(st.nextToken());
+		final int npcId = Integer.parseInt(st.nextToken());
+		
+		return new TowerSpawn(npcId, new Location(x, y, z));
+	}
+}

+ 46 - 0
src/main/java/com/l2jserver/gameserver/config/converter/FileConverter.java

@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.io.File;
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * File Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class FileConverter implements Converter<File> {
+	
+	private static final Logger LOG = LoggerFactory.getLogger(FileConverter.class);
+	
+	@Override
+	public File convert(Method method, String input) {
+		try {
+			return new File(input.replaceAll("\\\\", "/")).getCanonicalFile();
+		} catch (Exception ex) {
+			LOG.warn("Error setting script root!", ex);
+			return new File(".");
+		}
+	}
+}

+ 57 - 0
src/main/java/com/l2jserver/gameserver/config/converter/FlameTowerConverter.java

@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.l2jserver.gameserver.model.Location;
+import com.l2jserver.gameserver.model.TowerSpawn;
+
+/**
+ * Flame Tower Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class FlameTowerConverter implements Converter<TowerSpawn> {
+	
+	@Override
+	public TowerSpawn convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		
+		final StringTokenizer st = new StringTokenizer(input, ",");
+		final int x = Integer.parseInt(st.nextToken());
+		final int y = Integer.parseInt(st.nextToken());
+		final int z = Integer.parseInt(st.nextToken());
+		final int npcId = Integer.parseInt(st.nextToken());
+		final List<Integer> zones = new LinkedList<>();
+		while (st.hasMoreTokens()) {
+			zones.add(Integer.parseInt(st.nextToken()));
+		}
+		
+		return new TowerSpawn(npcId, new Location(x, y, z), zones);
+	}
+}

+ 41 - 0
src/main/java/com/l2jserver/gameserver/config/converter/HexIdConverter.java

@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Hex Id Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class HexIdConverter implements Converter<BigInteger> {
+	
+	@Override
+	public BigInteger convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		return new BigInteger(input, 16);
+	}
+}

+ 58 - 0
src/main/java/com/l2jserver/gameserver/config/converter/IPLimitConverter.java

@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * IP-Limit Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class IPLimitConverter implements Converter<Map<Integer, Integer>> {
+	
+	private static final Logger LOG = LoggerFactory.getLogger(IPLimitConverter.class);
+	
+	@Override
+	public Map<Integer, Integer> convert(Method method, String input) {
+		final var map = new HashMap<Integer, Integer>();
+		if (Strings.isBlank(input)) {
+			return map;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(";");
+		for (var token : tokens) {
+			final var splitToken = token.split(",");
+			try {
+				map.put(InetAddress.getByName(splitToken[0]).hashCode(), Integer.valueOf(splitToken[1]));
+			} catch (Exception ex) {
+				LOG.warn("Invalid DualboxCheckWhitelist IP {} or limit {}!", splitToken[0], splitToken[1], ex);
+			}
+		}
+		return map;
+	}
+}

+ 44 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ItemChanceHolderConverter.java

@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
+
+/**
+ * Item Chance Holder Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ItemChanceHolderConverter implements Converter<ItemChanceHolder> {
+	
+	@Override
+	public ItemChanceHolder convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(",");
+		return new ItemChanceHolder(Integer.valueOf(tokens[0]), Float.valueOf(tokens[1]));
+	}
+}

+ 44 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ItemHolderConverter.java

@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.l2jserver.gameserver.model.holders.ItemHolder;
+
+/**
+ * Item Holder Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ItemHolderConverter implements Converter<ItemHolder> {
+	
+	@Override
+	public ItemHolder convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(",");
+		return new ItemHolder(Integer.valueOf(tokens[0]), Long.valueOf(tokens[1]));
+	}
+}

+ 51 - 0
src/main/java/com/l2jserver/gameserver/config/converter/LocationConverter.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.l2jserver.gameserver.model.Location;
+
+/**
+ * Location Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class LocationConverter implements Converter<Location> {
+	
+	@Override
+	public Location convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(",");
+		final var location = new Location(Integer.valueOf(tokens[0]), Integer.valueOf(tokens[1]), Integer.valueOf(tokens[2]));
+		if (tokens.length >= 4) {
+			location.setHeading(Integer.valueOf(tokens[3]));
+		}
+		if (tokens.length == 5) {
+			location.setInstanceId(Integer.valueOf(tokens[4]));
+		}
+		return location;
+	}
+}

+ 49 - 0
src/main/java/com/l2jserver/gameserver/config/converter/MapIntegerFloatConverter.java

@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Map Integer-Float Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class MapIntegerFloatConverter implements Converter<Map<Integer, Float>> {
+	
+	@Override
+	public Map<Integer, Float> convert(Method method, String input) {
+		final var map = new HashMap<Integer, Float>();
+		if (Strings.isBlank(input)) {
+			return map;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(";");
+		for (var token : tokens) {
+			final var splitToken = token.split(",");
+			map.put(Integer.valueOf(splitToken[0]), Float.valueOf(splitToken[1]));
+		}
+		return map;
+	}
+}

+ 49 - 0
src/main/java/com/l2jserver/gameserver/config/converter/MapIntegerIntegerConverter.java

@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Map Integer-Integer Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class MapIntegerIntegerConverter implements Converter<Map<Integer, Integer>> {
+	
+	@Override
+	public Map<Integer, Integer> convert(Method method, String input) {
+		final var map = new HashMap<Integer, Integer>();
+		if (Strings.isBlank(input)) {
+			return map;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(";");
+		for (var token : tokens) {
+			final var splitToken = token.split(",");
+			map.put(Integer.valueOf(splitToken[0]), Integer.valueOf(splitToken[1]));
+		}
+		return map;
+	}
+}

+ 42 - 0
src/main/java/com/l2jserver/gameserver/config/converter/Minutes2MillisecondsConverter.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Minutes to Milliseconds Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class Minutes2MillisecondsConverter implements Converter<Integer> {
+	
+	@Override
+	public Integer convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return 0;
+		}
+		return (int) MINUTES.toMillis(Integer.parseInt(input));
+	}
+}

+ 48 - 0
src/main/java/com/l2jserver/gameserver/config/converter/PatternConverter.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+import java.util.regex.Pattern;
+
+import org.aeonbits.owner.Converter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Pattern Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class PatternConverter implements Converter<Pattern> {
+	
+	private static final Logger LOG = LoggerFactory.getLogger(PatternConverter.class);
+	
+	private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9]*");
+	
+	@Override
+	public Pattern convert(Method method, String input) {
+		try {
+			return Pattern.compile(input);
+		} catch (Exception ex) {
+			LOG.error("Error creating pattern {}!", input, ex);
+			return DEFAULT_PATTERN;
+		}
+	}
+}

+ 42 - 0
src/main/java/com/l2jserver/gameserver/config/converter/Seconds2MillisecondsConverter.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Seconds to Milliseconds Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class Seconds2MillisecondsConverter implements Converter<Integer> {
+	
+	@Override
+	public Integer convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return 0;
+		}
+		return (int) SECONDS.toMillis(Integer.parseInt(input));
+	}
+}

+ 78 - 0
src/main/java/com/l2jserver/gameserver/config/converter/ServerListTypeConverter.java

@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Server List Type Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class ServerListTypeConverter implements Converter<Integer> {
+	
+	@Override
+	public Integer convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return 1;
+		}
+		return getServerTypeId(input.split(","));
+	}
+	
+	public static int getServerTypeId(String[] serverTypes) {
+		int typeId = 0;
+		for (String serverType : serverTypes) {
+			switch (serverType.trim().toLowerCase()) {
+				default:
+				case "normal": {
+					typeId |= 0x01;
+					break;
+				}
+				case "relax": {
+					typeId |= 0x02;
+					break;
+				}
+				case "test": {
+					typeId |= 0x04;
+					break;
+				}
+				case "nolabel": {
+					typeId |= 0x08;
+					break;
+				}
+				case "restricted": {
+					typeId |= 0x10;
+					break;
+				}
+				case "event": {
+					typeId |= 0x20;
+					break;
+				}
+				case "free": {
+					typeId |= 0x40;
+					break;
+				}
+			}
+		}
+		return typeId;
+	}
+}

+ 44 - 0
src/main/java/com/l2jserver/gameserver/config/converter/SkillHolderConverter.java

@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2019 L2J Server
+ *
+ * This file is part of L2J Server.
+ *
+ * L2J Server is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.gameserver.config.converter;
+
+import java.lang.reflect.Method;
+
+import org.aeonbits.owner.Converter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.l2jserver.gameserver.model.holders.SkillHolder;
+
+/**
+ * Skill Holder Converter.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public class SkillHolderConverter implements Converter<SkillHolder> {
+	
+	@Override
+	public SkillHolder convert(Method method, String input) {
+		if (Strings.isBlank(input)) {
+			return null;
+		}
+		
+		final var tokens = input.replaceAll(" ", "").split(",");
+		return new SkillHolder(Integer.valueOf(tokens[0]), Integer.valueOf(tokens[1]));
+	}
+}

+ 5 - 4
src/main/java/com/l2jserver/gameserver/dao/factory/impl/DAOFactory.java

@@ -18,10 +18,11 @@
  */
 package com.l2jserver.gameserver.dao.factory.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.database;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.dao.factory.IDAOFactory;
 
 /**
@@ -43,15 +44,15 @@ public class DAOFactory {
 		protected static final IDAOFactory INSTANCE;
 		
 		static {
-			switch (Config.DATABASE_ENGINE) {
+			switch (database().getEngine()) {
+				default:
 				case "MSSQL":
 				case "OracleDB":
 				case "PostgreSQL":
 				case "H2":
 				case "HSQLDB": {
-					throw new UnsupportedOperationException(Config.DATABASE_ENGINE + " is not supported!");
+					throw new UnsupportedOperationException(database().getEngine() + " is not supported!");
 				}
-				default:
 				case "MariaDB":
 				case "MySQL": {
 					INSTANCE = MySQLDAOFactory.INSTANCE;

+ 3 - 2
src/main/java/com/l2jserver/gameserver/dao/impl/mysql/PetSkillSaveDAOMySQL.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.dao.impl.mysql;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.LinkedList;
 import java.util.List;
 
@@ -25,7 +27,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.dao.PetSkillSaveDAO;
 import com.l2jserver.gameserver.data.sql.impl.SummonEffectsTable;
 import com.l2jserver.gameserver.datatables.SkillData;
@@ -80,7 +81,7 @@ public class PetSkillSaveDAOMySQL implements PetSkillSaveDAO {
 					}
 					
 					// Dances and songs are not kept in retail.
-					if (skill.isDance() && !Config.ALT_STORE_DANCES) {
+					if (skill.isDance() && !character().storeDances()) {
 						continue;
 					}
 					

+ 3 - 1
src/main/java/com/l2jserver/gameserver/dao/impl/mysql/PlayerDAOMySQLImpl.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.dao.impl.mysql;
 
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
 import java.sql.Timestamp;
 
 import org.slf4j.Logger;
@@ -257,7 +259,7 @@ public class PlayerDAOMySQLImpl implements PlayerDAO {
 	public void storeCharBase(L2PcInstance player) {
 		long totalOnlineTime = player.getOnlineTime();
 		if (player.getOnlineBeginTime() > 0) {
-			totalOnlineTime += (System.currentTimeMillis() - player.getOnlineBeginTime()) / 1000;
+			totalOnlineTime += MILLISECONDS.toSeconds(System.currentTimeMillis() - player.getOnlineBeginTime());
 		}
 		
 		try (var con = ConnectionFactory.getInstance().getConnection();

+ 3 - 2
src/main/java/com/l2jserver/gameserver/dao/impl/mysql/PlayerSkillSaveDAOMySQLImpl.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.dao.impl.mysql;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -27,7 +29,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.dao.PlayerSkillSaveDAO;
 import com.l2jserver.gameserver.datatables.SkillData;
 import com.l2jserver.gameserver.model.TimeStamp;
@@ -93,7 +94,7 @@ public class PlayerSkillSaveDAOMySQLImpl implements PlayerSkillSaveDAO {
 					}
 					
 					// Dances and songs are not kept in retail.
-					if (skill.isDance() && !Config.ALT_STORE_DANCES) {
+					if (skill.isDance() && !character().storeDances()) {
 						continue;
 					}
 					

+ 3 - 2
src/main/java/com/l2jserver/gameserver/dao/impl/mysql/ServitorSkillSaveDAOMySQLImpl.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.dao.impl.mysql;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.LinkedList;
 import java.util.List;
 
@@ -25,7 +27,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.dao.ServitorSkillSaveDAO;
 import com.l2jserver.gameserver.data.sql.impl.SummonEffectsTable;
 import com.l2jserver.gameserver.datatables.SkillData;
@@ -83,7 +84,7 @@ public class ServitorSkillSaveDAOMySQLImpl implements ServitorSkillSaveDAO {
 						}
 						
 						// Dances and songs are not kept in retail.
-						if (skill.isDance() && !Config.ALT_STORE_DANCES) {
+						if (skill.isDance() && !character().storeDances()) {
 							continue;
 						}
 						

+ 4 - 3
src/main/java/com/l2jserver/gameserver/dao/impl/mysql/SkillDAOMySQLImpl.java

@@ -18,13 +18,14 @@
  */
 package com.l2jserver.gameserver.dao.impl.mysql;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.List;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.dao.SkillDAO;
 import com.l2jserver.gameserver.data.xml.impl.ClassListData;
 import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
@@ -77,11 +78,11 @@ public class SkillDAOMySQLImpl implements SkillDAO {
 					// Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character
 					player.addSkill(skill);
 					
-					if (Config.SKILL_CHECK_ENABLE && (!player.canOverrideCond(PcCondOverride.SKILL_CONDITIONS) || Config.SKILL_CHECK_GM)) {
+					if (general().skillCheckEnable() && (!player.canOverrideCond(PcCondOverride.SKILL_CONDITIONS) || general().skillCheckGM())) {
 						if (!SkillTreesData.getInstance().isSkillAllowed(player, skill)) {
 							Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " has invalid skill " + skill.getName() + " (" + skill.getId() + "/" + skill.getLevel() + "), class:"
 								+ ClassListData.getInstance().getClass(player.getClassId()).getClassName(), IllegalActionPunishmentType.BROADCAST);
-							if (Config.SKILL_CHECK_REMOVE) {
+							if (general().skillCheckRemove()) {
 								player.removeSkill(skill);
 							}
 						}

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/json/ExperienceData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.json;
 
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
@@ -32,7 +34,6 @@ import org.slf4j.LoggerFactory;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import com.google.gson.stream.JsonReader;
-import com.l2jserver.gameserver.config.Config;
 
 /**
  * @author Zealar
@@ -52,7 +53,7 @@ public final class ExperienceData {
 	
 	public void load() {
 		_expTable.clear();
-		try (JsonReader reader = new JsonReader(new FileReader(new File(Config.DATAPACK_ROOT, "data/stats/expData.json")))) {
+		try (JsonReader reader = new JsonReader(new FileReader(new File(server().getDatapackRoot(), "data/stats/expData.json")))) {
 			_expTable.putAll(GSON.fromJson(reader, TYPE_MAP_INTEGER_LONG));
 		} catch (FileNotFoundException fnfe) {
 			LOG.warn("data/stats/expData.json not found!");

+ 5 - 4
src/main/java/com/l2jserver/gameserver/data/sql/impl/CharNameTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
@@ -26,7 +28,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 
 /**
@@ -42,7 +43,7 @@ public class CharNameTable {
 	private final Map<Integer, Integer> _accessLevels = new ConcurrentHashMap<>();
 	
 	protected CharNameTable() {
-		if (Config.CACHE_CHAR_NAMES) {
+		if (general().cacheCharNames()) {
 			loadAll();
 		}
 	}
@@ -78,7 +79,7 @@ public class CharNameTable {
 			}
 		}
 		
-		if (Config.CACHE_CHAR_NAMES) {
+		if (general().cacheCharNames()) {
 			return -1;
 		}
 		
@@ -117,7 +118,7 @@ public class CharNameTable {
 			return name;
 		}
 		
-		if (Config.CACHE_CHAR_NAMES) {
+		if (general().cacheCharNames()) {
 			return null;
 		}
 		

+ 4 - 3
src/main/java/com/l2jserver/gameserver/data/sql/impl/CharSummonTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -25,7 +27,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.NpcData;
 import com.l2jserver.gameserver.data.xml.impl.PetDataTable;
 import com.l2jserver.gameserver.datatables.SkillData;
@@ -69,7 +70,7 @@ public class CharSummonTable {
 	}
 	
 	public void init() {
-		if (Config.RESTORE_SERVITOR_ON_RECONNECT) {
+		if (character().restoreServitorOnReconnect()) {
 			try (var con = ConnectionFactory.getInstance().getConnection();
 				var s = con.createStatement();
 				var rs = s.executeQuery(INIT_SUMMONS)) {
@@ -81,7 +82,7 @@ public class CharSummonTable {
 			}
 		}
 		
-		if (Config.RESTORE_PET_ON_RECONNECT) {
+		if (character().restorePetOnReconnect()) {
 			try (var con = ConnectionFactory.getInstance().getConnection();
 				var s = con.createStatement();
 				var rs = s.executeQuery(INIT_PET)) {

+ 4 - 3
src/main/java/com/l2jserver/gameserver/data/sql/impl/ClanTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -30,7 +32,6 @@ import org.slf4j.LoggerFactory;
 import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.communitybbs.Manager.ForumsBBSManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.idfactory.IdFactory;
 import com.l2jserver.gameserver.instancemanager.AuctionManager;
 import com.l2jserver.gameserver.instancemanager.ClanHallSiegeManager;
@@ -73,7 +74,7 @@ public class ClanTable {
 	
 	protected ClanTable() {
 		// forums has to be loaded before clan data, because of last forum id used should have also memo included
-		if (Config.ENABLE_COMMUNITY_BOARD) {
+		if (general().enableCommunityBoard()) {
 			ForumsBBSManager.getInstance().initRoot();
 		}
 		
@@ -135,7 +136,7 @@ public class ClanTable {
 			return null;
 		}
 		
-		if (Config.DEBUG) {
+		if (general().debug()) {
 			LOG.info("{} requested a clan creation.", player);
 		}
 		

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/sql/impl/NpcBufferTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -25,7 +27,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
 
@@ -113,7 +114,7 @@ public class NpcBufferTable {
 			LOG.warn("There has been an error reading npc_buffer table!", ex);
 		}
 		
-		if (Config.CUSTOM_NPCBUFFER_TABLES) {
+		if (general().customNpcBufferTables()) {
 			try (var con = ConnectionFactory.getInstance().getConnection();
 				var s = con.createStatement();
 				var rset = s.executeQuery("SELECT `npc_id`,`skill_id`,`skill_level`,`skill_fee_id`,`skill_fee_amount`,`buff_group` FROM `custom_npc_buffer` ORDER BY `npc_id` ASC")) {

+ 8 - 8
src/main/java/com/l2jserver/gameserver/data/sql/impl/OfflineTradersTable.java

@@ -18,6 +18,7 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.customs;
 import static com.l2jserver.gameserver.enums.PrivateStoreType.NONE;
 
 import java.util.Calendar;
@@ -27,7 +28,6 @@ import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.gameserver.LoginServerThread;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.enums.PrivateStoreType;
 import com.l2jserver.gameserver.model.L2ManufactureItem;
 import com.l2jserver.gameserver.model.L2World;
@@ -72,7 +72,7 @@ public class OfflineTradersTable {
 						
 						switch (pc.getPrivateStoreType()) {
 							case BUY:
-								if (!Config.OFFLINE_TRADE_ENABLE) {
+								if (!customs().offlineTradeEnable()) {
 									continue;
 								}
 								title = pc.getBuyList().getTitle();
@@ -87,7 +87,7 @@ public class OfflineTradersTable {
 								break;
 							case SELL:
 							case PACKAGE_SELL:
-								if (!Config.OFFLINE_TRADE_ENABLE) {
+								if (!customs().offlineTradeEnable()) {
 									continue;
 								}
 								title = pc.getSellList().getTitle();
@@ -101,7 +101,7 @@ public class OfflineTradersTable {
 								}
 								break;
 							case MANUFACTURE:
-								if (!Config.OFFLINE_CRAFT_ENABLE) {
+								if (!customs().offlineCraftEnable()) {
 									continue;
 								}
 								title = pc.getStoreName();
@@ -137,10 +137,10 @@ public class OfflineTradersTable {
 			var rs = stm.executeQuery(LOAD_OFFLINE_STATUS)) {
 			while (rs.next()) {
 				long time = rs.getLong("time");
-				if (Config.OFFLINE_MAX_DAYS > 0) {
+				if (customs().getOfflineMaxDays() > 0) {
 					Calendar cal = Calendar.getInstance();
 					cal.setTimeInMillis(time);
-					cal.add(Calendar.DAY_OF_YEAR, Config.OFFLINE_MAX_DAYS);
+					cal.add(Calendar.DAY_OF_YEAR, customs().getOfflineMaxDays());
 					if (cal.getTimeInMillis() <= System.currentTimeMillis()) {
 						continue;
 					}
@@ -203,8 +203,8 @@ public class OfflineTradersTable {
 						}
 					}
 					player.sitDown();
-					if (Config.OFFLINE_SET_NAME_COLOR) {
-						player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR);
+					if (customs().offlineSetNameColor()) {
+						player.getAppearance().setNameColor(customs().getOfflineNameColor());
 					}
 					player.setPrivateStoreType(type);
 					player.setOnlineStatus(true, true);

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/sql/impl/PetNameTable.java

@@ -18,11 +18,12 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 
 public class PetNameTable {
 	
@@ -42,7 +43,7 @@ public class PetNameTable {
 	}
 	
 	public boolean isValidPetName(String name) {
-		return Config.PET_NAME_TEMPLATE.matcher(name).matches();
+		return character().getPetNameTemplate().matcher(name).matches();
 	}
 	
 	public static PetNameTable getInstance() {

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/sql/impl/TeleportLocationTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.sql.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -25,7 +27,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.L2TeleportLocation;
 
 public class TeleportLocationTable {
@@ -62,7 +63,7 @@ public class TeleportLocationTable {
 			LOG.error("There has been an error loading teleport table.", ex);
 		}
 		
-		if (Config.CUSTOM_TELEPORT_TABLE) {
+		if (general().customTeleportTable()) {
 			int _cTeleCount = _teleports.size();
 			try (var con = ConnectionFactory.getInstance().getConnection();
 				var s = con.createStatement();

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/xml/impl/BuyListData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.xml.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.io.File;
 import java.io.FileFilter;
 import java.util.HashMap;
@@ -30,7 +32,6 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.datatables.ItemTable;
 import com.l2jserver.gameserver.model.buylist.L2BuyList;
 import com.l2jserver.gameserver.model.buylist.Product;
@@ -58,7 +59,7 @@ public final class BuyListData implements IXmlReader {
 	public synchronized void load() {
 		_buyLists.clear();
 		parseDatapackDirectory("data/buylists", false);
-		if (Config.CUSTOM_BUYLIST_LOAD) {
+		if (general().customBuyListLoad()) {
 			parseDatapackDirectory("data/buylists/custom", false);
 		}
 		

+ 0 - 5
src/main/java/com/l2jserver/gameserver/data/xml/impl/EnchantSkillGroupsData.java

@@ -27,7 +27,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.L2EnchantSkillGroup;
 import com.l2jserver.gameserver.model.L2EnchantSkillGroup.EnchantSkillHolder;
 import com.l2jserver.gameserver.model.L2EnchantSkillLearn;
@@ -44,10 +43,6 @@ public class EnchantSkillGroupsData implements IXmlReader {
 	
 	private static final Logger LOG = LoggerFactory.getLogger(EnchantSkillGroupsData.class);
 	
-	public static final int NORMAL_ENCHANT_COST_MULTIPLIER = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
-	
-	public static final int SAFE_ENCHANT_COST_MULTIPLIER = Config.SAFE_ENCHANT_COST_MULTIPLIER;
-	
 	public static final int NORMAL_ENCHANT_BOOK = 6622;
 	
 	public static final int SAFE_ENCHANT_BOOK = 9627;

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/xml/impl/InitialEquipmentData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.xml.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -29,7 +31,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.base.ClassId;
 import com.l2jserver.gameserver.model.items.PcItemTemplate;
@@ -57,7 +58,7 @@ public final class InitialEquipmentData implements IXmlReader {
 	@Override
 	public void load() {
 		_initialEquipmentList.clear();
-		parseDatapackFile(Config.INITIAL_EQUIPMENT_EVENT ? EVENT : NORMAL);
+		parseDatapackFile(character().initialEquipmentEvent() ? EVENT : NORMAL);
 		LOG.info("Loaded {} initial equipment data.", _initialEquipmentList.size());
 	}
 	

+ 6 - 9
src/main/java/com/l2jserver/gameserver/data/xml/impl/MultisellData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.xml.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.io.File;
 import java.io.FileFilter;
 import java.util.HashMap;
@@ -31,7 +33,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.StatsSet;
 import com.l2jserver.gameserver.model.actor.L2Npc;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
@@ -70,7 +71,7 @@ public final class MultisellData implements IXmlReader {
 	public void load() {
 		_entries.clear();
 		parseDatapackDirectory("data/multisell", false);
-		if (Config.CUSTOM_MULTISELL_LOAD) {
+		if (general().customMultisellLoad()) {
 			parseDatapackDirectory("data/multisell/custom", false);
 		}
 		
@@ -99,13 +100,9 @@ public final class MultisellData implements IXmlReader {
 							if (list.getUseRate() <= 1e-6) {
 								throw new NumberFormatException("The value cannot be 0"); // threat 0 as invalid value
 							}
-						} catch (NumberFormatException e) {
-							try {
-								list.setUseRate(Config.class.getField(att.getNodeValue()).getDouble(Config.class));
-							} catch (Exception ex) {
-								LOG.warn("Unable to parse {}!", doc.getLocalName(), ex);
-								list.setUseRate(1.0);
-							}
+						} catch (NumberFormatException ex) {
+							LOG.warn("Unable to parse {}!", doc.getLocalName(), ex);
+							list.setUseRate(1.0);
 						} catch (DOMException ex) {
 							LOG.warn("Unable to parse {}!", doc.getLocalName(), ex);
 						}

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/xml/impl/NpcData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.xml.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -37,7 +39,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.datatables.SkillData;
 import com.l2jserver.gameserver.enums.AISkillScope;
 import com.l2jserver.gameserver.model.StatsSet;
@@ -79,7 +80,7 @@ public class NpcData implements IXmlReader {
 		parseDatapackDirectory("data/stats/npcs", false);
 		LOG.info("Loaded {} NPCs.", _npcs.size());
 		
-		if (Config.CUSTOM_NPC_DATA) {
+		if (general().customNpcData()) {
 			final int npcCount = _npcs.size();
 			parseDatapackDirectory("data/stats/npcs/custom", true);
 			LOG.info("Loaded {} custom NPCs.", (_npcs.size() - npcCount));

+ 5 - 4
src/main/java/com/l2jserver/gameserver/data/xml/impl/PlayerXpPercentLostData.java

@@ -18,13 +18,14 @@
  */
 package com.l2jserver.gameserver.data.xml.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.Arrays;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.util.IXmlReader;
 
 /**
@@ -33,7 +34,7 @@ import com.l2jserver.gameserver.util.IXmlReader;
  */
 public final class PlayerXpPercentLostData implements IXmlReader {
 	
-	private final double[] _playerXpPercentLost = new double[Config.MAX_PLAYER_LEVEL + 1];
+	private final double[] _playerXpPercentLost = new double[character().getMaxPlayerLevel() + 1];
 	
 	protected PlayerXpPercentLostData() {
 		Arrays.fill(_playerXpPercentLost, 1.);
@@ -60,9 +61,9 @@ public final class PlayerXpPercentLostData implements IXmlReader {
 	}
 	
 	public double getXpPercent(final int level) {
-		if (level > Config.MAX_PLAYER_LEVEL) {
+		if (level > character().getMaxPlayerLevel()) {
 			LOG.warn("Require to high level inside PlayerXpPercentLostData ({})", level);
-			return _playerXpPercentLost[Config.MAX_PLAYER_LEVEL];
+			return _playerXpPercentLost[character().getMaxPlayerLevel()];
 		}
 		return _playerXpPercentLost[level];
 	}

+ 3 - 2
src/main/java/com/l2jserver/gameserver/data/xml/impl/SkillTreesData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.data.xml.impl;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -35,7 +37,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.datatables.SkillData;
 import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.model.L2Clan;
@@ -462,7 +463,7 @@ public final class SkillTreesData implements IXmlReader {
 		}
 		
 		for (L2SkillLearn skill : skills.values()) {
-			if (((skill.getSkillId() == CommonSkill.DIVINE_INSPIRATION.getId()) && (!Config.AUTO_LEARN_DIVINE_INSPIRATION && includeAutoGet) && !player.isGM())) {
+			if (((skill.getSkillId() == CommonSkill.DIVINE_INSPIRATION.getId()) && (!character().autoLearnDivineInspiration() && includeAutoGet) && !player.isGM())) {
 				continue;
 			}
 			

+ 43 - 40
src/main/java/com/l2jserver/gameserver/datatables/AugmentationData.java

@@ -18,6 +18,10 @@
  */
 package com.l2jserver.gameserver.datatables;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -33,7 +37,6 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
 import com.l2jserver.commons.util.Rnd;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.OptionData;
 import com.l2jserver.gameserver.model.L2Augmentation;
 import com.l2jserver.gameserver.model.holders.SkillHolder;
@@ -101,7 +104,7 @@ public class AugmentationData {
 		
 		load();
 		
-		if (!Config.RETAIL_LIKE_AUGMENTATION) {
+		if (!character().retailLikeAugmentation()) {
 			for (int i = 0; i < 10; i++) {
 				LOG.info("Loaded {} blue, {} purple and {} red skills for life stone level {}.", _blueSkills.get(i).size(), _purpleSkills.get(i).size(), _redSkills.get(i).size(), i);
 			}
@@ -205,14 +208,14 @@ public class AugmentationData {
 		// Note: the skillmap data is only used when generating new augmentations
 		// the client expects a different id in order to display the skill in the
 		// items description...
-		if (!Config.RETAIL_LIKE_AUGMENTATION) {
+		if (!character().retailLikeAugmentation()) {
 			try {
 				int badAugmantData = 0;
 				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 				factory.setValidating(false);
 				factory.setIgnoringComments(true);
 				
-				File file = new File(Config.DATAPACK_ROOT + "/data/stats/augmentation/augmentation_skillmap.xml");
+				File file = new File(server().getDatapackRoot(), "data/stats/augmentation/augmentation_skillmap.xml");
 				if (!file.exists()) {
 					LOG.warn("The augmentation skillmap file is missing!");
 					return;
@@ -275,7 +278,7 @@ public class AugmentationData {
 			factory.setValidating(false);
 			factory.setIgnoringComments(true);
 			
-			File aFile = new File(Config.DATAPACK_ROOT + "/data/stats/augmentation/retailchances.xml");
+			File aFile = new File(server().getDatapackRoot(), "data/stats/augmentation/retailchances.xml");
 			if (aFile.exists()) {
 				Document aDoc = null;
 				
@@ -346,12 +349,12 @@ public class AugmentationData {
 			}
 		}
 		
-		if (Config.RETAIL_LIKE_AUGMENTATION_ACCESSORY) {
+		if (character().retailLikeAugmentationAccessory()) {
 			DocumentBuilderFactory factory3 = DocumentBuilderFactory.newInstance();
 			factory3.setValidating(false);
 			factory3.setIgnoringComments(true);
 			
-			File aFile3 = new File(Config.DATAPACK_ROOT + "/data/stats/augmentation/retailchances_accessory.xml");
+			File aFile3 = new File(server().getDatapackRoot(), "data/stats/augmentation/retailchances_accessory.xml");
 			if (aFile3.exists()) {
 				Document aDoc = null;
 				
@@ -445,7 +448,7 @@ public class AugmentationData {
 	private L2Augmentation generateRandomWeaponAugmentation(int lifeStoneLevel, int lifeStoneGrade, int lifeStoneId, L2ItemInstance item) {
 		int stat12 = 0;
 		int stat34 = 0;
-		if (Config.RETAIL_LIKE_AUGMENTATION) {
+		if (character().retailLikeAugmentation()) {
 			if (item.getItem().isMagicWeapon()) {
 				List<AugmentationChance> _selectedChances12 = new ArrayList<>();
 				List<AugmentationChance> _selectedChances34 = new ArrayList<>();
@@ -466,30 +469,30 @@ public class AugmentationData {
 						stat12 = ac.getAugmentId();
 					}
 				}
-				int[] gradeChance = null;
+				List<Integer> gradeChance = null;
 				switch (lifeStoneGrade) {
 					case AbstractRefinePacket.GRADE_NONE:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationNoGradeChance();
 						break;
 					case AbstractRefinePacket.GRADE_MID:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationMidGradeChance();
 						break;
 					case AbstractRefinePacket.GRADE_HIGH:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationHighGradeChance();
 						break;
 					case AbstractRefinePacket.GRADE_TOP:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationTopGradeChance();
 						break;
 					default:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationNoGradeChance();
 				}
 				
 				int c = Rnd.get(100);
-				if (c < gradeChance[0]) {
+				if (c < gradeChance.get(0)) {
 					c = 55;
-				} else if (c < (gradeChance[0] + gradeChance[1])) {
+				} else if (c < (gradeChance.get(0) + gradeChance.get(1))) {
 					c = 35;
-				} else if (c < (gradeChance[0] + gradeChance[1] + gradeChance[2])) {
+				} else if (c < (gradeChance.get(0) + gradeChance.get(1) + gradeChance.get(2))) {
 					c = 7;
 				} else {
 					c = 3;
@@ -530,30 +533,30 @@ public class AugmentationData {
 						stat12 = ac.getAugmentId();
 					}
 				}
-				int[] gradeChance = null;
+				List<Integer> gradeChance = null;
 				switch (lifeStoneGrade) {
 					case AbstractRefinePacket.GRADE_NONE:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationNoGradeChance();
 						break;
 					case AbstractRefinePacket.GRADE_MID:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationMidGradeChance();
 						break;
 					case AbstractRefinePacket.GRADE_HIGH:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationHighGradeChance();
 						break;
 					case AbstractRefinePacket.GRADE_TOP:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationTopGradeChance();
 						break;
 					default:
-						gradeChance = Config.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
+						gradeChance = character().getRetailLikeAugmentationNoGradeChance();
 				}
 				
 				int c = Rnd.get(100);
-				if (c < gradeChance[0]) {
+				if (c < gradeChance.get(0)) {
 					c = 55;
-				} else if (c < (gradeChance[0] + gradeChance[1])) {
+				} else if (c < (gradeChance.get(0) + gradeChance.get(1))) {
 					c = 35;
-				} else if (c < (gradeChance[0] + gradeChance[1] + gradeChance[2])) {
+				} else if (c < (gradeChance.get(0) + gradeChance.get(1) + gradeChance.get(2))) {
 					c = 7;
 				} else {
 					c = 3;
@@ -583,44 +586,44 @@ public class AugmentationData {
 		
 		switch (lifeStoneGrade) {
 			case AbstractRefinePacket.GRADE_NONE:
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_NG_SKILL_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationNGSkillChance()) {
 					generateSkill = true;
 				}
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_NG_GLOW_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationNGGlowChance()) {
 					generateGlow = true;
 				}
 				break;
 			case AbstractRefinePacket.GRADE_MID:
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_MID_SKILL_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationMidSkillChance()) {
 					generateSkill = true;
 				}
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_MID_GLOW_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationMidGlowChance()) {
 					generateGlow = true;
 				}
 				break;
 			case AbstractRefinePacket.GRADE_HIGH:
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_HIGH_SKILL_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationHighSkillChance()) {
 					generateSkill = true;
 				}
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_HIGH_GLOW_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationHighGlowChance()) {
 					generateGlow = true;
 				}
 				break;
 			case AbstractRefinePacket.GRADE_TOP:
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_TOP_SKILL_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationTopSkillChance()) {
 					generateSkill = true;
 				}
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_TOP_GLOW_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationTopGlowChance()) {
 					generateGlow = true;
 				}
 				break;
 			case AbstractRefinePacket.GRADE_ACC:
-				if (Rnd.get(1, 100) <= Config.AUGMENTATION_ACC_SKILL_CHANCE) {
+				if (Rnd.get(1, 100) <= character().getAugmentationAccSkillChance()) {
 					generateSkill = true;
 				}
 		}
 		
-		if (!generateSkill && (Rnd.get(1, 100) <= Config.AUGMENTATION_BASESTAT_CHANCE)) {
+		if (!generateSkill && (Rnd.get(1, 100) <= character().getAugmentationBaseStatChance())) {
 			stat34 = Rnd.get(BASESTAT_STR, BASESTAT_MEN);
 		}
 		
@@ -703,7 +706,7 @@ public class AugmentationData {
 		}
 		stat12 = Rnd.get(offset, (offset + STAT_SUBBLOCKSIZE) - 1);
 		
-		if (Config.DEBUG) {
+		if (general().debug()) {
 			LOG.info("Augmentation success: stat12={}; stat34={}; resultColor={}; level={}; grade={}", stat12, stat34, resultColor, lifeStoneLevel, lifeStoneGrade);
 		}
 		return new L2Augmentation(((stat34 << 16) + stat12));
@@ -712,7 +715,7 @@ public class AugmentationData {
 	private L2Augmentation generateRandomAccessoryAugmentation(int lifeStoneLevel, int bodyPart, int lifeStoneId) {
 		int stat12 = 0;
 		int stat34 = 0;
-		if (Config.RETAIL_LIKE_AUGMENTATION_ACCESSORY) {
+		if (character().retailLikeAugmentationAccessory()) {
 			List<augmentationChanceAcc> _selectedChances12 = new ArrayList<>();
 			List<augmentationChanceAcc> _selectedChances34 = new ArrayList<>();
 			for (augmentationChanceAcc ac : _augmentationChancesAcc) {
@@ -785,7 +788,7 @@ public class AugmentationData {
 		// first augmentation (stats only)
 		stat12 = Rnd.get(ACC_STAT_SUBBLOCKSIZE);
 		Options op = null;
-		if (Rnd.get(1, 100) <= Config.AUGMENTATION_ACC_SKILL_CHANCE) {
+		if (Rnd.get(1, 100) <= character().getAugmentationAccSkillChance()) {
 			// second augmentation (skill)
 			stat34 = base + Rnd.get(skillsLength);
 			op = OptionData.getInstance().getOptions(stat34);
@@ -803,7 +806,7 @@ public class AugmentationData {
 		// stat12 has stats only
 		stat12 = base + skillsLength + (ACC_STAT_SUBBLOCKSIZE * resultColor) + stat12;
 		
-		if (Config.DEBUG) {
+		if (general().debug()) {
 			LOG.info("Accessory augmentation success: stat12={}; stat34={}; level={}", stat12, stat34, lifeStoneLevel);
 		}
 		return new L2Augmentation(((stat34 << 16) + stat12));

+ 10 - 9
src/main/java/com/l2jserver/gameserver/datatables/BotReportTable.java

@@ -18,6 +18,7 @@
  */
 package com.l2jserver.gameserver.datatables;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
 import static com.l2jserver.gameserver.network.SystemMessageId.C1_WAS_REPORTED_AS_BOT;
 import static com.l2jserver.gameserver.network.SystemMessageId.CANNOT_REPORT_TARGET_ALREDY_REPORTED_BY_CLAN_ALLY_MEMBER_OR_SAME_IP;
 import static com.l2jserver.gameserver.network.SystemMessageId.TARGET_NOT_REPORT_CANNOT_REPORT_PEACE_PVP_ZONE_OR_OLYMPIAD_OR_CLAN_WAR_ENEMY;
@@ -29,6 +30,7 @@ import static com.l2jserver.gameserver.network.SystemMessageId.YOU_CAN_REPORT_IN
 import static com.l2jserver.gameserver.network.SystemMessageId.YOU_HAVE_BEEN_REPORTED_AND_CANNOT_REPORT;
 import static com.l2jserver.gameserver.network.SystemMessageId.YOU_HAVE_USED_ALL_POINTS_POINTS_ARE_RESET_AT_NOON;
 import static com.l2jserver.gameserver.network.SystemMessageId.YOU_HAVE_USED_REPORT_POINT_ON_C1_YOU_HAVE_C2_POINTS_LEFT;
+import static java.util.concurrent.TimeUnit.DAYS;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -47,7 +49,6 @@ import org.xml.sax.helpers.DefaultHandler;
 
 import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.L2Clan;
 import com.l2jserver.gameserver.model.L2Object;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
@@ -85,7 +86,7 @@ public final class BotReportTable {
 	private Map<Integer, PunishHolder> _punishments;
 	
 	BotReportTable() {
-		if (Config.BOTREPORT_ENABLE) {
+		if (general().enableBotReportButton()) {
 			_ipRegistry = new HashMap<>();
 			_charRegistry = new ConcurrentHashMap<>();
 			_reports = new ConcurrentHashMap<>();
@@ -118,7 +119,7 @@ public final class BotReportTable {
 			var rset = st.executeQuery(SQL_LOAD_REPORTED_CHAR_DATA)) {
 			long lastResetTime = 0;
 			try {
-				String[] hour = Config.BOTREPORT_RESETPOINT_HOUR;
+				String[] hour = general().getBotReportPointsResetHour().split(":");
 				Calendar c = Calendar.getInstance();
 				c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour[0]));
 				c.set(Calendar.MINUTE, Integer.parseInt(hour[1]));
@@ -246,7 +247,7 @@ public final class BotReportTable {
 					return false;
 				}
 				
-				if (!Config.BOTREPORT_ALLOW_REPORTS_FROM_SAME_CLAN_MEMBERS && rcd.reportedBySameClan(reporter.getClan())) {
+				if (!general().allowReportsFromSameClanMembers() && rcd.reportedBySameClan(reporter.getClan())) {
 					reporter.sendPacket(CANNOT_REPORT_TARGET_ALREDY_REPORTED_BY_CLAN_ALLY_MEMBER_OR_SAME_IP);
 					return false;
 				}
@@ -259,7 +260,7 @@ public final class BotReportTable {
 				}
 				
 				long reuse = (System.currentTimeMillis() - rcdRep.getLastReporTime());
-				if (reuse < Config.BOTREPORT_REPORT_DELAY) {
+				if (reuse < general().getBotReportDelay()) {
 					SystemMessage sm = SystemMessage.getSystemMessage(YOU_CAN_REPORT_IN_S1_MINS_YOU_HAVE_S2_POINTS_LEFT);
 					sm.addInt((int) (reuse / 60000));
 					sm.addInt(rcdRep.getPointsLeft());
@@ -361,7 +362,7 @@ public final class BotReportTable {
 	
 	private void scheduleResetPointTask() {
 		try {
-			String[] hour = Config.BOTREPORT_RESETPOINT_HOUR;
+			String[] hour = general().getBotReportPointsResetHour().split(":");
 			Calendar c = Calendar.getInstance();
 			c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour[0]));
 			c.set(Calendar.MINUTE, Integer.parseInt(hour[1]));
@@ -372,7 +373,7 @@ public final class BotReportTable {
 			
 			ThreadPoolManager.getInstance().scheduleGeneral(new ResetPointTask(), c.getTimeInMillis() - System.currentTimeMillis());
 		} catch (Exception ex) {
-			ThreadPoolManager.getInstance().scheduleGeneral(new ResetPointTask(), 24 * 3600 * 1000);
+			ThreadPoolManager.getInstance().scheduleGeneral(new ResetPointTask(), DAYS.toMillis(1));
 			LOG.warn("Could not properly schedule bot report points reset task. Scheduled in 24 hours!", ex);
 		}
 	}
@@ -394,14 +395,14 @@ public final class BotReportTable {
 	}
 	
 	/**
-	 * Checks and return if the abstrat barrier specified by an integer (map key) has accomplished the waiting time
+	 * Checks and return if the abstract barrier specified by an integer (map key) has accomplished the waiting time
 	 * @param map (a Map to study (Int = barrier, Long = fully qualified unix time)
 	 * @param objectId (an existent map key)
 	 * @return true if the time has passed.
 	 */
 	private static boolean timeHasPassed(Map<Integer, Long> map, int objectId) {
 		if (map.containsKey(objectId)) {
-			return (System.currentTimeMillis() - map.get(objectId)) > Config.BOTREPORT_REPORT_DELAY;
+			return (System.currentTimeMillis() - map.get(objectId)) > general().getBotReportDelay();
 		}
 		return true;
 	}

+ 12 - 11
src/main/java/com/l2jserver/gameserver/datatables/ItemTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.datatables;
 
+import static com.l2jserver.gameserver.config.Configuration.character;
+import static com.l2jserver.gameserver.config.Configuration.general;
 import static com.l2jserver.gameserver.model.itemcontainer.Inventory.ADENA_ID;
 import static com.l2jserver.gameserver.model.items.type.EtcItemType.ARROW;
 import static com.l2jserver.gameserver.model.items.type.EtcItemType.SHOT;
@@ -32,7 +34,6 @@ import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
 import com.l2jserver.gameserver.ThreadPoolManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.EnchantItemHPBonusData;
 import com.l2jserver.gameserver.engines.DocumentEngine;
 import com.l2jserver.gameserver.enums.ItemLocation;
@@ -203,19 +204,19 @@ public class ItemTable {
 			{
 				L2Attackable raid = (L2Attackable) reference;
 				// if in CommandChannel and was killing a World/RaidBoss
-				if ((raid.getFirstCommandChannelAttacked() != null) && !Config.AUTO_LOOT_RAIDS) {
+				if ((raid.getFirstCommandChannelAttacked() != null) && !character().autoLootRaids()) {
 					item.setOwnerId(raid.getFirstCommandChannelAttacked().getLeaderObjectId());
-					itemLootShedule = ThreadPoolManager.getInstance().scheduleGeneral(new ResetOwner(item), Config.LOOT_RAIDS_PRIVILEGE_INTERVAL);
+					itemLootShedule = ThreadPoolManager.getInstance().scheduleGeneral(new ResetOwner(item), character().getRaidLootRightsInterval());
 					item.setItemLootShedule(itemLootShedule);
 				}
-			} else if (!Config.AUTO_LOOT || ((reference instanceof L2EventMonsterInstance) && ((L2EventMonsterInstance) reference).eventDropOnGround())) {
+			} else if (!character().autoLoot() || ((reference instanceof L2EventMonsterInstance) && ((L2EventMonsterInstance) reference).eventDropOnGround())) {
 				item.setOwnerId(actor.getObjectId());
 				itemLootShedule = ThreadPoolManager.getInstance().scheduleGeneral(new ResetOwner(item), 15000);
 				item.setItemLootShedule(itemLootShedule);
 			}
 		}
 		
-		if (Config.DEBUG) {
+		if (general().debug()) {
 			LOG.info("Item created object Id {} and item Id {}.", item.getObjectId(), itemId);
 		}
 		
@@ -227,8 +228,8 @@ public class ItemTable {
 			item.setCount(count);
 		}
 		
-		if (Config.LOG_ITEMS && !process.equals("Reset")) {
-			if (!Config.LOG_ITEMS_SMALL_LOG || (Config.LOG_ITEMS_SMALL_LOG && (item.isEquipable() || (item.getId() == ADENA_ID)))) {
+		if (general().logItems() && !process.equals("Reset")) {
+			if (!general().logItemsSmallLog() || (general().logItemsSmallLog() && (item.isEquipable() || (item.getId() == ADENA_ID)))) {
 				if (item.getItemType() != ARROW && item.getItemType() != SHOT) {
 					LOG_ITEM.info("CREATED {} by {}, referenced by {}.", item, actor, reference);
 				}
@@ -244,7 +245,7 @@ public class ItemTable {
 					referenceName = (String) reference;
 				}
 				String targetName = (actor.getTarget() != null ? actor.getTarget().getName() : "no-target");
-				if (Config.GMAUDIT) {
+				if (general().gmAudit()) {
 					GMAudit.auditGMAction(actor.getName() + " [" + actor.getObjectId() + "]", process + "(id: " + itemId + " count: " + count + " name: " + item.getItemName() + " objId: " + item.getObjectId() + ")", targetName, "L2Object referencing this action is: " + referenceName);
 				}
 			}
@@ -283,8 +284,8 @@ public class ItemTable {
 			L2World.getInstance().removeObject(item);
 			IdFactory.getInstance().releaseId(item.getObjectId());
 			
-			if (Config.LOG_ITEMS) {
-				if (!Config.LOG_ITEMS_SMALL_LOG || (Config.LOG_ITEMS_SMALL_LOG && (item.isEquipable() || (item.getId() == ADENA_ID)))) {
+			if (general().logItems()) {
+				if (!general().logItemsSmallLog() || (general().logItemsSmallLog() && (item.isEquipable() || (item.getId() == ADENA_ID)))) {
 					if (item.getItemType() != ARROW && item.getItemType() != SHOT) {
 						LOG_ITEM.info("DELETED {} amount {} by {}, referenced by {}.", item, old, actor, reference);
 					}
@@ -300,7 +301,7 @@ public class ItemTable {
 						referenceName = (String) reference;
 					}
 					String targetName = (actor.getTarget() != null ? actor.getTarget().getName() : "no-target");
-					if (Config.GMAUDIT) {
+					if (general().gmAudit()) {
 						GMAudit.auditGMAction(actor.getName() + " [" + actor.getObjectId() + "]", process + "(id: " + item.getId() + " count: " + item.getCount() + " itemObjId: " + item.getObjectId() + ")", targetName, "L2Object referencing this action is: " + referenceName);
 					}
 				}

+ 3 - 2
src/main/java/com/l2jserver/gameserver/datatables/MerchantPriceConfigTable.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.datatables;
 
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
@@ -33,7 +35,6 @@ import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
 import com.l2jserver.gameserver.InstanceListManager;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.instancemanager.CastleManager;
 import com.l2jserver.gameserver.model.actor.instance.L2MerchantInstance;
 import com.l2jserver.gameserver.model.entity.Castle;
@@ -72,7 +73,7 @@ public class MerchantPriceConfigTable implements InstanceListManager {
 		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 		factory.setValidating(false);
 		factory.setIgnoringComments(true);
-		File file = new File(Config.DATAPACK_ROOT + "/data/" + MPCS_FILE);
+		File file = new File(server().getDatapackRoot(), "data/" + MPCS_FILE);
 		if (file.exists()) {
 			int defaultPriceConfigId;
 			Document doc = factory.newDocumentBuilder().parse(file);

+ 3 - 2
src/main/java/com/l2jserver/gameserver/datatables/SkillData.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.datatables;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -26,7 +28,6 @@ import java.util.Set;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
 import com.l2jserver.gameserver.engines.DocumentEngine;
 import com.l2jserver.gameserver.model.skills.Skill;
@@ -108,7 +109,7 @@ public final class SkillData {
 		final int maxLvl = getMaxLevel(skillId);
 		// requested level too high
 		if ((maxLvl > 0) && (level > maxLvl)) {
-			if (Config.DEBUG) {
+			if (general().debug()) {
 				LOG.warn("Call to unexisting skill level Id {} requested level {} max level {}!", skillId, level, maxLvl);
 			}
 			return _skills.get(getSkillHashCode(skillId, maxLvl));

+ 7 - 5
src/main/java/com/l2jserver/gameserver/datatables/SpawnTable.java

@@ -18,6 +18,9 @@
  */
 package com.l2jserver.gameserver.datatables;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -32,7 +35,6 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.data.xml.impl.NpcData;
 import com.l2jserver.gameserver.instancemanager.DayNightSpawnManager;
 import com.l2jserver.gameserver.instancemanager.ZoneManager;
@@ -59,12 +61,12 @@ public final class SpawnTable implements IXmlReader {
 	
 	@Override
 	public void load() {
-		if (!Config.ALT_DEV_NO_SPAWNS) {
+		if (!general().noSpawns()) {
 			fillSpawnTable(false);
 			final int spawnCount = _spawnTable.size();
 			LOG.info("Loaded {} NPC spawns.", spawnCount);
 			
-			if (Config.CUSTOM_SPAWNLIST_TABLE) {
+			if (general().customSpawnlistTable()) {
 				fillSpawnTable(true);
 				LOG.info("Loaded {} custom NPC spawns.", (_spawnTable.size() - spawnCount));
 			}
@@ -352,7 +354,7 @@ public final class SpawnTable implements IXmlReader {
 		addSpawn(spawn);
 		
 		if (storeInDb) {
-			final String spawnTable = spawn.isCustom() && Config.CUSTOM_SPAWNLIST_TABLE ? "custom_spawnlist" : "spawnlist";
+			final String spawnTable = spawn.isCustom() && general().customSpawnlistTable() ? "custom_spawnlist" : "spawnlist";
 			try (var con = ConnectionFactory.getInstance().getConnection();
 				var insert = con.prepareStatement("INSERT INTO " + spawnTable + "(count,npc_templateid,locx,locy,locz,heading,respawn_delay,respawn_random,loc_id) values(?,?,?,?,?,?,?,?,?)")) {
 				insert.setInt(1, spawn.getAmount());
@@ -361,7 +363,7 @@ public final class SpawnTable implements IXmlReader {
 				insert.setInt(4, spawn.getY());
 				insert.setInt(5, spawn.getZ());
 				insert.setInt(6, spawn.getHeading());
-				insert.setInt(7, spawn.getRespawnDelay() / 1000);
+				insert.setInt(7, (int) MILLISECONDS.toSeconds(spawn.getRespawnDelay()));
 				insert.setInt(8, spawn.getRespawnMaxDelay() - spawn.getRespawnMinDelay());
 				insert.setInt(9, spawn.getLocationId());
 				insert.execute();

+ 6 - 4
src/main/java/com/l2jserver/gameserver/engines/DocumentEngine.java

@@ -18,6 +18,9 @@
  */
 package com.l2jserver.gameserver.engines;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
@@ -26,7 +29,6 @@ import java.util.Map;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.datatables.SkillData;
 import com.l2jserver.gameserver.engines.items.DocumentItem;
 import com.l2jserver.gameserver.engines.skills.DocumentSkill;
@@ -52,17 +54,17 @@ public class DocumentEngine {
 	
 	protected DocumentEngine() {
 		hashFiles("data/stats/items", _itemFiles);
-		if (Config.CUSTOM_ITEMS_LOAD) {
+		if (general().customItemsLoad()) {
 			hashFiles("data/stats/items/custom", _itemFiles);
 		}
 		hashFiles("data/stats/skills", _skillFiles);
-		if (Config.CUSTOM_SKILLS_LOAD) {
+		if (general().customSkillsLoad()) {
 			hashFiles("data/stats/skills/custom", _skillFiles);
 		}
 	}
 	
 	private void hashFiles(String dirname, List<File> hash) {
-		final var dir = new File(Config.DATAPACK_ROOT, dirname);
+		final var dir = new File(server().getDatapackRoot(), dirname);
 		if (!dir.exists()) {
 			LOG.warn("Directory {} does not exists!", dir.getAbsolutePath());
 			return;

+ 1 - 10
src/main/java/com/l2jserver/gameserver/enums/IllegalActionPunishmentType.java

@@ -27,14 +27,5 @@ public enum IllegalActionPunishmentType {
 	BROADCAST,
 	KICK,
 	KICKBAN,
-	JAIL;
-	
-	public static final IllegalActionPunishmentType findByName(String name) {
-		for (IllegalActionPunishmentType type : values()) {
-			if (type.name().toLowerCase().equals(name.toLowerCase())) {
-				return type;
-			}
-		}
-		return NONE;
-	}
+	JAIL
 }

+ 4 - 3
src/main/java/com/l2jserver/gameserver/handler/CommunityBoardHandler.java

@@ -18,12 +18,13 @@
  */
 package com.l2jserver.gameserver.handler;
 
+import static com.l2jserver.gameserver.config.Configuration.general;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Logger;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.SystemMessageId;
 import com.l2jserver.gameserver.util.Util;
@@ -93,7 +94,7 @@ public final class CommunityBoardHandler implements IHandler<IParseBoardHandler,
 			return;
 		}
 		
-		if (!Config.ENABLE_COMMUNITY_BOARD) {
+		if (!general().enableCommunityBoard()) {
 			player.sendPacket(SystemMessageId.CB_OFFLINE);
 			return;
 		}
@@ -122,7 +123,7 @@ public final class CommunityBoardHandler implements IHandler<IParseBoardHandler,
 			return;
 		}
 		
-		if (!Config.ENABLE_COMMUNITY_BOARD) {
+		if (!general().enableCommunityBoard()) {
 			player.sendPacket(SystemMessageId.CB_OFFLINE);
 			return;
 		}

+ 3 - 2
src/main/java/com/l2jserver/gameserver/idfactory/CompactionIDFactory.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.idfactory;
 
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.sql.Connection;
 import java.sql.SQLException;
 
@@ -25,7 +27,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 
 /**
  * 18.8.2010 - JIV: Disabling until someone update it
@@ -66,7 +67,7 @@ public class CompactionIDFactory extends IdFactory {
 			return N;
 		}
 		// check these IDs not present in DB
-		if (Config.BAD_ID_CHECKING) {
+		if (server().badIdChecking()) {
 			for (String check : ID_CHECKS) {
 				try (var ps = con.prepareStatement(check)) {
 					ps.setInt(1, _curOID);

+ 12 - 11
src/main/java/com/l2jserver/gameserver/idfactory/IdFactory.java

@@ -18,6 +18,10 @@
  */
 package com.l2jserver.gameserver.idfactory;
 
+import static com.l2jserver.gameserver.config.Configuration.customs;
+import static com.l2jserver.gameserver.config.Configuration.general;
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -26,7 +30,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 
 /**
  * Id Factory.
@@ -130,8 +133,8 @@ public abstract class IdFactory {
 	
 	protected IdFactory() {
 		setAllCharacterOffline();
-		if (Config.DATABASE_CLEAN_UP) {
-			if (Config.L2JMOD_ALLOW_WEDDING) {
+		if (general().databaseCleanUp()) {
+			if (customs().allowWedding()) {
 				cleanInvalidWeddings();
 			}
 			cleanUpDB();
@@ -140,20 +143,18 @@ public abstract class IdFactory {
 	}
 	
 	static {
-		switch (Config.IDFACTORY_TYPE) {
-			case Compaction:
-				throw new UnsupportedOperationException("Compaction IdFactory is disabled.");
-				// _instance = new CompactionIDFactory();
-				// break;
+		switch (server().getIdFactory()) {
+			default:
 			case BitSet:
 				_instance = new BitSetIDFactory();
 				break;
 			case Stack:
 				_instance = new StackIDFactory();
 				break;
-			default:
-				_instance = null;
-				break;
+			case Compaction:
+				throw new UnsupportedOperationException("Compaction IdFactory is disabled.");
+			// _instance = new CompactionIDFactory();
+			// break;
 		}
 	}
 	

+ 12 - 0
src/main/java/com/l2jserver/gameserver/idfactory/IdFactoryType.java

@@ -0,0 +1,12 @@
+package com.l2jserver.gameserver.idfactory;
+
+/**
+ * Id Factory Type.
+ * @author Zoey76
+ * @version 2.6.1.0
+ */
+public enum IdFactoryType {
+	Compaction,
+	BitSet,
+	Stack
+}

+ 3 - 2
src/main/java/com/l2jserver/gameserver/idfactory/StackIDFactory.java

@@ -18,6 +18,8 @@
  */
 package com.l2jserver.gameserver.idfactory;
 
+import static com.l2jserver.gameserver.config.Configuration.server;
+
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Stack;
@@ -26,7 +28,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.l2jserver.commons.database.ConnectionFactory;
-import com.l2jserver.gameserver.config.Config;
 
 /**
  * Stack ID Factory.
@@ -74,7 +75,7 @@ public class StackIDFactory extends IdFactory {
 			return N;
 		}
 		// check these IDs not present in DB
-		if (Config.BAD_ID_CHECKING) {
+		if (server().badIdChecking()) {
 			for (String check : ID_CHECKS) {
 				try (var ps = con.prepareStatement(check)) {
 					ps.setInt(1, _tempOID);

+ 11 - 10
src/main/java/com/l2jserver/gameserver/instancemanager/AntiFeedManager.java

@@ -18,11 +18,13 @@
  */
 package com.l2jserver.gameserver.instancemanager;
 
+import static com.l2jserver.gameserver.config.Configuration.customs;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.l2jserver.gameserver.config.Config;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.network.L2GameClient;
@@ -54,7 +56,7 @@ public final class AntiFeedManager {
 	 * @return True if kill is non-feeded.
 	 */
 	public final boolean check(L2Character attacker, L2Character target) {
-		if (!Config.L2JMOD_ANTIFEED_ENABLE) {
+		if (!customs().antiFeedEnable()) {
 			return true;
 		}
 		
@@ -67,13 +69,13 @@ public final class AntiFeedManager {
 			return false;
 		}
 		
-		if ((Config.L2JMOD_ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) {
-			if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.L2JMOD_ANTIFEED_INTERVAL) {
+		if ((customs().getAntiFeedInterval() > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) {
+			if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < SECONDS.toMillis(customs().getAntiFeedInterval())) {
 				return false;
 			}
 		}
 		
-		if (Config.L2JMOD_ANTIFEED_DUALBOX && (attacker != null)) {
+		if (customs().antiFeedDualbox() && (attacker != null)) {
 			final L2PcInstance attackerPlayer = attacker.getActingPlayer();
 			if (attackerPlayer == null) {
 				return false;
@@ -83,7 +85,7 @@ public final class AntiFeedManager {
 			final L2GameClient attackerClient = attackerPlayer.getClient();
 			if ((targetClient == null) || (attackerClient == null) || targetClient.isDetached() || attackerClient.isDetached()) {
 				// unable to check ip address
-				return !Config.L2JMOD_ANTIFEED_DISCONNECTED_AS_DUALBOX;
+				return !customs().antiFeedDisconnectedAsDualbox();
 			}
 			
 			return !targetClient.getConnectionAddress().equals(attackerClient.getConnectionAddress());
@@ -136,9 +138,8 @@ public final class AntiFeedManager {
 		}
 		
 		final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
-		
 		final AtomicInteger connectionCount = event.computeIfAbsent(addrHash, k -> new AtomicInteger());
-		int whiteListCount = Config.L2JMOD_DUALBOX_CHECK_WHITELIST.getOrDefault(addrHash, 0);
+		int whiteListCount = customs().getDualboxCheckWhitelist().getOrDefault(addrHash, 0);
 		if ((whiteListCount < 0) || ((connectionCount.get() + 1) <= (max + whiteListCount))) {
 			connectionCount.incrementAndGet();
 			return true;
@@ -228,8 +229,8 @@ public final class AntiFeedManager {
 		
 		final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
 		int limit = max;
-		if (Config.L2JMOD_DUALBOX_CHECK_WHITELIST.containsKey(addrHash)) {
-			limit += Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash);
+		if (customs().getDualboxCheckWhitelist().containsKey(addrHash)) {
+			limit += customs().getDualboxCheckWhitelist().get(addrHash);
 		}
 		return limit;
 	}

Некоторые файлы не были показаны из-за большого количества измененных файлов