Browse Source

instance manager rework by fordfrog, big thx (+l2j code format)

janiii 16 years ago
parent
commit
f44166e15d
100 changed files with 12853 additions and 12683 deletions
  1. 147 121
      L2_GameServer/java/net/sf/l2j/L2DatabaseFactory.java
  2. 10 11
      L2_GameServer/java/net/sf/l2j/gameserver/Announcements.java
  3. 10 8
      L2_GameServer/java/net/sf/l2j/gameserver/GameServer.java
  4. 77 68
      L2_GameServer/java/net/sf/l2j/gameserver/GameTimeController.java
  5. 155 140
      L2_GameServer/java/net/sf/l2j/gameserver/GeoData.java
  6. 569 547
      L2_GameServer/java/net/sf/l2j/gameserver/GeoEngine.java
  7. 26 21
      L2_GameServer/java/net/sf/l2j/gameserver/GmListTable.java
  8. 25 0
      L2_GameServer/java/net/sf/l2j/gameserver/InstanceListManager.java
  9. 76 74
      L2_GameServer/java/net/sf/l2j/gameserver/ItemsAutoDestroy.java
  10. 269 251
      L2_GameServer/java/net/sf/l2j/gameserver/LoginServerThread.java
  11. 117 119
      L2_GameServer/java/net/sf/l2j/gameserver/MonsterRace.java
  12. 323 307
      L2_GameServer/java/net/sf/l2j/gameserver/RecipeController.java
  13. 363 362
      L2_GameServer/java/net/sf/l2j/gameserver/SevenSigns.java
  14. 2429 2393
      L2_GameServer/java/net/sf/l2j/gameserver/SevenSignsFestival.java
  15. 20 21
      L2_GameServer/java/net/sf/l2j/gameserver/Shutdown.java
  16. 23 18
      L2_GameServer/java/net/sf/l2j/gameserver/Territory.java
  17. 274 309
      L2_GameServer/java/net/sf/l2j/gameserver/ThreadPoolManager.java
  18. 325 307
      L2_GameServer/java/net/sf/l2j/gameserver/TradeController.java
  19. 474 464
      L2_GameServer/java/net/sf/l2j/gameserver/Universe.java
  20. 7 6
      L2_GameServer/java/net/sf/l2j/gameserver/ai2/AiManager.java
  21. 11 10
      L2_GameServer/java/net/sf/l2j/gameserver/cache/CrestCache.java
  22. 8 6
      L2_GameServer/java/net/sf/l2j/gameserver/cache/HtmCache.java
  23. 7 4
      L2_GameServer/java/net/sf/l2j/gameserver/cache/WarehouseCacheManager.java
  24. 5 2
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/BB/Forum.java
  25. 12 11
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/CommunityBoard.java
  26. 15 9
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/AdminBBSManager.java
  27. 181 282
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/ClanBBSManager.java
  28. 23 28
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/ForumsBBSManager.java
  29. 81 141
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/PostBBSManager.java
  30. 168 363
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/RegionBBSManager.java
  31. 13 5
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/TopBBSManager.java
  32. 109 160
      L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/TopicBBSManager.java
  33. 13 9
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/AccessLevels.java
  34. 7 6
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/AdminCommandAccessRights.java
  35. 15 12
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/ArmorSetsTable.java
  36. 39 33
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/AugmentationData.java
  37. 10 6
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/CharNameTable.java
  38. 10 8
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/CharTemplateTable.java
  39. 11 11
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/ClanTable.java
  40. 111 102
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/DoorTable.java
  41. 6 7
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/EventDroplist.java
  42. 24 22
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/ExtractableItemsData.java
  43. 6 2
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/FishTable.java
  44. 9 10
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/HelperBuffTable.java
  45. 6 8
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/HennaTable.java
  46. 7 3
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/HennaTreeTable.java
  47. 8 8
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/HeroSkillTable.java
  48. 78 76
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/ItemTable.java
  49. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/LevelUpData.java
  50. 17 21
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/MapRegionTable.java
  51. 49 25
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/MerchantPriceConfigTable.java
  52. 7 4
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/NobleSkillTable.java
  53. 8 9
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/NpcBufferTable.java
  54. 75 76
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/NpcTable.java
  55. 8 9
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/NpcWalkerRoutesTable.java
  56. 10 6
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/PetNameTable.java
  57. 25 20
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/PetSkillsTable.java
  58. 18 16
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/SkillSpellbookTable.java
  59. 12 29
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/SkillTable.java
  60. 13 10
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/SkillTreeTable.java
  61. 13 6
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/SpawnTable.java
  62. 9 5
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/StaticObjects.java
  63. 8 7
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/SummonItemsData.java
  64. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/datatables/TeleportLocationTable.java
  65. 15 10
      L2_GameServer/java/net/sf/l2j/gameserver/geoeditorcon/GeoEditorListener.java
  66. 8 8
      L2_GameServer/java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java
  67. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/handler/ChatHandler.java
  68. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/handler/ItemHandler.java
  69. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/handler/SkillHandler.java
  70. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/handler/UserCommandHandler.java
  71. 7 7
      L2_GameServer/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java
  72. 244 239
      L2_GameServer/java/net/sf/l2j/gameserver/idfactory/IdFactory.java
  73. 50 32
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/AuctionManager.java
  74. 10 11
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/BoatManager.java
  75. 205 185
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CastleManager.java
  76. 335 221
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CastleManorManager.java
  77. 155 152
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/ClanHallManager.java
  78. 147 132
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CoupleManager.java
  79. 274 238
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CursedWeaponsManager.java
  80. 249 219
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/DayNightSpawnManager.java
  81. 443 437
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/DimensionalRiftManager.java
  82. 62 44
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/DuelManager.java
  83. 183 172
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortManager.java
  84. 416 388
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortSiegeManager.java
  85. 200 233
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FourSepulchersManager.java
  86. 60 58
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/GrandBossManager.java
  87. 25 20
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/InstanceManager.java
  88. 14 19
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/ItemsOnGroundManager.java
  89. 379 371
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/MercTicketManager.java
  90. 213 244
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/PetitionManager.java
  91. 145 147
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/QuestManager.java
  92. 499 456
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/RaidBossSpawnManager.java
  93. 351 316
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/SiegeManager.java
  94. 70 66
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/TransformationManager.java
  95. 70 80
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/ZoneManager.java
  96. 8 9
      L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/games/Lottery.java
  97. 12 14
      L2_GameServer/java/net/sf/l2j/gameserver/lib/SqlUtils.java
  98. 8 4
      L2_GameServer/java/net/sf/l2j/gameserver/lib/memcache.java
  99. 779 756
      L2_GameServer/java/net/sf/l2j/gameserver/model/AutoChatHandler.java
  100. 191 219
      L2_GameServer/java/net/sf/l2j/gameserver/model/AutoSpawnHandler.java

+ 147 - 121
L2_GameServer/java/net/sf/l2j/L2DatabaseFactory.java

@@ -23,65 +23,64 @@ import com.mchange.v2.c3p0.ComboPooledDataSource;
 
 public class L2DatabaseFactory
 {
-    static Logger _log = Logger.getLogger(L2DatabaseFactory.class.getName());
-
-    public static enum ProviderType
-    {
-        MySql,
-        MsSql
-    }
-
-    // =========================================================
-    // Data Field
-    private static L2DatabaseFactory _instance;
-    private ProviderType _providerType;
+	static Logger _log = Logger.getLogger(L2DatabaseFactory.class.getName());
+	
+	public static enum ProviderType
+	{
+		MySql,
+		MsSql
+	}
+	
+	// =========================================================
+	// Data Field
+	private static L2DatabaseFactory _instance;
+	private ProviderType _providerType;
 	private ComboPooledDataSource _source;
-
-    // =========================================================
-    // Constructor
+	
+	// =========================================================
+	// Constructor
 	public L2DatabaseFactory() throws SQLException
 	{
 		try
 		{
 			if (Config.DATABASE_MAX_CONNECTIONS < 2)
-            {
-                Config.DATABASE_MAX_CONNECTIONS = 2;
-                _log.warning("A minimum of " + Config.DATABASE_MAX_CONNECTIONS + " db connections are required.");
-            }
-
+			{
+				Config.DATABASE_MAX_CONNECTIONS = 2;
+				_log.warning("A minimum of " + Config.DATABASE_MAX_CONNECTIONS + " db connections are required.");
+			}
+			
 			_source = new ComboPooledDataSource();
 			_source.setAutoCommitOnClose(true);
-
+			
 			_source.setInitialPoolSize(10);
 			_source.setMinPoolSize(10);
 			_source.setMaxPoolSize(Math.max(10, Config.DATABASE_MAX_CONNECTIONS));
-
-
+			
 			_source.setAcquireRetryAttempts(0); // try to obtain connections indefinitely (0 = never quit)
-			_source.setAcquireRetryDelay(500);  // 500 milliseconds wait before try to acquire connection again
-			_source.setCheckoutTimeout(0);      // 0 = wait indefinitely for new connection
+			_source.setAcquireRetryDelay(500); // 500 milliseconds wait before try to acquire connection again
+			_source.setCheckoutTimeout(0); // 0 = wait indefinitely for new connection
 			// if pool is exhausted
-			_source.setAcquireIncrement(5);     // if pool is exhausted, get 5 more connections at a time
+			_source.setAcquireIncrement(5); // if pool is exhausted, get 5 more connections at a time
 			// cause there is a "long" delay on acquire connection
 			// so taking more than one connection at once will make connection pooling
 			// more effective.
-
+			
 			// this "connection_test_table" is automatically created if not already there
 			_source.setAutomaticTestTable("connection_test_table");
 			_source.setTestConnectionOnCheckin(false);
-
+			
 			// testing OnCheckin used with IdleConnectionTestPeriod is faster than  testing on checkout
-
+			
 			_source.setIdleConnectionTestPeriod(3600); // test idle connection every 60 sec
 			_source.setMaxIdleTime(Config.DATABASE_MAX_IDLE_TIME); // 0 = idle connections never expire
 			// *THANKS* to connection testing configured above
 			// but I prefer to disconnect all connections not used
 			// for more than 1 hour
-
+			
 			// enables statement caching,  there is a "semi-bug" in c3p0 0.9.0 but in 0.9.0.2 and later it's fixed
 			_source.setMaxStatementsPerConnection(100);
-
-			_source.setBreakAfterAcquireFailure(false);  // never fail if any way possible
+			
+			_source.setBreakAfterAcquireFailure(false); // never fail if any way possible
 			// setting this to true will make
 			// c3p0 "crash" and refuse to work
 			// till restart thus making acquire
@@ -91,128 +90,155 @@ public class L2DatabaseFactory
 			_source.setJdbcUrl(Config.DATABASE_URL);
 			_source.setUser(Config.DATABASE_LOGIN);
 			_source.setPassword(Config.DATABASE_PASSWORD);
-
+			
 			/* Test the connection */
 			_source.getConnection().close();
-
-			if (Config.DEBUG) _log.fine("Database Connection Working");
-
+			
+			if (Config.DEBUG)
+				_log.fine("Database Connection Working");
+			
 			if (Config.DATABASE_DRIVER.toLowerCase().contains("microsoft"))
-                _providerType = ProviderType.MsSql;
-            else
-                _providerType = ProviderType.MySql;
+				_providerType = ProviderType.MsSql;
+			else
+				_providerType = ProviderType.MySql;
 		}
 		catch (SQLException x)
 		{
-			if (Config.DEBUG) _log.fine("Database Connection FAILED");
+			if (Config.DEBUG)
+				_log.fine("Database Connection FAILED");
 			// re-throw the exception
 			throw x;
 		}
 		catch (Exception e)
 		{
-			if (Config.DEBUG) _log.fine("Database Connection FAILED");
-			throw new SQLException("could not init DB connection:"+e);
+			if (Config.DEBUG)
+				_log.fine("Database Connection FAILED");
+			throw new SQLException("could not init DB connection:" + e);
 		}
 	}
-
-    // =========================================================
-    // Method - Public
-    public final String prepQuerySelect(String[] fields, String tableName, String whereClause, boolean returnOnlyTopRecord)
-    {
-        String msSqlTop1 = "";
-        String mySqlTop1 = "";
-        if (returnOnlyTopRecord)
-        {
-            if (getProviderType() == ProviderType.MsSql) msSqlTop1 = " Top 1 ";
-            if (getProviderType() == ProviderType.MySql) mySqlTop1 = " Limit 1 ";
-        }
-        String query = "SELECT " + msSqlTop1 + safetyString(fields) + " FROM " + tableName + " WHERE " + whereClause + mySqlTop1;
-        return query;
-    }
-
-    public void shutdown()
-    {
-        try {
-            _source.close();
-        } catch (Exception e) {_log.log(Level.INFO, "", e);}
-        try {
-            _source = null;
-        } catch (Exception e) {_log.log(Level.INFO, "", e);}
-    }
-
-    public final String safetyString(String... whatToCheck)
-    {
-        // NOTE: Use brace as a safty precaution just incase name is a reserved word
-        final char braceLeft;
-        final char braceRight;
-        
-        if (getProviderType() == ProviderType.MsSql) {
-            braceLeft = '[';
-            braceRight = ']';
-        } else {
-            braceLeft = '`';
-            braceRight = '`';
-        }
-
-        int length = 0;
-        
-        for (String word : whatToCheck) {
-            length += word.length() + 4;
-        }
-
-        final StringBuilder sbResult = new StringBuilder(length);
-        
-        for(String word : whatToCheck)
-        {
-            if (sbResult.length() > 0) {
-                sbResult.append(", ");
-            }
-
-            sbResult.append(braceLeft);
-            sbResult.append(word);
-            sbResult.append(braceRight);
-        }
-        
-        return sbResult.toString();
-    }
-
-    // =========================================================
-    // Property - Public
+	
+	// =========================================================
+	// Method - Public
+	public final String prepQuerySelect(String[] fields, String tableName, String whereClause, boolean returnOnlyTopRecord)
+	{
+		String msSqlTop1 = "";
+		String mySqlTop1 = "";
+		if (returnOnlyTopRecord)
+		{
+			if (getProviderType() == ProviderType.MsSql)
+				msSqlTop1 = " Top 1 ";
+			if (getProviderType() == ProviderType.MySql)
+				mySqlTop1 = " Limit 1 ";
+		}
+		String query = "SELECT " + msSqlTop1 + safetyString(fields) + " FROM " + tableName + " WHERE " + whereClause + mySqlTop1;
+		return query;
+	}
+	
+	public void shutdown()
+	{
+		try
+		{
+			_source.close();
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.INFO, "", e);
+		}
+		try
+		{
+			_source = null;
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.INFO, "", e);
+		}
+	}
+	
+	public final String safetyString(String... whatToCheck)
+	{
+		// NOTE: Use brace as a safty precaution just incase name is a reserved word
+		final char braceLeft;
+		final char braceRight;
+		
+		if (getProviderType() == ProviderType.MsSql)
+		{
+			braceLeft = '[';
+			braceRight = ']';
+		}
+		else
+		{
+			braceLeft = '`';
+			braceRight = '`';
+		}
+		
+		int length = 0;
+		
+		for (String word : whatToCheck)
+		{
+			length += word.length() + 4;
+		}
+		
+		final StringBuilder sbResult = new StringBuilder(length);
+		
+		for (String word : whatToCheck)
+		{
+			if (sbResult.length() > 0)
+			{
+				sbResult.append(", ");
+			}
+			
+			sbResult.append(braceLeft);
+			sbResult.append(word);
+			sbResult.append(braceRight);
+		}
+		
+		return sbResult.toString();
+	}
+	
+	// =========================================================
+	// Property - Public
 	public static L2DatabaseFactory getInstance() throws SQLException
 	{
-		if (_instance == null)
+		synchronized (L2DatabaseFactory.class)
 		{
-			_instance = new L2DatabaseFactory();
+			if (_instance == null)
+			{
+				_instance = new L2DatabaseFactory();
+			}
 		}
 		return _instance;
 	}
-
+	
 	public Connection getConnection() //throws SQLException
 	{
-		Connection con=null;
-
-		while(con==null)
+		Connection con = null;
+		
+		while (con == null)
 		{
 			try
 			{
-				con=_source.getConnection();
-			} catch (SQLException e)
+				con = _source.getConnection();
+			}
+			catch (SQLException e)
 			{
-				_log.warning("L2DatabaseFactory: getConnection() failed, trying again "+e);
+				_log.warning("L2DatabaseFactory: getConnection() failed, trying again " + e);
 			}
 		}
 		return con;
 	}
-
+	
 	public int getBusyConnectionCount() throws SQLException
 	{
-	    return _source.getNumBusyConnectionsDefaultUser();
+		return _source.getNumBusyConnectionsDefaultUser();
 	}
-
+	
 	public int getIdleConnectionCount() throws SQLException
 	{
-	    return _source.getNumIdleConnectionsDefaultUser();
+		return _source.getNumIdleConnectionsDefaultUser();
+	}
+	
+	public final ProviderType getProviderType()
+	{
+		return _providerType;
 	}
-
-    public final ProviderType getProviderType() { return _providerType; }
 }

+ 10 - 11
L2_GameServer/java/net/sf/l2j/gameserver/Announcements.java

@@ -47,23 +47,17 @@ public class Announcements
 {
 	private static Logger _log = Logger.getLogger(Announcements.class.getName());
 	
-	private static Announcements _instance;
 	private List<String> _announcements = new FastList<String>();
 	private List<List<Object>> _eventAnnouncements = new FastList<List<Object>>();
 	
-	public Announcements()
+	private Announcements()
 	{
 		loadAnnouncements();
 	}
 	
 	public static Announcements getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new Announcements();
-		}
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public void loadAnnouncements()
@@ -126,8 +120,7 @@ public class Announcements
 		for (int i = 0; i < _announcements.size(); i++)
 		{
 			StringUtil.append(replyMSG, "<table width=260><tr><td width=220>", _announcements.get(i), "</td><td width=40>"
-			        + "<button value=\"Delete\" action=\"bypass -h admin_del_announcement ", String.valueOf(i),
-			        "\" width=60 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>");
+					+ "<button value=\"Delete\" action=\"bypass -h admin_del_announcement ", String.valueOf(i), "\" width=60 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>");
 		}
 		adminReply.replace("%announces%", replyMSG.toString());
 		activeChar.sendPacket(adminReply);
@@ -237,7 +230,7 @@ public class Announcements
 		{
 			// Announce string to everyone on server
 			String text = command.substring(lengthToTrim);
-			Announcements.getInstance().announceToAll(text);
+			SingletonHolder._instance.announceToAll(text);
 		}
 		
 		// No body cares!
@@ -246,4 +239,10 @@ public class Announcements
 			// empty message.. ignore
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final Announcements _instance = new Announcements();
+	}
 }

+ 10 - 8
L2_GameServer/java/net/sf/l2j/gameserver/GameServer.java

@@ -152,7 +152,7 @@ public class GameServer
 	
 	public long getUsedMemoryMB()
 	{
-		return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576;																				   // ;
+		return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576; // ;
 	}
 	
 	public SelectorThread<L2GameClient> getSelectorThread()
@@ -226,7 +226,7 @@ public class GameServer
 		ExtractableItemsData.getInstance();
 		SummonItemsData.getInstance();
 		ZoneManager.getInstance();
-		MerchantPriceConfigTable.getInstance();
+		MerchantPriceConfigTable.getInstance().loadInstances();
 		TradeController.getInstance();
 		InstanceManager.getInstance();
 		
@@ -286,9 +286,9 @@ public class GameServer
 		if (Config.GEODATA == 2)
 			PathFinding.getInstance();
 		
-		CastleManager.getInstance();
+		CastleManager.getInstance().loadInstances();
 		SiegeManager.getInstance();
-		FortManager.getInstance();
+		FortManager.getInstance().loadInstances();
 		FortSiegeManager.getInstance();
 		
 		TeleportLocationTable.getInstance();
@@ -367,8 +367,7 @@ public class GameServer
 		if (Config.SAVE_DROPPED_ITEM)
 			ItemsOnGroundManager.getInstance();
 		
-		if (Config.AUTODESTROY_ITEM_AFTER > 0
-		        || Config.HERB_AUTO_DESTROY_TIME > 0)
+		if (Config.AUTODESTROY_ITEM_AFTER > 0 || Config.HERB_AUTO_DESTROY_TIME > 0)
 			ItemsAutoDestroy.getInstance();
 		
 		MonsterRace.getInstance();
@@ -410,6 +409,10 @@ public class GameServer
 		// read pet stats from db
 		L2PetDataTable.getInstance().loadPetsData();
 		
+		MerchantPriceConfigTable.getInstance().updateReferences();
+		CastleManager.getInstance().activateInstances();
+		FortManager.getInstance().activateInstances();
+		
 		Universe.getInstance();
 		
 		if (Config.ACCEPT_GEOEDITOR_CONN)
@@ -442,8 +445,7 @@ public class GameServer
 		
 		ForumsBBSManager.getInstance();
 		
-		_log.config("IdFactory: Free ObjectID's remaining: "
-		        + IdFactory.getInstance().size());
+		_log.config("IdFactory: Free ObjectID's remaining: " + IdFactory.getInstance().size());
 		
 		// initialize the dynamic extension loader
 		try

+ 77 - 68
L2_GameServer/java/net/sf/l2j/gameserver/GameTimeController.java

@@ -37,57 +37,55 @@ import net.sf.l2j.gameserver.model.actor.L2Character;
 public class GameTimeController
 {
 	static final Logger _log = Logger.getLogger(GameTimeController.class.getName());
-
+	
 	public static final int TICKS_PER_SECOND = 10; // not able to change this without checking through code
 	public static final int MILLIS_IN_TICK = 1000 / TICKS_PER_SECOND;
-
-	private static GameTimeController _instance = new GameTimeController();
-
+	
 	protected static int _gameTicks;
 	protected static long _gameStartTime;
 	protected static boolean _isNight = false;
-
-	private static Map<Integer,L2Character> _movingObjects = new FastMap<Integer,L2Character>().setShared(true);
-
+	
+	private static Map<Integer, L2Character> _movingObjects = new FastMap<Integer, L2Character>().setShared(true);
+	
 	protected static TimerThread _timer;
 	private ScheduledFuture<?> _timerWatcher;
-
+	
 	/**
 	 * one ingame day is 240 real minutes
 	 */
 	public static GameTimeController getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private GameTimeController()
 	{
 		_gameStartTime = System.currentTimeMillis() - 3600000; // offset so that the server starts a day begin
 		_gameTicks = 3600000 / MILLIS_IN_TICK; // offset so that the server starts a day begin
-
+		
 		_timer = new TimerThread();
 		_timer.start();
-
+		
 		_timerWatcher = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new TimerWatcher(), 0, 1000);
-        ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new BroadcastSunState(), 0, 600000);
-
+		ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new BroadcastSunState(), 0, 600000);
+		
 	}
-
+	
 	public boolean isNowNight()
 	{
 		return _isNight;
 	}
-
+	
 	public int getGameTime()
 	{
 		return (_gameTicks / (TICKS_PER_SECOND * 10));
 	}
-
+	
 	public static int getGameTicks()
 	{
 		return _gameTicks;
 	}
-
+	
 	/**
 	 * Add a L2Character to movingObjects of GameTimeController.<BR><BR>
 	 *
@@ -99,10 +97,12 @@ public class GameTimeController
 	 */
 	public void registerMovingObject(L2Character cha)
 	{
-		if(cha == null) return;
-		if (!_movingObjects.containsKey(cha.getObjectId())) _movingObjects.put(cha.getObjectId(),cha);   
+		if (cha == null)
+			return;
+		if (!_movingObjects.containsKey(cha.getObjectId()))
+			_movingObjects.put(cha.getObjectId(), cha);
 	}
-
+	
 	/**
 	 * Move all L2Characters contained in movingObjects of GameTimeController.<BR><BR>
 	 *
@@ -145,17 +145,17 @@ public class GameTimeController
 			}
 		}
 	}
-
+	
 	public void stopTimer()
 	{
 		_timerWatcher.cancel(true);
 		_timer.interrupt();
 	}
-
+	
 	class TimerThread extends Thread
 	{
 		protected Exception _error;
-
+		
 		public TimerThread()
 		{
 			super("GameTimeController");
@@ -163,7 +163,7 @@ public class GameTimeController
 			setPriority(MAX_PRIORITY);
 			_error = null;
 		}
-
+		
 		@Override
 		public void run()
 		{
@@ -171,20 +171,21 @@ public class GameTimeController
 			{
 				for (;;)
 				{
-					int _oldTicks=_gameTicks; // save old ticks value to avoid moving objects 2x in same tick
+					int _oldTicks = _gameTicks; // save old ticks value to avoid moving objects 2x in same tick
 					long runtime = System.currentTimeMillis() - _gameStartTime; // from server boot to now
-
+					
 					_gameTicks = (int) (runtime / MILLIS_IN_TICK); // new ticks value (ticks now)
-
-					if (_oldTicks != _gameTicks) moveObjects(); // Runs possibly too often
-
+					
+					if (_oldTicks != _gameTicks)
+						moveObjects(); // Runs possibly too often
+						
 					runtime = (System.currentTimeMillis() - _gameStartTime) - runtime;
-
+					
 					// calculate sleep time... time needed to next tick minus time it takes to call moveObjects()
 					int sleepTime = 1 + MILLIS_IN_TICK - ((int) runtime) % MILLIS_IN_TICK;
-
+					
 					//_log.finest("TICK: "+_gameTicks);
-
+					
 					sleep(sleepTime);
 				}
 			}
@@ -194,7 +195,7 @@ public class GameTimeController
 			}
 		}
 	}
-
+	
 	class TimerWatcher implements Runnable
 	{
 		public void run()
@@ -203,43 +204,45 @@ public class GameTimeController
 			{
 				String time = (new SimpleDateFormat("HH:mm:ss")).format(new Date());
 				_log.warning(time + " TimerThread stop with following error. restart it.");
-				if (_timer._error != null) _timer._error.printStackTrace();
-
+				if (_timer._error != null)
+					_timer._error.printStackTrace();
+				
 				_timer = new TimerThread();
 				_timer.start();
 			}
 		}
 	}
-
+	
 	/**
 	 * Update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object then notify AI with EVT_ARRIVED.<BR><BR>
 	 */
 	class MovingObjectArrived implements Runnable
-    {
-        private final L2Character _ended;
-        
-        MovingObjectArrived(L2Character ended)
-        {
-            _ended = ended;
-        }
-        
-        public void run()
-        {
-            try
-            {
-            	if (_ended.hasAI()) // AI could be just disabled due to region turn off
-            	{
-            		if (Config.MOVE_BASED_KNOWNLIST) _ended.getKnownList().findObjects();
-            		_ended.getAI().notifyEvent(CtrlEvent.EVT_ARRIVED);
-            	}
-            }
-            catch (NullPointerException e)
-            {
-            	e.printStackTrace();
-            }
-        }
-    }
-
+	{
+		private final L2Character _ended;
+		
+		MovingObjectArrived(L2Character ended)
+		{
+			_ended = ended;
+		}
+		
+		public void run()
+		{
+			try
+			{
+				if (_ended.hasAI()) // AI could be just disabled due to region turn off
+				{
+					if (Config.MOVE_BASED_KNOWNLIST)
+						_ended.getKnownList().findObjects();
+					_ended.getAI().notifyEvent(CtrlEvent.EVT_ARRIVED);
+				}
+			}
+			catch (NullPointerException e)
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+	
 	/**
 	 * @param rise
 	 */
@@ -249,12 +252,18 @@ public class GameTimeController
 		{
 			int h = (getGameTime() / 60) % 24; // Time in hour
 			boolean tempIsNight = (h < 6);
-
-			if (tempIsNight != _isNight) { // If diff day/night state
-                _isNight = tempIsNight; // Set current day/night varible to value of temp varible
-
-                DayNightSpawnManager.getInstance().notifyChangeMode();
-            }
+			
+			if (tempIsNight != _isNight)
+			{ // If diff day/night state
+				_isNight = tempIsNight; // Set current day/night varible to value of temp varible
+				DayNightSpawnManager.getInstance().notifyChangeMode();
+			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final GameTimeController _instance = new GameTimeController();
+	}
 }

+ 155 - 140
L2_GameServer/java/net/sf/l2j/gameserver/GeoData.java

@@ -30,153 +30,168 @@ import net.sf.l2j.util.Point3D;
 public class GeoData
 {
 	private static Logger _log = Logger.getLogger(GeoData.class.getName());
-	private static GeoData _instance;
-
+	
+	protected GeoData()
+	{
+	}
+	
+	private GeoData(final boolean disabled)
+	{
+		if (disabled)
+		{
+			_log.info("Geodata Engine: Disabled.");
+		}
+	}
+	
 	public static GeoData getInstance()
-    {
-        if(_instance == null)
-        {
-        	if (Config.GEODATA > 0)
-        		_instance = GeoEngine.getInstance();
-        	else
-        	{
-        		_instance = new GeoData();
-        		_log.info("Geodata Engine: Disabled.");
-        	}
-        }
-        return _instance;
-    }
-
-    // Public Methods
-    /**
-     * @param x
-     * @param y
-     * @return Geo Block Type
-     */
-    public short getType  (int x, int y)
-    {
-        return 0;
-    }
-    /**
-     * @param x
-     * @param y
-     * @param z
-     * @return Nearles Z
-     */
-    public short getHeight(int x, int y, int z)
-    {
-        return (short)z;
-    }
-    /**
-     * @param x
-     * @param y
-     * @param zmin
-     * @param zmax
-     * @param spawnid
-     * @return
-     */
-    public short getSpawnHeight(int x, int y, int zmin, int zmax, int spawnid)
-    {
-        return (short)zmin;
-    }
-    /**
-     * @param x
-     * @param y
-     * @return
-     */
-    public String geoPosition(int x, int y)
-    {
-    	return "";
-    }
-
-    /**
-     * @param cha
-     * @param target
-     * @return True if cha can see target (LOS)
-     */
-    public boolean canSeeTarget(L2Object cha, L2Object target)
-    {
-    	//If geo is off do simple check :]
-    	//Don't allow casting on players on different dungeon lvls etc
-        return (Math.abs(target.getZ() - cha.getZ()) < 1000);
-    }
-    
-    public boolean canSeeTarget(L2Object cha, Point3D worldPosition)
-    {
-        //If geo is off do simple check :]
-        //Don't allow casting on players on different dungeon lvls etc
-        return Math.abs(worldPosition.getZ() - cha.getZ()) < 1000;
-    }
-
+	{
+		return SingletonHolder._instance;
+	}
+	
+	// Public Methods
+	/**
+	 * @param x
+	 * @param y
+	 * @return Geo Block Type
+	 */
+	public short getType(int x, int y)
+	{
+		return 0;
+	}
+	
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @return Nearles Z
+	 */
+	public short getHeight(int x, int y, int z)
+	{
+		return (short) z;
+	}
+	
+	/**
+	 * @param x
+	 * @param y
+	 * @param zmin
+	 * @param zmax
+	 * @param spawnid
+	 * @return
+	 */
+	public short getSpawnHeight(int x, int y, int zmin, int zmax, int spawnid)
+	{
+		return (short) zmin;
+	}
+	
+	/**
+	 * @param x
+	 * @param y
+	 * @return
+	 */
+	public String geoPosition(int x, int y)
+	{
+		return "";
+	}
+	
+	/**
+	 * @param cha
+	 * @param target
+	 * @return True if cha can see target (LOS)
+	 */
+	public boolean canSeeTarget(L2Object cha, L2Object target)
+	{
+		//If geo is off do simple check :]
+		//Don't allow casting on players on different dungeon lvls etc
+		return (Math.abs(target.getZ() - cha.getZ()) < 1000);
+	}
+	
+	public boolean canSeeTarget(L2Object cha, Point3D worldPosition)
+	{
+		//If geo is off do simple check :]
+		//Don't allow casting on players on different dungeon lvls etc
+		return Math.abs(worldPosition.getZ() - cha.getZ()) < 1000;
+	}
+	
 	public boolean canSeeTarget(int x, int y, int z, int tx, int ty, int tz)
 	{
 		// If geo is off do simple check :]
 		// Don't allow casting on players on different dungeon lvls etc
 		return (Math.abs(z - tz) < 1000);
 	}
-    /**
-     * @param cha
-     * @param target
-     * @return True if cha can see target (LOS) and send usful info to PC
-     */
-    public boolean canSeeTargetDebug(L2PcInstance gm, L2Object target)
-    {
-        return true;
-    }
-    /**
-     * @param x
-     * @param y
-     * @param z
-     * @return Geo NSWE (0-15)
-     */
-    public short getNSWE(int x, int y, int z)
-    {
-        return 15;
-    }
-    /**
-     * @param x
-     * @param y
-     * @param z
-     * @param tx
-     * @param ty
-     * @param tz
-     * @param instanceId
-     * @return Last Location (x,y,z) where player can walk - just before wall
-     */
-    public Location moveCheck(int x, int y, int z, int tx, int ty, int tz, int instanceId)
-    {
-        return new Location(tx,ty,tz);
-    }
-    public boolean canMoveFromToTarget(int x, int y, int z, int tx, int ty, int tz, int instanceId)
-    {
-    	return true;
-    }
-    /**
-     * @param gm
-     * @param comment
-     */
-    public void addGeoDataBug(L2PcInstance gm, String comment)
-    {
-    	//Do Nothing
-    }
-    public static void unloadGeodata(byte rx, byte ry)
+	
+	/**
+	 * @param cha
+	 * @param target
+	 * @return True if cha can see target (LOS) and send usful info to PC
+	 */
+	public boolean canSeeTargetDebug(L2PcInstance gm, L2Object target)
 	{
-
+		return true;
+	}
+	
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @return Geo NSWE (0-15)
+	 */
+	public short getNSWE(int x, int y, int z)
+	{
+		return 15;
+	}
+	
+	/**
+	 * @param x
+	 * @param y
+	 * @param z
+	 * @param tx
+	 * @param ty
+	 * @param tz
+	 * @param instanceId
+	 * @return Last Location (x,y,z) where player can walk - just before wall
+	 */
+	public Location moveCheck(int x, int y, int z, int tx, int ty, int tz, int instanceId)
+	{
+		return new Location(tx, ty, tz);
+	}
+	
+	public boolean canMoveFromToTarget(int x, int y, int z, int tx, int ty, int tz, int instanceId)
+	{
+		return true;
+	}
+	
+	/**
+	 * @param gm
+	 * @param comment
+	 */
+	public void addGeoDataBug(L2PcInstance gm, String comment)
+	{
+		//Do Nothing
+	}
+	
+	public static void unloadGeodata(byte rx, byte ry)
+	{
+		
+	}
+	
+	public static boolean loadGeodataFile(byte rx, byte ry)
+	{
+		return false;
+	}
+	
+	public boolean hasGeo(int x, int y)
+	{
+		return false;
+	}
+	
+	public Node[] getNeighbors(Node n)
+	{
+		return null;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final GeoData _instance = Config.GEODATA > 0 ? GeoEngine.getInstance() : new GeoData(true);
 	}
-
-    public static boolean loadGeodataFile(byte rx, byte ry)
-    {
-    	return false;
-    }
-    
-    public boolean hasGeo(int x, int y)
-    {
-    	return false;
-    }
-    
-    public Node[] getNeighbors(Node n)
-    {
-    	return null;
-    }
-    
 }

File diff suppressed because it is too large
+ 569 - 547
L2_GameServer/java/net/sf/l2j/gameserver/GeoEngine.java


+ 26 - 21
L2_GameServer/java/net/sf/l2j/gameserver/GmListTable.java

@@ -32,26 +32,20 @@ import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 public class GmListTable
 {
 	private static Logger _log = Logger.getLogger(GmListTable.class.getName());
-	private static GmListTable _instance;
-	
 	
 	/** Set(L2PcInstance>) containing all the GM in game */
 	private FastMap<L2PcInstance, Boolean> _gmList;
 	
 	public static GmListTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new GmListTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public FastList<L2PcInstance> getAllGms(boolean includeHidden)
 	{
 		FastList<L2PcInstance> tmpGmList = new FastList<L2PcInstance>();
 		
-		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext())!=end;)
+		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext()) != end;)
 			if (includeHidden || !n.getValue())
 				tmpGmList.add(n.getKey());
 		
@@ -62,18 +56,18 @@ public class GmListTable
 	{
 		FastList<String> tmpGmList = new FastList<String>();
 		
-		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext())!=end;)
+		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext()) != end;)
 			if (!n.getValue())
 				tmpGmList.add(n.getKey().getName());
 			else if (includeHidden)
-				tmpGmList.add(n.getKey().getName()+" (invis)");
+				tmpGmList.add(n.getKey().getName() + " (invis)");
 		
 		return tmpGmList;
 	}
 	
 	private GmListTable()
 	{
-		_gmList = new FastMap<L2PcInstance,Boolean>().setShared(true);
+		_gmList = new FastMap<L2PcInstance, Boolean>().setShared(true);
 	}
 	
 	/**
@@ -81,13 +75,15 @@ public class GmListTable
 	 */
 	public void addGm(L2PcInstance player, boolean hidden)
 	{
-		if (Config.DEBUG) _log.fine("added gm: "+player.getName());
-		_gmList.put(player,hidden);
+		if (Config.DEBUG)
+			_log.fine("added gm: " + player.getName());
+		_gmList.put(player, hidden);
 	}
 	
 	public void deleteGm(L2PcInstance player)
 	{
-		if (Config.DEBUG) _log.fine("deleted gm: "+player.getName());
+		if (Config.DEBUG)
+			_log.fine("deleted gm: " + player.getName());
 		
 		_gmList.remove(player);
 	}
@@ -99,7 +95,8 @@ public class GmListTable
 	public void showGm(L2PcInstance player)
 	{
 		FastMap.Entry<L2PcInstance, Boolean> gm = _gmList.getEntry(player);
-		if (gm != null) gm.setValue(false);
+		if (gm != null)
+			gm.setValue(false);
 	}
 	
 	/**
@@ -109,12 +106,13 @@ public class GmListTable
 	public void hideGm(L2PcInstance player)
 	{
 		FastMap.Entry<L2PcInstance, Boolean> gm = _gmList.getEntry(player);
-		if (gm != null) gm.setValue(true);
+		if (gm != null)
+			gm.setValue(true);
 	}
 	
 	public boolean isGmOnline(boolean includeHidden)
 	{
-		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext())!=end;)
+		for (FastMap.Entry<L2PcInstance, Boolean> n = _gmList.head(), end = _gmList.tail(); (n = n.getNext()) != end;)
 		{
 			if (includeHidden || !n.getValue())
 				return true;
@@ -123,19 +121,20 @@ public class GmListTable
 		return false;
 	}
 	
-	public void sendListToPlayer (L2PcInstance player)
+	public void sendListToPlayer(L2PcInstance player)
 	{
 		if (!isGmOnline(player.isGM()))
 		{
 			SystemMessage sm = new SystemMessage(SystemMessageId.NO_GM_PROVIDING_SERVICE_NOW); //There are not any GMs that are providing customer service currently.
 			player.sendPacket(sm);
-		} else
+		}
+		else
 		{
 			SystemMessage sm = new SystemMessage(SystemMessageId.GM_LIST);
 			player.sendPacket(sm);
 			
-            for (String name : getAllGmNames(player.isGM()))
-            {
+			for (String name : getAllGmNames(player.isGM()))
+			{
 				sm = new SystemMessage(SystemMessageId.GM_C1);
 				sm.addString(name);
 				player.sendPacket(sm);
@@ -158,4 +157,10 @@ public class GmListTable
 			gm.sendMessage(message);
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final GmListTable _instance = new GmListTable();
+	}
 }

+ 25 - 0
L2_GameServer/java/net/sf/l2j/gameserver/InstanceListManager.java

@@ -0,0 +1,25 @@
+package net.sf.l2j.gameserver;
+
+/**
+ * Interface for managers of list of instances.
+ * 
+ * @author fordfrog
+ */
+public interface InstanceListManager {
+
+	/**
+ 	* Loads instances with their data from persistant format. This method
+ 	* has no side effect as calling methods of another instance manager.
+ 	*/
+	void loadInstances();
+
+	/**
+	 * For each loaded instance, updates references to related instances.
+	 */
+	void updateReferences();
+
+	/**
+	 * Activates instances so their setup is performed.
+	 */
+	void activateInstances();
+}

+ 76 - 74
L2_GameServer/java/net/sf/l2j/gameserver/ItemsAutoDestroy.java

@@ -27,81 +27,83 @@ import net.sf.l2j.gameserver.templates.item.L2EtcItemType;
 public class ItemsAutoDestroy
 {
 	protected static final Logger _log = Logger.getLogger("ItemsAutoDestroy");
-	private static ItemsAutoDestroy _instance;
 	protected List<L2ItemInstance> _items = null;
 	protected static long _sleep;
-
-    private ItemsAutoDestroy()
-    {
-        _items = new FastList<L2ItemInstance>();
-        _sleep	= Config.AUTODESTROY_ITEM_AFTER * 1000;
-        if(_sleep == 0) // it should not happend as it is not called when AUTODESTROY_ITEM_AFTER = 0 but we never know..
-        	_sleep = 3600000;
-        ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckItemsForDestroy(),5000,5000);
-    }
-
-    public static ItemsAutoDestroy getInstance()
-    {
-        if (_instance == null)
-        {
-			_log.info("Initializing ItemsAutoDestroy.");
-            _instance = new ItemsAutoDestroy();
-        }
-        return _instance;
-    }
-
-    public synchronized void addItem (L2ItemInstance item)
-    {
-        item.setDropTime(System.currentTimeMillis());
-        _items.add(item);
-    }
-
-    public synchronized void removeItems()
-    {
-    	if (Config.DEBUG)
-    		_log.info("[ItemsAutoDestroy] : "+_items.size()+" items to check.");
-
-    	if (_items.isEmpty()) return;
-
-        long curtime = System.currentTimeMillis();
-        for (L2ItemInstance item : _items)
-        {
-            if (item == null || item.getDropTime()==0 || item.getLocation() != L2ItemInstance.ItemLocation.VOID)
-                _items.remove(item);
-            else
-            {
-            	if(item.getItemType() == L2EtcItemType.HERB )
-            	{
-            		if((curtime - item.getDropTime()) > Config.HERB_AUTO_DESTROY_TIME)
-            		{
-            			L2World.getInstance().removeVisibleObject(item,item.getWorldRegion());
-            			L2World.getInstance().removeObject(item);
-            			_items.remove(item);
-            			if (Config.SAVE_DROPPED_ITEM)
-                			ItemsOnGroundManager.getInstance().removeObject(item);
-            		}
-            	}
-            	else if ( (curtime - item.getDropTime()) > _sleep)
-                {
-                    L2World.getInstance().removeVisibleObject(item,item.getWorldRegion());
-                    L2World.getInstance().removeObject(item);
-                    _items.remove(item);
-                    if (Config.SAVE_DROPPED_ITEM)
-                    	ItemsOnGroundManager.getInstance().removeObject(item);
-                }
-            }
-        }
-
-    	if (Config.DEBUG)
-    		_log.info("[ItemsAutoDestroy] : "+_items.size()+" items remaining.");
-    }
-
-    protected class CheckItemsForDestroy extends Thread
-    {
-        @Override
+	
+	private ItemsAutoDestroy()
+	{
+		_log.info("Initializing ItemsAutoDestroy.");
+		_items = new FastList<L2ItemInstance>();
+		_sleep = Config.AUTODESTROY_ITEM_AFTER * 1000;
+		if (_sleep == 0) // it should not happend as it is not called when AUTODESTROY_ITEM_AFTER = 0 but we never know..
+			_sleep = 3600000;
+		ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new CheckItemsForDestroy(), 5000, 5000);
+	}
+	
+	public static ItemsAutoDestroy getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	public synchronized void addItem(L2ItemInstance item)
+	{
+		item.setDropTime(System.currentTimeMillis());
+		_items.add(item);
+	}
+	
+	public synchronized void removeItems()
+	{
+		if (Config.DEBUG)
+			_log.info("[ItemsAutoDestroy] : " + _items.size() + " items to check.");
+		
+		if (_items.isEmpty())
+			return;
+		
+		long curtime = System.currentTimeMillis();
+		for (L2ItemInstance item : _items)
+		{
+			if (item == null || item.getDropTime() == 0 || item.getLocation() != L2ItemInstance.ItemLocation.VOID)
+				_items.remove(item);
+			else
+			{
+				if (item.getItemType() == L2EtcItemType.HERB)
+				{
+					if ((curtime - item.getDropTime()) > Config.HERB_AUTO_DESTROY_TIME)
+					{
+						L2World.getInstance().removeVisibleObject(item, item.getWorldRegion());
+						L2World.getInstance().removeObject(item);
+						_items.remove(item);
+						if (Config.SAVE_DROPPED_ITEM)
+							ItemsOnGroundManager.getInstance().removeObject(item);
+					}
+				}
+				else if ((curtime - item.getDropTime()) > _sleep)
+				{
+					L2World.getInstance().removeVisibleObject(item, item.getWorldRegion());
+					L2World.getInstance().removeObject(item);
+					_items.remove(item);
+					if (Config.SAVE_DROPPED_ITEM)
+						ItemsOnGroundManager.getInstance().removeObject(item);
+				}
+			}
+		}
+		
+		if (Config.DEBUG)
+			_log.info("[ItemsAutoDestroy] : " + _items.size() + " items remaining.");
+	}
+	
+	protected class CheckItemsForDestroy extends Thread
+	{
+		@Override
 		public void run()
-        {
-        	removeItems();
-        }
-    }
+		{
+			removeItems();
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ItemsAutoDestroy _instance = new ItemsAutoDestroy();
+	}
 }

+ 269 - 251
L2_GameServer/java/net/sf/l2j/gameserver/LoginServerThread.java

@@ -60,20 +60,17 @@ import net.sf.l2j.util.Util;
 public class LoginServerThread extends Thread
 {
 	protected static final Logger _log = Logger.getLogger(LoginServerThread.class.getName());
-
-	/** The LoginServerThread singleton */
-	private static LoginServerThread	_instance;
-
+	
 	/** {@see net.sf.l2j.loginserver.LoginServer#PROTOCOL_REV } */
-	private static final int			REVISION = 0x0102;
-	private RSAPublicKey				_publicKey;
-	private String						_hostname;
-	private int							_port;
-	private int							_gamePort;
-	private Socket						_loginSocket;
-	private InputStream 				_in;
-	private OutputStream 				_out;
-
+	private static final int REVISION = 0x0102;
+	private RSAPublicKey _publicKey;
+	private String _hostname;
+	private int _port;
+	private int _gamePort;
+	private Socket _loginSocket;
+	private InputStream _in;
+	private OutputStream _out;
+	
 	/**
 	 * The BlowFish engine used to encrypt packets<br>
 	 * It is first initialized with a unified key:<br>
@@ -83,29 +80,29 @@ public class LoginServerThread extends Thread
 	 * loginserver during the handshake. This new key is stored<br>
 	 * in {@link #_blowfishKey}
 	 */
-	private NewCrypt 					_blowfish;
-	private byte[]			 			_blowfishKey;
-	private byte[] 						_hexID;
-	private boolean			 			_acceptAlternate;
-	private int							_requestID;
-	private int							_serverID;
-	private boolean 					_reserveHost;
-	private int							_maxPlayer;
-	private List<WaitingClient>			_waitingClients;
-	private Map<String, L2GameClient>	_accountsInGameServer;
-	private int							_status;
-	private String						_serverName;
-	private String						_gameExternalHost;
-	private String						_gameInternalHost;
-
-	public LoginServerThread()
+	private NewCrypt _blowfish;
+	private byte[] _blowfishKey;
+	private byte[] _hexID;
+	private boolean _acceptAlternate;
+	private int _requestID;
+	private int _serverID;
+	private boolean _reserveHost;
+	private int _maxPlayer;
+	private List<WaitingClient> _waitingClients;
+	private Map<String, L2GameClient> _accountsInGameServer;
+	private int _status;
+	private String _serverName;
+	private String _gameExternalHost;
+	private String _gameInternalHost;
+	
+	private 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)
+		if (_hexID == null)
 		{
 			_requestID = Config.REQUEST_ID;
 			_hexID = generateHex(16);
@@ -122,33 +119,29 @@ public class LoginServerThread extends Thread
 		_accountsInGameServer = new FastMap<String, L2GameClient>().setShared(true);
 		_maxPlayer = Config.MAXIMUM_ONLINE_USERS;
 	}
-
+	
 	public static LoginServerThread getInstance()
 	{
-		if(_instance == null)
-		{
-			_instance = new LoginServerThread();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	@Override
 	public void run()
 	{
-		while(true)
+		while (true)
 		{
-			int lengthHi =0;
-			int lengthLo =0;
+			int lengthHi = 0;
+			int lengthLo = 0;
 			int length = 0;
 			boolean checksumOk = false;
 			try
 			{
 				// Connection
-				_log.info("Connecting to login on "+_hostname+":"+_port);
-				_loginSocket = new Socket(_hostname,_port);
+				_log.info("Connecting to login on " + _hostname + ":" + _port);
+				_loginSocket = new Socket(_hostname, _port);
 				_in = _loginSocket.getInputStream();
 				_out = new BufferedOutputStream(_loginSocket.getOutputStream());
-
+				
 				//init Blowfish
 				_blowfishKey = generateHex(40);
 				_blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
@@ -156,188 +149,196 @@ public class LoginServerThread extends Thread
 				{
 					lengthLo = _in.read();
 					lengthHi = _in.read();
-					length= lengthHi*256 + lengthLo;
-
-					if (lengthHi < 0 )
+					length = lengthHi * 256 + lengthLo;
+					
+					if (lengthHi < 0)
 					{
 						_log.finer("LoginServerThread: Login terminated the connection.");
 						break;
 					}
-
+					
 					byte[] incoming = new byte[length];
 					incoming[0] = (byte) lengthLo;
 					incoming[1] = (byte) lengthHi;
-
+					
 					int receivedBytes = 0;
 					int newBytes = 0;
-					while (newBytes != -1 && receivedBytes<length-2)
+					while (newBytes != -1 && receivedBytes < length - 2)
 					{
-						newBytes =  _in.read(incoming, 2, length-2);
+						newBytes = _in.read(incoming, 2, length - 2);
 						receivedBytes = receivedBytes + newBytes;
 					}
-
-					if (receivedBytes != length-2)
+					
+					if (receivedBytes != length - 2)
 					{
 						_log.warning("Incomplete Packet is sent to the server, closing connection.(LS)");
 						break;
 					}
-
+					
 					byte[] decrypt = new byte[length - 2];
 					System.arraycopy(incoming, 2, decrypt, 0, decrypt.length);
 					// decrypt if we have a key
 					decrypt = _blowfish.decrypt(decrypt);
 					checksumOk = NewCrypt.verifyChecksum(decrypt);
-
+					
 					if (!checksumOk)
 					{
 						_log.warning("Incorrect packet checksum, ignoring packet (LS)");
 						break;
 					}
-
+					
 					if (Config.DEBUG)
-						_log.warning("[C]\n"+Util.printData(decrypt));
-
-					int packetType = decrypt[0]&0xff;
+						_log.warning("[C]\n" + Util.printData(decrypt));
+					
+					int packetType = decrypt[0] & 0xff;
 					switch (packetType)
 					{
-					case 00:
-						InitLS init = new InitLS(decrypt);
-						if (Config.DEBUG) _log.info("Init received");
-						if(init.getRevision() != REVISION)
-						{
-							//TODO: revision mismatch
-							_log.warning("/!\\ Revision mismatch between LS and GS /!\\");
+						case 00:
+							InitLS init = new InitLS(decrypt);
+							if (Config.DEBUG)
+								_log.info("Init received");
+							if (init.getRevision() != REVISION)
+							{
+								//TODO: revision mismatch
+								_log.warning("/!\\ Revision mismatch between LS and GS /!\\");
+								break;
+							}
+							try
+							{
+								KeyFactory kfac = KeyFactory.getInstance("RSA");
+								BigInteger modulus = new BigInteger(init.getRSAKey());
+								RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
+								_publicKey = (RSAPublicKey) kfac.generatePublic(kspec1);
+								if (Config.DEBUG)
+									_log.info("RSA key set up");
+							}
+							
+							catch (GeneralSecurityException e)
+							{
+								_log.warning("Troubles while init the public key send by login");
+								break;
+							}
+							//send the blowfish key through the rsa encryption
+							BlowFishKey bfk = new BlowFishKey(_blowfishKey, _publicKey);
+							sendPacket(bfk);
+							if (Config.DEBUG)
+								_log.info("Sent new blowfish key");
+							//now, only accept paket with the new encryption
+							_blowfish = new NewCrypt(_blowfishKey);
+							if (Config.DEBUG)
+								_log.info("Changed blowfish key");
+							AuthRequest ar = new AuthRequest(_requestID, _acceptAlternate, _hexID, _gameExternalHost, _gameInternalHost, _gamePort, _reserveHost, _maxPlayer);
+							sendPacket(ar);
+							if (Config.DEBUG)
+								_log.info("Sent AuthRequest to login");
 							break;
-						}
-						try
-						{
-							KeyFactory kfac = KeyFactory.getInstance("RSA");
-							BigInteger modulus = new BigInteger(init.getRSAKey());
-							RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
-							_publicKey = (RSAPublicKey)kfac.generatePublic(kspec1);
-							if (Config.DEBUG) _log.info("RSA key set up");
-						}
-
-						catch (GeneralSecurityException e)
-						{
-							_log.warning("Troubles while init the public key send by login");
+						case 01:
+							LoginServerFail lsf = new LoginServerFail(decrypt);
+							_log.info("Damn! Registeration Failed: " + lsf.getReasonString());
+							// login will close the connection here
 							break;
-						}
-						//send the blowfish key through the rsa encryption
-						BlowFishKey bfk = new BlowFishKey(_blowfishKey,_publicKey);
-						sendPacket(bfk);
-						if (Config.DEBUG)_log.info("Sent new blowfish key");
-						//now, only accept paket with the new encryption
-						_blowfish = new NewCrypt(_blowfishKey);
-						if (Config.DEBUG)_log.info("Changed blowfish key");
-						AuthRequest ar = new AuthRequest(_requestID, _acceptAlternate, _hexID, _gameExternalHost, _gameInternalHost, _gamePort, _reserveHost, _maxPlayer);
-						sendPacket(ar);
-						if (Config.DEBUG)_log.info("Sent AuthRequest to login");
-						break;
-					case 01:
-						LoginServerFail lsf = new LoginServerFail(decrypt);
-						_log.info("Damn! Registeration Failed: "+lsf.getReasonString());
-						// login will close the connection here
-						break;
-					case 02:
-						AuthResponse aresp = new AuthResponse(decrypt);
-						_serverID = aresp.getServerId();
-						_serverName = aresp.getServerName();
-						Config.saveHexid(_serverID, hexToString(_hexID));
-						_log.info("Registered on login as Server "+_serverID+" : "+_serverName);
-						ServerStatus st = new ServerStatus();
-						if(Config.SERVER_LIST_BRACKET)
-						{
-							st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET,ServerStatus.ON);
-						}
-						else
-						{
-							st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET,ServerStatus.OFF);
-						}
-						if(Config.SERVER_LIST_CLOCK)
-						{
-							st.addAttribute(ServerStatus.SERVER_LIST_CLOCK,ServerStatus.ON);
-						}
-						else
-						{
-							st.addAttribute(ServerStatus.SERVER_LIST_CLOCK,ServerStatus.OFF);
-						}
-						if(Config.SERVER_LIST_TESTSERVER)
-						{
-							st.addAttribute(ServerStatus.TEST_SERVER,ServerStatus.ON);
-						}
-						else
-						{
-							st.addAttribute(ServerStatus.TEST_SERVER,ServerStatus.OFF);
-						}
-						if(Config.SERVER_GMONLY)
-						{
-							st.addAttribute(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_GM_ONLY);
-						}
-						else
-						{
-							st.addAttribute(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_AUTO);
-						}
-						sendPacket(st);
-						if(L2World.getInstance().getAllPlayersCount() > 0)
-						{
-							FastList<String> playerList = new FastList<String>();
-							Collection<L2PcInstance> pls = L2World.getInstance().getAllPlayers().values();
-							//synchronized (L2World.getInstance().getAllPlayers())
+						case 02:
+							AuthResponse aresp = new AuthResponse(decrypt);
+							_serverID = aresp.getServerId();
+							_serverName = aresp.getServerName();
+							Config.saveHexid(_serverID, hexToString(_hexID));
+							_log.info("Registered on login as Server " + _serverID + " : " + _serverName);
+							ServerStatus st = new ServerStatus();
+							if (Config.SERVER_LIST_BRACKET)
 							{
-								for(L2PcInstance player : pls)
-									playerList.add(player.getAccountName());
+								st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.ON);
 							}
-							PlayerInGame pig = new PlayerInGame(playerList);
-							sendPacket(pig);
-						}
-						break;
-					case 03:
-						PlayerAuthResponse par = new PlayerAuthResponse(decrypt);
-						String account = par.getAccount();
-						WaitingClient wcToRemove = null;
-						synchronized(_waitingClients)
-						{
-							for(WaitingClient wc : _waitingClients)
+							else
+							{
+								st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.OFF);
+							}
+							if (Config.SERVER_LIST_CLOCK)
+							{
+								st.addAttribute(ServerStatus.SERVER_LIST_CLOCK, ServerStatus.ON);
+							}
+							else
+							{
+								st.addAttribute(ServerStatus.SERVER_LIST_CLOCK, ServerStatus.OFF);
+							}
+							if (Config.SERVER_LIST_TESTSERVER)
+							{
+								st.addAttribute(ServerStatus.TEST_SERVER, ServerStatus.ON);
+							}
+							else
+							{
+								st.addAttribute(ServerStatus.TEST_SERVER, ServerStatus.OFF);
+							}
+							if (Config.SERVER_GMONLY)
+							{
+								st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
+							}
+							else
+							{
+								st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
+							}
+							sendPacket(st);
+							if (L2World.getInstance().getAllPlayersCount() > 0)
 							{
-								if(wc.account.equals(account))
+								FastList<String> playerList = new FastList<String>();
+								Collection<L2PcInstance> pls = L2World.getInstance().getAllPlayers().values();
+								//synchronized (L2World.getInstance().getAllPlayers())
 								{
-									wcToRemove = wc;
+									for (L2PcInstance player : pls)
+										playerList.add(player.getAccountName());
 								}
+								PlayerInGame pig = new PlayerInGame(playerList);
+								sendPacket(pig);
 							}
-						}
-						if(wcToRemove != null)
-						{
-							if (par.isAuthed())
+							break;
+						case 03:
+							PlayerAuthResponse par = new PlayerAuthResponse(decrypt);
+							String account = par.getAccount();
+							WaitingClient wcToRemove = null;
+							synchronized (_waitingClients)
 							{
-								if (Config.DEBUG)_log.info("Login accepted player "+wcToRemove.account+" waited("+(GameTimeController.getGameTicks()-wcToRemove.timestamp)+"ms)");
-								PlayerInGame pig = new PlayerInGame(par.getAccount());
-								sendPacket(pig);
-								wcToRemove.gameClient.setState(GameClientState.AUTHED);
-								wcToRemove.gameClient.setSessionId(wcToRemove.session);
-								CharSelectionInfo cl = new CharSelectionInfo(wcToRemove.account, wcToRemove.gameClient.getSessionId().playOkID1);
-								wcToRemove.gameClient.getConnection().sendPacket(cl);
-								wcToRemove.gameClient.setCharSelection(cl.getCharInfo());
+								for (WaitingClient wc : _waitingClients)
+								{
+									if (wc.account.equals(account))
+									{
+										wcToRemove = wc;
+									}
+								}
 							}
-							else
+							if (wcToRemove != null)
 							{
-								_log.warning("session key is not correct. closing connection");
-								wcToRemove.gameClient.getConnection().sendPacket(new LoginFail(1));
-								wcToRemove.gameClient.closeNow();
+								if (par.isAuthed())
+								{
+									if (Config.DEBUG)
+										_log.info("Login accepted player " + wcToRemove.account + " waited("
+												+ (GameTimeController.getGameTicks() - wcToRemove.timestamp) + "ms)");
+									PlayerInGame pig = new PlayerInGame(par.getAccount());
+									sendPacket(pig);
+									wcToRemove.gameClient.setState(GameClientState.AUTHED);
+									wcToRemove.gameClient.setSessionId(wcToRemove.session);
+									CharSelectionInfo cl = new CharSelectionInfo(wcToRemove.account, wcToRemove.gameClient.getSessionId().playOkID1);
+									wcToRemove.gameClient.getConnection().sendPacket(cl);
+									wcToRemove.gameClient.setCharSelection(cl.getCharInfo());
+								}
+								else
+								{
+									_log.warning("session key is not correct. closing connection");
+									wcToRemove.gameClient.getConnection().sendPacket(new LoginFail(1));
+									wcToRemove.gameClient.closeNow();
+								}
+								_waitingClients.remove(wcToRemove);
 							}
-							_waitingClients.remove(wcToRemove);
-						}
-						break;
-					case 04:
-						KickPlayer kp = new KickPlayer(decrypt);
-						doKickPlayer(kp.getAccount());
-						break;
+							break;
+						case 04:
+							KickPlayer kp = new KickPlayer(decrypt);
+							doKickPlayer(kp.getAccount());
+							break;
 					}
 				}
 			}
 			catch (UnknownHostException e)
 			{
-				if (Config.DEBUG) e.printStackTrace();
+				if (Config.DEBUG)
+					e.printStackTrace();
 			}
 			catch (IOException e)
 			{
@@ -346,30 +347,36 @@ public class LoginServerThread extends Thread
 			}
 			finally
 			{
-				try { _loginSocket.close(); } catch (Exception e) {}
+				try
+				{
+					_loginSocket.close();
+				}
+				catch (Exception e)
+				{
+				}
 			}
-
+			
 			try
 			{
 				Thread.sleep(5000); // 5 seconds tempo.
 			}
-			catch(InterruptedException e)
+			catch (InterruptedException e)
 			{
 				//
 			}
 		}
 	}
-
+	
 	public void addWaitingClientAndSendRequest(String acc, L2GameClient client, SessionKey key)
 	{
-		if(Config.DEBUG)
+		if (Config.DEBUG)
 			_log.info(String.valueOf(key));
 		WaitingClient wc = new WaitingClient(acc, client, key);
-		synchronized(_waitingClients)
+		synchronized (_waitingClients)
 		{
 			_waitingClients.add(wc);
 		}
-		PlayerAuthRequest par = new PlayerAuthRequest(acc,key);
+		PlayerAuthRequest par = new PlayerAuthRequest(acc, key);
 		try
 		{
 			sendPacket(par);
@@ -377,27 +384,28 @@ public class LoginServerThread extends Thread
 		catch (IOException e)
 		{
 			_log.warning("Error while sending player auth request");
-			if (Config.DEBUG) e.printStackTrace();
+			if (Config.DEBUG)
+				e.printStackTrace();
 		}
 	}
-
+	
 	public void removeWaitingClient(L2GameClient client)
 	{
 		WaitingClient toRemove = null;
-		synchronized(_waitingClients)
+		synchronized (_waitingClients)
 		{
-			for(WaitingClient c :_waitingClients)
+			for (WaitingClient c : _waitingClients)
 			{
-				if(c.gameClient == client)
+				if (c.gameClient == client)
 				{
 					toRemove = c;
 				}
 			}
-			if(toRemove != null)
+			if (toRemove != null)
 				_waitingClients.remove(toRemove);
 		}
 	}
-
+	
 	public void sendLogout(String account)
 	{
 		PlayerLogout pl = new PlayerLogout(account);
@@ -408,15 +416,16 @@ public class LoginServerThread extends Thread
 		catch (IOException e)
 		{
 			_log.warning("Error while sending logout packet to login");
-			if (Config.DEBUG) e.printStackTrace();
+			if (Config.DEBUG)
+				e.printStackTrace();
 		}
 	}
-
+	
 	public void addGameServerLogin(String account, L2GameClient client)
 	{
 		_accountsInGameServer.put(account, client);
 	}
-
+	
 	public void sendAccessLevel(String account, int level)
 	{
 		ChangeAccessLevel cal = new ChangeAccessLevel(account, level);
@@ -430,29 +439,30 @@ public class LoginServerThread extends Thread
 				e.printStackTrace();
 		}
 	}
-
+	
 	private String hexToString(byte[] hex)
 	{
 		return new BigInteger(hex).toString(16);
 	}
-
+	
 	public void doKickPlayer(String account)
 	{
-		if(_accountsInGameServer.get(account) != null)
+		if (_accountsInGameServer.get(account) != null)
 		{
 			_accountsInGameServer.get(account).closeNow();
 			LoginServerThread.getInstance().sendLogout(account);
 		}
 	}
-
+	
 	public static byte[] generateHex(int size)
 	{
-		byte [] array = new byte[size];
+		byte[] array = new byte[size];
 		Rnd.nextBytes(array);
-		if (Config.DEBUG)_log.fine("Generated random String:  \""+array+"\"");
+		if (Config.DEBUG)
+			_log.fine("Generated random String:  \"" + array + "\"");
 		return array;
 	}
-
+	
 	/**
 	 * @param sl
 	 * @throws IOException
@@ -461,28 +471,29 @@ public class LoginServerThread extends Thread
 	{
 		byte[] data = sl.getContent();
 		NewCrypt.appendChecksum(data);
-		if (Config.DEBUG) _log.finest("[S]\n"+Util.printData(data));
+		if (Config.DEBUG)
+			_log.finest("[S]\n" + Util.printData(data));
 		data = _blowfish.crypt(data);
-
-		int len = data.length+2;
+		
+		int len = data.length + 2;
 		synchronized (_out) //avoids tow threads writing in the mean time
 		{
 			_out.write(len & 0xff);
-			_out.write(len >> 8 &0xff);
+			_out.write(len >> 8 & 0xff);
 			_out.write(data);
 			_out.flush();
 		}
 	}
-
+	
 	/**
 	 * @param maxPlayer The maxPlayer to set.
 	 */
 	public void setMaxPlayer(int maxPlayer)
 	{
-		sendServerStatus(ServerStatus.MAX_PLAYERS,maxPlayer);
+		sendServerStatus(ServerStatus.MAX_PLAYERS, maxPlayer);
 		_maxPlayer = maxPlayer;
 	}
-
+	
 	/**
 	 * @return Returns the maxPlayer.
 	 */
@@ -490,24 +501,25 @@ public class LoginServerThread extends Thread
 	{
 		return _maxPlayer;
 	}
-
+	
 	/**
 	 * @param server_gm_only
 	 */
 	public void sendServerStatus(int id, int value)
 	{
 		ServerStatus ss = new ServerStatus();
-		ss.addAttribute(id,value);
+		ss.addAttribute(id, value);
 		try
 		{
 			sendPacket(ss);
 		}
 		catch (IOException e)
 		{
-			if (Config.DEBUG) e.printStackTrace();
+			if (Config.DEBUG)
+				e.printStackTrace();
 		}
 	}
-
+	
 	/**
 	 * @return
 	 */
@@ -515,7 +527,7 @@ public class LoginServerThread extends Thread
 	{
 		return ServerStatus.STATUS_STRING[_status];
 	}
-
+	
 	/**
 	 * @return
 	 */
@@ -523,7 +535,7 @@ public class LoginServerThread extends Thread
 	{
 		return Config.SERVER_LIST_CLOCK;
 	}
-
+	
 	/**
 	 * @return
 	 */
@@ -531,7 +543,7 @@ public class LoginServerThread extends Thread
 	{
 		return Config.SERVER_LIST_BRACKET;
 	}
-
+	
 	/**
 	 * @return Returns the serverName.
 	 */
@@ -539,47 +551,47 @@ public class LoginServerThread extends Thread
 	{
 		return _serverName;
 	}
-
+	
 	public void setServerStatus(int status)
 	{
-		switch(status)
+		switch (status)
 		{
-		case ServerStatus.STATUS_AUTO:
-			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_AUTO);
-			_status = status;
-			break;
-		case ServerStatus.STATUS_DOWN:
-			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_DOWN);
-			_status = status;
-			break;
-		case ServerStatus.STATUS_FULL:
-			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_FULL);
-			_status = status;
-			break;
-		case ServerStatus.STATUS_GM_ONLY:
-			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_GM_ONLY);
-			_status = status;
-			break;
-		case ServerStatus.STATUS_GOOD:
-			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_GOOD);
-			_status = status;
-			break;
-		case ServerStatus.STATUS_NORMAL:
-			sendServerStatus(ServerStatus.SERVER_LIST_STATUS,ServerStatus.STATUS_NORMAL);
-			_status = status;
-			break;
-		default:
-			throw new IllegalArgumentException("Status does not exists:"+status);
+			case ServerStatus.STATUS_AUTO:
+				sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
+				_status = status;
+				break;
+			case ServerStatus.STATUS_DOWN:
+				sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_DOWN);
+				_status = status;
+				break;
+			case ServerStatus.STATUS_FULL:
+				sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_FULL);
+				_status = status;
+				break;
+			case ServerStatus.STATUS_GM_ONLY:
+				sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
+				_status = status;
+				break;
+			case ServerStatus.STATUS_GOOD:
+				sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GOOD);
+				_status = status;
+				break;
+			case ServerStatus.STATUS_NORMAL:
+				sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_NORMAL);
+				_status = status;
+				break;
+			default:
+				throw new IllegalArgumentException("Status does not exists:" + status);
 		}
 	}
-
+	
 	public static class SessionKey
 	{
 		public int playOkID1;
 		public int playOkID2;
 		public int loginOkID1;
 		public int loginOkID2;
-
+		
 		public SessionKey(int loginOK1, int loginOK2, int playOK1, int playOK2)
 		{
 			playOkID1 = playOK1;
@@ -587,21 +599,21 @@ public class LoginServerThread extends Thread
 			loginOkID1 = loginOK1;
 			loginOkID2 = loginOK2;
 		}
-
+		
 		@Override
 		public String toString()
 		{
-			return "PlayOk: "+playOkID1+" "+playOkID2+" LoginOk:"+loginOkID1+" "+loginOkID2;
+			return "PlayOk: " + playOkID1 + " " + playOkID2 + " LoginOk:" + loginOkID1 + " " + loginOkID2;
 		}
 	}
-
+	
 	private class WaitingClient
 	{
 		public int timestamp;
 		public String account;
 		public L2GameClient gameClient;
 		public SessionKey session;
-
+		
 		public WaitingClient(String acc, L2GameClient client, SessionKey key)
 		{
 			account = acc;
@@ -610,4 +622,10 @@ public class LoginServerThread extends Thread
 			session = key;
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final LoginServerThread _instance = new LoginServerThread();
+	}
 }

+ 117 - 119
L2_GameServer/java/net/sf/l2j/gameserver/MonsterRace.java

@@ -22,125 +22,123 @@ import net.sf.l2j.gameserver.model.actor.L2Npc;
 import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 import net.sf.l2j.util.Rnd;
 
-
 public class MonsterRace
 {
-    private L2Npc[] _monsters;
-    private static MonsterRace _instance;
-    private Constructor<?> _constructor;
-    private int[][] _speeds;
-    private int[] _first, _second;
-
-    private MonsterRace()
-    {
-        _monsters    = new L2Npc[8];
-        _speeds      = new int[8][20];
-        _first       = new int[2];
-        _second      = new int[2];
-    }
-
-    public static MonsterRace getInstance()
-    {
-        if (_instance == null)
-        {
-            _instance = new MonsterRace();
-        }
-
-        return _instance;
-    }
-
-    public void newRace()
-    {
-        int random = 0;
-
-        for (int i=0; i<8; i++)
-        {
-            int id = 31003;
-            random = Rnd.get(24);
-            while(true)
-            {
-                for (int j=i-1; j>=0; j--)
-                {
-                    if (_monsters[j].getTemplate().npcId == (id + random))
-                    {
-                        random = Rnd.get(24);
-                        continue;
-                    }
-                }
-                break;
-            }
-            try
-            {
-                L2NpcTemplate template = NpcTable.getInstance().getTemplate(id+random);
-                _constructor = Class.forName("net.sf.l2j.gameserver.model.actor.instance." + template.type + "Instance").getConstructors()[0];
-                int objectId = IdFactory.getInstance().getNextId();
-                _monsters[i] = (L2Npc)_constructor.newInstance(objectId, template);
-            }
-            catch (Exception e)
-            {
-                e.printStackTrace();
-            }
-            //_log.info("Monster "+i+" is id: "+(id+random));
-        }
-        newSpeeds();
-    }
-
-    public void newSpeeds()
-    {
-        _speeds = new int[8][20];
-        int total = 0;
-        _first[1]=0;_second[1]=0;
-        for (int i=0; i<8; i++)
-        {
-            total = 0;
-            for (int j=0; j<20 ;j++)
-            {
-                if (j == 19)
-                    _speeds[i][j] = 100;
-                else
-                    _speeds[i][j] = Rnd.get(60) + 65;
-                total += _speeds[i][j];
-            }
-            if (total >= _first[1])
-            {
-                _second[0] = _first[0];
-                _second[1] = _first[1];
-                _first[0] = 8 - i;
-                _first[1] = total;
-            }
-            else if (total >= _second[1])
-            {
-                _second[0] = 8 - i;
-                _second[1] = total;
-            }
-        }
-    }
-
-    /**
-     * @return Returns the monsters.
-     */
-    public L2Npc[] getMonsters()
-    {
-        return _monsters;
-    }
-
-    /**
-     * @return Returns the speeds.
-     */
-    public int[][] getSpeeds()
-    {
-        return _speeds;
-    }
-
-    public int getFirstPlace()
-    {
-        return _first[0];
-    }
-
-    public int getSecondPlace()
-    {
-        return _second[0];
-    }
-
-
+	private L2Npc[] _monsters;
+	private Constructor<?> _constructor;
+	private int[][] _speeds;
+	private int[] _first, _second;
+	
+	private MonsterRace()
+	{
+		_monsters = new L2Npc[8];
+		_speeds = new int[8][20];
+		_first = new int[2];
+		_second = new int[2];
+	}
+	
+	public static MonsterRace getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	public void newRace()
+	{
+		int random = 0;
+		
+		for (int i = 0; i < 8; i++)
+		{
+			int id = 31003;
+			random = Rnd.get(24);
+			while (true)
+			{
+				for (int j = i - 1; j >= 0; j--)
+				{
+					if (_monsters[j].getTemplate().npcId == (id + random))
+					{
+						random = Rnd.get(24);
+						continue;
+					}
+				}
+				break;
+			}
+			try
+			{
+				L2NpcTemplate template = NpcTable.getInstance().getTemplate(id + random);
+				_constructor = Class.forName("net.sf.l2j.gameserver.model.actor.instance." + template.type + "Instance").getConstructors()[0];
+				int objectId = IdFactory.getInstance().getNextId();
+				_monsters[i] = (L2Npc) _constructor.newInstance(objectId, template);
+			}
+			catch (Exception e)
+			{
+				e.printStackTrace();
+			}
+			//_log.info("Monster "+i+" is id: "+(id+random));
+		}
+		newSpeeds();
+	}
+	
+	public void newSpeeds()
+	{
+		_speeds = new int[8][20];
+		int total = 0;
+		_first[1] = 0;
+		_second[1] = 0;
+		for (int i = 0; i < 8; i++)
+		{
+			total = 0;
+			for (int j = 0; j < 20; j++)
+			{
+				if (j == 19)
+					_speeds[i][j] = 100;
+				else
+					_speeds[i][j] = Rnd.get(60) + 65;
+				total += _speeds[i][j];
+			}
+			if (total >= _first[1])
+			{
+				_second[0] = _first[0];
+				_second[1] = _first[1];
+				_first[0] = 8 - i;
+				_first[1] = total;
+			}
+			else if (total >= _second[1])
+			{
+				_second[0] = 8 - i;
+				_second[1] = total;
+			}
+		}
+	}
+	
+	/**
+	 * @return Returns the monsters.
+	 */
+	public L2Npc[] getMonsters()
+	{
+		return _monsters;
+	}
+	
+	/**
+	 * @return Returns the speeds.
+	 */
+	public int[][] getSpeeds()
+	{
+		return _speeds;
+	}
+	
+	public int getFirstPlace()
+	{
+		return _first[0];
+	}
+	
+	public int getSecondPlace()
+	{
+		return _second[0];
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final MonsterRace _instance = new MonsterRace();
+	}
 }

File diff suppressed because it is too large
+ 323 - 307
L2_GameServer/java/net/sf/l2j/gameserver/RecipeController.java


File diff suppressed because it is too large
+ 363 - 362
L2_GameServer/java/net/sf/l2j/gameserver/SevenSigns.java


+ 2429 - 2393
L2_GameServer/java/net/sf/l2j/gameserver/SevenSignsFestival.java

@@ -55,2402 +55,2438 @@ import net.sf.l2j.gameserver.util.Util;
 import net.sf.l2j.util.Rnd;
 
 /**
- *  Seven Signs Festival of Darkness Engine
+ *Seven Signs Festival of Darkness Engine
  *
- *  TODO:
- *  - Archer mobs should target healer characters over other party members.
- *  - ADDED 29 Sep: Players that leave a party during the Seven Signs Festival will now take damage and cannot be healed.
+ *TODO:
+ *- Archer mobs should target healer characters over other party members.
+ *- ADDED 29 Sep: Players that leave a party during the Seven Signs Festival will now take damage and cannot be healed.
  *
- *  @author Tempy
+ *@author Tempy
  */
 public class SevenSignsFestival implements SpawnListener
 {
-    protected static final Logger _log = Logger.getLogger(SevenSignsFestival.class.getName());
-    private static SevenSignsFestival _instance;
-
-    private static final String GET_CLAN_NAME = "SELECT clan_name FROM clan_data WHERE clan_id = (SELECT clanid FROM characters WHERE char_name = ?)";
-
-    /**
-     * These length settings are important! :)
-     * All times are relative to the ELAPSED time (in ms) since a festival begins.
-     *
-     * Festival manager start is the time after the server starts to begin the first
-     * festival cycle.
-     *
-     * The cycle length should ideally be at least 2x longer than the festival length.
-     * This allows ample time for players to sign-up to participate in the festival.
-     *
-     * The intermission is the time between the festival participants being moved
-     * to the "arenas" and the spawning of the first set of mobs.
-     *
-     * The monster swarm time is the time before the monsters swarm to the center of the arena,
-     * after they are spawned.
-     *
-     * 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;
-
-    // Key Constants \\
-    private static final int FESTIVAL_MAX_OFFSET_X = 230;
-    private static final int FESTIVAL_MAX_OFFSET_Y = 230;
-    private static final int FESTIVAL_DEFAULT_RESPAWN = 60; // Specify in seconds!
-
-    public static final int FESTIVAL_COUNT = 5;
-    public static final int FESTIVAL_LEVEL_MAX_31 = 0;
-    public static final int FESTIVAL_LEVEL_MAX_42 = 1;
-    public static final int FESTIVAL_LEVEL_MAX_53 = 2;
-    public static final int FESTIVAL_LEVEL_MAX_64 = 3;
-    public static final int FESTIVAL_LEVEL_MAX_NONE = 4;
-    public static final int[] FESTIVAL_LEVEL_SCORES = {60, 70, 100, 120, 150}; // 500 maximum possible score
-
-    public static final int FESTIVAL_OFFERING_ID = 5901;
-    public static final int FESTIVAL_OFFERING_VALUE = 5;
-
-    //////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\
-    /*
-    * The following contains all the necessary spawn data for:
-    * - Player Start Locations
-    * - Witches
-    * - Monsters
-    * - Chests
-    *
-    * All data is given by: X, Y, Z (coords), Heading, NPC ID (if necessary)
-    * This may be moved externally in time, but the data should not change.
-    */
-    public static final int[][] FESTIVAL_DAWN_PLAYER_SPAWNS =
-    {
-         {-79187, 113186, -4895, 0}, // 31 and below
-         {-75918, 110137, -4895, 0}, // 42 and below
-         {-73835, 111969, -4895, 0}, // 53 and below
-         {-76170, 113804, -4895, 0}, // 64 and below
-         {-78927, 109528, -4895, 0}  // No level limit
-    };
-
-    public static final int[][] FESTIVAL_DUSK_PLAYER_SPAWNS =
-    {
-         {-77200, 88966, -5151, 0}, // 31 and below
-         {-76941, 85307, -5151, 0}, // 42 and below
-         {-74855, 87135, -5151, 0}, // 53 and below
-         {-80208, 88222, -5151, 0}, // 64 and below
-         {-79954, 84697, -5151, 0}  // No level limit
-    };
-
-    protected static final int[][] FESTIVAL_DAWN_WITCH_SPAWNS =
-    {
-         {-79183, 113052, -4891, 0, 31132}, // 31 and below
-         {-75916, 110270, -4891, 0, 31133}, // 42 and below
-         {-73979, 111970, -4891, 0, 31134}, // 53 and below
-         {-76174, 113663, -4891, 0, 31135}, // 64 and below
-         {-78930, 109664, -4891, 0, 31136}  // No level limit
-    };
-
-    protected static final int[][] FESTIVAL_DUSK_WITCH_SPAWNS =
-    {
-         {-77199, 88830, -5147, 0, 31142}, // 31 and below
-         {-76942, 85438, -5147, 0, 31143}, // 42 and below
-         {-74990, 87135, -5147, 0, 31144}, // 53 and below
-         {-80207, 88222, -5147, 0, 31145}, // 64 and below
-         {-79952, 84833, -5147, 0, 31146}  // No level limit
-    };
-
-    protected static final int[][][] FESTIVAL_DAWN_PRIMARY_SPAWNS =
-    {
-     {
-         /* Level 31 and Below - Offering of the Branded */
-         {-78537, 113839, -4895, -1, 18009},
-         {-78466, 113852, -4895, -1, 18010},
-         {-78509, 113899, -4895, -1, 18010},
-
-         {-78481, 112557, -4895, -1, 18009},
-         {-78559, 112504, -4895, -1, 18010},
-         {-78489, 112494, -4895, -1, 18010},
-
-         {-79803, 112543, -4895, -1, 18012},
-         {-79854, 112492, -4895, -1, 18013},
-         {-79886, 112557, -4895, -1, 18014},
-
-         {-79821, 113811, -4895, -1, 18015},
-         {-79857, 113896, -4895, -1, 18017},
-         {-79878, 113816, -4895, -1, 18018},
-
-         // Archers and Marksmen \\
-         {-79190, 113660, -4895, -1, 18011},
-         {-78710, 113188, -4895, -1, 18011},
-         {-79190, 112730, -4895, -1, 18016},
-         {-79656, 113188, -4895, -1, 18016}
-     },
-     {
-         /* Level 42 and Below - Apostate Offering */
-         {-76558, 110784, -4895, -1, 18019},
-         {-76607, 110815, -4895, -1, 18020}, // South West
-         {-76559, 110820, -4895, -1, 18020},
-
-         {-75277, 110792, -4895, -1, 18019},
-         {-75225, 110801, -4895, -1, 18020}, // South East
-         {-75262, 110832, -4895, -1, 18020},
-
-         {-75249, 109441, -4895, -1, 18022},
-         {-75278, 109495, -4895, -1, 18023}, // North East
-         {-75223, 109489, -4895, -1, 18024},
-
-         {-76556, 109490, -4895, -1, 18025},
-         {-76607, 109469, -4895, -1, 18027}, // North West
-         {-76561, 109450, -4895, -1, 18028},
-
-         // Archers and Marksmen \\
-         {-76399, 110144, -4895, -1, 18021},
-         {-75912, 110606, -4895, -1, 18021},
-         {-75444, 110144, -4895, -1, 18026},
-         {-75930, 109665, -4895, -1, 18026}
-     },
-     {
-         /* Level 53 and Below - Witch's Offering */
-         {-73184, 111319, -4895, -1, 18029},
-         {-73135, 111294, -4895, -1, 18030}, // South West
-         {-73185, 111281, -4895, -1, 18030},
-
-         {-74477, 111321, -4895, -1, 18029},
-         {-74523, 111293, -4895, -1, 18030}, // South East
-         {-74481, 111280, -4895, -1, 18030},
-
-         {-74489, 112604, -4895, -1, 18032},
-         {-74491, 112660, -4895, -1, 18033}, // North East
-         {-74527, 112629, -4895, -1, 18034},
-
-         {-73197, 112621, -4895, -1, 18035},
-         {-73142, 112631, -4895, -1, 18037}, // North West
-         {-73182, 112656, -4895, -1, 18038},
-
-         // Archers and Marksmen \\
-         {-73834, 112430, -4895, -1, 18031},
-         {-74299, 111959, -4895, -1, 18031},
-         {-73841, 111491, -4895, -1, 18036},
-         {-73363, 111959, -4895, -1, 18036}
-     },
-     {
-         /* Level 64 and Below - Dark Omen Offering */
-         {-75543, 114461, -4895, -1, 18039},
-         {-75514, 114493, -4895, -1, 18040}, // South West
-         {-75488, 114456, -4895, -1, 18040},
-
-         {-75521, 113158, -4895, -1, 18039},
-         {-75504, 113110, -4895, -1, 18040}, // South East
-         {-75489, 113142, -4895, -1, 18040},
-
-         {-76809, 113143, -4895, -1, 18042},
-         {-76860, 113138, -4895, -1, 18043}, // North East
-         {-76831, 113112, -4895, -1, 18044},
-
-         {-76831, 114441, -4895, -1, 18045},
-         {-76840, 114490, -4895, -1, 18047}, // North West
-         {-76864, 114455, -4895, -1, 18048},
-
-         // Archers and Marksmen \\
-         {-75703, 113797, -4895, -1, 18041},
-         {-76180, 114263, -4895, -1, 18041},
-         {-76639, 113797, -4895, -1, 18046},
-         {-76180, 113337, -4895, -1, 18046}
-     },
-     {
-         /* No Level Limit - Offering of Forbidden Path */
-         {-79576, 108881, -4895, -1, 18049},
-         {-79592, 108835, -4895, -1, 18050}, // South West
-         {-79614, 108871, -4895, -1, 18050},
-
-         {-79586, 110171, -4895, -1, 18049},
-         {-79589, 110216, -4895, -1, 18050}, // South East
-         {-79620, 110177, -4895, -1, 18050},
-
-         {-78825, 110182, -4895, -1, 18052},
-         {-78238, 110182, -4895, -1, 18053}, // North East
-         {-78266, 110218, -4895, -1, 18054},
-
-         {-78275, 108883, -4895, -1, 18055},
-         {-78267, 108839, -4895, -1, 18057}, // North West
-         {-78241, 108871, -4895, -1, 18058},
-
-         // Archers and Marksmen \\
-         {-79394, 109538, -4895, -1, 18051},
-         {-78929, 109992, -4895, -1, 18051},
-         {-78454, 109538, -4895, -1, 18056},
-         {-78929, 109053, -4895, -1, 18056}
-     }
-    };
-
-    protected static final int[][][] FESTIVAL_DUSK_PRIMARY_SPAWNS =
-    {
-     {
-         /* Level 31 and Below - Offering of the Branded */
-         {-76542, 89653, -5151, -1, 18009},
-         {-76509, 89637, -5151, -1, 18010},
-         {-76548, 89614, -5151, -1, 18010},
-
-         {-76539, 88326, -5151, -1, 18009},
-         {-76512, 88289, -5151, -1, 18010},
-         {-76546, 88287, -5151, -1, 18010},
-
-         {-77879, 88308, -5151, -1, 18012},
-         {-77886, 88310, -5151, -1, 18013},
-         {-77879, 88278, -5151, -1, 18014},
-
-         {-77857, 89605, -5151, -1, 18015},
-         {-77858, 89658, -5151, -1, 18017},
-         {-77891, 89633, -5151, -1, 18018},
-
-         // Archers and Marksmen \\
-         {-76728, 88962, -5151, -1, 18011},
-         {-77194, 88494, -5151, -1, 18011},
-         {-77660, 88896, -5151, -1, 18016},
-         {-77195, 89438, -5151, -1, 18016}
-     },
-     {
-         /* Level 42 and Below - Apostate's Offering */
-         {-77585, 84650, -5151, -1, 18019},
-         {-77628, 84643, -5151, -1, 18020},
-         {-77607, 84613, -5151, -1, 18020},
-
-         {-76603, 85946, -5151, -1, 18019},
-         {-77606, 85994, -5151, -1, 18020},
-         {-77638, 85959, -5151, -1, 18020},
-
-         {-76301, 85960, -5151, -1, 18022},
-         {-76257, 85972, -5151, -1, 18023},
-         {-76286, 85992, -5151, -1, 18024},
-
-         {-76281, 84667, -5151, -1, 18025},
-         {-76291, 84611, -5151, -1, 18027},
-         {-76257, 84616, -5151, -1, 18028},
-
-         // Archers and Marksmen \\
-         {-77419, 85307, -5151, -1, 18021},
-         {-76952, 85768, -5151, -1, 18021},
-         {-76477, 85312, -5151, -1, 18026},
-         {-76942, 84832, -5151, -1, 18026}
-     },
-     {
-         /* Level 53 and Below - Witch's Offering */
-         {-74211, 86494, -5151, -1, 18029},
-         {-74200, 86449, -5151, -1, 18030},
-         {-74167, 86464, -5151, -1, 18030},
-
-         {-75495, 86482, -5151, -1, 18029},
-         {-75540, 86473, -5151, -1, 18030},
-         {-75509, 86445, -5151, -1, 18030},
-
-         {-75509, 87775, -5151, -1, 18032},
-         {-75518, 87826, -5151, -1, 18033},
-         {-75542, 87780, -5151, -1, 18034},
-
-         {-74214, 87789, -5151, -1, 18035},
-         {-74169, 87801, -5151, -1, 18037},
-         {-74198, 87827, -5151, -1, 18038},
-
-         // Archers and Marksmen \\
-         {-75324, 87135, -5151, -1, 18031},
-         {-74852, 87606, -5151, -1, 18031},
-         {-74388, 87146, -5151, -1, 18036},
-         {-74856, 86663, -5151, -1, 18036}
-     },
-     {
-         /* Level 64 and Below - Dark Omen Offering */
-         {-79560, 89007, -5151, -1, 18039},
-         {-79521, 89016, -5151, -1, 18040},
-         {-79544, 89047, -5151, -1, 18040},
-
-         {-79552, 87717, -5151, -1, 18039},
-         {-79552, 87673, -5151, -1, 18040},
-         {-79510, 87702, -5151, -1, 18040},
-
-         {-80866, 87719, -5151, -1, 18042},
-         {-80897, 87689, -5151, -1, 18043},
-         {-80850, 87685, -5151, -1, 18044},
-
-         {-80848, 89013, -5151, -1, 18045},
-         {-80887, 89051, -5151, -1, 18047},
-         {-80891, 89004, -5151, -1, 18048},
-
-         // Archers and Marksmen \\
-         {-80205, 87895, -5151, -1, 18041},
-         {-80674, 88350, -5151, -1, 18041},
-         {-80209, 88833, -5151, -1, 18046},
-         {-79743, 88364, -5151, -1, 18046}
-     },
-     {
-         /* No Level Limit - Offering of Forbidden Path */
-         {-80624, 84060, -5151, -1, 18049},
-         {-80621, 84007, -5151, -1, 18050},
-         {-80590, 84039, -5151, -1, 18050},
-
-         {-80605, 85349, -5151, -1, 18049},
-         {-80639, 85363, -5151, -1, 18050},
-         {-80611, 85385, -5151, -1, 18050},
-
-         {-79311, 85353, -5151, -1, 18052},
-         {-79277, 85384, -5151, -1, 18053},
-         {-79273, 85539, -5151, -1, 18054},
-
-         {-79297, 84054, -5151, -1, 18055},
-         {-79285, 84006, -5151, -1, 18057},
-         {-79260, 84040, -5151, -1, 18058},
-
-         // Archers and Marksmen \\
-         {-79945, 85171, -5151, -1, 18051},
-         {-79489, 84707, -5151, -1, 18051},
-         {-79952, 84222, -5151, -1, 18056},
-         {-80423, 84703, -5151, -1, 18056}
-     }
-    };
-
-    protected static final int[][][] FESTIVAL_DAWN_SECONDARY_SPAWNS =
-    {
-     {
-         /* 31 and Below */
-         {-78757, 112834, -4895, -1, 18016},
-         {-78581, 112834, -4895, -1, 18016},
-
-         {-78822, 112526, -4895, -1, 18011},
-         {-78822, 113702, -4895, -1, 18011},
-         {-78822, 113874, -4895, -1, 18011},
-
-         {-79524, 113546, -4895, -1, 18011},
-         {-79693, 113546, -4895, -1, 18011},
-         {-79858, 113546, -4895, -1, 18011},
-
-         {-79545, 112757, -4895, -1, 18016},
-         {-79545, 112586, -4895, -1, 18016},
-     },
-     {
-         /* 42 and Below */
-         {-75565, 110580, -4895, -1, 18026},
-         {-75565, 110740, -4895, -1, 18026},
-
-         {-75577, 109776, -4895, -1, 18021},
-         {-75413, 109776, -4895, -1, 18021},
-         {-75237, 109776, -4895, -1, 18021},
-
-         {-76274, 109468, -4895, -1, 18021},
-         {-76274, 109635, -4895, -1, 18021},
-         {-76274, 109795, -4895, -1, 18021},
-
-         {-76351, 110500, -4895, -1, 18056},
-         {-76528, 110500, -4895, -1, 18056},
-     },
-     {
-         /* 53 and Below */
-         {-74191, 111527, -4895, -1, 18036},
-         {-74191, 111362, -4895, -1, 18036},
-
-         {-73495, 111611, -4895, -1, 18031},
-         {-73327, 111611, -4895, -1, 18031},
-         {-73154, 111611, -4895, -1, 18031},
-
-         {-73473, 112301, -4895, -1, 18031},
-         {-73473, 112475, -4895, -1, 18031},
-         {-73473, 112649, -4895, -1, 18031},
-
-         {-74270, 112326, -4895, -1, 18036},
-         {-74443, 112326, -4895, -1, 18036},
-     },
-     {
-         /* 64 and Below */
-         {-75738, 113439, -4895, -1, 18046},
-         {-75571, 113439, -4895, -1, 18046},
-
-         {-75824, 114141, -4895, -1, 18041},
-         {-75824, 114309, -4895, -1, 18041},
-         {-75824, 114477, -4895, -1, 18041},
-
-         {-76513, 114158, -4895, -1, 18041},
-         {-76683, 114158, -4895, -1, 18041},
-         {-76857, 114158, -4895, -1, 18041},
-
-         {-76535, 113357, -4895, -1, 18056},
-         {-76535, 113190, -4895, -1, 18056},
-     },
-     {
-         /* No Level Limit */
-         {-79350, 109894, -4895, -1, 18056},
-         {-79534, 109894, -4895, -1, 18056},
-
-         {-79285, 109187, -4895, -1, 18051},
-         {-79285, 109019, -4895, -1, 18051},
-         {-79285, 108860, -4895, -1, 18051},
-
-         {-78587, 109172, -4895, -1, 18051},
-         {-78415, 109172, -4895, -1, 18051},
-         {-78249, 109172, -4895, -1, 18051},
-
-         {-78575, 109961, -4895, -1, 18056},
-         {-78575, 110130, -4895, -1, 18056},
-     }
-    };
-
-    protected static final int[][][] FESTIVAL_DUSK_SECONDARY_SPAWNS =
-    {
-     {
-         /* 31 and Below */
-         {-76844, 89304, -5151, -1, 18011},
-         {-76844, 89479, -5151, -1, 18011},
-         {-76844, 89649, -5151, -1, 18011},
-
-         {-77544, 89326, -5151, -1, 18011},
-         {-77716, 89326, -5151, -1, 18011},
-         {-77881, 89326, -5151, -1, 18011},
-
-         {-77561, 88530, -5151, -1, 18016},
-         {-77561, 88364, -5151, -1, 18016},
-
-         {-76762, 88615, -5151, -1, 18016},
-         {-76594, 88615, -5151, -1, 18016},
-     },
-     {
-         /* 42 and Below */
-         {-77307, 84969, -5151, -1, 18021},
-         {-77307, 84795, -5151, -1, 18021},
-         {-77307, 84623, -5151, -1, 18021},
-
-         {-76614, 84944, -5151, -1, 18021},
-         {-76433, 84944, -5151, -1, 18021},
-         {-7626-1, 84944, -5151, -1, 18021},
-
-         {-76594, 85745, -5151, -1, 18026},
-         {-76594, 85910, -5151, -1, 18026},
-
-         {-77384, 85660, -5151, -1, 18026},
-         {-77555, 85660, -5151, -1, 18026},
-     },
-     {
-         /* 53 and Below */
-         {-74517, 86782, -5151, -1, 18031},
-         {-74344, 86782, -5151, -1, 18031},
-         {-74185, 86782, -5151, -1, 18031},
-
-         {-74496, 87464, -5151, -1, 18031},
-         {-74496, 87636, -5151, -1, 18031},
-         {-74496, 87815, -5151, -1, 18031},
-
-         {-75298, 87497, -5151, -1, 18036},
-         {-75460, 87497, -5151, -1, 18036},
-
-         {-75219, 86712, -5151, -1, 18036},
-         {-75219, 86531, -5151, -1, 18036},
-     },
-     {
-         /* 64 and Below */
-         {-79851, 88703, -5151, -1, 18041},
-         {-79851, 88868, -5151, -1, 18041},
-         {-79851, 89040, -5151, -1, 18041},
-
-         {-80548, 88722, -5151, -1, 18041},
-         {-80711, 88722, -5151, -1, 18041},
-         {-80883, 88722, -5151, -1, 18041},
-
-         {-80565, 87916, -5151, -1, 18046},
-         {-80565, 87752, -5151, -1, 18046},
-
-         {-79779, 87996, -5151, -1, 18046},
-         {-79613, 87996, -5151, -1, 18046},
-     },
-     {
-         /* No Level Limit */
-         {-79271, 84330, -5151, -1, 18051},
-         {-79448, 84330, -5151, -1, 18051},
-         {-79601, 84330, -5151, -1, 18051},
-
-         {-80311, 84367, -5151, -1, 18051},
-         {-80311, 84196, -5151, -1, 18051},
-         {-80311, 84015, -5151, -1, 18051},
-
-         {-80556, 85049, -5151, -1, 18056},
-         {-80384, 85049, -5151, -1, 18056},
-
-         {-79598, 85127, -5151, -1, 18056},
-         {-79598, 85303, -5151, -1, 18056},
-     }
-    };
-
-    protected static final int[][][] FESTIVAL_DAWN_CHEST_SPAWNS =
-    {
-     {
-         /* Level 31 and Below */
-         {-78999, 112957, -4927, -1, 18109},
-         {-79153, 112873, -4927, -1, 18109},
-         {-79256, 112873, -4927, -1, 18109},
-         {-79368, 112957, -4927, -1, 18109},
-
-         {-79481, 113124, -4927, -1, 18109},
-         {-79481, 113275, -4927, -1, 18109},
-
-         {-79364, 113398, -4927, -1, 18109},
-         {-79213, 113500, -4927, -1, 18109},
-         {-79099, 113500, -4927, -1, 18109},
-         {-78960, 113398, -4927, -1, 18109},
-
-         {-78882, 113235, -4927, -1, 18109},
-         {-78882, 113099, -4927, -1, 18109},
-     },
-     {
-         /* Level 42 and Below */
-         {-76119, 110383, -4927, -1, 18110},
-         {-75980, 110442, -4927, -1, 18110},
-         {-75848, 110442, -4927, -1, 18110},
-         {-75720, 110383, -4927, -1, 18110},
-
-         {-75625, 110195, -4927, -1, 18110},
-         {-75625, 110063, -4927, -1, 18110},
-
-         {-75722, 109908, -4927, -1, 18110},
-         {-75863, 109832, -4927, -1, 18110},
-         {-75989, 109832, -4927, -1, 18110},
-         {-76130, 109908, -4927, -1, 18110},
-
-         {-76230, 110079, -4927, -1, 18110},
-         {-76230, 110215, -4927, -1, 18110},
-     },
-     {
-         /* Level 53 and Below */
-         {-74055, 111781, -4927, -1, 18111},
-         {-74144, 111938, -4927, -1, 18111},
-         {-74144, 112075, -4927, -1, 18111},
-         {-74055, 112173, -4927, -1, 18111},
-
-         {-73885, 112289, -4927, -1, 18111},
-         {-73756, 112289, -4927, -1, 18111},
-
-         {-73574, 112141, -4927, -1, 18111},
-         {-73511, 112040, -4927, -1, 18111},
-         {-73511, 111912, -4927, -1, 18111},
-         {-73574, 111772, -4927, -1, 18111},
-
-         {-73767, 111669, -4927, -1, 18111},
-         {-73899, 111669, -4927, -1, 18111},
-     },
-     {
-         /* Level 64 and Below */
-         {-76008, 113566, -4927, -1, 18112},
-         {-76159, 113485, -4927, -1, 18112},
-         {-76267, 113485, -4927, -1, 18112},
-         {-76386, 113566, -4927, -1, 18112},
-
-         {-76482, 113748, -4927, -1, 18112},
-         {-76482, 113885, -4927, -1, 18112},
-
-         {-76371, 114029, -4927, -1, 18112},
-         {-76220, 114118, -4927, -1, 18112},
-         {-76092, 114118, -4927, -1, 18112},
-         {-75975, 114029, -4927, -1, 18112},
-
-         {-75861, 11385-1, -4927, -1, 18112},
-         {-75861, 113713, -4927, -1, 18112},
-     },
-     {
-         /* No Level Limit */
-         {-79100, 109782, -4927, -1, 18113},
-         {-78962, 109853, -4927, -1, 18113},
-         {-78851, 109853, -4927, -1, 18113},
-         {-78721, 109782, -4927, -1, 18113},
-
-         {-78615, 109596, -4927, -1, 18113},
-         {-78615, 109453, -4927, -1, 18113},
-
-         {-78746, 109300, -4927, -1, 18113},
-         {-78881, 109203, -4927, -1, 18113},
-         {-79027, 109203, -4927, -1, 18113},
-         {-79159, 109300, -4927, -1, 18113},
-
-         {-79240, 109480, -4927, -1, 18113},
-         {-79240, 109615, -4927, -1, 18113},
-     }
-    };
-
-    protected static final int[][][] FESTIVAL_DUSK_CHEST_SPAWNS =
-    {
-     {
-         /* Level 31 and Below */
-         {-77016, 88726, -5183, -1, 18114},
-         {-77136, 88646, -5183, -1, 18114},
-         {-77247, 88646, -5183, -1, 18114},
-         {-77380, 88726, -5183, -1, 18114},
-
-         {-77512, 88883, -5183, -1, 18114},
-         {-77512, 89053, -5183, -1, 18114},
-
-         {-77378, 89287, -5183, -1, 18114},
-         {-77254, 89238, -5183, -1, 18114},
-         {-77095, 89238, -5183, -1, 18114},
-         {-76996, 89287, -5183, -1, 18114},
-
-         {-76901, 89025, -5183, -1, 18114},
-         {-76901, 88891, -5183, -1, 18114},
-     },
-     {
-         /* Level 42 and Below */
-         {-77128, 85553, -5183, -1, 18115},
-         {-77036, 85594, -5183, -1, 18115},
-         {-76919, 85594, -5183, -1, 18115},
-         {-76755, 85553, -5183, -1, 18115},
-
-         {-76635, 85392, -5183, -1, 18115},
-         {-76635, 85216, -5183, -1, 18115},
-
-         {-76761, 85025, -5183, -1, 18115},
-         {-76908, 85004, -5183, -1, 18115},
-         {-77041, 85004, -5183, -1, 18115},
-         {-77138, 85025, -5183, -1, 18115},
-
-         {-77268, 85219, -5183, -1, 18115},
-         {-77268, 85410, -5183, -1, 18115},
-     },
-     {
-         /* Level 53 and Below */
-         {-75150, 87303, -5183, -1, 18116},
-         {-75150, 87175, -5183, -1, 18116},
-         {-75150, 87175, -5183, -1, 18116},
-         {-75150, 87303, -5183, -1, 18116},
-
-         {-74943, 87433, -5183, -1, 18116},
-         {-74767, 87433, -5183, -1, 18116},
-
-         {-74556, 87306, -5183, -1, 18116},
-         {-74556, 87184, -5183, -1, 18116},
-         {-74556, 87184, -5183, -1, 18116},
-         {-74556, 87306, -5183, -1, 18116},
-
-         {-74757, 86830, -5183, -1, 18116},
-         {-74927, 86830, -5183, -1, 18116},
-     },
-     {
-         /* Level 64 and Below */
-         {-80010, 88128, -5183, -1, 18117},
-         {-80113, 88066, -5183, -1, 18117},
-         {-80220, 88066, -5183, -1, 18117},
-         {-80359, 88128, -5183, -1, 18117},
-
-         {-80467, 88267, -5183, -1, 18117},
-         {-80467, 88436, -5183, -1, 18117},
-
-         {-80381, 88639, -5183, -1, 18117},
-         {-80278, 88577, -5183, -1, 18117},
-         {-80142, 88577, -5183, -1, 18117},
-         {-80028, 88639, -5183, -1, 18117},
-
-         {-79915, 88466, -5183, -1, 18117},
-         {-79915, 88322, -5183, -1, 18117},
-     },
-     {
-         /* No Level Limit */
-         {-80153, 84947, -5183, -1, 18118},
-         {-80003, 84962, -5183, -1, 18118},
-         {-79848, 84962, -5183, -1, 18118},
-         {-79742, 84947, -5183, -1, 18118},
-
-         {-79668, 84772, -5183, -1, 18118},
-         {-79668, 84619, -5183, -1, 18118},
-
-         {-79772, 84471, -5183, -1, 18118},
-         {-79888, 84414, -5183, -1, 18118},
-         {-80023, 84414, -5183, -1, 18118},
-         {-80166, 84471, -5183, -1, 18118},
-
-         {-80253, 84600, -5183, -1, 18118},
-         {-80253, 84780, -5183, -1, 18118},
-     }
-    };
-
-    //////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\
-
-    protected FestivalManager _managerInstance;
-    protected ScheduledFuture<?> _managerScheduledTask;
-
-    protected int _signsCycle = SevenSigns.getInstance().getCurrentCycle();
-    protected int _festivalCycle;
-    protected long _nextFestivalCycleStart;
-    protected long _nextFestivalStart;
-    protected boolean _festivalInitialized;
-    protected boolean _festivalInProgress;
-    protected List<Integer> _accumulatedBonuses;   // The total bonus available (in Ancient Adena)
-
-    boolean _noPartyRegister;
-    private L2Npc _dawnChatGuide;
-    private L2Npc _duskChatGuide;
-
-    protected Map<Integer, List<L2PcInstance>> _dawnFestivalParticipants;
-    protected Map<Integer, List<L2PcInstance>> _duskFestivalParticipants;
-
-    protected Map<Integer, List<L2PcInstance>> _dawnPreviousParticipants;
-    protected Map<Integer, List<L2PcInstance>> _duskPreviousParticipants;
-
-    private Map<Integer, Long> _dawnFestivalScores;
-    private Map<Integer, Long> _duskFestivalScores;
-
-    /**
-     * _festivalData is essentially an instance of the seven_signs_festival table and
-     * should be treated as such.
-     *
-     * Data is initially accessed by the related Seven Signs cycle, with _signsCycle representing
-     * data for the current round of Festivals.
-     *
-     * The actual table data is stored as a series of StatsSet constructs. These are accessed by
-     * the use of an offset based on the number of festivals, thus:
-     *
-     *  offset = FESTIVAL_COUNT + festivalId
-     *  (Data for Dawn is always accessed by offset > FESTIVAL_COUNT)
-     */
-    private Map<Integer, Map<Integer, StatsSet>> _festivalData;
-
-    public SevenSignsFestival()
-    {
-        _accumulatedBonuses = new FastList<Integer>();
-
-        _dawnFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
-        _dawnPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
-        _dawnFestivalScores = new FastMap<Integer, Long>();
-
-        _duskFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
-        _duskPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
-        _duskFestivalScores = new FastMap<Integer, Long>();
-
-        _festivalData = new FastMap<Integer, Map<Integer, StatsSet>>();
-
-        restoreFestivalData();
-
-        if (SevenSigns.getInstance().isSealValidationPeriod())
-        {
-            _log.info("SevenSignsFestival: Initialization bypassed due to Seal Validation in effect.");
-            return;
-        }
-
-        L2Spawn.addSpawnListener(this);
-        startFestivalManager();
-    }
-
-    public static SevenSignsFestival getInstance()
-    {
-        if (_instance == null)
-            _instance = new SevenSignsFestival();
-
-        return _instance;
-    }
-
-    /**
-     * Returns the associated name (level range) to a given festival ID.
-     *
-     * @param int festivalID
-     * @return String festivalName
-     */
-    public static final String getFestivalName(int festivalID)
-    {
-        String festivalName;
-
-        switch (festivalID)
-        {
-            case FESTIVAL_LEVEL_MAX_31:
-                festivalName = "Level 31 or lower";
-                break;
-            case FESTIVAL_LEVEL_MAX_42:
-                festivalName = "Level 42 or lower";
-                break;
-            case FESTIVAL_LEVEL_MAX_53:
-                festivalName = "Level 53 or lower";
-                break;
-            case FESTIVAL_LEVEL_MAX_64:
-                festivalName = "Level 64 or lower";
-                break;
-            default:
-                festivalName = "No Level Limit";
-            break;
-        }
-
-        return festivalName;
-    }
-
-    /**
-     * Returns the maximum allowed player level for the given festival type.
-     *
-     * @param festivalId
-     * @return int maxLevel
-     */
-    public static final int getMaxLevelForFestival(int festivalId)
-    {
-        int maxLevel = (Experience.MAX_LEVEL - 1);
-
-        switch (festivalId)
-        {
-            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_31:
-                maxLevel = 31;
-                break;
-            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_42:
-                maxLevel = 42;
-                break;
-            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_53:
-                maxLevel = 53;
-                break;
-            case SevenSignsFestival.FESTIVAL_LEVEL_MAX_64:
-                maxLevel = 64;
-                break;
-        }
-
-        return maxLevel;
-    }
-
-    /**
-     * Returns true if the monster ID given is of an archer/marksman type.
-     *
-     * @param npcId
-     * @return boolean isArcher
-     */
-    protected static final boolean isFestivalArcher(int npcId)
-    {
-        if (npcId < 18009 || npcId > 18108)
-            return false;
-
-        int identifier = npcId%10;
-        return (identifier == 4 || identifier == 9);
-    }
-
-    /**
-     * Returns true if the monster ID given is a festival chest.
-     *
-     * @param npcId
-     * @return boolean isChest
-     */
-    protected static final boolean isFestivalChest(int npcId)
-    {
-        return (npcId < 18109 || npcId > 18118);
-    }
-
-    /**
-     * Primarily used to terminate the Festival Manager, when the Seven Signs period changes.
-     *
-     * @return ScheduledFuture festManagerScheduler
-     */
-    protected final ScheduledFuture<?> getFestivalManagerSchedule()
-    {
-        if (_managerScheduledTask == null)
-            startFestivalManager();
-
-        return _managerScheduledTask;
-    }
-
-    /**
-     * Used to start the Festival Manager, if the current period is not Seal Validation.
-     */
-    protected void startFestivalManager()
-    {
-        // Start the Festival Manager for the first time after the server has started
-        // at the specified time, then invoke it automatically after every cycle.
-        FestivalManager fm = new FestivalManager();
-        setNextFestivalStart(Config.ALT_FESTIVAL_MANAGER_START + FESTIVAL_SIGNUP_TIME);
-        _managerScheduledTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(fm, Config.ALT_FESTIVAL_MANAGER_START, Config.ALT_FESTIVAL_CYCLE_LENGTH);
-
-        _log.info("SevenSignsFestival: The first Festival of Darkness cycle begins in " + (Config.ALT_FESTIVAL_MANAGER_START / 60000) + " minute(s).");
-    }
-
-    /**
-     * Restores saved festival data, basic settings from the properties file
-     * and past high score data from the database.
-     *
-     * @throws Exception
-     */
-    protected void restoreFestivalData()
-    {
-        Connection con = null;
-        PreparedStatement statement = null;
-        ResultSet rset = null;
-
-        if (Config.DEBUG)
-            _log.info("SevenSignsFestival: Restoring festival data. Current SS Cycle: " + _signsCycle);
-
-        try
-        {
-          con = L2DatabaseFactory.getInstance().getConnection();
-          statement = con.prepareStatement("SELECT festivalId, cabal, cycle, date, score, members " +
-              "FROM seven_signs_festival");
-          rset = statement.executeQuery();
-
-          while (rset.next())
-          {
-              int festivalCycle = rset.getInt("cycle");
-              int festivalId = rset.getInt("festivalId");
-              String cabal = rset.getString("cabal");
-
-              StatsSet festivalDat = new StatsSet();
-              festivalDat.set("festivalId", festivalId);
-              festivalDat.set("cabal", cabal);
-              festivalDat.set("cycle", festivalCycle);
-              festivalDat.set("date", rset.getString("date"));
-              festivalDat.set("score", rset.getInt("score"));
-              festivalDat.set("members", rset.getString("members"));
-
-              if (Config.DEBUG)
-                  _log.info("SevenSignsFestival: Loaded data from DB for (Cycle = " + festivalCycle + ", Oracle = " + cabal + ", Festival = "+ getFestivalName(festivalId));
-
-              if (cabal.equals("dawn"))
-                  festivalId += FESTIVAL_COUNT;
-
-              Map<Integer, StatsSet> tempData = _festivalData.get(festivalCycle);
-
-              if (tempData == null)
-                  tempData = new FastMap<Integer, StatsSet>();
-
-              tempData.put(festivalId, festivalDat);
-              _festivalData.put(festivalCycle, tempData);
-          }
-
-          rset.close();
-          statement.close();
-
-          String query = "SELECT festival_cycle, ";
-
-          for (int i = 0; i < FESTIVAL_COUNT-1; i++)
-
-              query += "accumulated_bonus" + String.valueOf(i) + ", ";
-          query += "accumulated_bonus" + String.valueOf(FESTIVAL_COUNT -1) + " ";
-          query += "FROM seven_signs_status WHERE id=0";
-
-          statement = con.prepareStatement(query);
-          rset = statement.executeQuery();
-
-          while (rset.next())
-          {
-              _festivalCycle = rset.getInt("festival_cycle");
-
-              for(int i = 0; i < FESTIVAL_COUNT; i++)
-                  _accumulatedBonuses.add(i, rset.getInt("accumulated_bonus" + String.valueOf(i)));
-          }
-
-          rset.close();
-          statement.close();
-          con.close();
-
-          if (Config.DEBUG)
-              _log.info("SevenSignsFestival: Loaded data from database.");
-        }
-        catch (SQLException e)
-        {
-            _log.severe("SevenSignsFestival: Failed to load configuration: " + e);
-        }
-        finally
-        {
-          try
-          {
-              rset.close();
-              statement.close();
-              con.close();
-          }
-          catch (SQLException e) {}
-        }
-     }
-
-    /**
-     * Stores current festival data, basic settings to the properties file
-     * and past high score data to the database.
-     *
-     * If updateSettings = true, then all Seven Signs data is updated in the database.
-     *
-     * @param updateSettings
-     * @throws Exception
-     */
-    public void saveFestivalData(boolean updateSettings)
-    {
-      Connection con = null;
-      PreparedStatement statement = null;
-
-      if (Config.DEBUG)
-            _log.info("SevenSignsFestival: Saving festival data to disk.");
-
-        try
-        {
-          con = L2DatabaseFactory.getInstance().getConnection();
-
-          for (Map<Integer, StatsSet> currCycleData : _festivalData.values())
-          {
-              for (StatsSet festivalDat : currCycleData.values())
-              {
-                  int festivalCycle = festivalDat.getInteger("cycle");
-                  int festivalId = festivalDat.getInteger("festivalId");
-                  String cabal = festivalDat.getString("cabal");
-
-                  // Try to update an existing record.
-                  statement = con.prepareStatement(
-                      "UPDATE seven_signs_festival SET date=?, score=?, members=? WHERE cycle=? AND cabal=? AND festivalId=?");
-                  statement.setLong(1, Long.valueOf(festivalDat.getString("date")));
-                  statement.setInt(2, festivalDat.getInteger("score"));
-                  statement.setString(3, festivalDat.getString("members"));
-                  statement.setInt(4, festivalCycle);
-                  statement.setString(5, cabal);
-                  statement.setInt(6, festivalId);
-
-                  // If there was no record to update, assume it doesn't exist and add a new one,
-                  // otherwise continue with the next record to store.
-                  if (statement.executeUpdate() > 0)
-                  {
-                      if (Config.DEBUG)
-                          _log.info("SevenSignsFestival: Updated data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal + ", FestID = " + festivalId + ")");
-
-                    statement.close();
-                      continue;
-                  }
-
-                  statement.close();
-
-                statement = con.prepareStatement(
-                      "INSERT INTO seven_signs_festival (festivalId, cabal, cycle, date, score, members) VALUES (?,?,?,?,?,?)");
-                  statement.setInt(1, festivalId);
-                  statement.setString(2, cabal);
-                  statement.setInt(3, festivalCycle);
-                  statement.setLong(4, Long.valueOf(festivalDat.getString("date")));
-                  statement.setInt(5, festivalDat.getInteger("score"));
-                  statement.setString(6, festivalDat.getString("members"));
-                  statement.execute();
-                  statement.close();
-
-                  if (Config.DEBUG)
-                      _log.info("SevenSignsFestival: Inserted data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal + ", FestID = " + festivalId + ")");
-              }
-          }
-
-          con.close();
-
-          // Updates Seven Signs DB data also, so call only if really necessary.
-          if (updateSettings)
-              SevenSigns.getInstance().saveSevenSignsData(null, true);
-        }
-        catch (SQLException e)
-        {
-          _log.severe("SevenSignsFestival: Failed to save configuration: " + e);
-        }
-        finally
-        {
-          try
-          {
-              statement.close();
-              con.close();
-          }
-          catch (Exception e) {}
-        }
-    }
-
-    /**
-     * If a clan member is a member of the highest-ranked party in the Festival of Darkness, 100 points are added per member
-     */
-    protected void rewardHighestRanked()
-    {
-      String[] partyMembers;
-      StatsSet overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_31);
-        if (overallData != null)
-      {
-        partyMembers = overallData.getString("members").split(",");
-        for (String partyMemberName : partyMembers)
-          addReputationPointsForPartyMemberClan(partyMemberName);
-      }
-
-      overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_42);
-      if (overallData != null)
-      {
-        partyMembers = overallData.getString("members").split(",");
-        for (String partyMemberName : partyMembers)
-          addReputationPointsForPartyMemberClan(partyMemberName);
-      }
-
-      overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_53);
-      if (overallData != null)
-      {
-        partyMembers = overallData.getString("members").split(",");
-        for (String partyMemberName : partyMembers)
-          addReputationPointsForPartyMemberClan(partyMemberName);
-      }
-
-      overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_64);
-      if (overallData != null)
-      {
-        partyMembers = overallData.getString("members").split(",");
-        for (String partyMemberName : partyMembers)
-          addReputationPointsForPartyMemberClan(partyMemberName);
-      }
-
-      overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_NONE);
-      if (overallData != null)
-      {
-        partyMembers = overallData.getString("members").split(",");
-        for (String partyMemberName : partyMembers)
-          addReputationPointsForPartyMemberClan(partyMemberName);
-      }
-    }
-
-    private void addReputationPointsForPartyMemberClan(String partyMemberName)
-    {
-      L2PcInstance player = L2World.getInstance().getPlayer(partyMemberName);
-    if (player != null)
-    {
-      if (player.getClan() != null)
-      {
-        player.getClan().setReputationScore(player.getClan().getReputationScore()+Config.FESTIVAL_WIN_POINTS, true);
-        SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_C1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
-                sm.addString(partyMemberName);
-                sm.addNumber(Config.FESTIVAL_WIN_POINTS);
-        player.getClan().broadcastToOnlineMembers(sm);
-      }
-    }
-    else
-    {
-      Connection con = null;
-
-          try
-          {
-            con = L2DatabaseFactory.getInstance().getConnection();
-            PreparedStatement statement = con.prepareStatement(GET_CLAN_NAME);
-            statement.setString(1, partyMemberName);
-            ResultSet rset = statement.executeQuery();
-            if (rset.next())
-            {
-              String clanName = rset.getString("clan_name");
-              if (clanName != null)
-              {
-                L2Clan clan = ClanTable.getInstance().getClanByName(clanName);
-                if (clan != null)
-                {
-                  clan.setReputationScore(clan.getReputationScore()+Config.FESTIVAL_WIN_POINTS, true);
-                  SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_C1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
-                          sm.addString(partyMemberName);
-                          sm.addNumber(Config.FESTIVAL_WIN_POINTS);
-                  clan.broadcastToOnlineMembers(sm);
-                }
-              }
-            }
-
-            rset.close();
-            statement.close();
-          }
-          catch (Exception e)
-          {
-            _log.warning("could not get clan name of " + partyMemberName + ": "+e);
-          }
-          finally
-          {
-            try { con.close(); } catch (Exception e) {}
-          }
-    }
-    }
-
-
-    /**
-     * Used to reset all festival data at the beginning of a new quest event period.
-     */
-    protected void resetFestivalData(boolean updateSettings)
-    {
-        _festivalCycle = 0;
-        _signsCycle = SevenSigns.getInstance().getCurrentCycle();
-
-        // Set all accumulated bonuses back to 0.
-        for (int i = 0; i < FESTIVAL_COUNT; i++)
-            _accumulatedBonuses.set(i, 0);
-
-        _dawnFestivalParticipants.clear();
-        _dawnPreviousParticipants.clear();
-        _dawnFestivalScores.clear();
-
-        _duskFestivalParticipants.clear();
-        _duskPreviousParticipants.clear();
-        _duskFestivalScores.clear();
-
-        // Set up a new data set for the current cycle of festivals
-        Map<Integer, StatsSet> newData = new FastMap<Integer, StatsSet>();
-
-        for (int i = 0; i < FESTIVAL_COUNT * 2; i++)
-        {
-            int festivalId = i;
-
-            if (i >= FESTIVAL_COUNT)
-                festivalId -= FESTIVAL_COUNT;
-
-            // Create a new StatsSet with "default" data for Dusk
-            StatsSet tempStats = new StatsSet();
-            tempStats.set("festivalId", festivalId);
-            tempStats.set("cycle", _signsCycle);
-            tempStats.set("date", "0");
-            tempStats.set("score", 0);
-            tempStats.set("members", "");
-
-            if (i >= FESTIVAL_COUNT)
-                tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DAWN));
-            else
-                tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DUSK));
-
-            newData.put(i, tempStats);
-        }
-
-        // Add the newly created cycle data to the existing festival data, and
-        // subsequently save it to the database.
-        _festivalData.put(_signsCycle, newData);
-
-        saveFestivalData(updateSettings);
-
-        // Remove any unused blood offerings from online players.
-        Collection<L2PcInstance> pls = L2World.getInstance().getAllPlayers().values();
-        //synchronized (L2World.getInstance().getAllPlayers())
-        {
-        	for (L2PcInstance onlinePlayer : pls)
-        	{
-        		try {
-        			L2ItemInstance bloodOfferings = onlinePlayer.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
-
-        			if (bloodOfferings != null)
-        				onlinePlayer.destroyItem("SevenSigns", bloodOfferings, null, false);
-        		} catch (NullPointerException e) {}
-        	}
-        }
-
-        _log.info("SevenSignsFestival: Reinitialized engine for next competition period.");
-    }
-
-
-    public final int getCurrentFestivalCycle()
-    {
-        return _festivalCycle;
-    }
-
-    public final boolean isFestivalInitialized()
-    {
-        return _festivalInitialized;
-    }
-
-    public final boolean isFestivalInProgress()
-    {
-        return _festivalInProgress;
-    }
-
-    public void setNextCycleStart()
-    {
-        _nextFestivalCycleStart = System.currentTimeMillis() + Config.ALT_FESTIVAL_CYCLE_LENGTH;
-    }
-
-    public void setNextFestivalStart(long milliFromNow)
-    {
-        _nextFestivalStart = System.currentTimeMillis() + milliFromNow;
-    }
-
-    public final int getMinsToNextCycle()
-    {
-        if (SevenSigns.getInstance().isSealValidationPeriod())
-            return -1;
-
-        return Math.round((_nextFestivalCycleStart - System.currentTimeMillis()) / 60000);
-    }
-
-    public final int getMinsToNextFestival()
-    {
-        if (SevenSigns.getInstance().isSealValidationPeriod())
-            return -1;
-
-        return Math.round((_nextFestivalStart - System.currentTimeMillis()) / 60000) + 1;
-    }
-
-    public final String getTimeToNextFestivalStr()
-    {
-        if (SevenSigns.getInstance().isSealValidationPeriod())
-            return "<font color=\"FF0000\">This is the Seal Validation period. Festivals will resume next week.</font>";
-
-        return "<font color=\"FF0000\">The next festival will begin in " + getMinsToNextFestival() + " minute(s).</font>";
-    }
-
-    /**
-     * Returns the current festival ID and oracle ID that the specified player is in,
-     * but will return the default of {-1, -1} if the player is not found as a participant.
-     *
-     * @param player
-     * @return int[] playerFestivalInfo
-     */
-    public final int[] getFestivalForPlayer(L2PcInstance player)
-    {
-        int[] playerFestivalInfo = {-1, -1};
-        int festivalId = 0;
-
-        while (festivalId < FESTIVAL_COUNT)
-        {
-            List<L2PcInstance> participants = _dawnFestivalParticipants.get(festivalId);
-
-            // If there are no participants in this festival, move on to the next.
-            if (participants != null && participants.contains(player))
-            {
-                playerFestivalInfo[0] = SevenSigns.CABAL_DAWN;
-                playerFestivalInfo[1] = festivalId;
-
-                return playerFestivalInfo;
-            }
-
-            participants = _duskFestivalParticipants.get(++festivalId);
-
-            if (participants != null && participants.contains(player))
-            {
-                playerFestivalInfo[0] = SevenSigns.CABAL_DUSK;
-                playerFestivalInfo[1] = festivalId;
-
-                return playerFestivalInfo;
-            }
-
-            festivalId++;
-        }
-
-        // Return default data if the player is not found as a participant.
-        return playerFestivalInfo;
-    }
-
-    public final boolean isParticipant(L2PcInstance player)
-    {
-        if (SevenSigns.getInstance().isSealValidationPeriod())
-            return false;
-
-        if (_managerInstance == null)
-            return false;
-
-        for (List<L2PcInstance> participants : _dawnFestivalParticipants.values())
-            if (participants.contains(player))
-                return true;
-
-        for (List<L2PcInstance> participants : _duskFestivalParticipants.values())
-            if (participants.contains(player))
-                return true;
-
-        return false;
-    }
-
-    public final List<L2PcInstance> getParticipants(int oracle, int festivalId)
-    {
-        if (oracle == SevenSigns.CABAL_DAWN)
-            return _dawnFestivalParticipants.get(festivalId);
-
-        return _duskFestivalParticipants.get(festivalId);
-    }
-
-    public final List<L2PcInstance> getPreviousParticipants(int oracle, int festivalId)
-    {
-        if (oracle == SevenSigns.CABAL_DAWN)
-            return _dawnPreviousParticipants.get(festivalId);
-
-        return _duskPreviousParticipants.get(festivalId);
-    }
-
-    public void setParticipants(int oracle, int festivalId, L2Party festivalParty)
-    {
-        List<L2PcInstance> participants = new FastList<L2PcInstance>();
-
-        if (festivalParty != null)
-        {
-            participants = festivalParty.getPartyMembers();
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: " + festivalParty.getPartyMembers().toString() +
-                    " have signed up to the " + SevenSigns.getCabalShortName(oracle) + " " + getFestivalName(festivalId) + " festival.");
-        }
-
-        if (oracle == SevenSigns.CABAL_DAWN)
-            _dawnFestivalParticipants.put(festivalId, participants);
-        else
-            _duskFestivalParticipants.put(festivalId, participants);
-    }
-
-    public void updateParticipants(L2PcInstance player, L2Party festivalParty)
-    {
-        if (!isParticipant(player))
-            return;
-
-        final int[] playerFestInfo = getFestivalForPlayer(player);
-        final int oracle = playerFestInfo[0];
-        final int festivalId = playerFestInfo[1];
-
-        if (festivalId > -1)
-        {
-            if (_festivalInitialized)
-            {
-                L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);
-
-                if (festivalParty == null) // leader has left
-                    for (L2PcInstance partyMember : getParticipants(oracle, festivalId))
-                        festivalInst.relocatePlayer(partyMember, true);
-                else
-                    festivalInst.relocatePlayer(player, true);
-            }
-
-            setParticipants(oracle, festivalId, festivalParty);
-
-            // Check on disconnect if min player in party
-            if (festivalParty != null && festivalParty.getMemberCount() < Config.ALT_FESTIVAL_MIN_PLAYER)
-            {
-              updateParticipants(player, null); // under minimum count
-              festivalParty.removePartyMember(player);
-            }
-        }
-    }
-
-    public final long getFinalScore(int oracle, int festivalId)
-    {
-        if (oracle == SevenSigns.CABAL_DAWN)
-            return _dawnFestivalScores.get(festivalId);
-
-        return _duskFestivalScores.get(festivalId);
-    }
-
-    public final int getHighestScore(int oracle, int festivalId)
-    {
-        return getHighestScoreData(oracle, festivalId).getInteger("score");
-    }
-
-    /**
-     * Returns a stats set containing the highest score <b>this cycle</b> for the
-     * the specified cabal and associated festival ID.
-     *
-     * @param oracle
-     * @param festivalId
-     * @return StatsSet festivalDat
-     */
-    public final StatsSet getHighestScoreData(int oracle, int festivalId)
-    {
-        int offsetId = festivalId;
-
-        if (oracle == SevenSigns.CABAL_DAWN)
-            offsetId += 5;
-
-        // Attempt to retrieve existing score data (if found), otherwise create a
-        // new blank data set and display a console warning.
-        StatsSet currData = null;
-
-        try
-        {
-            currData = _festivalData.get(_signsCycle).get(offsetId);
-        }
-        catch (Exception e)
-        {
-            currData = new StatsSet();
-            currData.set("score", 0);
-            currData.set("members", "");
-
-            if (Config.DEBUG)
-              _log.info("SevenSignsFestival: Data missing for " + SevenSigns.getCabalName(oracle) + ", FestivalID = " + festivalId + " (Current Cycle " + _signsCycle + ")");
-        }
-
-        return currData;
-    }
-
-    /**
-     * Returns a stats set containing the highest ever recorded
-     * score data for the specified festival.
-     *
-     * @param festivalId
-     * @return StatsSet result
-     */
-    public final StatsSet getOverallHighestScoreData(int festivalId)
-    {
-        StatsSet result = null;
-        int highestScore = 0;
-
-        for (Map<Integer, StatsSet> currCycleData : _festivalData.values())
-        {
-            for (StatsSet currFestData : currCycleData.values())
-            {
-                int currFestID = currFestData.getInteger("festivalId");
-                int festivalScore = currFestData.getInteger("score");
-
-                if (currFestID != festivalId)
-                    continue;
-
-                if (festivalScore > highestScore)
-                {
-                    highestScore = festivalScore;
-                    result = currFestData;
-                }
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Set the final score details for the last participants of the specified festival data.
-     * Returns <b>true</b> if the score is higher than that previously recorded <b>this cycle</b>.
-     *
-     * @param player
-     * @param oracle
-     * @param festivalId
-     * @param offeringScore
-     * @return boolean isHighestScore
-     */
-    public boolean setFinalScore(L2PcInstance player, int oracle, int festivalId, long offeringScore)
-    {
-        List<String> partyMembers;
-
-        int currDawnHighScore = getHighestScore(SevenSigns.CABAL_DAWN, festivalId);
-        int currDuskHighScore = getHighestScore(SevenSigns.CABAL_DUSK, festivalId);
-
-        int thisCabalHighScore = 0;
-        int otherCabalHighScore = 0;
-
-        if (oracle == SevenSigns.CABAL_DAWN)
-        {
-            thisCabalHighScore = currDawnHighScore;
-            otherCabalHighScore = currDuskHighScore;
-
-            _dawnFestivalScores.put(festivalId, offeringScore);
-        }
-        else
-        {
-            thisCabalHighScore = currDuskHighScore;
-            otherCabalHighScore = currDawnHighScore;
-
-            _duskFestivalScores.put(festivalId, offeringScore);
-        }
-
-        StatsSet currFestData = getHighestScoreData(oracle, festivalId);
-
-        // Check if this is the highest score for this level range so far for the player's cabal.
-        if (offeringScore > thisCabalHighScore)
-        {
-            // If the current score is greater than that for the other cabal,
-            // then they already have the points from this festival.
-            if (thisCabalHighScore < otherCabalHighScore)
-                return false;
-
-            partyMembers = new FastList<String>();
-            List<L2PcInstance> prevParticipants = getPreviousParticipants(oracle, festivalId);
-
-            // Record a string list of the party members involved.
-            for (L2PcInstance partyMember : prevParticipants)
-            {
-                try {
-                  partyMembers.add(partyMember.getName());
-                } catch (NullPointerException e) {}
-            }
-
-            // Update the highest scores and party list.
-            currFestData.set("date", String.valueOf(System.currentTimeMillis()));
-            currFestData.set("score", offeringScore);
-            currFestData.set("members", Util.implodeString(partyMembers, ","));
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: " + player.getName() + "'s party has the highest score (" +
-                    offeringScore + ") so far for " + SevenSigns.getCabalName(oracle) + " in " + getFestivalName(festivalId));
-
-            // Only add the score to the cabal's overall if it's higher than the other cabal's score.
-            if (offeringScore > otherCabalHighScore)
-            {
-                int contribPoints = FESTIVAL_LEVEL_SCORES[festivalId];
-
-                // Give this cabal the festival points, while deducting them from the other.
-                SevenSigns.getInstance().addFestivalScore(oracle, contribPoints);
-
-                if (Config.DEBUG)
-                    _log.info("SevenSignsFestival: This is the highest score overall so far for the " + getFestivalName(festivalId) + " festival!");
-            }
-
-            saveFestivalData(true);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    public final int getAccumulatedBonus(int festivalId)
-    {
-        return _accumulatedBonuses.get(festivalId);
-    }
-
-    public final int getTotalAccumulatedBonus()
-    {
-        int totalAccumBonus = 0;
-
-        for (int accumBonus : _accumulatedBonuses)
-            totalAccumBonus += accumBonus;
-
-        return totalAccumBonus;
-    }
-
-    public void addAccumulatedBonus(int festivalId, int stoneType, int stoneAmount)
-    {
-        int eachStoneBonus = 0;
-
-        switch (stoneType)
-        {
-            case SevenSigns.SEAL_STONE_BLUE_ID:
-                eachStoneBonus = SevenSigns.SEAL_STONE_BLUE_VALUE;
-                break;
-            case SevenSigns.SEAL_STONE_GREEN_ID:
-                eachStoneBonus = SevenSigns.SEAL_STONE_GREEN_VALUE;
-                break;
-            case SevenSigns.SEAL_STONE_RED_ID:
-                eachStoneBonus = SevenSigns.SEAL_STONE_RED_VALUE;
-                break;
-        }
-
-        int newTotalBonus = _accumulatedBonuses.get(festivalId) + (stoneAmount * eachStoneBonus);
-        _accumulatedBonuses.set(festivalId, newTotalBonus);
-    }
-
-    /**
-     * Calculate and return the proportion of the accumulated bonus for the festival
-     * where the player was in the winning party, if the winning party's cabal won the event.
-     *
-     * The accumulated bonus is then updated, with the player's share deducted.
-     *
-     * @param player
-     * @return playerBonus (the share of the bonus for the party)
-     */
-    public final int distribAccumulatedBonus(L2PcInstance player)
-    {
-        int playerBonus = 0;
-        String playerName = player.getName();
-        int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);
-
-        if (playerCabal != SevenSigns.getInstance().getCabalHighestScore())
-            return 0;
-
-        if (_festivalData.get(_signsCycle) != null)
-            for (StatsSet festivalData : _festivalData.get(_signsCycle).values())
-            {
-                if (festivalData.getString("members").indexOf(playerName) > -1)
-                {
-                    int festivalId = festivalData.getInteger("festivalId");
-                    int numPartyMembers = festivalData.getString("members").split(",").length;
-                    int totalAccumBonus = _accumulatedBonuses.get(festivalId);
-
-                    playerBonus = totalAccumBonus / numPartyMembers;
-                    _accumulatedBonuses.set(festivalId, totalAccumBonus - playerBonus);
-                    break;
-                }
-            }
-
-        return playerBonus;
-    }
-
-    /**
-     * Used to send a "shout" message to all players currently present in an Oracle.
-     * Primarily used for Festival Guide and Witch related speech.
-     *
-     * @param senderName
-     * @param message
-     */
-    public void sendMessageToAll(String senderName, String message)
-    {
-        if (_dawnChatGuide == null || _duskChatGuide == null)
-            return;
-
-        CreatureSay cs = new CreatureSay(_dawnChatGuide.getObjectId(), Say2.SHOUT, senderName, message);
-        _dawnChatGuide.broadcastPacket(cs);
-
-        cs = new CreatureSay(_duskChatGuide.getObjectId(), Say2.SHOUT, senderName, message);
-        _duskChatGuide.broadcastPacket(cs);
-    }
-
-    /**
-     * Basically a wrapper-call to signal to increase the challenge of the specified festival.
-     *
-     * @param oracle
-     * @param festivalId
-     * @return boolean isChalIncreased
-     */
-    public final boolean increaseChallenge(int oracle, int festivalId)
-    {
-        L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);
-
-        return festivalInst.increaseChallenge();
-    }
-
-    /**
-     * Used with the SpawnListener, to update the required "chat guide" instances,
-     * for use with announcements in the oracles.
-     *
-     * @param npc
-     */
-    public void npcSpawned(L2Npc npc)
-    {
-        if (npc == null)
-            return;
-
-        int npcId = npc.getNpcId();
-
-        // If the spawned NPC ID matches the ones we need, assign their instances.
-        if (npcId == 31127)
-        {
-            if (Config.DEBUG)
-                _log.config("SevenSignsFestival: Instance found for NPC ID 31127 (" + npc.getObjectId() + ").");
-
-            _dawnChatGuide = npc;
-        }
-
-        if (npcId == 31137)
-        {
-            if (Config.DEBUG)
-                _log.config("SevenSignsFestival: Instance found for NPC ID 31137 (" + npc.getObjectId() + ").");
-
-            _duskChatGuide = npc;
-        }
-    }
-
-
-    /**
-     * The FestivalManager class is the main runner of all the festivals.
-     * It is used for easier integration and management of all running festivals.
-     *
-     * @author Tempy
-     */
-    private class FestivalManager implements Runnable
-    {
-        protected Map<Integer, L2DarknessFestival> _festivalInstances;
-
-        public FestivalManager()
-        {
-            _festivalInstances = new FastMap<Integer, L2DarknessFestival>();
-            _managerInstance = this;
-
-            // Increment the cycle counter.
-            _festivalCycle++;
-
-            // Set the next start timers.
-            setNextCycleStart();
-            setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
-        }
-
-        public synchronized void run()
-        {
-            // The manager shouldn't be running if Seal Validation is in effect.
-            if (SevenSigns.getInstance().isSealValidationPeriod())
-                return;
-
-            // 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)
-                return;
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Festival manager initialized. Those wishing to participate have " + getMinsToNextFestival() + " minute(s) to sign up.");
-
-            sendMessageToAll("Festival Guide", "The main event will start in " + getMinsToNextFestival() + " minutes. Please register now.");
-
-            // Stand by until the allowed signup period has elapsed.
-            try {
-                wait(FESTIVAL_SIGNUP_TIME);
-            }
-            catch (InterruptedException e) { }
-
-            // Clear past participants, they can no longer register their score if not done so already.
-            _dawnPreviousParticipants.clear();
-            _duskPreviousParticipants.clear();
-
-            // Get rid of random monsters that avoided deletion after last festival
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-              festivalInst.unspawnMobs();
-
-            // Start only if participants signed up
-            _noPartyRegister = true;
-
-            while (_noPartyRegister)
-            {
-              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);
-                  for (L2DarknessFestival festivalInst : _festivalInstances.values())
-                  {
-                    if (!festivalInst._npcInsts.isEmpty())
-                    {
-                      festivalInst.unspawnMobs();
-                    }
-                  }
-                }
-                catch (InterruptedException e)
-                {
-                }
-              }
-              else
-              {
-                _noPartyRegister = false;
-              }
-            }
-
-            /* INITIATION */
-            // Set the festival timer to 0, as it is just beginning.
-            long elapsedTime = 0;
-
-            // Create the instances for the festivals in both Oracles,
-            // but only if they have participants signed up for them.
-            for (int i = 0; i < FESTIVAL_COUNT; i++)
-            {
-                if (_duskFestivalParticipants.get(i) != null)
-                    _festivalInstances.put(10 + i, new L2DarknessFestival(SevenSigns.CABAL_DUSK, i));
-
-                if (_dawnFestivalParticipants.get(i) != null)
-                    _festivalInstances.put(20 + i, new L2DarknessFestival(SevenSigns.CABAL_DAWN, i));
-            }
-
-            // Prevent future signups while festival is in progress.
-            _festivalInitialized = true;
-
-            setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH);
-            sendMessageToAll("Festival Guide", "The main event is now starting.");
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: The current set of festivals will begin in " + (Config.ALT_FESTIVAL_FIRST_SPAWN / 60000) + " minute(s).");
-
-            // Stand by for a short length of time before starting the festival.
-            try {
-                wait(Config.ALT_FESTIVAL_FIRST_SPAWN);
-            }
-            catch (InterruptedException e) { }
-
-            elapsedTime = Config.ALT_FESTIVAL_FIRST_SPAWN;
-
-            // Participants can now opt to increase the challenge, if desired.
-            _festivalInProgress = true;
-
-
-            /* PROPOGATION */
-            // Sequentially set all festivals to begin, spawn the Festival Witch and notify participants.
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-            {
-                festivalInst.festivalStart();
-                festivalInst.sendMessageToParticipants("The festival is about to begin!");
-            }
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Each of the festivals will end in " + (Config.ALT_FESTIVAL_LENGTH / 60000) + " minutes. New participants can signup then.");
-
-
-            // 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);
-            }
-            catch (InterruptedException e) { }
-
-            elapsedTime += Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN;
-
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-                festivalInst.moveMonstersToCenter();
-
-
-            // Stand by until the time comes for the second spawn.
-            try {
-                wait(Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM);
-            }
-            catch (InterruptedException e) { }
-
-            // Spawn an extra set of monsters (archers) on the free platforms with
-            // a faster respawn when killed.
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-            {
-                festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN / 2, 2);
-                festivalInst.sendMessageToParticipants("The festival will end in " + ((Config.ALT_FESTIVAL_LENGTH - Config.ALT_FESTIVAL_SECOND_SPAWN) / 60000) + " minute(s).");
-            }
-
-            elapsedTime += Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM;
-
-
-            // 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);
-            }
-            catch (InterruptedException e) { }
-
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-                festivalInst.moveMonstersToCenter();
-
-            elapsedTime += Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN;
-
-
-            // Stand by until the time comes for the chests to be spawned.
-            try {
-                wait(Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM);
-            }
-            catch (InterruptedException e) { }
-
-            // Spawn the festival chests, which enable the team to gain greater rewards
-            // for each chest they kill.
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-            {
-                festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 3);
-                festivalInst.sendMessageToParticipants("The chests have spawned! Be quick, the festival will end soon.");
-            }
-
-            elapsedTime += Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM;
-
-            // Stand by and wait until it's time to end the festival.
-            try {
-                wait(Config.ALT_FESTIVAL_LENGTH - elapsedTime);
-            }
-            catch (InterruptedException e) { }
-
-            // Participants can no longer opt to increase the challenge, as the festival will soon close.
-            _festivalInProgress = false;
-
-
-            /* TERMINATION */
-            // Sequentially begin the ending sequence for all running festivals.
-            for (L2DarknessFestival festivalInst : _festivalInstances.values())
-                festivalInst.festivalEnd();
-
-            // Clear the participants list for the next round of signups.
-            _dawnFestivalParticipants.clear();
-            _duskFestivalParticipants.clear();
-
-            // Allow signups for the next festival cycle.
-            _festivalInitialized = false;
-
-            sendMessageToAll("Festival Witch", "That will do! I'll move you to the outside soon.");
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: The next set of festivals begin in " + getMinsToNextFestival() + " minute(s).");
-        }
-
-        /**
-         * Returns the running instance of a festival for the given Oracle and festivalID.
-         * <BR>
-         * A <B>null</B> value is returned if there are no participants in that festival.
-         *
-         * @param oracle
-         * @param festivalId
-         * @return L2DarknessFestival festivalInst
-         */
-        public final L2DarknessFestival getFestivalInstance(int oracle, int festivalId)
-        {
-            if (!isFestivalInitialized())
-                return null;
-
-            /* Compute the offset if a Dusk instance is required.
-             *
-             * ID:      0   1   2   3   4
-             * Dusk 1:  10  11  12  13  14
-             * Dawn 2:  20  21  22  23  24
-             */
-
-            festivalId += (oracle == SevenSigns.CABAL_DUSK) ? 10 : 20;
-            return _festivalInstances.get(festivalId);
-        }
-
-        /**
-         * Returns the number of currently running festivals <b>WITH</b> participants.
-         *
-         * @return int Count
-         */
-        public final int getInstanceCount()
-        {
-            return _festivalInstances.size();
-        }
-    }
-
-
-    /**
-     * Each running festival is represented by an L2DarknessFestival class.
-     * It contains all the spawn information and data for the running festival.
-     *
-     * All festivals are managed by the FestivalManager class, which must be initialized first.
-     *
-     * @author Tempy
-     */
-    private class L2DarknessFestival
-    {
-        protected final int _cabal;
-        protected final int _levelRange;
-        protected boolean _challengeIncreased;
-
-        private FestivalSpawn _startLocation;
-        private FestivalSpawn _witchSpawn;
-
-        private L2Npc _witchInst;
-        List<L2FestivalMonsterInstance> _npcInsts;
-
-        private List<L2PcInstance> _participants;
-        private Map<L2PcInstance, FestivalSpawn> _originalLocations;
-
-        protected L2DarknessFestival(int cabal, int levelRange)
-        {
-            _cabal = cabal;
-            _levelRange = levelRange;
-            _originalLocations = new FastMap<L2PcInstance, FestivalSpawn>();
-            _npcInsts = new FastList<L2FestivalMonsterInstance>();
-
-            if (cabal == SevenSigns.CABAL_DAWN)
-            {
-                _participants = _dawnFestivalParticipants.get(levelRange);
-                _witchSpawn = new FestivalSpawn(FESTIVAL_DAWN_WITCH_SPAWNS[levelRange]);
-                _startLocation = new FestivalSpawn(FESTIVAL_DAWN_PLAYER_SPAWNS[levelRange]);
-            }
-            else
-            {
-                _participants = _duskFestivalParticipants.get(levelRange);
-                _witchSpawn = new FestivalSpawn(FESTIVAL_DUSK_WITCH_SPAWNS[levelRange]);
-                _startLocation = new FestivalSpawn(FESTIVAL_DUSK_PLAYER_SPAWNS[levelRange]);
-            }
-
-            // FOR TESTING!
-            if (_participants == null)
-                _participants = new FastList<L2PcInstance>();
-
-            festivalInit();
-        }
-
-        protected void festivalInit()
-        {
-            boolean isPositive;
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Initializing festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
-
-            // Teleport all players to arena and notify them.
-            if (!_participants.isEmpty())
-            {
-              try {
-               for (L2PcInstance participant : _participants)
-                 {
-                    _originalLocations.put(participant, new FestivalSpawn(participant.getX(), participant.getY(), participant.getZ(), participant.getHeading()));
-
-                    // Randomize the spawn point around the specific centerpoint for each player.
-                    int x = _startLocation._x;
-                    int y = _startLocation._y;
-
-                    isPositive = (Rnd.nextInt(2) == 1);
-
-                    if (isPositive)
-                    {
-                        x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
-                        y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
-                    }
-                    else
-                    {
-                        x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
-                        y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
-                    }
-
-                    participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-                    participant.teleToLocation(x, y, _startLocation._z, true);
-
-                    // Remove all buffs from all participants on entry. Works like the skill Cancel.
-                    participant.stopAllEffects();
-
-                    // Remove any stray blood offerings in inventory
-                    L2ItemInstance bloodOfferings = participant.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
-                    if (bloodOfferings != null)
-                      participant.destroyItem("SevenSigns", bloodOfferings, null, true);
-                 }
-              } catch (NullPointerException e)
-              {
-                // deleteMe handling should teleport party out in case of disconnect
-              }
-            }
-
-            L2NpcTemplate witchTemplate = NpcTable.getInstance().getTemplate(_witchSpawn._npcId);
-
-            // Spawn the festival witch for this arena
-            try
-            {
-                L2Spawn npcSpawn = new L2Spawn(witchTemplate);
-
-                npcSpawn.setLocx(_witchSpawn._x);
-                npcSpawn.setLocy(_witchSpawn._y);
-                npcSpawn.setLocz(_witchSpawn._z);
-                npcSpawn.setHeading(_witchSpawn._heading);
-                npcSpawn.setAmount(1);
-                npcSpawn.setRespawnDelay(1);
-
-                // Needed as doSpawn() is required to be called also for the NpcInstance it returns.
-                npcSpawn.startRespawn();
-
-                SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
-                _witchInst = npcSpawn.doSpawn();
-
-                if (Config.DEBUG)
-                    _log.fine("SevenSignsFestival: Spawned the Festival Witch " + npcSpawn.getNpcid() + " at " + _witchSpawn._x + " " + _witchSpawn._y + " " + _witchSpawn._z);
-            }
-            catch (Exception e)
-            {
-                _log.warning("SevenSignsFestival: Error while spawning Festival Witch ID " + _witchSpawn._npcId + ": " + e);
-            }
-
-            // Make it appear as though the Witch has apparated there.
-            MagicSkillUse msu = new MagicSkillUse(_witchInst, _witchInst, 2003, 1, 1, 0);
-            _witchInst.broadcastPacket(msu);
-
-            // And another one...:D
-            msu = new MagicSkillUse(_witchInst, _witchInst, 2133, 1, 1, 0);
-            _witchInst.broadcastPacket(msu);
-
-            // Send a message to all participants from the witch.
-            sendMessageToParticipants("The festival will begin in 2 minutes.");
-        }
-
-        protected void festivalStart()
-        {
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Starting festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
-
-            spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 0);
-        }
-
-        protected void moveMonstersToCenter()
-        {
-            boolean isPositive;
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Moving spawns to arena center for festival " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
-
-            for (L2FestivalMonsterInstance festivalMob : _npcInsts)
-            {
-                if (festivalMob.isDead())
-                    continue;
-
-                // Only move monsters that are idle or doing their usual functions.
-                CtrlIntention currIntention = festivalMob.getAI().getIntention();
-
-                if (currIntention != CtrlIntention.AI_INTENTION_IDLE && currIntention != CtrlIntention.AI_INTENTION_ACTIVE)
-                    continue;
-
-                int x = _startLocation._x;
-                int y = _startLocation._y;
-
-                /*
-                 * Random X and Y coords around the player start location, up to half of the
-                 * maximum allowed offset are generated to prevent the mobs from all moving
-                 * to the exact same place.
-                 */
-                isPositive = (Rnd.nextInt(2) == 1);
-
-                if (isPositive)
-                {
-                    x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
-                    y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
-                }
-                else
-                {
-                    x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
-                    y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
-                }
-
-                L2CharPosition moveTo = new L2CharPosition(x, y, _startLocation._z, Rnd.nextInt(65536));
-
-                festivalMob.setRunning();
-                festivalMob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, moveTo);
-            }
-        }
-
-        public void setSpawnRate(int respawnDelay)
-        {
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Modifying spawn rate of festival mobs to " + respawnDelay + " ms for festival " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
-
-            for (L2FestivalMonsterInstance monsterInst : _npcInsts)
-                monsterInst.getSpawn().setRespawnDelay(respawnDelay);
-        }
-
-        /**
-         * Used to spawn monsters unique to the festival.
-         * <BR>
-         * Valid SpawnTypes:<BR>
-         * 0 - All Primary Monsters (starting monsters)
-         * <BR>
-         * 1 - Same as 0, but without archers/marksmen. (used for challenge increase)
-         * <BR>
-         * 2 - Secondary Monsters (archers)
-         * <BR>
-         * 3 - Festival Chests
-         *
-         * @param respawnDelay
-         * @param spawnType
-         */
-        protected void spawnFestivalMonsters(int respawnDelay, int spawnType)
-        {
-            int[][] _npcSpawns = null;
-
-            switch (spawnType)
-            {
-                case 0:
-                case 1:
-                    _npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_PRIMARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_PRIMARY_SPAWNS[_levelRange];
-                    break;
-                case 2:
-                    _npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_SECONDARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_SECONDARY_SPAWNS[_levelRange];
-                    break;
-                case 3:
-                    _npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_CHEST_SPAWNS[_levelRange] : FESTIVAL_DUSK_CHEST_SPAWNS[_levelRange];
-                    break;
-            }
-
-            for (int i = 0; i < _npcSpawns.length; i++)
-            {
-                FestivalSpawn currSpawn = new FestivalSpawn(_npcSpawns[i]);
-
-                // Only spawn archers/marksmen if specified to do so.
-                if (spawnType == 1 && isFestivalArcher(currSpawn._npcId))
-                    continue;
-
-                L2NpcTemplate npcTemplate = NpcTable.getInstance().getTemplate(currSpawn._npcId);
-
-                try
-                {
-                    L2Spawn npcSpawn = new L2Spawn(npcTemplate);
-
-                    npcSpawn.setLocx(currSpawn._x);
-                    npcSpawn.setLocy(currSpawn._y);
-                    npcSpawn.setLocz(currSpawn._z);
-                    npcSpawn.setHeading(Rnd.nextInt(65536));
-                    npcSpawn.setAmount(1);
-                    npcSpawn.setRespawnDelay(respawnDelay);
-
-                    // Needed as doSpawn() is required to be called also for the NpcInstance it returns.
-                    npcSpawn.startRespawn();
-
-                    SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
-                    L2FestivalMonsterInstance festivalMob = (L2FestivalMonsterInstance)npcSpawn.doSpawn();
-
-                    // Set the offering bonus to 2x or 5x the amount per kill,
-                    // if this spawn is part of an increased challenge or is a festival chest.
-                    if (spawnType == 1)
-                        festivalMob.setOfferingBonus(2);
-                    else if (spawnType == 3)
-                        festivalMob.setOfferingBonus(5);
-
-                    _npcInsts.add(festivalMob);
-
-                    if (Config.DEBUG)
-                        _log.fine("SevenSignsFestival: Spawned NPC ID " + currSpawn._npcId + " at " + currSpawn._x + " " + currSpawn._y + " " + currSpawn._z);
-                }
-                catch (Exception e)
-                {
-                    _log.warning("SevenSignsFestival: Error while spawning NPC ID " + currSpawn._npcId + ": " + e);
-                }
-            }
-        }
-
-        protected boolean increaseChallenge()
-        {
-            if (_challengeIncreased)
-                return false;
-
-            // Set this flag to true to make sure that this can only be done once.
-            _challengeIncreased = true;
-
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: " + _participants.get(0).getName() + "'s team have opted to increase the festival challenge!");
-
-            // Spawn more festival monsters, but this time with a twist.
-            spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 1);
-            return true;
-        }
-
-        public void sendMessageToParticipants(String message)
-        {
-            if (!_participants.isEmpty())
-            {
-                CreatureSay cs = new CreatureSay(_witchInst.getObjectId(), Say2.ALL, "Festival Witch", message);
-
-                for (L2PcInstance participant : _participants)
-                {
-                  try {
-                    participant.sendPacket(cs);
-                  } catch (NullPointerException e) { }
-                }
-            }
-        }
-
-        protected void festivalEnd()
-        {
-            if (Config.DEBUG)
-                _log.info("SevenSignsFestival: Ending festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
-
-            if (!_participants.isEmpty())
-            {
-                for (L2PcInstance participant : _participants)
-                {
-                    try {
-                      relocatePlayer(participant, false);
-                      participant.sendMessage("The festival has ended. Your party leader must now register your score before the next festival takes place.");
-                    } catch (NullPointerException e) { }
-                }
-
-                if (_cabal == SevenSigns.CABAL_DAWN)
-                    _dawnPreviousParticipants.put(_levelRange, _participants);
-                else
-                    _duskPreviousParticipants.put(_levelRange, _participants);
-            }
-            _participants = null;
-
-            unspawnMobs();
-        }
-
-        protected void unspawnMobs()
-        {
-          // Delete all the NPCs in the current festival arena.
-          if (_witchInst != null)
-          {
-            _witchInst.getSpawn().stopRespawn();
-            _witchInst.deleteMe();
-          }
-
-          if (_npcInsts != null)
-              for (L2FestivalMonsterInstance monsterInst : _npcInsts)
-                if (monsterInst != null)
-                {
-                  monsterInst.getSpawn().stopRespawn();
-                  monsterInst.deleteMe();
-                }
-        }
-
-        public void relocatePlayer(L2PcInstance participant, boolean isRemoving)
-        {
-            try
-            {
-                FestivalSpawn origPosition = _originalLocations.get(participant);
-
-                if (isRemoving) _originalLocations.remove(participant);
-
-                participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-                participant.teleToLocation(origPosition._x, origPosition._y, origPosition._z, true);
-                participant.sendMessage("You have been removed from the festival arena.");
-            }
-            catch (Exception e)
-            {
-                // If an exception occurs, just move the player to the nearest town.
-                try {
-                  participant.teleToLocation(MapRegionTable.TeleportWhereType.Town);
-                  participant.sendMessage("You have been removed from the festival arena.");
-                } catch (NullPointerException e2) {}
-            }
-        }
-    }
-
-    private class FestivalSpawn
-    {
-        protected final int _x;
-        protected final int _y;
-        protected final int _z;
-        protected final int _heading;
-        protected final int _npcId;
-
-        protected FestivalSpawn(int x, int y, int z, int heading)
-        {
-            _x = x;
-            _y = y;
-            _z = z;
-
-            // Generate a random heading if no positive one given.
-            _heading = (heading < 0) ? Rnd.nextInt(65536) : heading;
-
-            _npcId = -1;
-        }
-
-        protected FestivalSpawn(int[] spawnData)
-        {
-            _x = spawnData[0];
-            _y = spawnData[1];
-            _z = spawnData[2];
-
-            _heading = (spawnData[3] < 0) ? Rnd.nextInt(65536) : spawnData[3];
-
-            if (spawnData.length > 4)
-                _npcId = spawnData[4];
-            else
-                _npcId = -1;
-        }
-    }
+	protected static final Logger _log = Logger.getLogger(SevenSignsFestival.class.getName());
+	
+	private static final String GET_CLAN_NAME = "SELECT clan_name FROM clan_data WHERE clan_id = (SELECT clanid FROM characters WHERE char_name = ?)";
+	
+	/**
+	 * These length settings are important! :)
+	 * All times are relative to the ELAPSED time (in ms) since a festival begins.
+	 *
+	 * Festival manager start is the time after the server starts to begin the first
+	 * festival cycle.
+	 *
+	 * The cycle length should ideally be at least 2x longer than the festival length.
+	 * This allows ample time for players to sign-up to participate in the festival.
+	 *
+	 * The intermission is the time between the festival participants being moved
+	 * to the "arenas" and the spawning of the first set of mobs.
+	 *
+	 * The monster swarm time is the time before the monsters swarm to the center of the arena,
+	 * after they are spawned.
+	 *
+	 * 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;
+	
+	// Key Constants \\
+	private static final int FESTIVAL_MAX_OFFSET_X = 230;
+	private static final int FESTIVAL_MAX_OFFSET_Y = 230;
+	private static final int FESTIVAL_DEFAULT_RESPAWN = 60; // Specify in seconds!
+	
+	public static final int FESTIVAL_COUNT = 5;
+	public static final int FESTIVAL_LEVEL_MAX_31 = 0;
+	public static final int FESTIVAL_LEVEL_MAX_42 = 1;
+	public static final int FESTIVAL_LEVEL_MAX_53 = 2;
+	public static final int FESTIVAL_LEVEL_MAX_64 = 3;
+	public static final int FESTIVAL_LEVEL_MAX_NONE = 4;
+	public static final int[] FESTIVAL_LEVEL_SCORES = { 60, 70, 100, 120, 150 }; // 500 maximum possible score
+	
+	public static final int FESTIVAL_OFFERING_ID = 5901;
+	public static final int FESTIVAL_OFFERING_VALUE = 5;
+	
+	//////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\
+	/*
+	* The following contains all the necessary spawn data for:
+	* - Player Start Locations
+	* - Witches
+	* - Monsters
+	* - Chests
+	*
+	* All data is given by: X, Y, Z (coords), Heading, NPC ID (if necessary)
+	* This may be moved externally in time, but the data should not change.
+	*/
+	public static final int[][] FESTIVAL_DAWN_PLAYER_SPAWNS = { { -79187, 113186, -4895, 0 }, // 31 and below
+			{ -75918, 110137, -4895, 0 }, // 42 and below
+			{ -73835, 111969, -4895, 0 }, // 53 and below
+			{ -76170, 113804, -4895, 0 }, // 64 and below
+			{ -78927, 109528, -4895, 0 } // No level limit
+	};
+	
+	public static final int[][] FESTIVAL_DUSK_PLAYER_SPAWNS = { { -77200, 88966, -5151, 0 }, // 31 and below
+			{ -76941, 85307, -5151, 0 }, // 42 and below
+			{ -74855, 87135, -5151, 0 }, // 53 and below
+			{ -80208, 88222, -5151, 0 }, // 64 and below
+			{ -79954, 84697, -5151, 0 } // No level limit
+	};
+	
+	protected static final int[][] FESTIVAL_DAWN_WITCH_SPAWNS = { { -79183, 113052, -4891, 0, 31132 }, // 31 and below
+			{ -75916, 110270, -4891, 0, 31133 }, // 42 and below
+			{ -73979, 111970, -4891, 0, 31134 }, // 53 and below
+			{ -76174, 113663, -4891, 0, 31135 }, // 64 and below
+			{ -78930, 109664, -4891, 0, 31136 } // No level limit
+	};
+	
+	protected static final int[][] FESTIVAL_DUSK_WITCH_SPAWNS = { { -77199, 88830, -5147, 0, 31142 }, // 31 and below
+			{ -76942, 85438, -5147, 0, 31143 }, // 42 and below
+			{ -74990, 87135, -5147, 0, 31144 }, // 53 and below
+			{ -80207, 88222, -5147, 0, 31145 }, // 64 and below
+			{ -79952, 84833, -5147, 0, 31146 } // No level limit
+	};
+	
+	protected static final int[][][] FESTIVAL_DAWN_PRIMARY_SPAWNS = {
+			{
+				/* Level 31 and Below - Offering of the Branded */
+				{ -78537, 113839, -4895, -1, 18009 },
+				{ -78466, 113852, -4895, -1, 18010 },
+				{ -78509, 113899, -4895, -1, 18010 },
+				
+				{ -78481, 112557, -4895, -1, 18009 },
+				{ -78559, 112504, -4895, -1, 18010 },
+				{ -78489, 112494, -4895, -1, 18010 },
+				
+				{ -79803, 112543, -4895, -1, 18012 },
+				{ -79854, 112492, -4895, -1, 18013 },
+				{ -79886, 112557, -4895, -1, 18014 },
+				
+				{ -79821, 113811, -4895, -1, 18015 },
+				{ -79857, 113896, -4895, -1, 18017 },
+				{ -79878, 113816, -4895, -1, 18018 },
+				
+				// Archers and Marksmen \\
+				{ -79190, 113660, -4895, -1, 18011 },
+				{ -78710, 113188, -4895, -1, 18011 },
+				{ -79190, 112730, -4895, -1, 18016 },
+				{ -79656, 113188, -4895, -1, 18016 }
+			},
+			{
+				/* Level 42 and Below - Apostate Offering */
+				{ -76558, 110784, -4895, -1, 18019 },
+				{ -76607, 110815, -4895, -1, 18020 }, // South West
+				{ -76559, 110820, -4895, -1, 18020 },
+				
+				{ -75277, 110792, -4895, -1, 18019 },
+				{ -75225, 110801, -4895, -1, 18020 }, // South East
+				{ -75262, 110832, -4895, -1, 18020 },
+				
+				{ -75249, 109441, -4895, -1, 18022 },
+				{ -75278, 109495, -4895, -1, 18023 }, // North East
+				{ -75223, 109489, -4895, -1, 18024 },
+				
+				{ -76556, 109490, -4895, -1, 18025 },
+				{ -76607, 109469, -4895, -1, 18027 }, // North West
+				{ -76561, 109450, -4895, -1, 18028 },
+				// Archers and Marksmen \\
+				{ -76399, 110144, -4895, -1, 18021 },
+				{ -75912, 110606, -4895, -1, 18021 },
+				{ -75444, 110144, -4895, -1, 18026 },
+				{ -75930, 109665, -4895, -1, 18026 }
+			},
+			{
+				/* Level 53 and Below - Witch's Offering */
+				{ -73184, 111319, -4895, -1, 18029 },
+				{ -73135, 111294, -4895, -1, 18030 }, // South West
+				{ -73185, 111281, -4895, -1, 18030 },
+				
+				{ -74477, 111321, -4895, -1, 18029 },
+				{ -74523, 111293, -4895, -1, 18030 }, // South East
+				{ -74481, 111280, -4895, -1, 18030 },
+				
+				{ -74489, 112604, -4895, -1, 18032 },
+				{ -74491, 112660, -4895, -1, 18033 }, // North East
+				{ -74527, 112629, -4895, -1, 18034 },
+				
+				{ -73197, 112621, -4895, -1, 18035 },
+				{ -73142, 112631, -4895, -1, 18037 }, // North West
+				{ -73182, 112656, -4895, -1, 18038 },
+				
+				// Archers and Marksmen \\
+				{ -73834, 112430, -4895, -1, 18031 },
+				{ -74299, 111959, -4895, -1, 18031 },
+				{ -73841, 111491, -4895, -1, 18036 },
+				{ -73363, 111959, -4895, -1, 18036 }
+			},
+			{
+				/* Level 64 and Below - Dark Omen Offering */
+				{ -75543, 114461, -4895, -1, 18039 },
+				{ -75514, 114493, -4895, -1, 18040 }, // South West
+				{ -75488, 114456, -4895, -1, 18040 },
+				
+				{ -75521, 113158, -4895, -1, 18039 },
+				{ -75504, 113110, -4895, -1, 18040 }, // South East
+				{ -75489, 113142, -4895, -1, 18040 },
+				
+				{ -76809, 113143, -4895, -1, 18042 },
+				{ -76860, 113138, -4895, -1, 18043 }, // North East
+				{ -76831, 113112, -4895, -1, 18044 },
+				
+				{ -76831, 114441, -4895, -1, 18045 },
+				{ -76840, 114490, -4895, -1, 18047 }, // North West
+				{ -76864, 114455, -4895, -1, 18048 },
+				
+				// Archers and Marksmen \\
+				{ -75703, 113797, -4895, -1, 18041 },
+				{ -76180, 114263, -4895, -1, 18041 },
+				{ -76639, 113797, -4895, -1, 18046 },
+				{ -76180, 113337, -4895, -1, 18046 }
+			},
+			{
+				/* No Level Limit - Offering of Forbidden Path */
+				{ -79576, 108881, -4895, -1, 18049 },
+				{ -79592, 108835, -4895, -1, 18050 }, // South West
+				{ -79614, 108871, -4895, -1, 18050 },
+				
+				{ -79586, 110171, -4895, -1, 18049 },
+				{ -79589, 110216, -4895, -1, 18050 }, // South East
+				{ -79620, 110177, -4895, -1, 18050 },
+				
+				{ -78825, 110182, -4895, -1, 18052 },
+				{ -78238, 110182, -4895, -1, 18053 }, // North East
+				{ -78266, 110218, -4895, -1, 18054 },
+				
+				{ -78275, 108883, -4895, -1, 18055 },
+				{ -78267, 108839, -4895, -1, 18057 }, // North West
+				{ -78241, 108871, -4895, -1, 18058 },
+				
+				// Archers and Marksmen \\
+				{ -79394, 109538, -4895, -1, 18051 },
+				{ -78929, 109992, -4895, -1, 18051 },
+				{ -78454, 109538, -4895, -1, 18056 },
+				{ -78929, 109053, -4895, -1, 18056 }
+			}
+	};
+	
+	protected static final int[][][] FESTIVAL_DUSK_PRIMARY_SPAWNS = {
+			{
+				/* Level 31 and Below - Offering of the Branded */
+				{ -76542, 89653, -5151, -1, 18009 },
+				{ -76509, 89637, -5151, -1, 18010 },
+				{ -76548, 89614, -5151, -1, 18010 },
+				
+				{ -76539, 88326, -5151, -1, 18009 },
+				{ -76512, 88289, -5151, -1, 18010 },
+				{ -76546, 88287, -5151, -1, 18010 },
+				
+				{ -77879, 88308, -5151, -1, 18012 },
+				{ -77886, 88310, -5151, -1, 18013 },
+				{ -77879, 88278, -5151, -1, 18014 },
+				
+				{ -77857, 89605, -5151, -1, 18015 },
+				{ -77858, 89658, -5151, -1, 18017 },
+				{ -77891, 89633, -5151, -1, 18018 },
+				
+				// Archers and Marksmen \\
+				{ -76728, 88962, -5151, -1, 18011 },
+				{ -77194, 88494, -5151, -1, 18011 },
+				{ -77660, 88896, -5151, -1, 18016 },
+				{ -77195, 89438, -5151, -1, 18016 }
+			},
+			{
+				/* Level 42 and Below - Apostate's Offering */
+				{ -77585, 84650, -5151, -1, 18019 },
+				{ -77628, 84643, -5151, -1, 18020 },
+				{ -77607, 84613, -5151, -1, 18020 },
+				
+				{ -76603, 85946, -5151, -1, 18019 },
+				{ -77606, 85994, -5151, -1, 18020 },
+				{ -77638, 85959, -5151, -1, 18020 },
+				
+				{ -76301, 85960, -5151, -1, 18022 },
+				{ -76257, 85972, -5151, -1, 18023 },
+				{ -76286, 85992, -5151, -1, 18024 },
+				
+				{ -76281, 84667, -5151, -1, 18025 },
+				{ -76291, 84611, -5151, -1, 18027 },
+				{ -76257, 84616, -5151, -1, 18028 },
+				
+				// Archers and Marksmen \\
+				{ -77419, 85307, -5151, -1, 18021 },
+				{ -76952, 85768, -5151, -1, 18021 },
+				{ -76477, 85312, -5151, -1, 18026 },
+				{ -76942, 84832, -5151, -1, 18026 }
+			},
+			{
+				/* Level 53 and Below - Witch's Offering */
+				{ -74211, 86494, -5151, -1, 18029 },
+				{ -74200, 86449, -5151, -1, 18030 },
+				{ -74167, 86464, -5151, -1, 18030 },
+				
+				{ -75495, 86482, -5151, -1, 18029 },
+				{ -75540, 86473, -5151, -1, 18030 },
+				{ -75509, 86445, -5151, -1, 18030 },
+				
+				{ -75509, 87775, -5151, -1, 18032 },
+				{ -75518, 87826, -5151, -1, 18033 },
+				{ -75542, 87780, -5151, -1, 18034 },
+				
+				{ -74214, 87789, -5151, -1, 18035 },
+				{ -74169, 87801, -5151, -1, 18037 },
+				{ -74198, 87827, -5151, -1, 18038 },
+				
+				// Archers and Marksmen \\
+				{ -75324, 87135, -5151, -1, 18031 },
+				{ -74852, 87606, -5151, -1, 18031 },
+				{ -74388, 87146, -5151, -1, 18036 },
+				{ -74856, 86663, -5151, -1, 18036 }
+			},
+			{
+				/* Level 64 and Below - Dark Omen Offering */
+				{ -79560, 89007, -5151, -1, 18039 },
+				{ -79521, 89016, -5151, -1, 18040 },
+				{ -79544, 89047, -5151, -1, 18040 },
+				
+				{ -79552, 87717, -5151, -1, 18039 },
+				{ -79552, 87673, -5151, -1, 18040 },
+				{ -79510, 87702, -5151, -1, 18040 },
+				
+				{ -80866, 87719, -5151, -1, 18042 },
+				{ -80897, 87689, -5151, -1, 18043 },
+				{ -80850, 87685, -5151, -1, 18044 },
+				
+				{ -80848, 89013, -5151, -1, 18045 },
+				{ -80887, 89051, -5151, -1, 18047 },
+				{ -80891, 89004, -5151, -1, 18048 },
+				
+				// Archers and Marksmen \\
+				{ -80205, 87895, -5151, -1, 18041 },
+				{ -80674, 88350, -5151, -1, 18041 },
+				{ -80209, 88833, -5151, -1, 18046 },
+				{ -79743, 88364, -5151, -1, 18046 }
+			},
+			{
+				/* No Level Limit - Offering of Forbidden Path */
+				{ -80624, 84060, -5151, -1, 18049 },
+				{ -80621, 84007, -5151, -1, 18050 },
+				{ -80590, 84039, -5151, -1, 18050 },
+				
+				{ -80605, 85349, -5151, -1, 18049 },
+				{ -80639, 85363, -5151, -1, 18050 },
+				{ -80611, 85385, -5151, -1, 18050 },
+				
+				{ -79311, 85353, -5151, -1, 18052 },
+				{ -79277, 85384, -5151, -1, 18053 },
+				{ -79273, 85539, -5151, -1, 18054 },
+				
+				{ -79297, 84054, -5151, -1, 18055 },
+				{ -79285, 84006, -5151, -1, 18057 },
+				{ -79260, 84040, -5151, -1, 18058 },
+				
+				// Archers and Marksmen \\
+				{ -79945, 85171, -5151, -1, 18051 },
+				{ -79489, 84707, -5151, -1, 18051 },
+				{ -79952, 84222, -5151, -1, 18056 },
+				{ -80423, 84703, -5151, -1, 18056 }
+			}
+	};
+	
+	protected static final int[][][] FESTIVAL_DAWN_SECONDARY_SPAWNS = {
+			{
+				/* 31 and Below */
+				{ -78757, 112834, -4895, -1, 18016 },
+				{ -78581, 112834, -4895, -1, 18016 },
+				{ -78822, 112526, -4895, -1, 18011 },
+				
+				{ -78822, 113702, -4895, -1, 18011 },
+				{ -78822, 113874, -4895, -1, 18011 },
+				{ -79524, 113546, -4895, -1, 18011 },
+				
+				{ -79693, 113546, -4895, -1, 18011 },
+				{ -79858, 113546, -4895, -1, 18011 },
+				{ -79545, 112757, -4895, -1, 18016 },
+				{ -79545, 112586, -4895, -1, 18016 },
+			},
+			{
+				/* 42 and Below */
+				{ -75565, 110580, -4895, -1, 18026 },
+				{ -75565, 110740, -4895, -1, 18026 },
+				{ -75577, 109776, -4895, -1, 18021 },
+				
+				{ -75413, 109776, -4895, -1, 18021 },
+				{ -75237, 109776, -4895, -1, 18021 },
+				{ -76274, 109468, -4895, -1, 18021 },
+				
+				{ -76274, 109635, -4895, -1, 18021 },
+				{ -76274, 109795, -4895, -1, 18021 },
+				{ -76351, 110500, -4895, -1, 18056 },
+				{ -76528, 110500, -4895, -1, 18056 },
+			},
+			{
+				/* 53 and Below */
+				{ -74191, 111527, -4895, -1, 18036 },
+				{ -74191, 111362, -4895, -1, 18036 },
+				{ -73495, 111611, -4895, -1, 18031 },
+				
+				{ -73327, 111611, -4895, -1, 18031 },
+				{ -73154, 111611, -4895, -1, 18031 },
+				{ -73473, 112301, -4895, -1, 18031 },
+				
+				{ -73473, 112475, -4895, -1, 18031 },
+				{ -73473, 112649, -4895, -1, 18031 },
+				{ -74270, 112326, -4895, -1, 18036 },
+				{ -74443, 112326, -4895, -1, 18036 },
+			},
+			{
+				/* 64 and Below */
+				{ -75738, 113439, -4895, -1, 18046 },
+				{ -75571, 113439, -4895, -1, 18046 },
+				{ -75824, 114141, -4895, -1, 18041 },
+				
+				{ -75824, 114309, -4895, -1, 18041 },
+				{ -75824, 114477, -4895, -1, 18041 },
+				{ -76513, 114158, -4895, -1, 18041 },
+				
+				{ -76683, 114158, -4895, -1, 18041 },
+				{ -76857, 114158, -4895, -1, 18041 },
+				{ -76535, 113357, -4895, -1, 18056 },
+				{ -76535, 113190, -4895, -1, 18056 },
+			},
+			{
+				/* No Level Limit */
+				{ -79350, 109894, -4895, -1, 18056 },
+				{ -79534, 109894, -4895, -1, 18056 },
+				{ -79285, 109187, -4895, -1, 18051 },
+				
+				{ -79285, 109019, -4895, -1, 18051 },
+				{ -79285, 108860, -4895, -1, 18051 },
+				{ -78587, 109172, -4895, -1, 18051 },
+				
+				{ -78415, 109172, -4895, -1, 18051 },
+				{ -78249, 109172, -4895, -1, 18051 },
+				{ -78575, 109961, -4895, -1, 18056 },
+				{ -78575, 110130, -4895, -1, 18056 },
+			}
+	};
+	
+	protected static final int[][][] FESTIVAL_DUSK_SECONDARY_SPAWNS = {
+			{
+				/* 31 and Below */
+				{ -76844, 89304, -5151, -1, 18011 },
+				{ -76844, 89479, -5151, -1, 18011 },
+				{ -76844, 89649, -5151, -1, 18011 },
+				
+				{ -77544, 89326, -5151, -1, 18011 },
+				{ -77716, 89326, -5151, -1, 18011 },
+				{ -77881, 89326, -5151, -1, 18011 },
+				
+				{ -77561, 88530, -5151, -1, 18016 },
+				{ -77561, 88364, -5151, -1, 18016 },
+				{ -76762, 88615, -5151, -1, 18016 },
+				{ -76594, 88615, -5151, -1, 18016 },
+			},
+			{
+				/* 42 and Below */
+				{ -77307, 84969, -5151, -1, 18021 },
+				{ -77307, 84795, -5151, -1, 18021 },
+				{ -77307, 84623, -5151, -1, 18021 },
+				
+				{ -76614, 84944, -5151, -1, 18021 },
+				{ -76433, 84944, -5151, -1, 18021 },
+				{ -76251, 84944, -5151, -1, 18021 },
+				
+				{ -76594, 85745, -5151, -1, 18026 },
+				{ -76594, 85910, -5151, -1, 18026 },
+				{ -77384, 85660, -5151, -1, 18026 },
+				{ -77555, 85660, -5151, -1, 18026 },
+			},
+			{
+				/* 53 and Below */
+				{ -74517, 86782, -5151, -1, 18031 },
+				{ -74344, 86782, -5151, -1, 18031 },
+				{ -74185, 86782, -5151, -1, 18031 },
+				
+				{ -74496, 87464, -5151, -1, 18031 },
+				{ -74496, 87636, -5151, -1, 18031 },
+				{ -74496, 87815, -5151, -1, 18031 },
+				
+				{ -75298, 87497, -5151, -1, 18036 },
+				{ -75460, 87497, -5151, -1, 18036 },
+				{ -75219, 86712, -5151, -1, 18036 },
+				{ -75219, 86531, -5151, -1, 18036 },
+			},
+			{
+				/* 64 and Below */
+				{ -79851, 88703, -5151, -1, 18041 },
+				{ -79851, 88868, -5151, -1, 18041 },
+				{ -79851, 89040, -5151, -1, 18041 },
+				
+				{ -80548, 88722, -5151, -1, 18041 },
+				{ -80711, 88722, -5151, -1, 18041 },
+				{ -80883, 88722, -5151, -1, 18041 },
+				
+				{ -80565, 87916, -5151, -1, 18046 },
+				{ -80565, 87752, -5151, -1, 18046 },
+				{ -79779, 87996, -5151, -1, 18046 },
+				{ -79613, 87996, -5151, -1, 18046 },
+			},
+			{
+				/* No Level Limit */
+				{ -79271, 84330, -5151, -1, 18051 },
+				{ -79448, 84330, -5151, -1, 18051 },
+				{ -79601, 84330, -5151, -1, 18051 },
+				
+				{ -80311, 84367, -5151, -1, 18051 },
+				{ -80311, 84196, -5151, -1, 18051 },
+				{ -80311, 84015, -5151, -1, 18051 },
+				
+				{ -80556, 85049, -5151, -1, 18056 },
+				{ -80384, 85049, -5151, -1, 18056 },
+				{ -79598, 85127, -5151, -1, 18056 },
+				{ -79598, 85303, -5151, -1, 18056 },
+			}
+	};
+	
+	protected static final int[][][] FESTIVAL_DAWN_CHEST_SPAWNS = {
+			{
+				/* Level 31 and Below */
+				{ -78999, 112957, -4927, -1, 18109 },
+				{ -79153, 112873, -4927, -1, 18109 },
+				{ -79256, 112873, -4927, -1, 18109 },
+				
+				{ -79368, 112957, -4927, -1, 18109 },
+				{ -79481, 113124, -4927, -1, 18109 },
+				{ -79481, 113275, -4927, -1, 18109 },
+				
+				{ -79364, 113398, -4927, -1, 18109 },
+				{ -79213, 113500, -4927, -1, 18109 },
+				{ -79099, 113500, -4927, -1, 18109 },
+				
+				{ -78960, 113398, -4927, -1, 18109 },
+				{ -78882, 113235, -4927, -1, 18109 },
+				{ -78882, 113099, -4927, -1, 18109 },
+			},
+			{
+				/* Level 42 and Below */
+				{ -76119, 110383, -4927, -1, 18110 },
+				{ -75980, 110442, -4927, -1, 18110 },
+				{ -75848, 110442, -4927, -1, 18110 },
+				
+				{ -75720, 110383, -4927, -1, 18110 },
+				{ -75625, 110195, -4927, -1, 18110 },
+				{ -75625, 110063, -4927, -1, 18110 },
+				
+				{ -75722, 109908, -4927, -1, 18110 },
+				{ -75863, 109832, -4927, -1, 18110 },
+				{ -75989, 109832, -4927, -1, 18110 },
+				
+				{ -76130, 109908, -4927, -1, 18110 },
+				{ -76230, 110079, -4927, -1, 18110 },
+				{ -76230, 110215, -4927, -1, 18110 },
+			},
+			{
+				/* Level 53 and Below */
+				{ -74055, 111781, -4927, -1, 18111 },
+				{ -74144, 111938, -4927, -1, 18111 },
+				{ -74144, 112075, -4927, -1, 18111 },
+				
+				{ -74055, 112173, -4927, -1, 18111 },
+				{ -73885, 112289, -4927, -1, 18111 },
+				{ -73756, 112289, -4927, -1, 18111 },
+				
+				{ -73574, 112141, -4927, -1, 18111 },
+				{ -73511, 112040, -4927, -1, 18111 },
+				{ -73511, 111912, -4927, -1, 18111 },
+				
+				{ -73574, 111772, -4927, -1, 18111 },
+				{ -73767, 111669, -4927, -1, 18111 },
+				{ -73899, 111669, -4927, -1, 18111 },
+			},
+			{
+				/* Level 64 and Below */
+				{ -76008, 113566, -4927, -1, 18112 },
+				{ -76159, 113485, -4927, -1, 18112 },
+				{ -76267, 113485, -4927, -1, 18112 },
+				
+				{ -76386, 113566, -4927, -1, 18112 },
+				{ -76482, 113748, -4927, -1, 18112 },
+				{ -76482, 113885, -4927, -1, 18112 },
+				
+				{ -76371, 114029, -4927, -1, 18112 },
+				{ -76220, 114118, -4927, -1, 18112 },
+				{ -76092, 114118, -4927, -1, 18112 },
+				
+				{ -75975, 114029, -4927, -1, 18112 },
+				{ -75861, 113851, -4927, -1, 18112 },
+				{ -75861, 113713, -4927, -1, 18112 },
+			},
+			{
+				/* No Level Limit */
+				{ -79100, 109782, -4927, -1, 18113 },
+				{ -78962, 109853, -4927, -1, 18113 },
+				{ -78851, 109853, -4927, -1, 18113 },
+				
+				{ -78721, 109782, -4927, -1, 18113 },
+				{ -78615, 109596, -4927, -1, 18113 },
+				{ -78615, 109453, -4927, -1, 18113 },
+				
+				{ -78746, 109300, -4927, -1, 18113 },
+				{ -78881, 109203, -4927, -1, 18113 },
+				{ -79027, 109203, -4927, -1, 18113 },
+				
+				{ -79159, 109300, -4927, -1, 18113 },
+				{ -79240, 109480, -4927, -1, 18113 },
+				{ -79240, 109615, -4927, -1, 18113 },
+			}
+	};
+	
+	protected static final int[][][] FESTIVAL_DUSK_CHEST_SPAWNS = {
+			{
+				/* Level 31 and Below */
+				{ -77016, 88726, -5183, -1, 18114 },
+				{ -77136, 88646, -5183, -1, 18114 },
+				{ -77247, 88646, -5183, -1, 18114 },
+				
+				{ -77380, 88726, -5183, -1, 18114 },
+				{ -77512, 88883, -5183, -1, 18114 },
+				{ -77512, 89053, -5183, -1, 18114 },
+				
+				{ -77378, 89287, -5183, -1, 18114 },
+				{ -77254, 89238, -5183, -1, 18114 },
+				{ -77095, 89238, -5183, -1, 18114 },
+				
+				{ -76996, 89287, -5183, -1, 18114 },
+				{ -76901, 89025, -5183, -1, 18114 },
+				{ -76901, 88891, -5183, -1, 18114 },
+			},
+			{
+				/* Level 42 and Below */
+				{ -77128, 85553, -5183, -1, 18115 },
+				{ -77036, 85594, -5183, -1, 18115 },
+				{ -76919, 85594, -5183, -1, 18115 },
+				
+				{ -76755, 85553, -5183, -1, 18115 },
+				{ -76635, 85392, -5183, -1, 18115 },
+				{ -76635, 85216, -5183, -1, 18115 },
+				
+				{ -76761, 85025, -5183, -1, 18115 },
+				{ -76908, 85004, -5183, -1, 18115 },
+				{ -77041, 85004, -5183, -1, 18115 },
+				
+				{ -77138, 85025, -5183, -1, 18115 },
+				{ -77268, 85219, -5183, -1, 18115 },
+				{ -77268, 85410, -5183, -1, 18115 },
+			},
+			{
+				/* Level 53 and Below */
+				{ -75150, 87303, -5183, -1, 18116 },
+				{ -75150, 87175, -5183, -1, 18116 },
+				{ -75150, 87175, -5183, -1, 18116 },
+				
+				{ -75150, 87303, -5183, -1, 18116 },
+				{ -74943, 87433, -5183, -1, 18116 },
+				{ -74767, 87433, -5183, -1, 18116 },
+				
+				{ -74556, 87306, -5183, -1, 18116 },
+				{ -74556, 87184, -5183, -1, 18116 },
+				{ -74556, 87184, -5183, -1, 18116 },
+				
+				{ -74556, 87306, -5183, -1, 18116 },
+				{ -74757, 86830, -5183, -1, 18116 },
+				{ -74927, 86830, -5183, -1, 18116 },
+			},
+			{
+				/* Level 64 and Below */
+				{ -80010, 88128, -5183, -1, 18117 },
+				{ -80113, 88066, -5183, -1, 18117 },
+				{ -80220, 88066, -5183, -1, 18117 },
+				
+				{ -80359, 88128, -5183, -1, 18117 },
+				{ -80467, 88267, -5183, -1, 18117 },
+				{ -80467, 88436, -5183, -1, 18117 },
+				
+				{ -80381, 88639, -5183, -1, 18117 },
+				{ -80278, 88577, -5183, -1, 18117 },
+				{ -80142, 88577, -5183, -1, 18117 },
+				
+				{ -80028, 88639, -5183, -1, 18117 },
+				{ -79915, 88466, -5183, -1, 18117 },
+				{ -79915, 88322, -5183, -1, 18117 },
+			},
+			{
+				/* No Level Limit */
+				{ -80153, 84947, -5183, -1, 18118 },
+				{ -80003, 84962, -5183, -1, 18118 },
+				{ -79848, 84962, -5183, -1, 18118 },
+				
+				{ -79742, 84947, -5183, -1, 18118 },
+				{ -79668, 84772, -5183, -1, 18118 },
+				{ -79668, 84619, -5183, -1, 18118 },
+				
+				{ -79772, 84471, -5183, -1, 18118 },
+				{ -79888, 84414, -5183, -1, 18118 },
+				{ -80023, 84414, -5183, -1, 18118 },
+				
+				{ -80166, 84471, -5183, -1, 18118 },
+				{ -80253, 84600, -5183, -1, 18118 },
+				{ -80253, 84780, -5183, -1, 18118 },
+			}
+	};
+	
+	//////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\
+	
+	protected FestivalManager _managerInstance;
+	protected ScheduledFuture<?> _managerScheduledTask;
+	
+	protected int _signsCycle = SevenSigns.getInstance().getCurrentCycle();
+	protected int _festivalCycle;
+	protected long _nextFestivalCycleStart;
+	protected long _nextFestivalStart;
+	protected boolean _festivalInitialized;
+	protected boolean _festivalInProgress;
+	protected List<Integer> _accumulatedBonuses; // The total bonus available (in Ancient Adena)
+	
+	boolean _noPartyRegister;
+	private L2Npc _dawnChatGuide;
+	private L2Npc _duskChatGuide;
+	
+	protected Map<Integer, List<L2PcInstance>> _dawnFestivalParticipants;
+	protected Map<Integer, List<L2PcInstance>> _duskFestivalParticipants;
+	
+	protected Map<Integer, List<L2PcInstance>> _dawnPreviousParticipants;
+	protected Map<Integer, List<L2PcInstance>> _duskPreviousParticipants;
+	
+	private Map<Integer, Long> _dawnFestivalScores;
+	private Map<Integer, Long> _duskFestivalScores;
+	
+	/**
+	 * _festivalData is essentially an instance of the seven_signs_festival table and
+	 * should be treated as such.
+	 *
+	 * Data is initially accessed by the related Seven Signs cycle, with _signsCycle representing
+	 * data for the current round of Festivals.
+	 *
+	 * The actual table data is stored as a series of StatsSet constructs. These are accessed by
+	 * the use of an offset based on the number of festivals, thus:
+	 *
+	 *offset = FESTIVAL_COUNT + festivalId
+	 *(Data for Dawn is always accessed by offset > FESTIVAL_COUNT)
+	 */
+	private Map<Integer, Map<Integer, StatsSet>> _festivalData;
+	
+	private SevenSignsFestival()
+	{
+		_accumulatedBonuses = new FastList<Integer>();
+		
+		_dawnFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
+		_dawnPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
+		_dawnFestivalScores = new FastMap<Integer, Long>();
+		
+		_duskFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
+		_duskPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
+		_duskFestivalScores = new FastMap<Integer, Long>();
+		
+		_festivalData = new FastMap<Integer, Map<Integer, StatsSet>>();
+		
+		restoreFestivalData();
+		
+		if (SevenSigns.getInstance().isSealValidationPeriod())
+		{
+			_log.info("SevenSignsFestival: Initialization bypassed due to Seal Validation in effect.");
+			return;
+		}
+		
+		L2Spawn.addSpawnListener(this);
+		startFestivalManager();
+	}
+	
+	public static SevenSignsFestival getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	/**
+	 * Returns the associated name (level range) to a given festival ID.
+	 *
+	 * @param int festivalID
+	 * @return String festivalName
+	 */
+	public static final String getFestivalName(int festivalID)
+	{
+		String festivalName;
+		
+		switch (festivalID)
+		{
+			case FESTIVAL_LEVEL_MAX_31:
+				festivalName = "Level 31 or lower";
+				break;
+			case FESTIVAL_LEVEL_MAX_42:
+				festivalName = "Level 42 or lower";
+				break;
+			case FESTIVAL_LEVEL_MAX_53:
+				festivalName = "Level 53 or lower";
+				break;
+			case FESTIVAL_LEVEL_MAX_64:
+				festivalName = "Level 64 or lower";
+				break;
+			default:
+				festivalName = "No Level Limit";
+				break;
+		}
+		
+		return festivalName;
+	}
+	
+	/**
+	 * Returns the maximum allowed player level for the given festival type.
+	 *
+	 * @param festivalId
+	 * @return int maxLevel
+	 */
+	public static final int getMaxLevelForFestival(int festivalId)
+	{
+		int maxLevel = (Experience.MAX_LEVEL - 1);
+		
+		switch (festivalId)
+		{
+			case SevenSignsFestival.FESTIVAL_LEVEL_MAX_31:
+				maxLevel = 31;
+				break;
+			case SevenSignsFestival.FESTIVAL_LEVEL_MAX_42:
+				maxLevel = 42;
+				break;
+			case SevenSignsFestival.FESTIVAL_LEVEL_MAX_53:
+				maxLevel = 53;
+				break;
+			case SevenSignsFestival.FESTIVAL_LEVEL_MAX_64:
+				maxLevel = 64;
+				break;
+		}
+		
+		return maxLevel;
+	}
+	
+	/**
+	 * Returns true if the monster ID given is of an archer/marksman type.
+	 *
+	 * @param npcId
+	 * @return boolean isArcher
+	 */
+	protected static final boolean isFestivalArcher(int npcId)
+	{
+		if (npcId < 18009 || npcId > 18108)
+			return false;
+		
+		int identifier = npcId % 10;
+		return (identifier == 4 || identifier == 9);
+	}
+	
+	/**
+	 * Returns true if the monster ID given is a festival chest.
+	 *
+	 * @param npcId
+	 * @return boolean isChest
+	 */
+	protected static final boolean isFestivalChest(int npcId)
+	{
+		return (npcId < 18109 || npcId > 18118);
+	}
+	
+	/**
+	 * Primarily used to terminate the Festival Manager, when the Seven Signs period changes.
+	 *
+	 * @return ScheduledFuture festManagerScheduler
+	 */
+	protected final ScheduledFuture<?> getFestivalManagerSchedule()
+	{
+		if (_managerScheduledTask == null)
+			startFestivalManager();
+		
+		return _managerScheduledTask;
+	}
+	
+	/**
+	 * Used to start the Festival Manager, if the current period is not Seal Validation.
+	 */
+	protected void startFestivalManager()
+	{
+		// Start the Festival Manager for the first time after the server has started
+		// at the specified time, then invoke it automatically after every cycle.
+		FestivalManager fm = new FestivalManager();
+		setNextFestivalStart(Config.ALT_FESTIVAL_MANAGER_START + FESTIVAL_SIGNUP_TIME);
+		_managerScheduledTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(fm, Config.ALT_FESTIVAL_MANAGER_START, Config.ALT_FESTIVAL_CYCLE_LENGTH);
+		
+		_log.info("SevenSignsFestival: The first Festival of Darkness cycle begins in " + (Config.ALT_FESTIVAL_MANAGER_START / 60000)
+				+ " minute(s).");
+	}
+	
+	/**
+	 * Restores saved festival data, basic settings from the properties file
+	 * and past high score data from the database.
+	 *
+	 * @throws Exception
+	 */
+	protected void restoreFestivalData()
+	{
+		Connection con = null;
+		PreparedStatement statement = null;
+		ResultSet rset = null;
+		
+		if (Config.DEBUG)
+			_log.info("SevenSignsFestival: Restoring festival data. Current SS Cycle: " + _signsCycle);
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			statement = con.prepareStatement("SELECT festivalId, cabal, cycle, date, score, members " + "FROM seven_signs_festival");
+			rset = statement.executeQuery();
+			
+			while (rset.next())
+			{
+				int festivalCycle = rset.getInt("cycle");
+				int festivalId = rset.getInt("festivalId");
+				String cabal = rset.getString("cabal");
+				
+				StatsSet festivalDat = new StatsSet();
+				festivalDat.set("festivalId", festivalId);
+				festivalDat.set("cabal", cabal);
+				festivalDat.set("cycle", festivalCycle);
+				festivalDat.set("date", rset.getString("date"));
+				festivalDat.set("score", rset.getInt("score"));
+				festivalDat.set("members", rset.getString("members"));
+				
+				if (Config.DEBUG)
+					_log.info("SevenSignsFestival: Loaded data from DB for (Cycle = " + festivalCycle + ", Oracle = " + cabal
+							+ ", Festival = " + getFestivalName(festivalId));
+				
+				if (cabal.equals("dawn"))
+					festivalId += FESTIVAL_COUNT;
+				
+				Map<Integer, StatsSet> tempData = _festivalData.get(festivalCycle);
+				
+				if (tempData == null)
+					tempData = new FastMap<Integer, StatsSet>();
+				
+				tempData.put(festivalId, festivalDat);
+				_festivalData.put(festivalCycle, tempData);
+			}
+			
+			rset.close();
+			statement.close();
+			
+			String query = "SELECT festival_cycle, ";
+			
+			for (int i = 0; i < FESTIVAL_COUNT - 1; i++)
+				
+				query += "accumulated_bonus" + String.valueOf(i) + ", ";
+			query += "accumulated_bonus" + String.valueOf(FESTIVAL_COUNT - 1) + " ";
+			query += "FROM seven_signs_status WHERE id=0";
+			
+			statement = con.prepareStatement(query);
+			rset = statement.executeQuery();
+			
+			while (rset.next())
+			{
+				_festivalCycle = rset.getInt("festival_cycle");
+				
+				for (int i = 0; i < FESTIVAL_COUNT; i++)
+					_accumulatedBonuses.add(i, rset.getInt("accumulated_bonus" + String.valueOf(i)));
+			}
+			
+			rset.close();
+			statement.close();
+			con.close();
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Loaded data from database.");
+		}
+		catch (SQLException e)
+		{
+			_log.severe("SevenSignsFestival: Failed to load configuration: " + e);
+		}
+		finally
+		{
+			try
+			{
+				rset.close();
+				statement.close();
+				con.close();
+			}
+			catch (SQLException e)
+			{
+			}
+		}
+	}
+	
+	/**
+	 * Stores current festival data, basic settings to the properties file
+	 * and past high score data to the database.
+	 *
+	 * If updateSettings = true, then all Seven Signs data is updated in the database.
+	 *
+	 * @param updateSettings
+	 * @throws Exception
+	 */
+	public void saveFestivalData(boolean updateSettings)
+	{
+		Connection con = null;
+		PreparedStatement statement = null;
+		
+		if (Config.DEBUG)
+			_log.info("SevenSignsFestival: Saving festival data to disk.");
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			for (Map<Integer, StatsSet> currCycleData : _festivalData.values())
+			{
+				for (StatsSet festivalDat : currCycleData.values())
+				{
+					int festivalCycle = festivalDat.getInteger("cycle");
+					int festivalId = festivalDat.getInteger("festivalId");
+					String cabal = festivalDat.getString("cabal");
+					
+					// Try to update an existing record.
+					statement = con.prepareStatement("UPDATE seven_signs_festival SET date=?, score=?, members=? WHERE cycle=? AND cabal=? AND festivalId=?");
+					statement.setLong(1, Long.valueOf(festivalDat.getString("date")));
+					statement.setInt(2, festivalDat.getInteger("score"));
+					statement.setString(3, festivalDat.getString("members"));
+					statement.setInt(4, festivalCycle);
+					statement.setString(5, cabal);
+					statement.setInt(6, festivalId);
+					
+					// If there was no record to update, assume it doesn't exist and add a new one,
+					// otherwise continue with the next record to store.
+					if (statement.executeUpdate() > 0)
+					{
+						if (Config.DEBUG)
+							_log.info("SevenSignsFestival: Updated data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal
+									+ ", FestID = " + festivalId + ")");
+						
+						statement.close();
+						continue;
+					}
+					
+					statement.close();
+					
+					statement = con.prepareStatement("INSERT INTO seven_signs_festival (festivalId, cabal, cycle, date, score, members) VALUES (?,?,?,?,?,?)");
+					statement.setInt(1, festivalId);
+					statement.setString(2, cabal);
+					statement.setInt(3, festivalCycle);
+					statement.setLong(4, Long.valueOf(festivalDat.getString("date")));
+					statement.setInt(5, festivalDat.getInteger("score"));
+					statement.setString(6, festivalDat.getString("members"));
+					statement.execute();
+					statement.close();
+					
+					if (Config.DEBUG)
+						_log.info("SevenSignsFestival: Inserted data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal
+								+ ", FestID = " + festivalId + ")");
+				}
+			}
+			
+			con.close();
+			
+			// Updates Seven Signs DB data also, so call only if really necessary.
+			if (updateSettings)
+				SevenSigns.getInstance().saveSevenSignsData(null, true);
+		}
+		catch (SQLException e)
+		{
+			_log.severe("SevenSignsFestival: Failed to save configuration: " + e);
+		}
+		finally
+		{
+			try
+			{
+				statement.close();
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	/**
+	 * If a clan member is a member of the highest-ranked party in the Festival of Darkness, 100 points are added per member
+	 */
+	protected void rewardHighestRanked()
+	{
+		String[] partyMembers;
+		StatsSet overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_31);
+		if (overallData != null)
+		{
+			partyMembers = overallData.getString("members").split(",");
+			for (String partyMemberName : partyMembers)
+				addReputationPointsForPartyMemberClan(partyMemberName);
+		}
+		
+		overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_42);
+		if (overallData != null)
+		{
+			partyMembers = overallData.getString("members").split(",");
+			for (String partyMemberName : partyMembers)
+				addReputationPointsForPartyMemberClan(partyMemberName);
+		}
+		
+		overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_53);
+		if (overallData != null)
+		{
+			partyMembers = overallData.getString("members").split(",");
+			for (String partyMemberName : partyMembers)
+				addReputationPointsForPartyMemberClan(partyMemberName);
+		}
+		
+		overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_64);
+		if (overallData != null)
+		{
+			partyMembers = overallData.getString("members").split(",");
+			for (String partyMemberName : partyMembers)
+				addReputationPointsForPartyMemberClan(partyMemberName);
+		}
+		
+		overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_NONE);
+		if (overallData != null)
+		{
+			partyMembers = overallData.getString("members").split(",");
+			for (String partyMemberName : partyMembers)
+				addReputationPointsForPartyMemberClan(partyMemberName);
+		}
+	}
+	
+	private void addReputationPointsForPartyMemberClan(String partyMemberName)
+	{
+		L2PcInstance player = L2World.getInstance().getPlayer(partyMemberName);
+		if (player != null)
+		{
+			if (player.getClan() != null)
+			{
+				player.getClan().setReputationScore(player.getClan().getReputationScore() + Config.FESTIVAL_WIN_POINTS, true);
+				SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_C1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
+				sm.addString(partyMemberName);
+				sm.addNumber(Config.FESTIVAL_WIN_POINTS);
+				player.getClan().broadcastToOnlineMembers(sm);
+			}
+		}
+		else
+		{
+			Connection con = null;
+			
+			try
+			{
+				con = L2DatabaseFactory.getInstance().getConnection();
+				PreparedStatement statement = con.prepareStatement(GET_CLAN_NAME);
+				statement.setString(1, partyMemberName);
+				ResultSet rset = statement.executeQuery();
+				if (rset.next())
+				{
+					String clanName = rset.getString("clan_name");
+					if (clanName != null)
+					{
+						L2Clan clan = ClanTable.getInstance().getClanByName(clanName);
+						if (clan != null)
+						{
+							clan.setReputationScore(clan.getReputationScore() + Config.FESTIVAL_WIN_POINTS, true);
+							SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_C1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
+							sm.addString(partyMemberName);
+							sm.addNumber(Config.FESTIVAL_WIN_POINTS);
+							clan.broadcastToOnlineMembers(sm);
+						}
+					}
+				}
+				
+				rset.close();
+				statement.close();
+			}
+			catch (Exception e)
+			{
+				_log.warning("could not get clan name of " + partyMemberName + ": " + e);
+			}
+			finally
+			{
+				try
+				{
+					con.close();
+				}
+				catch (Exception e)
+				{
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Used to reset all festival data at the beginning of a new quest event period.
+	 */
+	protected void resetFestivalData(boolean updateSettings)
+	{
+		_festivalCycle = 0;
+		_signsCycle = SevenSigns.getInstance().getCurrentCycle();
+		
+		// Set all accumulated bonuses back to 0.
+		for (int i = 0; i < FESTIVAL_COUNT; i++)
+			_accumulatedBonuses.set(i, 0);
+		
+		_dawnFestivalParticipants.clear();
+		_dawnPreviousParticipants.clear();
+		_dawnFestivalScores.clear();
+		
+		_duskFestivalParticipants.clear();
+		_duskPreviousParticipants.clear();
+		_duskFestivalScores.clear();
+		
+		// Set up a new data set for the current cycle of festivals
+		Map<Integer, StatsSet> newData = new FastMap<Integer, StatsSet>();
+		
+		for (int i = 0; i < FESTIVAL_COUNT * 2; i++)
+		{
+			int festivalId = i;
+			
+			if (i >= FESTIVAL_COUNT)
+				festivalId -= FESTIVAL_COUNT;
+			
+			// Create a new StatsSet with "default" data for Dusk
+			StatsSet tempStats = new StatsSet();
+			tempStats.set("festivalId", festivalId);
+			tempStats.set("cycle", _signsCycle);
+			tempStats.set("date", "0");
+			tempStats.set("score", 0);
+			tempStats.set("members", "");
+			
+			if (i >= FESTIVAL_COUNT)
+				tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DAWN));
+			else
+				tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DUSK));
+			
+			newData.put(i, tempStats);
+		}
+		
+		// Add the newly created cycle data to the existing festival data, and
+		// subsequently save it to the database.
+		_festivalData.put(_signsCycle, newData);
+		
+		saveFestivalData(updateSettings);
+		
+		// Remove any unused blood offerings from online players.
+		Collection<L2PcInstance> pls = L2World.getInstance().getAllPlayers().values();
+		//synchronized (L2World.getInstance().getAllPlayers())
+		{
+			for (L2PcInstance onlinePlayer : pls)
+			{
+				try
+				{
+					L2ItemInstance bloodOfferings = onlinePlayer.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
+					
+					if (bloodOfferings != null)
+						onlinePlayer.destroyItem("SevenSigns", bloodOfferings, null, false);
+				}
+				catch (NullPointerException e)
+				{
+				}
+			}
+		}
+		
+		_log.info("SevenSignsFestival: Reinitialized engine for next competition period.");
+	}
+	
+	public final int getCurrentFestivalCycle()
+	{
+		return _festivalCycle;
+	}
+	
+	public final boolean isFestivalInitialized()
+	{
+		return _festivalInitialized;
+	}
+	
+	public final boolean isFestivalInProgress()
+	{
+		return _festivalInProgress;
+	}
+	
+	public void setNextCycleStart()
+	{
+		_nextFestivalCycleStart = System.currentTimeMillis() + Config.ALT_FESTIVAL_CYCLE_LENGTH;
+	}
+	
+	public void setNextFestivalStart(long milliFromNow)
+	{
+		_nextFestivalStart = System.currentTimeMillis() + milliFromNow;
+	}
+	
+	public final int getMinsToNextCycle()
+	{
+		if (SevenSigns.getInstance().isSealValidationPeriod())
+			return -1;
+		
+		return Math.round((_nextFestivalCycleStart - System.currentTimeMillis()) / 60000);
+	}
+	
+	public final int getMinsToNextFestival()
+	{
+		if (SevenSigns.getInstance().isSealValidationPeriod())
+			return -1;
+		
+		return Math.round((_nextFestivalStart - System.currentTimeMillis()) / 60000) + 1;
+	}
+	
+	public final String getTimeToNextFestivalStr()
+	{
+		if (SevenSigns.getInstance().isSealValidationPeriod())
+			return "<font color=\"FF0000\">This is the Seal Validation period. Festivals will resume next week.</font>";
+		
+		return "<font color=\"FF0000\">The next festival will begin in " + getMinsToNextFestival() + " minute(s).</font>";
+	}
+	
+	/**
+	 * Returns the current festival ID and oracle ID that the specified player is in,
+	 * but will return the default of {-1, -1} if the player is not found as a participant.
+	 *
+	 * @param player
+	 * @return int[] playerFestivalInfo
+	 */
+	public final int[] getFestivalForPlayer(L2PcInstance player)
+	{
+		int[] playerFestivalInfo = { -1, -1 };
+		int festivalId = 0;
+		
+		while (festivalId < FESTIVAL_COUNT)
+		{
+			List<L2PcInstance> participants = _dawnFestivalParticipants.get(festivalId);
+			
+			// If there are no participants in this festival, move on to the next.
+			if (participants != null && participants.contains(player))
+			{
+				playerFestivalInfo[0] = SevenSigns.CABAL_DAWN;
+				playerFestivalInfo[1] = festivalId;
+				
+				return playerFestivalInfo;
+			}
+			
+			participants = _duskFestivalParticipants.get(++festivalId);
+			
+			if (participants != null && participants.contains(player))
+			{
+				playerFestivalInfo[0] = SevenSigns.CABAL_DUSK;
+				playerFestivalInfo[1] = festivalId;
+				
+				return playerFestivalInfo;
+			}
+			
+			festivalId++;
+		}
+		
+		// Return default data if the player is not found as a participant.
+		return playerFestivalInfo;
+	}
+	
+	public final boolean isParticipant(L2PcInstance player)
+	{
+		if (SevenSigns.getInstance().isSealValidationPeriod())
+			return false;
+		
+		if (_managerInstance == null)
+			return false;
+		
+		for (List<L2PcInstance> participants : _dawnFestivalParticipants.values())
+			if (participants.contains(player))
+				return true;
+		
+		for (List<L2PcInstance> participants : _duskFestivalParticipants.values())
+			if (participants.contains(player))
+				return true;
+		
+		return false;
+	}
+	
+	public final List<L2PcInstance> getParticipants(int oracle, int festivalId)
+	{
+		if (oracle == SevenSigns.CABAL_DAWN)
+			return _dawnFestivalParticipants.get(festivalId);
+		
+		return _duskFestivalParticipants.get(festivalId);
+	}
+	
+	public final List<L2PcInstance> getPreviousParticipants(int oracle, int festivalId)
+	{
+		if (oracle == SevenSigns.CABAL_DAWN)
+			return _dawnPreviousParticipants.get(festivalId);
+		
+		return _duskPreviousParticipants.get(festivalId);
+	}
+	
+	public void setParticipants(int oracle, int festivalId, L2Party festivalParty)
+	{
+		List<L2PcInstance> participants = new FastList<L2PcInstance>();
+		
+		if (festivalParty != null)
+		{
+			participants = festivalParty.getPartyMembers();
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: " + festivalParty.getPartyMembers().toString() + " have signed up to the "
+						+ SevenSigns.getCabalShortName(oracle) + " " + getFestivalName(festivalId) + " festival.");
+		}
+		
+		if (oracle == SevenSigns.CABAL_DAWN)
+			_dawnFestivalParticipants.put(festivalId, participants);
+		else
+			_duskFestivalParticipants.put(festivalId, participants);
+	}
+	
+	public void updateParticipants(L2PcInstance player, L2Party festivalParty)
+	{
+		if (!isParticipant(player))
+			return;
+		
+		final int[] playerFestInfo = getFestivalForPlayer(player);
+		final int oracle = playerFestInfo[0];
+		final int festivalId = playerFestInfo[1];
+		
+		if (festivalId > -1)
+		{
+			if (_festivalInitialized)
+			{
+				L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);
+				
+				if (festivalParty == null)// leader has left
+					for (L2PcInstance partyMember : getParticipants(oracle, festivalId))
+						festivalInst.relocatePlayer(partyMember, true);
+				else
+					festivalInst.relocatePlayer(player, true);
+			}
+			
+			setParticipants(oracle, festivalId, festivalParty);
+			
+			// Check on disconnect if min player in party
+			if (festivalParty != null && festivalParty.getMemberCount() < Config.ALT_FESTIVAL_MIN_PLAYER)
+			{
+				updateParticipants(player, null); // under minimum count
+				festivalParty.removePartyMember(player);
+			}
+		}
+	}
+	
+	public final long getFinalScore(int oracle, int festivalId)
+	{
+		if (oracle == SevenSigns.CABAL_DAWN)
+			return _dawnFestivalScores.get(festivalId);
+		
+		return _duskFestivalScores.get(festivalId);
+	}
+	
+	public final int getHighestScore(int oracle, int festivalId)
+	{
+		return getHighestScoreData(oracle, festivalId).getInteger("score");
+	}
+	
+	/**
+	 * Returns a stats set containing the highest score <b>this cycle</b> for the
+	 * the specified cabal and associated festival ID.
+	 *
+	 * @param oracle
+	 * @param festivalId
+	 * @return StatsSet festivalDat
+	 */
+	public final StatsSet getHighestScoreData(int oracle, int festivalId)
+	{
+		int offsetId = festivalId;
+		
+		if (oracle == SevenSigns.CABAL_DAWN)
+			offsetId += 5;
+		
+		// Attempt to retrieve existing score data (if found), otherwise create a
+		// new blank data set and display a console warning.
+		StatsSet currData = null;
+		
+		try
+		{
+			currData = _festivalData.get(_signsCycle).get(offsetId);
+		}
+		catch (Exception e)
+		{
+			currData = new StatsSet();
+			currData.set("score", 0);
+			currData.set("members", "");
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Data missing for " + SevenSigns.getCabalName(oracle) + ", FestivalID = " + festivalId
+						+ " (Current Cycle " + _signsCycle + ")");
+		}
+		
+		return currData;
+	}
+	
+	/**
+	 * Returns a stats set containing the highest ever recorded
+	 * score data for the specified festival.
+	 *
+	 * @param festivalId
+	 * @return StatsSet result
+	 */
+	public final StatsSet getOverallHighestScoreData(int festivalId)
+	{
+		StatsSet result = null;
+		int highestScore = 0;
+		
+		for (Map<Integer, StatsSet> currCycleData : _festivalData.values())
+		{
+			for (StatsSet currFestData : currCycleData.values())
+			{
+				int currFestID = currFestData.getInteger("festivalId");
+				int festivalScore = currFestData.getInteger("score");
+				
+				if (currFestID != festivalId)
+					continue;
+				
+				if (festivalScore > highestScore)
+				{
+					highestScore = festivalScore;
+					result = currFestData;
+				}
+			}
+		}
+		
+		return result;
+	}
+	
+	/**
+	 * Set the final score details for the last participants of the specified festival data.
+	 * Returns <b>true</b> if the score is higher than that previously recorded <b>this cycle</b>.
+	 *
+	 * @param player
+	 * @param oracle
+	 * @param festivalId
+	 * @param offeringScore
+	 * @return boolean isHighestScore
+	 */
+	public boolean setFinalScore(L2PcInstance player, int oracle, int festivalId, long offeringScore)
+	{
+		List<String> partyMembers;
+		
+		int currDawnHighScore = getHighestScore(SevenSigns.CABAL_DAWN, festivalId);
+		int currDuskHighScore = getHighestScore(SevenSigns.CABAL_DUSK, festivalId);
+		
+		int thisCabalHighScore = 0;
+		int otherCabalHighScore = 0;
+		
+		if (oracle == SevenSigns.CABAL_DAWN)
+		{
+			thisCabalHighScore = currDawnHighScore;
+			otherCabalHighScore = currDuskHighScore;
+			
+			_dawnFestivalScores.put(festivalId, offeringScore);
+		}
+		else
+		{
+			thisCabalHighScore = currDuskHighScore;
+			otherCabalHighScore = currDawnHighScore;
+			
+			_duskFestivalScores.put(festivalId, offeringScore);
+		}
+		
+		StatsSet currFestData = getHighestScoreData(oracle, festivalId);
+		
+		// Check if this is the highest score for this level range so far for the player's cabal.
+		if (offeringScore > thisCabalHighScore)
+		{
+			// If the current score is greater than that for the other cabal,
+			// then they already have the points from this festival.
+			if (thisCabalHighScore < otherCabalHighScore)
+				return false;
+			
+			partyMembers = new FastList<String>();
+			List<L2PcInstance> prevParticipants = getPreviousParticipants(oracle, festivalId);
+			
+			// Record a string list of the party members involved.
+			for (L2PcInstance partyMember : prevParticipants)
+			{
+				try
+				{
+					partyMembers.add(partyMember.getName());
+				}
+				catch (NullPointerException e)
+				{
+				}
+			}
+			
+			// Update the highest scores and party list.
+			currFestData.set("date", String.valueOf(System.currentTimeMillis()));
+			currFestData.set("score", offeringScore);
+			currFestData.set("members", Util.implodeString(partyMembers, ","));
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: " + player.getName() + "'s party has the highest score (" + offeringScore + ") so far for "
+						+ SevenSigns.getCabalName(oracle) + " in " + getFestivalName(festivalId));
+			
+			// Only add the score to the cabal's overall if it's higher than the other cabal's score.
+			if (offeringScore > otherCabalHighScore)
+			{
+				int contribPoints = FESTIVAL_LEVEL_SCORES[festivalId];
+				
+				// Give this cabal the festival points, while deducting them from the other.
+				SevenSigns.getInstance().addFestivalScore(oracle, contribPoints);
+				
+				if (Config.DEBUG)
+					_log.info("SevenSignsFestival: This is the highest score overall so far for the " + getFestivalName(festivalId)
+							+ " festival!");
+			}
+			
+			saveFestivalData(true);
+			
+			return true;
+		}
+		
+		return false;
+	}
+	
+	public final int getAccumulatedBonus(int festivalId)
+	{
+		return _accumulatedBonuses.get(festivalId);
+	}
+	
+	public final int getTotalAccumulatedBonus()
+	{
+		int totalAccumBonus = 0;
+		
+		for (int accumBonus : _accumulatedBonuses)
+			totalAccumBonus += accumBonus;
+		
+		return totalAccumBonus;
+	}
+	
+	public void addAccumulatedBonus(int festivalId, int stoneType, int stoneAmount)
+	{
+		int eachStoneBonus = 0;
+		
+		switch (stoneType)
+		{
+			case SevenSigns.SEAL_STONE_BLUE_ID:
+				eachStoneBonus = SevenSigns.SEAL_STONE_BLUE_VALUE;
+				break;
+			case SevenSigns.SEAL_STONE_GREEN_ID:
+				eachStoneBonus = SevenSigns.SEAL_STONE_GREEN_VALUE;
+				break;
+			case SevenSigns.SEAL_STONE_RED_ID:
+				eachStoneBonus = SevenSigns.SEAL_STONE_RED_VALUE;
+				break;
+		}
+		
+		int newTotalBonus = _accumulatedBonuses.get(festivalId) + (stoneAmount * eachStoneBonus);
+		_accumulatedBonuses.set(festivalId, newTotalBonus);
+	}
+	
+	/**
+	 * Calculate and return the proportion of the accumulated bonus for the festival
+	 * where the player was in the winning party, if the winning party's cabal won the event.
+	 *
+	 * The accumulated bonus is then updated, with the player's share deducted.
+	 *
+	 * @param player
+	 * @return playerBonus (the share of the bonus for the party)
+	 */
+	public final int distribAccumulatedBonus(L2PcInstance player)
+	{
+		int playerBonus = 0;
+		String playerName = player.getName();
+		int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);
+		
+		if (playerCabal != SevenSigns.getInstance().getCabalHighestScore())
+			return 0;
+		
+		if (_festivalData.get(_signsCycle) != null)
+			for (StatsSet festivalData : _festivalData.get(_signsCycle).values())
+			{
+				if (festivalData.getString("members").indexOf(playerName) > -1)
+				{
+					int festivalId = festivalData.getInteger("festivalId");
+					int numPartyMembers = festivalData.getString("members").split(",").length;
+					int totalAccumBonus = _accumulatedBonuses.get(festivalId);
+					
+					playerBonus = totalAccumBonus / numPartyMembers;
+					_accumulatedBonuses.set(festivalId, totalAccumBonus - playerBonus);
+					break;
+				}
+			}
+		
+		return playerBonus;
+	}
+	
+	/**
+	 * Used to send a "shout" message to all players currently present in an Oracle.
+	 * Primarily used for Festival Guide and Witch related speech.
+	 *
+	 * @param senderName
+	 * @param message
+	 */
+	public void sendMessageToAll(String senderName, String message)
+	{
+		if (_dawnChatGuide == null || _duskChatGuide == null)
+			return;
+		
+		CreatureSay cs = new CreatureSay(_dawnChatGuide.getObjectId(), Say2.SHOUT, senderName, message);
+		_dawnChatGuide.broadcastPacket(cs);
+		
+		cs = new CreatureSay(_duskChatGuide.getObjectId(), Say2.SHOUT, senderName, message);
+		_duskChatGuide.broadcastPacket(cs);
+	}
+	
+	/**
+	 * Basically a wrapper-call to signal to increase the challenge of the specified festival.
+	 *
+	 * @param oracle
+	 * @param festivalId
+	 * @return boolean isChalIncreased
+	 */
+	public final boolean increaseChallenge(int oracle, int festivalId)
+	{
+		L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);
+		
+		return festivalInst.increaseChallenge();
+	}
+	
+	/**
+	 * Used with the SpawnListener, to update the required "chat guide" instances,
+	 * for use with announcements in the oracles.
+	 *
+	 * @param npc
+	 */
+	public void npcSpawned(L2Npc npc)
+	{
+		if (npc == null)
+			return;
+		
+		int npcId = npc.getNpcId();
+		
+		// If the spawned NPC ID matches the ones we need, assign their instances.
+		if (npcId == 31127)
+		{
+			if (Config.DEBUG)
+				_log.config("SevenSignsFestival: Instance found for NPC ID 31127 (" + npc.getObjectId() + ").");
+			
+			_dawnChatGuide = npc;
+		}
+		
+		if (npcId == 31137)
+		{
+			if (Config.DEBUG)
+				_log.config("SevenSignsFestival: Instance found for NPC ID 31137 (" + npc.getObjectId() + ").");
+			
+			_duskChatGuide = npc;
+		}
+	}
+	
+	/**
+	 * The FestivalManager class is the main runner of all the festivals.
+	 * It is used for easier integration and management of all running festivals.
+	 *
+	 * @author Tempy
+	 */
+	private class FestivalManager implements Runnable
+	{
+		protected Map<Integer, L2DarknessFestival> _festivalInstances;
+		
+		public FestivalManager()
+		{
+			_festivalInstances = new FastMap<Integer, L2DarknessFestival>();
+			_managerInstance = this;
+			
+			// Increment the cycle counter.
+			_festivalCycle++;
+			
+			// Set the next start timers.
+			setNextCycleStart();
+			setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
+		}
+		
+		public synchronized void run()
+		{
+			// The manager shouldn't be running if Seal Validation is in effect.
+			if (SevenSigns.getInstance().isSealValidationPeriod())
+				return;
+			
+			// 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)
+				return;
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Festival manager initialized. Those wishing to participate have " + getMinsToNextFestival()
+						+ " minute(s) to sign up.");
+			
+			sendMessageToAll("Festival Guide", "The main event will start in " + getMinsToNextFestival() + " minutes. Please register now.");
+			
+			// Stand by until the allowed signup period has elapsed.
+			try
+			{
+				wait(FESTIVAL_SIGNUP_TIME);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			// Clear past participants, they can no longer register their score if not done so already.
+			_dawnPreviousParticipants.clear();
+			_duskPreviousParticipants.clear();
+			
+			// Get rid of random monsters that avoided deletion after last festival
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+				festivalInst.unspawnMobs();
+			
+			// Start only if participants signed up
+			_noPartyRegister = true;
+			
+			while (_noPartyRegister)
+			{
+				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);
+						for (L2DarknessFestival festivalInst : _festivalInstances.values())
+						{
+							if (!festivalInst._npcInsts.isEmpty())
+							{
+								festivalInst.unspawnMobs();
+							}
+						}
+					}
+					catch (InterruptedException e)
+					{
+					}
+				}
+				else
+				{
+					_noPartyRegister = false;
+				}
+			}
+			
+			/* INITIATION */
+			// Set the festival timer to 0, as it is just beginning.
+			long elapsedTime = 0;
+			
+			// Create the instances for the festivals in both Oracles,
+			// but only if they have participants signed up for them.
+			for (int i = 0; i < FESTIVAL_COUNT; i++)
+			{
+				if (_duskFestivalParticipants.get(i) != null)
+					_festivalInstances.put(10 + i, new L2DarknessFestival(SevenSigns.CABAL_DUSK, i));
+				
+				if (_dawnFestivalParticipants.get(i) != null)
+					_festivalInstances.put(20 + i, new L2DarknessFestival(SevenSigns.CABAL_DAWN, i));
+			}
+			
+			// Prevent future signups while festival is in progress.
+			_festivalInitialized = true;
+			
+			setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH);
+			sendMessageToAll("Festival Guide", "The main event is now starting.");
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: The current set of festivals will begin in " + (Config.ALT_FESTIVAL_FIRST_SPAWN / 60000)
+						+ " minute(s).");
+			
+			// Stand by for a short length of time before starting the festival.
+			try
+			{
+				wait(Config.ALT_FESTIVAL_FIRST_SPAWN);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			elapsedTime = Config.ALT_FESTIVAL_FIRST_SPAWN;
+			
+			// Participants can now opt to increase the challenge, if desired.
+			_festivalInProgress = true;
+			
+			/* PROPOGATION */
+			// Sequentially set all festivals to begin, spawn the Festival Witch and notify participants.
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+			{
+				festivalInst.festivalStart();
+				festivalInst.sendMessageToParticipants("The festival is about to begin!");
+			}
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Each of the festivals will end in " + (Config.ALT_FESTIVAL_LENGTH / 60000)
+						+ " minutes. New participants can signup then.");
+			
+			// 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);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			elapsedTime += Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN;
+			
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+				festivalInst.moveMonstersToCenter();
+			
+			// Stand by until the time comes for the second spawn.
+			try
+			{
+				wait(Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			// Spawn an extra set of monsters (archers) on the free platforms with
+			// a faster respawn when killed.
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+			{
+				festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN / 2, 2);
+				festivalInst.sendMessageToParticipants("The festival will end in "
+						+ ((Config.ALT_FESTIVAL_LENGTH - Config.ALT_FESTIVAL_SECOND_SPAWN) / 60000) + " minute(s).");
+			}
+			
+			elapsedTime += Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM;
+			
+			// 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);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+				festivalInst.moveMonstersToCenter();
+			
+			elapsedTime += Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN;
+			
+			// Stand by until the time comes for the chests to be spawned.
+			try
+			{
+				wait(Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			// Spawn the festival chests, which enable the team to gain greater rewards
+			// for each chest they kill.
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+			{
+				festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 3);
+				festivalInst.sendMessageToParticipants("The chests have spawned! Be quick, the festival will end soon.");
+			}
+			
+			elapsedTime += Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM;
+			
+			// Stand by and wait until it's time to end the festival.
+			try
+			{
+				wait(Config.ALT_FESTIVAL_LENGTH - elapsedTime);
+			}
+			catch (InterruptedException e)
+			{
+			}
+			
+			// Participants can no longer opt to increase the challenge, as the festival will soon close.
+			_festivalInProgress = false;
+			
+			/* TERMINATION */
+			// Sequentially begin the ending sequence for all running festivals.
+			for (L2DarknessFestival festivalInst : _festivalInstances.values())
+				festivalInst.festivalEnd();
+			
+			// Clear the participants list for the next round of signups.
+			_dawnFestivalParticipants.clear();
+			_duskFestivalParticipants.clear();
+			
+			// Allow signups for the next festival cycle.
+			_festivalInitialized = false;
+			
+			sendMessageToAll("Festival Witch", "That will do! I'll move you to the outside soon.");
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: The next set of festivals begin in " + getMinsToNextFestival() + " minute(s).");
+		}
+		
+		/**
+		 * Returns the running instance of a festival for the given Oracle and festivalID.
+		 * <BR>
+		 * A <B>null</B> value is returned if there are no participants in that festival.
+		 *
+		 * @param oracle
+		 * @param festivalId
+		 * @return L2DarknessFestival festivalInst
+		 */
+		public final L2DarknessFestival getFestivalInstance(int oracle, int festivalId)
+		{
+			if (!isFestivalInitialized())
+				return null;
+			
+			/* Compute the offset if a Dusk instance is required.
+			 *
+			 * ID:	0 1 2 3 4
+			 * Dusk 1:1011121314
+			 * Dawn 2:2021222324
+			 */
+
+			festivalId += (oracle == SevenSigns.CABAL_DUSK) ? 10 : 20;
+			return _festivalInstances.get(festivalId);
+		}
+		
+		/**
+		 * Returns the number of currently running festivals <b>WITH</b> participants.
+		 *
+		 * @return int Count
+		 */
+		public final int getInstanceCount()
+		{
+			return _festivalInstances.size();
+		}
+	}
+	
+	/**
+	 * Each running festival is represented by an L2DarknessFestival class.
+	 * It contains all the spawn information and data for the running festival.
+	 *
+	 * All festivals are managed by the FestivalManager class, which must be initialized first.
+	 *
+	 * @author Tempy
+	 */
+	private class L2DarknessFestival
+	{
+		protected final int _cabal;
+		protected final int _levelRange;
+		protected boolean _challengeIncreased;
+		
+		private FestivalSpawn _startLocation;
+		private FestivalSpawn _witchSpawn;
+		
+		private L2Npc _witchInst;
+		List<L2FestivalMonsterInstance> _npcInsts;
+		
+		private List<L2PcInstance> _participants;
+		private Map<L2PcInstance, FestivalSpawn> _originalLocations;
+		
+		protected L2DarknessFestival(int cabal, int levelRange)
+		{
+			_cabal = cabal;
+			_levelRange = levelRange;
+			_originalLocations = new FastMap<L2PcInstance, FestivalSpawn>();
+			_npcInsts = new FastList<L2FestivalMonsterInstance>();
+			
+			if (cabal == SevenSigns.CABAL_DAWN)
+			{
+				_participants = _dawnFestivalParticipants.get(levelRange);
+				_witchSpawn = new FestivalSpawn(FESTIVAL_DAWN_WITCH_SPAWNS[levelRange]);
+				_startLocation = new FestivalSpawn(FESTIVAL_DAWN_PLAYER_SPAWNS[levelRange]);
+			}
+			else
+			{
+				_participants = _duskFestivalParticipants.get(levelRange);
+				_witchSpawn = new FestivalSpawn(FESTIVAL_DUSK_WITCH_SPAWNS[levelRange]);
+				_startLocation = new FestivalSpawn(FESTIVAL_DUSK_PLAYER_SPAWNS[levelRange]);
+			}
+			
+			// FOR TESTING!
+			if (_participants == null)
+				_participants = new FastList<L2PcInstance>();
+			
+			festivalInit();
+		}
+		
+		protected void festivalInit()
+		{
+			boolean isPositive;
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Initializing festival for " + SevenSigns.getCabalShortName(_cabal) + " ("
+						+ getFestivalName(_levelRange) + ")");
+			
+			// Teleport all players to arena and notify them.
+			if (!_participants.isEmpty())
+			{
+				try
+				{
+					for (L2PcInstance participant : _participants)
+					{
+						_originalLocations.put(participant, new FestivalSpawn(participant.getX(), participant.getY(), participant.getZ(), participant.getHeading()));
+						
+						// Randomize the spawn point around the specific centerpoint for each player.
+						int x = _startLocation._x;
+						int y = _startLocation._y;
+						
+						isPositive = (Rnd.nextInt(2) == 1);
+						
+						if (isPositive)
+						{
+							x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+							y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+						}
+						else
+						{
+							x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+							y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+						}
+						
+						participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
+						participant.teleToLocation(x, y, _startLocation._z, true);
+						
+						// Remove all buffs from all participants on entry. Works like the skill Cancel.
+						participant.stopAllEffects();
+						
+						// Remove any stray blood offerings in inventory
+						L2ItemInstance bloodOfferings = participant.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
+						if (bloodOfferings != null)
+							participant.destroyItem("SevenSigns", bloodOfferings, null, true);
+					}
+				}
+				catch (NullPointerException e)
+				{
+					// deleteMe handling should teleport party out in case of disconnect
+				}
+			}
+			
+			L2NpcTemplate witchTemplate = NpcTable.getInstance().getTemplate(_witchSpawn._npcId);
+			
+			// Spawn the festival witch for this arena
+			try
+			{
+				L2Spawn npcSpawn = new L2Spawn(witchTemplate);
+				
+				npcSpawn.setLocx(_witchSpawn._x);
+				npcSpawn.setLocy(_witchSpawn._y);
+				npcSpawn.setLocz(_witchSpawn._z);
+				npcSpawn.setHeading(_witchSpawn._heading);
+				npcSpawn.setAmount(1);
+				npcSpawn.setRespawnDelay(1);
+				
+				// Needed as doSpawn() is required to be called also for the NpcInstance it returns.
+				npcSpawn.startRespawn();
+				
+				SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
+				_witchInst = npcSpawn.doSpawn();
+				
+				if (Config.DEBUG)
+					_log.fine("SevenSignsFestival: Spawned the Festival Witch " + npcSpawn.getNpcid() + " at " + _witchSpawn._x + " "
+							+ _witchSpawn._y + " " + _witchSpawn._z);
+			}
+			catch (Exception e)
+			{
+				_log.warning("SevenSignsFestival: Error while spawning Festival Witch ID " + _witchSpawn._npcId + ": " + e);
+			}
+			
+			// Make it appear as though the Witch has apparated there.
+			MagicSkillUse msu = new MagicSkillUse(_witchInst, _witchInst, 2003, 1, 1, 0);
+			_witchInst.broadcastPacket(msu);
+			
+			// And another one...:D
+			msu = new MagicSkillUse(_witchInst, _witchInst, 2133, 1, 1, 0);
+			_witchInst.broadcastPacket(msu);
+			
+			// Send a message to all participants from the witch.
+			sendMessageToParticipants("The festival will begin in 2 minutes.");
+		}
+		
+		protected void festivalStart()
+		{
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Starting festival for " + SevenSigns.getCabalShortName(_cabal) + " ("
+						+ getFestivalName(_levelRange) + ")");
+			
+			spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 0);
+		}
+		
+		protected void moveMonstersToCenter()
+		{
+			boolean isPositive;
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Moving spawns to arena center for festival " + SevenSigns.getCabalShortName(_cabal) + " ("
+						+ getFestivalName(_levelRange) + ")");
+			
+			for (L2FestivalMonsterInstance festivalMob : _npcInsts)
+			{
+				if (festivalMob.isDead())
+					continue;
+				
+				// Only move monsters that are idle or doing their usual functions.
+				CtrlIntention currIntention = festivalMob.getAI().getIntention();
+				
+				if (currIntention != CtrlIntention.AI_INTENTION_IDLE && currIntention != CtrlIntention.AI_INTENTION_ACTIVE)
+					continue;
+				
+				int x = _startLocation._x;
+				int y = _startLocation._y;
+				
+				/*
+				 * Random X and Y coords around the player start location, up to half of the
+				 * maximum allowed offset are generated to prevent the mobs from all moving
+				 * to the exact same place.
+				 */
+				isPositive = (Rnd.nextInt(2) == 1);
+				
+				if (isPositive)
+				{
+					x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+					y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+				}
+				else
+				{
+					x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
+					y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
+				}
+				
+				L2CharPosition moveTo = new L2CharPosition(x, y, _startLocation._z, Rnd.nextInt(65536));
+				
+				festivalMob.setRunning();
+				festivalMob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, moveTo);
+			}
+		}
+		
+		public void setSpawnRate(int respawnDelay)
+		{
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Modifying spawn rate of festival mobs to " + respawnDelay + " ms for festival "
+						+ SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
+			
+			for (L2FestivalMonsterInstance monsterInst : _npcInsts)
+				monsterInst.getSpawn().setRespawnDelay(respawnDelay);
+		}
+		
+		/**
+		 * Used to spawn monsters unique to the festival.
+		 * <BR>
+		 * Valid SpawnTypes:<BR>
+		 * 0 - All Primary Monsters (starting monsters)
+		 * <BR>
+		 * 1 - Same as 0, but without archers/marksmen. (used for challenge increase)
+		 * <BR>
+		 * 2 - Secondary Monsters (archers)
+		 * <BR>
+		 * 3 - Festival Chests
+		 *
+		 * @param respawnDelay
+		 * @param spawnType
+		 */
+		protected void spawnFestivalMonsters(int respawnDelay, int spawnType)
+		{
+			int[][] _npcSpawns = null;
+			
+			switch (spawnType)
+			{
+				case 0:
+				case 1:
+					_npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_PRIMARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_PRIMARY_SPAWNS[_levelRange];
+					break;
+				case 2:
+					_npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_SECONDARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_SECONDARY_SPAWNS[_levelRange];
+					break;
+				case 3:
+					_npcSpawns = (_cabal == SevenSigns.CABAL_DAWN) ? FESTIVAL_DAWN_CHEST_SPAWNS[_levelRange] : FESTIVAL_DUSK_CHEST_SPAWNS[_levelRange];
+					break;
+			}
+			
+			for (int i = 0; i < _npcSpawns.length; i++)
+			{
+				FestivalSpawn currSpawn = new FestivalSpawn(_npcSpawns[i]);
+				
+				// Only spawn archers/marksmen if specified to do so.
+				if (spawnType == 1 && isFestivalArcher(currSpawn._npcId))
+					continue;
+				
+				L2NpcTemplate npcTemplate = NpcTable.getInstance().getTemplate(currSpawn._npcId);
+				
+				try
+				{
+					L2Spawn npcSpawn = new L2Spawn(npcTemplate);
+					
+					npcSpawn.setLocx(currSpawn._x);
+					npcSpawn.setLocy(currSpawn._y);
+					npcSpawn.setLocz(currSpawn._z);
+					npcSpawn.setHeading(Rnd.nextInt(65536));
+					npcSpawn.setAmount(1);
+					npcSpawn.setRespawnDelay(respawnDelay);
+					
+					// Needed as doSpawn() is required to be called also for the NpcInstance it returns.
+					npcSpawn.startRespawn();
+					
+					SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
+					L2FestivalMonsterInstance festivalMob = (L2FestivalMonsterInstance) npcSpawn.doSpawn();
+					
+					// Set the offering bonus to 2x or 5x the amount per kill,
+					// if this spawn is part of an increased challenge or is a festival chest.
+					if (spawnType == 1)
+						festivalMob.setOfferingBonus(2);
+					else if (spawnType == 3)
+						festivalMob.setOfferingBonus(5);
+					
+					_npcInsts.add(festivalMob);
+					
+					if (Config.DEBUG)
+						_log.fine("SevenSignsFestival: Spawned NPC ID " + currSpawn._npcId + " at " + currSpawn._x + " " + currSpawn._y
+								+ " " + currSpawn._z);
+				}
+				catch (Exception e)
+				{
+					_log.warning("SevenSignsFestival: Error while spawning NPC ID " + currSpawn._npcId + ": " + e);
+				}
+			}
+		}
+		
+		protected boolean increaseChallenge()
+		{
+			if (_challengeIncreased)
+				return false;
+			
+			// Set this flag to true to make sure that this can only be done once.
+			_challengeIncreased = true;
+			
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: " + _participants.get(0).getName()
+						+ "'s team have opted to increase the festival challenge!");
+			
+			// Spawn more festival monsters, but this time with a twist.
+			spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 1);
+			return true;
+		}
+		
+		public void sendMessageToParticipants(String message)
+		{
+			if (!_participants.isEmpty())
+			{
+				CreatureSay cs = new CreatureSay(_witchInst.getObjectId(), Say2.ALL, "Festival Witch", message);
+				
+				for (L2PcInstance participant : _participants)
+				{
+					try
+					{
+						participant.sendPacket(cs);
+					}
+					catch (NullPointerException e)
+					{
+					}
+				}
+			}
+		}
+		
+		protected void festivalEnd()
+		{
+			if (Config.DEBUG)
+				_log.info("SevenSignsFestival: Ending festival for " + SevenSigns.getCabalShortName(_cabal) + " ("
+						+ getFestivalName(_levelRange) + ")");
+			
+			if (!_participants.isEmpty())
+			{
+				for (L2PcInstance participant : _participants)
+				{
+					try
+					{
+						relocatePlayer(participant, false);
+						participant.sendMessage("The festival has ended. Your party leader must now register your score before the next festival takes place.");
+					}
+					catch (NullPointerException e)
+					{
+					}
+				}
+				
+				if (_cabal == SevenSigns.CABAL_DAWN)
+					_dawnPreviousParticipants.put(_levelRange, _participants);
+				else
+					_duskPreviousParticipants.put(_levelRange, _participants);
+			}
+			_participants = null;
+			
+			unspawnMobs();
+		}
+		
+		protected void unspawnMobs()
+		{
+			// Delete all the NPCs in the current festival arena.
+			if (_witchInst != null)
+			{
+				_witchInst.getSpawn().stopRespawn();
+				_witchInst.deleteMe();
+			}
+			
+			if (_npcInsts != null)
+				for (L2FestivalMonsterInstance monsterInst : _npcInsts)
+					if (monsterInst != null)
+					{
+						monsterInst.getSpawn().stopRespawn();
+						monsterInst.deleteMe();
+					}
+		}
+		
+		public void relocatePlayer(L2PcInstance participant, boolean isRemoving)
+		{
+			try
+			{
+				FestivalSpawn origPosition = _originalLocations.get(participant);
+				
+				if (isRemoving)
+					_originalLocations.remove(participant);
+				
+				participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
+				participant.teleToLocation(origPosition._x, origPosition._y, origPosition._z, true);
+				participant.sendMessage("You have been removed from the festival arena.");
+			}
+			catch (Exception e)
+			{
+				// If an exception occurs, just move the player to the nearest town.
+				try
+				{
+					participant.teleToLocation(MapRegionTable.TeleportWhereType.Town);
+					participant.sendMessage("You have been removed from the festival arena.");
+				}
+				catch (NullPointerException e2)
+				{
+				}
+			}
+		}
+	}
+	
+	private class FestivalSpawn
+	{
+		protected final int _x;
+		protected final int _y;
+		protected final int _z;
+		protected final int _heading;
+		protected final int _npcId;
+		
+		protected FestivalSpawn(int x, int y, int z, int heading)
+		{
+			_x = x;
+			_y = y;
+			_z = z;
+			
+			// Generate a random heading if no positive one given.
+			_heading = (heading < 0) ? Rnd.nextInt(65536) : heading;
+			
+			_npcId = -1;
+		}
+		
+		protected FestivalSpawn(int[] spawnData)
+		{
+			_x = spawnData[0];
+			_y = spawnData[1];
+			_z = spawnData[2];
+			
+			_heading = (spawnData[3] < 0) ? Rnd.nextInt(65536) : spawnData[3];
+			
+			if (spawnData.length > 4)
+				_npcId = spawnData[4];
+			else
+				_npcId = -1;
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SevenSignsFestival _instance = new SevenSignsFestival();
+	}
 }

+ 20 - 21
L2_GameServer/java/net/sf/l2j/gameserver/Shutdown.java

@@ -46,7 +46,6 @@ import net.sf.l2j.gameserver.util.Broadcast;
 public class Shutdown extends Thread
 {
 	private static Logger _log = Logger.getLogger(Shutdown.class.getName());
-	private static Shutdown _instance;
 	private static Shutdown _counterInstance = null;
 	
 	private int _secondsShut;
@@ -55,17 +54,14 @@ public class Shutdown extends Thread
 	public static final int GM_SHUTDOWN = 1;
 	public static final int GM_RESTART = 2;
 	public static final int ABORT = 3;
-	private static final String[] MODE_TEXT =
-	{
-		"SIGTERM", "shutting down", "restarting", "aborting"
-	};
+	private static final String[] MODE_TEXT = { "SIGTERM", "shutting down", "restarting", "aborting" };
 	
 	/**
 	 * This function starts a shutdown countdown from Telnet (Copied from Function startShutdown())
 	 *
-	 * @param ip            IP Which Issued shutdown command
-	 * @param seconds       seconds untill shutdown
-	 * @param restart       true if the server will restart after shutdown
+	 * @param ip IP Which Issued shutdown command
+	 * @param seconds seconds untill shutdown
+	 * @param restart true if the server will restart after shutdown
 	 */
 	private void SendServerQuit(int seconds)
 	{
@@ -125,7 +121,7 @@ public class Shutdown extends Thread
 	/**
 	 * This function aborts a running countdown
 	 *
-	 * @param IP            IP Which Issued shutdown command
+	 * @param IP IP Which Issued shutdown command
 	 */
 	public void telnetAbort(String IP)
 	{
@@ -143,7 +139,7 @@ public class Shutdown extends Thread
 	 * Default constucter is only used internal to create the shutdown-hook instance
 	 *
 	 */
-	public Shutdown()
+	private Shutdown()
 	{
 		_secondsShut = -1;
 		_shutdownMode = SIGTERM;
@@ -182,11 +178,7 @@ public class Shutdown extends Thread
 	 */
 	public static Shutdown getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new Shutdown();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -208,7 +200,7 @@ public class Shutdown extends Thread
 	@Override
 	public void run()
 	{
-		if (this == _instance)
+		if (this == SingletonHolder._instance)
 		{
 			// ensure all services are stopped
 			try
@@ -265,7 +257,7 @@ public class Shutdown extends Thread
 			}
 			
 			// server will quit, when this function ends.
-			if (_instance._shutdownMode == GM_RESTART)
+			if (SingletonHolder._instance._shutdownMode == GM_RESTART)
 			{
 				Runtime.getRuntime().halt(2);
 			}
@@ -283,11 +275,11 @@ public class Shutdown extends Thread
 			switch (_shutdownMode)
 			{
 				case GM_SHUTDOWN:
-					_instance.setMode(GM_SHUTDOWN);
+					SingletonHolder._instance.setMode(GM_SHUTDOWN);
 					System.exit(0);
 					break;
 				case GM_RESTART:
-					_instance.setMode(GM_RESTART);
+					SingletonHolder._instance.setMode(GM_RESTART);
 					System.exit(2);
 					break;
 			}
@@ -303,7 +295,8 @@ public class Shutdown extends Thread
 	 */
 	public void startShutdown(L2PcInstance activeChar, int seconds, boolean restart)
 	{
-		_log.warning("GM: " + activeChar.getName() + "(" + activeChar.getObjectId() + ") issued shutdown command. " + MODE_TEXT[_shutdownMode] + " in " + seconds + " seconds!");
+		_log.warning("GM: " + activeChar.getName() + "(" + activeChar.getObjectId() + ") issued shutdown command. "
+				+ MODE_TEXT[_shutdownMode] + " in " + seconds + " seconds!");
 		
 		if (restart)
 		{
@@ -357,7 +350,8 @@ public class Shutdown extends Thread
 	 */
 	public void abort(L2PcInstance activeChar)
 	{
-		_log.warning("GM: " + activeChar.getName() + "(" + activeChar.getObjectId() + ") issued shutdown ABORT. " + MODE_TEXT[_shutdownMode] + " has been stopped!");
+		_log.warning("GM: " + activeChar.getName() + "(" + activeChar.getObjectId() + ") issued shutdown ABORT. "
+				+ MODE_TEXT[_shutdownMode] + " has been stopped!");
 		if (_counterInstance != null)
 		{
 			_counterInstance._abort();
@@ -586,4 +580,9 @@ public class Shutdown extends Thread
 		}
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final Shutdown _instance = new Shutdown();
+	}
 }

+ 23 - 18
L2_GameServer/java/net/sf/l2j/gameserver/Territory.java

@@ -34,51 +34,56 @@ import net.sf.l2j.gameserver.model.L2Territory;
 public class Territory
 {
 	private static Logger _log = Logger.getLogger(TradeController.class.getName());
-	private static final Territory _instance = new Territory();
-	private static Map<Integer,L2Territory> _territory;
-
+	private static Map<Integer, L2Territory> _territory;
+	
 	public static Territory getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private Territory()
 	{
 		// load all data at server start
 		reload_data();
 	}
-
+	
 	public int[] getRandomPoint(int terr)
 	{
 		return _territory.get(terr).getRandomPoint();
 	}
-
+	
 	public int getProcMax(int terr)
 	{
 		return _territory.get(terr).getProcMax();
 	}
-
+	
 	public void reload_data()
 	{
-		_territory = new FastMap<Integer,L2Territory>();
-
-		Integer[][] point = SqlUtils.get2DIntArray(new String[]{"loc_id","loc_x","loc_y","loc_zmin","loc_zmax","proc"}, "locations", "loc_id > 0");
-		for(Integer[] row : point)
+		_territory = new FastMap<Integer, L2Territory>();
+		
+		Integer[][] point = SqlUtils.get2DIntArray(new String[] { "loc_id", "loc_x", "loc_y", "loc_zmin", "loc_zmax", "proc" }, "locations", "loc_id > 0");
+		for (Integer[] row : point)
 		{
-//			_log.info("row = "+row[0]);
+			//			_log.info("row = "+row[0]);
 			Integer terr = row[0];
-			if(terr == null)
+			if (terr == null)
 			{
 				_log.warning("Null territory!");
 				continue;
 			}
-
-			if(_territory.get(terr) == null)
+			
+			if (_territory.get(terr) == null)
 			{
 				L2Territory t = new L2Territory(terr);
 				_territory.put(terr, t);
-		   	}
-			_territory.get(terr).add(row[1],row[2],row[3],row[4],row[5]);
+			}
+			_territory.get(terr).add(row[1], row[2], row[3], row[4], row[5]);
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final Territory _instance = new Territory();
+	}
 }

+ 274 - 309
L2_GameServer/java/net/sf/l2j/gameserver/ThreadPoolManager.java

@@ -63,9 +63,7 @@ import org.mmocore.network.ReceivablePacket;
  */
 public class ThreadPoolManager
 {
-    protected static final Logger _log = Logger.getLogger(ThreadPoolManager.class.getName());
-    
-	private static ThreadPoolManager _instance;
+	protected static final Logger _log = Logger.getLogger(ThreadPoolManager.class.getName());
 	
 	public ScheduledThreadPoolExecutor _effectsScheduledThreadPool;
 	private ScheduledThreadPoolExecutor _generalScheduledThreadPool;
@@ -75,256 +73,238 @@ public class ThreadPoolManager
 	// will be really used in the next AI implementation.
 	private ThreadPoolExecutor _aiThreadPool;
 	private ThreadPoolExecutor _generalThreadPool;
-
+	
 	// temp
 	private ScheduledThreadPoolExecutor _aiScheduledThreadPool;
-
-    /** temp workaround for VM issue */
-    private static final long MAX_DELAY = Long.MAX_VALUE/1000000/2;
-    
+	
+	/** temp workaround for VM issue */
+	private static final long MAX_DELAY = Long.MAX_VALUE / 1000000 / 2;
+	
 	private boolean _shutdown;
-
+	
 	public static ThreadPoolManager getInstance()
 	{
-		if(_instance == null)
-		{
-			_instance = new ThreadPoolManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private 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));
-
-		_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));
-
+		
+		_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));
+		
 		// will be really used in the next AI implementation.
-		_aiThreadPool = new ThreadPoolExecutor(1, Config.AI_MAX_THREAD,
-			                                      10L, TimeUnit.SECONDS,
-			                                      new LinkedBlockingQueue<Runnable>());
-
+		_aiThreadPool = new ThreadPoolExecutor(1, Config.AI_MAX_THREAD, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
+		
 		_aiScheduledThreadPool = new ScheduledThreadPoolExecutor(Config.AI_MAX_THREAD, new PriorityThreadFactory("AISTPool", Thread.NORM_PRIORITY));
 	}
-    
-    public static long validateDelay(long delay)
-    {
-        if (delay < 0)
-        {
-            delay = 0;
-        }
-        else if (delay > MAX_DELAY)
-        {
-            delay = MAX_DELAY;
-        }
-        return delay;
-    }
-
+	
+	public static long validateDelay(long delay)
+	{
+		if (delay < 0)
+			delay = 0;
+		else if (delay > MAX_DELAY)
+			delay = MAX_DELAY;
+		return delay;
+	}
+	
 	public ScheduledFuture<?> scheduleEffect(Runnable r, long delay)
 	{
 		try
 		{
-            delay = ThreadPoolManager.validateDelay(delay);
-            return _effectsScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
-        }
-        catch (RejectedExecutionException e)
-        {
-            return null;
-        }
+			delay = ThreadPoolManager.validateDelay(delay);
+			return _effectsScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
+		}
+		catch (RejectedExecutionException e)
+		{
+			return null;
+		}
 	}
-
+	
 	public ScheduledFuture<?> scheduleEffectAtFixedRate(Runnable r, long initial, long delay)
 	{
 		try
-        {
-            delay = ThreadPoolManager.validateDelay(delay);
-            initial = ThreadPoolManager.validateDelay(initial);
-            return _effectsScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
-        }
-        catch (RejectedExecutionException e)
-        {
-            return null; /* shutdown, ignore */
-        }
+		{
+			delay = ThreadPoolManager.validateDelay(delay);
+			initial = ThreadPoolManager.validateDelay(initial);
+			return _effectsScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
+		}
+		catch (RejectedExecutionException e)
+		{
+			return null; /* shutdown, ignore */
+		}
 	}
-
+	
 	public ScheduledFuture<?> scheduleGeneral(Runnable r, long delay)
 	{
 		try
-        {
-            delay = ThreadPoolManager.validateDelay(delay);
-            return _generalScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
-        }
-        catch (RejectedExecutionException e)
-        {
-            return null; /* shutdown, ignore */
-        }
-    }
-
+		{
+			delay = ThreadPoolManager.validateDelay(delay);
+			return _generalScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
+		}
+		catch (RejectedExecutionException e)
+		{
+			return null; /* shutdown, ignore */
+		}
+	}
+	
 	public ScheduledFuture<?> scheduleGeneralAtFixedRate(Runnable r, long initial, long delay)
-    {
-        try
-        {
-            delay = ThreadPoolManager.validateDelay(delay);
-            initial = ThreadPoolManager.validateDelay(initial);
-            return _generalScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
-        }
-        catch (RejectedExecutionException e)
-        {
-            return null; /* shutdown, ignore */
-        }
-    }
-
+	{
+		try
+		{
+			delay = ThreadPoolManager.validateDelay(delay);
+			initial = ThreadPoolManager.validateDelay(initial);
+			return _generalScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
+		}
+		catch (RejectedExecutionException e)
+		{
+			return null; /* shutdown, ignore */
+		}
+	}
+	
 	public ScheduledFuture<?> scheduleAi(Runnable r, long delay)
 	{
-        try
-        {
-            delay = ThreadPoolManager.validateDelay(delay);
-            return _aiScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
-        }
-        catch (RejectedExecutionException e)
-        {
-            return null; /* shutdown, ignore */
-        }
-    }
-
+		try
+		{
+			delay = ThreadPoolManager.validateDelay(delay);
+			return _aiScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS);
+		}
+		catch (RejectedExecutionException e)
+		{
+			return null; /* shutdown, ignore */
+		}
+	}
+	
 	public ScheduledFuture<?> scheduleAiAtFixedRate(Runnable r, long initial, long delay)
 	{
-        try
-        {
-            delay = ThreadPoolManager.validateDelay(delay);
-            initial = ThreadPoolManager.validateDelay(initial);
-            return _aiScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
-        }
-        catch (RejectedExecutionException e)
-        {
-            return null; /* shutdown, ignore */
-        }
-    }
-
+		try
+		{
+			delay = ThreadPoolManager.validateDelay(delay);
+			initial = ThreadPoolManager.validateDelay(initial);
+			return _aiScheduledThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
+		}
+		catch (RejectedExecutionException e)
+		{
+			return null; /* shutdown, ignore */
+		}
+	}
+	
 	public void executePacket(ReceivablePacket<L2GameClient> pkt)
 	{
 		_generalPacketsThreadPool.execute(pkt);
 	}
-
+	
 	public void executeIOPacket(ReceivablePacket<L2GameClient> pkt)
 	{
 		_ioPacketsThreadPool.execute(pkt);
 	}
-
+	
 	public void executeTask(Runnable r)
 	{
 		_generalThreadPool.execute(r);
 	}
-
+	
 	public void executeAi(Runnable r)
 	{
 		_aiThreadPool.execute(r);
 	}
-
+	
 	public String[] getStats()
 	{
 		return new String[] {
-		                     "STP:",
-		                     " + Effects:",
-		                     " |- ActiveThreads:   "+_effectsScheduledThreadPool.getActiveCount(),
-		                     " |- getCorePoolSize: "+_effectsScheduledThreadPool.getCorePoolSize(),
-		                     " |- PoolSize:        "+_effectsScheduledThreadPool.getPoolSize(),
-		                     " |- MaximumPoolSize: "+_effectsScheduledThreadPool.getMaximumPoolSize(),
-		                     " |- CompletedTasks:  "+_effectsScheduledThreadPool.getCompletedTaskCount(),
-		                     " |- ScheduledTasks:  "+(_effectsScheduledThreadPool.getTaskCount() - _effectsScheduledThreadPool.getCompletedTaskCount()),
-		                     " | -------",
-		                     " + General:",
-		                     " |- ActiveThreads:   "+_generalScheduledThreadPool.getActiveCount(),
-		                     " |- getCorePoolSize: "+_generalScheduledThreadPool.getCorePoolSize(),
-		                     " |- PoolSize:        "+_generalScheduledThreadPool.getPoolSize(),
-		                     " |- MaximumPoolSize: "+_generalScheduledThreadPool.getMaximumPoolSize(),
-		                     " |- CompletedTasks:  "+_generalScheduledThreadPool.getCompletedTaskCount(),
-		                     " |- ScheduledTasks:  "+(_generalScheduledThreadPool.getTaskCount() - _generalScheduledThreadPool.getCompletedTaskCount()),
-		                     " | -------",
-		                     " + AI:",
-		                     " |- ActiveThreads:   "+_aiScheduledThreadPool.getActiveCount(),
-		                     " |- getCorePoolSize: "+_aiScheduledThreadPool.getCorePoolSize(),
-		                     " |- PoolSize:        "+_aiScheduledThreadPool.getPoolSize(),
-		                     " |- MaximumPoolSize: "+_aiScheduledThreadPool.getMaximumPoolSize(),
-		                     " |- CompletedTasks:  "+_aiScheduledThreadPool.getCompletedTaskCount(),
-		                     " |- ScheduledTasks:  "+(_aiScheduledThreadPool.getTaskCount() - _aiScheduledThreadPool.getCompletedTaskCount()),
-		                     "TP:",
-		                     " + Packets:",
-		                     " |- ActiveThreads:   "+_generalPacketsThreadPool.getActiveCount(),
-		                     " |- getCorePoolSize: "+_generalPacketsThreadPool.getCorePoolSize(),
-		                     " |- MaximumPoolSize: "+_generalPacketsThreadPool.getMaximumPoolSize(),
-		                     " |- LargestPoolSize: "+_generalPacketsThreadPool.getLargestPoolSize(),
-		                     " |- PoolSize:        "+_generalPacketsThreadPool.getPoolSize(),
-		                     " |- CompletedTasks:  "+_generalPacketsThreadPool.getCompletedTaskCount(),
-		                     " |- QueuedTasks:     "+_generalPacketsThreadPool.getQueue().size(),
-		                     " | -------",
-		                     " + I/O Packets:",
-		                     " |- ActiveThreads:   "+_ioPacketsThreadPool.getActiveCount(),
-		                     " |- getCorePoolSize: "+_ioPacketsThreadPool.getCorePoolSize(),
-		                     " |- MaximumPoolSize: "+_ioPacketsThreadPool.getMaximumPoolSize(),
-		                     " |- LargestPoolSize: "+_ioPacketsThreadPool.getLargestPoolSize(),
-		                     " |- PoolSize:        "+_ioPacketsThreadPool.getPoolSize(),
-		                     " |- CompletedTasks:  "+_ioPacketsThreadPool.getCompletedTaskCount(),
-		                     " |- QueuedTasks:     "+_ioPacketsThreadPool.getQueue().size(),
-		                     " | -------",
-		                     " + General Tasks:",
-		                     " |- ActiveThreads:   "+_generalThreadPool.getActiveCount(),
-		                     " |- getCorePoolSize: "+_generalThreadPool.getCorePoolSize(),
-		                     " |- MaximumPoolSize: "+_generalThreadPool.getMaximumPoolSize(),
-		                     " |- LargestPoolSize: "+_generalThreadPool.getLargestPoolSize(),
-		                     " |- PoolSize:        "+_generalThreadPool.getPoolSize(),
-		                     " |- CompletedTasks:  "+_generalThreadPool.getCompletedTaskCount(),
-		                     " |- QueuedTasks:     "+_generalThreadPool.getQueue().size(),
-		                     " | -------",
-		                     " + AI:",
-		                     " |- Not Done"
+				"STP:",
+				" + Effects:",
+				" |- ActiveThreads:   " + _effectsScheduledThreadPool.getActiveCount(),
+				" |- getCorePoolSize: " + _effectsScheduledThreadPool.getCorePoolSize(),
+				" |- PoolSize:        " + _effectsScheduledThreadPool.getPoolSize(),
+				" |- MaximumPoolSize: " + _effectsScheduledThreadPool.getMaximumPoolSize(),
+				" |- CompletedTasks:  " + _effectsScheduledThreadPool.getCompletedTaskCount(),
+				" |- ScheduledTasks:  " + (_effectsScheduledThreadPool.getTaskCount() - _effectsScheduledThreadPool.getCompletedTaskCount()),
+				" | -------",
+				" + General:",
+				" |- ActiveThreads:   " + _generalScheduledThreadPool.getActiveCount(),
+				" |- getCorePoolSize: " + _generalScheduledThreadPool.getCorePoolSize(),
+				" |- PoolSize:        " + _generalScheduledThreadPool.getPoolSize(),
+				" |- MaximumPoolSize: " + _generalScheduledThreadPool.getMaximumPoolSize(),
+				" |- CompletedTasks:  " + _generalScheduledThreadPool.getCompletedTaskCount(),
+				" |- ScheduledTasks:  " + (_generalScheduledThreadPool.getTaskCount() - _generalScheduledThreadPool.getCompletedTaskCount()),
+				" | -------",
+				" + AI:",
+				" |- ActiveThreads:   " + _aiScheduledThreadPool.getActiveCount(),
+				" |- getCorePoolSize: " + _aiScheduledThreadPool.getCorePoolSize(),
+				" |- PoolSize:        " + _aiScheduledThreadPool.getPoolSize(),
+				" |- MaximumPoolSize: " + _aiScheduledThreadPool.getMaximumPoolSize(),
+				" |- CompletedTasks:  " + _aiScheduledThreadPool.getCompletedTaskCount(),
+				" |- ScheduledTasks:  " + (_aiScheduledThreadPool.getTaskCount() - _aiScheduledThreadPool.getCompletedTaskCount()),
+				"TP:",
+				" + Packets:",
+				" |- ActiveThreads:   " + _generalPacketsThreadPool.getActiveCount(),
+				" |- getCorePoolSize: " + _generalPacketsThreadPool.getCorePoolSize(),
+				" |- MaximumPoolSize: " + _generalPacketsThreadPool.getMaximumPoolSize(),
+				" |- LargestPoolSize: " + _generalPacketsThreadPool.getLargestPoolSize(),
+				" |- PoolSize:        " + _generalPacketsThreadPool.getPoolSize(),
+				" |- CompletedTasks:  " + _generalPacketsThreadPool.getCompletedTaskCount(),
+				" |- QueuedTasks:     " + _generalPacketsThreadPool.getQueue().size(),
+				" | -------",
+				" + I/O Packets:",
+				" |- ActiveThreads:   " + _ioPacketsThreadPool.getActiveCount(),
+				" |- getCorePoolSize: " + _ioPacketsThreadPool.getCorePoolSize(),
+				" |- MaximumPoolSize: " + _ioPacketsThreadPool.getMaximumPoolSize(),
+				" |- LargestPoolSize: " + _ioPacketsThreadPool.getLargestPoolSize(),
+				" |- PoolSize:        " + _ioPacketsThreadPool.getPoolSize(),
+				" |- CompletedTasks:  " + _ioPacketsThreadPool.getCompletedTaskCount(),
+				" |- QueuedTasks:     " + _ioPacketsThreadPool.getQueue().size(),
+				" | -------",
+				" + General Tasks:",
+				" |- ActiveThreads:   " + _generalThreadPool.getActiveCount(),
+				" |- getCorePoolSize: " + _generalThreadPool.getCorePoolSize(),
+				" |- MaximumPoolSize: " + _generalThreadPool.getMaximumPoolSize(),
+				" |- LargestPoolSize: " + _generalThreadPool.getLargestPoolSize(),
+				" |- PoolSize:        " + _generalThreadPool.getPoolSize(),
+				" |- CompletedTasks:  " + _generalThreadPool.getCompletedTaskCount(),
+				" |- QueuedTasks:     " + _generalThreadPool.getQueue().size(),
+				" | -------",
+				" + AI:",
+				" |- Not Done"
 		};
 	}
-
-    private class PriorityThreadFactory implements ThreadFactory
-    {
-    	private int _prio;
+	
+	private class PriorityThreadFactory implements ThreadFactory
+	{
+		private int _prio;
 		private String _name;
 		private AtomicInteger _threadNumber = new AtomicInteger(1);
 		private ThreadGroup _group;
-
+		
 		public PriorityThreadFactory(String name, int prio)
-    	{
-    		_prio = prio;
-    		_name = name;
-    		_group = new ThreadGroup(_name);
-    	}
+		{
+			_prio = prio;
+			_name = name;
+			_group = new ThreadGroup(_name);
+		}
+		
 		/* (non-Javadoc)
 		 * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
 		 */
 		public Thread newThread(Runnable r)
 		{
-			Thread t = new Thread(_group,r);
-			t.setName(_name+"-"+_threadNumber.getAndIncrement());
+			Thread t = new Thread(_group, r);
+			t.setName(_name + "-" + _threadNumber.getAndIncrement());
 			t.setPriority(_prio);
 			return t;
 		}
-
+		
 		public ThreadGroup getGroup()
 		{
 			return _group;
 		}
-    }
-
+	}
+	
 	/**
 	 *
 	 */
@@ -333,12 +313,12 @@ public class ThreadPoolManager
 		_shutdown = true;
 		try
 		{
-			_effectsScheduledThreadPool.awaitTermination(1,TimeUnit.SECONDS);
-			_generalScheduledThreadPool.awaitTermination(1,TimeUnit.SECONDS);
-			_generalPacketsThreadPool.awaitTermination(1,TimeUnit.SECONDS);
-			_ioPacketsThreadPool.awaitTermination(1,TimeUnit.SECONDS);
-			_generalThreadPool.awaitTermination(1,TimeUnit.SECONDS);
-			_aiThreadPool.awaitTermination(1,TimeUnit.SECONDS);
+			_effectsScheduledThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+			_generalScheduledThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+			_generalPacketsThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+			_ioPacketsThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+			_generalThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+			_aiThreadPool.awaitTermination(1, TimeUnit.SECONDS);
 			_effectsScheduledThreadPool.shutdown();
 			_generalScheduledThreadPool.shutdown();
 			_generalPacketsThreadPool.shutdown();
@@ -346,7 +326,7 @@ public class ThreadPoolManager
 			_generalThreadPool.shutdown();
 			_aiThreadPool.shutdown();
 			_log.info("All ThreadPools are now stoped");
-
+			
 		}
 		catch (InterruptedException e)
 		{
@@ -354,12 +334,12 @@ public class ThreadPoolManager
 			e.printStackTrace();
 		}
 	}
-
+	
 	public boolean isShutdown()
 	{
 		return _shutdown;
 	}
-
+	
 	/**
 	 *
 	 */
@@ -373,124 +353,109 @@ public class ThreadPoolManager
 		_generalThreadPool.purge();
 		_aiThreadPool.purge();
 	}
-
+	
 	/**
 	 *
 	 */
-	public String getPacketStats() {
-            final StringBuilder sb = new StringBuilder(1000);
-            ThreadFactory tf = _generalPacketsThreadPool.getThreadFactory();
-            if (tf instanceof PriorityThreadFactory) {
-                PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
-                int count = ptf.getGroup().activeCount();
-                Thread[] threads = new Thread[count+2];
-                ptf.getGroup().enumerate(threads);
-                StringUtil.append(sb,
-                        "General Packet Thread Pool:\r\n" +
-                        "Tasks in the queue: ",
-                        String.valueOf(_generalPacketsThreadPool.getQueue().size()),
-                        "\r\n" +
-                        "Showing threads stack trace:\r\n" +
-                        "There should be ",
-                        String.valueOf(count),
-                        " Threads\r\n");
-                for(Thread t : threads) {
-                        if(t == null)
-                                continue;
-
-                        StringUtil.append(sb,
-                                t.getName(),
-                                "\r\n");
-                        for(StackTraceElement ste :t.getStackTrace()) {
-                            StringUtil.append(sb,
-                                    ste.toString(),
-                                    "\r\n");
-                        }
-                }
-            }
-
-            sb.append("Packet Tp stack traces printed.\r\n");
-            
-            return sb.toString();
+	public String getPacketStats()
+	{
+		final StringBuilder sb = new StringBuilder(1000);
+		ThreadFactory tf = _generalPacketsThreadPool.getThreadFactory();
+		if (tf instanceof PriorityThreadFactory)
+		{
+			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
+			int count = ptf.getGroup().activeCount();
+			Thread[] threads = new Thread[count + 2];
+			ptf.getGroup().enumerate(threads);
+			StringUtil.append(sb, "General Packet Thread Pool:\r\n" + "Tasks in the queue: ", String.valueOf(_generalPacketsThreadPool.getQueue().size()), "\r\n"
+					+ "Showing threads stack trace:\r\n" + "There should be ", String.valueOf(count), " Threads\r\n");
+			for (Thread t : threads)
+			{
+				if (t == null)
+					continue;
+				
+				StringUtil.append(sb, t.getName(), "\r\n");
+				for (StackTraceElement ste : t.getStackTrace())
+				{
+					StringUtil.append(sb, ste.toString(), "\r\n");
+				}
+			}
+		}
+		
+		sb.append("Packet Tp stack traces printed.\r\n");
+		
+		return sb.toString();
 	}
-
-	public String getIOPacketStats() {
-            final StringBuilder sb = new StringBuilder(1000);
-            ThreadFactory tf = _ioPacketsThreadPool.getThreadFactory();
-
-            if (tf instanceof PriorityThreadFactory) {
-                PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
-                int count = ptf.getGroup().activeCount();
-                Thread[] threads = new Thread[count+2];
-                ptf.getGroup().enumerate(threads);
-                StringUtil.append(sb,
-                        "I/O Packet Thread Pool:\r\n" +
-                        "Tasks in the queue: ",
-                        String.valueOf(_ioPacketsThreadPool.getQueue().size()),
-                        "\r\n" +
-                        "Showing threads stack trace:\r\n" +
-                        "There should be ",
-                        String.valueOf(count),
-                        " Threads\r\n");
-
-                for(Thread t : threads) {
-                        if(t == null)
-                                continue;
-
-                        StringUtil.append(sb,
-                                t.getName(),
-                                "\r\n");
-                        
-                        for(StackTraceElement ste :t.getStackTrace()) {
-                            StringUtil.append(sb,
-                                    ste.toString(),
-                                    "\r\n");
-                        }
-                }
-            }
-
-            sb.append("Packet Tp stack traces printed.\r\n");
-
-            return sb.toString();
+	
+	public String getIOPacketStats()
+	{
+		final StringBuilder sb = new StringBuilder(1000);
+		ThreadFactory tf = _ioPacketsThreadPool.getThreadFactory();
+		
+		if (tf instanceof PriorityThreadFactory)
+		{
+			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
+			int count = ptf.getGroup().activeCount();
+			Thread[] threads = new Thread[count + 2];
+			ptf.getGroup().enumerate(threads);
+			StringUtil.append(sb, "I/O Packet Thread Pool:\r\n" + "Tasks in the queue: ", String.valueOf(_ioPacketsThreadPool.getQueue().size()), "\r\n"
+					+ "Showing threads stack trace:\r\n" + "There should be ", String.valueOf(count), " Threads\r\n");
+			
+			for (Thread t : threads)
+			{
+				if (t == null)
+					continue;
+				
+				StringUtil.append(sb, t.getName(), "\r\n");
+				
+				for (StackTraceElement ste : t.getStackTrace())
+				{
+					StringUtil.append(sb, ste.toString(), "\r\n");
+				}
+			}
+		}
+		
+		sb.append("Packet Tp stack traces printed.\r\n");
+		
+		return sb.toString();
 	}
-
-	public String getGeneralStats() {
-            final StringBuilder sb = new StringBuilder(1000);
-            ThreadFactory tf = _generalThreadPool.getThreadFactory();
-
-            if (tf instanceof PriorityThreadFactory) {
-                    PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
-                    int count = ptf.getGroup().activeCount();
-                    Thread[] threads = new Thread[count+2];
-                    ptf.getGroup().enumerate(threads);
-                    StringUtil.append(sb,
-                            "General Thread Pool:\r\n" +
-                            "Tasks in the queue: ",
-                            String.valueOf(_generalThreadPool.getQueue().size()),
-                            "\r\n" +
-                            "Showing threads stack trace:\r\n" +
-                            "There should be ",
-                            String.valueOf(count),
-                            " Threads\r\n");
-                    
-                    for(Thread t : threads) {
-                            if(t == null)
-                                    continue;
-
-                            StringUtil.append(sb,
-                                    t.getName(),
-                                    "\r\n");
-
-                            for(StackTraceElement ste :t.getStackTrace()) {
-                                StringUtil.append(sb,
-                                        ste.toString(),
-                                        "\r\n");
-                            }
-                    }
-            }
-
-            sb.append("Packet Tp stack traces printed.\r\n");
-            
-            return sb.toString();
+	
+	public String getGeneralStats()
+	{
+		final StringBuilder sb = new StringBuilder(1000);
+		ThreadFactory tf = _generalThreadPool.getThreadFactory();
+		
+		if (tf instanceof PriorityThreadFactory)
+		{
+			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
+			int count = ptf.getGroup().activeCount();
+			Thread[] threads = new Thread[count + 2];
+			ptf.getGroup().enumerate(threads);
+			StringUtil.append(sb, "General Thread Pool:\r\n" + "Tasks in the queue: ", String.valueOf(_generalThreadPool.getQueue().size()), "\r\n"
+					+ "Showing threads stack trace:\r\n" + "There should be ", String.valueOf(count), " Threads\r\n");
+			
+			for (Thread t : threads)
+			{
+				if (t == null)
+					continue;
+				
+				StringUtil.append(sb, t.getName(), "\r\n");
+				
+				for (StackTraceElement ste : t.getStackTrace())
+				{
+					StringUtil.append(sb, ste.toString(), "\r\n");
+				}
+			}
+		}
+		
+		sb.append("Packet Tp stack traces printed.\r\n");
+		
+		return sb.toString();
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ThreadPoolManager _instance = new ThreadPoolManager();
 	}
 }

+ 325 - 307
L2_GameServer/java/net/sf/l2j/gameserver/TradeController.java

@@ -38,312 +38,330 @@ import net.sf.l2j.gameserver.model.L2TradeList.L2TradeItem;
  */
 public class TradeController
 {
-    private static Logger _log = Logger.getLogger(TradeController.class.getName());
-    private static TradeController _instance;
-    
-    private int _nextListId;
-    private Map<Integer, L2TradeList> _lists= new FastMap<Integer, L2TradeList>();
-    
-    /** Task launching the function for restore count of Item (Clan Hall) */
-    /*public class RestoreCount implements Runnable
-    {
-        private int _timer;
-        
-        public RestoreCount(int time)
-        {
-            _timer = time;
-        }
-        
-        public void run()
-        {
-            restoreCount(_timer);
-            dataTimerSave(_timer);
-            ThreadPoolManager.getInstance().scheduleGeneral(new RestoreCount(_timer), (long)_timer*60*60*1000);
-        }
-    }*/
-    
-    public static TradeController getInstance()
-    {
-        if (_instance == null)
-        {
-            _instance = new TradeController();
-        }
-        return _instance;
-    }
-    
-    private TradeController()
-    {
-        _lists.clear();
-        Connection con = null;
-        
-        /*
-         * Initialize Shop buylist
-         */
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-            PreparedStatement statement1 = con.prepareStatement("SELECT  shop_id, npc_id FROM merchant_shopids");
-            ResultSet rset1 = statement1.executeQuery();
-            
-            int itemId, price, maxCount, currentCount, time;
-            long saveTimer;
-            while (rset1.next())
-            {
-                PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, "+L2DatabaseFactory.getInstance().safetyString("order")+", count, currentCount, time, savetimer FROM merchant_buylists WHERE shop_id=? ORDER BY "+L2DatabaseFactory.getInstance().safetyString("order")+" ASC");
-                statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
-                ResultSet rset = statement.executeQuery();
-                L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
-                
-                while (rset.next())
-                {
-                    itemId = rset.getInt("item_id");
-                    price = rset.getInt("price");
-                    maxCount = rset.getInt("count");
-                    currentCount = rset.getInt("currentCount");
-                    time = rset.getInt("time");
-                    saveTimer = rset.getLong("saveTimer");
-                    
-                    L2TradeItem item = new L2TradeItem(itemId);
-                    if (ItemTable.getInstance().getTemplate(itemId) == null)
-                    {
-                        _log.warning("Skipping itemId: "+itemId+" on buylistId: "+buy1.getListId()+", missing data for that item.");
-                        continue;
-                    }
-                    
-                    if (price <= -1)
-                    {
-                        price = ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
-                    }
-                    
-                    if (Config.DEBUG)
-                    {
-                        // debug
-                        double diff = ((double) (price)) / ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
-                        if (diff < 0.8 || diff > 1.2)
-                        {
-                            _log.severe("PRICING DEBUG: TradeListId: "+buy1.getListId()+" -  ItemId: "+itemId+" ("+ItemTable.getInstance().getTemplate(itemId).getName()+") diff: "+diff+" - Price: "+price+" - Reference: "+ItemTable.getInstance().getTemplate(itemId).getReferencePrice());
-                        }
-                    }
-                    
-                    item.setPrice(price);
-                    
-                    item.setRestoreDelay(time);
-                    item.setNextRestoreTime(saveTimer);
-                    item.setMaxCount(maxCount);
-                    
-                    if (currentCount > -1)
-                    {
-                        item.setCurrentCount(currentCount);
-                    }
-                    else
-                    {
-                        item.setCurrentCount(maxCount);
-                    }
-                    
-                    buy1.addItem(item);
-                }
-                
-                buy1.setNpcId(rset1.getString("npc_id"));
-                _lists.put(buy1.getListId(), buy1);
-                _nextListId = Math.max(_nextListId, buy1.getListId() + 1);
-                
-                rset.close();
-                statement.close();
-            }
-            rset1.close();
-            statement1.close();
-            
-            _log.config("TradeController: Loaded " + _lists.size() + " Buylists.");
-        }
-        catch (Exception e)
-        {
-            // problem with initializing spawn, go to next one
-            _log.warning("TradeController: Buylists could not be initialized.");
-            e.printStackTrace();
-        }
-        finally
-        {
-            try
-            {
-                con.close();
-            }
-            catch (Exception e)
-            {
-                
-            }
-        }
-        
-        /*
-         * If enabled, initialize the custom buylist
-         */
-        if (Config.CUSTOM_MERCHANT_TABLES)
-        {
-            try
-            {
-                int initialSize = _lists.size();
-                con = L2DatabaseFactory.getInstance().getConnection();
-                PreparedStatement statement1 = con.prepareStatement("SELECT  shop_id, npc_id FROM custom_merchant_shopids");
-                ResultSet rset1 = statement1.executeQuery();
-                
-                int itemId, price, maxCount, currentCount, time;
-                long saveTimer;
-                while (rset1.next())
-                {
-                    PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, "+L2DatabaseFactory.getInstance().safetyString("order")+", count, currentCount, time, savetimer FROM custom_merchant_buylists WHERE shop_id=? ORDER BY "+L2DatabaseFactory.getInstance().safetyString("order")+" ASC");
-                    statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
-                    ResultSet rset = statement.executeQuery();
-                    L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
-                    
-                    while (rset.next())
-                    {
-                        itemId = rset.getInt("item_id");
-                        price = rset.getInt("price");
-                        maxCount = rset.getInt("count");
-                        currentCount = rset.getInt("currentCount");
-                        time = rset.getInt("time");
-                        saveTimer = rset.getLong("saveTimer");
-                        
-                        L2TradeItem item = new L2TradeItem(itemId);
-                        if (ItemTable.getInstance().getTemplate(itemId) == null)
-                        {
-                            _log.warning("Skipping itemId: "+itemId+" on buylistId: "+buy1.getListId()+", missing data for that item.");
-                            continue;
-                        }
-                        
-                        if (price <= -1)
-                        {
-                            price = ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
-                        }
-                        
-                        if (Config.DEBUG)
-                        {
-                            // debug
-                            double diff = ((double) (price)) / ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
-                            if (diff < 0.8 || diff > 1.2)
-                            {
-                                _log.severe("PRICING DEBUG: TradeListId: "+buy1.getListId()+" -  ItemId: "+itemId+" ("+ItemTable.getInstance().getTemplate(itemId).getName()+") diff: "+diff+" - Price: "+price+" - Reference: "+ItemTable.getInstance().getTemplate(itemId).getReferencePrice());
-                            }
-                        }
-                        
-                        item.setPrice(price);
-                        
-                        item.setRestoreDelay(time);
-                        item.setNextRestoreTime(saveTimer);
-                        item.setMaxCount(maxCount);
-                        
-                        if (currentCount > -1)
-                        {
-                            item.setCurrentCount(currentCount);
-                        }
-                        else
-                        {
-                            item.setCurrentCount(maxCount);
-                        }
-                        
-                        buy1.addItem(item);
-                    }
-                    
-                    buy1.setNpcId(rset1.getString("npc_id"));
-                    _lists.put(buy1.getListId(), buy1);
-                    _nextListId = Math.max(_nextListId, buy1.getListId() + 1);
-                    
-                    rset.close();
-                    statement.close();
-                }
-                rset1.close();
-                statement1.close();
-                
-                _log.config("TradeController: Loaded " + (_lists.size() - initialSize) + " Custom Buylists.");
+	private static Logger _log = Logger.getLogger(TradeController.class.getName());
+	
+	private int _nextListId;
+	private Map<Integer, L2TradeList> _lists = new FastMap<Integer, L2TradeList>();
+	
+	/** Task launching the function for restore count of Item (Clan Hall) */
+	/*public class RestoreCount implements Runnable
+	{
+		private int _timer;
+		
+		public RestoreCount(int time)
+		{
+			_timer = time;
+		}
+		
+		public void run()
+		{
+			restoreCount(_timer);
+			dataTimerSave(_timer);
+			ThreadPoolManager.getInstance().scheduleGeneral(new RestoreCount(_timer), (long)_timer*60*60*1000);
+		}
+	}*/
 
-            }
-            catch (Exception e)
-            {
-                // problem with initializing spawn, go to next one
-                _log.warning("TradeController: Buylists could not be initialized.");
-                e.printStackTrace();
-            }
-            finally
-            {
-                try
-                {
-                    con.close();
-                }
-                catch (Exception e)
-                {
-                    
-                }
-            }
-        }
-    }
-    
-    public L2TradeList getBuyList(int listId)
-    {
-        return _lists.get(listId);
-    }
-    
-    public List<L2TradeList> getBuyListByNpcId(int npcId)
-    {
-        List<L2TradeList> lists = new FastList<L2TradeList>();
-        Collection<L2TradeList> values = _lists.values();
-        
-        for (L2TradeList list : values)
-        {
-            String tradeNpcId = list.getNpcId();
-            if (tradeNpcId.startsWith("gm"))
-                continue;
-            if (npcId == Integer.parseInt(tradeNpcId))
-                lists.add(list);
-        }
-        return lists;
-    }
-    
-    
-    
-    public void dataCountStore()
-    {
-        Connection con = null;
-        PreparedStatement statement;
-        
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-            
-            for (L2TradeList list : _lists.values())
-            {
-                if (list.hasLimitedStockItem())
-                {
-                    
-                    int listId = list.getListId();
-                    
-                    for (L2TradeItem item :list.getItems())
-                    {
-                        if (item.hasLimitedStock() && item.getCurrentCount() < item.getMaxCount()) //needed?
-                        {
-                            statement = con.prepareStatement("UPDATE merchant_buylists SET currentCount=? WHERE item_id=? AND shop_id=?");
-                            statement.setLong(1, item.getCurrentCount());
-                            statement.setInt(2, item.getItemId());
-                            statement.setInt(3, listId);
-                            statement.executeUpdate();
-                            statement.close();
-                        }
-                    }
-                }
-            }
-        }
-        catch (Exception e)
-        {
-            _log.log(Level.SEVERE, "TradeController: Could not store Count Item" );
-        }
-        finally
-        {
-            try { con.close(); } catch (Exception e) { e.printStackTrace(); }
-        }
-    }
-    /**
-     * @return
-     */
-    public synchronized int getNextId()
-    {
-        return _nextListId++;
-    }
+	public static TradeController getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private TradeController()
+	{
+		_lists.clear();
+		Connection con = null;
+		
+		/*
+		 * Initialize Shop buylist
+		 */
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement1 = con.prepareStatement("SELECT  shop_id, npc_id FROM merchant_shopids");
+			ResultSet rset1 = statement1.executeQuery();
+			
+			int itemId, price, maxCount, currentCount, time;
+			long saveTimer;
+			while (rset1.next())
+			{
+				PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, "
+						+ L2DatabaseFactory.getInstance().safetyString("order")
+						+ ", count, currentCount, time, savetimer FROM merchant_buylists WHERE shop_id=? ORDER BY "
+						+ L2DatabaseFactory.getInstance().safetyString("order") + " ASC");
+				statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
+				ResultSet rset = statement.executeQuery();
+				L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
+				
+				while (rset.next())
+				{
+					itemId = rset.getInt("item_id");
+					price = rset.getInt("price");
+					maxCount = rset.getInt("count");
+					currentCount = rset.getInt("currentCount");
+					time = rset.getInt("time");
+					saveTimer = rset.getLong("saveTimer");
+					
+					L2TradeItem item = new L2TradeItem(itemId);
+					if (ItemTable.getInstance().getTemplate(itemId) == null)
+					{
+						_log.warning("Skipping itemId: " + itemId + " on buylistId: " + buy1.getListId() + ", missing data for that item.");
+						continue;
+					}
+					
+					if (price <= -1)
+					{
+						price = ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
+					}
+					
+					if (Config.DEBUG)
+					{
+						// debug
+						double diff = ((double) (price)) / ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
+						if (diff < 0.8 || diff > 1.2)
+						{
+							_log.severe("PRICING DEBUG: TradeListId: " + buy1.getListId() + " -  ItemId: " + itemId + " ("
+									+ ItemTable.getInstance().getTemplate(itemId).getName() + ") diff: " + diff + " - Price: " + price
+									+ " - Reference: " + ItemTable.getInstance().getTemplate(itemId).getReferencePrice());
+						}
+					}
+					
+					item.setPrice(price);
+					
+					item.setRestoreDelay(time);
+					item.setNextRestoreTime(saveTimer);
+					item.setMaxCount(maxCount);
+					
+					if (currentCount > -1)
+					{
+						item.setCurrentCount(currentCount);
+					}
+					else
+					{
+						item.setCurrentCount(maxCount);
+					}
+					
+					buy1.addItem(item);
+				}
+				
+				buy1.setNpcId(rset1.getString("npc_id"));
+				_lists.put(buy1.getListId(), buy1);
+				_nextListId = Math.max(_nextListId, buy1.getListId() + 1);
+				
+				rset.close();
+				statement.close();
+			}
+			rset1.close();
+			statement1.close();
+			
+			_log.config("TradeController: Loaded " + _lists.size() + " Buylists.");
+		}
+		catch (Exception e)
+		{
+			// problem with initializing spawn, go to next one
+			_log.warning("TradeController: Buylists could not be initialized.");
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+				
+			}
+		}
+		
+		/*
+		 * If enabled, initialize the custom buylist
+		 */
+		if (Config.CUSTOM_MERCHANT_TABLES)
+		{
+			try
+			{
+				int initialSize = _lists.size();
+				con = L2DatabaseFactory.getInstance().getConnection();
+				PreparedStatement statement1 = con.prepareStatement("SELECT  shop_id, npc_id FROM custom_merchant_shopids");
+				ResultSet rset1 = statement1.executeQuery();
+				
+				int itemId, price, maxCount, currentCount, time;
+				long saveTimer;
+				while (rset1.next())
+				{
+					PreparedStatement statement = con.prepareStatement("SELECT item_id, price, shop_id, "
+							+ L2DatabaseFactory.getInstance().safetyString("order")
+							+ ", count, currentCount, time, savetimer FROM custom_merchant_buylists WHERE shop_id=? ORDER BY "
+							+ L2DatabaseFactory.getInstance().safetyString("order") + " ASC");
+					statement.setString(1, String.valueOf(rset1.getInt("shop_id")));
+					ResultSet rset = statement.executeQuery();
+					L2TradeList buy1 = new L2TradeList(rset1.getInt("shop_id"));
+					
+					while (rset.next())
+					{
+						itemId = rset.getInt("item_id");
+						price = rset.getInt("price");
+						maxCount = rset.getInt("count");
+						currentCount = rset.getInt("currentCount");
+						time = rset.getInt("time");
+						saveTimer = rset.getLong("saveTimer");
+						
+						L2TradeItem item = new L2TradeItem(itemId);
+						if (ItemTable.getInstance().getTemplate(itemId) == null)
+						{
+							_log.warning("Skipping itemId: " + itemId + " on buylistId: " + buy1.getListId()
+									+ ", missing data for that item.");
+							continue;
+						}
+						
+						if (price <= -1)
+						{
+							price = ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
+						}
+						
+						if (Config.DEBUG)
+						{
+							// debug
+							double diff = ((double) (price)) / ItemTable.getInstance().getTemplate(itemId).getReferencePrice();
+							if (diff < 0.8 || diff > 1.2)
+							{
+								_log.severe("PRICING DEBUG: TradeListId: " + buy1.getListId() + " -  ItemId: " + itemId + " ("
+										+ ItemTable.getInstance().getTemplate(itemId).getName() + ") diff: " + diff + " - Price: " + price
+										+ " - Reference: " + ItemTable.getInstance().getTemplate(itemId).getReferencePrice());
+							}
+						}
+						
+						item.setPrice(price);
+						
+						item.setRestoreDelay(time);
+						item.setNextRestoreTime(saveTimer);
+						item.setMaxCount(maxCount);
+						
+						if (currentCount > -1)
+						{
+							item.setCurrentCount(currentCount);
+						}
+						else
+						{
+							item.setCurrentCount(maxCount);
+						}
+						
+						buy1.addItem(item);
+					}
+					
+					buy1.setNpcId(rset1.getString("npc_id"));
+					_lists.put(buy1.getListId(), buy1);
+					_nextListId = Math.max(_nextListId, buy1.getListId() + 1);
+					
+					rset.close();
+					statement.close();
+				}
+				rset1.close();
+				statement1.close();
+				
+				_log.config("TradeController: Loaded " + (_lists.size() - initialSize) + " Custom Buylists.");
+				
+			}
+			catch (Exception e)
+			{
+				// problem with initializing spawn, go to next one
+				_log.warning("TradeController: Buylists could not be initialized.");
+				e.printStackTrace();
+			}
+			finally
+			{
+				try
+				{
+					con.close();
+				}
+				catch (Exception e)
+				{
+					
+				}
+			}
+		}
+	}
+	
+	public L2TradeList getBuyList(int listId)
+	{
+		return _lists.get(listId);
+	}
+	
+	public List<L2TradeList> getBuyListByNpcId(int npcId)
+	{
+		List<L2TradeList> lists = new FastList<L2TradeList>();
+		Collection<L2TradeList> values = _lists.values();
+		
+		for (L2TradeList list : values)
+		{
+			String tradeNpcId = list.getNpcId();
+			if (tradeNpcId.startsWith("gm"))
+				continue;
+			if (npcId == Integer.parseInt(tradeNpcId))
+				lists.add(list);
+		}
+		return lists;
+	}
+	
+	public void dataCountStore()
+	{
+		Connection con = null;
+		PreparedStatement statement;
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			for (L2TradeList list : _lists.values())
+			{
+				if (list.hasLimitedStockItem())
+				{
+					
+					int listId = list.getListId();
+					
+					for (L2TradeItem item : list.getItems())
+					{
+						if (item.hasLimitedStock() && item.getCurrentCount() < item.getMaxCount()) //needed?
+						{
+							statement = con.prepareStatement("UPDATE merchant_buylists SET currentCount=? WHERE item_id=? AND shop_id=?");
+							statement.setLong(1, item.getCurrentCount());
+							statement.setInt(2, item.getItemId());
+							statement.setInt(3, listId);
+							statement.executeUpdate();
+							statement.close();
+						}
+					}
+				}
+			}
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.SEVERE, "TradeController: Could not store Count Item");
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	/**
+	 * @return
+	 */
+	public synchronized int getNextId()
+	{
+		return _nextListId++;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final TradeController _instance = new TradeController();
+	}
 }

+ 474 - 464
L2_GameServer/java/net/sf/l2j/gameserver/Universe.java

@@ -43,470 +43,480 @@ import net.sf.l2j.gameserver.model.L2CharPosition;
 
 public class Universe implements java.io.Serializable
 {
-
-    /**
-     * Comment for <code>serialVersionUID</code>
-     */
-    private static final long serialVersionUID = -2040223695811104704L;
-    public static final int MIN_X = -127900;
-    public static final int MAX_X = 194327;
-    public static final int MIN_Y = -30000;
-    public static final int MAX_Y = 259536;
-    public static final int MIN_Z = -17000;
-    public static final int MAX_Z = 17000;
-    public static final int MIN_X_GRID = 60;
-    public static final int MIN_Y_GRID = 60;
-    public static final int MIN_Z_GRID = 60;
-    public static final int MIN_GRID = 360;
-    private static Universe _instance;
-    protected static final Logger _log = Logger.getLogger(Universe.class.getName());
-
-    protected List<Coord> _coordList;
-
-    private HashSet<Integer> _logPlayers;
-    private boolean _logAll = true;
-
-
-    public static void main(String[] args)
-    {
-        Universe u = new Universe();
-        u.load();
-        //u.removeDoubles();
-        u.implode(false);
-    }
-
-    private class Position implements Comparable<Position>, java.io.Serializable
-    {
-        /**
-         * Comment for <code>serialVersionUID</code>
-         */
-        private static final long serialVersionUID = -8798746764450022287L;
-        protected int _x;
-        protected int _flag;
-        protected int _y;
-        protected int _z;
-
-        public Position(int x, int y, int z, int flag)
-        {
-            _x = x;
-            _y = y;
-            _z = z;
-            _flag = flag;
-        }
-
-        public Position(L2CharPosition pos)
-        {
-            _x = pos.x;
-            _y = pos.y;
-            _z = pos.z;
-            _flag = 0;
-        }
-
-        @Deprecated
-        public L2CharPosition l2CP()
-        {
-            return new L2CharPosition(_x, _y, _z, 0);
-        }
-
-        public int compareTo(Position obj)
-        {
-            int res = Integer.valueOf(_x).compareTo(obj._x);
-            if (res != 0) return res;
-            res = Integer.valueOf(_y).compareTo(obj._y);
-            if (res != 0) return res;
-            res = Integer.valueOf(_z).compareTo(obj._z);
-            return res;
-        }
-
-        @Override
+	
+	/**
+	 * Comment for <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = -2040223695811104704L;
+	public static final int MIN_X = -127900;
+	public static final int MAX_X = 194327;
+	public static final int MIN_Y = -30000;
+	public static final int MAX_Y = 259536;
+	public static final int MIN_Z = -17000;
+	public static final int MAX_Z = 17000;
+	public static final int MIN_X_GRID = 60;
+	public static final int MIN_Y_GRID = 60;
+	public static final int MIN_Z_GRID = 60;
+	public static final int MIN_GRID = 360;
+	protected static final Logger _log = Logger.getLogger(Universe.class.getName());
+	
+	protected List<Coord> _coordList;
+	
+	private HashSet<Integer> _logPlayers;
+	private boolean _logAll = true;
+	
+	public static void main(String[] args)
+	{
+		Universe u = new Universe();
+		u.load();
+		//u.removeDoubles();
+		u.implode(false);
+	}
+	
+	private class Position implements Comparable<Position>, java.io.Serializable
+	{
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = -8798746764450022287L;
+		protected int _x;
+		protected int _flag;
+		protected int _y;
+		protected int _z;
+		
+		public Position(int x, int y, int z, int flag)
+		{
+			_x = x;
+			_y = y;
+			_z = z;
+			_flag = flag;
+		}
+		
+		public Position(L2CharPosition pos)
+		{
+			_x = pos.x;
+			_y = pos.y;
+			_z = pos.z;
+			_flag = 0;
+		}
+		
+		@Deprecated
+		public L2CharPosition l2CP()
+		{
+			return new L2CharPosition(_x, _y, _z, 0);
+		}
+		
+		public int compareTo(Position obj)
+		{
+			int res = Integer.valueOf(_x).compareTo(obj._x);
+			if (res != 0)
+				return res;
+			res = Integer.valueOf(_y).compareTo(obj._y);
+			if (res != 0)
+				return res;
+			res = Integer.valueOf(_z).compareTo(obj._z);
+			return res;
+		}
+		
+		@Override
 		public String toString()
-        {
-            return String.valueOf(_x) + " " + _y + " " + _z + " " + _flag;
-        }
-    }
-
-    private class Coord implements Comparable<Position>, java.io.Serializable
-    {
-        /**
-         * Comment for <code>serialVersionUID</code>
-         */
-        private static final long serialVersionUID = -558060332886829552L;
-        protected int _x;
-        protected int _y;
-        protected int _z;
-
-        public Coord(int x, int y, int z)
-        {
-            _x = x;
-            _y = y;
-            _z = z;
-        }
-
-        public Coord(L2CharPosition pos)
-        {
-            _x = pos.x;
-            _y = pos.y;
-            _z = pos.z;
-        }
-
-        public int compareTo(Position obj)
-        {
-            int res = Integer.valueOf(_x).compareTo(obj._x);
-            if (res != 0) return res;
-            res = Integer.valueOf(_y).compareTo(obj._y);
-            if (res != 0) return res;
-            res = Integer.valueOf(_z).compareTo(obj._z);
-            return res;
-        }
-
-        @Override
+		{
+			return String.valueOf(_x) + " " + _y + " " + _z + " " + _flag;
+		}
+	}
+	
+	private class Coord implements Comparable<Position>, java.io.Serializable
+	{
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = -558060332886829552L;
+		protected int _x;
+		protected int _y;
+		protected int _z;
+		
+		public Coord(int x, int y, int z)
+		{
+			_x = x;
+			_y = y;
+			_z = z;
+		}
+		
+		public Coord(L2CharPosition pos)
+		{
+			_x = pos.x;
+			_y = pos.y;
+			_z = pos.z;
+		}
+		
+		public int compareTo(Position obj)
+		{
+			int res = Integer.valueOf(_x).compareTo(obj._x);
+			if (res != 0)
+				return res;
+			res = Integer.valueOf(_y).compareTo(obj._y);
+			if (res != 0)
+				return res;
+			res = Integer.valueOf(_z).compareTo(obj._z);
+			return res;
+		}
+		
+		@Override
 		public String toString()
-        {
-            return String.valueOf(_x) + " " + _y + " " + _z;
-        }
-    }
-
-    public static Universe getInstance()
-    {
-        if (_instance == null && Config.ACTIVATE_POSITION_RECORDER)
-        {
-            _instance = new Universe();
-        }
-        return _instance;
-    }
-
-    private Universe()
-    {
-        _coordList = new LinkedList<Coord>();
-        _logPlayers = new HashSet<Integer>();
-
-        ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new UniverseDump(), 30000, 30000);
-    }
-
-    public void registerHeight(int x, int y, int z)
-    {
-        // don't overwrite obstacle entries
-        //Position p  = new Position(x, y, z, 0);
-        //_map.add(p);
-        _coordList.add(new Coord(x, y, z));
-    }
-
-    public void registerObstacle(int x, int y, int z)
-    {
-        //Position p = new Position(x, y, z, -1);
-        //_map.add(p);
-        _coordList.add(new Coord(x, y, z));
-    }
-
-    public boolean shouldLog(Integer id)
-    {
-        return (_logPlayers.contains(id) || _logAll);
-    }
-
-    public void setLogAll(boolean flag)
-    {
-        _logAll = flag;
-    }
-
-    public void addLogPlayer(Integer id)
-    {
-        _logPlayers.add(id);
-        _logAll = false;
-    }
-
-    public void removeLogPlayer(Integer id)
-    {
-        _logPlayers.remove(id);
-    }
-
-    public void loadAscii()
-    {
-        int initialSize = _coordList.size();
-        BufferedReader r = null;
-        try
-        {
-            r = new BufferedReader(new FileReader("data/universe.txt"));
-            String line;
-            while ((line = r.readLine()) != null)
-            {
-                StringTokenizer st = new StringTokenizer(line);
-                String x1 = st.nextToken();
-                String y1 = st.nextToken();
-                String z1 = st.nextToken();
-                //                String f1 = st.nextToken();
-                int x = Integer.parseInt(x1);
-                int y = Integer.parseInt(y1);
-                int z = Integer.parseInt(z1);
-                //                int f = Integer.parseInt(f1);
-                _coordList.add(new Coord(x, y, z));
-            }
-            _log.info((_coordList.size() - initialSize) + " additional nodes loaded from text file.");
-        }
-        catch (Exception e)
-        {
-            _log.info("could not read text file universe.txt");
-        }
-        finally
-        {
-        	try
-        	{
-        		r.close();
-        	}
-        	catch (Exception e)
-        	{
-        	}
-        }
-    }
-
-    public void createMap()
-    {
-        int zoom = 100;
-        int w = (MAX_X - MIN_X) / zoom;
-        int h = (MAX_Y - MIN_Y) / zoom;
-        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_GRAY);
-        Graphics2D gr = bi.createGraphics();
-        int min_z = 0, max_z = 0;
-        for (Coord pos : _coordList)
-        {
-            if (pos == null) continue;
-
-            if (pos._z < min_z) min_z = pos._z;
-            if (pos._z > max_z) max_z = pos._z;
-        }
-        for (Coord pos : _coordList)
-        {
-            if (pos == null) continue;
-
-            int x = (pos._x - MIN_X) / zoom;
-            int y = (pos._y - MIN_Y) / zoom;
-            int color = (int) (((long) pos._z - MIN_Z) * 0xFFFFFF / (MAX_Z - MIN_Z));
-            gr.setColor(new Color(color));
-            gr.drawLine(x, y, x, y);
-        }
-        try
-        {
-            ImageIO.write(bi, "png", new File("universe.png"));
-        }
-        catch (Exception e)
-        {
-            _log.warning("cannot create universe.png: " + e);
-        }
-    }
-
-    public class UniverseFilter implements FilenameFilter
-    {
-        String _ext = "";
-
-        public UniverseFilter(String pExt)
-        {
-            _ext = pExt;
-        }
-
-        /* (non-Javadoc)
-         * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
-         */
-        public boolean accept(File arg0, String name)
-        {
-            return name.startsWith("universe") && name.endsWith("." + _ext);
-        }
-
-    }
-
-    public void load()
-    {
-        int total = 0;
-        if (_coordList == null)
-        {
-            _coordList = new LinkedList<Coord>();
-        }
-        try
-        {
-            loadBinFiles();
-
-            loadHexFiles();
-
-            loadFinFiles();
-
-            _log.info(_coordList.size() + " map vertices loaded in total.");
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-        _log.info("Total: " + total);
-    }
-
-    /**
-     * @throws FileNotFoundException
-     * @throws IOException
-     */
-    private void loadFinFiles() throws FileNotFoundException, IOException
-    {
-        FilenameFilter filter = new UniverseFilter("fin");
-        File directory = new File("data");
-        File[] files = directory.listFiles(filter);
-        for (File file : files)
-        {
-            FileInputStream fos = new FileInputStream(file); // Save to file
-            DataInputStream data = new DataInputStream(fos);
-            int count = data.readInt();
-            List<Coord> newMap = new LinkedList<Coord>();
-            for (int i = 0; i < count; i++)
-            {
-                newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
-            }
-            data.close(); // Close the stream.
-
-            _log.info(newMap.size() + " map vertices loaded from file " + file.getName());
-
-            _coordList.addAll(newMap);
-        }
-    }
-
-    /**
-     * @throws FileNotFoundException
-     * @throws IOException
-     */
-    private void loadHexFiles() throws FileNotFoundException, IOException
-    {
-        FilenameFilter filter = new UniverseFilter("hex");
-        File directory = new File("data");
-        File[] files = directory.listFiles(filter);
-        for (File file : files)
-        {
-            FileInputStream fos = new FileInputStream(file); // Save to file
-            GZIPInputStream gzos = new GZIPInputStream(fos);
-            DataInputStream data = new DataInputStream(gzos);
-            int count = data.readInt();
-            List<Coord> newMap = new LinkedList<Coord>();
-            for (int i = 0; i < count; i++)
-            {
-                newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
-                data.readInt();
-            }
-            data.close(); // Close the stream.
-
-            _log.info(newMap.size() + " map vertices loaded from file " + file.getName());
-
-            _coordList.addAll(newMap);
-        }
-    }
-
-    /**
-     * @throws FileNotFoundException
-     * @throws IOException
-     * @throws ClassNotFoundException
-     */
-    @SuppressWarnings(value = {"unchecked"})
-    private void loadBinFiles() throws FileNotFoundException, IOException, ClassNotFoundException
-    {
-        FilenameFilter filter = new UniverseFilter("bin");
-        File directory = new File("data");
-        File[] files = directory.listFiles(filter);
-        for (File file : files)
-        {
-            //Create necessary input streams
-            FileInputStream fis = new FileInputStream(file); // Read from file
-            GZIPInputStream gzis = new GZIPInputStream(fis); // Uncompress
-            ObjectInputStream in = new ObjectInputStream(gzis); // Read objects
-            // Read in an object. It should be a vector of scribbles
-
-            TreeSet<Position> temp = (TreeSet<Position>) in.readObject();
-            _log.info(temp.size() + " map vertices loaded from file " + file.getName());
-            in.close(); // Close the stream.
-            for (Position p : temp)
-            {
-                _coordList.add(new Coord(p._x, p._y, p._z));
-            }
-        }
-    }
-
-    public class UniverseDump implements Runnable
-    {
-        /* (non-Javadoc)
-         * @see java.lang.Runnable#run()
-         */
-        public void run()
-        {
-            int size = _coordList.size();
-            //_log.info("Univere Map has " + _map.size() + " nodes.");
-            if (size > 100000)
-            {
-                flush();
-            }
-        }
-    }
-
-    public void flush()
-    {
-        //_log.info("Size of dump: "+coordList.size());
-        List<Coord> oldMap = _coordList;
-        _coordList = new LinkedList<Coord>();
-        int size = oldMap.size();
-        dump(oldMap, true);
-        _log.info("Universe Map : Dumped " + size + " vertices.");
-    }
-
-    public int size()
-    {
-        int size = 0;
-        if (_coordList != null) size = _coordList.size();
-        return size;
-    }
-
-    public void dump(List<Coord> _map, boolean b)
-    {
-    	FileOutputStream fos = null;
-    	DataOutputStream data = null;
-        try
-        {
-            String pad = "";
-            if (b) pad = "" + System.currentTimeMillis();
-            fos = new FileOutputStream("data/universe" + pad + ".fin"); // Save to file
-            data = new DataOutputStream(fos);
-            int count = _map.size();
-            //_log.info("Size of dump: "+count);
-            data.writeInt(count);
-
-            for (Coord p : _map)
-            {
-                if (p != null)
-                {
-                    data.writeInt(p._x);
-                    data.writeInt(p._y);
-                    data.writeInt(p._z);
-                }
-            }
-            _log.info("Universe Map saved to: " + "data/universe" + pad + ".fin");
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-        finally
-        {
-        	try
-        	{
-        		data.close();
-        	}
-        	catch (Exception e)
-        	{
-        	}
-        	
-        	try
-        	{
-        		fos.close();
-        	}
-        	catch (Exception e)
-        	{
-        	}
-        }
-    }
-
-    // prepare for shutdown
-    public void implode(boolean b)
-    {
-        createMap();
-        dump(_coordList, b);
-    }
+		{
+			return String.valueOf(_x) + " " + _y + " " + _z;
+		}
+	}
+	
+	public static Universe getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private Universe()
+	{
+		_coordList = new LinkedList<Coord>();
+		_logPlayers = new HashSet<Integer>();
+		
+		ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new UniverseDump(), 30000, 30000);
+	}
+	
+	public void registerHeight(int x, int y, int z)
+	{
+		// don't overwrite obstacle entries
+		//Position p  = new Position(x, y, z, 0);
+		//_map.add(p);
+		_coordList.add(new Coord(x, y, z));
+	}
+	
+	public void registerObstacle(int x, int y, int z)
+	{
+		//Position p = new Position(x, y, z, -1);
+		//_map.add(p);
+		_coordList.add(new Coord(x, y, z));
+	}
+	
+	public boolean shouldLog(Integer id)
+	{
+		return (_logPlayers.contains(id) || _logAll);
+	}
+	
+	public void setLogAll(boolean flag)
+	{
+		_logAll = flag;
+	}
+	
+	public void addLogPlayer(Integer id)
+	{
+		_logPlayers.add(id);
+		_logAll = false;
+	}
+	
+	public void removeLogPlayer(Integer id)
+	{
+		_logPlayers.remove(id);
+	}
+	
+	public void loadAscii()
+	{
+		int initialSize = _coordList.size();
+		BufferedReader r = null;
+		try
+		{
+			r = new BufferedReader(new FileReader("data/universe.txt"));
+			String line;
+			while ((line = r.readLine()) != null)
+			{
+				StringTokenizer st = new StringTokenizer(line);
+				String x1 = st.nextToken();
+				String y1 = st.nextToken();
+				String z1 = st.nextToken();
+				//				String f1 = st.nextToken();
+				int x = Integer.parseInt(x1);
+				int y = Integer.parseInt(y1);
+				int z = Integer.parseInt(z1);
+				//				int f = Integer.parseInt(f1);
+				_coordList.add(new Coord(x, y, z));
+			}
+			_log.info((_coordList.size() - initialSize) + " additional nodes loaded from text file.");
+		}
+		catch (Exception e)
+		{
+			_log.info("could not read text file universe.txt");
+		}
+		finally
+		{
+			try
+			{
+				r.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	public void createMap()
+	{
+		int zoom = 100;
+		int w = (MAX_X - MIN_X) / zoom;
+		int h = (MAX_Y - MIN_Y) / zoom;
+		BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_GRAY);
+		Graphics2D gr = bi.createGraphics();
+		int min_z = 0, max_z = 0;
+		for (Coord pos : _coordList)
+		{
+			if (pos == null)
+				continue;
+			
+			if (pos._z < min_z)
+				min_z = pos._z;
+			if (pos._z > max_z)
+				max_z = pos._z;
+		}
+		for (Coord pos : _coordList)
+		{
+			if (pos == null)
+				continue;
+			
+			int x = (pos._x - MIN_X) / zoom;
+			int y = (pos._y - MIN_Y) / zoom;
+			int color = (int) (((long) pos._z - MIN_Z) * 0xFFFFFF / (MAX_Z - MIN_Z));
+			gr.setColor(new Color(color));
+			gr.drawLine(x, y, x, y);
+		}
+		try
+		{
+			ImageIO.write(bi, "png", new File("universe.png"));
+		}
+		catch (Exception e)
+		{
+			_log.warning("cannot create universe.png: " + e);
+		}
+	}
+	
+	public class UniverseFilter implements FilenameFilter
+	{
+		String _ext = "";
+		
+		public UniverseFilter(String pExt)
+		{
+			_ext = pExt;
+		}
+		
+		/* (non-Javadoc)
+		 * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
+		 */
+		public boolean accept(File arg0, String name)
+		{
+			return name.startsWith("universe") && name.endsWith("." + _ext);
+		}
+		
+	}
+	
+	public void load()
+	{
+		int total = 0;
+		if (_coordList == null)
+		{
+			_coordList = new LinkedList<Coord>();
+		}
+		try
+		{
+			loadBinFiles();
+			
+			loadHexFiles();
+			
+			loadFinFiles();
+			
+			_log.info(_coordList.size() + " map vertices loaded in total.");
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+		_log.info("Total: " + total);
+	}
+	
+	/**
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	private void loadFinFiles() throws FileNotFoundException, IOException
+	{
+		FilenameFilter filter = new UniverseFilter("fin");
+		File directory = new File("data");
+		File[] files = directory.listFiles(filter);
+		for (File file : files)
+		{
+			FileInputStream fos = new FileInputStream(file); // Save to file
+			DataInputStream data = new DataInputStream(fos);
+			int count = data.readInt();
+			List<Coord> newMap = new LinkedList<Coord>();
+			for (int i = 0; i < count; i++)
+			{
+				newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
+			}
+			data.close(); // Close the stream.
+			
+			_log.info(newMap.size() + " map vertices loaded from file " + file.getName());
+			
+			_coordList.addAll(newMap);
+		}
+	}
+	
+	/**
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	private void loadHexFiles() throws FileNotFoundException, IOException
+	{
+		FilenameFilter filter = new UniverseFilter("hex");
+		File directory = new File("data");
+		File[] files = directory.listFiles(filter);
+		for (File file : files)
+		{
+			FileInputStream fos = new FileInputStream(file); // Save to file
+			GZIPInputStream gzos = new GZIPInputStream(fos);
+			DataInputStream data = new DataInputStream(gzos);
+			int count = data.readInt();
+			List<Coord> newMap = new LinkedList<Coord>();
+			for (int i = 0; i < count; i++)
+			{
+				newMap.add(new Coord(data.readInt(), data.readInt(), data.readInt()));
+				data.readInt();
+			}
+			data.close(); // Close the stream.
+			
+			_log.info(newMap.size() + " map vertices loaded from file " + file.getName());
+			
+			_coordList.addAll(newMap);
+		}
+	}
+	
+	/**
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 * @throws ClassNotFoundException
+	 */
+	@SuppressWarnings(value = { "unchecked" })
+	private void loadBinFiles() throws FileNotFoundException, IOException, ClassNotFoundException
+	{
+		FilenameFilter filter = new UniverseFilter("bin");
+		File directory = new File("data");
+		File[] files = directory.listFiles(filter);
+		for (File file : files)
+		{
+			//Create necessary input streams
+			FileInputStream fis = new FileInputStream(file); // Read from file
+			GZIPInputStream gzis = new GZIPInputStream(fis); // Uncompress
+			ObjectInputStream in = new ObjectInputStream(gzis); // Read objects
+			// Read in an object. It should be a vector of scribbles
+			
+			TreeSet<Position> temp = (TreeSet<Position>) in.readObject();
+			_log.info(temp.size() + " map vertices loaded from file " + file.getName());
+			in.close(); // Close the stream.
+			for (Position p : temp)
+			{
+				_coordList.add(new Coord(p._x, p._y, p._z));
+			}
+		}
+	}
+	
+	public class UniverseDump implements Runnable
+	{
+		/* (non-Javadoc)
+		 * @see java.lang.Runnable#run()
+		 */
+		public void run()
+		{
+			int size = _coordList.size();
+			//_log.info("Univere Map has " + _map.size() + " nodes.");
+			if (size > 100000)
+			{
+				flush();
+			}
+		}
+	}
+	
+	public void flush()
+	{
+		//_log.info("Size of dump: "+coordList.size());
+		List<Coord> oldMap = _coordList;
+		_coordList = new LinkedList<Coord>();
+		int size = oldMap.size();
+		dump(oldMap, true);
+		_log.info("Universe Map : Dumped " + size + " vertices.");
+	}
+	
+	public int size()
+	{
+		int size = 0;
+		if (_coordList != null)
+			size = _coordList.size();
+		return size;
+	}
+	
+	public void dump(List<Coord> _map, boolean b)
+	{
+		FileOutputStream fos = null;
+		DataOutputStream data = null;
+		try
+		{
+			String pad = "";
+			if (b)
+				pad = "" + System.currentTimeMillis();
+			fos = new FileOutputStream("data/universe" + pad + ".fin"); // Save to file
+			data = new DataOutputStream(fos);
+			int count = _map.size();
+			//_log.info("Size of dump: "+count);
+			data.writeInt(count);
+			
+			for (Coord p : _map)
+			{
+				if (p != null)
+				{
+					data.writeInt(p._x);
+					data.writeInt(p._y);
+					data.writeInt(p._z);
+				}
+			}
+			_log.info("Universe Map saved to: " + "data/universe" + pad + ".fin");
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				data.close();
+			}
+			catch (Exception e)
+			{
+			}
+			
+			try
+			{
+				fos.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	// prepare for shutdown
+	public void implode(boolean b)
+	{
+		createMap();
+		dump(_coordList, b);
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final Universe _instance = Config.ACTIVATE_POSITION_RECORDER ? new Universe() : null;
+	}
 }

+ 7 - 6
L2_GameServer/java/net/sf/l2j/gameserver/ai2/AiManager.java

@@ -38,7 +38,6 @@ import net.sf.l2j.gameserver.ai2.AiInstance.QueueEventRunner;
 public class AiManager
 {
 	protected static final Logger _log = Logger.getLogger(AiManager.class.getName());
-	private static AiManager _instance;
 	private List<AiInstance> _aiList;
 	private Map<Integer, AiInstance> _aiMap;
 	private ThreadPoolManager _tpm;
@@ -46,11 +45,7 @@ public class AiManager
 	
 	public static AiManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new AiManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private AiManager()
@@ -232,4 +227,10 @@ public class AiManager
 			return ids.isEmpty();
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AiManager _instance = new AiManager();
+	}
 }

+ 11 - 10
L2_GameServer/java/net/sf/l2j/gameserver/cache/CrestCache.java

@@ -40,8 +40,6 @@ public class CrestCache
 {
 	private static Logger _log = Logger.getLogger(CrestCache.class.getName());
 	
-	private static CrestCache _instance;
-	
 	private FastMRUCache<Integer, byte[]> _cachePledge = new FastMRUCache<Integer, byte[]>();
 	
 	private FastMRUCache<Integer, byte[]> _cachePledgeLarge = new FastMRUCache<Integer, byte[]>();
@@ -54,15 +52,10 @@ public class CrestCache
 	
 	public static CrestCache getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new CrestCache();
-		}
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public CrestCache()
+	private CrestCache()
 	{
 		convertOldPedgeFiles();
 		reload();
@@ -133,7 +126,9 @@ public class CrestCache
 			}
 		}
 		
-		_log.info("Cache[Crest]: " + String.format("%.3f", getMemoryUsage()) + "MB on " + getLoadedFiles() + " files loaded. (Forget Time: " + (_cachePledge.getForgetTime() / 1000) + "s , Capacity: " + _cachePledge.capacity() + ")");
+		_log.info("Cache[Crest]: " + String.format("%.3f", getMemoryUsage()) + "MB on " + getLoadedFiles()
+				+ " files loaded. (Forget Time: " + (_cachePledge.getForgetTime() / 1000) + "s , Capacity: " + _cachePledge.capacity()
+				+ ")");
 	}
 	
 	public void convertOldPedgeFiles()
@@ -371,4 +366,10 @@ public class CrestCache
 			return (file.getName().startsWith("Pledge_"));
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CrestCache _instance = new CrestCache();
+	}
 }

+ 8 - 6
L2_GameServer/java/net/sf/l2j/gameserver/cache/HtmCache.java

@@ -31,7 +31,6 @@ import net.sf.l2j.gameserver.util.Util;
 public class HtmCache
 {
 	private static Logger _log = Logger.getLogger(HtmCache.class.getName());
-	private static HtmCache _instance;
 	
 	private FastMap<Integer, String> _cache;
 	
@@ -40,13 +39,10 @@ public class HtmCache
 	
 	public static HtmCache getInstance()
 	{
-		if (_instance == null)
-			_instance = new HtmCache();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public HtmCache()
+	private HtmCache()
 	{
 		_cache = new FastMap<Integer, String>();
 		reload();
@@ -217,4 +213,10 @@ public class HtmCache
 		
 		return false;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final HtmCache _instance = new HtmCache();
+	}
 }

+ 7 - 4
L2_GameServer/java/net/sf/l2j/gameserver/cache/WarehouseCacheManager.java

@@ -25,15 +25,12 @@ import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  */
 public class WarehouseCacheManager
 {
-	private static WarehouseCacheManager _instance;
 	protected final FastMap<L2PcInstance, Long> _cachedWh;
 	protected final long _cacheTime;
 	
 	public static WarehouseCacheManager getInstance()
 	{
-		if (_instance == null)
-			_instance = new WarehouseCacheManager();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private WarehouseCacheManager()
@@ -68,4 +65,10 @@ public class WarehouseCacheManager
 			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final WarehouseCacheManager _instance = new WarehouseCacheManager();
+	}
 }

+ 5 - 2
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/BB/Forum.java

@@ -55,6 +55,11 @@ public class Forum
 	private boolean _loaded = false;
 	
 	/**
+	 * Creates new instance of Forum. When you create new forum, use
+	 * {@link net.sf.l2j.gameserver.communitybbs.Manager.ForumsBBSManager#
+	 * addForum(net.sf.l2j.gameserver.communitybbs.BB.Forum)} to add forum
+	 * to the forums manager.
+	 *
 	 * @param i
 	 */
 	public Forum(int Forumid, Forum FParent)
@@ -66,8 +71,6 @@ public class Forum
 		
 		/*load();
 		getChildren();	*/
-		ForumsBBSManager.getInstance().addForum(this);
-		
 	}
 	
 	/**

+ 12 - 11
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/CommunityBoard.java

@@ -28,20 +28,13 @@ import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 
 public class CommunityBoard
 {
-	private static CommunityBoard _instance;
-	
-	public CommunityBoard()
+	private CommunityBoard()
 	{
 	}
 	
 	public static CommunityBoard getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new CommunityBoard();
-		}
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public void handleCommands(L2GameClient client, String command)
@@ -90,7 +83,8 @@ public class CommunityBoard
 				}
 				else
 				{
-					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
+					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command
+							+ " is not implemented yet</center><br><br></body></html>", "101");
 					activeChar.sendPacket(sb);
 					activeChar.sendPacket(new ShowBoard(null, "102"));
 					activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -135,7 +129,8 @@ public class CommunityBoard
 				}
 				else
 				{
-					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + url + " is not implemented yet</center><br><br></body></html>", "101");
+					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + url
+							+ " is not implemented yet</center><br><br></body></html>", "101");
 					activeChar.sendPacket(sb);
 					activeChar.sendPacket(new ShowBoard(null, "102"));
 					activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -153,4 +148,10 @@ public class CommunityBoard
 				break;
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CommunityBoard _instance = new CommunityBoard();
+	}
 }

+ 15 - 9
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/AdminBBSManager.java

@@ -19,18 +19,16 @@ import net.sf.l2j.gameserver.network.serverpackets.ShowBoard;
 
 public class AdminBBSManager extends BaseBBSManager
 {
-	private static AdminBBSManager _instance = null;
-	
 	/**
 	 * @return
 	 */
 	public static AdminBBSManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new AdminBBSManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
+	}
+	
+	private AdminBBSManager()
+	{
 	}
 	
 	/**
@@ -46,12 +44,14 @@ public class AdminBBSManager extends BaseBBSManager
 		}
 		if (command.startsWith("admin_bbs"))
 		{
-			separateAndSend("<html><body><br><br><center>This Page is only an exemple :)<br><br>command=" + command + "</center></body></html>", activeChar);
+			separateAndSend("<html><body><br><br><center>This Page is only an exemple :)<br><br>command=" + command
+					+ "</center></body></html>", activeChar);
 		}
 		else
 		{
 			
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -72,4 +72,10 @@ public class AdminBBSManager extends BaseBBSManager
 		}
 		
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AdminBBSManager _instance = new AdminBBSManager();
+	}
 }

+ 181 - 282
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/ClanBBSManager.java

@@ -25,14 +25,16 @@ import net.sf.l2j.gameserver.util.StringUtil;
 
 public class ClanBBSManager extends BaseBBSManager
 {
-	private static ClanBBSManager _instance = new ClanBBSManager();
+	private ClanBBSManager()
+	{
+	}
 	
 	/**
 	 * @return
 	 */
 	public static ClanBBSManager getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -88,16 +90,16 @@ public class ClanBBSManager extends BaseBBSManager
 				clanhome(activeChar, index);
 			}
 		}
-		else if(command.startsWith("_bbsclan_clannotice_edit;"))
+		else if (command.startsWith("_bbsclan_clannotice_edit;"))
 		{
 			clanNotice(activeChar, activeChar.getClan().getClanId());
 		}
-		else if(command.startsWith("_bbsclan_clannotice_enable"))
+		else if (command.startsWith("_bbsclan_clannotice_enable"))
 		{
 			activeChar.getClan().setNoticeEnabled(true);
 			clanNotice(activeChar, activeChar.getClan().getClanId());
 		}
-		else if(command.startsWith("_bbsclan_clannotice_disable"))
+		else if (command.startsWith("_bbsclan_clannotice_disable"))
 		{
 			activeChar.getClan().setNoticeEnabled(false);
 			clanNotice(activeChar, activeChar.getClan().getClanId());
@@ -121,188 +123,127 @@ public class ClanBBSManager extends BaseBBSManager
 			}
 			else
 			{
-				final StringBuilder html = StringUtil.startAppend(2000,
-						"<html><body><br><br>" +
-						"<table border=0 width=610><tr><td width=10></td><td width=600 align=left>" +
-						"<a action=\"bypass _bbshome\">HOME</a> &gt; " +
-						"<a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>  &gt; " +
-						"<a action=\"bypass _bbsclan_clanhome;",
-						String.valueOf(clanId),
-						"\"> &amp;$802; </a>" +
-						"</td></tr>" +
-						"</table>"
-						);
-				if(activeChar.isClanLeader())
+				final StringBuilder html = StringUtil.startAppend(2000, "<html><body><br><br>"
+						+ "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>"
+						+ "<a action=\"bypass _bbshome\">HOME</a> &gt; "
+						+ "<a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>  &gt; " + "<a action=\"bypass _bbsclan_clanhome;", String.valueOf(clanId), "\"> &amp;$802; </a>"
+						+ "</td></tr>" + "</table>");
+				if (activeChar.isClanLeader())
 				{
-					StringUtil.append(html,
-							"<br><br><center>" +
-							"<table width=610 border=0 cellspacing=0 cellpadding=0>" +
-							"<tr><td fixwidth=610><font color=\"AAAAAA\">The Clan Notice function allows the clan leader to send messages through a pop-up window to clan members at login.</font> </td></tr>" +
-							"<tr><td height=20></td></tr>"
-							);
+					StringUtil.append(html, "<br><br><center>"
+							+ "<table width=610 border=0 cellspacing=0 cellpadding=0>"
+							+ "<tr><td fixwidth=610><font color=\"AAAAAA\">The Clan Notice function allows the clan leader to send messages through a pop-up window to clan members at login.</font> </td></tr>"
+							+ "<tr><td height=20></td></tr>");
 					
-					if(activeChar.getClan().isNoticeEnabled())
+					if (activeChar.getClan().isNoticeEnabled())
 						StringUtil.append(html, "<tr><td fixwidth=610> Clan Notice Function:&nbsp;&nbsp;&nbsp;on&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;&nbsp;<a action=\"bypass _bbsclan_clannotice_disable\">off</a>");
 					else
 						StringUtil.append(html, "<tr><td fixwidth=610> Clan Notice Function:&nbsp;&nbsp;&nbsp;<a action=\"bypass _bbsclan_clannotice_enable\">on</a>&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;&nbsp;off");
 					
-					StringUtil.append(html,
-							"</td></tr>" +
-							"</table>" +
-							"<img src=\"L2UI.Squaregray\" width=\"610\" height=\"1\">" +
-							"<br> <br>" +
-							"<table width=610 border=0 cellspacing=2 cellpadding=0>" +
-							"<tr><td>Edit Notice: </td></tr>" +
-							"<tr><td height=5></td></tr>" +
-							"<tr><td>" +
-							"<MultiEdit var =\"Content\" width=610 height=100>" +
-							"</td></tr>" +
-							"</table>" +
-							"<br>" +
-							"<table width=610 border=0 cellspacing=0 cellpadding=0>" +
-							"<tr><td height=5></td></tr>" +
-							"<tr>" +
-							"<td align=center FIXWIDTH=65><button value=\"&$140;\" action=\"Write Notice Set _ Content Content Content\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>" +
-							"<td align=center FIXWIDTH=45></td>" +
-							"<td align=center FIXWIDTH=500></td>" +
-							"</tr>" +
-							"</table>" +
-							"</center>" +
-							"</body>" +
-							"</html>"
-							);
+					StringUtil.append(html, "</td></tr>"
+							+ "</table>"
+							+ "<img src=\"L2UI.Squaregray\" width=\"610\" height=\"1\">"
+							+ "<br> <br>"
+							+ "<table width=610 border=0 cellspacing=2 cellpadding=0>"
+							+ "<tr><td>Edit Notice: </td></tr>"
+							+ "<tr><td height=5></td></tr>"
+							+ "<tr><td>"
+							+ "<MultiEdit var =\"Content\" width=610 height=100>"
+							+ "</td></tr>"
+							+ "</table>"
+							+ "<br>"
+							+ "<table width=610 border=0 cellspacing=0 cellpadding=0>"
+							+ "<tr><td height=5></td></tr>"
+							+ "<tr>"
+							+ "<td align=center FIXWIDTH=65><button value=\"&$140;\" action=\"Write Notice Set _ Content Content Content\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>"
+							+ "<td align=center FIXWIDTH=45></td>" + "<td align=center FIXWIDTH=500></td>" + "</tr>" + "</table>"
+							+ "</center>" + "</body>" + "</html>");
 					send1001(html.toString(), activeChar);
-					send1002(activeChar,activeChar.getClan().getNotice()," ","0");
+					send1002(activeChar, activeChar.getClan().getNotice(), " ", "0");
 				}
 				else
 				{
-					StringUtil.append(html,
-							"<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" +
-							"<center>" +
-							"<table border=0 cellspacing=0 cellpadding=0><tr>" +
-							"<td>You are not your clan's leader, and therefore cannot change the clan notice</td>" +
-							"</tr></table>"
-							);
+					StringUtil.append(html, "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" + "<center>"
+							+ "<table border=0 cellspacing=0 cellpadding=0><tr>"
+							+ "<td>You are not your clan's leader, and therefore cannot change the clan notice</td>" + "</tr></table>");
 					if (activeChar.getClan().isNoticeEnabled())
 					{
-						StringUtil.append(html, 
-								"<table border=0 cellspacing=0 cellpadding=0>" +
-								"<tr>" +
-								"<td>The current clan notice:</td>" +
-								"</tr>" +
-								"<tr><td fixwidth=5></td>" +
-								"<td FIXWIDTH=600 align=left>" +
-								activeChar.getClan().getNotice() +
-								"</td>" +
-								"<td fixqqwidth=5></td>" +
-								"</tr>" +
-								"</table>"
-								);
+						StringUtil.append(html, "<table border=0 cellspacing=0 cellpadding=0>" + "<tr>"
+								+ "<td>The current clan notice:</td>" + "</tr>" + "<tr><td fixwidth=5></td>"
+								+ "<td FIXWIDTH=600 align=left>" + activeChar.getClan().getNotice() + "</td>" + "<td fixqqwidth=5></td>"
+								+ "</tr>" + "</table>");
 					}
-					StringUtil.append(html,
-							"</center>" +
-							"</body>" +
-							"</html>"
-							);
+					StringUtil.append(html, "</center>" + "</body>" + "</html>");
 					separateAndSend(html.toString(), activeChar);
 				}
 			}
 		}
 	}
+	
 	/**
 	 * @param activeChar
 	 */
 	private void clanlist(L2PcInstance activeChar, int index)
 	{
-		if (index < 1) {
+		if (index < 1)
+		{
 			index = 1;
 		}
-
+		
 		//header
-                final StringBuilder html = StringUtil.startAppend(2000,
-                        "<html><body><br><br><center>" +
-                        "<br1><br1><table border=0 cellspacing=0 cellpadding=0>" +
-                        "<tr><td FIXWIDTH=15>&nbsp;</td>" +
-                        "<td width=610 height=30 align=left>" +
-                        "<a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>" +
-                        "</td></tr></table>" +
-                        "<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=434343>" +
-                        "<tr><td height=10></td></tr>" +
-                        "<tr>" +
-                        "<td fixWIDTH=5></td>" +
-                        "<td fixWIDTH=600>" +
-                        "<a action=\"bypass _bbsclan_clanhome;",
-                        String.valueOf((activeChar.getClan() != null) ? activeChar.getClan().getClanId() : 0),
-                        "\">[GO TO MY CLAN]</a>&nbsp;&nbsp;" +
-                        "</td>" +
-                        "<td fixWIDTH=5></td>" +
-                        "</tr>" +
-                        "<tr><td height=10></td></tr>" +
-                        "</table>" +
-                        "<br>" +
-                        "<table border=0 cellspacing=0 cellpadding=2 bgcolor=5A5A5A width=610>" +
-                        "<tr>" +
-                        "<td FIXWIDTH=5></td>" +
-                        "<td FIXWIDTH=200 align=center>CLAN NAME</td>" +
-                        "<td FIXWIDTH=200 align=center>CLAN LEADER</td>" +
-                        "<td FIXWIDTH=100 align=center>CLAN LEVEL</td>" +
-                        "<td FIXWIDTH=100 align=center>CLAN MEMBERS</td>" +
-                        "<td FIXWIDTH=5></td>" +
-                        "</tr>" +
-                        "</table>" +
-                        "<img src=\"L2UI.Squareblank\" width=\"1\" height=\"5\">"
-                        );
-
-                int i = 0;
+		final StringBuilder html = StringUtil.startAppend(2000, "<html><body><br><br><center>"
+				+ "<br1><br1><table border=0 cellspacing=0 cellpadding=0>" + "<tr><td FIXWIDTH=15>&nbsp;</td>"
+				+ "<td width=610 height=30 align=left>" + "<a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>"
+				+ "</td></tr></table>" + "<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=434343>"
+				+ "<tr><td height=10></td></tr>" + "<tr>" + "<td fixWIDTH=5></td>" + "<td fixWIDTH=600>"
+				+ "<a action=\"bypass _bbsclan_clanhome;", String.valueOf((activeChar.getClan() != null) ? activeChar.getClan().getClanId() : 0), "\">[GO TO MY CLAN]</a>&nbsp;&nbsp;"
+				+ "</td>"
+				+ "<td fixWIDTH=5></td>"
+				+ "</tr>"
+				+ "<tr><td height=10></td></tr>"
+				+ "</table>"
+				+ "<br>"
+				+ "<table border=0 cellspacing=0 cellpadding=2 bgcolor=5A5A5A width=610>"
+				+ "<tr>"
+				+ "<td FIXWIDTH=5></td>"
+				+ "<td FIXWIDTH=200 align=center>CLAN NAME</td>"
+				+ "<td FIXWIDTH=200 align=center>CLAN LEADER</td>"
+				+ "<td FIXWIDTH=100 align=center>CLAN LEVEL</td>"
+				+ "<td FIXWIDTH=100 align=center>CLAN MEMBERS</td>"
+				+ "<td FIXWIDTH=5></td>" + "</tr>" + "</table>" + "<img src=\"L2UI.Squareblank\" width=\"1\" height=\"5\">");
+		
+		int i = 0;
 		for (L2Clan cl : ClanTable.getInstance().getClans())
 		{
-			if (i > (index + 1) * 7) {
+			if (i > (index + 1) * 7)
+			{
 				break;
 			}
-
-			if (i++ >= (index - 1) * 7) {
-                            StringUtil.append(html,
-                                    "<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"3\">" +
-                                    "<table border=0 cellspacing=0 cellpadding=0 width=610>" +
-                                    "<tr> " +
-                                    "<td FIXWIDTH=5></td>" +
-                                    "<td FIXWIDTH=200 align=center><a action=\"bypass _bbsclan_clanhome;",
-                                    String.valueOf(cl.getClanId()),
-                                    "\">",
-                                    cl.getName(),
-                                    "</a></td>" +
-                                    "<td FIXWIDTH=200 align=center>",
-                                    cl.getLeaderName(),
-                                    "</td>" +
-                                    "<td FIXWIDTH=100 align=center>",
-                                    String.valueOf(cl.getLevel()),
-                                    "</td>" +
-                                    "<td FIXWIDTH=100 align=center>",
-                                    String.valueOf(cl.getMembersCount()),
-                                    "</td>" +
-                                    "<td FIXWIDTH=5></td>" +
-                                    "</tr>" +
-                                    "<tr><td height=5></td></tr>" +
-                                    "</table>" +
-                                    "<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"3\">" +
-                                    "<img src=\"L2UI.SquareGray\" width=\"610\" height=\"1\">"
-                                    );
+			
+			if (i++ >= (index - 1) * 7)
+			{
+				StringUtil.append(html, "<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"3\">"
+						+ "<table border=0 cellspacing=0 cellpadding=0 width=610>" + "<tr> " + "<td FIXWIDTH=5></td>"
+						+ "<td FIXWIDTH=200 align=center><a action=\"bypass _bbsclan_clanhome;", String.valueOf(cl.getClanId()), "\">", cl.getName(), "</a></td>"
+						+ "<td FIXWIDTH=200 align=center>", cl.getLeaderName(), "</td>" + "<td FIXWIDTH=100 align=center>", String.valueOf(cl.getLevel()), "</td>"
+						+ "<td FIXWIDTH=100 align=center>", String.valueOf(cl.getMembersCount()), "</td>" + "<td FIXWIDTH=5></td>"
+						+ "</tr>" + "<tr><td height=5></td></tr>" + "</table>"
+						+ "<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"3\">"
+						+ "<img src=\"L2UI.SquareGray\" width=\"610\" height=\"1\">");
 			}
 		}
-
-		html.append(
-                        "<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"2\">" +
-                        "<table cellpadding=0 cellspacing=2 border=0><tr>");
-
-		if (index == 1) {
+		
+		html.append("<img src=\"L2UI.SquareBlank\" width=\"610\" height=\"2\">" + "<table cellpadding=0 cellspacing=2 border=0><tr>");
+		
+		if (index == 1)
+		{
 			html.append("<td><button action=\"\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
-		} else {
-                    StringUtil.append(html,
-                            "<td><button action=\"_bbsclan_clanlist;",
-                            String.valueOf(index - 1),
-                            "\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
 		}
-                
+		else
+		{
+			StringUtil.append(html, "<td><button action=\"_bbsclan_clanlist;", String.valueOf(index - 1), "\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
+		}
+		
 		i = 0;
 		int nbp;
 		nbp = ClanTable.getInstance().getClans().length / 8;
@@ -312,42 +253,33 @@ public class ClanBBSManager extends BaseBBSManager
 		}
 		for (i = 1; i <= nbp; i++)
 		{
-			if (i == index) {
-                            StringUtil.append(html,
-                                    "<td> ",
-                                    String.valueOf(i),
-                                    " </td>");
-			} else {
-                            StringUtil.append(html,
-                                    "<td><a action=\"bypass _bbsclan_clanlist;",
-                                    String.valueOf(i),
-                                    "\"> ",
-                                    String.valueOf(i),
-                                    " </a></td>");
+			if (i == index)
+			{
+				StringUtil.append(html, "<td> ", String.valueOf(i), " </td>");
+			}
+			else
+			{
+				StringUtil.append(html, "<td><a action=\"bypass _bbsclan_clanlist;", String.valueOf(i), "\"> ", String.valueOf(i), " </a></td>");
 			}
 			
 		}
-		if (index == nbp) {
+		if (index == nbp)
+		{
 			html.append("<td><button action=\"\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
-		} else {
-                    StringUtil.append(html,
-                            "<td><button action=\"bypass _bbsclan_clanlist;",
-                            String.valueOf(index + 1),
-                            "\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
 		}
-		html.append(
-                        "</tr></table>" +
-                        "<table border=0 cellspacing=0 cellpadding=0>" +
-                        "<tr><td width=610><img src=\"sek.cbui141\" width=\"610\" height=\"1\"></td></tr>" +
-                        "</table>" +
-                        "<table border=0><tr><td><combobox width=65 var=keyword list=\"Name;Ruler\"></td><td><edit var = \"Search\" width=130 height=11 length=\"16\"></td>" +
-        		//TODO: search (Write in BBS)
-                        "<td><button value=\"&$420;\" action=\"Write 5 -1 0 Search keyword keyword\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td> </tr></table>" +
-                        "<br>" +
-                        "<br>" +
-                        "</center>" +
-                        "</body>" +
-                        "</html>");
+		else
+		{
+			StringUtil.append(html, "<td><button action=\"bypass _bbsclan_clanlist;", String.valueOf(index + 1), "\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
+		}
+		html.append("</tr></table>"
+				+ "<table border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td width=610><img src=\"sek.cbui141\" width=\"610\" height=\"1\"></td></tr>"
+				+ "</table>"
+				+ "<table border=0><tr><td><combobox width=65 var=keyword list=\"Name;Ruler\"></td><td><edit var = \"Search\" width=130 height=11 length=\"16\"></td>"
+				+
+				//TODO: search (Write in BBS)
+				"<td><button value=\"&$420;\" action=\"Write 5 -1 0 Search keyword keyword\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td> </tr></table>"
+				+ "<br>" + "<br>" + "</center>" + "</body>" + "</html>");
 		separateAndSend(html.toString(), activeChar);
 	}
 	
@@ -359,6 +291,12 @@ public class ClanBBSManager extends BaseBBSManager
 		clanhome(activeChar, activeChar.getClan().getClanId());
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ClanBBSManager _instance = new ClanBBSManager();
+	}
+	
 	/**
 	 * @param activeChar
 	 * @param clanId
@@ -372,103 +310,64 @@ public class ClanBBSManager extends BaseBBSManager
 			{
 				activeChar.sendPacket(new SystemMessage(SystemMessageId.NO_CB_IN_MY_CLAN));
 				parsecmd("_bbsclan_clanlist", activeChar);
-			} else {
-                            final String html = StringUtil.concat(
-                                    "<html><body><center><br><br>" +
-                                    "<br1><br1><table border=0 cellspacing=0 cellpadding=0>" +
-                                    "<tr><td FIXWIDTH=15>&nbsp;</td>" +
-                                    "<td width=610 height=30 align=left>" +
-                                    "<a action=\"bypass _bbshome\">HOME</a> &gt; <a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>  &gt; <a action=\"bypass _bbsclan_clanhome;",
-                                    String.valueOf(clanId),
-                                    "\"> &amp;$802; </a>" +
-                                    "</td></tr></table>" +
-                                    "<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=434343>" +
-                                    "<tr><td height=10></td></tr>" +
-                                    "<tr>" +
-                                    "<td fixWIDTH=5></td>" +
-                                    "<td fixwidth=600>" +
-                                    "<a action=\"bypass _bbsclan_clanhome;",
-                                    String.valueOf(clanId),
-                                    ";announce\">[CLAN ANNOUNCEMENT]</a> <a action=\"bypass _bbsclan_clanhome;",
-                                    String.valueOf(clanId),
-                                    ";cbb\">[CLAN BULLETIN BOARD]</a>" +
-                                    "<a action=\"bypass _bbsclan_clanhome;",
-                                    String.valueOf(clanId),
-                                    ";cmail\">[CLAN MAIL]</a>&nbsp;&nbsp;" +
-                                    "<a action=\"bypass _bbsclan_clannotice_edit;",
-                                    String.valueOf(clanId),
-                                    ";cnotice\">[CLAN NOTICE]</a>&nbsp;&nbsp;" +
-                                    "</td>" +
-                                    "<td fixWIDTH=5></td>" +
-                                    "</tr>" +
-                                    "<tr><td height=10></td></tr>" +
-                                    "</table>" +
-                                    "<table border=0 cellspacing=0 cellpadding=0 width=610>" +
-                                    "<tr><td height=10></td></tr>" +
-                                    "<tr><td fixWIDTH=5></td>" +
-                                    "<td fixwidth=290 valign=top>" +
-                                    "</td>" +
-                                    "<td fixWIDTH=5></td>" +
-                                    "<td fixWIDTH=5 align=center valign=top><img src=\"l2ui.squaregray\" width=2  height=128></td>" +
-                                    "<td fixWIDTH=5></td>" +
-                                    "<td fixwidth=295>" +
-                                    "<table border=0 cellspacing=0 cellpadding=0 width=295>" +
-                                    "<tr>" +
-                                    "<td fixWIDTH=100 align=left>CLAN NAME</td>" +
-                                    "<td fixWIDTH=195 align=left>",
-                                    cl.getName(),
-                                    "</td>" +
-                                    "</tr>" +
-                                    "<tr><td height=7></td></tr>" +
-                                    "<tr>" +
-                                    "<td fixWIDTH=100 align=left>CLAN LEVEL</td>" +
-                                    "<td fixWIDTH=195 align=left height=16>",
-                                    String.valueOf(cl.getLevel()),
-                                    "</td>" +
-                                    "</tr>" +
-                                    "<tr><td height=7></td></tr>" +
-                                    "<tr>" +
-                                    "<td fixWIDTH=100 align=left>CLAN MEMBERS</td>" +
-                                    "<td fixWIDTH=195 align=left height=16>",
-                                    String.valueOf(cl.getMembersCount()),
-                                    "</td>" +
-                                    "</tr>" +
-                                    "<tr><td height=7></td></tr>" +
-                                    "<tr>" +
-                                    "<td fixWIDTH=100 align=left>CLAN LEADER</td>" +
-                                    "<td fixWIDTH=195 align=left height=16>",
-                                    cl.getLeaderName(),
-                                    "</td>" +
-                                    "</tr>" +
-                                    "<tr><td height=7></td></tr>" +
-                                    //ADMINISTRATOR ??
-                                    /*html.append("<tr>");
-                                     html.append("<td fixWIDTH=100 align=left>ADMINISTRATOR</td>");
-                                     html.append("<td fixWIDTH=195 align=left height=16>"+cl.getLeaderName()+"</td>");
-                                     html.append("</tr>");*/
-                                    "<tr><td height=7></td></tr>" +
-                                    "<tr>" +
-                                    "<td fixWIDTH=100 align=left>ALLIANCE</td>" +
-                                    "<td fixWIDTH=195 align=left height=16>",
-                                    (cl.getAllyName() != null) ? cl.getAllyName() : "",
-                                    "</td>" +
-                                    "</tr>" +
-                                    "</table>" +
-                                    "</td>" +
-                                    "<td fixWIDTH=5></td>" +
-                                    "</tr>" +
-                                    "<tr><td height=10></td></tr>" +
-                                    "</table>" +
-                                    //TODO: the BB for clan :)
-                                    //html.append("<table border=0 cellspacing=0 cellpadding=0 width=610  bgcolor=333333>");
-                                    "<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">" +
-                                    "<img src=\"L2UI.squaregray\" width=\"610\" height=\"1\">" +
-                                    "<br>" +
-                                    "</center>" +
-                                    "<br> <br>" +
-                                    "</body>" +
-                                    "</html>"
-                                    );
+			}
+			else
+			{
+				final String html = StringUtil.concat("<html><body><center><br><br>"
+						+ "<br1><br1><table border=0 cellspacing=0 cellpadding=0>"
+						+ "<tr><td FIXWIDTH=15>&nbsp;</td>"
+						+ "<td width=610 height=30 align=left>"
+						+ "<a action=\"bypass _bbshome\">HOME</a> &gt; <a action=\"bypass _bbsclan_clanlist\"> CLAN COMMUNITY </a>  &gt; <a action=\"bypass _bbsclan_clanhome;", String.valueOf(clanId), "\"> &amp;$802; </a>"
+						+ "</td></tr></table>"
+						+ "<table border=0 cellspacing=0 cellpadding=0 width=610 bgcolor=434343>"
+						+ "<tr><td height=10></td></tr>"
+						+ "<tr>"
+						+ "<td fixWIDTH=5></td>"
+						+ "<td fixwidth=600>"
+						+ "<a action=\"bypass _bbsclan_clanhome;", String.valueOf(clanId), ";announce\">[CLAN ANNOUNCEMENT]</a> <a action=\"bypass _bbsclan_clanhome;", String.valueOf(clanId), ";cbb\">[CLAN BULLETIN BOARD]</a>"
+						+ "<a action=\"bypass _bbsclan_clanhome;", String.valueOf(clanId), ";cmail\">[CLAN MAIL]</a>&nbsp;&nbsp;"
+						+ "<a action=\"bypass _bbsclan_clannotice_edit;", String.valueOf(clanId), ";cnotice\">[CLAN NOTICE]</a>&nbsp;&nbsp;"
+						+ "</td>"
+						+ "<td fixWIDTH=5></td>"
+						+ "</tr>"
+						+ "<tr><td height=10></td></tr>"
+						+ "</table>"
+						+ "<table border=0 cellspacing=0 cellpadding=0 width=610>"
+						+ "<tr><td height=10></td></tr>"
+						+ "<tr><td fixWIDTH=5></td>"
+						+ "<td fixwidth=290 valign=top>"
+						+ "</td>"
+						+ "<td fixWIDTH=5></td>"
+						+ "<td fixWIDTH=5 align=center valign=top><img src=\"l2ui.squaregray\" width=2  height=128></td>"
+						+ "<td fixWIDTH=5></td>"
+						+ "<td fixwidth=295>"
+						+ "<table border=0 cellspacing=0 cellpadding=0 width=295>"
+						+ "<tr>"
+						+ "<td fixWIDTH=100 align=left>CLAN NAME</td>" + "<td fixWIDTH=195 align=left>", cl.getName(), "</td>" + "</tr>"
+						+ "<tr><td height=7></td></tr>" + "<tr>" + "<td fixWIDTH=100 align=left>CLAN LEVEL</td>"
+						+ "<td fixWIDTH=195 align=left height=16>", String.valueOf(cl.getLevel()), "</td>" + "</tr>"
+						+ "<tr><td height=7></td></tr>" + "<tr>" + "<td fixWIDTH=100 align=left>CLAN MEMBERS</td>"
+						+ "<td fixWIDTH=195 align=left height=16>", String.valueOf(cl.getMembersCount()), "</td>" + "</tr>"
+						+ "<tr><td height=7></td></tr>" + "<tr>" + "<td fixWIDTH=100 align=left>CLAN LEADER</td>"
+						+ "<td fixWIDTH=195 align=left height=16>", cl.getLeaderName(), "</td>" + "</tr>" + "<tr><td height=7></td></tr>"
+						+
+						//ADMINISTRATOR ??
+						/*html.append("<tr>");
+						 html.append("<td fixWIDTH=100 align=left>ADMINISTRATOR</td>");
+						 html.append("<td fixWIDTH=195 align=left height=16>"+cl.getLeaderName()+"</td>");
+						 html.append("</tr>");*/
+						"<tr><td height=7></td></tr>" + "<tr>" + "<td fixWIDTH=100 align=left>ALLIANCE</td>"
+						+ "<td fixWIDTH=195 align=left height=16>", (cl.getAllyName() != null) ? cl.getAllyName() : "", "</td>" + "</tr>"
+						+ "</table>" + "</td>" + "<td fixWIDTH=5></td>"
+						+ "</tr>"
+						+ "<tr><td height=10></td></tr>"
+						+ "</table>"
+						+
+						//TODO: the BB for clan :)
+						//html.append("<table border=0 cellspacing=0 cellpadding=0 width=610  bgcolor=333333>");
+						"<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">"
+						+ "<img src=\"L2UI.squaregray\" width=\"610\" height=\"1\">" + "<br>" + "</center>" + "<br> <br>" + "</body>"
+						+ "</html>");
 				separateAndSend(html, activeChar);
 			}
 		}
@@ -484,7 +383,7 @@ public class ClanBBSManager extends BaseBBSManager
 		if (ar1.equals("Set"))
 		{
 			activeChar.getClan().setNotice(ar4);
-			parsecmd("_bbsclan_clanhome;" + activeChar.getClan().getClanId(),activeChar);
+			parsecmd("_bbsclan_clanhome;" + activeChar.getClan().getClanId(), activeChar);
 		}
 	}
 	

+ 23 - 28
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/ForumsBBSManager.java

@@ -32,7 +32,6 @@ public class ForumsBBSManager extends BaseBBSManager
 	private static Logger _log = Logger.getLogger(ForumsBBSManager.class.getName());
 	private Map<Integer, Forum> _root;
 	private List<Forum> _table;
-	private static ForumsBBSManager _instance;
 	private int _lastid = 1;
 	
 	/**
@@ -40,38 +39,14 @@ public class ForumsBBSManager extends BaseBBSManager
 	 */
 	public static ForumsBBSManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ForumsBBSManager();
-			_instance.load();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public ForumsBBSManager()
+	private ForumsBBSManager()
 	{
 		_root = new FastMap<Integer, Forum>();
 		_table = new FastList<Forum>();
-	}
-	
-	public void addForum(Forum ff)
-	{
-		if (ff == null)
-			return;
-			
-		_table.add(ff);
 		
-		if (ff.getID() > _lastid)
-		{
-			_lastid = ff.getID();
-		}
-	}
-	
-	/**
-	 *
-	 */
-	private void load()
-	{
 		Connection con = null;
 		try
 		{
@@ -80,9 +55,9 @@ public class ForumsBBSManager extends BaseBBSManager
 			ResultSet result = statement.executeQuery();
 			while (result.next())
 			{
-				
 				Forum f = new Forum(Integer.parseInt(result.getString("forum_id")), null);
 				_root.put(Integer.parseInt(result.getString("forum_id")), f);
+				addForum(f);
 			}
 			result.close();
 			statement.close();
@@ -104,6 +79,19 @@ public class ForumsBBSManager extends BaseBBSManager
 		}
 	}
 	
+	public void addForum(Forum ff)
+	{
+		if (ff == null)
+			return;
+		
+		_table.add(ff);
+		
+		if (ff.getID() > _lastid)
+		{
+			_lastid = ff.getID();
+		}
+	}
+	
 	/* (non-Javadoc)
 	 * @see net.sf.l2j.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, net.sf.l2j.gameserver.model.actor.instance.L2PcInstance)
 	 */
@@ -141,6 +129,7 @@ public class ForumsBBSManager extends BaseBBSManager
 		Forum forum;
 		forum = new Forum(name, parent, type, perm, oid);
 		forum.insertindb();
+		addForum(forum);
 		return forum;
 	}
 	
@@ -177,4 +166,10 @@ public class ForumsBBSManager extends BaseBBSManager
 		// TODO Auto-generated method stub
 		
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ForumsBBSManager _instance = new ForumsBBSManager();
+	}
 }

+ 81 - 141
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/PostBBSManager.java

@@ -33,18 +33,13 @@ public class PostBBSManager extends BaseBBSManager
 {
 	
 	private Map<Topic, Post> _postByTopic;
-	private static PostBBSManager _instance;
 	
 	public static PostBBSManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new PostBBSManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public PostBBSManager()
+	private PostBBSManager()
 	{
 		_postByTopic = new FastMap<Topic, Post>();
 	}
@@ -130,7 +125,8 @@ public class PostBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -181,7 +177,8 @@ public class PostBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName() + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName()
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -196,57 +193,35 @@ public class PostBBSManager extends BaseBBSManager
 	 */
 	private void showHtmlEditPost(Topic topic, L2PcInstance activeChar, Forum forum, Post p)
 	{
-            final String html = StringUtil.concat(
-                    "<html>" +
-                    "<body><br><br>" +
-                    "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>" +
-                    "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">",
-                    forum.getName(),
-                    " Form</a>" +
-                    "</td></tr>" +
-                    "</table>" +
-                    "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" +
-                    "<center>" +
-                    "<table border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td width=610><img src=\"sek.cbui355\" width=\"610\" height=\"1\"><br1><img src=\"sek.cbui355\" width=\"610\" height=\"1\"></td></tr>" +
-                    "</table>" +
-                    "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=20></td></tr>" +
-                    "<tr>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "<td align=center FIXWIDTH=60 height=29>&$413;</td>" +
-                    "<td FIXWIDTH=540>",
-                    topic.getName(),
-                    "</td>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "</tr></table>" +
-                    "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                    "<tr>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "<td align=center FIXWIDTH=60 height=29 valign=top>&$427;</td>" +
-                    "<td align=center FIXWIDTH=540><MultiEdit var =\"Content\" width=535 height=313></td>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "</tr>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                    "</table>" +
-                    "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                    "<tr>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "<td align=center FIXWIDTH=60 height=29>&nbsp;</td>" +
-                    "<td align=center FIXWIDTH=70><button value=\"&$140;\" action=\"Write Post ",
-                    String.valueOf(forum.getID()),
-                    ";",
-                    String.valueOf(topic.getID()),
-		    ";0 _ Content Content Content\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>" +
-                    "<td align=center FIXWIDTH=70><button value = \"&$141;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td>" +
-                    "<td align=center FIXWIDTH=400>&nbsp;</td>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "</tr></table>" +
-                    "</center>" +
-                    "</body>" +
-                    "</html>");
+		final String html = StringUtil.concat("<html>" + "<body><br><br>"
+				+ "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>"
+				+ "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">", forum.getName(), " Form</a>"
+				+ "</td></tr>"
+				+ "</table>"
+				+ "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">"
+				+ "<center>"
+				+ "<table border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td width=610><img src=\"sek.cbui355\" width=\"610\" height=\"1\"><br1><img src=\"sek.cbui355\" width=\"610\" height=\"1\"></td></tr>"
+				+ "</table>" + "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=20></td></tr>" + "<tr>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "<td align=center FIXWIDTH=60 height=29>&$413;</td>"
+				+ "<td FIXWIDTH=540>", topic.getName(), "</td>" + "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>"
+				+ "</tr></table>" + "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" + "<tr>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>"
+				+ "<td align=center FIXWIDTH=60 height=29 valign=top>&$427;</td>"
+				+ "<td align=center FIXWIDTH=540><MultiEdit var =\"Content\" width=535 height=313></td>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "</tr>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" + "</table>"
+				+ "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" + "<tr>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "<td align=center FIXWIDTH=60 height=29>&nbsp;</td>"
+				+ "<td align=center FIXWIDTH=70><button value=\"&$140;\" action=\"Write Post ", String.valueOf(forum.getID()), ";", String.valueOf(topic.getID()), ";0 _ Content Content Content\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>"
+				+ "<td align=center FIXWIDTH=70><button value = \"&$141;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td>"
+				+ "<td align=center FIXWIDTH=400>&nbsp;</td>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>"
+				+ "</tr></table>"
+				+ "</center>" + "</body>" + "</html>");
 		send1001(html, activeChar);
 		send1002(activeChar, p.getCPost(0).postTxt, topic.getName(), DateFormat.getInstance().format(new Date(topic.getDate())));
 	}
@@ -262,87 +237,43 @@ public class PostBBSManager extends BaseBBSManager
 		Post p = getGPosttByTopic(topic);
 		Locale locale = Locale.getDefault();
 		DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL, locale);
-
+		
 		String mes = p.getCPost(0).postTxt.replace(">", "&gt;");
 		mes = mes.replace("<", "&lt;");
 		mes = mes.replace("\n", "<br1>");
-
-                final String html = StringUtil.concat(
-                        "<html><body><br><br>" +
-                        "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>" +
-                        "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>" +
-                        "</td></tr>" +
-                        "</table>" +
-                        "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" +
-                        "<center>" +
-                        "<table border=0 cellspacing=0 cellpadding=0 bgcolor=333333>" +
-                        "<tr><td height=10></td></tr>" +
-                        "<tr>" +
-                        "<td fixWIDTH=55 align=right valign=top>&$413; : &nbsp;</td>" +
-                        "<td fixWIDTH=380 valign=top>",
-                        topic.getName(),
-                        "</td>" +
-                        "<td fixwidth=5></td>" +
-                        "<td fixwidth=50></td>" +
-                        "<td fixWIDTH=120></td>" +
-                        "</tr>" +
-                        "<tr><td height=10></td></tr>" +
-                        "<tr>" +
-                        "<td align=right><font color=\"AAAAAA\" >&$417; : &nbsp;</font></td>" +
-                        "<td><font color=\"AAAAAA\">",
-                        topic.getOwnerName() +
-                        "</font></td>" +
-                        "<td></td>" +
-                        "<td><font color=\"AAAAAA\">&$418; :</font></td>" +
-                        "<td><font color=\"AAAAAA\">",
-                        dateFormat.format(p.getCPost(0).postDate),
-                        "</font></td>" +
-                        "</tr>" +
-                        "<tr><td height=10></td></tr>" +
-                        "</table>" +
-                        "<br>" +
-                        "<table border=0 cellspacing=0 cellpadding=0>" +
-                        "<tr>" +
-                        "<td fixwidth=5></td>" +
-                        "<td FIXWIDTH=600 align=left>",
-                        mes,
-                        "</td>" +
-                        "<td fixqqwidth=5></td>" +
-                        "</tr>" +
-                        "</table>" +
-                        "<br>" +
-                        "<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">" +
-                        "<img src=\"L2UI.squaregray\" width=\"610\" height=\"1\">" +
-                        "<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">" +
-                        "<table border=0 cellspacing=0 cellpadding=0 FIXWIDTH=610>" +
-                        "<tr>" +
-                        "<td width=50>" +
-                        "<button value=\"&$422;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\">" +
-                        "</td>" +
-                        "<td width=560 align=right><table border=0 cellspacing=0><tr>" +
-                        "<td FIXWIDTH=300></td><td><button value = \"&$424;\" action=\"bypass _bbsposts;edit;",
-                        String.valueOf(forum.getID()),
-                        ";",
-                        String.valueOf(topic.getID()),
-			";0\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;" +
-                        "<td><button value = \"&$425;\" action=\"bypass _bbstopics;del;",
-                        String.valueOf(forum.getID()),
-                        ";",
-                        String.valueOf(topic.getID()),
-                        "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;" +
-                        "<td><button value = \"&$421;\" action=\"bypass _bbstopics;crea;",
-                        String.valueOf(forum.getID()),
-                        "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;" +
-                        "</tr></table>" +
-                        "</td>" +
-                        "</tr>" +
-                        "</table>" +
-                        "<br>" +
-                        "<br>" +
-                        "<br></center>" +
-                        "</body>" +
-                        "</html>"
-                        );
+		
+		final String html = StringUtil.concat("<html><body><br><br>"
+				+ "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>"
+				+ "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>" + "</td></tr>"
+				+ "</table>" + "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" + "<center>"
+				+ "<table border=0 cellspacing=0 cellpadding=0 bgcolor=333333>" + "<tr><td height=10></td></tr>" + "<tr>"
+				+ "<td fixWIDTH=55 align=right valign=top>&$413; : &nbsp;</td>" + "<td fixWIDTH=380 valign=top>", topic.getName(), "</td>"
+				+ "<td fixwidth=5></td>" + "<td fixwidth=50></td>" + "<td fixWIDTH=120></td>" + "</tr>" + "<tr><td height=10></td></tr>"
+				+ "<tr>" + "<td align=right><font color=\"AAAAAA\" >&$417; : &nbsp;</font></td>" + "<td><font color=\"AAAAAA\">", topic.getOwnerName()
+				+ "</font></td>" + "<td></td>" + "<td><font color=\"AAAAAA\">&$418; :</font></td>" + "<td><font color=\"AAAAAA\">", dateFormat.format(p.getCPost(0).postDate), "</font></td>"
+				+ "</tr>"
+				+ "<tr><td height=10></td></tr>"
+				+ "</table>"
+				+ "<br>"
+				+ "<table border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr>"
+				+ "<td fixwidth=5></td>" + "<td FIXWIDTH=600 align=left>", mes, "</td>"
+				+ "<td fixqqwidth=5></td>"
+				+ "</tr>"
+				+ "</table>"
+				+ "<br>"
+				+ "<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">"
+				+ "<img src=\"L2UI.squaregray\" width=\"610\" height=\"1\">"
+				+ "<img src=\"L2UI.squareblank\" width=\"1\" height=\"5\">"
+				+ "<table border=0 cellspacing=0 cellpadding=0 FIXWIDTH=610>"
+				+ "<tr>"
+				+ "<td width=50>"
+				+ "<button value=\"&$422;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\">"
+				+ "</td>" + "<td width=560 align=right><table border=0 cellspacing=0><tr>"
+				+ "<td FIXWIDTH=300></td><td><button value = \"&$424;\" action=\"bypass _bbsposts;edit;", String.valueOf(forum.getID()), ";", String.valueOf(topic.getID()), ";0\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;"
+				+ "<td><button value = \"&$425;\" action=\"bypass _bbstopics;del;", String.valueOf(forum.getID()), ";", String.valueOf(topic.getID()), "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;"
+				+ "<td><button value = \"&$421;\" action=\"bypass _bbstopics;crea;", String.valueOf(forum.getID()), "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>&nbsp;"
+				+ "</tr></table>" + "</td>" + "</tr>" + "</table>" + "<br>" + "<br>" + "<br></center>" + "</body>" + "</html>");
 		separateAndSend(html, activeChar);
 	}
 	
@@ -361,7 +292,8 @@ public class PostBBSManager extends BaseBBSManager
 		Forum f = ForumsBBSManager.getInstance().getForumByID(idf);
 		if (f == null)
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " does not exist !</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf
+					+ " does not exist !</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -371,7 +303,8 @@ public class PostBBSManager extends BaseBBSManager
 			Topic t = f.gettopic(idt);
 			if (t == null)
 			{
-				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + idt + " does not exist !</center><br><br></body></html>", "101");
+				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + idt
+						+ " does not exist !</center><br><br></body></html>", "101");
 				activeChar.sendPacket(sb);
 				activeChar.sendPacket(new ShowBoard(null, "102"));
 				activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -386,7 +319,8 @@ public class PostBBSManager extends BaseBBSManager
 				}
 				if (cp == null)
 				{
-					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the post: " + idp + " does not exist !</center><br><br></body></html>", "101");
+					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the post: " + idp
+							+ " does not exist !</center><br><br></body></html>", "101");
 					activeChar.sendPacket(sb);
 					activeChar.sendPacket(new ShowBoard(null, "102"));
 					activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -400,4 +334,10 @@ public class PostBBSManager extends BaseBBSManager
 			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final PostBBSManager _instance = new PostBBSManager();
+	}
 }

+ 168 - 363
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/RegionBBSManager.java

@@ -40,6 +40,10 @@ public class RegionBBSManager extends BaseBBSManager
 {
 	private static Logger _logChat = Logger.getLogger("chat");
 	
+	private RegionBBSManager()
+	{
+	}
+	
 	/**
 	 * 
 	 * @see net.sf.l2j.gameserver.communitybbs.Manager.BaseBBSManager#parsecmd(java.lang.String, net.sf.l2j.gameserver.model.actor.instance.L2PcInstance)
@@ -84,7 +88,8 @@ public class RegionBBSManager extends BaseBBSManager
 			}
 			else
 			{
-				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
+				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command
+						+ " is not implemented yet</center><br><br></body></html>", "101");
 				activeChar.sendPacket(sb);
 				activeChar.sendPacket(new ShowBoard(null, "102"));
 				activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -98,16 +103,15 @@ public class RegionBBSManager extends BaseBBSManager
 	 */
 	private void showOldCommunityPI(L2PcInstance activeChar, String name)
 	{
-            final StringBuilder htmlCode = StringUtil.startAppend(1000,
-                    "<html><body><br>" +
-                    "<table border=0><tr><td FIXWIDTH=15></td><td align=center>L2J Community Board<img src=\"sek.cbui355\" width=610 height=1></td></tr><tr><td FIXWIDTH=15></td><td>"
-                    );
+		final StringBuilder htmlCode = StringUtil.startAppend(1000, "<html><body><br>"
+				+ "<table border=0><tr><td FIXWIDTH=15></td><td align=center>L2J Community Board<img src=\"sek.cbui355\" width=610 height=1></td></tr><tr><td FIXWIDTH=15></td><td>");
 		L2PcInstance player = L2World.getInstance().getPlayer(name);
 		
 		if (player != null)
 		{
 			String sex = "Male";
-			if (player.getAppearance().getSex()) {
+			if (player.getAppearance().getSex())
+			{
 				sex = "Female";
 			}
 			String levelApprox = "low";
@@ -117,22 +121,12 @@ public class RegionBBSManager extends BaseBBSManager
 				levelApprox = "high";
 			else if (player.getLevel() >= 20)
 				levelApprox = "medium";
-
-                        StringUtil.append(htmlCode,
-                                "<table border=0><tr><td>",
-                                player.getName(),
-                                " (",
-                                sex,
-                                " ",
-                                player.getTemplate().className,
-                                "):</td></tr>" +
-                                "<tr><td>Level: ",
-                                levelApprox,
-                                "</td></tr>" +
-                                "<tr><td><br></td></tr>"
-                                );
 			
-			if (activeChar != null && (activeChar.isGM() || player.getObjectId() == activeChar.getObjectId() || Config.SHOW_LEVEL_COMMUNITYBOARD))
+			StringUtil.append(htmlCode, "<table border=0><tr><td>", player.getName(), " (", sex, " ", player.getTemplate().className, "):</td></tr>"
+					+ "<tr><td>Level: ", levelApprox, "</td></tr>" + "<tr><td><br></td></tr>");
+			
+			if (activeChar != null
+					&& (activeChar.isGM() || player.getObjectId() == activeChar.getObjectId() || Config.SHOW_LEVEL_COMMUNITYBOARD))
 			{
 				long nextLevelExp = 0;
 				long nextLevelExpNeeded = 0;
@@ -141,64 +135,32 @@ public class RegionBBSManager extends BaseBBSManager
 					nextLevelExp = Experience.LEVEL[player.getLevel() + 1];
 					nextLevelExpNeeded = nextLevelExp - player.getExp();
 				}
-
-                                StringUtil.append(htmlCode,
-                                        "<tr><td>Level: ",
-                                        String.valueOf(player.getLevel()),
-                                        "</td></tr>" +
-                                        "<tr><td>Experience: ",
-                                        String.valueOf(player.getExp()),
-                                        "/",
-                                        String.valueOf(nextLevelExp),
-                                        "</td></tr>" +
-                                        "<tr><td>Experience needed for level up: ",
-                                        String.valueOf(nextLevelExpNeeded),
-                                        "</td></tr>" +
-                                        "<tr><td><br></td></tr>"
-                                        );
+				
+				StringUtil.append(htmlCode, "<tr><td>Level: ", String.valueOf(player.getLevel()), "</td></tr>" + "<tr><td>Experience: ", String.valueOf(player.getExp()), "/", String.valueOf(nextLevelExp), "</td></tr>"
+						+ "<tr><td>Experience needed for level up: ", String.valueOf(nextLevelExpNeeded), "</td></tr>"
+						+ "<tr><td><br></td></tr>");
 			}
 			
 			int uptime = (int) player.getUptime() / 1000;
 			int h = uptime / 3600;
 			int m = (uptime - (h * 3600)) / 60;
 			int s = ((uptime - (h * 3600)) - (m * 60));
-
-                        StringUtil.append(htmlCode,
-                                "<tr><td>Uptime: ",
-                                String.valueOf(h),
-                                "h ",
-                                String.valueOf(m),
-                                "m ",
-                                String.valueOf(s),
-                                "s</td></tr>" +
-                                "<tr><td><br></td></tr>"
-                                );
 			
-			if (player.getClan() != null) {
-                            StringUtil.append(htmlCode,
-                                    "<tr><td>Clan: ",
-                                    player.getClan().getName(),
-                                    "</td></tr>" +
-                                    "<tr><td><br></td></tr>"
-                                    );
+			StringUtil.append(htmlCode, "<tr><td>Uptime: ", String.valueOf(h), "h ", String.valueOf(m), "m ", String.valueOf(s), "s</td></tr>"
+					+ "<tr><td><br></td></tr>");
+			
+			if (player.getClan() != null)
+			{
+				StringUtil.append(htmlCode, "<tr><td>Clan: ", player.getClan().getName(), "</td></tr>" + "<tr><td><br></td></tr>");
 			}
-
-                        StringUtil.append(htmlCode,
-                                "<tr><td><multiedit var=\"pm\" width=240 height=40><button value=\"Send PM\" action=\"Write Region PM ",
-                                player.getName(),
-                                " pm pm pm\" width=110 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr><tr><td><br><button value=\"Back\" action=\"bypass _bbsloc\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>" +
-                                "</td></tr></table>" +
-                                "</body></html>"
-                                );
+			
+			StringUtil.append(htmlCode, "<tr><td><multiedit var=\"pm\" width=240 height=40><button value=\"Send PM\" action=\"Write Region PM ", player.getName(), " pm pm pm\" width=110 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr><tr><td><br><button value=\"Back\" action=\"bypass _bbsloc\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>"
+					+ "</td></tr></table>" + "</body></html>");
 			separateAndSend(htmlCode.toString(), activeChar);
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard(
-                                StringUtil.concat(
-                                "<html><body><br><br><center>No player with name ",
-                                name,
-                                "</center><br><br></body></html>"), "101");
+			ShowBoard sb = new ShowBoard(StringUtil.concat("<html><body><br><br><center>No player with name ", name, "</center><br><br></body></html>"), "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -224,10 +186,8 @@ public class RegionBBSManager extends BaseBBSManager
 		
 		if (ar1.equals("PM"))
 		{
-                    final StringBuilder htmlCode = StringUtil.startAppend(500,
-                            "<html><body><br>" +
-                            "<table border=0><tr><td FIXWIDTH=15></td><td align=center>L2J Community Board<img src=\"sek.cbui355\" width=610 height=1></td></tr><tr><td FIXWIDTH=15></td><td>"
-                            );
+			final StringBuilder htmlCode = StringUtil.startAppend(500, "<html><body><br>"
+					+ "<table border=0><tr><td FIXWIDTH=15></td><td align=center>L2J Community Board<img src=\"sek.cbui355\" width=610 height=1></td></tr><tr><td FIXWIDTH=15></td><td>");
 			
 			try
 			{
@@ -235,12 +195,8 @@ public class RegionBBSManager extends BaseBBSManager
 				L2PcInstance receiver = L2World.getInstance().getPlayer(ar2);
 				if (receiver == null)
 				{
-                                    StringUtil.append(htmlCode,
-                                            "Player not found!<br><button value=\"Back\" action=\"bypass _bbsloc;playerinfo;",
-                                            ar2,
-                                            "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
-                                            "</td></tr></table></body></html>"
-                                            );
+					StringUtil.append(htmlCode, "Player not found!<br><button value=\"Back\" action=\"bypass _bbsloc;playerinfo;", ar2, "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">"
+							+ "</td></tr></table></body></html>");
 					separateAndSend(htmlCode.toString(), activeChar);
 					return;
 				}
@@ -269,10 +225,7 @@ public class RegionBBSManager extends BaseBBSManager
 				{
 					LogRecord record = new LogRecord(Level.INFO, ar3);
 					record.setLoggerName("chat");
-					record.setParameters(new Object[]
-					{
-						"TELL", "[" + activeChar.getName() + " to " + receiver.getName() + "]"
-					});
+					record.setParameters(new Object[] { "TELL", "[" + activeChar.getName() + " to " + receiver.getName() + "]" });
 					_logChat.log(record);
 				}
 				CreatureSay cs = new CreatureSay(activeChar.getObjectId(), Say2.TELL, activeChar.getName(), ar3);
@@ -282,12 +235,8 @@ public class RegionBBSManager extends BaseBBSManager
 					{
 						receiver.sendPacket(cs);
 						activeChar.sendPacket(new CreatureSay(activeChar.getObjectId(), Say2.TELL, "->" + receiver.getName(), ar3));
-                                                StringUtil.append(htmlCode,
-                                                        "Message Sent<br><button value=\"Back\" action=\"bypass _bbsloc;playerinfo;",
-                                                        receiver.getName(),
-                                                        "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
-                                                        "</td></tr></table></body></html>"
-                                                        );
+						StringUtil.append(htmlCode, "Message Sent<br><button value=\"Back\" action=\"bypass _bbsloc;playerinfo;", receiver.getName(), "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">"
+								+ "</td></tr></table></body></html>");
 						separateAndSend(htmlCode.toString(), activeChar);
 					}
 					else
@@ -312,18 +261,13 @@ public class RegionBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard(
-                                StringUtil.concat(
-                                "<html><body><br><br><center>the command: ",
-                                ar1,
-                                " is not implemented yet</center><br><br></body></html>"), "101");
+			ShowBoard sb = new ShowBoard(StringUtil.concat("<html><body><br><br><center>the command: ", ar1, " is not implemented yet</center><br><br></body></html>"), "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
 		}
 		
 	}
-	private static RegionBBSManager _instance = null;
 	private int _onlineCount = 0;
 	private int _onlineCountGm = 0;
 	private static FastMap<Integer, FastList<L2PcInstance>> _onlinePlayers = new FastMap<Integer, FastList<L2PcInstance>>().setShared(true);
@@ -334,11 +278,7 @@ public class RegionBBSManager extends BaseBBSManager
 	 */
 	public static RegionBBSManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new RegionBBSManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public synchronized void changeCommunityBoard()
@@ -408,256 +348,129 @@ public class RegionBBSManager extends BaseBBSManager
 		}
 	}
 	
-	private void writeCommunityPages() {
-            final StringBuilder htmlCode = new StringBuilder(2000);
-            final String tdClose = "</td>";
-            final String tdOpen = "<td align=left valign=top>";
-            final String trClose = "</tr>";
-            final String trOpen = "<tr>";
-            final String colSpacer = "<td FIXWIDTH=15></td>";
-            
-		for (int page : _onlinePlayers.keySet()) {
+	private void writeCommunityPages()
+	{
+		final StringBuilder htmlCode = new StringBuilder(2000);
+		final String tdClose = "</td>";
+		final String tdOpen = "<td align=left valign=top>";
+		final String trClose = "</tr>";
+		final String trOpen = "<tr>";
+		final String colSpacer = "<td FIXWIDTH=15></td>";
+		
+		for (int page : _onlinePlayers.keySet())
+		{
 			FastMap<String, String> communityPage = new FastMap<String, String>();
-                        htmlCode.setLength(0);
-                        StringUtil.append(htmlCode,
-                                "<html><body><br>" +
-                                "<table>" +
-                                trOpen +
-                                "<td align=left valign=top>Server Restarted: ",
-                                String.valueOf(GameServer.dateTimeServerStarted.getTime()),
-                                tdClose +
-                                trClose +
-                                "</table>" +
-                                "<table>" +
-                                trOpen +
-                                tdOpen +
-                                "XP Rate: x",
-                                String.valueOf(Config.RATE_XP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Party XP Rate: x",
-                                String.valueOf(Config.RATE_XP * Config.RATE_PARTY_XP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "XP Exponent: ",
-                                String.valueOf(Config.ALT_GAME_EXPONENT_XP),
-                                tdClose +
-                                trClose +
-                                trOpen +
-                                tdOpen +
-                                "SP Rate: x",
-                                String.valueOf(Config.RATE_SP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Party SP Rate: x",
-                                String.valueOf(Config.RATE_SP * Config.RATE_PARTY_SP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "SP Exponent: ",
-                                String.valueOf(Config.ALT_GAME_EXPONENT_SP),
-                                tdClose +
-                                trClose +
-                                trOpen +
-                                tdOpen +
-                                "Drop Rate: ",
-                                String.valueOf(Config.RATE_DROP_ITEMS),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Spoil Rate: ",
-                                String.valueOf(Config.RATE_DROP_SPOIL),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Adena Rate: ",
-                                String.valueOf(Config.RATE_DROP_ADENA),
-                                tdClose +
-                                trClose +
-                                "</table>" +
-                                "<table>" +
-                                trOpen +
-                                "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>" +
-                                trClose +
-                                trOpen +
-                                tdOpen,
-                                String.valueOf(L2World.getInstance().getAllVisibleObjectsCount()),
-                                " Object count</td>" +
-                                trClose +
-                                trOpen +
-                                tdOpen,
-                                String.valueOf(getOnlineCount("gm")),
-                                " Player(s) Online</td>" +
-                                trClose +
-                                "</table>"
-                                );
+			htmlCode.setLength(0);
+			StringUtil.append(htmlCode, "<html><body><br>" + "<table>" + trOpen + "<td align=left valign=top>Server Restarted: ", String.valueOf(GameServer.dateTimeServerStarted.getTime()), tdClose
+					+ trClose + "</table>" + "<table>" + trOpen + tdOpen + "XP Rate: x", String.valueOf(Config.RATE_XP), tdClose
+					+ colSpacer + tdOpen + "Party XP Rate: x", String.valueOf(Config.RATE_XP * Config.RATE_PARTY_XP), tdClose + colSpacer
+					+ tdOpen + "XP Exponent: ", String.valueOf(Config.ALT_GAME_EXPONENT_XP), tdClose + trClose + trOpen + tdOpen
+					+ "SP Rate: x", String.valueOf(Config.RATE_SP), tdClose + colSpacer + tdOpen + "Party SP Rate: x", String.valueOf(Config.RATE_SP
+					* Config.RATE_PARTY_SP), tdClose + colSpacer + tdOpen + "SP Exponent: ", String.valueOf(Config.ALT_GAME_EXPONENT_SP), tdClose
+					+ trClose + trOpen + tdOpen + "Drop Rate: ", String.valueOf(Config.RATE_DROP_ITEMS), tdClose + colSpacer + tdOpen
+					+ "Spoil Rate: ", String.valueOf(Config.RATE_DROP_SPOIL), tdClose + colSpacer + tdOpen + "Adena Rate: ", String.valueOf(Config.RATE_DROP_ADENA), tdClose
+					+ trClose
+					+ "</table>"
+					+ "<table>"
+					+ trOpen
+					+ "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>"
+					+ trClose
+					+ trOpen + tdOpen, String.valueOf(L2World.getInstance().getAllVisibleObjectsCount()), " Object count</td>" + trClose
+					+ trOpen + tdOpen, String.valueOf(getOnlineCount("gm")), " Player(s) Online</td>" + trClose + "</table>");
 			
 			int cell = 0;
-			if (Config.BBS_SHOW_PLAYERLIST) {
-				htmlCode.append("<table border=0>" +
-                                        "<tr><td><table border=0>");
+			if (Config.BBS_SHOW_PLAYERLIST)
+			{
+				htmlCode.append("<table border=0><tr><td><table border=0>");
 				
 				for (L2PcInstance player : getOnlinePlayers(page))
 				{
 					cell++;
 					
-					if (cell == 1) {
+					if (cell == 1)
+					{
 						htmlCode.append(trOpen);
-                                        }
-
-                                        StringUtil.append(htmlCode,
-                                                "<td align=left valign=top FIXWIDTH=110><a action=\"bypass _bbsloc;playerinfo;",
-                                                player.getName(),
-                                                "\">");
+					}
 					
-					if (player.isGM()) {
-                                            StringUtil.append(htmlCode,
-                                                    "<font color=\"LEVEL\">",
-                                                    player.getName(),
-                                                    "</font>");
-                                        } else {
+					StringUtil.append(htmlCode, "<td align=left valign=top FIXWIDTH=110><a action=\"bypass _bbsloc;playerinfo;", player.getName(), "\">");
+					
+					if (player.isGM())
+					{
+						StringUtil.append(htmlCode, "<font color=\"LEVEL\">", player.getName(), "</font>");
+					}
+					else
+					{
 						htmlCode.append(player.getName());
-                                        }
+					}
 					
 					htmlCode.append("</a></td>");
 					
 					if (cell < Config.NAME_PER_ROW_COMMUNITYBOARD)
 						htmlCode.append(colSpacer);
 					
-					if (cell == Config.NAME_PER_ROW_COMMUNITYBOARD) {
+					if (cell == Config.NAME_PER_ROW_COMMUNITYBOARD)
+					{
 						cell = 0;
 						htmlCode.append(trClose);
 					}
 				}
-				if (cell > 0 && cell < Config.NAME_PER_ROW_COMMUNITYBOARD) {
+				if (cell > 0 && cell < Config.NAME_PER_ROW_COMMUNITYBOARD)
+				{
 					htmlCode.append(trClose);
-                                }
-
-				htmlCode.append("</table><br></td></tr>" +
-                                        trOpen +
-                                        "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>" +
-                                        trClose +
-                                        "</table>");
+				}
+				
+				htmlCode.append("</table><br></td></tr>" + trOpen + "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>" + trClose
+						+ "</table>");
 			}
 			
 			if (getOnlineCount("gm") > Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
 			{
-				htmlCode.append("<table border=0 width=600>" +
-                                        "<tr>");
-				if (page == 1) {
+				htmlCode.append("<table border=0 width=600><tr>");
+				if (page == 1)
+				{
 					htmlCode.append("<td align=right width=190><button value=\"Prev\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                } else {
-                                    StringUtil.append(htmlCode,
-                                            "<td align=right width=190><button value=\"Prev\" action=\"bypass _bbsloc;page;",
-                                            String.valueOf(page - 1),
-                                            "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                }
-
-                                StringUtil.append(htmlCode,
-                                        "<td FIXWIDTH=10></td>" +
-                                        "<td align=center valign=top width=200>Displaying ",
-                                        String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + 1),
-                                        " - ",
-                                        String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + getOnlinePlayers(page).size()),
-                                        " player(s)</td>" +
-                                        "<td FIXWIDTH=10></td>"
-                                        );
-				if (getOnlineCount("gm") <= (page * Config.NAME_PAGE_SIZE_COMMUNITYBOARD)) {
+				}
+				else
+				{
+					StringUtil.append(htmlCode, "<td align=right width=190><button value=\"Prev\" action=\"bypass _bbsloc;page;", String.valueOf(page - 1), "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
+				}
+				
+				StringUtil.append(htmlCode, "<td FIXWIDTH=10></td>" + "<td align=center valign=top width=200>Displaying ", String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + 1), " - ", String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
+						+ getOnlinePlayers(page).size()), " player(s)</td>" + "<td FIXWIDTH=10></td>");
+				if (getOnlineCount("gm") <= (page * Config.NAME_PAGE_SIZE_COMMUNITYBOARD))
+				{
 					htmlCode.append("<td width=190><button value=\"Next\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                } else {
-                                    StringUtil.append(htmlCode,
-                                            "<td width=190><button value=\"Next\" action=\"bypass _bbsloc;page;",
-                                            String.valueOf(page + 1),
-                                            "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                }
-				htmlCode.append(
-                                        "</tr>" +
-                                        "</table>");
+				}
+				else
+				{
+					StringUtil.append(htmlCode, "<td width=190><button value=\"Next\" action=\"bypass _bbsloc;page;", String.valueOf(page + 1), "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
+				}
+				htmlCode.append("</tr></table>");
 			}
 			
 			htmlCode.append("</body></html>");
 			
 			communityPage.put("gm", htmlCode.toString());
-
-                        htmlCode.setLength(0);
-                        StringUtil.append(htmlCode,
-                                "<html><body><br>" +
-                                "<table>" +
-                                trOpen +
-                                "<td align=left valign=top>Server Restarted: ",
-                                String.valueOf(GameServer.dateTimeServerStarted.getTime()),
-                                tdClose +
-                                trClose +
-                                "</table>" +
-                                "<table>" +
-                                trOpen +
-                                tdOpen +
-                                "XP Rate: ",
-                                String.valueOf(Config.RATE_XP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Party XP Rate: ",
-                                String.valueOf(Config.RATE_PARTY_XP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "XP Exponent: ",
-                                String.valueOf(Config.ALT_GAME_EXPONENT_XP),
-                                tdClose +
-                                trClose +
-                                trOpen +
-                                tdOpen +
-                                "SP Rate: ",
-                                String.valueOf(Config.RATE_SP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Party SP Rate: ",
-                                String.valueOf(Config.RATE_PARTY_SP),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "SP Exponent: ",
-                                String.valueOf(Config.ALT_GAME_EXPONENT_SP),
-                                tdClose +
-                                trClose +
-                                trOpen +
-                                tdOpen +
-                                "Drop Rate: ",
-                                String.valueOf(Config.RATE_DROP_ITEMS),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Spoil Rate: ",
-                                String.valueOf(Config.RATE_DROP_SPOIL),
-                                tdClose +
-                                colSpacer +
-                                tdOpen +
-                                "Adena Rate: ",
-                                String.valueOf(Config.RATE_DROP_ADENA),
-                                tdClose +
-                                trClose +
-                                "</table>" +
-                                "<table>" +
-                                trOpen +
-                                "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>" +
-                                trClose +
-                                trOpen +
-                                tdOpen,
-                                String.valueOf(getOnlineCount("pl")),
-                                " Player(s) Online</td>" +
-                                trClose +
-                                "</table>"
-                                );
+			
+			htmlCode.setLength(0);
+			StringUtil.append(htmlCode, "<html><body><br>" + "<table>" + trOpen + "<td align=left valign=top>Server Restarted: ", String.valueOf(GameServer.dateTimeServerStarted.getTime()), tdClose
+					+ trClose + "</table>" + "<table>" + trOpen + tdOpen + "XP Rate: ", String.valueOf(Config.RATE_XP), tdClose + colSpacer
+					+ tdOpen + "Party XP Rate: ", String.valueOf(Config.RATE_PARTY_XP), tdClose + colSpacer + tdOpen + "XP Exponent: ", String.valueOf(Config.ALT_GAME_EXPONENT_XP), tdClose
+					+ trClose + trOpen + tdOpen + "SP Rate: ", String.valueOf(Config.RATE_SP), tdClose + colSpacer + tdOpen
+					+ "Party SP Rate: ", String.valueOf(Config.RATE_PARTY_SP), tdClose + colSpacer + tdOpen + "SP Exponent: ", String.valueOf(Config.ALT_GAME_EXPONENT_SP), tdClose
+					+ trClose + trOpen + tdOpen + "Drop Rate: ", String.valueOf(Config.RATE_DROP_ITEMS), tdClose + colSpacer + tdOpen
+					+ "Spoil Rate: ", String.valueOf(Config.RATE_DROP_SPOIL), tdClose + colSpacer + tdOpen + "Adena Rate: ", String.valueOf(Config.RATE_DROP_ADENA), tdClose
+					+ trClose
+					+ "</table>"
+					+ "<table>"
+					+ trOpen
+					+ "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>"
+					+ trClose
+					+ trOpen + tdOpen, String.valueOf(getOnlineCount("pl")), " Player(s) Online</td>" + trClose + "</table>");
 			
 			if (Config.BBS_SHOW_PLAYERLIST)
 			{
-				htmlCode.append("<table border=0>" +
-                                        "<tr><td><table border=0>");
+				htmlCode.append("<table border=0><tr><td><table border=0>");
 				
 				cell = 0;
 				for (L2PcInstance player : getOnlinePlayers(page))
@@ -667,23 +480,21 @@ public class RegionBBSManager extends BaseBBSManager
 						
 					cell++;
 					
-					if (cell == 1) {
+					if (cell == 1)
+					{
 						htmlCode.append(trOpen);
-                                        }
-
-                                        StringUtil.append(htmlCode,
-                                                "<td align=left valign=top FIXWIDTH=110><a action=\"bypass _bbsloc;playerinfo;",
-                                                player.getName(),
-                                                "\">");
+					}
+					
+					StringUtil.append(htmlCode, "<td align=left valign=top FIXWIDTH=110><a action=\"bypass _bbsloc;playerinfo;", player.getName(), "\">");
 					
-					if (player.isGM()) {
-                                            StringUtil.append(htmlCode,
-                                                    "<font color=\"LEVEL\">",
-                                                    player.getName(),
-                                                    "</font>");
-                                        } else {
+					if (player.isGM())
+					{
+						StringUtil.append(htmlCode, "<font color=\"LEVEL\">", player.getName(), "</font>");
+					}
+					else
+					{
 						htmlCode.append(player.getName());
-                                        }
+					}
 					
 					htmlCode.append("</a></td>");
 					
@@ -698,49 +509,37 @@ public class RegionBBSManager extends BaseBBSManager
 				}
 				if (cell > 0 && cell < Config.NAME_PER_ROW_COMMUNITYBOARD)
 					htmlCode.append(trClose);
-
-				htmlCode.append("</table><br></td></tr>" +
-                                        trOpen +
-                                        "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>" +
-                                        trClose +
-                                        "</table>");
+				
+				htmlCode.append("</table><br></td></tr>" + trOpen + "<td><img src=\"sek.cbui355\" width=600 height=1><br></td>" + trClose
+						+ "</table>");
 			}
 			
 			if (getOnlineCount("pl") > Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
 			{
-				htmlCode.append("<table border=0 width=600>" +
-                                        "<tr>");
-
-				if (page == 1) {
+				htmlCode.append("<table border=0 width=600><tr>");
+				
+				if (page == 1)
+				{
 					htmlCode.append("<td align=right width=190><button value=\"Prev\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                } else {
-                                    StringUtil.append(htmlCode,
-                                            "<td align=right width=190><button value=\"Prev\" action=\"bypass _bbsloc;page;",
-                                            String.valueOf(page - 1),
-                                            "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                }
-
-                                StringUtil.append(htmlCode,
-                                        "<td FIXWIDTH=10></td>" +
-                                        "<td align=center valign=top width=200>Displaying ",
-                                        String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + 1),
-                                        " - ",
-                                        String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + getOnlinePlayers(page).size()),
-                                        " player(s)</td>" +
-                                        "<td FIXWIDTH=10></td>"
-                                        );
-
-                                if (getOnlineCount("pl") <= (page * Config.NAME_PAGE_SIZE_COMMUNITYBOARD)) {
+				}
+				else
+				{
+					StringUtil.append(htmlCode, "<td align=right width=190><button value=\"Prev\" action=\"bypass _bbsloc;page;", String.valueOf(page - 1), "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
+				}
+				
+				StringUtil.append(htmlCode, "<td FIXWIDTH=10></td>" + "<td align=center valign=top width=200>Displaying ", String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD) + 1), " - ", String.valueOf(((page - 1) * Config.NAME_PAGE_SIZE_COMMUNITYBOARD)
+						+ getOnlinePlayers(page).size()), " player(s)</td>" + "<td FIXWIDTH=10></td>");
+				
+				if (getOnlineCount("pl") <= (page * Config.NAME_PAGE_SIZE_COMMUNITYBOARD))
+				{
 					htmlCode.append("<td width=190><button value=\"Next\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                } else {
-                                    StringUtil.append(htmlCode,
-                                            "<td width=190><button value=\"Next\" action=\"bypass _bbsloc;page;",
-                                            String.valueOf(page + 1),
-                                            "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
-                                }
-
-				htmlCode.append("</tr>" +
-                                        "</table>");
+				}
+				else
+				{
+					StringUtil.append(htmlCode, "<td width=190><button value=\"Next\" action=\"bypass _bbsloc;page;", String.valueOf(page + 1), "\" width=50 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
+				}
+				
+				htmlCode.append("</tr></table>");
 			}
 			
 			htmlCode.append("</body></html>");
@@ -771,4 +570,10 @@ public class RegionBBSManager extends BaseBBSManager
 		else
 			return null;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final RegionBBSManager _instance = new RegionBBSManager();
+	}
 }

+ 13 - 5
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/TopBBSManager.java

@@ -22,6 +22,9 @@ import net.sf.l2j.gameserver.network.serverpackets.ShowBoard;
 
 public class TopBBSManager extends BaseBBSManager
 {
+	private TopBBSManager()
+	{
+	}
 	
 	/**
 	 * 
@@ -56,13 +59,15 @@ public class TopBBSManager extends BaseBBSManager
 			String content = HtmCache.getInstance().getHtm("data/html/CommunityBoard/" + idp + ".htm");
 			if (content == null)
 			{
-				content = "<html><body><br><br><center>404 :File Not foud: 'data/html/CommunityBoard/" + idp + ".htm' </center></body></html>";
+				content = "<html><body><br><br><center>404 :File Not foud: 'data/html/CommunityBoard/" + idp
+						+ ".htm' </center></body></html>";
 			}
 			separateAndSend(content, activeChar);
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -80,14 +85,17 @@ public class TopBBSManager extends BaseBBSManager
 		
 	}
 	
-	private static TopBBSManager _instance = new TopBBSManager();
-	
 	/**
 	 * @return
 	 */
 	public static TopBBSManager getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final TopBBSManager _instance = new TopBBSManager();
+	}
 }

+ 109 - 160
L2_GameServer/java/net/sf/l2j/gameserver/communitybbs/Manager/TopicBBSManager.java

@@ -35,15 +35,10 @@ public class TopicBBSManager extends BaseBBSManager
 {
 	private List<Topic> _table;
 	private Map<Forum, Integer> _maxId;
-	private static TopicBBSManager _instance;
 	
 	public static TopicBBSManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new TopicBBSManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private TopicBBSManager()
@@ -105,7 +100,8 @@ public class TopicBBSManager extends BaseBBSManager
 			Forum f = ForumsBBSManager.getInstance().getForumByID(Integer.parseInt(ar2));
 			if (f == null)
 			{
-				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + ar2 + " is not implemented yet</center><br><br></body></html>", "101");
+				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + ar2
+						+ " is not implemented yet</center><br><br></body></html>", "101");
 				activeChar.sendPacket(sb);
 				activeChar.sendPacket(new ShowBoard(null, "102"));
 				activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -127,7 +123,8 @@ public class TopicBBSManager extends BaseBBSManager
 			Forum f = ForumsBBSManager.getInstance().getForumByID(Integer.parseInt(ar2));
 			if (f == null)
 			{
-				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + ar2 + " does not exist !</center><br><br></body></html>", "101");
+				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + ar2
+						+ " does not exist !</center><br><br></body></html>", "101");
 				activeChar.sendPacket(sb);
 				activeChar.sendPacket(new ShowBoard(null, "102"));
 				activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -137,7 +134,8 @@ public class TopicBBSManager extends BaseBBSManager
 				Topic t = f.gettopic(Integer.parseInt(ar3));
 				if (t == null)
 				{
-					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + ar3 + " does not exist !</center><br><br></body></html>", "101");
+					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + ar3
+							+ " does not exist !</center><br><br></body></html>", "101");
 					activeChar.sendPacket(sb);
 					activeChar.sendPacket(new ShowBoard(null, "102"));
 					activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -157,7 +155,8 @@ public class TopicBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + ar1 + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + ar1
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -215,7 +214,8 @@ public class TopicBBSManager extends BaseBBSManager
 			Forum f = ForumsBBSManager.getInstance().getForumByID(idf);
 			if (f == null)
 			{
-				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " does not exist !</center><br><br></body></html>", "101");
+				ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf
+						+ " does not exist !</center><br><br></body></html>", "101");
 				activeChar.sendPacket(sb);
 				activeChar.sendPacket(new ShowBoard(null, "102"));
 				activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -225,7 +225,8 @@ public class TopicBBSManager extends BaseBBSManager
 				Topic t = f.gettopic(idt);
 				if (t == null)
 				{
-					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + idt + " does not exist !</center><br><br></body></html>", "101");
+					ShowBoard sb = new ShowBoard("<html><body><br><br><center>the topic: " + idt
+							+ " does not exist !</center><br><br></body></html>", "101");
 					activeChar.sendPacket(sb);
 					activeChar.sendPacket(new ShowBoard(null, "102"));
 					activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -245,7 +246,8 @@ public class TopicBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the command: " + command
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -261,7 +263,8 @@ public class TopicBBSManager extends BaseBBSManager
 	{
 		if (forum == null)
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -272,7 +275,8 @@ public class TopicBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName() + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName()
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -285,52 +289,37 @@ public class TopicBBSManager extends BaseBBSManager
 	 */
 	private void showMemoNewTopics(Forum forum, L2PcInstance activeChar)
 	{
-            final String html = StringUtil.concat(
-                    "<html>" +
-                    "<body><br><br>" +
-                    "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>" +
-                    "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>" +
-                    "</td></tr>" +
-                    "</table>" +
-                    "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" +
-                    "<center>" +
-                    "<table border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td width=610><img src=\"sek.cbui355\" width=\"610\" height=\"1\"><br1><img src=\"sek.cbui355\" width=\"610\" height=\"1\"></td></tr>" +
-                    "</table>" +
-                    "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=20></td></tr>" +
-                    "<tr>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "<td align=center FIXWIDTH=60 height=29>&$413;</td>" +
-                    "<td FIXWIDTH=540><edit var = \"Title\" width=540 height=13></td>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "</tr></table>" +
-                    "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                    "<tr>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "<td align=center FIXWIDTH=60 height=29 valign=top>&$427;</td>" +
-                    "<td align=center FIXWIDTH=540><MultiEdit var =\"Content\" width=535 height=313></td>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "</tr>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                    "</table>" +
-                    "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>" +
-                    "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                    "<tr>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "<td align=center FIXWIDTH=60 height=29>&nbsp;</td>" +
-                    "<td align=center FIXWIDTH=70><button value=\"&$140;\" action=\"Write Topic crea ",
-                    String.valueOf(forum.getID()),
-                    " Title Content Title\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>" +
-                    "<td align=center FIXWIDTH=70><button value = \"&$141;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td>" +
-                    "<td align=center FIXWIDTH=400>&nbsp;</td>" +
-                    "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" +
-                    "</tr></table>" +
-                    "</center>" +
-                    "</body>" +
-                    "</html>"
-                    );
+		final String html = StringUtil.concat("<html>"
+				+ "<body><br><br>"
+				+ "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>"
+				+ "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>"
+				+ "</td></tr>"
+				+ "</table>"
+				+ "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">"
+				+ "<center>"
+				+ "<table border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td width=610><img src=\"sek.cbui355\" width=\"610\" height=\"1\"><br1><img src=\"sek.cbui355\" width=\"610\" height=\"1\"></td></tr>"
+				+ "</table>" + "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=20></td></tr>" + "<tr>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "<td align=center FIXWIDTH=60 height=29>&$413;</td>"
+				+ "<td FIXWIDTH=540><edit var = \"Title\" width=540 height=13></td>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "</tr></table>"
+				+ "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" + "<tr>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>"
+				+ "<td align=center FIXWIDTH=60 height=29 valign=top>&$427;</td>"
+				+ "<td align=center FIXWIDTH=540><MultiEdit var =\"Content\" width=535 height=313></td>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "</tr>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" + "</table>"
+				+ "<table fixwidth=610 border=0 cellspacing=0 cellpadding=0>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" + "<tr>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>" + "<td align=center FIXWIDTH=60 height=29>&nbsp;</td>"
+				+ "<td align=center FIXWIDTH=70><button value=\"&$140;\" action=\"Write Topic crea ", String.valueOf(forum.getID()), " Title Content Title\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td>"
+				+ "<td align=center FIXWIDTH=70><button value = \"&$141;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td>"
+				+ "<td align=center FIXWIDTH=400>&nbsp;</td>"
+				+ "<td><img src=\"l2ui.mini_logo\" width=5 height=1></td>"
+				+ "</tr></table>"
+				+ "</center>" + "</body>" + "</html>");
 		send1001(html, activeChar);
 		send1002(activeChar);
 	}
@@ -342,7 +331,8 @@ public class TopicBBSManager extends BaseBBSManager
 	{
 		if (forum == null)
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + idf
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -353,7 +343,8 @@ public class TopicBBSManager extends BaseBBSManager
 		}
 		else
 		{
-			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName() + " is not implemented yet</center><br><br></body></html>", "101");
+			ShowBoard sb = new ShowBoard("<html><body><br><br><center>the forum: " + forum.getName()
+					+ " is not implemented yet</center><br><br></body></html>", "101");
 			activeChar.sendPacket(sb);
 			activeChar.sendPacket(new ShowBoard(null, "102"));
 			activeChar.sendPacket(new ShowBoard(null, "103"));
@@ -367,24 +358,14 @@ public class TopicBBSManager extends BaseBBSManager
 	private void showMemoTopics(Forum forum, L2PcInstance activeChar, int index)
 	{
 		forum.vload();
-                final StringBuilder html = StringUtil.startAppend(2000,
-                        "<html><body><br><br>" +
-                        "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>" +
-                        "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>" +
-                        "</td></tr>" +
-                        "</table>" +
-                        "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" +
-                        "<center>" +
-                        "<table border=0 cellspacing=0 cellpadding=2 bgcolor=888888 width=610>" +
-                        "<tr>" +
-                        "<td FIXWIDTH=5></td>" +
-                        "<td FIXWIDTH=415 align=center>&$413;</td>" +
-                        "<td FIXWIDTH=120 align=center></td>" +
-                        "<td FIXWIDTH=70 align=center>&$418;</td>" +
-                        "</tr>" +
-                        "</table>"
-                        );
-                final DateFormat dateFormat = DateFormat.getInstance();
+		final StringBuilder html = StringUtil.startAppend(2000, "<html><body><br><br>"
+				+ "<table border=0 width=610><tr><td width=10></td><td width=600 align=left>"
+				+ "<a action=\"bypass _bbshome\">HOME</a>&nbsp;>&nbsp;<a action=\"bypass _bbsmemo\">Memo Form</a>" + "</td></tr>"
+				+ "</table>" + "<img src=\"L2UI.squareblank\" width=\"1\" height=\"10\">" + "<center>"
+				+ "<table border=0 cellspacing=0 cellpadding=2 bgcolor=888888 width=610>" + "<tr>" + "<td FIXWIDTH=5></td>"
+				+ "<td FIXWIDTH=415 align=center>&$413;</td>" + "<td FIXWIDTH=120 align=center></td>"
+				+ "<td FIXWIDTH=70 align=center>&$418;</td>" + "</tr>" + "</table>");
+		final DateFormat dateFormat = DateFormat.getInstance();
 		
 		for (int i = 0, j = getMaxID(forum) + 1; i < 12 * index; j--)
 		{
@@ -395,103 +376,71 @@ public class TopicBBSManager extends BaseBBSManager
 			Topic t = forum.gettopic(j);
 			if (t != null)
 			{
-				if (i++ >= 12 * (index - 1)) {
-                                    StringUtil.append(html,
-                                            "<table border=0 cellspacing=0 cellpadding=5 WIDTH=610>" +
-                                            "<tr>" +
-                                            "<td FIXWIDTH=5></td>" +
-                                            "<td FIXWIDTH=415><a action=\"bypass _bbsposts;read;",
-                                            String.valueOf(forum.getID()),
-                                            ";",
-                                            String.valueOf(t.getID()),
-                                            "\">",
-                                            t.getName(),
-                                            "</a></td>" +
-                                            "<td FIXWIDTH=120 align=center></td>" +
-                                            "<td FIXWIDTH=70 align=center>",
-                                            dateFormat.format(new Date(t.getDate())),
-                                            "</td>" +
-                                            "</tr>" +
-                                            "</table>" +
-                                            "<img src=\"L2UI.Squaregray\" width=\"610\" height=\"1\">");
+				if (i++ >= 12 * (index - 1))
+				{
+					StringUtil.append(html, "<table border=0 cellspacing=0 cellpadding=5 WIDTH=610>" + "<tr>" + "<td FIXWIDTH=5></td>"
+							+ "<td FIXWIDTH=415><a action=\"bypass _bbsposts;read;", String.valueOf(forum.getID()), ";", String.valueOf(t.getID()), "\">", t.getName(), "</a></td>"
+							+ "<td FIXWIDTH=120 align=center></td>" + "<td FIXWIDTH=70 align=center>", dateFormat.format(new Date(t.getDate())), "</td>"
+							+ "</tr>" + "</table>" + "<img src=\"L2UI.Squaregray\" width=\"610\" height=\"1\">");
 				}
 			}
 		}
 		
-		html.append(
-                        "<br>" +
-                        "<table width=610 cellspace=0 cellpadding=0>" +
-                        "<tr>" +
-                        "<td width=50>" +
-                        "<button value=\"&$422;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\">" +
-                        "</td>" +
-                        "<td width=510 align=center>" +
-                        "<table border=0><tr>");
+		html.append("<br>"
+				+ "<table width=610 cellspace=0 cellpadding=0>"
+				+ "<tr>"
+				+ "<td width=50>"
+				+ "<button value=\"&$422;\" action=\"bypass _bbsmemo\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\">"
+				+ "</td>" + "<td width=510 align=center>" + "<table border=0><tr>");
 		
-		if (index == 1) {
+		if (index == 1)
+		{
 			html.append("<td><button action=\"\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
-		} else {
-                    StringUtil.append(html,
-                            "<td><button action=\"bypass _bbstopics;read;",
-                            String.valueOf(forum.getID()),
-                            ";",
-                            String.valueOf(index - 1),
-                            "\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
 		}
-                
+		else
+		{
+			StringUtil.append(html, "<td><button action=\"bypass _bbstopics;read;", String.valueOf(forum.getID()), ";", String.valueOf(index - 1), "\" back=\"l2ui_ch3.prev1_down\" fore=\"l2ui_ch3.prev1\" width=16 height=16 ></td>");
+		}
+		
 		int nbp;
 		nbp = forum.getTopicSize() / 8;
 		if (nbp * 8 != ClanTable.getInstance().getClans().length)
 		{
 			nbp++;
 		}
-		for (int i = 1; i <= nbp; i++) {
-			if (i == index) {
-                            StringUtil.append(html,
-                                    "<td> ",
-                                    String.valueOf(i),
-                                    " </td>");
-			} else {
-                            StringUtil.append(html,
-                                    "<td><a action=\"bypass _bbstopics;read;",
-                                    String.valueOf(forum.getID()),
-                                    ";",
-                                    String.valueOf(i),
-                                    "\"> ",
-                                    String.valueOf(i),
-                                    " </a></td>");
+		for (int i = 1; i <= nbp; i++)
+		{
+			if (i == index)
+			{
+				StringUtil.append(html, "<td> ", String.valueOf(i), " </td>");
+			}
+			else
+			{
+				StringUtil.append(html, "<td><a action=\"bypass _bbstopics;read;", String.valueOf(forum.getID()), ";", String.valueOf(i), "\"> ", String.valueOf(i), " </a></td>");
 			}
 		}
-		if (index == nbp) {
+		if (index == nbp)
+		{
 			html.append("<td><button action=\"\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
-		} else {
-                    StringUtil.append(html,
-                            "<td><button action=\"bypass _bbstopics;read;",
-                            String.valueOf(forum.getID()),
-                            ";",
-                            String.valueOf(index + 1),
-                            "\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
 		}
-
-                StringUtil.append(html,
-                        "</tr></table> </td> " +
-                        "<td align=right><button value = \"&$421;\" action=\"bypass _bbstopics;crea;",
-                        String.valueOf(forum.getID()),
-                        "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td></tr>" +
-                        "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>" +
-                        "<tr> " +
-                        "<td></td>" +
-                        "<td align=center><table border=0><tr><td></td><td><edit var = \"Search\" width=130 height=11></td>" +
-                        "<td><button value=\"&$420;\" action=\"Write 5 -2 0 Search _ _\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td> </tr></table> </td>" +
-                        "</tr>" +
-                        "</table>" +
-                        "<br>" +
-                        "<br>" +
-                        "<br>" +
-                        "</center>" +
-                        "</body>" +
-                        "</html>");
+		else
+		{
+			StringUtil.append(html, "<td><button action=\"bypass _bbstopics;read;", String.valueOf(forum.getID()), ";", String.valueOf(index + 1), "\" back=\"l2ui_ch3.next1_down\" fore=\"l2ui_ch3.next1\" width=16 height=16 ></td>");
+		}
+		
+		StringUtil.append(html, "</tr></table> </td> " + "<td align=right><button value = \"&$421;\" action=\"bypass _bbstopics;crea;", String.valueOf(forum.getID()), "\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\" ></td></tr>"
+				+ "<tr><td><img src=\"l2ui.mini_logo\" width=5 height=10></td></tr>"
+				+ "<tr> "
+				+ "<td></td>"
+				+ "<td align=center><table border=0><tr><td></td><td><edit var = \"Search\" width=130 height=11></td>"
+				+ "<td><button value=\"&$420;\" action=\"Write 5 -2 0 Search _ _\" back=\"l2ui_ch3.smallbutton2_down\" width=65 height=20 fore=\"l2ui_ch3.smallbutton2\"> </td> </tr></table> </td>"
+				+ "</tr>" + "</table>" + "<br>" + "<br>" + "<br>" + "</center>" + "</body>" + "</html>");
 		separateAndSend(html.toString(), activeChar);
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final TopicBBSManager _instance = new TopicBBSManager();
+	}
 }

+ 13 - 9
L2_GameServer/java/net/sf/l2j/gameserver/datatables/AccessLevels.java

@@ -33,8 +33,6 @@ public class AccessLevels
 {
 	/** The logger<br> */
 	private static Logger _log = Logger.getLogger(AccessLevels.class.getName());
-	/** The one and only instance of this class, retrievable by getInstance()<br> */
-	private static AccessLevels _instance = null;
 	/** Reserved master access level<br> */
 	public static final int _masterAccessLevelNum = Config.MASTERACCESS_LEVEL;
 	/** The master access level which can use everything<br> */
@@ -53,10 +51,7 @@ public class AccessLevels
 	 */
 	public static AccessLevels getInstance()
 	{
-		if (_instance == null)
-			_instance = new AccessLevels();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private AccessLevels()
@@ -100,17 +95,20 @@ public class AccessLevels
 				
 				if (accessLevel == _userAccessLevelNum)
 				{
-					_log.warning("AccessLevels: Access level with name " + name + " is using reserved user access level " + _userAccessLevelNum + ". Ignoring it!");
+					_log.warning("AccessLevels: Access level with name " + name + " is using reserved user access level "
+							+ _userAccessLevelNum + ". Ignoring it!");
 					continue;
 				}
 				else if (accessLevel == _masterAccessLevelNum)
 				{
-					_log.warning("AccessLevels: Access level with name " + name + " is using reserved master access level " + _masterAccessLevelNum + ". Ignoring it!");
+					_log.warning("AccessLevels: Access level with name " + name + " is using reserved master access level "
+							+ _masterAccessLevelNum + ". Ignoring it!");
 					continue;
 				}
 				else if (accessLevel < 0)
 				{
-					_log.warning("AccessLevels: Access level with name " + name + " is using banned access level state(below 0). Ignoring it!");
+					_log.warning("AccessLevels: Access level with name " + name
+							+ " is using banned access level state(below 0). Ignoring it!");
 					continue;
 				}
 				
@@ -216,4 +214,10 @@ public class AccessLevels
 	{
 		loadAccessLevels();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AccessLevels _instance = new AccessLevels();
+	}
 }

+ 7 - 6
L2_GameServer/java/net/sf/l2j/gameserver/datatables/AdminCommandAccessRights.java

@@ -34,8 +34,6 @@ public class AdminCommandAccessRights
 	/** The logger<br> */
 	private static Logger _log = Logger.getLogger(AdminCommandAccessRights.class.getName());
 	
-	/** The one and only instance of this class, retrievable by getInstance()<br> */
-	private static AdminCommandAccessRights _instance = null;
 	private Map<String, L2AdminCommandAccessRight> _adminCommandAccessRights;
 	
 	/**
@@ -45,10 +43,7 @@ public class AdminCommandAccessRights
 	 */
 	public static AdminCommandAccessRights getInstance()
 	{
-		if (_instance == null)
-			_instance = new AdminCommandAccessRights();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/** The access rights<br> */
@@ -125,4 +120,10 @@ public class AdminCommandAccessRights
 	{
 		loadAdminCommandAccessRights();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AdminCommandAccessRights _instance = new AdminCommandAccessRights();
+	}
 }

+ 15 - 12
L2_GameServer/java/net/sf/l2j/gameserver/datatables/ArmorSetsTable.java

@@ -37,15 +37,12 @@ import net.sf.l2j.gameserver.model.L2ArmorSet;
 public class ArmorSetsTable
 {
 	private static Logger _log = Logger.getLogger(ArmorSetsTable.class.getName());
-	private static ArmorSetsTable _instance;
 	
 	private FastMap<Integer, L2ArmorSet> _armorSets;
 	
 	public static ArmorSetsTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new ArmorSetsTable();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private ArmorSetsTable()
@@ -75,10 +72,10 @@ public class ArmorSetsTable
 				int shield = rset.getInt("shield");
 				int shield_skill_id = rset.getInt("shield_skill_id");
 				int enchant6skill = rset.getInt("enchant6skill");
-				int mw_legs = rset.getInt("mw_legs"); 
-				int mw_head = rset.getInt("mw_head"); 
-				int mw_gloves = rset.getInt("mw_gloves"); 
-				int mw_feet = rset.getInt("mw_feet"); 
+				int mw_legs = rset.getInt("mw_legs");
+				int mw_head = rset.getInt("mw_head");
+				int mw_gloves = rset.getInt("mw_gloves");
+				int mw_feet = rset.getInt("mw_feet");
 				int mw_shield = rset.getInt("mw_shield");
 				_armorSets.put(chest, new L2ArmorSet(chest, legs, head, gloves, feet, skill_id, skill_lvl, shield, shield_skill_id, enchant6skill, mw_legs, mw_head, mw_gloves, mw_feet, mw_shield));
 			}
@@ -122,10 +119,10 @@ public class ArmorSetsTable
 					int shield = rset.getInt("shield");
 					int shield_skill_id = rset.getInt("shield_skill_id");
 					int enchant6skill = rset.getInt("enchant6skill");
-					int mw_legs = rset.getInt("mw_legs"); 
-					int mw_head = rset.getInt("mw_head"); 
-					int mw_gloves = rset.getInt("mw_gloves"); 
-					int mw_feet = rset.getInt("mw_feet"); 
+					int mw_legs = rset.getInt("mw_legs");
+					int mw_head = rset.getInt("mw_head");
+					int mw_gloves = rset.getInt("mw_gloves");
+					int mw_feet = rset.getInt("mw_feet");
 					int mw_shield = rset.getInt("mw_shield");
 					_armorSets.put(chest, new L2ArmorSet(chest, legs, head, gloves, feet, skill_id, skill_lvl, shield, shield_skill_id, enchant6skill, mw_legs, mw_head, mw_gloves, mw_feet, mw_shield));
 				}
@@ -159,4 +156,10 @@ public class ArmorSetsTable
 	{
 		return _armorSets.get(chestId);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ArmorSetsTable _instance = new ArmorSetsTable();
+	}
 }

+ 39 - 33
L2_GameServer/java/net/sf/l2j/gameserver/datatables/AugmentationData.java

@@ -44,16 +44,9 @@ public class AugmentationData
 {
 	private static final Logger _log = Logger.getLogger(AugmentationData.class.getName());
 	
-	// =========================================================
-	private static AugmentationData _instance;
-	
 	public static final AugmentationData getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new AugmentationData();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	// =========================================================
@@ -66,7 +59,7 @@ public class AugmentationData
 	//private static final int STAT_NUMBEROF_BLOCKS = 4;
 	private static final int STAT_SUBBLOCKSIZE = 91;
 	//private static final int STAT_NUMBEROF_SUBBLOCKS = 40;
-
+	
 	// skills
 	private static final int BLUE_START = 14561;
 	// private static final int PURPLE_START = 14578;
@@ -80,13 +73,13 @@ public class AugmentationData
 	private static final int BASESTAT_MEN = 16344;
 	
 	private FastList<?> _augmentationStats[];
-	private Map<Integer,FastList<augmentationSkill>> _blueSkills;
-	private Map<Integer,FastList<augmentationSkill>> _purpleSkills;
-	private Map<Integer,FastList<augmentationSkill>> _redSkills;
+	private Map<Integer, FastList<augmentationSkill>> _blueSkills;
+	private Map<Integer, FastList<augmentationSkill>> _purpleSkills;
+	private Map<Integer, FastList<augmentationSkill>> _redSkills;
 	
 	// =========================================================
 	// Constructor
-	public AugmentationData()
+	private AugmentationData()
 	{
 		_log.info("Initializing AugmentationData.");
 		
@@ -99,7 +92,7 @@ public class AugmentationData
 		_blueSkills = new FastMap<Integer, FastList<augmentationSkill>>();
 		_purpleSkills = new FastMap<Integer, FastList<augmentationSkill>>();
 		_redSkills = new FastMap<Integer, FastList<augmentationSkill>>();
-		for(int i = 1; i <= 10; i++)
+		for (int i = 1; i <= 10; i++)
 		{
 			_blueSkills.put(i, new FastList<augmentationSkill>());
 			_purpleSkills.put(i, new FastList<augmentationSkill>());
@@ -110,9 +103,10 @@ public class AugmentationData
 		
 		// Use size*4: since theres 4 blocks of stat-data with equivalent size
 		_log.info("AugmentationData: Loaded: " + (_augmentationStats[0].size() * 4) + " augmentation stats.");
-		for(int i = 1; i <= 10; i++)
+		for (int i = 1; i <= 10; i++)
 		{
-			_log.info("AugmentationData: Loaded: " + _blueSkills.get(i).size() + " blue, " + _purpleSkills.get(i).size() + " purple and " + _redSkills.get(i).size() + " red skills for lifeStoneLevel " + i);
+			_log.info("AugmentationData: Loaded: " + _blueSkills.get(i).size() + " blue, " + _purpleSkills.get(i).size() + " purple and "
+					+ _redSkills.get(i).size() + " red skills for lifeStoneLevel " + i);
 		}
 	}
 	
@@ -251,14 +245,16 @@ public class AugmentationData
 							if (skillId == 0)
 							{
 								if (Config.DEBUG)
-									_log.log(Level.SEVERE, "Bad skillId in augmentation_skillmap.xml in the augmentationId:" + augmentationId);
+									_log.log(Level.SEVERE, "Bad skillId in augmentation_skillmap.xml in the augmentationId:"
+											+ augmentationId);
 								badAugmantData++;
 								continue;
 							}
 							else if (skillLvL == 0)
 							{
 								if (Config.DEBUG)
-									_log.log(Level.SEVERE, "Bad skillLevel in augmentation_skillmap.xml in the augmentationId:" + augmentationId);
+									_log.log(Level.SEVERE, "Bad skillLevel in augmentation_skillmap.xml in the augmentationId:"
+											+ augmentationId);
 								badAugmantData++;
 								continue;
 							}
@@ -361,7 +357,7 @@ public class AugmentationData
 	
 	// =========================================================
 	// Properties - Public
-
+	
 	/**
 	 * Generate a new random augmentation
 	 * @param item
@@ -375,10 +371,10 @@ public class AugmentationData
 		// this is because a value can contain up to 2 stat modifications
 		// (there are two short values packed in one integer value, meaning 4 stat modifications at max)
 		// for more info take a look at getAugStatsById(...)
-
+		
 		// Note: lifeStoneGrade: (0 means low grade, 3 top grade)
 		// First: determine whether we will add a skill/baseStatModifier or not
-		//        because this determine which color could be the result 
+		// because this determine which color could be the result 
 		int skill_Chance = 0;
 		int stat34 = 0;
 		boolean generateSkill = false;
@@ -391,35 +387,35 @@ public class AugmentationData
 		{
 			case 0:
 				skill_Chance = Config.AUGMENTATION_NG_SKILL_CHANCE;
-				if (Rnd.get(1,100) <= Config.AUGMENTATION_NG_GLOW_CHANCE)
+				if (Rnd.get(1, 100) <= Config.AUGMENTATION_NG_GLOW_CHANCE)
 					generateGlow = true;
 				break;
 			case 1:
 				skill_Chance = Config.AUGMENTATION_MID_SKILL_CHANCE;
-				if (Rnd.get(1,100) <= Config.AUGMENTATION_MID_GLOW_CHANCE)
+				if (Rnd.get(1, 100) <= Config.AUGMENTATION_MID_GLOW_CHANCE)
 					generateGlow = true;
 				break;
 			case 2:
 				skill_Chance = Config.AUGMENTATION_HIGH_SKILL_CHANCE;
-				if (Rnd.get(1,100) <= Config.AUGMENTATION_HIGH_GLOW_CHANCE)
+				if (Rnd.get(1, 100) <= Config.AUGMENTATION_HIGH_GLOW_CHANCE)
 					generateGlow = true;
 				break;
 			case 3:
 				skill_Chance = Config.AUGMENTATION_TOP_SKILL_CHANCE;
-				if (Rnd.get(1,100) <= Config.AUGMENTATION_TOP_GLOW_CHANCE)
+				if (Rnd.get(1, 100) <= Config.AUGMENTATION_TOP_GLOW_CHANCE)
 					generateGlow = true;
 		}
-
+		
 		if (Rnd.get(1, 100) <= skill_Chance)
 			generateSkill = true;
 		else if (Rnd.get(1, 100) <= Config.AUGMENTATION_BASESTAT_CHANCE)
 			stat34 = Rnd.get(BASESTAT_STR, BASESTAT_MEN);
-
+		
 		// Second: decide which grade the augmentation result is going to have:
 		// 0:yellow, 1:blue, 2:purple, 3:red
 		// The chances used here are most likely custom,
 		// whats known is: you cant have yellow with skill(or baseStatModifier)
-		//                 noGrade stone can not have glow, mid only with skill, high has a chance(custom), top allways glow
+		// noGrade stone can not have glow, mid only with skill, high has a chance(custom), top allways glow
 		if (stat34 == 0 && !generateSkill)
 		{
 			resultColor = Rnd.get(0, 100);
@@ -463,15 +459,17 @@ public class AugmentationData
 		int stat12 = 0;
 		if (stat34 == 0 && !generateSkill)
 		{
-			int temp = Rnd.get(2,3);
+			int temp = Rnd.get(2, 3);
 			int colorOffset = resultColor * (10 * STAT_SUBBLOCKSIZE) + temp * STAT_BLOCKSIZE + 1;
 			int offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + colorOffset;
 			
 			stat34 = Rnd.get(offset, offset + STAT_SUBBLOCKSIZE - 1);
 			if (generateGlow && lifeStoneGrade >= 2)
-				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + (temp - 2) * STAT_BLOCKSIZE + lifeStoneGrade * (10 * STAT_SUBBLOCKSIZE) + 1;
+				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + (temp - 2) * STAT_BLOCKSIZE + lifeStoneGrade
+						* (10 * STAT_SUBBLOCKSIZE) + 1;
 			else
-				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + (temp - 2) * STAT_BLOCKSIZE + Rnd.get(0, 1) * (10 * STAT_SUBBLOCKSIZE) + 1;
+				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + (temp - 2) * STAT_BLOCKSIZE + Rnd.get(0, 1)
+						* (10 * STAT_SUBBLOCKSIZE) + 1;
 			stat12 = Rnd.get(offset, offset + STAT_SUBBLOCKSIZE - 1);
 		}
 		else
@@ -480,7 +478,8 @@ public class AugmentationData
 			if (!generateGlow)
 				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + Rnd.get(0, 1) * STAT_BLOCKSIZE + 1;
 			else
-				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + Rnd.get(0, 1) * STAT_BLOCKSIZE + (lifeStoneGrade + resultColor) / 2 * (10 * STAT_SUBBLOCKSIZE) + 1;
+				offset = ((lifeStoneLevel - 1) * STAT_SUBBLOCKSIZE) + Rnd.get(0, 1) * STAT_BLOCKSIZE + (lifeStoneGrade + resultColor) / 2
+						* (10 * STAT_SUBBLOCKSIZE) + 1;
 			stat12 = Rnd.get(offset, offset + STAT_SUBBLOCKSIZE - 1);
 		}
 		
@@ -510,7 +509,8 @@ public class AugmentationData
 		}
 		
 		if (Config.DEBUG)
-			_log.info("Augmentation success: stat12=" + stat12 + "; stat34=" + stat34 + "; resultColor=" + resultColor + "; level=" + lifeStoneLevel + "; grade=" + lifeStoneGrade);
+			_log.info("Augmentation success: stat12=" + stat12 + "; stat34=" + stat34 + "; resultColor=" + resultColor + "; level="
+					+ lifeStoneLevel + "; grade=" + lifeStoneGrade);
 		return new L2Augmentation(((stat34 << 16) + stat12), skill);
 	}
 	
@@ -632,4 +632,10 @@ public class AugmentationData
 		
 		return temp;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AugmentationData _instance = new AugmentationData();
+	}
 }

+ 10 - 6
L2_GameServer/java/net/sf/l2j/gameserver/datatables/CharNameTable.java

@@ -31,15 +31,13 @@ public class CharNameTable
 {
 	private static Logger _log = Logger.getLogger(CharNameTable.class.getName());
 	
-	private static CharNameTable _instance;
+	private CharNameTable()
+	{
+	}
 	
 	public static CharNameTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new CharNameTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public synchronized boolean doesCharNameExist(String name)
@@ -109,4 +107,10 @@ public class CharNameTable
 		
 		return number;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CharNameTable _instance = new CharNameTable();
+	}
 }

+ 10 - 8
L2_GameServer/java/net/sf/l2j/gameserver/datatables/CharTemplateTable.java

@@ -37,17 +37,11 @@ public class CharTemplateTable
 {
 	private static final Logger LOG = Logger.getLogger(CharTemplateTable.class.getName());
 	
-	private static CharTemplateTable _instance;
-	
 	private final Map<Integer, L2PcTemplate> _templates = new FastMap<Integer, L2PcTemplate>();
 	
 	public static CharTemplateTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new CharTemplateTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private CharTemplateTable()
@@ -57,7 +51,9 @@ public class CharTemplateTable
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-			PreparedStatement statement = con.prepareStatement("SELECT * FROM class_list, char_templates, lvlupgain" + " WHERE class_list.id = char_templates.classId" + " AND class_list.id = lvlupgain.classId" + " ORDER BY class_list.id");
+			PreparedStatement statement = con.prepareStatement("SELECT * FROM class_list, char_templates, lvlupgain"
+					+ " WHERE class_list.id = char_templates.classId" + " AND class_list.id = lvlupgain.classId"
+					+ " ORDER BY class_list.id");
 			ResultSet rset = statement.executeQuery();
 			
 			while (rset.next())
@@ -210,4 +206,10 @@ public class CharTemplateTable
 		}
 		return pcTemplate.className;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CharTemplateTable _instance = new CharTemplateTable();
+	}
 }

+ 11 - 11
L2_GameServer/java/net/sf/l2j/gameserver/datatables/ClanTable.java

@@ -53,17 +53,11 @@ public class ClanTable
 {
 	private static Logger _log = Logger.getLogger(ClanTable.class.getName());
 	
-	private static ClanTable _instance;
-	
 	private Map<Integer, L2Clan> _clans;
 	
 	public static ClanTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ClanTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public L2Clan[] getClans()
@@ -283,12 +277,12 @@ public class ClanTable
 			statement.setInt(2, clanId);
 			statement.execute();
 			statement.close();
-
+			
 			statement = con.prepareStatement("DELETE FROM clan_notices WHERE clan_id=?");
 			statement.setInt(1, clanId);
 			statement.execute();
 			statement.close();
-
+			
 			if (castleId != 0)
 			{
 				statement = con.prepareStatement("UPDATE castle SET taxPercent = 0 WHERE id = ?");
@@ -413,12 +407,12 @@ public class ClanTable
 		clan2.broadcastClanStatus();
 		//for(L2ClanMember player: clan1.getMembers())
 		//{
-		//    if(player.getPlayerInstance()!=null)
+		//	if(player.getPlayerInstance()!=null)
 		//			player.getPlayerInstance().setWantsPeace(0);
 		//}
 		//for(L2ClanMember player: clan2.getMembers())
 		//{
-		//    if(player.getPlayerInstance()!=null)
+		//	if(player.getPlayerInstance()!=null)
 		//			player.getPlayerInstance().setWantsPeace(0);
 		//}
 		Connection con = null;
@@ -510,4 +504,10 @@ public class ClanTable
 			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ClanTable _instance = new ClanTable();
+	}
 }

+ 111 - 102
L2_GameServer/java/net/sf/l2j/gameserver/datatables/DoorTable.java

@@ -40,22 +40,16 @@ public class DoorTable
 {
 	private static Logger _log = Logger.getLogger(DoorTable.class.getName());
 	
-	private Map<Integer, L2DoorInstance> _staticItems;
+	private Map<Integer, L2DoorInstance> _staticItems = new FastMap<Integer, L2DoorInstance>();
 	private boolean _initialized;
 	
-	private static DoorTable _instance;
-	
 	public static DoorTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new DoorTable();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private DoorTable()
 	{
-		_staticItems = new FastMap<Integer, L2DoorInstance>();
 		_initialized = true;
 		parseData();
 	}
@@ -67,7 +61,8 @@ public class DoorTable
 	
 	public void respawn()
 	{
-		_instance = new DoorTable();
+		_staticItems.clear();
+		parseData();
 	}
 	
 	public void parseData()
@@ -86,7 +81,7 @@ public class DoorTable
 				if (line.trim().length() == 0 || line.startsWith("#"))
 					continue;
 				
-				L2DoorInstance door = parseList(line);
+				L2DoorInstance door = parseList(line, false);
 				_staticItems.put(door.getDoorId(), door);
 				door.spawnMe(door.getX(), door.getY(), door.getZ());
 				ClanHall clanhall = ClanHallManager.getInstance().getNearbyClanHall(door.getX(), door.getY(), 500);
@@ -123,7 +118,15 @@ public class DoorTable
 		}
 	}
 	
-	public static L2DoorInstance parseList(String line)
+	/**
+	 * Parses door list.
+	 *
+	 * @param line string
+	 * @param commanderDoor whether the door is commander door (fortress)
+	 *
+	 * @return created door instance
+	*/
+	public static L2DoorInstance parseList(final String line, final boolean commanderDoor)
 	{
 		StringTokenizer st = new StringTokenizer(line, ";");
 		L2DoorInstance door = null;
@@ -149,77 +152,77 @@ public class DoorTable
 			boolean startOpen = false;
 			if (st.hasMoreTokens())
 				startOpen = Boolean.parseBoolean(st.nextToken());
-		if (rangeXMin > rangeXMax)
-			_log.severe("Error in door data, ID:" + id);
-		if (rangeYMin > rangeYMax)
-			_log.severe("Error in door data, ID:" + id);
-		if (rangeZMin > rangeZMax)
-			_log.severe("Error in door data, ID:" + id);
-		int collisionRadius; // (max) radius for movement checks
-		if ((rangeXMax - rangeXMin) > (rangeYMax - rangeYMin))
-			collisionRadius = rangeYMax - rangeYMin;
-		else
-			collisionRadius = rangeXMax - rangeXMin;
-		
-		StatsSet npcDat = new StatsSet();
-		npcDat.set("npcId", id);
-		npcDat.set("level", 0);
-		npcDat.set("jClass", "door");
-		
-		npcDat.set("baseSTR", 0);
-		npcDat.set("baseCON", 0);
-		npcDat.set("baseDEX", 0);
-		npcDat.set("baseINT", 0);
-		npcDat.set("baseWIT", 0);
-		npcDat.set("baseMEN", 0);
-		
-		npcDat.set("baseShldDef", 0);
-		npcDat.set("baseShldRate", 0);
-		npcDat.set("baseAccCombat", 38);
-		npcDat.set("baseEvasRate", 38);
-		npcDat.set("baseCritRate", 38);
-		
-		//npcDat.set("name", "");
-		npcDat.set("collision_radius", collisionRadius);
-		npcDat.set("collision_height", rangeZMax - rangeZMin);
-		npcDat.set("sex", "male");
-		npcDat.set("type", "");
-		npcDat.set("baseAtkRange", 0);
-		npcDat.set("baseMpMax", 0);
-		npcDat.set("baseCpMax", 0);
-		npcDat.set("rewardExp", 0);
-		npcDat.set("rewardSp", 0);
-		npcDat.set("basePAtk", 0);
-		npcDat.set("baseMAtk", 0);
-		npcDat.set("basePAtkSpd", 0);
-		npcDat.set("aggroRange", 0);
-		npcDat.set("baseMAtkSpd", 0);
-		npcDat.set("rhand", 0);
-		npcDat.set("lhand", 0);
-		npcDat.set("armor", 0);
-		npcDat.set("baseWalkSpd", 0);
-		npcDat.set("baseRunSpd", 0);
-		npcDat.set("name", name);
-		npcDat.set("baseHpMax", hp);
-		npcDat.set("baseHpReg", 3.e-3f);
-		npcDat.set("baseMpReg", 3.e-3f);
-		npcDat.set("basePDef", pdef);
-		npcDat.set("baseMDef", mdef);
-		
-		L2CharTemplate template = new L2CharTemplate(npcDat);
-		door = new L2DoorInstance(IdFactory.getInstance().getNextId(), template, id, name, unlockable);
-		door.setRange(rangeXMin, rangeYMin, rangeZMin, rangeXMax, rangeYMax, rangeZMax);
-		door.setCurrentHpMp(door.getMaxHp(), door.getMaxMp());
-		door.setXYZInvisible(x, y, z);
-		
-		if (door.getFort() != null)
-			door.setIsCommanderDoor(startOpen);
-		else
-			door.setOpen(startOpen);
+			if (rangeXMin > rangeXMax)
+				_log.severe("Error in door data, ID:" + id);
+			if (rangeYMin > rangeYMax)
+				_log.severe("Error in door data, ID:" + id);
+			if (rangeZMin > rangeZMax)
+				_log.severe("Error in door data, ID:" + id);
+			int collisionRadius; // (max) radius for movement checks
+			if ((rangeXMax - rangeXMin) > (rangeYMax - rangeYMin))
+				collisionRadius = rangeYMax - rangeYMin;
+			else
+				collisionRadius = rangeXMax - rangeXMin;
+			
+			StatsSet npcDat = new StatsSet();
+			npcDat.set("npcId", id);
+			npcDat.set("level", 0);
+			npcDat.set("jClass", "door");
+			
+			npcDat.set("baseSTR", 0);
+			npcDat.set("baseCON", 0);
+			npcDat.set("baseDEX", 0);
+			npcDat.set("baseINT", 0);
+			npcDat.set("baseWIT", 0);
+			npcDat.set("baseMEN", 0);
+			
+			npcDat.set("baseShldDef", 0);
+			npcDat.set("baseShldRate", 0);
+			npcDat.set("baseAccCombat", 38);
+			npcDat.set("baseEvasRate", 38);
+			npcDat.set("baseCritRate", 38);
+			
+			//npcDat.set("name", "");
+			npcDat.set("collision_radius", collisionRadius);
+			npcDat.set("collision_height", rangeZMax - rangeZMin);
+			npcDat.set("sex", "male");
+			npcDat.set("type", "");
+			npcDat.set("baseAtkRange", 0);
+			npcDat.set("baseMpMax", 0);
+			npcDat.set("baseCpMax", 0);
+			npcDat.set("rewardExp", 0);
+			npcDat.set("rewardSp", 0);
+			npcDat.set("basePAtk", 0);
+			npcDat.set("baseMAtk", 0);
+			npcDat.set("basePAtkSpd", 0);
+			npcDat.set("aggroRange", 0);
+			npcDat.set("baseMAtkSpd", 0);
+			npcDat.set("rhand", 0);
+			npcDat.set("lhand", 0);
+			npcDat.set("armor", 0);
+			npcDat.set("baseWalkSpd", 0);
+			npcDat.set("baseRunSpd", 0);
+			npcDat.set("name", name);
+			npcDat.set("baseHpMax", hp);
+			npcDat.set("baseHpReg", 3.e-3f);
+			npcDat.set("baseMpReg", 3.e-3f);
+			npcDat.set("basePDef", pdef);
+			npcDat.set("baseMDef", mdef);
+			
+			L2CharTemplate template = new L2CharTemplate(npcDat);
+			door = new L2DoorInstance(IdFactory.getInstance().getNextId(), template, id, name, unlockable);
+			door.setRange(rangeXMin, rangeYMin, rangeZMin, rangeXMax, rangeYMax, rangeZMax);
+			door.setCurrentHpMp(door.getMaxHp(), door.getMaxMp());
+			door.setXYZInvisible(x, y, z);
+			
+			if (commanderDoor)
+				door.setIsCommanderDoor(startOpen);
+			else
+				door.setOpen(startOpen);
 		}
 		catch (Exception e)
 		{
-			_log.severe("Error in door data at line: " +line);
+			_log.severe("Error in door data at line: " + line);
 		}
 		return door;
 	}
@@ -264,22 +267,22 @@ public class DoorTable
 		// devils (every 5 minutes)
 		else if (doorInst.getDoorName().startsWith("pirate_isle"))
 		   doorInst.setAutoActionDelay(300000);
-		    
+			
 		// Cruma Tower (every 20 minutes) 
 		else if (doorInst.getDoorName().startsWith("cruma")) 
-		    doorInst.setAutoActionDelay(1200000);
-		    
+			doorInst.setAutoActionDelay(1200000);
+			
 		// Coral Garden Gate (every 15 minutes) 
 		else if (doorInst.getDoorName().startsWith("Coral_garden")) 
-		    doorInst.setAutoActionDelay(900000);
-		    
+			doorInst.setAutoActionDelay(900000);
+			
 		// Normil's cave (every 5 minutes) 
 		else if (doorInst.getDoorName().startsWith("Normils_cave")) 
-		    doorInst.setAutoActionDelay(300000);
-		    
+			doorInst.setAutoActionDelay(300000);
+			
 		// Normil's Garden (every 15 minutes) 
 		else if (doorInst.getDoorName().startsWith("Normils_garden")) 
-		    doorInst.setAutoActionDelay(900000);
+			doorInst.setAutoActionDelay(900000);
 		*/
 	}
 	
@@ -309,7 +312,7 @@ public class DoorTable
 		// there are quite many doors, maybe they should be splitted
 		for (L2DoorInstance doorInst : allDoors)
 		{
-			if (doorInst.getMapRegion() != region) 
+			if (doorInst.getMapRegion() != region)
 				continue;
 			if (doorInst.getXMax() == 0)
 				continue;
@@ -325,7 +328,7 @@ public class DoorTable
 					// phase 3, basically only z remains but now we calculate it with another formula (by rage)
 					// in some cases the direct line check (only) in the beginning isn't sufficient, 
 					// when char z changes a lot along the path
-					if (doorInst.getCurrentHp() > 0 && !doorInst.getOpen()) 
+					if (doorInst.getCurrentHp() > 0 && !doorInst.getOpen())
 					{
 						int px1 = doorInst.getXMin();
 						int py1 = doorInst.getYMin();
@@ -340,22 +343,22 @@ public class DoorTable
 						
 						int dk;
 						
-						if ((dk = (doorInst.getA() * l + doorInst.getB() * m + doorInst.getC() * n)) == 0) continue; // Parallel
-						
-						float p = (float)(doorInst.getA() * x + doorInst.getB() * y + doorInst.getC() * z + doorInst.getD()) / (float)dk;
+						if ((dk = (doorInst.getA() * l + doorInst.getB() * m + doorInst.getC() * n)) == 0)
+							continue; // Parallel
+							
+						float p = (float) (doorInst.getA() * x + doorInst.getB() * y + doorInst.getC() * z + doorInst.getD()) / (float) dk;
 						
-						int fx = (int)(x - l * p);
-						int fy = (int)(y - m * p);
-						int fz = (int)(z - n * p);
+						int fx = (int) (x - l * p);
+						int fy = (int) (y - m * p);
+						int fz = (int) (z - n * p);
 						
-						if((Math.min(x,tx) <= fx && fx <= Math.max(x,tx)) &&
-								(Math.min(y,ty) <= fy && fy <= Math.max(y,ty)) &&
-								(Math.min(z,tz) <= fz && fz <= Math.max(z,tz)))
+						if ((Math.min(x, tx) <= fx && fx <= Math.max(x, tx)) && (Math.min(y, ty) <= fy && fy <= Math.max(y, ty))
+								&& (Math.min(z, tz) <= fz && fz <= Math.max(z, tz)))
 						{
-
-							if (((fx >= px1 && fx <= px2) || (fx >= px2 && fx <= px1)) &&
-									((fy >= py1 && fy <= py2) || (fy >= py2 && fy <= py1)) &&
-									((fz >= pz1 && fz <= pz2) || (fz >= pz2 && fz <= pz1)))
+							
+							if (((fx >= px1 && fx <= px2) || (fx >= px2 && fx <= px1))
+									&& ((fy >= py1 && fy <= py2) || (fy >= py2 && fy <= py1))
+									&& ((fz >= pz1 && fz <= pz2) || (fz >= pz2 && fz <= pz1)))
 								return true; // Door between
 						}
 					}
@@ -364,4 +367,10 @@ public class DoorTable
 		}
 		return false;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final DoorTable _instance = new DoorTable();
+	}
 }

+ 6 - 7
L2_GameServer/java/net/sf/l2j/gameserver/datatables/EventDroplist.java

@@ -32,18 +32,12 @@ public class EventDroplist
 	
 	//private static Logger _log = Logger.getLogger(EventDroplist.class.getName());
 	
-	private static EventDroplist _instance;
-	
 	/** The table containing all DataDrop object */
 	private List<DateDrop> _allNpcDateDrops;
 	
 	public static EventDroplist getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new EventDroplist();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public class DateDrop
@@ -116,4 +110,9 @@ public class EventDroplist
 		return list;
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final EventDroplist _instance = new EventDroplist();
+	}
 }

+ 24 - 22
L2_GameServer/java/net/sf/l2j/gameserver/datatables/ExtractableItemsData.java

@@ -39,17 +39,12 @@ public class ExtractableItemsData
 	//          Map<FastMap<itemid, skill>, L2ExtractableItem>
 	private Map<Integer, L2ExtractableItem> _items = new FastMap<Integer, L2ExtractableItem>();
 	
-	private static ExtractableItemsData _instance = null;
-	
 	public static ExtractableItemsData getInstance()
 	{
-		if (_instance == null)
-			_instance = new ExtractableItemsData();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public ExtractableItemsData()
+	private ExtractableItemsData()
 	{
 		_items.clear();
 		
@@ -99,22 +94,22 @@ public class ExtractableItemsData
 			L2Skill skill = SkillTable.getInstance().getInfo(skillID, skillLvl);
 			if (skill == null)
 			{
-					_log.warning("Extractable items data: Error in line " + lineCount + " -> skill is null!");
-					_log.warning("		" + line);
-					ok = false;
+				_log.warning("Extractable items data: Error in line " + lineCount + " -> skill is null!");
+				_log.warning("		" + line);
+				ok = false;
 			}
 			if (!ok)
 				continue;
 			
 			FastList<L2ExtractableProductItem> product_temp = new FastList<L2ExtractableProductItem>();
 			
-			for (int i = 2; i < lineSplit.length -1 ; i++)
+			for (int i = 2; i < lineSplit.length - 1; i++)
 			{
 				ok = true;
 				
 				String[] lineSplit2 = lineSplit[i + 1].split(",");
 				
-				if (lineSplit2.length < 3 )//|| lineSplit2.length-1 %2 != 0)
+				if (lineSplit2.length < 3)//|| lineSplit2.length-1 %2 != 0)
 				{
 					_log.warning("Extractable items data: Error in line " + lineCount + " -> wrong seperator!");
 					_log.warning("		" + line);
@@ -124,27 +119,28 @@ public class ExtractableItemsData
 				if (!ok)
 					continue;
 				
-				int[] production =null;
+				int[] production = null;
 				int[] amount = null;
 				int chance = 0;
 				
 				try
 				{
-					int k =0;
-					production = new int[lineSplit2.length-1/2];
-					amount = new int[lineSplit2.length-1/2];
-					for (int j = 0; j < lineSplit2.length-1 ;j++)
+					int k = 0;
+					production = new int[lineSplit2.length - 1 / 2];
+					amount = new int[lineSplit2.length - 1 / 2];
+					for (int j = 0; j < lineSplit2.length - 1; j++)
 					{
 						production[k] = Integer.parseInt(lineSplit2[j]);
-						amount[k] = Integer.parseInt(lineSplit2[j+=1]);
+						amount[k] = Integer.parseInt(lineSplit2[j += 1]);
 						k++;
 					}
-
-					chance = Integer.parseInt(lineSplit2[lineSplit2.length-1]);
+					
+					chance = Integer.parseInt(lineSplit2[lineSplit2.length - 1]);
 				}
 				catch (Exception e)
 				{
-					_log.warning("Extractable items data: Error in line " + lineCount + " -> incomplete/invalid production data or wrong seperator!");
+					_log.warning("Extractable items data: Error in line " + lineCount
+							+ " -> incomplete/invalid production data or wrong seperator!");
 					_log.warning("		" + line);
 					ok = false;
 				}
@@ -167,7 +163,7 @@ public class ExtractableItemsData
 				_log.warning("		" + line);
 				continue;
 			}
-
+			
 			L2ExtractableItem product = new L2ExtractableItem(itemID, product_temp);
 			_items.put(itemID, product);
 		}
@@ -192,4 +188,10 @@ public class ExtractableItemsData
 		}
 		return result;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ExtractableItemsData _instance = new ExtractableItemsData();
+	}
 }

+ 6 - 2
L2_GameServer/java/net/sf/l2j/gameserver/datatables/FishTable.java

@@ -32,7 +32,6 @@ import net.sf.l2j.gameserver.model.FishData;
 public class FishTable
 {
 	private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
-	private static final FishTable _instance = new FishTable();
 	
 	private static List<FishData> _fishsNormal;
 	private static List<FishData> _fishsEasy;
@@ -40,7 +39,7 @@ public class FishTable
 	
 	public static FishTable getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private FishTable()
@@ -146,4 +145,9 @@ public class FishTable
 		return result;
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final FishTable _instance = new FishTable();
+	}
 }

+ 9 - 10
L2_GameServer/java/net/sf/l2j/gameserver/datatables/HelperBuffTable.java

@@ -37,8 +37,6 @@ public class HelperBuffTable
 	
 	private static Logger _log = Logger.getLogger(HennaTable.class.getName());
 	
-	private static HelperBuffTable _instance;
-	
 	/** The table containing all Buff of the Newbie Helper */
 	private List<L2HelperBuff> _helperBuff;
 	
@@ -53,18 +51,14 @@ public class HelperBuffTable
 	 *  Used to generate message : "Only novice character of level ... or less can receive my support magic.") */
 	private int _magicClassHighestLevel = 1;
 	private int _physicClassHighestLevel = 1;
-
+	
 	private int _servitorLowestLevel = 100;
-
+	
 	private int _servitorHighestLevel = 1;
 	
 	public static HelperBuffTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new HelperBuffTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -188,7 +182,6 @@ public class HelperBuffTable
 		return _magicClassHighestLevel;
 	}
 	
-	
 	/**
 	 * @return Returns the magicClassLowestLevel.
 	 */
@@ -228,4 +221,10 @@ public class HelperBuffTable
 	{
 		return _servitorHighestLevel;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final HelperBuffTable _instance = new HelperBuffTable();
+	}
 }

+ 6 - 8
L2_GameServer/java/net/sf/l2j/gameserver/datatables/HennaTable.java

@@ -34,25 +34,18 @@ public class HennaTable
 {
 	private static Logger _log = Logger.getLogger(HennaTable.class.getName());
 	
-	private static HennaTable _instance;
-	
 	private Map<Integer, L2Henna> _henna;
 	private boolean _initialized = true;
 	
 	public static HennaTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new HennaTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private HennaTable()
 	{
 		_henna = new FastMap<Integer, L2Henna>();
 		restoreHennaData();
-		
 	}
 	
 	/**
@@ -124,4 +117,9 @@ public class HennaTable
 		return _henna.get(id);
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final HennaTable _instance = new HennaTable();
+	}
 }

+ 7 - 3
L2_GameServer/java/net/sf/l2j/gameserver/datatables/HennaTreeTable.java

@@ -37,13 +37,12 @@ import net.sf.l2j.gameserver.templates.item.L2Henna;
 public class HennaTreeTable
 {
 	private static Logger _log = Logger.getLogger(HennaTreeTable.class.getName());
-	private static final HennaTreeTable _instance = new HennaTreeTable();
 	private Map<ClassId, List<L2HennaInstance>> _hennaTrees;
 	private boolean _initialized = true;
 	
 	public static HennaTreeTable getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private HennaTreeTable()
@@ -134,7 +133,7 @@ public class HennaTreeTable
 			return new L2HennaInstance[0];
 		}
 		
-		for (L2HennaInstance temp: henna)
+		for (L2HennaInstance temp : henna)
 		{
 			result.add(temp);
 		}
@@ -147,4 +146,9 @@ public class HennaTreeTable
 		return _initialized;
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final HennaTreeTable _instance = new HennaTreeTable();
+	}
 }

+ 8 - 8
L2_GameServer/java/net/sf/l2j/gameserver/datatables/HeroSkillTable.java

@@ -22,7 +22,6 @@ import net.sf.l2j.gameserver.model.L2Skill;
  */
 public class HeroSkillTable
 {
-	private static HeroSkillTable _instance;
 	private static L2Skill[] _heroSkills;
 	
 	private HeroSkillTable()
@@ -37,9 +36,7 @@ public class HeroSkillTable
 	
 	public static HeroSkillTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new HeroSkillTable();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public static L2Skill[] getHeroSkills()
@@ -49,10 +46,7 @@ public class HeroSkillTable
 	
 	public static boolean isHeroSkill(int skillid)
 	{
-		Integer[] _HeroSkillsId = new Integer[]
-		{
-			395, 396, 1374, 1375, 1376
-		};
+		Integer[] _HeroSkillsId = new Integer[] { 395, 396, 1374, 1375, 1376 };
 		
 		for (int id : _HeroSkillsId)
 		{
@@ -62,4 +56,10 @@ public class HeroSkillTable
 		
 		return false;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final HeroSkillTable _instance = new HeroSkillTable();
+	}
 }

+ 78 - 76
L2_GameServer/java/net/sf/l2j/gameserver/datatables/ItemTable.java

@@ -169,39 +169,34 @@ public class ItemTable
 		
 	}
 	
-	private static ItemTable _instance;
-	
 	/** Table of SQL request in order to obtain items from tables [etcitem], [armor], [weapon] */
-	private static final String[] SQL_ITEM_SELECTS =
-	{
-		"SELECT item_id, name, crystallizable, item_type, weight, consume_type, material," + " crystal_type, duration, time, price, crystal_count, sellable, dropable, destroyable, tradeable, handler, skill FROM etcitem",
-		
-		"SELECT item_id, name, bodypart, crystallizable, armor_type, weight," + " material, crystal_type, avoid_modify, duration, time, p_def, m_def, mp_bonus,"
-				+ " price, crystal_count, sellable, dropable, destroyable, tradeable, enchant4_skill, skill FROM armor",
-		
-		"SELECT item_id, name, bodypart, crystallizable, weight, soulshots, spiritshots," + " material, crystal_type, p_dam, rnd_dam, weaponType, critical, hit_modify, avoid_modify,"
-				+ " shield_def, shield_def_rate, atk_speed, mp_consume, m_dam, duration, time, price, crystal_count," + " sellable, dropable, destroyable, tradeable, skill,enchant4_skill_id,enchant4_skill_lvl, onCast_skill_id, onCast_skill_lvl,"
-				+ " onCast_skill_chance, onCrit_skill_id, onCrit_skill_lvl, onCrit_skill_chance, change_weaponId FROM weapon"
-	};
-	
-	private static final String[] SQL_CUSTOM_ITEM_SELECTS =
-	{
-		"SELECT item_id, name, crystallizable, item_type, weight, consume_type, material," + " crystal_type, duration, time, price, crystal_count, sellable, dropable, destroyable, tradeable, handler, skill FROM custom_etcitem",
-		
-		"SELECT item_id, name, bodypart, crystallizable, armor_type, weight," + " material, crystal_type, avoid_modify, duration, time, p_def, m_def, mp_bonus,"
-				+ " price, crystal_count, sellable, dropable, destroyable, tradeable, enchant4_skill, skill FROM custom_armor",
-		
-		"SELECT item_id, name, bodypart, crystallizable, weight, soulshots, spiritshots," + " material, crystal_type, p_dam, rnd_dam, weaponType, critical, hit_modify, avoid_modify,"
-				+ " shield_def, shield_def_rate, atk_speed, mp_consume, m_dam, duration, time, price, crystal_count," + " sellable, dropable, destroyable, tradeable, skill,enchant4_skill_id,enchant4_skill_lvl, onCast_skill_id, onCast_skill_lvl,"
-				+ " onCast_skill_chance, onCrit_skill_id, onCrit_skill_lvl, onCrit_skill_chance, change_weaponId FROM custom_weapon"
-	};
+	private static final String[] SQL_ITEM_SELECTS = {
+			"SELECT item_id, name, crystallizable, item_type, weight, consume_type, material,"
+					+ " crystal_type, duration, time, price, crystal_count, sellable, dropable, destroyable, tradeable, handler, skill FROM etcitem",
+			
+			"SELECT item_id, name, bodypart, crystallizable, armor_type, weight,"
+					+ " material, crystal_type, avoid_modify, duration, time, p_def, m_def, mp_bonus,"
+					+ " price, crystal_count, sellable, dropable, destroyable, tradeable, enchant4_skill, skill FROM armor",
+			
+			"SELECT item_id, name, bodypart, crystallizable, weight, soulshots, spiritshots,"
+					+ " material, crystal_type, p_dam, rnd_dam, weaponType, critical, hit_modify, avoid_modify,"
+					+ " shield_def, shield_def_rate, atk_speed, mp_consume, m_dam, duration, time, price, crystal_count,"
+					+ " sellable, dropable, destroyable, tradeable, skill,enchant4_skill_id,enchant4_skill_lvl, onCast_skill_id, onCast_skill_lvl,"
+					+ " onCast_skill_chance, onCrit_skill_id, onCrit_skill_lvl, onCrit_skill_chance, change_weaponId FROM weapon" };
 	
-	/** List of etcItem */
-	private static final Map<Integer, Item> itemData = new FastMap<Integer, Item>();
-	/** List of weapons */
-	private static final Map<Integer, Item> weaponData = new FastMap<Integer, Item>();
-	/** List of armor */
-	private static final Map<Integer, Item> armorData = new FastMap<Integer, Item>();
+	private static final String[] SQL_CUSTOM_ITEM_SELECTS = {
+			"SELECT item_id, name, crystallizable, item_type, weight, consume_type, material,"
+					+ " crystal_type, duration, time, price, crystal_count, sellable, dropable, destroyable, tradeable, handler, skill FROM custom_etcitem",
+			
+			"SELECT item_id, name, bodypart, crystallizable, armor_type, weight,"
+					+ " material, crystal_type, avoid_modify, duration, time, p_def, m_def, mp_bonus,"
+					+ " price, crystal_count, sellable, dropable, destroyable, tradeable, enchant4_skill, skill FROM custom_armor",
+			
+			"SELECT item_id, name, bodypart, crystallizable, weight, soulshots, spiritshots,"
+					+ " material, crystal_type, p_dam, rnd_dam, weaponType, critical, hit_modify, avoid_modify,"
+					+ " shield_def, shield_def_rate, atk_speed, mp_consume, m_dam, duration, time, price, crystal_count,"
+					+ " sellable, dropable, destroyable, tradeable, skill,enchant4_skill_id,enchant4_skill_lvl, onCast_skill_id, onCast_skill_lvl,"
+					+ " onCast_skill_chance, onCrit_skill_id, onCrit_skill_lvl, onCrit_skill_chance, change_weaponId FROM custom_weapon" };
 	
 	/**
 	 * Returns instance of ItemTable
@@ -209,11 +204,7 @@ public class ItemTable
 	 */
 	public static ItemTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ItemTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -228,11 +219,22 @@ public class ItemTable
 	/**
 	 * Constructor.
 	 */
-	public ItemTable()
+	private ItemTable()
 	{
 		_etcItems = new FastMap<Integer, L2EtcItem>();
 		_armors = new FastMap<Integer, L2Armor>();
 		_weapons = new FastMap<Integer, L2Weapon>();
+		load();
+	}
+	
+	private void load()
+	{
+		/** List of etcItem */
+		final Map<Integer, Item> itemData = new FastMap<Integer, Item>();
+		/** List of weapons */
+		final Map<Integer, Item> weaponData = new FastMap<Integer, Item>();
+		/** List of armor */
+		final Map<Integer, Item> armorData = new FastMap<Integer, Item>();
 		
 		Connection con = null;
 		try
@@ -343,18 +345,21 @@ public class ItemTable
 			}
 		}
 		
+		_armors.clear();
 		for (L2Armor armor : SkillsEngine.getInstance().loadArmors(armorData))
 		{
 			_armors.put(armor.getItemId(), armor);
 		}
 		_log.config("ItemTable: Loaded " + _armors.size() + " Armors.");
 		
+		_etcItems.clear();
 		for (L2EtcItem item : SkillsEngine.getInstance().loadItems(itemData))
 		{
 			_etcItems.put(item.getItemId(), item);
 		}
 		_log.config("ItemTable: Loaded " + _etcItems.size() + " Items.");
 		
+		_weapons.clear();
 		for (L2Weapon weapon : SkillsEngine.getInstance().loadWeapons(weaponData))
 		{
 			_weapons.put(weapon.getItemId(), weapon);
@@ -367,9 +372,7 @@ public class ItemTable
 	/**
 	 * Returns object Item from the record of the database
 	 * 
-	 * @param rset :
-	 *            ResultSet designating a record of the [weapon] table of
-	 *            database
+	 * @param rset : ResultSet designating a record of the [weapon] table of database
 	 * @return Item : object created from the database record
 	 * @throws SQLException
 	 */
@@ -483,7 +486,8 @@ public class ItemTable
 		item.set.set("enchant4_skill", rset.getString("enchant4_skill"));
 		item.set.set("skill", rset.getString("skill"));
 		
-		if (bodypart == L2Item.SLOT_NECK || bodypart == L2Item.SLOT_HAIR || bodypart == L2Item.SLOT_HAIR2 || bodypart == L2Item.SLOT_HAIRALL || (bodypart & L2Item.SLOT_L_EAR) != 0 || (bodypart & L2Item.SLOT_L_FINGER) != 0)
+		if (bodypart == L2Item.SLOT_NECK || bodypart == L2Item.SLOT_HAIR || bodypart == L2Item.SLOT_HAIR2
+				|| bodypart == L2Item.SLOT_HAIRALL || (bodypart & L2Item.SLOT_L_EAR) != 0 || (bodypart & L2Item.SLOT_L_FINGER) != 0)
 		{
 			item.set.set("type1", L2Item.TYPE1_WEAPON_RING_EARRING_NECKLACE);
 			item.set.set("type2", L2Item.TYPE2_ACCESSORY);
@@ -660,41 +664,41 @@ public class ItemTable
 	/*
 	private void fillEtcItemsTable()
 	{
-	    for (Item itemInfo : itemData.values())
-	    {
-	        L2EtcItem item = SkillsEngine.getInstance().loadEtcItem(itemInfo.id, itemInfo.type, itemInfo.name, itemInfo.set);
-	        if (item == null)
-	        {
-	            item = new L2EtcItem((L2EtcItemType)itemInfo.type, itemInfo.set);
+		for (Item itemInfo : itemData.values())
+		{
+			L2EtcItem item = SkillsEngine.getInstance().loadEtcItem(itemInfo.id, itemInfo.type, itemInfo.name, itemInfo.set);
+			if (item == null)
+			{
+				item = new L2EtcItem((L2EtcItemType)itemInfo.type, itemInfo.set);
 			}
 
-	        _etcItems.put(item.getItemId(), item);
+			_etcItems.put(item.getItemId(), item);
 		}
 	}
 
 	private void fillArmorsTable()
 	{
-	    List<L2Armor> armorList = SkillsEngine.getInstance().loadArmors(armorData);
+		List<L2Armor> armorList = SkillsEngine.getInstance().loadArmors(armorData);
 
-	    /*for (Item itemInfo : armorData.values())
+		/*for (Item itemInfo : armorData.values())
 			{
 
-	        L2Armor armor = SkillsEngine.getInstance().loadArmor(itemInfo.id, itemInfo.type, itemInfo.name, itemInfo.set);
-	        if (armor == null)
-	            armor = new L2Armor((L2ArmorType)itemInfo.type, itemInfo.set);
+			L2Armor armor = SkillsEngine.getInstance().loadArmor(itemInfo.id, itemInfo.type, itemInfo.name, itemInfo.set);
+			if (armor == null)
+				armor = new L2Armor((L2ArmorType)itemInfo.type, itemInfo.set);
 
-	        _armors.put(armor.getItemId(), armor);
-	    }*
+			_armors.put(armor.getItemId(), armor);
+		}*
 				}
 
 	private void FillWeaponsTable()
 				{
 
-	    for (Item itemInfo : weaponData.values())
-	    {
-	        L2Weapon weapon = SkillsEngine.getInstance().loadWeapon(itemInfo.id, itemInfo.type, itemInfo.name, itemInfo.set);
+		for (Item itemInfo : weaponData.values())
+		{
+			L2Weapon weapon = SkillsEngine.getInstance().loadWeapon(itemInfo.id, itemInfo.type, itemInfo.name, itemInfo.set);
 				if (weapon == null)
-	            weapon = new L2Weapon((L2WeaponType)itemInfo.type, itemInfo.set);
+				weapon = new L2Weapon((L2WeaponType)itemInfo.type, itemInfo.set);
 
 				_weapons.put(weapon.getItemId(), weapon);
 				}
@@ -796,7 +800,8 @@ public class ItemTable
 			// if in CommandChannel and was killing a World/RaidBoss
 			if (reference instanceof L2GrandBossInstance || reference instanceof L2RaidBossInstance)
 			{
-				if (((L2Attackable) reference).getFirstCommandChannelAttacked() != null && ((L2Attackable) reference).getFirstCommandChannelAttacked().meetRaidWarCondition(reference))
+				if (((L2Attackable) reference).getFirstCommandChannelAttacked() != null
+						&& ((L2Attackable) reference).getFirstCommandChannelAttacked().meetRaidWarCondition(reference))
 				{
 					item.setOwnerId(((L2Attackable) reference).getFirstCommandChannelAttacked().getChannelLeader().getObjectId());
 					delay = 300000;
@@ -830,10 +835,7 @@ public class ItemTable
 		{
 			LogRecord record = new LogRecord(Level.INFO, "CREATE:" + process);
 			record.setLoggerName("item");
-			record.setParameters(new Object[]
-			{
-				item, actor, reference
-			});
+			record.setParameters(new Object[] { item, actor, reference });
 			_logItems.log(record);
 		}
 		
@@ -848,8 +850,8 @@ public class ItemTable
 				}
 				String targetName = (actor.getTarget() != null ? actor.getTarget().getName() : "no-target");
 				if (Config.GMAUDIT)
-					GMAudit.auditGMAction(actor.getName(), process + "(id: " + itemId + " count: " + count + " name: " + item.getItemName() + " objId: " + item.getObjectId() + ")", targetName, "L2Object referencing this action is: "
-						+ referenceName);
+					GMAudit.auditGMAction(actor.getName(), process + "(id: " + itemId + " count: " + count + " name: " + item.getItemName()
+							+ " objId: " + item.getObjectId() + ")", targetName, "L2Object referencing this action is: " + referenceName);
 			}
 		}
 		
@@ -920,10 +922,7 @@ public class ItemTable
 			{
 				LogRecord record = new LogRecord(Level.INFO, "DELETE:" + process);
 				record.setLoggerName("item");
-				record.setParameters(new Object[]
-				{
-					item, actor, reference
-				});
+				record.setParameters(new Object[] { item, actor, reference });
 				_logItems.log(record);
 			}
 			
@@ -938,7 +937,9 @@ public class ItemTable
 					}
 					String targetName = (actor.getTarget() != null ? actor.getTarget().getName() : "no-target");
 					if (Config.GMAUDIT)
-						GMAudit.auditGMAction(actor.getName(), process + "(id: " + item.getItemId() + " count: " + item.getCount() + " itemObjId: " + item.getObjectId() + ")", targetName, "L2Object referencing this action is: " + referenceName);
+						GMAudit.auditGMAction(actor.getName(), process + "(id: " + item.getItemId() + " count: " + item.getCount()
+								+ " itemObjId: " + item.getObjectId() + ")", targetName, "L2Object referencing this action is: "
+								+ referenceName);
 				}
 			}
 			
@@ -975,11 +976,7 @@ public class ItemTable
 	
 	public void reload()
 	{
-		synchronized (_instance)
-		{
-			_instance = null;
-			_instance = new ItemTable();
-		}
+		load();
 	}
 	
 	protected class resetOwner implements Runnable
@@ -998,4 +995,9 @@ public class ItemTable
 		}
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ItemTable _instance = new ItemTable();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/datatables/LevelUpData.java

@@ -49,17 +49,11 @@ public class LevelUpData
 	
 	private static Logger _log = Logger.getLogger(LevelUpData.class.getName());
 	
-	private static LevelUpData _instance;
-	
 	private Map<Integer, L2LvlupData> _lvlTable;
 	
 	public static LevelUpData getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new LevelUpData();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private LevelUpData()
@@ -125,4 +119,10 @@ public class LevelUpData
 	{
 		return _lvlTable.get(classId.getId());
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final LevelUpData _instance = new LevelUpData();
+	}
 }

+ 17 - 21
L2_GameServer/java/net/sf/l2j/gameserver/datatables/MapRegionTable.java

@@ -47,8 +47,6 @@ public class MapRegionTable
 {
 	private static Logger _log = Logger.getLogger(MapRegionTable.class.getName());
 	
-	private static MapRegionTable _instance;
-	
 	private final int[][] _regions = new int[16][18];
 	
 	private final int[][] _pointsWithKarmas;
@@ -64,11 +62,7 @@ public class MapRegionTable
 	
 	public static MapRegionTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new MapRegionTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private MapRegionTable()
@@ -200,7 +194,7 @@ public class MapRegionTable
 		{
 			// Position sent is outside MapRegionTable area.
 			if (Config.DEBUG)
-				_log.log(Level.WARNING, "MapRegionTable: Player outside map regions at X,Y="+posX+","+posY, e);
+				_log.log(Level.WARNING, "MapRegionTable: Player outside map regions at X,Y=" + posX + "," + posY, e);
 			return 0;
 		}
 	}
@@ -435,7 +429,7 @@ public class MapRegionTable
 			Castle castle = null;
 			Fort fort = null;
 			ClanHall clanhall = null;
-		
+			
 			if (player.getClan() != null && !player.isFlyingMounted()) // flying players in gracia cant use teleports to aden continent
 			{
 				// If teleport to clan hall
@@ -452,7 +446,7 @@ public class MapRegionTable
 						}
 					}
 				}
-
+				
 				// If teleport to castle
 				if (teleportWhere == TeleportWhereType.Castle)
 				{
@@ -462,16 +456,14 @@ public class MapRegionTable
 					if (castle == null)
 					{
 						castle = CastleManager.getInstance().getCastle(player);
-						if (!(castle != null 
-								&& castle.getSiege().getIsInProgress() 
-								&& castle.getSiege().getDefenderClan(player.getClan()) != null))
+						if (!(castle != null && castle.getSiege().getIsInProgress() && castle.getSiege().getDefenderClan(player.getClan()) != null))
 							castle = null;
 					}
 					
 					if (castle != null && castle.getCastleId() > 0)
 					{
-							coord = castle.getZone().getSpawn();
-							return new Location(coord[0], coord[1], coord[2]);
+						coord = castle.getZone().getSpawn();
+						return new Location(coord[0], coord[1], coord[2]);
 					}
 				}
 				
@@ -484,9 +476,7 @@ public class MapRegionTable
 					if (fort == null)
 					{
 						fort = FortManager.getInstance().getFort(player);
-						if (!(fort != null 
-								&& fort.getSiege().getIsInProgress() 
-								&& fort.getOwnerClan() == player.getClan()))
+						if (!(fort != null && fort.getSiege().getIsInProgress() && fort.getOwnerClan() == player.getClan()))
 							fort = null;
 					}
 					
@@ -555,19 +545,19 @@ public class MapRegionTable
 			}
 			//Checking if needed to be respawned in "far" town from the castle;
 			castle = CastleManager.getInstance().getCastle(player);
-			if ( castle != null)
+			if (castle != null)
 			{
 				if (castle.getSiege().getIsInProgress())
 				{
 					// Check if player's clan is participating
-					if ((castle.getSiege().checkIsDefender(player.getClan()) ||	castle.getSiege().checkIsAttacker(player.getClan())) 
+					if ((castle.getSiege().checkIsDefender(player.getClan()) || castle.getSiege().checkIsAttacker(player.getClan()))
 							&& SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_STRIFE) == SevenSigns.CABAL_DAWN)
 					{
 						coord = TownManager.getSecondClosestTown(activeChar).getSpawnLoc();
 						return new Location(coord[0], coord[1], coord[2]);
 					}
 				}
-			}    
+			}
 			
 			// Checking if in an instance
 			if (player.getInstanceId() > 0)
@@ -586,4 +576,10 @@ public class MapRegionTable
 		
 		return new Location(coord[0], coord[1], coord[2]);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final MapRegionTable _instance = new MapRegionTable();
+	}
 }

+ 49 - 25
L2_GameServer/java/net/sf/l2j/gameserver/datatables/MerchantPriceConfigTable.java

@@ -25,6 +25,7 @@ import javax.xml.parsers.ParserConfigurationException;
 
 import javolution.util.FastMap;
 import net.sf.l2j.Config;
+import net.sf.l2j.gameserver.InstanceListManager;
 import net.sf.l2j.gameserver.instancemanager.CastleManager;
 import net.sf.l2j.gameserver.model.actor.instance.L2MerchantInstance;
 import net.sf.l2j.gameserver.model.entity.Castle;
@@ -37,19 +38,13 @@ import org.xml.sax.SAXException;
  *
  * @author  KenM
  */
-public class MerchantPriceConfigTable
+public class MerchantPriceConfigTable implements InstanceListManager
 {
 	private static Logger _log = Logger.getLogger(MerchantPriceConfigTable.class.getName());
 	
-	private static MerchantPriceConfigTable _instance;
-	
 	public static MerchantPriceConfigTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new MerchantPriceConfigTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private static final String MPCS_FILE = "MerchantPriceConfig.xml";
@@ -59,15 +54,6 @@ public class MerchantPriceConfigTable
 	
 	private MerchantPriceConfigTable()
 	{
-		try
-		{
-			this.loadXML();
-			_log.info("MerchantPriceConfigTable: Loaded " + _mpcs.size() + " merchant price configs.");
-		}
-		catch (Exception e)
-		{
-			_log.log(Level.SEVERE, "Failed loading MerchantPriceConfigTable. Reason: " + e.getMessage(), e);
-		}
 	}
 	
 	public MerchantPriceConfig getMerchantPriceConfig(L2MerchantInstance npc)
@@ -131,9 +117,11 @@ public class MerchantPriceConfigTable
 	{
 		if (n.getNodeName().equals("priceConfig"))
 		{
-			int id, baseTax, castleId, zoneId = -1;
-			String name;
-			Castle castle = null;
+			final int id;
+			final int baseTax;
+			int castleId = -1;
+			int zoneId = -1;
+			final String name;
 			
 			Node node = n.getAttributes().getNamedItem("id");
 			if (node == null)
@@ -169,7 +157,6 @@ public class MerchantPriceConfigTable
 			if (node != null)
 			{
 				castleId = Integer.parseInt(node.getNodeValue());
-				castle = CastleManager.getInstance().getCastleById(castleId);
 			}
 			
 			node = n.getAttributes().getNamedItem("zoneId");
@@ -178,11 +165,36 @@ public class MerchantPriceConfigTable
 				zoneId = Integer.parseInt(node.getNodeValue());
 			}
 			
-			return new MerchantPriceConfig(id, name, baseTax, castle, zoneId);
+			return new MerchantPriceConfig(id, name, baseTax, castleId, zoneId);
 		}
 		return null;
 	}
 	
+	public void loadInstances()
+	{
+		try
+		{
+			this.loadXML();
+			_log.info("MerchantPriceConfigTable: Loaded " + _mpcs.size() + " merchant price configs.");
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.SEVERE, "Failed loading MerchantPriceConfigTable. Reason: " + e.getMessage(), e);
+		}
+	}
+	
+	public void updateReferences()
+	{
+		for (final MerchantPriceConfig mpc : _mpcs.values())
+		{
+			mpc.updateReferences();
+		}
+	}
+	
+	public void activateInstances()
+	{
+	}
+	
 	/**
 	 * 
 	 *
@@ -193,15 +205,16 @@ public class MerchantPriceConfigTable
 		private final int _id;
 		private final String _name;
 		private final int _baseTax;
-		private final Castle _castle;
+		private final int _castleId;
+		private Castle _castle;
 		private final int _zoneId;
 		
-		public MerchantPriceConfig(int id, String name, int baseTax, Castle castle, int zoneId)
+		public MerchantPriceConfig(final int id, final String name, final int baseTax, final int castleId, final int zoneId)
 		{
 			_id = id;
 			_name = name;
 			_baseTax = baseTax;
-			_castle = castle;
+			_castleId = castleId;
 			_zoneId = zoneId;
 		}
 		
@@ -272,5 +285,16 @@ public class MerchantPriceConfigTable
 		{
 			return this.getTotalTax() / 100.0;
 		}
+		
+		public void updateReferences()
+		{
+			_castle = CastleManager.getInstance().getCastleById(_castleId);
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final MerchantPriceConfigTable _instance = new MerchantPriceConfigTable();
 	}
 }

+ 7 - 4
L2_GameServer/java/net/sf/l2j/gameserver/datatables/NobleSkillTable.java

@@ -22,7 +22,6 @@ import net.sf.l2j.gameserver.model.L2Skill;
  */
 public class NobleSkillTable
 {
-	private static NobleSkillTable _instance;
 	private static L2Skill[] _nobleSkills;
 	
 	private NobleSkillTable()
@@ -40,13 +39,17 @@ public class NobleSkillTable
 	
 	public static NobleSkillTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new NobleSkillTable();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public L2Skill[] getNobleSkills()
 	{
 		return _nobleSkills;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final NobleSkillTable _instance = new NobleSkillTable();
+	}
 }

+ 8 - 9
L2_GameServer/java/net/sf/l2j/gameserver/datatables/NpcBufferTable.java

@@ -59,10 +59,7 @@ public class NpcBufferTable
 			if (skillId == null || skillLevel == null || skillFeeId == null || skillFeeAmount == null)
 				return null;
 			
-			return new int[]
-			{
-				skillId, skillLevel, skillFeeId, skillFeeAmount
-			};
+			return new int[] { skillId, skillLevel, skillFeeId, skillFeeAmount };
 		}
 		
 		public int getNpcId()
@@ -71,7 +68,6 @@ public class NpcBufferTable
 		}
 	}
 	
-	private static NpcBufferTable _instance = null;
 	private Map<Integer, NpcBufferSkills> _buffers = new FastMap<Integer, NpcBufferSkills>();
 	
 	private NpcBufferTable()
@@ -137,10 +133,7 @@ public class NpcBufferTable
 	
 	public static NpcBufferTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new NpcBufferTable();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public int[] getSkillInfo(int npcId, int buffGroup)
@@ -152,4 +145,10 @@ public class NpcBufferTable
 		
 		return skills.getSkillGroupInfo(buffGroup);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final NpcBufferTable _instance = new NpcBufferTable();
+	}
 }

+ 75 - 76
L2_GameServer/java/net/sf/l2j/gameserver/datatables/NpcTable.java

@@ -46,17 +46,12 @@ public class NpcTable
 {
 	private static Logger _log = Logger.getLogger(NpcTable.class.getName());
 	
-	private static NpcTable _instance;
-	
 	private Map<Integer, L2NpcTemplate> _npcs;
 	private boolean _initialized = false;
 	
 	public static NpcTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new NpcTable();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private NpcTable()
@@ -77,12 +72,12 @@ public class NpcTable
 				con = L2DatabaseFactory.getInstance().getConnection();
 				PreparedStatement statement;
 				statement = con.prepareStatement("SELECT "
-						+ L2DatabaseFactory.getInstance().safetyString(new String[]
-						{
-							"id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con",
-							"dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd", "faction_id", "faction_range", "isUndead", "absorb_level",
-							"absorb_type", "ss", "bss", "ss_rate", "AI", "drop_herbs"
-						}) + " FROM npc");
+						+ L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName",
+								"title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type",
+								"attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk",
+								"pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd",
+								"faction_id", "faction_range", "isUndead", "absorb_level", "absorb_type", "ss", "bss", "ss_rate", "AI",
+								"drop_herbs" }) + " FROM npc");
 				ResultSet npcdata = statement.executeQuery();
 				
 				fillNpcTable(npcdata, false);
@@ -100,12 +95,12 @@ public class NpcTable
 					con = L2DatabaseFactory.getInstance().getConnection();
 					PreparedStatement statement;
 					statement = con.prepareStatement("SELECT "
-							+ L2DatabaseFactory.getInstance().safetyString(new String[]
-							{
-								"id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con",
-								"dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd", "faction_id", "faction_range", "isUndead",
-								"absorb_level", "absorb_type", "ss", "bss", "ss_rate", "AI", "drop_herbs"
-							}) + " FROM custom_npc");
+							+ L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName",
+									"title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type",
+									"attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp",
+									"patk", "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd",
+									"runspd", "faction_id", "faction_range", "isUndead", "absorb_level", "absorb_type", "ss", "bss",
+									"ss_rate", "AI", "drop_herbs" }) + " FROM custom_npc");
 					ResultSet npcdata = statement.executeQuery();
 					
 					fillNpcTable(npcdata, true);
@@ -160,10 +155,9 @@ public class NpcTable
 			
 			try
 			{
-				PreparedStatement statement2 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
-				{
-					"mobId", "itemId", "min", "max", "category", "chance"
-				}) + " FROM droplist ORDER BY mobId, chance DESC");
+				PreparedStatement statement2 = con.prepareStatement("SELECT "
+						+ L2DatabaseFactory.getInstance().safetyString(new String[] { "mobId", "itemId", "min", "max", "category", "chance" })
+						+ " FROM droplist ORDER BY mobId, chance DESC");
 				ResultSet dropData = statement2.executeQuery();
 				L2DropData dropDat = null;
 				L2NpcTemplate npcDat = null;
@@ -201,10 +195,9 @@ public class NpcTable
 			{
 				try
 				{
-					PreparedStatement statement2 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
-					{
-						"mobId", "itemId", "min", "max", "category", "chance"
-					}) + " FROM custom_droplist ORDER BY mobId, chance DESC");
+					PreparedStatement statement2 = con.prepareStatement("SELECT "
+							+ L2DatabaseFactory.getInstance().safetyString(new String[] { "mobId", "itemId", "min", "max", "category",
+									"chance" }) + " FROM custom_droplist ORDER BY mobId, chance DESC");
 					ResultSet dropData = statement2.executeQuery();
 					L2DropData dropDat = null;
 					L2NpcTemplate npcDat = null;
@@ -239,10 +232,8 @@ public class NpcTable
 			
 			try
 			{
-				PreparedStatement statement3 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
-				{
-					"npc_id", "class_id"
-				}) + " FROM skill_learn");
+				PreparedStatement statement3 = con.prepareStatement("SELECT "
+						+ L2DatabaseFactory.getInstance().safetyString(new String[] { "npc_id", "class_id" }) + " FROM skill_learn");
 				ResultSet learndata = statement3.executeQuery();
 				
 				while (learndata.next())
@@ -270,10 +261,9 @@ public class NpcTable
 			
 			try
 			{
-				PreparedStatement statement4 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
-				{
-					"boss_id", "minion_id", "amount_min", "amount_max"
-				}) + " FROM minions");
+				PreparedStatement statement4 = con.prepareStatement("SELECT "
+						+ L2DatabaseFactory.getInstance().safetyString(new String[] { "boss_id", "minion_id", "amount_min", "amount_max" })
+						+ " FROM minions");
 				ResultSet minionData = statement4.executeQuery();
 				L2MinionData minionDat = null;
 				L2NpcTemplate npcDat = null;
@@ -404,8 +394,10 @@ public class NpcTable
 			_npcs.put(id, template);
 		}
 		
-		if (!customData) _log.config("NpcTable: Loaded " + _npcs.size() + " NPC templates.");
-		else _log.config("NpcTable: Loaded " + _npcs.size() + " custom NPC templates.");
+		if (!customData)
+			_log.config("NpcTable: Loaded " + _npcs.size() + " NPC templates.");
+		else
+			_log.config("NpcTable: Loaded " + _npcs.size() + " custom NPC templates.");
 	}
 	
 	public void reloadNpc(int id)
@@ -439,24 +431,24 @@ public class NpcTable
 			// reload the NPC base data
 			con = L2DatabaseFactory.getInstance().getConnection();
 			PreparedStatement st = con.prepareStatement("SELECT "
-					+ L2DatabaseFactory.getInstance().safetyString(new String[]
-					{
-						"id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex",
-						"int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd", "faction_id", "faction_range", "isUndead", "absorb_level",
-						"absorb_type", "ss", "bss", "ss_rate", "AI", "drop_herbs"
-					}) + " FROM npc WHERE id=?");
+					+ L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName", "title",
+							"serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange",
+							"hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk",
+							"mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd", "faction_id",
+							"faction_range", "isUndead", "absorb_level", "absorb_type", "ss", "bss", "ss_rate", "AI", "drop_herbs" })
+					+ " FROM npc WHERE id=?");
 			st.setInt(1, id);
 			ResultSet rs = st.executeQuery();
 			fillNpcTable(rs, false);
 			if (Config.CUSTOM_NPC_TABLE) // reload certain NPCs
 			{
 				st = con.prepareStatement("SELECT "
-					+ L2DatabaseFactory.getInstance().safetyString(new String[]
-					{
-						"id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con",
-						"dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd", "faction_id", "faction_range", "isUndead",
-						"absorb_level", "absorb_type", "ss", "bss", "ss_rate", "AI", "drop_herbs"
-					}) + " FROM custom_npc WHERE id=?");
+						+ L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName",
+								"title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type",
+								"attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk",
+								"pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "walkspd", "runspd",
+								"faction_id", "faction_range", "isUndead", "absorb_level", "absorb_type", "ss", "bss", "ss_rate", "AI",
+								"drop_herbs" }) + " FROM custom_npc WHERE id=?");
 				rs = st.executeQuery();
 				fillNpcTable(rs, true);
 			}
@@ -505,38 +497,40 @@ public class NpcTable
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
 			Map<String, Object> set = npc.getSet();
-
-            int length = 0;
-
-            for (Object obj : set.keySet()) {
-                // 15 is just guessed npc name length
-                length += ((String) obj).length() + 7 + 15;
-            }
-
-            final StringBuilder sbValues = new StringBuilder(length);
 			
-			for (Object obj : set.keySet()) {
-                final String name = (String) obj;
+			int length = 0;
+			
+			for (Object obj : set.keySet())
+			{
+				// 15 is just guessed npc name length
+				length += ((String) obj).length() + 7 + 15;
+			}
+			
+			final StringBuilder sbValues = new StringBuilder(length);
+			
+			for (Object obj : set.keySet())
+			{
+				final String name = (String) obj;
 				
-				if (!name.equalsIgnoreCase("npcId")) {
-                    if (sbValues.length() > 0) {
-                        sbValues.append(", ");
-                    }
-
-                    sbValues.append(name);
-                    sbValues.append(" = '");
-                    sbValues.append(set.get(name));
-                    sbValues.append('\'');
+				if (!name.equalsIgnoreCase("npcId"))
+				{
+					if (sbValues.length() > 0)
+					{
+						sbValues.append(", ");
+					}
+					
+					sbValues.append(name);
+					sbValues.append(" = '");
+					sbValues.append(set.get(name));
+					sbValues.append('\'');
 				}
 			}
-
-            final StringBuilder sbQuery =
-                    new StringBuilder(sbValues.length() + 28);
-            sbQuery.append("UPDATE npc SET ");
-            sbQuery.append(sbValues.toString());
-            sbQuery.append(" WHERE id = ?");
-			PreparedStatement statement =
-                    con.prepareStatement(sbQuery.toString());
+			
+			final StringBuilder sbQuery = new StringBuilder(sbValues.length() + 28);
+			sbQuery.append("UPDATE npc SET ");
+			sbQuery.append(sbValues.toString());
+			sbQuery.append(" WHERE id = ?");
+			PreparedStatement statement = con.prepareStatement(sbQuery.toString());
 			statement.setInt(1, npc.getInteger("npcId"));
 			statement.execute();
 			statement.close();
@@ -641,4 +635,9 @@ public class NpcTable
 		return null;
 	}
 	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final NpcTable _instance = new NpcTable();
+	}
 }

+ 8 - 9
L2_GameServer/java/net/sf/l2j/gameserver/datatables/NpcWalkerRoutesTable.java

@@ -35,23 +35,16 @@ public class NpcWalkerRoutesTable
 {
 	private final static Logger _log = Logger.getLogger(SpawnTable.class.getName());
 	
-	private static NpcWalkerRoutesTable _instance;
-	
 	private FastList<L2NpcWalkerNode> _routes = new FastList<L2NpcWalkerNode>();;
 	
 	public static NpcWalkerRoutesTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new NpcWalkerRoutesTable();
-			_log.info("Initializing Walkers Routes Table.");
-		}
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private NpcWalkerRoutesTable()
 	{
+		_log.info("Initializing Walkers Routes Table.");
 	}
 	
 	public void load()
@@ -116,4 +109,10 @@ public class NpcWalkerRoutesTable
 		return _return;
 		
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final NpcWalkerRoutesTable _instance = new NpcWalkerRoutesTable();
+	}
 }

+ 10 - 6
L2_GameServer/java/net/sf/l2j/gameserver/datatables/PetNameTable.java

@@ -31,15 +31,13 @@ public class PetNameTable
 {
 	private static Logger _log = Logger.getLogger(PetNameTable.class.getName());
 	
-	private static PetNameTable _instance;
+	private PetNameTable()
+	{
+	}
 	
 	public static PetNameTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new PetNameTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public boolean doesPetNameExist(String name, int petNpcId)
@@ -122,4 +120,10 @@ public class PetNameTable
 		}
 		return result;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final PetNameTable _instance = new PetNameTable();
+	}
 }

+ 25 - 20
L2_GameServer/java/net/sf/l2j/gameserver/datatables/PetSkillsTable.java

@@ -31,23 +31,25 @@ public class PetSkillsTable
 {
 	private static Logger _log = Logger.getLogger(PetSkillsTable.class.getName());
 	private FastMap<Integer, Map<Integer, L2PetSkillLearn>> _skillTrees;
-	private static PetSkillsTable _instance;
 	
 	public static PetSkillsTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new PetSkillsTable();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public void reload()
 	{
 		_skillTrees.clear();
-		_instance = new PetSkillsTable();
+		load();
 	}
 	
 	private PetSkillsTable()
+	{
+		_skillTrees = new FastMap<Integer, Map<Integer, L2PetSkillLearn>>();
+		load();
+	}
+	
+	private void load()
 	{
 		int npcId = 0;
 		int count = 0;
@@ -77,9 +79,9 @@ public class PetSkillsTable
 						int minLvl = skilltree.getInt("minLvl");
 						
 						skillLearn = new L2PetSkillLearn(id, lvl, minLvl);
-						map.put(SkillTable.getSkillHashCode(id, lvl+1), skillLearn);
+						map.put(SkillTable.getSkillHashCode(id, lvl + 1), skillLearn);
 					}
-					getPetSkillTrees().put(npcId, map);
+					_skillTrees.put(npcId, map);
 					skilltree.close();
 					statement2.close();
 					
@@ -111,19 +113,12 @@ public class PetSkillsTable
 		}
 	}
 	
-	private Map<Integer, Map<Integer, L2PetSkillLearn>> getPetSkillTrees()
-	{
-		if (_skillTrees == null)
-			_skillTrees = new FastMap<Integer, Map<Integer, L2PetSkillLearn>>();
-		
-		return _skillTrees;
-	}
 	public int getAvailableLevel(L2Summon cha, int skillId)
 	{
 		int lvl = 0;
-		if (!getPetSkillTrees().containsKey(cha.getNpcId()))
+		if (!_skillTrees.containsKey(cha.getNpcId()))
 			return lvl;
-		Collection<L2PetSkillLearn> skills = getPetSkillTrees().get(cha.getNpcId()).values();
+		Collection<L2PetSkillLearn> skills = _skillTrees.get(cha.getNpcId()).values();
 		for (L2PetSkillLearn temp : skills)
 		{
 			if (temp.getId() != skillId)
@@ -138,7 +133,7 @@ public class PetSkillsTable
 				}
 				else
 					lvl = (7 + ((cha.getLevel() - 70) / 5));
-					
+				
 				// formula usable for skill that have 10 or more skill levels
 				int maxLvl = SkillTable.getInstance().getMaxLevel(temp.getId(), 10);
 				if (lvl > maxLvl)
@@ -157,9 +152,9 @@ public class PetSkillsTable
 	public FastList<Integer> getAvailableSkills(L2Summon cha)
 	{
 		FastList<Integer> skillIds = new FastList<Integer>();
-		if (!getPetSkillTrees().containsKey(cha.getNpcId()))
+		if (!_skillTrees.containsKey(cha.getNpcId()))
 			return null;
-		Collection<L2PetSkillLearn> skills = getPetSkillTrees().get(cha.getNpcId()).values();
+		Collection<L2PetSkillLearn> skills = _skillTrees.get(cha.getNpcId()).values();
 		for (L2PetSkillLearn temp : skills)
 		{
 			if (skillIds.contains(temp.getId()))
@@ -168,6 +163,7 @@ public class PetSkillsTable
 		}
 		return skillIds;
 	}
+	
 	public final class L2PetSkillLearn
 	{
 		private final int _id;
@@ -180,17 +176,26 @@ public class PetSkillsTable
 			_level = lvl;
 			_minLevel = minLvl;
 		}
+		
 		public int getId()
 		{
 			return _id;
 		}
+		
 		public int getLevel()
 		{
 			return _level;
 		}
+		
 		public int getMinLevel()
 		{
 			return _minLevel;
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final PetSkillsTable _instance = new PetSkillsTable();
+	}
 }

+ 18 - 16
L2_GameServer/java/net/sf/l2j/gameserver/datatables/SkillSpellbookTable.java

@@ -28,26 +28,22 @@ import net.sf.l2j.gameserver.model.L2Skill;
 public class SkillSpellbookTable
 {
 	private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
-	private static SkillSpellbookTable _instance;
-
+	
 	private static Map<Integer, Integer> _skillSpellbooks;
-
+	
 	public static SkillSpellbookTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new SkillSpellbookTable();
-
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private SkillSpellbookTable()
 	{
 		if (!Config.SP_BOOK_NEEDED)
 			return;
-
+		
 		_skillSpellbooks = new FastMap<Integer, Integer>();
 		Connection con = null;
-
+		
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
@@ -77,7 +73,7 @@ public class SkillSpellbookTable
 			}
 		}
 	}
-
+	
 	public int getBookForSkill(int skillId, int level)
 	{
 		if (skillId == L2Skill.SKILL_DIVINE_INSPIRATION && level != -1)
@@ -96,23 +92,29 @@ public class SkillSpellbookTable
 					return -1;
 			}
 		}
-
+		
 		if (!Config.SP_BOOK_NEEDED)
 			return (-1);
-
+		
 		if (!_skillSpellbooks.containsKey(skillId))
 			return -1;
-
+		
 		return _skillSpellbooks.get(skillId);
 	}
-
+	
 	public int getBookForSkill(L2Skill skill)
 	{
 		return getBookForSkill(skill.getId(), -1);
 	}
-
+	
 	public int getBookForSkill(L2Skill skill, int level)
 	{
 		return getBookForSkill(skill.getId(), level);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SkillSpellbookTable _instance = new SkillSpellbookTable();
+	}
 }

+ 12 - 29
L2_GameServer/java/net/sf/l2j/gameserver/datatables/SkillTable.java

@@ -20,7 +20,6 @@ import javolution.util.FastList;
 import javolution.util.FastMap;
 import net.sf.l2j.gameserver.model.L2Skill;
 import net.sf.l2j.gameserver.skills.SkillsEngine;
-import net.sf.l2j.gameserver.templates.item.L2WeaponType;
 
 /**
  * This class ...
@@ -30,27 +29,24 @@ import net.sf.l2j.gameserver.templates.item.L2WeaponType;
 public class SkillTable
 {
 	//private static Logger _log = Logger.getLogger(SkillTable.class.getName());
-	private static SkillTable _instance;
-	
-	private Map<Integer, L2Skill> _skills;
+	private static Map<Integer, L2Skill> _skills = new FastMap<Integer, L2Skill>();
 	private boolean _initialized = true;
 	
 	public static SkillTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new SkillTable();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private SkillTable()
 	{
-		_skills = new FastMap<Integer, L2Skill>();
 		SkillsEngine.getInstance().loadAllSkills(_skills);
 	}
 	
-	public static void reload()
+	public void reload()
 	{
-		_instance = new SkillTable();
+		final Map<Integer, L2Skill> skills = new FastMap<Integer, L2Skill>();
+		SkillsEngine.getInstance().loadAllSkills(skills);
+		_skills = skills;
 	}
 	
 	public boolean isInitialized()
@@ -95,25 +91,6 @@ public class SkillTable
 		return level;
 	}
 	
-	private static final L2WeaponType[] weaponDbMasks =
-	{
-		L2WeaponType.ETC, L2WeaponType.BOW, L2WeaponType.POLE, L2WeaponType.DUALFIST, L2WeaponType.DUAL, L2WeaponType.BLUNT, L2WeaponType.SWORD, L2WeaponType.DAGGER, L2WeaponType.BIGSWORD, L2WeaponType.ROD, L2WeaponType.BIGBLUNT,
-		L2WeaponType.ANCIENT_SWORD, L2WeaponType.RAPIER, L2WeaponType.CROSSBOW
-	};
-	
-	public int calcWeaponsAllowed(int mask)
-	{
-		if (mask == 0)
-			return 0;
-		
-		int weaponsAllowed = 0;
-		
-		for (int i = 0; i < weaponDbMasks.length; i++)
-			if ((mask & (1 << i)) != 0)
-				weaponsAllowed |= weaponDbMasks[i].mask();
-		
-		return weaponsAllowed;
-	}
 	
 	/**
 	 * Returns an array with siege skills. If addNoble == true, will add also Advanced headquarters.
@@ -133,4 +110,10 @@ public class SkillTable
 		
 		return temp;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SkillTable _instance = new SkillTable();
+	}
 }

+ 13 - 10
L2_GameServer/java/net/sf/l2j/gameserver/datatables/SkillTreeTable.java

@@ -51,7 +51,6 @@ public class SkillTreeTable
 	public static final int UNTRAIN_ENCHANT_BOOK = 9625;
 	
 	private static Logger _log = Logger.getLogger(SkillTreeTable.class.getName());
-	private static SkillTreeTable _instance;
 	
 	private Map<ClassId, Map<Integer, L2SkillLearn>> _skillTrees;
 	private List<L2SkillLearn> _fishingSkillTrees; //all common skills (teached by Fisherman)
@@ -63,10 +62,7 @@ public class SkillTreeTable
 	
 	public static SkillTreeTable getInstance()
 	{
-		if (_instance == null)
-			_instance = new SkillTreeTable();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -422,7 +418,7 @@ public class SkillTreeTable
 		}
 		
 		_log.config("FishingSkillTreeTable: Loaded " + count2 + " general skills.");
-		_log.config("FishingSkillTreeTable: Loaded " + count3 + " dwarven skills.");
+		_log.config("DwarvenCraftSkillTreeTable: Loaded " + count3 + " dwarven skills.");
 		_log.config("EnchantSkillTreeTable: Loaded " + count4 + " enchant skills.");
 		_log.config("PledgeSkillTreeTable: Loaded " + count5 + " pledge skills");
 		_log.config("TransformSkillTreeTable: Loaded " + count6 + " transform skills");
@@ -553,13 +549,13 @@ public class SkillTreeTable
 		for (L2SkillLearn temp : skills)
 		{
 			boolean knownSkill = false;
-				
+			
 			for (int j = 0; j < oldSkills.length && !knownSkill; j++)
 			{
 				if (oldSkills[j].getId() == temp.getId())
 				{
 					knownSkill = true;
-						
+					
 					if (oldSkills[j].getLevel() == temp.getLevel() - 1)
 					{
 						// this is the next level of a skill that we know
@@ -567,7 +563,7 @@ public class SkillTreeTable
 					}
 				}
 			}
-				
+			
 			if (!knownSkill && temp.getLevel() == 1)
 			{
 				// this is a new skill
@@ -577,6 +573,7 @@ public class SkillTreeTable
 		
 		return result.toArray(new L2SkillLearn[result.size()]);
 	}
+	
 	public L2EnchantSkillLearn getSkillEnchantmentForSkill(L2Skill skill)
 	{
 		L2EnchantSkillLearn esl = this.getSkillEnchantmentBySkillId(skill.getId());
@@ -783,7 +780,7 @@ public class SkillTreeTable
 			{
 				skillCost = skillLearn.getSpCost();
 				if (!player.getClassId().equalsOrChildOf(classId))
-						return skillCost;
+					return skillCost;
 			}
 		}
 		
@@ -834,4 +831,10 @@ public class SkillTreeTable
 		
 		return 0;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SkillTreeTable _instance = new SkillTreeTable();
+	}
 }

+ 13 - 6
L2_GameServer/java/net/sf/l2j/gameserver/datatables/SpawnTable.java

@@ -38,8 +38,6 @@ public class SpawnTable
 {
 	private static Logger _log = Logger.getLogger(SpawnTable.class.getName());
 	
-	private static final SpawnTable _instance = new SpawnTable();
-	
 	private Map<Integer, L2Spawn> _spawntable = new FastMap<Integer, L2Spawn>().setShared(true);
 	private int _npcSpawnCount;
 	private int _customSpawnCount;
@@ -48,7 +46,7 @@ public class SpawnTable
 	
 	public static SpawnTable getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private SpawnTable()
@@ -284,7 +282,8 @@ public class SpawnTable
 			try
 			{
 				con = L2DatabaseFactory.getInstance().getConnection();
-				PreparedStatement statement = con.prepareStatement("INSERT INTO " + spawnTable + "(id,count,npc_templateid,locx,locy,locz,heading,respawn_delay,loc_id) values(?,?,?,?,?,?,?,?,?)");
+				PreparedStatement statement = con.prepareStatement("INSERT INTO " + spawnTable
+						+ "(id,count,npc_templateid,locx,locy,locz,heading,respawn_delay,loc_id) values(?,?,?,?,?,?,?,?,?)");
 				statement.setInt(1, spawn.getId());
 				statement.setInt(2, spawn.getAmount());
 				statement.setInt(3, spawn.getNpcid());
@@ -356,7 +355,8 @@ public class SpawnTable
 				try
 				{
 					con = L2DatabaseFactory.getInstance().getConnection();
-					PreparedStatement statement = con.prepareStatement("DELETE FROM " + (spawn.isCustom() ? "custom_spawnlist" : "spawnlist") + " WHERE id=?");
+					PreparedStatement statement = con.prepareStatement("DELETE FROM "
+							+ (spawn.isCustom() ? "custom_spawnlist" : "spawnlist") + " WHERE id=?");
 					statement.setInt(1, spawn.getId());
 					statement.execute();
 					statement.close();
@@ -408,7 +408,8 @@ public class SpawnTable
 				}
 				else
 				{
-					activeChar.sendMessage(index + " - " + spawn.getTemplate().name + " (" + spawn.getId() + "): " + spawn.getLocx() + " " + spawn.getLocy() + " " + spawn.getLocz());
+					activeChar.sendMessage(index + " - " + spawn.getTemplate().name + " (" + spawn.getId() + "): " + spawn.getLocx() + " "
+							+ spawn.getLocy() + " " + spawn.getLocz());
 				}
 			}
 		}
@@ -416,4 +417,10 @@ public class SpawnTable
 		if (index == 0)
 			activeChar.sendMessage("No current spawns found.");
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SpawnTable _instance = new SpawnTable();
+	}
 }

+ 9 - 5
L2_GameServer/java/net/sf/l2j/gameserver/datatables/StaticObjects.java

@@ -34,17 +34,14 @@ public class StaticObjects
 {
 	private static Logger _log = Logger.getLogger(StaticObjects.class.getName());
 	
-	private static StaticObjects _instance;
 	private Map<Integer, L2StaticObjectInstance> _staticObjects;
 	
 	public static StaticObjects getInstance()
 	{
-		if (_instance == null)
-			_instance = new StaticObjects();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public StaticObjects()
+	private StaticObjects()
 	{
 		_staticObjects = new FastMap<Integer, L2StaticObjectInstance>();
 		parseData();
@@ -158,8 +155,15 @@ public class StaticObjects
 		
 		return obj;
 	}
+	
 	public void putObject(L2StaticObjectInstance obj)
 	{
 		_staticObjects.put(obj.getStaticObjectId(), obj);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final StaticObjects _instance = new StaticObjects();
+	}
 }

+ 8 - 7
L2_GameServer/java/net/sf/l2j/gameserver/datatables/SummonItemsData.java

@@ -34,17 +34,12 @@ public class SummonItemsData
 	protected static final Logger _log = Logger.getLogger(SummonItemsData.class.getName());
 	private FastMap<Integer, L2SummonItem> _summonitems;
 	
-	private static SummonItemsData _instance;
-	
 	public static SummonItemsData getInstance()
 	{
-		if (_instance == null)
-			_instance = new SummonItemsData();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public SummonItemsData()
+	private SummonItemsData()
 	{
 		_summonitems = new FastMap<Integer, L2SummonItem>();
 		
@@ -119,4 +114,10 @@ public class SummonItemsData
 		}
 		return result;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SummonItemsData _instance = new SummonItemsData();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/datatables/TeleportLocationTable.java

@@ -35,17 +35,11 @@ public class TeleportLocationTable
 {
 	private static Logger _log = Logger.getLogger(TeleportLocationTable.class.getName());
 	
-	private static TeleportLocationTable _instance;
-	
 	private Map<Integer, L2TeleportLocation> _teleports;
 	
 	public static TeleportLocationTable getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new TeleportLocationTable();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private TeleportLocationTable()
@@ -150,4 +144,10 @@ public class TeleportLocationTable
 	{
 		return _teleports.get(id);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final TeleportLocationTable _instance = new TeleportLocationTable();
+	}
 }

+ 15 - 10
L2_GameServer/java/net/sf/l2j/gameserver/geoeditorcon/GeoEditorListener.java

@@ -33,18 +33,23 @@ public class GeoEditorListener extends Thread
 	
 	public static GeoEditorListener getInstance()
 	{
-		if (_instance == null)
-			try
-			{
-				_instance = new GeoEditorListener();
-				_instance.start();
-				_log.info("GeoEditorListener Initialized.");
-			}
-			catch (IOException e)
+		synchronized (GeoEditorListener.class)
+		{
+			if (_instance == null)
 			{
-				_log.severe("Error creating geoeditor listener! " + e.getMessage());
-				System.exit(1);
+				try
+				{
+					_instance = new GeoEditorListener();
+					_instance.start();
+					_log.info("GeoEditorListener Initialized.");
+				}
+				catch (IOException e)
+				{
+					_log.severe("Error creating geoeditor listener! " + e.getMessage());
+					System.exit(1);
+				}
 			}
+		}
 		return _instance;
 	}
 	

+ 8 - 8
L2_GameServer/java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java

@@ -29,19 +29,13 @@ public class AdminCommandHandler
 {
 	private static Logger _log = Logger.getLogger(AdminCommandHandler.class.getName());
 	
-	private static AdminCommandHandler _instance;
-	
 	private Map<String, IAdminCommandHandler> _datatable;
 	
 	public static AdminCommandHandler getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new AdminCommandHandler();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private AdminCommandHandler()
 	{
 		_datatable = new FastMap<String, IAdminCommandHandler>();
@@ -77,4 +71,10 @@ public class AdminCommandHandler
 	{
 		return _datatable.size();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AdminCommandHandler _instance = new AdminCommandHandler();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/handler/ChatHandler.java

@@ -28,17 +28,11 @@ public class ChatHandler
 {
 	private static Logger _log = Logger.getLogger(ChatHandler.class.getName());
 	
-	private static ChatHandler _instance;
-	
 	private FastMap<Integer, IChatHandler> _datatable;
 	
 	public static ChatHandler getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ChatHandler();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -82,4 +76,10 @@ public class ChatHandler
 	{
 		return _datatable.size();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ChatHandler _instance = new ChatHandler();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/handler/ItemHandler.java

@@ -26,8 +26,6 @@ import net.sf.l2j.gameserver.templates.item.L2EtcItem;
  */
 public class ItemHandler
 {
-	private static ItemHandler _instance;
-	
 	private List<IItemHandler> _datatable;
 	
 	/**
@@ -36,11 +34,7 @@ public class ItemHandler
 	 */
 	public static ItemHandler getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ItemHandler();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	/**
@@ -89,4 +83,10 @@ public class ItemHandler
 		}
 		return null;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ItemHandler _instance = new ItemHandler();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/handler/SkillHandler.java

@@ -26,17 +26,11 @@ import net.sf.l2j.gameserver.templates.skills.L2SkillType;
  */
 public class SkillHandler
 {
-	private static SkillHandler _instance;
-	
 	private Map<L2SkillType, ISkillHandler> _datatable;
 	
 	public static SkillHandler getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new SkillHandler();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private SkillHandler()
@@ -65,4 +59,10 @@ public class SkillHandler
 	{
 		return _datatable.size();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SkillHandler _instance = new SkillHandler();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/handler/UserCommandHandler.java

@@ -29,17 +29,11 @@ public class UserCommandHandler
 {
 	private static Logger _log = Logger.getLogger(UserCommandHandler.class.getName());
 	
-	private static UserCommandHandler _instance;
-	
 	private Map<Integer, IUserCommandHandler> _datatable;
 	
 	public static UserCommandHandler getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new UserCommandHandler();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private UserCommandHandler()
@@ -72,4 +66,10 @@ public class UserCommandHandler
 	{
 		return _datatable.size();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final UserCommandHandler _instance = new UserCommandHandler();
+	}
 }

+ 7 - 7
L2_GameServer/java/net/sf/l2j/gameserver/handler/VoicedCommandHandler.java

@@ -29,17 +29,11 @@ public class VoicedCommandHandler
 {
 	private static Logger _log = Logger.getLogger(ItemHandler.class.getName());
 	
-	private static VoicedCommandHandler _instance;
-	
 	private Map<String, IVoicedCommandHandler> _datatable;
 	
 	public static VoicedCommandHandler getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new VoicedCommandHandler();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private VoicedCommandHandler()
@@ -77,4 +71,10 @@ public class VoicedCommandHandler
 	{
 		return _datatable.size();
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final VoicedCommandHandler _instance = new VoicedCommandHandler();
+	}
 }

+ 244 - 239
L2_GameServer/java/net/sf/l2j/gameserver/idfactory/IdFactory.java

@@ -31,258 +31,263 @@ import net.sf.l2j.L2DatabaseFactory;
 public abstract class IdFactory
 {
 	private static Logger _log = Logger.getLogger(IdFactory.class.getName());
-
-	protected static final String[] ID_UPDATES =
-	{
-		"UPDATE items                 SET owner_id = ?    WHERE owner_id = ?",
-		"UPDATE items                 SET object_id = ?   WHERE object_id = ?",
-		"UPDATE character_quests      SET charId = ?     WHERE charId = ?",
-		"UPDATE character_friends     SET charId = ?     WHERE charId = ?",
-		"UPDATE character_friends     SET friendId = ?   WHERE friendId = ?",
-		"UPDATE character_hennas      SET charId = ? WHERE charId = ?",
-		"UPDATE character_recipebook  SET charId = ? WHERE charId = ?",
-		"UPDATE character_shortcuts   SET charId = ? WHERE charId = ?",
-		"UPDATE character_shortcuts   SET shortcut_id = ? WHERE shortcut_id = ? AND type = 1", // items
-		"UPDATE character_macroses    SET charId = ? WHERE charId = ?",
-		"UPDATE character_skills      SET charId = ? WHERE charId = ?",
-		"UPDATE character_skills_save SET charId = ? WHERE charId = ?",
-		"UPDATE character_subclasses  SET charId = ? WHERE charId = ?",
-		"UPDATE characters            SET charId = ? WHERE charId = ?",
-		"UPDATE characters            SET clanid = ?      WHERE clanid = ?",
-		"UPDATE clan_data             SET clan_id = ?     WHERE clan_id = ?",
-		"UPDATE siege_clans           SET clan_id = ?     WHERE clan_id = ?",
-		"UPDATE clan_data             SET ally_id = ?     WHERE ally_id = ?",
-		"UPDATE clan_data             SET leader_id = ?   WHERE leader_id = ?",
-		"UPDATE pets                  SET item_obj_id = ? WHERE item_obj_id = ?",
-		"UPDATE character_hennas     SET charId = ? WHERE charId = ?",
-		"UPDATE itemsonground         SET object_id = ?   WHERE object_id = ?",
-		"UPDATE auction_bid          SET bidderId = ?      WHERE bidderId = ?",
-        "UPDATE auction_watch        SET charObjId = ?     WHERE charObjId = ?",
-        "UPDATE clanhall             SET ownerId = ?       WHERE ownerId = ?"
+	
+	protected static final String[] ID_UPDATES = {
+			"UPDATE items                 SET owner_id = ?    WHERE owner_id = ?",
+			"UPDATE items                 SET object_id = ?   WHERE object_id = ?",
+			"UPDATE character_quests      SET charId = ?     WHERE charId = ?",
+			"UPDATE character_friends     SET charId = ?     WHERE charId = ?",
+			"UPDATE character_friends     SET friendId = ?   WHERE friendId = ?",
+			"UPDATE character_hennas      SET charId = ? WHERE charId = ?",
+			"UPDATE character_recipebook  SET charId = ? WHERE charId = ?",
+			"UPDATE character_shortcuts   SET charId = ? WHERE charId = ?",
+			"UPDATE character_shortcuts   SET shortcut_id = ? WHERE shortcut_id = ? AND type = 1", // items
+			"UPDATE character_macroses    SET charId = ? WHERE charId = ?", "UPDATE character_skills      SET charId = ? WHERE charId = ?",
+			"UPDATE character_skills_save SET charId = ? WHERE charId = ?", "UPDATE character_subclasses  SET charId = ? WHERE charId = ?",
+			"UPDATE characters            SET charId = ? WHERE charId = ?",
+			"UPDATE characters            SET clanid = ?      WHERE clanid = ?",
+			"UPDATE clan_data             SET clan_id = ?     WHERE clan_id = ?",
+			"UPDATE siege_clans           SET clan_id = ?     WHERE clan_id = ?",
+			"UPDATE clan_data             SET ally_id = ?     WHERE ally_id = ?",
+			"UPDATE clan_data             SET leader_id = ?   WHERE leader_id = ?",
+			"UPDATE pets                  SET item_obj_id = ? WHERE item_obj_id = ?",
+			"UPDATE character_hennas     SET charId = ? WHERE charId = ?",
+			"UPDATE itemsonground         SET object_id = ?   WHERE object_id = ?",
+			"UPDATE auction_bid          SET bidderId = ?      WHERE bidderId = ?",
+			"UPDATE auction_watch        SET charObjId = ?     WHERE charObjId = ?",
+			"UPDATE clanhall             SET ownerId = ?       WHERE ownerId = ?"
 	};
-
-    protected static final String[] ID_CHECKS =
-	{
-		"SELECT owner_id    FROM items                 WHERE object_id >= ?   AND object_id < ?",
-		"SELECT object_id   FROM items                 WHERE object_id >= ?   AND object_id < ?",
-		"SELECT charId     FROM character_quests      WHERE charId >= ?     AND charId < ?",
-		"SELECT charId     FROM character_friends     WHERE charId >= ?     AND charId < ?",
-		"SELECT charId     FROM character_friends     WHERE friendId >= ?   AND friendId < ?",
-		"SELECT charId     FROM character_hennas      WHERE charId >= ? AND charId < ?",
-		"SELECT charId     FROM character_recipebook  WHERE charId >= ?     AND charId < ?",
-		"SELECT charId     FROM character_shortcuts   WHERE charId >= ? AND charId < ?",
-		"SELECT charId     FROM character_macroses    WHERE charId >= ? AND charId < ?",
-		"SELECT charId     FROM character_skills      WHERE charId >= ? AND charId < ?",
-		"SELECT charId     FROM character_skills_save WHERE charId >= ? AND charId < ?",
-		"SELECT charId     FROM character_subclasses  WHERE charId >= ? AND charId < ?",
-		"SELECT charId      FROM characters            WHERE charId >= ?      AND charId < ?",
-		"SELECT clanid      FROM characters            WHERE clanid >= ?      AND clanid < ?",
-		"SELECT clan_id     FROM clan_data             WHERE clan_id >= ?     AND clan_id < ?",
-		"SELECT clan_id     FROM siege_clans           WHERE clan_id >= ?     AND clan_id < ?",
-		"SELECT ally_id     FROM clan_data             WHERE ally_id >= ?     AND ally_id < ?",
-		"SELECT leader_id   FROM clan_data             WHERE leader_id >= ?   AND leader_id < ?",
-		"SELECT item_obj_id FROM pets                  WHERE item_obj_id >= ? AND item_obj_id < ?",
-		"SELECT object_id   FROM itemsonground        WHERE object_id >= ?   AND object_id < ?"
+	
+	protected static final String[] ID_CHECKS = {
+			"SELECT owner_id    FROM items                 WHERE object_id >= ?   AND object_id < ?",
+			"SELECT object_id   FROM items                 WHERE object_id >= ?   AND object_id < ?",
+			"SELECT charId     FROM character_quests      WHERE charId >= ?     AND charId < ?",
+			"SELECT charId     FROM character_friends     WHERE charId >= ?     AND charId < ?",
+			"SELECT charId     FROM character_friends     WHERE friendId >= ?   AND friendId < ?",
+			"SELECT charId     FROM character_hennas      WHERE charId >= ? AND charId < ?",
+			"SELECT charId     FROM character_recipebook  WHERE charId >= ?     AND charId < ?",
+			"SELECT charId     FROM character_shortcuts   WHERE charId >= ? AND charId < ?",
+			"SELECT charId     FROM character_macroses    WHERE charId >= ? AND charId < ?",
+			"SELECT charId     FROM character_skills      WHERE charId >= ? AND charId < ?",
+			"SELECT charId     FROM character_skills_save WHERE charId >= ? AND charId < ?",
+			"SELECT charId     FROM character_subclasses  WHERE charId >= ? AND charId < ?",
+			"SELECT charId      FROM characters            WHERE charId >= ?      AND charId < ?",
+			"SELECT clanid      FROM characters            WHERE clanid >= ?      AND clanid < ?",
+			"SELECT clan_id     FROM clan_data             WHERE clan_id >= ?     AND clan_id < ?",
+			"SELECT clan_id     FROM siege_clans           WHERE clan_id >= ?     AND clan_id < ?",
+			"SELECT ally_id     FROM clan_data             WHERE ally_id >= ?     AND ally_id < ?",
+			"SELECT leader_id   FROM clan_data             WHERE leader_id >= ?   AND leader_id < ?",
+			"SELECT item_obj_id FROM pets                  WHERE item_obj_id >= ? AND item_obj_id < ?",
+			"SELECT object_id   FROM itemsonground        WHERE object_id >= ?   AND object_id < ?"
 	};
-
-    protected boolean _initialized;
-
-    public static final int FIRST_OID            = 0x10000000;
-    public static final int LAST_OID             = 0x7FFFFFFF;
-    public static final int FREE_OBJECT_ID_SIZE  = LAST_OID - FIRST_OID;
-
-    protected static IdFactory _instance = null;
-
+	
+	protected boolean _initialized;
+	
+	public static final int FIRST_OID = 0x10000000;
+	public static final int LAST_OID = 0x7FFFFFFF;
+	public static final int FREE_OBJECT_ID_SIZE = LAST_OID - FIRST_OID;
+	
+	protected static final IdFactory _instance;
+	
 	protected IdFactory()
 	{
-        setAllCharacterOffline();
-        cleanUpDB();
-    }
-
-    static
-    {
-        switch (Config.IDFACTORY_TYPE)
-        {
-            case Compaction:
-                _instance   = new CompactionIDFactory();
-                break;
-            case BitSet:
-                _instance   = new BitSetIDFactory();
-                break;
-            case Stack:
-                _instance   = new StackIDFactory();
-                break;
-        }
-    }
-
-    /**
-     * Sets all character offline
-     */
-    private void setAllCharacterOffline()
-    {
-        Connection con = null;
-        try
-        {
-        	con = L2DatabaseFactory.getInstance().getConnection();
-            Statement statement = con.createStatement();
-            statement.executeUpdate("UPDATE characters SET online = 0");
-            statement.close();
-            
-            _log.info("Updated characters online status.");
-        }
-        catch (SQLException e)
-        {
-        }
-        finally
-        {
-            try
-            {
-                con.close();
-            }
-            catch (Exception e)
-            {
-            }
-        }
-    }
-
-    /**
-     * Cleans up Database
-     */
-    private void cleanUpDB()
-    {
-        Connection con = null;
-        try
-        {
-            int cleanCount = 0;
-            con = L2DatabaseFactory.getInstance().getConnection();
-            Statement stmt = con.createStatement();
-            //Character related
-            cleanCount += stmt.executeUpdate("DELETE FROM character_friends WHERE character_friends.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_hennas WHERE character_hennas.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_macroses WHERE character_macroses.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_quests WHERE character_quests.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_recipebook WHERE character_recipebook.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_shortcuts WHERE character_shortcuts.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_skills WHERE character_skills.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_skills_save WHERE character_skills_save.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM character_subclasses WHERE character_subclasses.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM cursed_weapons WHERE cursed_weapons.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM heroes WHERE heroes.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM olympiad_nobles WHERE olympiad_nobles.charId NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM pets WHERE pets.item_obj_id NOT IN (SELECT object_id FROM items);");
-            cleanCount += stmt.executeUpdate("DELETE FROM seven_signs WHERE seven_signs.charId NOT IN (SELECT charId FROM characters);");
-            //Auction
-            // cleanCount += stmt.executeUpdate("DELETE FROM auction WHERE auction.id IN (SELECT id FROM clanhall WHERE ownerId <> 0);");
-            // cleanCount += stmt.executeUpdate("DELETE FROM auction_bid WHERE auctionId IN (SELECT id FROM clanhall WHERE ownerId <> 0)");
-            //Clan related
-            stmt.executeUpdate("UPDATE clan_data SET auction_bid_at = 0 WHERE auction_bid_at NOT IN (SELECT auctionId FROM auction_bid);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_data WHERE clan_data.leader_id NOT IN (SELECT charId FROM characters);");
-            cleanCount += stmt.executeUpdate("DELETE FROM auction_bid WHERE auction_bid.bidderId NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clanhall_functions WHERE clanhall_functions.hall_id NOT IN (SELECT id FROM clanhall WHERE ownerId <> 0);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_privs WHERE clan_privs.clan_id NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_skills WHERE clan_skills.clan_id NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_subpledges WHERE clan_subpledges.clan_id NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_wars WHERE clan_wars.clan1 NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_wars WHERE clan_wars.clan2 NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM siege_clans WHERE siege_clans.clan_id NOT IN (SELECT clan_id FROM clan_data);");
-            cleanCount += stmt.executeUpdate("DELETE FROM clan_notices WHERE clan_notices.clan_id NOT IN (SELECT clan_id FROM clan_data);");
-            stmt.executeUpdate("UPDATE castle SET taxpercent=0 WHERE castle.id NOT IN (SELECT hasCastle FROM clan_data);");
-            //Character & clan related
-            cleanCount += stmt.executeUpdate("DELETE FROM items WHERE items.owner_id NOT IN (SELECT charId FROM characters) AND items.owner_id NOT IN (SELECT clan_id FROM clan_data);");
-            stmt.executeUpdate("UPDATE characters SET clanid=0 WHERE characters.clanid NOT IN (SELECT clan_id FROM clan_data);");
-            stmt.executeUpdate("UPDATE clan_subpledges SET leader_id=0 WHERE clan_subpledges.leader_id NOT IN (SELECT charId FROM characters) AND leader_id > 0;");
-            //Forum related
-            cleanCount += stmt.executeUpdate("DELETE FROM forums WHERE forums.forum_owner_id NOT IN (SELECT clan_id FROM clan_data) AND forums.forum_parent=2;");
-            cleanCount += stmt.executeUpdate("DELETE FROM topic WHERE topic.topic_forum_id NOT IN (SELECT forum_id FROM forums);");
-            cleanCount += stmt.executeUpdate("DELETE FROM posts WHERE posts.post_forum_id NOT IN (SELECT forum_id FROM forums);");
-
-            stmt.close();
-            _log.info("Cleaned " + cleanCount + " elements from database.");
-        }
-        catch (SQLException e)
-        {
-        }
-        finally
-        {
-            try
-            {
-                con.close();
-            }
-            catch (Exception e)
-            {
-            }
-        }
-    }
-
-    /**
-     * @param con
-     * @return
-     * @throws SQLException
-     */
-    protected int[] extractUsedObjectIDTable() throws SQLException
-    {
-        Connection con = null;
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-
-            //create a temporary table
-            Statement statement = con.createStatement();
-
-            statement.executeUpdate("DROP TABLE IF EXISTS temporaryObjectTable");
-            statement.executeUpdate("DELETE FROM itemsonground WHERE object_id IN (SELECT object_id FROM items)");
-            statement.executeUpdate("CREATE TABLE temporaryObjectTable" + " (object_id int NOT NULL PRIMARY KEY)");
-
-            statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT charId FROM characters");
-            statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT object_id FROM items");
-            statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT clan_id FROM clan_data");
-            //statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT crest_id FROM clan_data WHERE crest_id > 0");
-            statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT object_id FROM itemsonground");
-
-            ResultSet result = statement.executeQuery("SELECT COUNT(object_id) FROM temporaryObjectTable");
-
-            result.next();
-            int size = result.getInt(1);
-            result.close();
-            int[] tmp_obj_ids = new int[size];
-            //_log.info("tmp table size: " + tmp_obj_ids.length);
-
-            result = statement.executeQuery("SELECT object_id FROM temporaryObjectTable ORDER BY object_id");
-
-            int idx = 0;
-            while (result.next())
-            {
-                tmp_obj_ids[idx++] = result.getInt(1);
-            }
-
-            result.close();
-            statement.close();
-
-            return tmp_obj_ids;
-        }
-        finally
-        {
-            try { con.close(); } catch (Exception e) {}
-        }
-    }
-
-	public boolean isInitialized() {
+		setAllCharacterOffline();
+		cleanUpDB();
+	}
+	
+	static
+	{
+		switch (Config.IDFACTORY_TYPE)
+		{
+			case Compaction:
+				_instance = new CompactionIDFactory();
+				break;
+			case BitSet:
+				_instance = new BitSetIDFactory();
+				break;
+			case Stack:
+				_instance = new StackIDFactory();
+				break;
+			default:
+				_instance = null;
+				break;
+		}
+	}
+	
+	/**
+	 * Sets all character offline
+	 */
+	private void setAllCharacterOffline()
+	{
+		Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			Statement statement = con.createStatement();
+			statement.executeUpdate("UPDATE characters SET online = 0");
+			statement.close();
+			
+			_log.info("Updated characters online status.");
+		}
+		catch (SQLException e)
+		{
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	/**
+	 * Cleans up Database
+	 */
+	private void cleanUpDB()
+	{
+		Connection con = null;
+		try
+		{
+			int cleanCount = 0;
+			con = L2DatabaseFactory.getInstance().getConnection();
+			Statement stmt = con.createStatement();
+			//Character related
+			cleanCount += stmt.executeUpdate("DELETE FROM character_friends WHERE character_friends.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_hennas WHERE character_hennas.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_macroses WHERE character_macroses.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_quests WHERE character_quests.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_recipebook WHERE character_recipebook.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_shortcuts WHERE character_shortcuts.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_skills WHERE character_skills.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_skills_save WHERE character_skills_save.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM character_subclasses WHERE character_subclasses.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM cursed_weapons WHERE cursed_weapons.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM heroes WHERE heroes.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM olympiad_nobles WHERE olympiad_nobles.charId NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM pets WHERE pets.item_obj_id NOT IN (SELECT object_id FROM items);");
+			cleanCount += stmt.executeUpdate("DELETE FROM seven_signs WHERE seven_signs.charId NOT IN (SELECT charId FROM characters);");
+			//Auction
+			// cleanCount += stmt.executeUpdate("DELETE FROM auction WHERE auction.id IN (SELECT id FROM clanhall WHERE ownerId <> 0);");
+			// cleanCount += stmt.executeUpdate("DELETE FROM auction_bid WHERE auctionId IN (SELECT id FROM clanhall WHERE ownerId <> 0)");
+			//Clan related
+			stmt.executeUpdate("UPDATE clan_data SET auction_bid_at = 0 WHERE auction_bid_at NOT IN (SELECT auctionId FROM auction_bid);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_data WHERE clan_data.leader_id NOT IN (SELECT charId FROM characters);");
+			cleanCount += stmt.executeUpdate("DELETE FROM auction_bid WHERE auction_bid.bidderId NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clanhall_functions WHERE clanhall_functions.hall_id NOT IN (SELECT id FROM clanhall WHERE ownerId <> 0);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_privs WHERE clan_privs.clan_id NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_skills WHERE clan_skills.clan_id NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_subpledges WHERE clan_subpledges.clan_id NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_wars WHERE clan_wars.clan1 NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_wars WHERE clan_wars.clan2 NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM siege_clans WHERE siege_clans.clan_id NOT IN (SELECT clan_id FROM clan_data);");
+			cleanCount += stmt.executeUpdate("DELETE FROM clan_notices WHERE clan_notices.clan_id NOT IN (SELECT clan_id FROM clan_data);");
+			stmt.executeUpdate("UPDATE castle SET taxpercent=0 WHERE castle.id NOT IN (SELECT hasCastle FROM clan_data);");
+			//Character & clan related
+			cleanCount += stmt.executeUpdate("DELETE FROM items WHERE items.owner_id NOT IN (SELECT charId FROM characters) AND items.owner_id NOT IN (SELECT clan_id FROM clan_data);");
+			stmt.executeUpdate("UPDATE characters SET clanid=0 WHERE characters.clanid NOT IN (SELECT clan_id FROM clan_data);");
+			stmt.executeUpdate("UPDATE clan_subpledges SET leader_id=0 WHERE clan_subpledges.leader_id NOT IN (SELECT charId FROM characters) AND leader_id > 0;");
+			//Forum related
+			cleanCount += stmt.executeUpdate("DELETE FROM forums WHERE forums.forum_owner_id NOT IN (SELECT clan_id FROM clan_data) AND forums.forum_parent=2;");
+			cleanCount += stmt.executeUpdate("DELETE FROM topic WHERE topic.topic_forum_id NOT IN (SELECT forum_id FROM forums);");
+			cleanCount += stmt.executeUpdate("DELETE FROM posts WHERE posts.post_forum_id NOT IN (SELECT forum_id FROM forums);");
+			
+			stmt.close();
+			_log.info("Cleaned " + cleanCount + " elements from database.");
+		}
+		catch (SQLException e)
+		{
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	/**
+	 * @param con
+	 * @return
+	 * @throws SQLException
+	 */
+	protected int[] extractUsedObjectIDTable() throws SQLException
+	{
+		Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			//create a temporary table
+			Statement statement = con.createStatement();
+			
+			statement.executeUpdate("DROP TABLE IF EXISTS temporaryObjectTable");
+			statement.executeUpdate("DELETE FROM itemsonground WHERE object_id IN (SELECT object_id FROM items)");
+			statement.executeUpdate("CREATE TABLE temporaryObjectTable" + " (object_id int NOT NULL PRIMARY KEY)");
+			
+			statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT charId FROM characters");
+			statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT object_id FROM items");
+			statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT clan_id FROM clan_data");
+			//statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT crest_id FROM clan_data WHERE crest_id > 0");
+			statement.executeUpdate("INSERT INTO temporaryObjectTable (object_id)" + " SELECT object_id FROM itemsonground");
+			
+			ResultSet result = statement.executeQuery("SELECT COUNT(object_id) FROM temporaryObjectTable");
+			
+			result.next();
+			int size = result.getInt(1);
+			result.close();
+			int[] tmp_obj_ids = new int[size];
+			//_log.info("tmp table size: " + tmp_obj_ids.length);
+			
+			result = statement.executeQuery("SELECT object_id FROM temporaryObjectTable ORDER BY object_id");
+			
+			int idx = 0;
+			while (result.next())
+			{
+				tmp_obj_ids[idx++] = result.getInt(1);
+			}
+			
+			result.close();
+			statement.close();
+			
+			return tmp_obj_ids;
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	public boolean isInitialized()
+	{
 		return _initialized;
 	}
-
+	
 	public static IdFactory getInstance()
 	{
-        return _instance;
+		return _instance;
 	}
-
-
+	
 	public abstract int getNextId();
-
+	
 	/**
 	 * return a used Object ID back to the pool
 	 * @param object ID
 	 */
 	public abstract void releaseId(int id);
-
-    public abstract int size();
+	
+	public abstract int size();
 }

+ 50 - 32
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/AuctionManager.java

@@ -28,47 +28,59 @@ import net.sf.l2j.gameserver.model.entity.Auction;
 public class AuctionManager
 {
 	protected static final Logger _log = Logger.getLogger(AuctionManager.class.getName());
-	private static AuctionManager _instance;
 	private List<Auction> _auctions;
-	private static final String[] ITEM_INIT_DATA =
-	{
-		"(23, 0, 'NPC', 'NPC Clan', 'ClanHall', 23, 0, 'Onyx Hall', 1, 20000000, 0, 1164841200000)", "(24, 0, 'NPC', 'NPC Clan', 'ClanHall', 24, 0, 'Topaz Hall', 1, 20000000, 0, 1164841200000)",
-		"(25, 0, 'NPC', 'NPC Clan', 'ClanHall', 25, 0, 'Ruby Hall', 1, 20000000, 0, 1164841200000)", "(26, 0, 'NPC', 'NPC Clan', 'ClanHall', 26, 0, 'Crystal Hall', 1, 20000000, 0, 1164841200000)",
-		"(27, 0, 'NPC', 'NPC Clan', 'ClanHall', 27, 0, 'Onyx Hall', 1, 20000000, 0, 1164841200000)", "(28, 0, 'NPC', 'NPC Clan', 'ClanHall', 28, 0, 'Sapphire Hall', 1, 20000000, 0, 1164841200000)",
-		"(29, 0, 'NPC', 'NPC Clan', 'ClanHall', 29, 0, 'Moonstone Hall', 1, 20000000, 0, 1164841200000)", "(30, 0, 'NPC', 'NPC Clan', 'ClanHall', 30, 0, 'Emerald Hall', 1, 20000000, 0, 1164841200000)",
-		"(31, 0, 'NPC', 'NPC Clan', 'ClanHall', 31, 0, 'The Atramental Barracks', 1, 8000000, 0, 1164841200000)", "(32, 0, 'NPC', 'NPC Clan', 'ClanHall', 32, 0, 'The Scarlet Barracks', 1, 8000000, 0, 1164841200000)",
-		"(33, 0, 'NPC', 'NPC Clan', 'ClanHall', 33, 0, 'The Viridian Barracks', 1, 8000000, 0, 1164841200000)", "(36, 0, 'NPC', 'NPC Clan', 'ClanHall', 36, 0, 'The Golden Chamber', 1, 50000000, 0, 1164841200000)",
-		"(37, 0, 'NPC', 'NPC Clan', 'ClanHall', 37, 0, 'The Silver Chamber', 1, 50000000, 0, 1164841200000)", "(38, 0, 'NPC', 'NPC Clan', 'ClanHall', 38, 0, 'The Mithril Chamber', 1, 50000000, 0, 1164841200000)",
-		"(39, 0, 'NPC', 'NPC Clan', 'ClanHall', 39, 0, 'Silver Manor', 1, 50000000, 0, 1164841200000)", "(40, 0, 'NPC', 'NPC Clan', 'ClanHall', 40, 0, 'Gold Manor', 1, 50000000, 0, 1164841200000)",
-		"(41, 0, 'NPC', 'NPC Clan', 'ClanHall', 41, 0, 'The Bronze Chamber', 1, 50000000, 0, 1164841200000)", "(42, 0, 'NPC', 'NPC Clan', 'ClanHall', 42, 0, 'The Golden Chamber', 1, 50000000, 0, 1164841200000)",
-		"(43, 0, 'NPC', 'NPC Clan', 'ClanHall', 43, 0, 'The Silver Chamber', 1, 50000000, 0, 1164841200000)", "(44, 0, 'NPC', 'NPC Clan', 'ClanHall', 44, 0, 'The Mithril Chamber', 1, 50000000, 0, 1164841200000)",
-		"(45, 0, 'NPC', 'NPC Clan', 'ClanHall', 45, 0, 'The Bronze Chamber', 1, 50000000, 0, 1164841200000)", "(46, 0, 'NPC', 'NPC Clan', 'ClanHall', 46, 0, 'Silver Manor', 1, 50000000, 0, 1164841200000)",
-		"(47, 0, 'NPC', 'NPC Clan', 'ClanHall', 47, 0, 'Moonstone Hall', 1, 50000000, 0, 1164841200000)", "(48, 0, 'NPC', 'NPC Clan', 'ClanHall', 48, 0, 'Onyx Hall', 1, 50000000, 0, 1164841200000)",
-		"(49, 0, 'NPC', 'NPC Clan', 'ClanHall', 49, 0, 'Emerald Hall', 1, 50000000, 0, 1164841200000)", "(50, 0, 'NPC', 'NPC Clan', 'ClanHall', 50, 0, 'Sapphire Hall', 1, 50000000, 0, 1164841200000)",
-		"(51, 0, 'NPC', 'NPC Clan', 'ClanHall', 51, 0, 'Mont Chamber', 1, 50000000, 0, 1164841200000)", "(52, 0, 'NPC', 'NPC Clan', 'ClanHall', 52, 0, 'Astaire Chamber', 1, 50000000, 0, 1164841200000)",
-		"(53, 0, 'NPC', 'NPC Clan', 'ClanHall', 53, 0, 'Aria Chamber', 1, 50000000, 0, 1164841200000)", "(54, 0, 'NPC', 'NPC Clan', 'ClanHall', 54, 0, 'Yiana Chamber', 1, 50000000, 0, 1164841200000)",
-		"(55, 0, 'NPC', 'NPC Clan', 'ClanHall', 55, 0, 'Roien Chamber', 1, 50000000, 0, 1164841200000)", "(56, 0, 'NPC', 'NPC Clan', 'ClanHall', 56, 0, 'Luna Chamber', 1, 50000000, 0, 1164841200000)",
-		"(57, 0, 'NPC', 'NPC Clan', 'ClanHall', 57, 0, 'Traban Chamber', 1, 50000000, 0, 1164841200000)", "(58, 0, 'NPC', 'NPC Clan', 'ClanHall', 58, 0, 'Eisen Hall', 1, 50000000, 0, 1164841200000)",
-		"(59, 0, 'NPC', 'NPC Clan', 'ClanHall', 59, 0, 'Heavy Metal Hall', 1, 50000000, 0, 1164841200000)", "(60, 0, 'NPC', 'NPC Clan', 'ClanHall', 60, 0, 'Molten Ore Hall', 1, 50000000, 0, 1164841200000)",
-		"(61, 0, 'NPC', 'NPC Clan', 'ClanHall', 61, 0, 'Titan Hall', 1, 50000000, 0, 1164841200000)"
+	private static final String[] ITEM_INIT_DATA = {
+			"(23, 0, 'NPC', 'NPC Clan', 'ClanHall', 23, 0, 'Onyx Hall', 1, 20000000, 0, 1164841200000)",
+			"(24, 0, 'NPC', 'NPC Clan', 'ClanHall', 24, 0, 'Topaz Hall', 1, 20000000, 0, 1164841200000)",
+			"(25, 0, 'NPC', 'NPC Clan', 'ClanHall', 25, 0, 'Ruby Hall', 1, 20000000, 0, 1164841200000)",
+			"(26, 0, 'NPC', 'NPC Clan', 'ClanHall', 26, 0, 'Crystal Hall', 1, 20000000, 0, 1164841200000)",
+			"(27, 0, 'NPC', 'NPC Clan', 'ClanHall', 27, 0, 'Onyx Hall', 1, 20000000, 0, 1164841200000)",
+			"(28, 0, 'NPC', 'NPC Clan', 'ClanHall', 28, 0, 'Sapphire Hall', 1, 20000000, 0, 1164841200000)",
+			"(29, 0, 'NPC', 'NPC Clan', 'ClanHall', 29, 0, 'Moonstone Hall', 1, 20000000, 0, 1164841200000)",
+			"(30, 0, 'NPC', 'NPC Clan', 'ClanHall', 30, 0, 'Emerald Hall', 1, 20000000, 0, 1164841200000)",
+			"(31, 0, 'NPC', 'NPC Clan', 'ClanHall', 31, 0, 'The Atramental Barracks', 1, 8000000, 0, 1164841200000)",
+			"(32, 0, 'NPC', 'NPC Clan', 'ClanHall', 32, 0, 'The Scarlet Barracks', 1, 8000000, 0, 1164841200000)",
+			"(33, 0, 'NPC', 'NPC Clan', 'ClanHall', 33, 0, 'The Viridian Barracks', 1, 8000000, 0, 1164841200000)",
+			"(36, 0, 'NPC', 'NPC Clan', 'ClanHall', 36, 0, 'The Golden Chamber', 1, 50000000, 0, 1164841200000)",
+			"(37, 0, 'NPC', 'NPC Clan', 'ClanHall', 37, 0, 'The Silver Chamber', 1, 50000000, 0, 1164841200000)",
+			"(38, 0, 'NPC', 'NPC Clan', 'ClanHall', 38, 0, 'The Mithril Chamber', 1, 50000000, 0, 1164841200000)",
+			"(39, 0, 'NPC', 'NPC Clan', 'ClanHall', 39, 0, 'Silver Manor', 1, 50000000, 0, 1164841200000)",
+			"(40, 0, 'NPC', 'NPC Clan', 'ClanHall', 40, 0, 'Gold Manor', 1, 50000000, 0, 1164841200000)",
+			"(41, 0, 'NPC', 'NPC Clan', 'ClanHall', 41, 0, 'The Bronze Chamber', 1, 50000000, 0, 1164841200000)",
+			"(42, 0, 'NPC', 'NPC Clan', 'ClanHall', 42, 0, 'The Golden Chamber', 1, 50000000, 0, 1164841200000)",
+			"(43, 0, 'NPC', 'NPC Clan', 'ClanHall', 43, 0, 'The Silver Chamber', 1, 50000000, 0, 1164841200000)",
+			"(44, 0, 'NPC', 'NPC Clan', 'ClanHall', 44, 0, 'The Mithril Chamber', 1, 50000000, 0, 1164841200000)",
+			"(45, 0, 'NPC', 'NPC Clan', 'ClanHall', 45, 0, 'The Bronze Chamber', 1, 50000000, 0, 1164841200000)",
+			"(46, 0, 'NPC', 'NPC Clan', 'ClanHall', 46, 0, 'Silver Manor', 1, 50000000, 0, 1164841200000)",
+			"(47, 0, 'NPC', 'NPC Clan', 'ClanHall', 47, 0, 'Moonstone Hall', 1, 50000000, 0, 1164841200000)",
+			"(48, 0, 'NPC', 'NPC Clan', 'ClanHall', 48, 0, 'Onyx Hall', 1, 50000000, 0, 1164841200000)",
+			"(49, 0, 'NPC', 'NPC Clan', 'ClanHall', 49, 0, 'Emerald Hall', 1, 50000000, 0, 1164841200000)",
+			"(50, 0, 'NPC', 'NPC Clan', 'ClanHall', 50, 0, 'Sapphire Hall', 1, 50000000, 0, 1164841200000)",
+			"(51, 0, 'NPC', 'NPC Clan', 'ClanHall', 51, 0, 'Mont Chamber', 1, 50000000, 0, 1164841200000)",
+			"(52, 0, 'NPC', 'NPC Clan', 'ClanHall', 52, 0, 'Astaire Chamber', 1, 50000000, 0, 1164841200000)",
+			"(53, 0, 'NPC', 'NPC Clan', 'ClanHall', 53, 0, 'Aria Chamber', 1, 50000000, 0, 1164841200000)",
+			"(54, 0, 'NPC', 'NPC Clan', 'ClanHall', 54, 0, 'Yiana Chamber', 1, 50000000, 0, 1164841200000)",
+			"(55, 0, 'NPC', 'NPC Clan', 'ClanHall', 55, 0, 'Roien Chamber', 1, 50000000, 0, 1164841200000)",
+			"(56, 0, 'NPC', 'NPC Clan', 'ClanHall', 56, 0, 'Luna Chamber', 1, 50000000, 0, 1164841200000)",
+			"(57, 0, 'NPC', 'NPC Clan', 'ClanHall', 57, 0, 'Traban Chamber', 1, 50000000, 0, 1164841200000)",
+			"(58, 0, 'NPC', 'NPC Clan', 'ClanHall', 58, 0, 'Eisen Hall', 1, 50000000, 0, 1164841200000)",
+			"(59, 0, 'NPC', 'NPC Clan', 'ClanHall', 59, 0, 'Heavy Metal Hall', 1, 50000000, 0, 1164841200000)",
+			"(60, 0, 'NPC', 'NPC Clan', 'ClanHall', 60, 0, 'Molten Ore Hall', 1, 50000000, 0, 1164841200000)",
+			"(61, 0, 'NPC', 'NPC Clan', 'ClanHall', 61, 0, 'Titan Hall', 1, 50000000, 0, 1164841200000)"
 	};
-	private static final Integer[] ItemInitDataId =
-	{
-		23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
+	private static final Integer[] ItemInitDataId = {
+			23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, 41, 42,
+			43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
 	};
 	
 	public static final AuctionManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_log.info("Initializing AuctionManager");
-			_instance = new AuctionManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
-	public AuctionManager()
+	private AuctionManager()
 	{
+		_log.info("Initializing AuctionManager");
 		_auctions = new FastList<Auction>();
 		load();
 	}
@@ -176,4 +188,10 @@ public class AuctionManager
 			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AuctionManager _instance = new AuctionManager();
+	}
 }

+ 10 - 11
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/BoatManager.java

@@ -34,18 +34,9 @@ public class BoatManager
 {
 	private static final Logger _log = Logger.getLogger(BoatManager.class.getName());
 	
-	// =========================================================
-	private static BoatManager _instance;
-	
 	public static final BoatManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_log.info("Initializing BoatManager");
-			_instance = new BoatManager();
-			_instance.load();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	// =========================================================
@@ -59,8 +50,10 @@ public class BoatManager
 	
 	// =========================================================
 	// Constructor
-	public BoatManager()
+	private BoatManager()
 	{
+		_log.info("Initializing BoatManager");
+		load();
 	}
 	
 	// =========================================================
@@ -222,4 +215,10 @@ public class BoatManager
 			_staticItems = new FastMap<Integer, L2BoatInstance>();
 		return _staticItems.get(boatId);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final BoatManager _instance = new BoatManager();
+	}
 }

+ 205 - 185
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CastleManager.java

@@ -22,6 +22,7 @@ import java.util.logging.Logger;
 
 import javolution.util.FastList;
 import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.InstanceListManager;
 import net.sf.l2j.gameserver.SevenSigns;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2ClanMember;
@@ -30,184 +31,143 @@ import net.sf.l2j.gameserver.model.L2Object;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.entity.Castle;
 
-
-public class CastleManager
+public class CastleManager implements InstanceListManager
 {
-    protected static final Logger _log = Logger.getLogger(CastleManager.class.getName());
-    // =========================================================
-    private static CastleManager _instance;
-    public static final CastleManager getInstance()
-    {
-        if (_instance == null)
-        {
-    		_log.info("Initializing CastleManager");
-            _instance = new CastleManager();
-            _instance.load();
-        }
-        return _instance;
-    }
-    // =========================================================
-
-
-    // =========================================================
-    // Data Field
-    private List<Castle> _castles;
-
-    // =========================================================
-    // Constructor
-    private static final int _castleCirclets[] = { 0, 6838, 6835, 6839, 6837, 6840, 6834, 6836, 8182, 8183 };
-    public CastleManager() {}
-
-    // =========================================================
-    // Method - Public
-
-    public final int findNearestCastleIndex(L2Object obj)
-    {
-        int index = getCastleIndex(obj);
-        if (index < 0)
-        {
-            double closestDistance = 99999999;
-            double distance;
-            Castle castle;
-            for (int i = 0; i < getCastles().size(); i++)
-            {
-                castle = getCastles().get(i);
-                if (castle == null) continue;
-                distance = castle.getDistance(obj);
-                if (closestDistance > distance)
-                {
-                    closestDistance = distance;
-                    index = i;
-                }
-            }
-        }
-        return index;
-    }
-
-    // =========================================================
-    // Method - Private
-    private final void load()
-    {
-        Connection con = null;
-        try
-        {
-            PreparedStatement statement;
-            ResultSet rs;
-
-            con = L2DatabaseFactory.getInstance().getConnection();
-
-            statement = con.prepareStatement("Select id from castle order by id");
-            rs = statement.executeQuery();
-
-            while (rs.next())
-            {
-                getCastles().add(new Castle(rs.getInt("id")));
-            }
-
-            statement.close();
-
-            _log.info("Loaded: " + getCastles().size() + " castles");
-        }
-        catch (Exception e)
-        {
-            _log.warning("Exception: loadCastleData(): " + e.getMessage());
-            e.printStackTrace();
-        }
-
-        finally
-        {
-            try
-            { 
-                con.close(); 
-            }
-            catch (Exception e)
-            {
-            }
-        }
-    }
-
-    // =========================================================
-    // Property - Public
-
-    public final Castle getCastleById(int castleId)
-    {
-    	for (Castle temp : getCastles())
-    	{
-    		if (temp.getCastleId() == castleId)
-    			return temp;
-    	}
-        return null;
-    }
-
-    public final Castle getCastleByOwner(L2Clan clan)
-    {
-    	for (Castle temp : getCastles())
-    	{
-    		if (temp.getOwnerId() == clan.getClanId())
-    			return temp;
-    	}
-        return null;
-    }
-
-    public final Castle getCastle(String name)
-    {
-    	for (Castle temp : getCastles())
-    	{
-    		if (temp.getName().equalsIgnoreCase(name.trim()))
-    			return temp;
-    	}
-        return null;
-    }
-
-    public final Castle getCastle(int x, int y, int z)
-    {
-    	for (Castle temp : getCastles())
-    	{
-    		if (temp.checkIfInZone(x, y, z))
-    			return temp;
-    	}
-        return null;
-    }
-
-    public final Castle getCastle(L2Object activeObject) { return getCastle(activeObject.getX(), activeObject.getY(), activeObject.getZ()); }
-
-    public final int getCastleIndex(int castleId)
-    {
-        Castle castle;
-        for (int i = 0; i < getCastles().size(); i++)
-        {
-            castle = getCastles().get(i);
-            if (castle != null && castle.getCastleId() == castleId) return i;
-        }
-        return -1;
-    }
-
-    public final int getCastleIndex(L2Object activeObject)
-    {
-    	return getCastleIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
-    }
-
-    public final int getCastleIndex(int x, int y, int z)
-    {
-        Castle castle;
-        for (int i = 0; i < getCastles().size(); i++)
-        {
-            castle = getCastles().get(i);
-            if (castle != null && castle.checkIfInZone(x, y, z)) return i;
-        }
-        return -1;
-    }
-
-    public final List<Castle> getCastles()
-    {
-        if (_castles == null) _castles = new FastList<Castle>();
-        return _castles;
-    }
-
+	protected static final Logger _log = Logger.getLogger(CastleManager.class.getName());
+	
+	public static final CastleManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	// =========================================================
+	
+	// =========================================================
+	// Data Field
+	private List<Castle> _castles;
+	
+	// =========================================================
+	// Constructor
+	private static final int _castleCirclets[] = { 0, 6838, 6835, 6839, 6837, 6840, 6834, 6836, 8182, 8183 };
+	
+	private CastleManager()
+	{
+	}
+	
+	// =========================================================
+	// Method - Public
+	
+	public final int findNearestCastleIndex(L2Object obj)
+	{
+		int index = getCastleIndex(obj);
+		if (index < 0)
+		{
+			double closestDistance = 99999999;
+			double distance;
+			Castle castle;
+			for (int i = 0; i < getCastles().size(); i++)
+			{
+				castle = getCastles().get(i);
+				if (castle == null)
+					continue;
+				distance = castle.getDistance(obj);
+				if (closestDistance > distance)
+				{
+					closestDistance = distance;
+					index = i;
+				}
+			}
+		}
+		return index;
+	}
+	
+	// =========================================================
+	// Property - Public
+	
+	public final Castle getCastleById(int castleId)
+	{
+		for (Castle temp : getCastles())
+		{
+			if (temp.getCastleId() == castleId)
+				return temp;
+		}
+		return null;
+	}
+	
+	public final Castle getCastleByOwner(L2Clan clan)
+	{
+		for (Castle temp : getCastles())
+		{
+			if (temp.getOwnerId() == clan.getClanId())
+				return temp;
+		}
+		return null;
+	}
+	
+	public final Castle getCastle(String name)
+	{
+		for (Castle temp : getCastles())
+		{
+			if (temp.getName().equalsIgnoreCase(name.trim()))
+				return temp;
+		}
+		return null;
+	}
+	
+	public final Castle getCastle(int x, int y, int z)
+	{
+		for (Castle temp : getCastles())
+		{
+			if (temp.checkIfInZone(x, y, z))
+				return temp;
+		}
+		return null;
+	}
+	
+	public final Castle getCastle(L2Object activeObject)
+	{
+		return getCastle(activeObject.getX(), activeObject.getY(), activeObject.getZ());
+	}
+	
+	public final int getCastleIndex(int castleId)
+	{
+		Castle castle;
+		for (int i = 0; i < getCastles().size(); i++)
+		{
+			castle = getCastles().get(i);
+			if (castle != null && castle.getCastleId() == castleId)
+				return i;
+		}
+		return -1;
+	}
+	
+	public final int getCastleIndex(L2Object activeObject)
+	{
+		return getCastleIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
+	}
+	
+	public final int getCastleIndex(int x, int y, int z)
+	{
+		Castle castle;
+		for (int i = 0; i < getCastles().size(); i++)
+		{
+			castle = getCastles().get(i);
+			if (castle != null && castle.checkIfInZone(x, y, z))
+				return i;
+		}
+		return -1;
+	}
+	
+	public final List<Castle> getCastles()
+	{
+		if (_castles == null)
+			_castles = new FastList<Castle>();
+		return _castles;
+	}
+	
 	public final void validateTaxes(int sealStrifeOwner)
 	{
 		int maxTax;
-		switch(sealStrifeOwner)
+		switch (sealStrifeOwner)
 		{
 			case SevenSigns.CABAL_DUSK:
 				maxTax = 5;
@@ -219,37 +179,40 @@ public class CastleManager
 				maxTax = 15;
 				break;
 		}
-		for(Castle castle : _castles)
-			if(castle.getTaxPercent() > maxTax)
+		for (Castle castle : _castles)
+			if (castle.getTaxPercent() > maxTax)
 				castle.setTaxPercent(maxTax);
 	}
-
+	
 	int _castleId = 1; // from this castle
+	
 	public int getCirclet()
 	{
 		return getCircletByCastleId(_castleId);
 	}
-
+	
 	public int getCircletByCastleId(int castleId)
 	{
 		if (castleId > 0 && castleId < 10)
 			return _castleCirclets[castleId];
-
+		
 		return 0;
 	}
-
+	
 	// remove this castle's circlets from the clan
 	public void removeCirclet(L2Clan clan, int castleId)
 	{
 		for (L2ClanMember member : clan.getMembers())
 			removeCirclet(member, castleId);
 	}
+	
 	public void removeCirclet(L2ClanMember member, int castleId)
 	{
-		if (member == null) return;
+		if (member == null)
+			return;
 		L2PcInstance player = member.getPlayerInstance();
 		int circletId = getCircletByCastleId(castleId);
-
+		
 		if (circletId != 0)
 		{
 			// online-player circlet removal
@@ -284,14 +247,14 @@ public class CastleManager
 			}
 			catch (Exception e)
 			{
-				_log.warning("Failed to remove castle circlets offline for player "+member.getName());
+				_log.warning("Failed to remove castle circlets offline for player " + member.getName());
 				e.printStackTrace();
 			}
 			finally
 			{
 				try
-				{ 
-				    con.close(); 
+				{
+					con.close();
 				}
 				catch (Exception e)
 				{
@@ -299,4 +262,61 @@ public class CastleManager
 			}
 		}
 	}
+	
+	public void loadInstances()
+	{
+		_log.info("Initializing CastleManager");
+		Connection con = null;
+		try
+		{
+			PreparedStatement statement;
+			ResultSet rs;
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			statement = con.prepareStatement("SELECT id FROM castle ORDER BY id");
+			rs = statement.executeQuery();
+			
+			while (rs.next())
+			{
+				getCastles().add(new Castle(rs.getInt("id")));
+			}
+			
+			statement.close();
+			
+			_log.info("Loaded: " + getCastles().size() + " castles");
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: loadCastleData(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	public void updateReferences()
+	{
+	}
+	
+	public void activateInstances()
+	{
+		for (final Castle castle : _castles)
+		{
+			castle.activateInstance();
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CastleManager _instance = new CastleManager();
+	}
 }

+ 335 - 221
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CastleManorManager.java

@@ -43,161 +43,208 @@ import net.sf.l2j.util.Rnd;
  * @author l3x
  */
 
-public class CastleManorManager {
+public class CastleManorManager
+{
 	protected static final Logger _log = Logger.getLogger(CastleManorManager.class.getName());
-
-	private static CastleManorManager _instance;
-
+	
 	public static final int PERIOD_CURRENT = 0;
 	public static final int PERIOD_NEXT = 1;
-
-	private static final String CASTLE_MANOR_LOAD_PROCURE =
-											"SELECT * FROM castle_manor_procure WHERE castle_id=?";
-	private static final String CASTLE_MANOR_LOAD_PRODUCTION =
-											"SELECT * FROM castle_manor_production WHERE castle_id=?";
-
-	private static final int NEXT_PERIOD_APPROVE = Config.ALT_MANOR_APPROVE_TIME;       // 6:00
-	private static final int NEXT_PERIOD_APPROVE_MIN = Config.ALT_MANOR_APPROVE_MIN;    //
-    private static final int MANOR_REFRESH = Config.ALT_MANOR_REFRESH_TIME;             // 20:00
-    private static final int MANOR_REFRESH_MIN = Config.ALT_MANOR_REFRESH_MIN;          //
-    protected static final long MAINTENANCE_PERIOD = Config.ALT_MANOR_MAINTENANCE_PERIOD; // 6 mins
-
-    private Calendar _manorRefresh;
-    private Calendar _periodApprove;
-
-    private boolean _underMaintenance;
-    private boolean _disabled;
-
-    protected ScheduledFuture<?> _scheduledManorRefresh;
-    protected ScheduledFuture<?> _scheduledMaintenanceEnd;
-    protected ScheduledFuture<?> _scheduledNextPeriodapprove;
-
-	public static final CastleManorManager getInstance() {
-		if (_instance == null) {
-			_log.info("Initializing CastleManorManager");
-			_instance = new CastleManorManager();
-		}
-		return _instance;
+	
+	private static final String CASTLE_MANOR_LOAD_PROCURE = "SELECT * FROM castle_manor_procure WHERE castle_id=?";
+	private static final String CASTLE_MANOR_LOAD_PRODUCTION = "SELECT * FROM castle_manor_production WHERE castle_id=?";
+	
+	private static final int NEXT_PERIOD_APPROVE = Config.ALT_MANOR_APPROVE_TIME; // 6:00
+	private static final int NEXT_PERIOD_APPROVE_MIN = Config.ALT_MANOR_APPROVE_MIN; //
+	private static final int MANOR_REFRESH = Config.ALT_MANOR_REFRESH_TIME; // 20:00
+	private static final int MANOR_REFRESH_MIN = Config.ALT_MANOR_REFRESH_MIN; //
+	protected static final long MAINTENANCE_PERIOD = Config.ALT_MANOR_MAINTENANCE_PERIOD; // 6 mins
+	
+	private Calendar _manorRefresh;
+	private Calendar _periodApprove;
+	
+	private boolean _underMaintenance;
+	private boolean _disabled;
+	
+	protected ScheduledFuture<?> _scheduledManorRefresh;
+	protected ScheduledFuture<?> _scheduledMaintenanceEnd;
+	protected ScheduledFuture<?> _scheduledNextPeriodapprove;
+	
+	public static final CastleManorManager getInstance()
+	{
+		return SingletonHolder._instance;
 	}
-
-	public class CropProcure {
+	
+	public class CropProcure
+	{
 		int _cropId;
 		long _buyResidual;
 		int _rewardType;
 		long _buy;
 		long _price;
-
-		public CropProcure(int id) {
-			_cropId      = id;
+		
+		public CropProcure(int id)
+		{
+			_cropId = id;
 			_buyResidual = 0;
-			_rewardType  = 0;
-			_buy         = 0;
-			_price       = 0;
+			_rewardType = 0;
+			_buy = 0;
+			_price = 0;
 		}
-
-		public CropProcure(int id, long amount, int type, long buy, long price) {
-			_cropId      = id;
+		
+		public CropProcure(int id, long amount, int type, long buy, long price)
+		{
+			_cropId = id;
+			_buyResidual = amount;
+			_rewardType = type;
+			_buy = buy;
+			_price = price;
+		}
+		
+		public int getReward()
+		{
+			return _rewardType;
+		}
+		
+		public int getId()
+		{
+			return _cropId;
+		}
+		
+		public long getAmount()
+		{
+			return _buyResidual;
+		}
+		
+		public long getStartAmount()
+		{
+			return _buy;
+		}
+		
+		public long getPrice()
+		{
+			return _price;
+		}
+		
+		public void setAmount(long amount)
+		{
 			_buyResidual = amount;
-			_rewardType  = type;
-			_buy         = buy;
-			_price       = price;
 		}
-
-		public int getReward() { return _rewardType; }
-		public int getId() { return _cropId; }
-		public long getAmount() { return _buyResidual; }
-		public long getStartAmount() { return _buy; }
-		public long getPrice() { return _price; }
-
-		public void setAmount (long amount) { _buyResidual = amount; }
 	}
-
-	public class SeedProduction {
+	
+	public class SeedProduction
+	{
 		int _seedId;
 		long _residual;
 		long _price;
 		long _sales;
-
-		public SeedProduction(int id) {
+		
+		public SeedProduction(int id)
+		{
 			_seedId = id;
 			_sales = 0;
 			_price = 0;
 			_sales = 0;
 		}
-
-		public SeedProduction(int id, long amount, long price, long sales) {
+		
+		public SeedProduction(int id, long amount, long price, long sales)
+		{
 			_seedId = id;
 			_residual = amount;
 			_price = price;
 			_sales = sales;
 		}
-
-		public int getId() {return _seedId; }
-		public long getCanProduce() {return _residual; }
-		public long getPrice() {return _price; }
-		public long getStartProduce() { return _sales; }
-
-		public void setCanProduce(long amount){ _residual = amount; }
+		
+		public int getId()
+		{
+			return _seedId;
+		}
+		
+		public long getCanProduce()
+		{
+			return _residual;
+		}
+		
+		public long getPrice()
+		{
+			return _price;
+		}
+		
+		public long getStartProduce()
+		{
+			return _sales;
+		}
+		
+		public void setCanProduce(long amount)
+		{
+			_residual = amount;
+		}
 	}
-
-	private CastleManorManager() {
+	
+	private CastleManorManager()
+	{
+		_log.info("Initializing CastleManorManager");
 		load(); // load data from database
 		init(); // schedule all manor related events
 		_underMaintenance = false;
 		_disabled = !Config.ALLOW_MANOR;
-
+		
 		boolean isApproved;
 		if (_periodApprove.getTimeInMillis() > _manorRefresh.getTimeInMillis())
 			// Next approve period already scheduled
 			isApproved = (_manorRefresh.getTimeInMillis() > Calendar.getInstance().getTimeInMillis());
 		else
-			isApproved = (_periodApprove.getTimeInMillis() < Calendar.getInstance().getTimeInMillis() &&
-					_manorRefresh.getTimeInMillis() > Calendar.getInstance().getTimeInMillis());
-
-		for (Castle c: CastleManager.getInstance().getCastles()) {
+			isApproved = (_periodApprove.getTimeInMillis() < Calendar.getInstance().getTimeInMillis() && _manorRefresh.getTimeInMillis() > Calendar.getInstance().getTimeInMillis());
+		
+		for (Castle c : CastleManager.getInstance().getCastles())
+		{
 			c.setNextPeriodApproved(isApproved);
 		}
 	}
-
-	private void load() {
+	
+	private void load()
+	{
 		Connection con = null;
 		ResultSet rs;
 		PreparedStatement statement;
-		try {
+		try
+		{
 			// Get Connection
 			con = L2DatabaseFactory.getInstance().getConnection();
-			for (Castle castle : CastleManager.getInstance().getCastles()) {
+			for (Castle castle : CastleManager.getInstance().getCastles())
+			{
 				FastList<SeedProduction> production = new FastList<SeedProduction>();
 				FastList<SeedProduction> productionNext = new FastList<SeedProduction>();
 				FastList<CropProcure> procure = new FastList<CropProcure>();
 				FastList<CropProcure> procureNext = new FastList<CropProcure>();
-
+				
 				// restore seed production info
 				statement = con.prepareStatement(CASTLE_MANOR_LOAD_PRODUCTION);
 				statement.setInt(1, castle.getCastleId());
 				rs = statement.executeQuery();
-				while(rs.next()) {
+				while (rs.next())
+				{
 					int seedId = rs.getInt("seed_id");
 					int canProduce = rs.getInt("can_produce");
 					int startProduce = rs.getInt("start_produce");
 					int price = rs.getInt("seed_price");
 					int period = rs.getInt("period");
 					if (period == PERIOD_CURRENT)
-						production.add(new SeedProduction(seedId,canProduce,price,startProduce));
+						production.add(new SeedProduction(seedId, canProduce, price, startProduce));
 					else
-						productionNext.add(new SeedProduction(seedId,canProduce,price,startProduce));
+						productionNext.add(new SeedProduction(seedId, canProduce, price, startProduce));
 				}
 				rs.close();
 				statement.close();
-
+				
 				castle.setSeedProduction(production, PERIOD_CURRENT);
 				castle.setSeedProduction(productionNext, PERIOD_NEXT);
-
+				
 				// restore procure info
 				statement = con.prepareStatement(CASTLE_MANOR_LOAD_PROCURE);
 				statement.setInt(1, castle.getCastleId());
 				rs = statement.executeQuery();
-				while(rs.next()) {
+				while (rs.next())
+				{
 					int cropId = rs.getInt("crop_id");
 					int canBuy = rs.getInt("can_buy");
 					int startBuy = rs.getInt("start_buy");
@@ -211,276 +258,343 @@ public class CastleManorManager {
 				}
 				rs.close();
 				statement.close();
-
+				
 				castle.setCropProcure(procure, PERIOD_CURRENT);
 				castle.setCropProcure(procureNext, PERIOD_NEXT);
-
-				if (!procure.isEmpty() || !procureNext.isEmpty() ||
-						!production.isEmpty() || !productionNext.isEmpty())
+				
+				if (!procure.isEmpty() || !procureNext.isEmpty() || !production.isEmpty() || !productionNext.isEmpty())
 					_log.info(castle.getName() + ": Data loaded");
 			}
-		} catch (Exception e) {
-			_log.info("Error restoring manor data: " + e.getMessage() );
-		} finally {
-			try { con.close(); } catch (Exception e) {}
+		}
+		catch (Exception e)
+		{
+			_log.info("Error restoring manor data: " + e.getMessage());
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
 		}
 	}
-
-	protected void init() {
+	
+	protected void init()
+	{
 		_manorRefresh = Calendar.getInstance();
 		_manorRefresh.set(Calendar.HOUR_OF_DAY, MANOR_REFRESH);
 		_manorRefresh.set(Calendar.MINUTE, MANOR_REFRESH_MIN);
-
+		
 		_periodApprove = Calendar.getInstance();
 		_periodApprove.set(Calendar.HOUR_OF_DAY, NEXT_PERIOD_APPROVE);
 		_periodApprove.set(Calendar.MINUTE, NEXT_PERIOD_APPROVE_MIN);
-
+		
 		updateManorRefresh();
 		updatePeriodApprove();
-    }
-
-	public void updateManorRefresh() {
+	}
+	
+	public void updateManorRefresh()
+	{
 		if (Config.DEBUG)
 			_log.info("Manor System: Manor refresh updated");
 		
-		_scheduledManorRefresh = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable(){
-            public void run() {
-            	if (!isDisabled()) {
-	        		setUnderMaintenance(true);
-	            	_log.info("Manor System: Under maintenance mode started");
-
-	            	_scheduledMaintenanceEnd = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable(){
-	                    public void run() {
-	                        _log.info("Manor System: Next period started");
-	                        setNextPeriod();
-	                        try {
-	                            save();
-	                        } catch (Exception e) {
-	                            _log.info("Manor System: Failed to save manor data: " + e);
-	                        }
-	                        setUnderMaintenance(false);
-	                    }
-	                    }, MAINTENANCE_PERIOD);
-            	}
-                updateManorRefresh();
-            }
-            }, getMillisToManorRefresh());
-
-
+		_scheduledManorRefresh = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+			public void run()
+			{
+				if (!isDisabled())
+				{
+					setUnderMaintenance(true);
+					_log.info("Manor System: Under maintenance mode started");
+					
+					_scheduledMaintenanceEnd = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+						public void run()
+						{
+							_log.info("Manor System: Next period started");
+							setNextPeriod();
+							try
+							{
+								save();
+							}
+							catch (Exception e)
+							{
+								_log.info("Manor System: Failed to save manor data: " + e);
+							}
+							setUnderMaintenance(false);
+						}
+					}, MAINTENANCE_PERIOD);
+				}
+				updateManorRefresh();
+			}
+		}, getMillisToManorRefresh());
+		
 	}
-
-	public void updatePeriodApprove() {
+	
+	public void updatePeriodApprove()
+	{
 		_log.info("Manor System: Manor period approve updated");
-		_scheduledNextPeriodapprove = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable(){
-            public void run() {
-            	if (!isDisabled()) {
-            		approveNextPeriod();
-            		_log.info("Manor System: Next period approved");
-            	}
-            	updatePeriodApprove();
-            }
-            }, getMillisToNextPeriodApprove());
+		_scheduledNextPeriodapprove = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+			public void run()
+			{
+				if (!isDisabled())
+				{
+					approveNextPeriod();
+					_log.info("Manor System: Next period approved");
+				}
+				updatePeriodApprove();
+			}
+		}, getMillisToNextPeriodApprove());
 	}
-
-	public long getMillisToManorRefresh() {
+	
+	public long getMillisToManorRefresh()
+	{
 		if (_manorRefresh.getTimeInMillis() > Calendar.getInstance().getTimeInMillis())
 			return (_manorRefresh.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
-
+		
 		return setNewManorRefresh();
 	}
-
-	public long setNewManorRefresh() {
+	
+	public long setNewManorRefresh()
+	{
 		_manorRefresh = Calendar.getInstance();
 		_manorRefresh.set(Calendar.HOUR_OF_DAY, MANOR_REFRESH);
 		_manorRefresh.set(Calendar.MINUTE, MANOR_REFRESH_MIN);
 		_manorRefresh.add(Calendar.HOUR_OF_DAY, 24);
-
-        _log.info("Manor System: New Schedule for manor refresh @ " + _manorRefresh.getTime());
-
-        return (_manorRefresh.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
-    }
-
-	public long getMillisToNextPeriodApprove() {
+		
+		_log.info("Manor System: New Schedule for manor refresh @ " + _manorRefresh.getTime());
+		
+		return (_manorRefresh.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
+	}
+	
+	public long getMillisToNextPeriodApprove()
+	{
 		if (_periodApprove.getTimeInMillis() > Calendar.getInstance().getTimeInMillis())
 			return (_periodApprove.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
-
+		
 		return setNewPeriodApprove();
 	}
-
-	public long setNewPeriodApprove() {
+	
+	public long setNewPeriodApprove()
+	{
 		_periodApprove = Calendar.getInstance();
 		_periodApprove.set(Calendar.HOUR_OF_DAY, NEXT_PERIOD_APPROVE);
 		_periodApprove.set(Calendar.MINUTE, NEXT_PERIOD_APPROVE_MIN);
 		_periodApprove.add(Calendar.HOUR_OF_DAY, 24);
-
-        _log.info("Manor System: New Schedule for period approve @ " + _periodApprove.getTime());
-
-        return (_periodApprove.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
-    }
-
-	public void setNextPeriod() {
-		for (Castle c: CastleManager.getInstance().getCastles()) {
+		
+		_log.info("Manor System: New Schedule for period approve @ " + _periodApprove.getTime());
+		
+		return (_periodApprove.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
+	}
+	
+	public void setNextPeriod()
+	{
+		for (Castle c : CastleManager.getInstance().getCastles())
+		{
 			if (c.getOwnerId() <= 0)
 				continue;
 			L2Clan clan = ClanTable.getInstance().getClan(c.getOwnerId());
 			if (clan == null)
 				continue;
-
+			
 			ItemContainer cwh = clan.getWarehouse();
-			if (!(cwh instanceof ClanWarehouse)) {
+			if (!(cwh instanceof ClanWarehouse))
+			{
 				_log.info("Can't get clan warehouse for clan " + ClanTable.getInstance().getClan(c.getOwnerId()));
 				return;
 			}
-
-			for (CropProcure crop: c.getCropProcure(PERIOD_CURRENT)) {
+			
+			for (CropProcure crop : c.getCropProcure(PERIOD_CURRENT))
+			{
 				if (crop.getStartAmount() == 0)
 					continue;
 				// adding bought crops to clan warehouse
-				if (crop.getStartAmount() - crop.getAmount() > 0) {
+				if (crop.getStartAmount() - crop.getAmount() > 0)
+				{
 					long count = crop.getStartAmount() - crop.getAmount();
 					count = count * 90 / 100;
-					if (count < 1) {
+					if (count < 1)
+					{
 						if (Rnd.nextInt(99) < 90)
 							count = 1;
 					}
-					if (count > 0) {
+					if (count > 0)
+					{
 						cwh.addItem("Manor", L2Manor.getInstance().getMatureCrop(crop.getId()), count, null, null);
 					}
 				}
 				// reserved and not used money giving back to treasury
-				if (crop.getAmount() > 0) {
+				if (crop.getAmount() > 0)
+				{
 					c.addToTreasuryNoTax(crop.getAmount() * crop.getPrice());
 				}
 			}
-
+			
 			c.setSeedProduction(c.getSeedProduction(PERIOD_NEXT), PERIOD_CURRENT);
 			c.setCropProcure(c.getCropProcure(PERIOD_NEXT), PERIOD_CURRENT);
-
-			if (c.getTreasury() < c.getManorCost(PERIOD_CURRENT)) {
+			
+			if (c.getTreasury() < c.getManorCost(PERIOD_CURRENT))
+			{
 				c.setSeedProduction(getNewSeedsList(c.getCastleId()), PERIOD_NEXT);
 				c.setCropProcure(getNewCropsList(c.getCastleId()), PERIOD_NEXT);
-			} else {
+			}
+			else
+			{
 				FastList<SeedProduction> production = new FastList<SeedProduction>();
-				for (SeedProduction s : c.getSeedProduction(PERIOD_CURRENT)) {
+				for (SeedProduction s : c.getSeedProduction(PERIOD_CURRENT))
+				{
 					s.setCanProduce(s.getStartProduce());
 					production.add(s);
 				}
 				c.setSeedProduction(production, PERIOD_NEXT);
-
+				
 				FastList<CropProcure> procure = new FastList<CropProcure>();
-				for (CropProcure cr : c.getCropProcure(PERIOD_CURRENT)) {
+				for (CropProcure cr : c.getCropProcure(PERIOD_CURRENT))
+				{
 					cr.setAmount(cr.getStartAmount());
 					procure.add(cr);
 				}
 				c.setCropProcure(procure, PERIOD_NEXT);
 			}
-			if (Config.ALT_MANOR_SAVE_ALL_ACTIONS) {
+			if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
+			{
 				c.saveCropData();
 				c.saveSeedData();
 			}
-
+			
 			// Sending notification to a clan leader
 			L2PcInstance clanLeader = null;
 			if (clan != null)
 				clanLeader = L2World.getInstance().getPlayer(clan.getLeader().getName());
 			if (clanLeader != null)
 				clanLeader.sendPacket(new SystemMessage(SystemMessageId.THE_MANOR_INFORMATION_HAS_BEEN_UPDATED));
-
+			
 			c.setNextPeriodApproved(false);
 		}
 	}
-
-	public void approveNextPeriod() {
-		for (Castle c: CastleManager.getInstance().getCastles()) {
+	
+	public void approveNextPeriod()
+	{
+		for (Castle c : CastleManager.getInstance().getCastles())
+		{
 			boolean notFunc = false;
-
-			if (c.getOwnerId() <= 0 ) {       				 	  // Castle has no owner
+			
+			if (c.getOwnerId() <= 0)
+			{ // Castle has no owner
 				c.setCropProcure(new FastList<CropProcure>(), PERIOD_NEXT);
 				c.setSeedProduction(new FastList<SeedProduction>(), PERIOD_NEXT);
-			} else if (c.getTreasury() < c.getManorCost(PERIOD_NEXT)) {
+			}
+			else if (c.getTreasury() < c.getManorCost(PERIOD_NEXT))
+			{
 				notFunc = true;
 				c.setSeedProduction(getNewSeedsList(c.getCastleId()), PERIOD_NEXT);
 				c.setCropProcure(getNewCropsList(c.getCastleId()), PERIOD_NEXT);
-			} else {
+			}
+			else
+			{
 				ItemContainer cwh = ClanTable.getInstance().getClan(c.getOwnerId()).getWarehouse();
-				if (!(cwh instanceof ClanWarehouse)) {
+				if (!(cwh instanceof ClanWarehouse))
+				{
 					_log.info("Can't get clan warehouse for clan " + ClanTable.getInstance().getClan(c.getOwnerId()));
 					return;
 				}
 				int slots = 0;
-				for (CropProcure crop : c.getCropProcure(PERIOD_NEXT)) {
-					if (crop.getStartAmount() > 0) {
+				for (CropProcure crop : c.getCropProcure(PERIOD_NEXT))
+				{
+					if (crop.getStartAmount() > 0)
+					{
 						if (cwh.getItemByItemId(L2Manor.getInstance().getMatureCrop(crop.getId())) == null)
 							slots++;
 					}
 				}
-				if (!cwh.validateCapacity(slots)) {
+				if (!cwh.validateCapacity(slots))
+				{
 					notFunc = true;
 					c.setSeedProduction(getNewSeedsList(c.getCastleId()), PERIOD_NEXT);
 					c.setCropProcure(getNewCropsList(c.getCastleId()), PERIOD_NEXT);
 				}
 			}
 			c.setNextPeriodApproved(true);
-			c.addToTreasuryNoTax( (-1)*c.getManorCost(PERIOD_NEXT) );
-
-			if (notFunc) {
+			c.addToTreasuryNoTax((-1) * c.getManorCost(PERIOD_NEXT));
+			
+			if (notFunc)
+			{
 				L2Clan clan = ClanTable.getInstance().getClan(c.getOwnerId());
 				L2PcInstance clanLeader = null;
 				if (clan != null)
-					 clanLeader = L2World.getInstance().getPlayer(clan.getLeader().getName());
+					clanLeader = L2World.getInstance().getPlayer(clan.getLeader().getName());
 				if (clanLeader != null)
 					clanLeader.sendPacket(new SystemMessage(SystemMessageId.THE_AMOUNT_IS_NOT_SUFFICIENT_AND_SO_THE_MANOR_IS_NOT_IN_OPERATION));
 			}
 		}
-
+		
 	}
-
-	private FastList<SeedProduction> getNewSeedsList(int castleId) {
+	
+	private FastList<SeedProduction> getNewSeedsList(int castleId)
+	{
 		FastList<SeedProduction> seeds = new FastList<SeedProduction>();
 		FastList<Integer> seedsIds = L2Manor.getInstance().getSeedsForCastle(castleId);
-		for (int sd : seedsIds) {
+		for (int sd : seedsIds)
+		{
 			seeds.add(new SeedProduction(sd));
 		}
 		return seeds;
 	}
-
-	private FastList<CropProcure> getNewCropsList(int castleId) {
+	
+	private FastList<CropProcure> getNewCropsList(int castleId)
+	{
 		FastList<CropProcure> crops = new FastList<CropProcure>();
 		FastList<Integer> cropsIds = L2Manor.getInstance().getCropsForCastle(castleId);
-		for (int cr : cropsIds) {
+		for (int cr : cropsIds)
+		{
 			crops.add(new CropProcure(cr));
 		}
 		return crops;
 	}
-
-	public boolean isUnderMaintenance() {
-    	return _underMaintenance;
-    }
-
-    public void setUnderMaintenance(boolean mode) {
-    	_underMaintenance = mode;
-    }
-
-    public boolean isDisabled() {
-    	return _disabled;
-    }
-
-    public void setDisabled(boolean mode) {
-    	_disabled = mode;
-    }
-
-	public SeedProduction getNewSeedProduction (int id, long amount, long price, long sales) {
+	
+	public boolean isUnderMaintenance()
+	{
+		return _underMaintenance;
+	}
+	
+	public void setUnderMaintenance(boolean mode)
+	{
+		_underMaintenance = mode;
+	}
+	
+	public boolean isDisabled()
+	{
+		return _disabled;
+	}
+	
+	public void setDisabled(boolean mode)
+	{
+		_disabled = mode;
+	}
+	
+	public SeedProduction getNewSeedProduction(int id, long amount, long price, long sales)
+	{
 		return new SeedProduction(id, amount, price, sales);
 	}
-
-	public CropProcure getNewCropProcure (int id, long amount, int type, long price, long buy) {
+	
+	public CropProcure getNewCropProcure(int id, long amount, int type, long price, long buy)
+	{
 		return new CropProcure(id, amount, type, buy, price);
 	}
-
-	public void save() {
-		for (Castle c : CastleManager.getInstance().getCastles()) {
+	
+	public void save()
+	{
+		for (Castle c : CastleManager.getInstance().getCastles())
+		{
 			c.saveSeedData();
 			c.saveCropData();
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CastleManorManager _instance = new CastleManorManager();
+	}
 }

+ 155 - 152
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/ClanHallManager.java

@@ -33,214 +33,217 @@ import net.sf.l2j.gameserver.model.zone.type.L2ClanHallZone;
  */
 public class ClanHallManager
 {
-    protected static final Logger _log = Logger.getLogger(ClanHallManager.class.getName());
-    
-	private static ClanHallManager _instance;
-
+	protected static final Logger _log = Logger.getLogger(ClanHallManager.class.getName());
+	
 	private Map<Integer, ClanHall> _clanHall;
 	private Map<Integer, ClanHall> _freeClanHall;
-    private Map<Integer, ClanHall> _allClanHalls;
+	private Map<Integer, ClanHall> _allClanHalls;
 	private boolean _loaded = false;
-
+	
 	public static ClanHallManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_log.info("Initializing ClanHallManager");
-			_instance = new ClanHallManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	public boolean loaded()
 	{
 		return _loaded;
 	}
-
+	
 	private ClanHallManager()
 	{
+		_log.info("Initializing ClanHallManager");
 		_clanHall = new FastMap<Integer, ClanHall>();
 		_freeClanHall = new FastMap<Integer, ClanHall>();
 		_allClanHalls = new FastMap<Integer, ClanHall>();
 		load();
 	}
-
+	
 	/** Reload All Clan Hall */
-/*	public final void reload() Cant reload atm - would loose zone info
-	{
-		_clanHall.clear();
-		_freeClanHall.clear();
-		load();
-	}
-*/
+	/*	public final void reload() Cant reload atm - would loose zone info
+		{
+			_clanHall.clear();
+			_freeClanHall.clear();
+			load();
+		}
+	*/
 
 	/** Load All Clan Hall */
 	private final void load()
 	{
 		Connection con = null;
-        try
-        {
-            int id,ownerId,lease,grade = 0;
-            String Name,Desc,Location;
-            long paidUntil = 0;
-            boolean paid = false;
-            PreparedStatement statement;
-            ResultSet rs;
-            con = L2DatabaseFactory.getInstance().getConnection();
-            statement = con.prepareStatement("SELECT * FROM clanhall ORDER BY id");
-            rs = statement.executeQuery();
-            while (rs.next())
-            {
-            	id = rs.getInt("id");
-                Name = rs.getString("name");
-                ownerId = rs.getInt("ownerId");
-                lease = rs.getInt("lease");
-                Desc = rs.getString("desc");
-                Location = rs.getString("location");
-                paidUntil = rs.getLong("paidUntil");
-                grade = rs.getInt("Grade");
-                paid = rs.getBoolean("paid");
-
-                ClanHall ch = new ClanHall(id, Name, ownerId, lease, Desc, Location, paidUntil, grade, paid);
-            	if(ownerId == 0)
-                {
-                    _freeClanHall.put(id, ch);
-                }
-            	else
-                {
-            		if(ClanTable.getInstance().getClan(rs.getInt("ownerId")) != null)
-            		{
-            			_clanHall.put(id, ch);
-            			ClanTable.getInstance().getClan(rs.getInt("ownerId")).setHasHideout(id);
-            		}
-                    else
-            		{
-            			_freeClanHall.put(id, ch);
-            			_freeClanHall.get(id).free();
-            			AuctionManager.getInstance().initNPC(id);
-            		}
-            	}
-                _allClanHalls.put(id, ch);
-                
-            }
-            statement.close();
-            _log.info("Loaded: "+getClanHalls().size() +" clan halls");
-            _log.info("Loaded: "+getFreeClanHalls().size() +" free clan halls");
-            _loaded = true;
-        }
-        catch (Exception e)
-        {
-            _log.warning("Exception: ClanHallManager.load(): " + e.getMessage());
-            e.printStackTrace();
-        }
-        finally
-        {
-            try
-            { 
-                con.close(); 
-            } catch (Exception e)
-            {        
-            }
-        }
+		try
+		{
+			int id, ownerId, lease, grade = 0;
+			String Name, Desc, Location;
+			long paidUntil = 0;
+			boolean paid = false;
+			PreparedStatement statement;
+			ResultSet rs;
+			con = L2DatabaseFactory.getInstance().getConnection();
+			statement = con.prepareStatement("SELECT * FROM clanhall ORDER BY id");
+			rs = statement.executeQuery();
+			while (rs.next())
+			{
+				id = rs.getInt("id");
+				Name = rs.getString("name");
+				ownerId = rs.getInt("ownerId");
+				lease = rs.getInt("lease");
+				Desc = rs.getString("desc");
+				Location = rs.getString("location");
+				paidUntil = rs.getLong("paidUntil");
+				grade = rs.getInt("Grade");
+				paid = rs.getBoolean("paid");
+				
+				ClanHall ch = new ClanHall(id, Name, ownerId, lease, Desc, Location, paidUntil, grade, paid);
+				if (ownerId == 0)
+				{
+					_freeClanHall.put(id, ch);
+				}
+				else
+				{
+					if (ClanTable.getInstance().getClan(rs.getInt("ownerId")) != null)
+					{
+						_clanHall.put(id, ch);
+						ClanTable.getInstance().getClan(rs.getInt("ownerId")).setHasHideout(id);
+					}
+					else
+					{
+						_freeClanHall.put(id, ch);
+						_freeClanHall.get(id).free();
+						AuctionManager.getInstance().initNPC(id);
+					}
+				}
+				_allClanHalls.put(id, ch);
+				
+			}
+			statement.close();
+			_log.info("Loaded: " + getClanHalls().size() + " clan halls");
+			_log.info("Loaded: " + getFreeClanHalls().size() + " free clan halls");
+			_loaded = true;
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: ClanHallManager.load(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
 	}
-
+	
 	/** Get Map with all FreeClanHalls */
 	public final Map<Integer, ClanHall> getFreeClanHalls()
 	{
 		return _freeClanHall;
 	}
-
+	
 	/** Get Map with all ClanHalls that have owner*/
 	public final Map<Integer, ClanHall> getClanHalls()
 	{
 		return _clanHall;
 	}
-    
-    /** Get Map with all ClanHalls*/ 
-    public final Map<Integer, ClanHall> getAllClanHalls() 
-    { 
-        return _allClanHalls; 
-    }
-
+	
+	/** Get Map with all ClanHalls*/
+	public final Map<Integer, ClanHall> getAllClanHalls()
+	{
+		return _allClanHalls;
+	}
+	
 	/** Check is free ClanHall */
 	public final boolean isFree(int chId)
 	{
-		if(_freeClanHall.containsKey(chId))
+		if (_freeClanHall.containsKey(chId))
 			return true;
 		return false;
 	}
-
+	
 	/** Free a ClanHall */
 	public final synchronized void setFree(int chId)
 	{
-		_freeClanHall.put(chId,_clanHall.get(chId));
+		_freeClanHall.put(chId, _clanHall.get(chId));
 		ClanTable.getInstance().getClan(_freeClanHall.get(chId).getOwnerId()).setHasHideout(0);
 		_freeClanHall.get(chId).free();
 		_clanHall.remove(chId);
 	}
-
+	
 	/** Set ClanHallOwner */
 	public final synchronized void setOwner(int chId, L2Clan clan)
 	{
-		if(!_clanHall.containsKey(chId))
+		if (!_clanHall.containsKey(chId))
 		{
-			_clanHall.put(chId,_freeClanHall.get(chId));
+			_clanHall.put(chId, _freeClanHall.get(chId));
 			_freeClanHall.remove(chId);
-		}else
+		}
+		else
 			_clanHall.get(chId).free();
 		ClanTable.getInstance().getClan(clan.getClanId()).setHasHideout(chId);
 		_clanHall.get(chId).setOwner(clan);
 	}
+	
+	/** Get Clan Hall by Id */
+	public final ClanHall getClanHallById(int clanHallId)
+	{
+		if (_clanHall.containsKey(clanHallId))
+			return _clanHall.get(clanHallId);
+		if (_freeClanHall.containsKey(clanHallId))
+			return _freeClanHall.get(clanHallId);
+		return null;
+	}
+	
+	/** Get Clan Hall by x,y,z */
+	/*
+		public final ClanHall getClanHall(int x, int y, int z)
+		{
+			for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
+				if (ch.getValue().getZone().isInsideZone(x, y, z)) return ch.getValue();
 
-    /** Get Clan Hall by Id */
-    public final ClanHall getClanHallById(int clanHallId)
-    {
-    	if(_clanHall.containsKey(clanHallId))
-    		return _clanHall.get(clanHallId);
-    	if(_freeClanHall.containsKey(clanHallId))
-    		return _freeClanHall.get(clanHallId);
-        return null;
-    }
-
-    /** Get Clan Hall by x,y,z *//*
-    public final ClanHall getClanHall(int x, int y, int z)
-    {
-    	for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
-    		if (ch.getValue().getZone().isInsideZone(x, y, z)) return ch.getValue();
-
-    	for (Map.Entry<Integer, ClanHall> ch : _freeClanHall.entrySet())
-    		if (ch.getValue().getZone().isInsideZone(x, y, z)) return ch.getValue();
-
-        return null;
-    }*/
-
-    public final ClanHall getNearbyClanHall(int x, int y, int maxDist)
-    {
-    	L2ClanHallZone zone = null;
+			for (Map.Entry<Integer, ClanHall> ch : _freeClanHall.entrySet())
+				if (ch.getValue().getZone().isInsideZone(x, y, z)) return ch.getValue();
 
-    	for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
-    	{
-    		zone = ch.getValue().getZone();
-    		if (zone != null && zone.getDistanceToZone(x, y) < maxDist)
-    			return ch.getValue();
-    	}
-    	for (Map.Entry<Integer, ClanHall> ch : _freeClanHall.entrySet())
-    	{
-    		zone = ch.getValue().getZone();
-    		if (zone != null && zone.getDistanceToZone(x, y) < maxDist)
-    			return ch.getValue();
-    	}
-        return null;
-    }
+			return null;
+		}*/
 
-    /** Get Clan Hall by Owner */
-    public final ClanHall getClanHallByOwner(L2Clan clan)
-    {
-    	for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
-    	{
-    		if (clan.getClanId() == ch.getValue().getOwnerId())
-    			return ch.getValue();
-    	}
-        return null;
-    }
-}
+	public final ClanHall getNearbyClanHall(int x, int y, int maxDist)
+	{
+		L2ClanHallZone zone = null;
+		
+		for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
+		{
+			zone = ch.getValue().getZone();
+			if (zone != null && zone.getDistanceToZone(x, y) < maxDist)
+				return ch.getValue();
+		}
+		for (Map.Entry<Integer, ClanHall> ch : _freeClanHall.entrySet())
+		{
+			zone = ch.getValue().getZone();
+			if (zone != null && zone.getDistanceToZone(x, y) < maxDist)
+				return ch.getValue();
+		}
+		return null;
+	}
+	
+	/** Get Clan Hall by Owner */
+	public final ClanHall getClanHallByOwner(L2Clan clan)
+	{
+		for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
+		{
+			if (clan.getClanId() == ch.getValue().getOwnerId())
+				return ch.getValue();
+		}
+		return null;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ClanHallManager _instance = new ClanHallManager();
+	}
+}

+ 147 - 132
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CoupleManager.java

@@ -31,136 +31,151 @@ import net.sf.l2j.gameserver.model.entity.Couple;
  */
 public class CoupleManager
 {
-    private static final Logger _log = Logger.getLogger(CoupleManager.class.getName());
-
-    // =========================================================
-    private static CoupleManager _instance;
-    public static final CoupleManager getInstance()
-    {
-        if (_instance == null)
-        {
-            _log.info("L2JMOD: Initializing CoupleManager");
-            _instance = new CoupleManager();
-            _instance.load();
-        }
-        return _instance;
-    }
-    // =========================================================
-
-    // =========================================================
-    // Data Field
-    private FastList<Couple> _couples;
-
-
-    // =========================================================
-    // Method - Public
-    public void reload()
-    {
-        getCouples().clear();
-        load();
-    }
-
-    // =========================================================
-    // Method - Private
-    private final void load()
-    {
-        Connection con = null;
-        try
-        {
-            PreparedStatement statement;
-            ResultSet rs;
-
-            con = L2DatabaseFactory.getInstance().getConnection();
-
-            statement = con.prepareStatement("Select id from mods_wedding order by id");
-            rs = statement.executeQuery();
-
-            while (rs.next())
-            {
-                getCouples().add(new Couple(rs.getInt("id")));
-            }
-
-            statement.close();
-
-            _log.info("Loaded: " + getCouples().size() + " couples(s)");
-        }
-        catch (Exception e)
-        {
-            _log.severe("Exception: CoupleManager.load(): " + e);
-        }
-
-        finally {try { con.close(); } catch (Exception e) {}}
-    }
-
-    // =========================================================
-    // Property - Public
-    public final Couple getCouple(int coupleId)
-    {
-        int index = getCoupleIndex(coupleId);
-        if (index >= 0) return getCouples().get(index);
-        return null;
-    }
-
-    public void createCouple(L2PcInstance player1,L2PcInstance player2)
-    {
-        if(player1!=null && player2!=null)
-        {
-            if(player1.getPartnerId()==0 && player2.getPartnerId()==0)
-            {
-                int _player1id = player1.getObjectId();
-                int _player2id = player2.getObjectId();
-
-                Couple _new = new Couple(player1,player2);
-                getCouples().add(_new);
-                player1.setPartnerId(_player2id);
-                player2.setPartnerId(_player1id);
-                player1.setCoupleId(_new.getId());
-                player2.setCoupleId(_new.getId());
-            }
-        }
-    }
-
-    public void deleteCouple(int coupleId)
-    {
-       int index = getCoupleIndex(coupleId);
-       Couple couple = getCouples().get(index);
-        if(couple!=null)
-        {
-           L2PcInstance player1 = (L2PcInstance)L2World.getInstance().findObject(couple.getPlayer1Id());
-           L2PcInstance player2 = (L2PcInstance)L2World.getInstance().findObject(couple.getPlayer2Id());
-            if (player1 != null)
-            {
-               player1.setPartnerId(0);
-               player1.setMarried(false);
-               player1.setCoupleId(0);
-
-            }
-            if (player2 != null)
-            {
-               player2.setPartnerId(0);
-               player2.setMarried(false);
-               player2.setCoupleId(0);
-
-            }
-            couple.divorce();
-            getCouples().remove(index);
-        }
-    }
-
-    public final int getCoupleIndex(int coupleId)
-    {
-        int i=0;
-        for (Couple temp : getCouples())
-        {
-        	if (temp != null && temp.getId() == coupleId) return i;
-        	i++;
-        }
-        return -1;
-    }
-
-    public final FastList<Couple> getCouples()
-    {
-        if (_couples == null) _couples = new FastList<Couple>();
-        return _couples;
-    }
+	private static final Logger _log = Logger.getLogger(CoupleManager.class.getName());
+	
+	private CoupleManager()
+	{
+		_log.info("L2JMOD: Initializing CoupleManager");
+		load();
+	}
+	
+	public static final CoupleManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	// =========================================================
+	
+	// =========================================================
+	// Data Field
+	private FastList<Couple> _couples;
+	
+	// =========================================================
+	// Method - Public
+	public void reload()
+	{
+		getCouples().clear();
+		load();
+	}
+	
+	// =========================================================
+	// Method - Private
+	private final void load()
+	{
+		Connection con = null;
+		try
+		{
+			PreparedStatement statement;
+			ResultSet rs;
+			
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			statement = con.prepareStatement("Select id from mods_wedding order by id");
+			rs = statement.executeQuery();
+			
+			while (rs.next())
+			{
+				getCouples().add(new Couple(rs.getInt("id")));
+			}
+			
+			statement.close();
+			
+			_log.info("Loaded: " + getCouples().size() + " couples(s)");
+		}
+		catch (Exception e)
+		{
+			_log.severe("Exception: CoupleManager.load(): " + e);
+		}
+		
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	// =========================================================
+	// Property - Public
+	public final Couple getCouple(int coupleId)
+	{
+		int index = getCoupleIndex(coupleId);
+		if (index >= 0)
+			return getCouples().get(index);
+		return null;
+	}
+	
+	public void createCouple(L2PcInstance player1, L2PcInstance player2)
+	{
+		if (player1 != null && player2 != null)
+		{
+			if (player1.getPartnerId() == 0 && player2.getPartnerId() == 0)
+			{
+				int _player1id = player1.getObjectId();
+				int _player2id = player2.getObjectId();
+				
+				Couple _new = new Couple(player1, player2);
+				getCouples().add(_new);
+				player1.setPartnerId(_player2id);
+				player2.setPartnerId(_player1id);
+				player1.setCoupleId(_new.getId());
+				player2.setCoupleId(_new.getId());
+			}
+		}
+	}
+	
+	public void deleteCouple(int coupleId)
+	{
+		int index = getCoupleIndex(coupleId);
+		Couple couple = getCouples().get(index);
+		if (couple != null)
+		{
+			L2PcInstance player1 = (L2PcInstance) L2World.getInstance().findObject(couple.getPlayer1Id());
+			L2PcInstance player2 = (L2PcInstance) L2World.getInstance().findObject(couple.getPlayer2Id());
+			if (player1 != null)
+			{
+				player1.setPartnerId(0);
+				player1.setMarried(false);
+				player1.setCoupleId(0);
+				
+			}
+			if (player2 != null)
+			{
+				player2.setPartnerId(0);
+				player2.setMarried(false);
+				player2.setCoupleId(0);
+				
+			}
+			couple.divorce();
+			getCouples().remove(index);
+		}
+	}
+	
+	public final int getCoupleIndex(int coupleId)
+	{
+		int i = 0;
+		for (Couple temp : getCouples())
+		{
+			if (temp != null && temp.getId() == coupleId)
+				return i;
+			i++;
+		}
+		return -1;
+	}
+	
+	public final FastList<Couple> getCouples()
+	{
+		if (_couples == null)
+			_couples = new FastList<Couple>();
+		return _couples;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CoupleManager _instance = new CoupleManager();
+	}
 }

+ 274 - 238
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/CursedWeaponsManager.java

@@ -58,151 +58,156 @@ import org.w3c.dom.Node;
 public class CursedWeaponsManager
 {
 	private static final Logger _log = Logger.getLogger(CursedWeaponsManager.class.getName());
-
-	// =========================================================
-	private static CursedWeaponsManager _instance;
-
+	
 	public static final CursedWeaponsManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new CursedWeaponsManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	// =========================================================
 	// Data Field
 	private Map<Integer, CursedWeapon> _cursedWeapons;
-
+	
 	// =========================================================
 	// Constructor
-	public CursedWeaponsManager()
+	private CursedWeaponsManager()
+	{
+		init();
+	}
+	
+	private void init()
 	{
 		_log.info("Initializing CursedWeaponsManager");
 		_cursedWeapons = new FastMap<Integer, CursedWeapon>();
-
-		if (!Config.ALLOW_CURSED_WEAPONS) return;
-
+		
+		if (!Config.ALLOW_CURSED_WEAPONS)
+			return;
+		
 		load();
 		restore();
 		controlPlayers();
-		_log.info("Loaded : "+_cursedWeapons.size() + " cursed weapon(s).");
+		_log.info("Loaded : " + _cursedWeapons.size() + " cursed weapon(s).");
 	}
-
+	
 	// =========================================================
 	// Method - Private
 	public final void reload()
 	{
-		_instance = new CursedWeaponsManager();
+		init();
 	}
+	
 	private final void load()
 	{
 		if (Config.DEBUG)
-    		_log.info("  Parsing ... ");
-        try
-        {
-            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-            factory.setValidating(false);
-            factory.setIgnoringComments(true);
-
-            File file = new File(Config.DATAPACK_ROOT+"/data/cursedWeapons.xml");
-            if (!file.exists())
-            {
-        		if (Config.DEBUG)
-            		_log.info("NO FILE");
-            	return;
-            }
-
-            Document doc = factory.newDocumentBuilder().parse(file);
-
-            for (Node n=doc.getFirstChild(); n != null; n = n.getNextSibling())
-            {
-                if ("list".equalsIgnoreCase(n.getNodeName()))
-                {
-                    for (Node d=n.getFirstChild(); d != null; d = d.getNextSibling())
-                    {
-                        if ("item".equalsIgnoreCase(d.getNodeName()))
-                        {
-                    		NamedNodeMap attrs = d.getAttributes();
-                        	int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
-                        	int skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
-                        	String name = attrs.getNamedItem("name").getNodeValue();
-
-                        	CursedWeapon cw = new CursedWeapon(id, skillId, name);
-
-                        	int val;
-                            for (Node cd=d.getFirstChild(); cd != null; cd = cd.getNextSibling())
-                            {
-                                if ("dropRate".equalsIgnoreCase(cd.getNodeName()))
-                                {
-                            		attrs = cd.getAttributes();
-                            		val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
-                            		cw.setDropRate(val);
-                                } else if ("duration".equalsIgnoreCase(cd.getNodeName()))
-                                {
-                            		attrs = cd.getAttributes();
-                            		val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
-                            		cw.setDuration(val);
-                                } else if ("durationLost".equalsIgnoreCase(cd.getNodeName()))
-                                {
-                            		attrs = cd.getAttributes();
-                            		val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
-                            		cw.setDurationLost(val);
-                                } else if ("disapearChance".equalsIgnoreCase(cd.getNodeName()))
-                                {
-                            		attrs = cd.getAttributes();
-                            		val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
-                            		cw.setDisapearChance(val);
-                                } else if ("stageKills".equalsIgnoreCase(cd.getNodeName()))
-                                {
-                            		attrs = cd.getAttributes();
-                            		val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
-                            		cw.setStageKills(val);
-                                }
-                            }
-
-                            // Store cursed weapon
-                            _cursedWeapons.put(id, cw);
-                        }
-                    }
-                }
-            }
-
-        	if (Config.DEBUG)
-        		_log.info("OK");
-        }
-        catch (Exception e)
-        {
-            _log.log(Level.SEVERE, "Error parsing cursed weapons file.", e);
-
-            if (Config.DEBUG)
-        		_log.warning("ERROR");
-            return ;
-        }
+			_log.info("  Parsing ... ");
+		try
+		{
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			factory.setValidating(false);
+			factory.setIgnoringComments(true);
+			
+			File file = new File(Config.DATAPACK_ROOT + "/data/cursedWeapons.xml");
+			if (!file.exists())
+			{
+				if (Config.DEBUG)
+					_log.info("NO FILE");
+				return;
+			}
+			
+			Document doc = factory.newDocumentBuilder().parse(file);
+			
+			for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+			{
+				if ("list".equalsIgnoreCase(n.getNodeName()))
+				{
+					for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+					{
+						if ("item".equalsIgnoreCase(d.getNodeName()))
+						{
+							NamedNodeMap attrs = d.getAttributes();
+							int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
+							int skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
+							String name = attrs.getNamedItem("name").getNodeValue();
+							
+							CursedWeapon cw = new CursedWeapon(id, skillId, name);
+							
+							int val;
+							for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
+							{
+								if ("dropRate".equalsIgnoreCase(cd.getNodeName()))
+								{
+									attrs = cd.getAttributes();
+									val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
+									cw.setDropRate(val);
+								}
+								else if ("duration".equalsIgnoreCase(cd.getNodeName()))
+								{
+									attrs = cd.getAttributes();
+									val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
+									cw.setDuration(val);
+								}
+								else if ("durationLost".equalsIgnoreCase(cd.getNodeName()))
+								{
+									attrs = cd.getAttributes();
+									val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
+									cw.setDurationLost(val);
+								}
+								else if ("disapearChance".equalsIgnoreCase(cd.getNodeName()))
+								{
+									attrs = cd.getAttributes();
+									val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
+									cw.setDisapearChance(val);
+								}
+								else if ("stageKills".equalsIgnoreCase(cd.getNodeName()))
+								{
+									attrs = cd.getAttributes();
+									val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
+									cw.setStageKills(val);
+								}
+							}
+							
+							// Store cursed weapon
+							_cursedWeapons.put(id, cw);
+						}
+					}
+				}
+			}
+			
+			if (Config.DEBUG)
+				_log.info("OK");
+		}
+		catch (Exception e)
+		{
+			_log.log(Level.SEVERE, "Error parsing cursed weapons file.", e);
+			
+			if (Config.DEBUG)
+				_log.warning("ERROR");
+			return;
+		}
 	}
+	
 	private final void restore()
 	{
-    	if (Config.DEBUG)
-    		_log.info("  Restoring ... ");
+		if (Config.DEBUG)
+			_log.info("  Restoring ... ");
 		Connection con = null;
 		try
 		{
 			// Retrieve the L2PcInstance from the characters table of the database
 			con = L2DatabaseFactory.getInstance().getConnection();
-
+			
 			PreparedStatement statement = con.prepareStatement("SELECT itemId, charId, playerKarma, playerPkKills, nbKills, endTime FROM cursed_weapons");
 			ResultSet rset = statement.executeQuery();
-
-			while(rset.next())
+			
+			while (rset.next())
 			{
-				int itemId        = rset.getInt("itemId");
-				int playerId      = rset.getInt("charId");
-				int playerKarma   = rset.getInt("playerKarma");
+				int itemId = rset.getInt("itemId");
+				int playerId = rset.getInt("charId");
+				int playerKarma = rset.getInt("playerKarma");
 				int playerPkKills = rset.getInt("playerPkKills");
-				int nbKills       = rset.getInt("nbKills");
-				long endTime      = rset.getLong("endTime");
-
+				int nbKills = rset.getInt("nbKills");
+				long endTime = rset.getLong("endTime");
+				
 				CursedWeapon cw = _cursedWeapons.get(itemId);
 				cw.setPlayerId(playerId);
 				cw.setPlayerKarma(playerKarma);
@@ -211,31 +216,38 @@ public class CursedWeaponsManager
 				cw.setEndTime(endTime);
 				cw.reActivate();
 			}
-
+			
 			rset.close();
 			statement.close();
-
-	    	if (Config.DEBUG)
-	    		_log.info("OK");
+			
+			if (Config.DEBUG)
+				_log.info("OK");
 		}
 		catch (Exception e)
 		{
 			_log.warning("Could not restore CursedWeapons data: " + e);
-
-	    	if (Config.DEBUG)
-	    		_log.warning("ERROR");
+			
+			if (Config.DEBUG)
+				_log.warning("ERROR");
 			return;
 		}
 		finally
 		{
-			try { con.close(); } catch (Exception e) {}
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
 		}
 	}
+	
 	private final void controlPlayers()
 	{
-    	if (Config.DEBUG)
-    		_log.info("  Checking players ... ");
-
+		if (Config.DEBUG)
+			_log.info("  Checking players ... ");
+		
 		Connection con = null;
 		try
 		{
@@ -243,7 +255,7 @@ public class CursedWeaponsManager
 			con = L2DatabaseFactory.getInstance().getConnection();
 			PreparedStatement statement = null;
 			ResultSet rset = null;
-
+			
 			// TODO: See comments below...
 			// This entire for loop should NOT be necessary, since it is already handled by
 			// CursedWeapon.endOfLife().  However, if we indeed *need* to duplicate it for safety,
@@ -252,8 +264,9 @@ public class CursedWeaponsManager
 			// or a lost-child entry in the cursedweapons table, without a corresponding one in items...
 			for (CursedWeapon cw : _cursedWeapons.values())
 			{
-				if (cw.isActivated()) continue;
-
+				if (cw.isActivated())
+					continue;
+				
 				// Do an item check to be sure that the cursed weapon isn't hold by someone
 				int itemId = cw.getItemId();
 				try
@@ -261,23 +274,23 @@ public class CursedWeaponsManager
 					statement = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?");
 					statement.setInt(1, itemId);
 					rset = statement.executeQuery();
-
+					
 					if (rset.next())
 					{
 						// A player has the cursed weapon in his inventory ...
 						int playerId = rset.getInt("owner_id");
-						_log.info("PROBLEM : Player "+playerId+" owns the cursed weapon "+itemId+" but he shouldn't.");
-
+						_log.info("PROBLEM : Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
+						
 						// Delete the item
 						statement = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?");
 						statement.setInt(1, playerId);
 						statement.setInt(2, itemId);
 						if (statement.executeUpdate() != 1)
 						{
-							_log.warning("Error while deleting cursed weapon "+itemId+" from userId "+playerId);
+							_log.warning("Error while deleting cursed weapon " + itemId + " from userId " + playerId);
 						}
 						statement.close();
-
+						
 						// Delete the skill
 						/*
 						statement = con.prepareStatement("DELETE FROM character_skills WHERE charId=? AND skill_id=");
@@ -289,61 +302,66 @@ public class CursedWeaponsManager
 						}
 						*/
 						// Restore the player's old karma and pk count
-		    			statement = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE charId=?");
-		    			statement.setInt(1, cw.getPlayerKarma());
-		    			statement.setInt(2, cw.getPlayerPkKills());
-		    			statement.setInt(3, playerId);
-		    			if (statement.executeUpdate() != 1)
-		    			{
-		    				_log.warning("Error while updating karma & pkkills for userId "+cw.getPlayerId());
-		    			}
-		    			// clean up the cursedweapons table.
-		    			removeFromDb(itemId);
+						statement = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE charId=?");
+						statement.setInt(1, cw.getPlayerKarma());
+						statement.setInt(2, cw.getPlayerPkKills());
+						statement.setInt(3, playerId);
+						if (statement.executeUpdate() != 1)
+						{
+							_log.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
+						}
+						// clean up the cursedweapons table.
+						removeFromDb(itemId);
 					}
 					rset.close();
 					statement.close();
-				} catch (SQLException sqlE)
-				{}
+				}
+				catch (SQLException sqlE)
+				{
+				}
 			}
 		}
 		catch (Exception e)
 		{
 			if (Config.DEBUG)
-		    	_log.warning("Could not check CursedWeapons data: " + e);
+				_log.warning("Could not check CursedWeapons data: " + e);
 			return;
 		}
 		finally
 		{
-			try { con.close(); } catch (Exception e) {}
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
 		}
-
-    	if (Config.DEBUG)
-    		_log.info("DONE");
+		
+		if (Config.DEBUG)
+			_log.info("DONE");
 	}
-
-
+	
 	// =========================================================
 	// Properties - Public
 	public synchronized void checkDrop(L2Attackable attackable, L2PcInstance player)
 	{
-		if (attackable instanceof L2SiegeGuardInstance
-			|| attackable instanceof L2RiftInvaderInstance
-			|| attackable instanceof L2FestivalMonsterInstance
-			|| attackable instanceof L2GuardInstance
-			|| attackable instanceof L2GrandBossInstance
-			|| attackable instanceof L2FeedableBeastInstance
-			|| attackable instanceof L2FortSiegeGuardInstance
-			|| attackable instanceof L2FortCommanderInstance
-			)return;
-
+		if (attackable instanceof L2SiegeGuardInstance || attackable instanceof L2RiftInvaderInstance
+				|| attackable instanceof L2FestivalMonsterInstance || attackable instanceof L2GuardInstance
+				|| attackable instanceof L2GrandBossInstance || attackable instanceof L2FeedableBeastInstance
+				|| attackable instanceof L2FortSiegeGuardInstance || attackable instanceof L2FortCommanderInstance)
+			return;
+		
 		for (CursedWeapon cw : _cursedWeapons.values())
 		{
-			if (cw.isActive()) continue;
-
-			if (cw.checkDrop(attackable, player)) break;
+			if (cw.isActive())
+				continue;
+			
+			if (cw.checkDrop(attackable, player))
+				break;
 		}
 	}
-
+	
 	public void activate(L2PcInstance player, L2ItemInstance item)
 	{
 		CursedWeapon cw = _cursedWeapons.get(item.getItemId());
@@ -358,48 +376,48 @@ public class CursedWeaponsManager
 			 * This code is a TEMP fix, so that the cursed weapon's bonus level can be observed with as
 			 * little change in the code as possible, until proper info arises.
 			 */
-			cw2.setNbKills(cw2.getStageKills()-1);
+			cw2.setNbKills(cw2.getStageKills() - 1);
 			cw2.increaseKills();
-
+			
 			// erase the newly obtained cursed weapon
-			cw.setPlayer(player);  // NECESSARY in order to find which inventory the weapon is in!
-			cw.endOfLife();        // expire the weapon and clean up.
+			cw.setPlayer(player); // NECESSARY in order to find which inventory the weapon is in!
+			cw.endOfLife(); // expire the weapon and clean up.
 		}
-		else cw.activate(player, item);
+		else
+			cw.activate(player, item);
 	}
-
+	
 	public void drop(int itemId, L2Character killer)
 	{
 		CursedWeapon cw = _cursedWeapons.get(itemId);
-
+		
 		cw.dropIt(killer);
 	}
-
+	
 	public void increaseKills(int itemId)
 	{
 		CursedWeapon cw = _cursedWeapons.get(itemId);
-
+		
 		cw.increaseKills();
 	}
-
+	
 	public int getLevel(int itemId)
 	{
 		CursedWeapon cw = _cursedWeapons.get(itemId);
-
+		
 		return cw.getLevel();
 	}
-
-
+	
 	public static void announce(SystemMessage sm)
 	{
 		Broadcast.toAllOnlinePlayers(sm);
 	}
-
+	
 	public void checkPlayer(L2PcInstance player)
 	{
 		if (player == null)
 			return;
-
+		
 		for (CursedWeapon cw : _cursedWeapons.values())
 		{
 			if (cw.isActivated() && player.getObjectId() == cw.getPlayerId())
@@ -408,81 +426,99 @@ public class CursedWeaponsManager
 				cw.setItem(player.getInventory().getItemByItemId(cw.getItemId()));
 				cw.giveSkill();
 				player.setCursedWeaponEquippedId(cw.getItemId());
-
+				
 				SystemMessage sm = new SystemMessage(SystemMessageId.S2_MINUTE_OF_USAGE_TIME_ARE_LEFT_FOR_S1);
 				sm.addString(cw.getName());
 				//sm.addItemName(cw.getItemId());
-				sm.addNumber((int)((cw.getEndTime() - System.currentTimeMillis()) / 60000));
+				sm.addNumber((int) ((cw.getEndTime() - System.currentTimeMillis()) / 60000));
 				player.sendPacket(sm);
 			}
 		}
 	}
 	
 	public int checkOwnsWeaponId(int ownerId)
-    {
-	    for (CursedWeapon cw : _cursedWeapons.values())
-            if (cw.isActivated() && ownerId == cw.getPlayerId())
-                return cw.getItemId();
-	    return -1;
-    }
+	{
+		for (CursedWeapon cw : _cursedWeapons.values())
+			if (cw.isActivated() && ownerId == cw.getPlayerId())
+				return cw.getItemId();
+		return -1;
+	}
 	
-    public static void removeFromDb(int itemId)
-    {
-    	Connection con = null;
-        try
-        {
-        	con = L2DatabaseFactory.getInstance().getConnection();
-
-        	// Delete datas
-        	PreparedStatement statement = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?");
-            statement.setInt(1, itemId);
-            statement.executeUpdate();
-
-            statement.close();
-        	con.close();
-        }
-        catch (SQLException e)
-        {
-        	_log.severe("CursedWeaponsManager: Failed to remove data: " + e);
-        }
-        finally
-        {
-        	try { con.close(); } catch (Exception e) {}
-        }
-    }
-
-    public void saveData()
-    {
+	public static void removeFromDb(int itemId)
+	{
+		Connection con = null;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			// Delete datas
+			PreparedStatement statement = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?");
+			statement.setInt(1, itemId);
+			statement.executeUpdate();
+			
+			statement.close();
+			con.close();
+		}
+		catch (SQLException e)
+		{
+			_log.severe("CursedWeaponsManager: Failed to remove data: " + e);
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	public void saveData()
+	{
 		for (CursedWeapon cw : _cursedWeapons.values())
 		{
 			cw.saveData();
 		}
-    }
-
-
+	}
+	
 	// =========================================================
-    public boolean isCursed(int itemId)
-    {
+	public boolean isCursed(int itemId)
+	{
 		return _cursedWeapons.containsKey(itemId);
-    }
-
-    public Collection<CursedWeapon> getCursedWeapons()
-    {
-    	return _cursedWeapons.values();
-    }
-
-    public Set<Integer> getCursedWeaponsIds()
-    {
-    	return _cursedWeapons.keySet();
-    }
-
-    public CursedWeapon getCursedWeapon(int itemId)
-    {
-    	return _cursedWeapons.get(itemId);
-    }
-
-    public void givePassive(int itemId)
-    {
-    	try { _cursedWeapons.get(itemId).giveSkill(); } catch (Exception e) {/***/}
-    }
+	}
+	
+	public Collection<CursedWeapon> getCursedWeapons()
+	{
+		return _cursedWeapons.values();
+	}
+	
+	public Set<Integer> getCursedWeaponsIds()
+	{
+		return _cursedWeapons.keySet();
+	}
+	
+	public CursedWeapon getCursedWeapon(int itemId)
+	{
+		return _cursedWeapons.get(itemId);
+	}
+	
+	public void givePassive(int itemId)
+	{
+		try
+		{
+			_cursedWeapons.get(itemId).giveSkill();
+		}
+		catch (Exception e)
+		{
+			/***/
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final CursedWeaponsManager _instance = new CursedWeaponsManager();
+	}
 }

+ 249 - 219
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/DayNightSpawnManager.java

@@ -31,225 +31,255 @@ import net.sf.l2j.gameserver.model.actor.instance.L2RaidBossInstance;
  * @author  godson
  */
 
-public class DayNightSpawnManager {
-
-    private static Logger _log = Logger.getLogger(DayNightSpawnManager.class.getName());
-
-    private static DayNightSpawnManager _instance;
-    private static Map<L2Spawn, L2Npc> _dayCreatures;
-    private static Map<L2Spawn, L2Npc> _nightCreatures;
-    private static Map<L2Spawn, L2RaidBossInstance> _bosses;
-
-    //private static int _currentState;  // 0 = Day, 1 = Night
-
-    public static DayNightSpawnManager getInstance()
-    {
-        if (_instance == null)
-            _instance = new DayNightSpawnManager();
-        return _instance;
-    }
-
-    private DayNightSpawnManager()
-    {
-        _dayCreatures = new FastMap<L2Spawn, L2Npc>();
-        _nightCreatures = new FastMap<L2Spawn, L2Npc>();
-        _bosses = new FastMap<L2Spawn, L2RaidBossInstance>();
-        
-        _log.info("DayNightSpawnManager: Day/Night handler initialized");
-    }
-
-    public void addDayCreature(L2Spawn spawnDat)
-    {
-        if (_dayCreatures.containsKey(spawnDat))
-        {
-            _log.warning("DayNightSpawnManager: Spawn already added into day map");
-            return;
-        }
-        else
-            _dayCreatures.put(spawnDat, null);
-    }
-
-    public void addNightCreature(L2Spawn spawnDat)
-    {
-        if (_nightCreatures.containsKey(spawnDat))
-        {
-            _log.warning("DayNightSpawnManager: Spawn already added into night map");
-            return;
-        }
-        else
-            _nightCreatures.put(spawnDat, null);
-    }
-    /*
-     * Spawn Day Creatures, and Unspawn Night Creatures
-     */
-    public void spawnDayCreatures(){
-    	spawnCreatures(_nightCreatures,_dayCreatures, "night", "day");
+public class DayNightSpawnManager
+{
+	
+	private static Logger _log = Logger.getLogger(DayNightSpawnManager.class.getName());
+	
+	private static Map<L2Spawn, L2Npc> _dayCreatures;
+	private static Map<L2Spawn, L2Npc> _nightCreatures;
+	private static Map<L2Spawn, L2RaidBossInstance> _bosses;
+	
+	//private static int _currentState;  // 0 = Day, 1 = Night
+	
+	public static DayNightSpawnManager getInstance()
+	{
+		return SingletonHolder._instance;
 	}
-    /*
-     * Spawn Night Creatures, and Unspawn Day Creatures
-     */
-    public void spawnNightCreatures(){
-    	spawnCreatures(_dayCreatures,_nightCreatures, "day", "night");
+	
+	private DayNightSpawnManager()
+	{
+		_dayCreatures = new FastMap<L2Spawn, L2Npc>();
+		_nightCreatures = new FastMap<L2Spawn, L2Npc>();
+		_bosses = new FastMap<L2Spawn, L2RaidBossInstance>();
+		
+		_log.info("DayNightSpawnManager: Day/Night handler initialized");
+	}
+	
+	public void addDayCreature(L2Spawn spawnDat)
+	{
+		if (_dayCreatures.containsKey(spawnDat))
+		{
+			_log.warning("DayNightSpawnManager: Spawn already added into day map");
+			return;
+		}
+		else
+			_dayCreatures.put(spawnDat, null);
+	}
+	
+	public void addNightCreature(L2Spawn spawnDat)
+	{
+		if (_nightCreatures.containsKey(spawnDat))
+		{
+			_log.warning("DayNightSpawnManager: Spawn already added into night map");
+			return;
+		}
+		else
+			_nightCreatures.put(spawnDat, null);
+	}
+	
+	/*
+	 * Spawn Day Creatures, and Unspawn Night Creatures
+	 */
+	public void spawnDayCreatures()
+	{
+		spawnCreatures(_nightCreatures, _dayCreatures, "night", "day");
+	}
+	
+	/*
+	 * Spawn Night Creatures, and Unspawn Day Creatures
+	 */
+	public void spawnNightCreatures()
+	{
+		spawnCreatures(_dayCreatures, _nightCreatures, "day", "night");
+	}
+	
+	/*
+	 * Manage Spawn/Respawn
+	 * Arg 1 : Map with L2NpcInstance must be unspawned
+	 * Arg 2 : Map with L2NpcInstance must be spawned
+	 * Arg 3 : String for log info for unspawned L2NpcInstance
+	 * Arg 4 : String for log info for spawned L2NpcInstance
+	 */
+	private void spawnCreatures(Map<L2Spawn, L2Npc> UnSpawnCreatures, Map<L2Spawn, L2Npc> SpawnCreatures, String UnspawnLogInfo,
+			String SpawnLogInfo)
+	{
+		try
+		{
+			if (!UnSpawnCreatures.isEmpty())
+			{
+				int i = 0;
+				for (L2Npc dayCreature : UnSpawnCreatures.values())
+				{
+					if (dayCreature == null)
+						continue;
+					
+					dayCreature.getSpawn().stopRespawn();
+					dayCreature.deleteMe();
+					i++;
+				}
+				if (Config.DEBUG)
+					_log.info("DayNightSpawnManager: Deleted " + i + " " + UnspawnLogInfo + " creatures");
+			}
+			
+			int i = 0;
+			L2Npc creature = null;
+			for (L2Spawn spawnDat : SpawnCreatures.keySet())
+			{
+				if (SpawnCreatures.get(spawnDat) == null)
+				{
+					creature = spawnDat.doSpawn();
+					if (creature == null)
+						continue;
+					
+					SpawnCreatures.remove(spawnDat);
+					SpawnCreatures.put(spawnDat, creature);
+					creature.setCurrentHp(creature.getMaxHp());
+					creature.setCurrentMp(creature.getMaxMp());
+					creature.getSpawn().startRespawn();
+					if (creature.isDecayed())
+						creature.setDecayed(false);
+					if (creature.isDead())
+						creature.doRevive();
+				}
+				else
+				{
+					creature = SpawnCreatures.get(spawnDat);
+					if (creature == null)
+						continue;
+					
+					creature.getSpawn().startRespawn();
+					if (creature.isDecayed())
+						creature.setDecayed(false);
+					if (creature.isDead())
+						creature.doRevive();
+					creature.setCurrentHp(creature.getMaxHp());
+					creature.setCurrentMp(creature.getMaxMp());
+					creature.spawnMe();
+				}
+				
+				i++;
+			}
+			
+			if (Config.DEBUG)
+				_log.info("DayNightSpawnManager: Spawning " + i + " " + SpawnLogInfo + " creatures");
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+	}
+	
+	private void changeMode(int mode)
+	{
+		if (_nightCreatures.isEmpty() && _dayCreatures.isEmpty())
+			return;
+		
+		switch (mode)
+		{
+			case 0:
+				spawnDayCreatures();
+				specialNightBoss(0);
+				break;
+			case 1:
+				spawnNightCreatures();
+				specialNightBoss(1);
+				break;
+			default:
+				_log.warning("DayNightSpawnManager: Wrong mode sent");
+				break;
+		}
+	}
+	
+	public void notifyChangeMode()
+	{
+		try
+		{
+			if (GameTimeController.getInstance().isNowNight())
+				changeMode(1);
+			else
+				changeMode(0);
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+	}
+	
+	public void cleanUp()
+	{
+		_nightCreatures.clear();
+		_dayCreatures.clear();
+		_bosses.clear();
+	}
+	
+	private void specialNightBoss(int mode)
+	{
+		try
+		{
+			for (L2Spawn spawn : _bosses.keySet())
+			{
+				L2RaidBossInstance boss = _bosses.get(spawn);
+				
+				if (boss == null && mode == 1)
+				{
+					boss = (L2RaidBossInstance) spawn.doSpawn();
+					RaidBossSpawnManager.getInstance().notifySpawnNightBoss(boss);
+					_bosses.remove(spawn);
+					_bosses.put(spawn, boss);
+					continue;
+				}
+				
+				if (boss == null && mode == 0)
+					continue;
+				
+				if (boss.getNpcId() == 25328 && boss.getRaidStatus().equals(RaidBossSpawnManager.StatusEnum.ALIVE))
+					handleHellmans(boss, mode);
+				return;
+			}
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+	}
+	
+	private void handleHellmans(L2RaidBossInstance boss, int mode)
+	{
+		switch (mode)
+		{
+			case 0:
+				boss.deleteMe();
+				_log.info("DayNightSpawnManager: Deleting Hellman raidboss");
+				break;
+			case 1:
+				boss.spawnMe();
+				_log.info("DayNightSpawnManager: Spawning Hellman raidboss");
+				break;
+		}
+	}
+	
+	public L2RaidBossInstance handleBoss(L2Spawn spawnDat)
+	{
+		if (_bosses.containsKey(spawnDat))
+			return _bosses.get(spawnDat);
+		
+		if (GameTimeController.getInstance().isNowNight())
+		{
+			L2RaidBossInstance raidboss = (L2RaidBossInstance) spawnDat.doSpawn();
+			_bosses.put(spawnDat, raidboss);
+			
+			return raidboss;
+		}
+		else
+			_bosses.put(spawnDat, null);
+		
+		return null;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final DayNightSpawnManager _instance = new DayNightSpawnManager();
 	}
-    /*
-     * Manage Spawn/Respawn
-     * Arg 1 : Map with L2NpcInstance must be unspawned
-     * Arg 2 : Map with L2NpcInstance must be spawned
-     * Arg 3 : String for log info for unspawned L2NpcInstance
-     * Arg 4 : String for log info for spawned L2NpcInstance
-     */
-    private void spawnCreatures(Map<L2Spawn, L2Npc> UnSpawnCreatures,Map<L2Spawn, L2Npc> SpawnCreatures, String UnspawnLogInfo, String SpawnLogInfo){
-        try
-        {
-            if (!UnSpawnCreatures.isEmpty())
-            {
-                int i = 0;
-                for (L2Npc dayCreature : UnSpawnCreatures.values())
-                {
-                    if (dayCreature == null) continue;
-
-                    dayCreature.getSpawn().stopRespawn();
-                    dayCreature.deleteMe();
-                    i++;
-                }
-                if (Config.DEBUG)
-                	_log.info("DayNightSpawnManager: Deleted " + i + " "+UnspawnLogInfo+" creatures");
-            }
-
-            int i = 0;
-            L2Npc creature = null;
-            for (L2Spawn spawnDat : SpawnCreatures.keySet())
-            {
-                if (SpawnCreatures.get(spawnDat) == null)
-                {
-                    creature = spawnDat.doSpawn();
-                    if (creature == null) continue;
-
-                    SpawnCreatures.remove(spawnDat);
-                    SpawnCreatures.put(spawnDat, creature);
-                    creature.setCurrentHp(creature.getMaxHp());
-                    creature.setCurrentMp(creature.getMaxMp());
-                    creature.getSpawn().startRespawn();
-                    if (creature.isDecayed())
-                        creature.setDecayed(false);
-                    if (creature.isDead())
-                        creature.doRevive();
-                }
-                else
-                {
-                    creature = SpawnCreatures.get(spawnDat);
-                    if (creature == null) continue;
-
-                    creature.getSpawn().startRespawn();
-                    if (creature.isDecayed())
-                        creature.setDecayed(false);
-                    if (creature.isDead())
-                        creature.doRevive();
-                    creature.setCurrentHp(creature.getMaxHp());
-                    creature.setCurrentMp(creature.getMaxMp());
-                    creature.spawnMe();
-                }
-
-                i++;
-            }
-
-            if (Config.DEBUG)
-            	_log.info("DayNightSpawnManager: Spawning " + i + " "+SpawnLogInfo+" creatures");
-        }catch(Exception e){e.printStackTrace();}
-    }
-    private void changeMode(int mode)
-    {
-        if (_nightCreatures.isEmpty() && _dayCreatures.isEmpty())
-            return;
-
-        switch(mode) {
-            case 0:
-                spawnDayCreatures();
-                specialNightBoss(0);
-                break;
-            case 1:
-                spawnNightCreatures();
-                specialNightBoss(1);
-                break;
-                default:
-                    _log.warning("DayNightSpawnManager: Wrong mode sent");
-                break;
-        }
-    }
-
-    public void notifyChangeMode()
-    {
-        try{
-            if (GameTimeController.getInstance().isNowNight())
-                changeMode(1);
-            else
-                changeMode(0);
-        }catch(Exception e){e.printStackTrace();}
-    }
-
-    public void cleanUp()
-    {
-        _nightCreatures.clear();
-        _dayCreatures.clear();
-        _bosses.clear();
-    }
-
-    private void specialNightBoss(int mode)
-    {
-        try{
-        for (L2Spawn spawn : _bosses.keySet())
-        {
-            L2RaidBossInstance boss = _bosses.get(spawn);
-
-            if (boss == null && mode == 1)
-            {
-                boss = (L2RaidBossInstance)spawn.doSpawn();
-                RaidBossSpawnManager.getInstance().notifySpawnNightBoss(boss);
-                _bosses.remove(spawn);
-                _bosses.put(spawn, boss);
-                continue;
-            }
-
-            if (boss == null && mode == 0)
-                continue;
-
-            if(boss.getNpcId() == 25328 &&
-                    boss.getRaidStatus().equals(RaidBossSpawnManager.StatusEnum.ALIVE))
-                handleHellmans(boss, mode);
-            return;
-        }
-        }catch(Exception e){e.printStackTrace();}
-    }
-
-    private void handleHellmans(L2RaidBossInstance boss, int mode)
-    {
-        switch(mode)
-        {
-            case 0:
-                boss.deleteMe();
-                _log.info("DayNightSpawnManager: Deleting Hellman raidboss");
-                break;
-            case 1:
-                boss.spawnMe();
-                _log.info("DayNightSpawnManager: Spawning Hellman raidboss");
-                break;
-        }
-    }
-
-    public L2RaidBossInstance handleBoss(L2Spawn spawnDat)
-    {
-        if(_bosses.containsKey(spawnDat)) return _bosses.get(spawnDat);
-
-        if (GameTimeController.getInstance().isNowNight())
-        {
-            L2RaidBossInstance raidboss = (L2RaidBossInstance)spawnDat.doSpawn();
-            _bosses.put(spawnDat, raidboss);
-
-            return raidboss;
-        }
-        else
-            _bosses.put(spawnDat, null);
-
-       return null;
-    }
 }

+ 443 - 437
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/DimensionalRiftManager.java

@@ -51,441 +51,447 @@ import org.w3c.dom.Node;
 */
 public class DimensionalRiftManager
 {
-
-    private static Logger _log = Logger.getLogger(DimensionalRiftManager.class.getName());
-    private static DimensionalRiftManager _instance;
-    private FastMap<Byte, FastMap<Byte, DimensionalRiftRoom>> _rooms = new FastMap<Byte, FastMap<Byte, DimensionalRiftRoom>>();
-    private final int DIMENSIONAL_FRAGMENT_ITEM_ID = 7079;
-
-    public static DimensionalRiftManager getInstance()
-    {
-        if(_instance == null)
-        {
-            _instance = new DimensionalRiftManager();
-            new Quest(635, "RiftQuest", "Dummy Quest shown in players' questlist when inside the rift");
-        }
-
-        return _instance;
-    }
-
-    private DimensionalRiftManager()
-    {
-        loadRooms();
-        loadSpawns();
-    }
-
-    public DimensionalRiftRoom getRoom(byte type, byte room)
-    {
-        return _rooms.get(type) == null ? null : _rooms.get(type).get(room);
-    }
-
-    private void loadRooms()
-    {
-        Connection con = null;
-
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-            PreparedStatement s = con.prepareStatement("SELECT * FROM dimensional_rift");
-            ResultSet rs = s.executeQuery();
-
-            while(rs.next())
-            {
-                // 0 waiting room, 1 recruit, 2 soldier, 3 officer, 4 captain , 5 commander, 6 hero
-                byte type = rs.getByte("type");
-                byte room_id = rs.getByte("room_id");
-
-                //coords related
-                int xMin = rs.getInt("xMin");
-                int xMax = rs.getInt("xMax");
-                int yMin = rs.getInt("yMin");
-                int yMax = rs.getInt("yMax");
-                int z1 = rs.getInt("zMin");
-                int z2 = rs.getInt("zMax");
-                int xT = rs.getInt("xT");
-                int yT = rs.getInt("yT");
-                int zT = rs.getInt("zT");
-                boolean isBossRoom = rs.getByte("boss") > 0;
-
-                if(!_rooms.containsKey(type))
-                    _rooms.put(type, new FastMap<Byte, DimensionalRiftRoom>());
-
-                _rooms.get(type).put(room_id, new DimensionalRiftRoom(type, room_id, xMin, xMax, yMin, yMax, z1, z2, xT, yT, zT, isBossRoom));
-            }
-
-            s.close();
-            con.close();
-        }
-        catch (Exception e)
-        {
-            _log.warning("Can't load Dimension Rift zones. " + e);
-        }
-        finally
-        {
-            try
-            {
-                con.close();
-            }
-            catch (Exception e)
-            { /*do nothing */}
-        }
-
-        int typeSize = _rooms.keySet().size();
-        int roomSize = 0;
-
-        for(Byte b : _rooms.keySet())
-            roomSize += _rooms.get(b).keySet().size();
-
-        _log.info("DimensionalRiftManager: Loaded " + typeSize + " room types with " + roomSize + " rooms.");
-    }
-
-    public void loadSpawns()
-    {
-        int countGood = 0, countBad = 0;
-        try
-        {
-            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-            factory.setValidating(false);
-            factory.setIgnoringComments(true);
-
-            File file = new File(Config.DATAPACK_ROOT+"/data/dimensionalRift.xml");
-            if (!file.exists())
-                throw new IOException();
-
-            Document doc = factory.newDocumentBuilder().parse(file);
-            NamedNodeMap attrs;
-            byte type, roomId;
-            int mobId, x, y, z, delay, count;
-            L2Spawn spawnDat;
-            L2NpcTemplate template;
-
-            for (Node rift = doc.getFirstChild(); rift != null; rift = rift.getNextSibling())
-            {
-                if ("rift".equalsIgnoreCase(rift.getNodeName()))
-                {
-                    for (Node area = rift.getFirstChild(); area != null; area = area.getNextSibling())
-                    {
-                        if ("area".equalsIgnoreCase(area.getNodeName()))
-                        {
-                            attrs = area.getAttributes();
-                            type = Byte.parseByte(attrs.getNamedItem("type").getNodeValue());
-
-                            for (Node room = area.getFirstChild(); room != null; room = room.getNextSibling())
-                            {
-                                if ("room".equalsIgnoreCase(room.getNodeName()))
-                                {
-                                    attrs = room.getAttributes();
-                                    roomId = Byte.parseByte(attrs.getNamedItem("id").getNodeValue());
-
-                                    for (Node spawn = room.getFirstChild(); spawn != null; spawn = spawn.getNextSibling())
-                                    {
-                                        if ("spawn".equalsIgnoreCase(spawn.getNodeName()))
-                                        {
-                                            attrs = spawn.getAttributes();
-                                            mobId = Integer.parseInt(attrs.getNamedItem("mobId").getNodeValue());
-                                            delay = Integer.parseInt(attrs.getNamedItem("delay").getNodeValue());
-                                            count = Integer.parseInt(attrs.getNamedItem("count").getNodeValue());
-
-                                            template = NpcTable.getInstance().getTemplate(mobId);
-                                            if (template==null)
-                                            {
-                                                _log.warning("Template "+mobId+" not found!");
-                                            }
-                                            if(!_rooms.containsKey(type))
-                                            {
-                                                _log.warning("Type "+type+" not found!");
-                                            }
-                                            else if(!_rooms.get(type).containsKey(roomId))
-                                            {
-                                                _log.warning("Room "+roomId+" in Type "+type+" not found!");
-                                            }
-                                            
-                                            for (int i = 0; i < count; i++)
-                                            {
-	                                            DimensionalRiftRoom riftRoom = _rooms.get(type).get(roomId);
-	                                            x = riftRoom.getRandomX();
-	                                            y = riftRoom.getRandomY();
-	                                            z = riftRoom.getTeleportCoords()[2];
-
-	                                            if (template != null && _rooms.containsKey(type) && _rooms.get(type).containsKey(roomId))
-	                                            {
-	                                                spawnDat = new L2Spawn(template);
-	                                                spawnDat.setAmount(1);
-	                                                spawnDat.setLocx(x);
-	                                                spawnDat.setLocy(y);
-	                                                spawnDat.setLocz(z);
-	                                                spawnDat.setHeading(-1);
-	                                                spawnDat.setRespawnDelay(delay);
-	                                                SpawnTable.getInstance().addNewSpawn(spawnDat, false);
-	                                                _rooms.get(type).get(roomId).getSpawns().add(spawnDat);
-	                                                countGood++;
-	                                            }
-	                                            else
-	                                            {
-	                                                countBad++;
-	                                            }
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        catch(Exception e)
-        {
-            _log.warning("Error on loading dimensional rift spawns: " + e);
-            e.printStackTrace();
-        }
-        _log.info("DimensionalRiftManager: Loaded " + countGood + " dimensional rift spawns, "+countBad + " errors.");
-    }
-
-    public void reload()
-    {
-        for(Byte b : _rooms.keySet())
-        {
-            for(int i : _rooms.get(b).keySet())
-            {
-                _rooms.get(b).get(i).getSpawns().clear();
-            }
-            _rooms.get(b).clear();
-       }
-        _rooms.clear();
-        loadRooms();
-        loadSpawns();
-    }
-
-    public boolean checkIfInRiftZone(int x, int y, int z, boolean ignorePeaceZone)
-    {
-        if(ignorePeaceZone)
-            return _rooms.get((byte) 0).get((byte) 1).checkIfInZone(x, y, z);
-        else
-            return _rooms.get((byte) 0).get((byte) 1).checkIfInZone(x, y, z) && !_rooms.get((byte) 0).get((byte) 0).checkIfInZone(x, y, z);
-    }
-
-    public boolean checkIfInPeaceZone(int x, int y, int z)
-    {
-        return _rooms.get((byte) 0).get((byte) 0).checkIfInZone(x, y, z);
-    }
-
-    public void teleportToWaitingRoom(L2PcInstance player)
-    {
-        int[] coords = getRoom((byte) 0, (byte) 0).getTeleportCoords();
-        player.teleToLocation(coords[0], coords[1], coords[2]);
-    }
-
-    public void start(L2PcInstance player, byte type, L2Npc npc)
-    {
-        boolean canPass = true;
-        if(!player.isInParty())
-        {
-            showHtmlFile(player, "data/html/seven_signs/rift/NoParty.htm", npc);
-            return;
-        }
-
-        if(player.getParty().getPartyLeaderOID() != player.getObjectId())
-        {
-            showHtmlFile(player, "data/html/seven_signs/rift/NotPartyLeader.htm", npc);
-            return;
-        }
-
-        if(player.getParty().isInDimensionalRift())
-        {
-            handleCheat(player, npc);
-            return;
-        }
-
-        if(player.getParty().getMemberCount() < Config.RIFT_MIN_PARTY_SIZE)
-        {
-            NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
-            html.setFile("data/html/seven_signs/rift/SmallParty.htm");
-            html.replace("%npc_name%", npc.getName());
-            html.replace("%count%", Integer.toString(Config.RIFT_MIN_PARTY_SIZE));
-            player.sendPacket(html);
-            return;
-        }
-
-        for(L2PcInstance p : player.getParty().getPartyMembers())
-            if(!checkIfInPeaceZone(p.getX(), p.getY(), p.getZ()))
-                canPass = false;
-
-        if(!canPass)
-        {
-            showHtmlFile(player, "data/html/seven_signs/rift/NotInWaitingRoom.htm", npc);
-            return;
-        }
-
-        L2ItemInstance i;
-        for(L2PcInstance p : player.getParty().getPartyMembers())
-        {
-            i = p.getInventory().getItemByItemId(DIMENSIONAL_FRAGMENT_ITEM_ID);
-
-            if(i == null)
-            {
-                canPass = false;
-                break;
-            }
-
-            if(i.getCount() > 0)
-                if(i.getCount() < getNeededItems(type))
-                    canPass = false;
-        }
-
-        if(!canPass)
-        {
-            NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
-            html.setFile("data/html/seven_signs/rift/NoFragments.htm");
-            html.replace("%npc_name%", npc.getName());
-            html.replace("%count%", Integer.toString(getNeededItems(type)));
-            player.sendPacket(html);
-            return;
-        }
-
-        for (L2PcInstance p : player.getParty().getPartyMembers())
-        {
-            i = p.getInventory().getItemByItemId(DIMENSIONAL_FRAGMENT_ITEM_ID);
-            p.destroyItem("RiftEntrance", i.getObjectId(), getNeededItems(type), null, false);
-        }
-
-        new DimensionalRift(player.getParty(), type, (byte) Rnd.get(1, 9));
-    }
-
-    public void killRift(DimensionalRift d)
-    {
-        if(d.getTeleportTimerTask() != null)d.getTeleportTimerTask().cancel();
-        d.setTeleportTimerTask(null);
-
-        if(d.getTeleportTimer() != null)d.getTeleportTimer().cancel();
-        d.setTeleportTimer(null);
-
-        if(d.getSpawnTimerTask() != null)d.getSpawnTimerTask().cancel();
-        d.setSpawnTimerTask(null);
-
-        if(d.getSpawnTimer() != null)d.getSpawnTimer().cancel();
-        d.setSpawnTimer(null);
-    }
-
-    public class DimensionalRiftRoom
-    {
-        protected final byte _type;
-        protected final byte _room;
-        private final int _xMin;
-        private final int _xMax;
-        private final int _yMin;
-        private final int _yMax;
-        private final int _zMin;
-        private final int _zMax;
-        private final int[] _teleportCoords;
-        private final Shape _s;
-        private final boolean _isBossRoom;
-        private final FastList<L2Spawn> _roomSpawns;
-        protected final FastList<L2Npc> _roomMobs;
-
-        public DimensionalRiftRoom(byte type, byte room, int xMin, int xMax, int yMin, int yMax, int zMin, int zMax, int xT, int yT, int zT, boolean isBossRoom)
-        {
-            _type = type;
-            _room = room;
-            _xMin = (xMin + 128);
-            _xMax = (xMax - 128);
-            _yMin = (yMin + 128);
-            _yMax = (yMax - 128);
-            _zMin = zMin;
-            _zMax = zMax;
-            _teleportCoords = new int[] { xT, yT, zT };
-            _isBossRoom = isBossRoom;
-            _roomSpawns = new FastList<L2Spawn>();
-            _roomMobs = new FastList<L2Npc>();
-            _s = new Polygon(new int[] { xMin, xMax, xMax, xMin }, new int[] { yMin, yMin, yMax, yMax }, 4);
-        }
-
-        public int getRandomX()
-        {
-        	return Rnd.get(_xMin, _xMax);
-        }
-
-        public int getRandomY()
-        {
-        	return Rnd.get(_yMin, _yMax);
-        }
-
-        public int[] getTeleportCoords()
-        {
-            return _teleportCoords;
-        }
-
-        public boolean checkIfInZone(int x, int y, int z)
-        {
-            return _s.contains(x, y) && z >= _zMin && z <= _zMax;
-        }
-
-        public boolean isBossRoom()
-        {
-            return _isBossRoom;
-        }
-
-        public FastList<L2Spawn> getSpawns()
-        {
-            return _roomSpawns;
-        }
-
-        public void spawn()
-        {
-            for(L2Spawn spawn : _roomSpawns)
-            {
-                spawn.doSpawn();
-                spawn.startRespawn();
-            }
-        }
-
-        public void unspawn()
-        {
-            for(L2Spawn spawn : _roomSpawns)
-            {
-                spawn.stopRespawn();
-                if(spawn.getLastSpawn() != null)
-                    spawn.getLastSpawn().deleteMe();
-            }
-        }
-    }
-
-    private int getNeededItems(byte type)
-    {
-        switch(type)
-        {
-            case 1:
-                return Config.RIFT_ENTER_COST_RECRUIT;
-            case 2:
-                return Config.RIFT_ENTER_COST_SOLDIER;
-            case 3:
-                return Config.RIFT_ENTER_COST_OFFICER;
-            case 4:
-                return Config.RIFT_ENTER_COST_CAPTAIN;
-            case 5:
-                return Config.RIFT_ENTER_COST_COMMANDER;
-            case 6:
-                return Config.RIFT_ENTER_COST_HERO;
-            default:
-                return 999999;
-        }
-    }
-
-    public void showHtmlFile(L2PcInstance player, String file, L2Npc npc)
-    {
-        NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
-        html.setFile(file);
-        html.replace("%npc_name%", npc.getName());
-        player.sendPacket(html);
-    }
-
-    public void handleCheat(L2PcInstance player, L2Npc npc)
-    {
-        showHtmlFile(player, "data/html/seven_signs/rift/Cheater.htm", npc);
-        if (!player.isGM())
-        {
-            _log.warning("Player "+player.getName()+"("+player.getObjectId()+") was cheating in dimension rift area!");
-            Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" tried to cheat in dimensional rift.",Config.DEFAULT_PUNISH);
-        }
-    }
+	
+	private static Logger _log = Logger.getLogger(DimensionalRiftManager.class.getName());
+	private FastMap<Byte, FastMap<Byte, DimensionalRiftRoom>> _rooms = new FastMap<Byte, FastMap<Byte, DimensionalRiftRoom>>();
+	private final int DIMENSIONAL_FRAGMENT_ITEM_ID = 7079;
+	
+	public static DimensionalRiftManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private DimensionalRiftManager()
+	{
+		loadRooms();
+		loadSpawns();
+		new Quest(635, "RiftQuest", "Dummy Quest shown in players' questlist when inside the rift");
+	}
+	
+	public DimensionalRiftRoom getRoom(byte type, byte room)
+	{
+		return _rooms.get(type) == null ? null : _rooms.get(type).get(room);
+	}
+	
+	private void loadRooms()
+	{
+		Connection con = null;
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement s = con.prepareStatement("SELECT * FROM dimensional_rift");
+			ResultSet rs = s.executeQuery();
+			
+			while (rs.next())
+			{
+				// 0 waiting room, 1 recruit, 2 soldier, 3 officer, 4 captain , 5 commander, 6 hero
+				byte type = rs.getByte("type");
+				byte room_id = rs.getByte("room_id");
+				
+				//coords related
+				int xMin = rs.getInt("xMin");
+				int xMax = rs.getInt("xMax");
+				int yMin = rs.getInt("yMin");
+				int yMax = rs.getInt("yMax");
+				int z1 = rs.getInt("zMin");
+				int z2 = rs.getInt("zMax");
+				int xT = rs.getInt("xT");
+				int yT = rs.getInt("yT");
+				int zT = rs.getInt("zT");
+				boolean isBossRoom = rs.getByte("boss") > 0;
+				
+				if (!_rooms.containsKey(type))
+					_rooms.put(type, new FastMap<Byte, DimensionalRiftRoom>());
+				
+				_rooms.get(type).put(room_id, new DimensionalRiftRoom(type, room_id, xMin, xMax, yMin, yMax, z1, z2, xT, yT, zT, isBossRoom));
+			}
+			
+			s.close();
+			con.close();
+		}
+		catch (Exception e)
+		{
+			_log.warning("Can't load Dimension Rift zones. " + e);
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{ /*do nothing */
+			}
+		}
+		
+		int typeSize = _rooms.keySet().size();
+		int roomSize = 0;
+		
+		for (Byte b : _rooms.keySet())
+			roomSize += _rooms.get(b).keySet().size();
+		
+		_log.info("DimensionalRiftManager: Loaded " + typeSize + " room types with " + roomSize + " rooms.");
+	}
+	
+	public void loadSpawns()
+	{
+		int countGood = 0, countBad = 0;
+		try
+		{
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			factory.setValidating(false);
+			factory.setIgnoringComments(true);
+			
+			File file = new File(Config.DATAPACK_ROOT + "/data/dimensionalRift.xml");
+			if (!file.exists())
+				throw new IOException();
+			
+			Document doc = factory.newDocumentBuilder().parse(file);
+			NamedNodeMap attrs;
+			byte type, roomId;
+			int mobId, x, y, z, delay, count;
+			L2Spawn spawnDat;
+			L2NpcTemplate template;
+			
+			for (Node rift = doc.getFirstChild(); rift != null; rift = rift.getNextSibling())
+			{
+				if ("rift".equalsIgnoreCase(rift.getNodeName()))
+				{
+					for (Node area = rift.getFirstChild(); area != null; area = area.getNextSibling())
+					{
+						if ("area".equalsIgnoreCase(area.getNodeName()))
+						{
+							attrs = area.getAttributes();
+							type = Byte.parseByte(attrs.getNamedItem("type").getNodeValue());
+							
+							for (Node room = area.getFirstChild(); room != null; room = room.getNextSibling())
+							{
+								if ("room".equalsIgnoreCase(room.getNodeName()))
+								{
+									attrs = room.getAttributes();
+									roomId = Byte.parseByte(attrs.getNamedItem("id").getNodeValue());
+									
+									for (Node spawn = room.getFirstChild(); spawn != null; spawn = spawn.getNextSibling())
+									{
+										if ("spawn".equalsIgnoreCase(spawn.getNodeName()))
+										{
+											attrs = spawn.getAttributes();
+											mobId = Integer.parseInt(attrs.getNamedItem("mobId").getNodeValue());
+											delay = Integer.parseInt(attrs.getNamedItem("delay").getNodeValue());
+											count = Integer.parseInt(attrs.getNamedItem("count").getNodeValue());
+											
+											template = NpcTable.getInstance().getTemplate(mobId);
+											if (template == null)
+											{
+												_log.warning("Template " + mobId + " not found!");
+											}
+											if (!_rooms.containsKey(type))
+											{
+												_log.warning("Type " + type + " not found!");
+											}
+											else if (!_rooms.get(type).containsKey(roomId))
+											{
+												_log.warning("Room " + roomId + " in Type " + type + " not found!");
+											}
+											
+											for (int i = 0; i < count; i++)
+											{
+												DimensionalRiftRoom riftRoom = _rooms.get(type).get(roomId);
+												x = riftRoom.getRandomX();
+												y = riftRoom.getRandomY();
+												z = riftRoom.getTeleportCoords()[2];
+												
+												if (template != null && _rooms.containsKey(type) && _rooms.get(type).containsKey(roomId))
+												{
+													spawnDat = new L2Spawn(template);
+													spawnDat.setAmount(1);
+													spawnDat.setLocx(x);
+													spawnDat.setLocy(y);
+													spawnDat.setLocz(z);
+													spawnDat.setHeading(-1);
+													spawnDat.setRespawnDelay(delay);
+													SpawnTable.getInstance().addNewSpawn(spawnDat, false);
+													_rooms.get(type).get(roomId).getSpawns().add(spawnDat);
+													countGood++;
+												}
+												else
+												{
+													countBad++;
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		catch (Exception e)
+		{
+			_log.warning("Error on loading dimensional rift spawns: " + e);
+			e.printStackTrace();
+		}
+		_log.info("DimensionalRiftManager: Loaded " + countGood + " dimensional rift spawns, " + countBad + " errors.");
+	}
+	
+	public void reload()
+	{
+		for (Byte b : _rooms.keySet())
+		{
+			for (int i : _rooms.get(b).keySet())
+			{
+				_rooms.get(b).get(i).getSpawns().clear();
+			}
+			_rooms.get(b).clear();
+		}
+		_rooms.clear();
+		loadRooms();
+		loadSpawns();
+	}
+	
+	public boolean checkIfInRiftZone(int x, int y, int z, boolean ignorePeaceZone)
+	{
+		if (ignorePeaceZone)
+			return _rooms.get((byte) 0).get((byte) 1).checkIfInZone(x, y, z);
+		else
+			return _rooms.get((byte) 0).get((byte) 1).checkIfInZone(x, y, z) && !_rooms.get((byte) 0).get((byte) 0).checkIfInZone(x, y, z);
+	}
+	
+	public boolean checkIfInPeaceZone(int x, int y, int z)
+	{
+		return _rooms.get((byte) 0).get((byte) 0).checkIfInZone(x, y, z);
+	}
+	
+	public void teleportToWaitingRoom(L2PcInstance player)
+	{
+		int[] coords = getRoom((byte) 0, (byte) 0).getTeleportCoords();
+		player.teleToLocation(coords[0], coords[1], coords[2]);
+	}
+	
+	public void start(L2PcInstance player, byte type, L2Npc npc)
+	{
+		boolean canPass = true;
+		if (!player.isInParty())
+		{
+			showHtmlFile(player, "data/html/seven_signs/rift/NoParty.htm", npc);
+			return;
+		}
+		
+		if (player.getParty().getPartyLeaderOID() != player.getObjectId())
+		{
+			showHtmlFile(player, "data/html/seven_signs/rift/NotPartyLeader.htm", npc);
+			return;
+		}
+		
+		if (player.getParty().isInDimensionalRift())
+		{
+			handleCheat(player, npc);
+			return;
+		}
+		
+		if (player.getParty().getMemberCount() < Config.RIFT_MIN_PARTY_SIZE)
+		{
+			NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
+			html.setFile("data/html/seven_signs/rift/SmallParty.htm");
+			html.replace("%npc_name%", npc.getName());
+			html.replace("%count%", Integer.toString(Config.RIFT_MIN_PARTY_SIZE));
+			player.sendPacket(html);
+			return;
+		}
+		
+		for (L2PcInstance p : player.getParty().getPartyMembers())
+			if (!checkIfInPeaceZone(p.getX(), p.getY(), p.getZ()))
+				canPass = false;
+		
+		if (!canPass)
+		{
+			showHtmlFile(player, "data/html/seven_signs/rift/NotInWaitingRoom.htm", npc);
+			return;
+		}
+		
+		L2ItemInstance i;
+		for (L2PcInstance p : player.getParty().getPartyMembers())
+		{
+			i = p.getInventory().getItemByItemId(DIMENSIONAL_FRAGMENT_ITEM_ID);
+			
+			if (i == null)
+			{
+				canPass = false;
+				break;
+			}
+			
+			if (i.getCount() > 0)
+				if (i.getCount() < getNeededItems(type))
+					canPass = false;
+		}
+		
+		if (!canPass)
+		{
+			NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
+			html.setFile("data/html/seven_signs/rift/NoFragments.htm");
+			html.replace("%npc_name%", npc.getName());
+			html.replace("%count%", Integer.toString(getNeededItems(type)));
+			player.sendPacket(html);
+			return;
+		}
+		
+		for (L2PcInstance p : player.getParty().getPartyMembers())
+		{
+			i = p.getInventory().getItemByItemId(DIMENSIONAL_FRAGMENT_ITEM_ID);
+			p.destroyItem("RiftEntrance", i.getObjectId(), getNeededItems(type), null, false);
+		}
+		
+		new DimensionalRift(player.getParty(), type, (byte) Rnd.get(1, 9));
+	}
+	
+	public void killRift(DimensionalRift d)
+	{
+		if (d.getTeleportTimerTask() != null)
+			d.getTeleportTimerTask().cancel();
+		d.setTeleportTimerTask(null);
+		
+		if (d.getTeleportTimer() != null)
+			d.getTeleportTimer().cancel();
+		d.setTeleportTimer(null);
+		
+		if (d.getSpawnTimerTask() != null)
+			d.getSpawnTimerTask().cancel();
+		d.setSpawnTimerTask(null);
+		
+		if (d.getSpawnTimer() != null)
+			d.getSpawnTimer().cancel();
+		d.setSpawnTimer(null);
+	}
+	
+	public class DimensionalRiftRoom
+	{
+		protected final byte _type;
+		protected final byte _room;
+		private final int _xMin;
+		private final int _xMax;
+		private final int _yMin;
+		private final int _yMax;
+		private final int _zMin;
+		private final int _zMax;
+		private final int[] _teleportCoords;
+		private final Shape _s;
+		private final boolean _isBossRoom;
+		private final FastList<L2Spawn> _roomSpawns;
+		protected final FastList<L2Npc> _roomMobs;
+		
+		public DimensionalRiftRoom(byte type, byte room, int xMin, int xMax, int yMin, int yMax, int zMin, int zMax, int xT, int yT,
+				int zT, boolean isBossRoom)
+		{
+			_type = type;
+			_room = room;
+			_xMin = (xMin + 128);
+			_xMax = (xMax - 128);
+			_yMin = (yMin + 128);
+			_yMax = (yMax - 128);
+			_zMin = zMin;
+			_zMax = zMax;
+			_teleportCoords = new int[] { xT, yT, zT };
+			_isBossRoom = isBossRoom;
+			_roomSpawns = new FastList<L2Spawn>();
+			_roomMobs = new FastList<L2Npc>();
+			_s = new Polygon(new int[] { xMin, xMax, xMax, xMin }, new int[] { yMin, yMin, yMax, yMax }, 4);
+		}
+		
+		public int getRandomX()
+		{
+			return Rnd.get(_xMin, _xMax);
+		}
+		
+		public int getRandomY()
+		{
+			return Rnd.get(_yMin, _yMax);
+		}
+		
+		public int[] getTeleportCoords()
+		{
+			return _teleportCoords;
+		}
+		
+		public boolean checkIfInZone(int x, int y, int z)
+		{
+			return _s.contains(x, y) && z >= _zMin && z <= _zMax;
+		}
+		
+		public boolean isBossRoom()
+		{
+			return _isBossRoom;
+		}
+		
+		public FastList<L2Spawn> getSpawns()
+		{
+			return _roomSpawns;
+		}
+		
+		public void spawn()
+		{
+			for (L2Spawn spawn : _roomSpawns)
+			{
+				spawn.doSpawn();
+				spawn.startRespawn();
+			}
+		}
+		
+		public void unspawn()
+		{
+			for (L2Spawn spawn : _roomSpawns)
+			{
+				spawn.stopRespawn();
+				if (spawn.getLastSpawn() != null)
+					spawn.getLastSpawn().deleteMe();
+			}
+		}
+	}
+	
+	private int getNeededItems(byte type)
+	{
+		switch (type)
+		{
+			case 1:
+				return Config.RIFT_ENTER_COST_RECRUIT;
+			case 2:
+				return Config.RIFT_ENTER_COST_SOLDIER;
+			case 3:
+				return Config.RIFT_ENTER_COST_OFFICER;
+			case 4:
+				return Config.RIFT_ENTER_COST_CAPTAIN;
+			case 5:
+				return Config.RIFT_ENTER_COST_COMMANDER;
+			case 6:
+				return Config.RIFT_ENTER_COST_HERO;
+			default:
+				return 999999;
+		}
+	}
+	
+	public void showHtmlFile(L2PcInstance player, String file, L2Npc npc)
+	{
+		NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
+		html.setFile(file);
+		html.replace("%npc_name%", npc.getName());
+		player.sendPacket(html);
+	}
+	
+	public void handleCheat(L2PcInstance player, L2Npc npc)
+	{
+		showHtmlFile(player, "data/html/seven_signs/rift/Cheater.htm", npc);
+		if (!player.isGM())
+		{
+			_log.warning("Player " + player.getName() + "(" + player.getObjectId() + ") was cheating in dimension rift area!");
+			Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " tried to cheat in dimensional rift.", Config.DEFAULT_PUNISH);
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final DimensionalRiftManager _instance = new DimensionalRiftManager();
+	}
 }

+ 62 - 44
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/DuelManager.java

@@ -25,24 +25,17 @@ import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket;
 public class DuelManager
 {
 	private static final Logger _log = Logger.getLogger(DuelManager.class.getName());
-
-	// =========================================================
-	private static DuelManager _instance;
-
+	
 	public static final DuelManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new DuelManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	// =========================================================
 	// Data Field
 	private FastList<Duel> _duels;
 	private int _currentDuelId = 0x90;
-
+	
 	// =========================================================
 	// Constructor
 	private DuelManager()
@@ -50,33 +43,36 @@ public class DuelManager
 		_log.info("Initializing DuelManager");
 		_duels = new FastList<Duel>();
 	}
-
+	
 	// =========================================================
 	// Method - Private
-
+	
 	private int getNextDuelId()
 	{
 		// In case someone wants to run the server forever :)
-		if (++_currentDuelId >= 2147483640) _currentDuelId = 1;
+		if (++_currentDuelId >= 2147483640)
+			_currentDuelId = 1;
 		return _currentDuelId;
 	}
-
+	
 	// =========================================================
 	// Method - Public
-
+	
 	public Duel getDuel(int duelId)
 	{
 		for (FastList.Node<Duel> e = _duels.head(), end = _duels.tail(); (e = e.getNext()) != end;)
 		{
-			if (e.getValue().getId() == duelId) return e.getValue();
+			if (e.getValue().getId() == duelId)
+				return e.getValue();
 		}
 		return null;
 	}
-
+	
 	public void addDuel(L2PcInstance playerA, L2PcInstance playerB, int partyDuel)
 	{
-		if (playerA == null || playerB == null) return;
-
+		if (playerA == null || playerB == null)
+			return;
+		
 		// return if a player has PvPFlag
 		String engagedInPvP = "The duel was canceled because a duelist engaged in PvP combat.";
 		if (partyDuel == 1)
@@ -84,13 +80,21 @@ public class DuelManager
 			boolean playerInPvP = false;
 			for (L2PcInstance temp : playerA.getParty().getPartyMembers())
 			{
-				if (temp.getPvpFlag() != 0) { playerInPvP = true; break; }
+				if (temp.getPvpFlag() != 0)
+				{
+					playerInPvP = true;
+					break;
+				}
 			}
 			if (!playerInPvP)
 			{
 				for (L2PcInstance temp : playerB.getParty().getPartyMembers())
 				{
-					if (temp.getPvpFlag() != 0) { playerInPvP = true; break; }
+					if (temp.getPvpFlag() != 0)
+					{
+						playerInPvP = true;
+						break;
+					}
 				}
 			}
 			// A player has PvP flag
@@ -116,34 +120,37 @@ public class DuelManager
 				return;
 			}
 		}
-
+		
 		Duel duel = new Duel(playerA, playerB, partyDuel, getNextDuelId());
 		_duels.add(duel);
 	}
-
+	
 	public void removeDuel(Duel duel)
 	{
 		_duels.remove(duel);
 	}
-
+	
 	public void doSurrender(L2PcInstance player)
 	{
-		if (player == null || !player.isInDuel()) return;
+		if (player == null || !player.isInDuel())
+			return;
 		Duel duel = getDuel(player.getDuelId());
 		duel.doSurrender(player);
 	}
-
+	
 	/**
 	 * Updates player states.
 	 * @param player - the dieing player
 	 */
 	public void onPlayerDefeat(L2PcInstance player)
 	{
-		if (player == null || !player.isInDuel()) return;
+		if (player == null || !player.isInDuel())
+			return;
 		Duel duel = getDuel(player.getDuelId());
-		if (duel != null) duel.onPlayerDefeat(player);
+		if (duel != null)
+			duel.onPlayerDefeat(player);
 	}
-
+	
 	/**
 	 * Registers a debuff which will be removed if the duel ends
 	 * @param player
@@ -151,22 +158,26 @@ public class DuelManager
 	 */
 	public void onBuff(L2PcInstance player, L2Effect buff)
 	{
-		if (player == null || !player.isInDuel() || buff == null) return;
+		if (player == null || !player.isInDuel() || buff == null)
+			return;
 		Duel duel = getDuel(player.getDuelId());
-		if (duel != null) duel.onBuff(player, buff);
+		if (duel != null)
+			duel.onBuff(player, buff);
 	}
-
+	
 	/**
 	 * Removes player from duel.
 	 * @param player - the removed player
 	 */
 	public void onRemoveFromParty(L2PcInstance player)
 	{
-		if (player == null || !player.isInDuel()) return;
+		if (player == null || !player.isInDuel())
+			return;
 		Duel duel = getDuel(player.getDuelId());
-		if (duel != null) duel.onRemoveFromParty(player);
+		if (duel != null)
+			duel.onRemoveFromParty(player);
 	}
-
+	
 	/**
 	 * Broadcasts a packet to the team opposing the given player.
 	 * @param player
@@ -174,11 +185,14 @@ public class DuelManager
 	 */
 	public void broadcastToOppositTeam(L2PcInstance player, L2GameServerPacket packet)
 	{
-		if (player == null || !player.isInDuel()) return;
+		if (player == null || !player.isInDuel())
+			return;
 		Duel duel = getDuel(player.getDuelId());
-		if (duel == null) return;
-		if (duel.getPlayerA() == null || duel.getPlayerB() == null) return;
-
+		if (duel == null)
+			return;
+		if (duel.getPlayerA() == null || duel.getPlayerB() == null)
+			return;
+		
 		if (duel.getPlayerA() == player)
 		{
 			duel.broadcastToTeam2(packet);
@@ -189,16 +203,20 @@ public class DuelManager
 		}
 		else if (duel.isPartyDuel())
 		{
-			if (duel.getPlayerA().getParty() != null &&
-					duel.getPlayerA().getParty().getPartyMembers().contains(player))
+			if (duel.getPlayerA().getParty() != null && duel.getPlayerA().getParty().getPartyMembers().contains(player))
 			{
 				duel.broadcastToTeam2(packet);
 			}
-			else if (duel.getPlayerB().getParty() != null &&
-					duel.getPlayerB().getParty().getPartyMembers().contains(player))
+			else if (duel.getPlayerB().getParty() != null && duel.getPlayerB().getParty().getPartyMembers().contains(player))
 			{
 				duel.broadcastToTeam1(packet);
 			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final DuelManager _instance = new DuelManager();
+	}
 }

+ 183 - 172
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortManager.java

@@ -22,184 +22,195 @@ import java.util.logging.Logger;
 
 import javolution.util.FastList;
 import net.sf.l2j.L2DatabaseFactory;
+import net.sf.l2j.gameserver.InstanceListManager;
 import net.sf.l2j.gameserver.model.L2Clan;
 import net.sf.l2j.gameserver.model.L2Object;
 import net.sf.l2j.gameserver.model.entity.Fort;
 
-public class FortManager
+public class FortManager implements InstanceListManager
 {
 	protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
-	// =========================================================
-	private static FortManager _instance;
 	
 	public static final FortManager getInstance()
-    {
-        if (_instance == null)
-        {
-            _log.info("Initializing FortManager");
-            _instance = new FortManager();
-            _instance.load();
-        }
-        return _instance;
-    }
-    
-    // =========================================================
-    // Data Field
-    private List<Fort> _forts;
-    
-    // =========================================================
-    // Constructor
-    public FortManager()
-    {
-    	
-    }
-
-    public final int findNearestFortIndex(L2Object obj)
-    {
-        int index = getFortIndex(obj);
-        if (index < 0)
-        {
-            double closestDistance = 99999999;
-            double distance;
-            Fort fort;
-            for (int i = 0; i < getForts().size(); i++)
-            {
-                fort = getForts().get(i);
-                if (fort == null) continue;
-                distance = fort.getDistance(obj);
-                if (closestDistance > distance)
-                {
-                    closestDistance = distance;
-                    index = i;
-                }
-            }
-        }
-        return index;
-    }
-    
-    // =========================================================
-    // Method - Private
-    private final void load()
-    {
-        Connection con = null;
-        try
-        {
-            PreparedStatement statement;
-            ResultSet rs;
-
-            con = L2DatabaseFactory.getInstance().getConnection();
-
-            statement = con.prepareStatement("Select id from fort order by id");
-            rs = statement.executeQuery();
-
-            while (rs.next())
-            {
-                getForts().add(new Fort(rs.getInt("id")));
-            }
-
-            rs.close();
-            statement.close();
-
-            _log.info("Loaded: " + getForts().size() + " fortress");
-    		for (Fort fort : getForts())
-    		{
-    			fort.getSiege().getSiegeGuardManager().loadSiegeGuard();
-    		}
-        }
-        catch (Exception e)
-        {
-            _log.warning("Exception: loadFortData(): " + e.getMessage());
-            e.printStackTrace();
-        }
-
-        finally 
-        {
-            try 
-            { 
-                con.close(); 
-            } 
-            catch (Exception e) 
-            {
-            	_log.warning(""+e.getMessage());
-            	e.printStackTrace();
-            }
-        }
-    }
-    
-    // =========================================================
-    // Property - Public
-    public final Fort getFortById(int fortId)
-    {
-        for (Fort f : getForts())
-        {
-            if (f.getFortId() == fortId)
-                return f;
-        }
-        return null;
-    }
-    
-    public final Fort getFortByOwner(L2Clan clan)
-    {
-        for (Fort f : getForts())
-        {
-            if (f.getOwnerClan() == clan)
-                return f;
-        }
-        return null;
-    }
-
-    public final Fort getFort(String name)
-    {
-        for (Fort f : getForts())
-        {
-            if (f.getName().equalsIgnoreCase(name.trim()))
-                return f;
-        }
-        return null;
-    }
-    
-    public final Fort getFort(int x, int y, int z)
-    {
-        for (Fort f : getForts())
-        {
-            if (f.checkIfInZone(x, y, z))
-                return f;
-        }
-        return null;
-    }
-    
-    public final Fort getFort(L2Object activeObject) { return getFort(activeObject.getX(), activeObject.getY(), activeObject.getZ()); }
-    
-    public final int getFortIndex(int fortId)
-    {
-        Fort fort;
-        for (int i = 0; i < getForts().size(); i++)
-        {
-            fort = getForts().get(i);
-            if (fort != null && fort.getFortId() == fortId) return i;
-        }
-        return -1;
-    }
-
-    public final int getFortIndex(L2Object activeObject)
-    {
-        return getFortIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
-    }
-    
-    public final int getFortIndex(int x, int y, int z)
-    {
-        Fort fort;
-        for (int i = 0; i < getForts().size(); i++)
-        {
-            fort = getForts().get(i);
-            if (fort != null && fort.checkIfInZone(x, y, z)) return i;
-        }
-        return -1;
-    }
-    
-    public final List<Fort> getForts()
-    {
-        if (_forts == null) _forts = new FastList<Fort>();
-        return _forts;
-    }
+	{
+		return SingletonHolder._instance;
+	}
+	
+	// =========================================================
+	// Data Field
+	private List<Fort> _forts;
+	
+	// =========================================================
+	// Constructor
+	private FortManager()
+	{
+	}
+	
+	public final int findNearestFortIndex(L2Object obj)
+	{
+		int index = getFortIndex(obj);
+		if (index < 0)
+		{
+			double closestDistance = 99999999;
+			double distance;
+			Fort fort;
+			for (int i = 0; i < getForts().size(); i++)
+			{
+				fort = getForts().get(i);
+				if (fort == null)
+					continue;
+				distance = fort.getDistance(obj);
+				if (closestDistance > distance)
+				{
+					closestDistance = distance;
+					index = i;
+				}
+			}
+		}
+		return index;
+	}
+	
+	// =========================================================
+	// Property - Public
+	public final Fort getFortById(int fortId)
+	{
+		for (Fort f : getForts())
+		{
+			if (f.getFortId() == fortId)
+				return f;
+		}
+		return null;
+	}
+	
+	public final Fort getFortByOwner(L2Clan clan)
+	{
+		for (Fort f : getForts())
+		{
+			if (f.getOwnerClan() == clan)
+				return f;
+		}
+		return null;
+	}
+	
+	public final Fort getFort(String name)
+	{
+		for (Fort f : getForts())
+		{
+			if (f.getName().equalsIgnoreCase(name.trim()))
+				return f;
+		}
+		return null;
+	}
+	
+	public final Fort getFort(int x, int y, int z)
+	{
+		for (Fort f : getForts())
+		{
+			if (f.checkIfInZone(x, y, z))
+				return f;
+		}
+		return null;
+	}
+	
+	public final Fort getFort(L2Object activeObject)
+	{
+		return getFort(activeObject.getX(), activeObject.getY(), activeObject.getZ());
+	}
+	
+	public final int getFortIndex(int fortId)
+	{
+		Fort fort;
+		for (int i = 0; i < getForts().size(); i++)
+		{
+			fort = getForts().get(i);
+			if (fort != null && fort.getFortId() == fortId)
+				return i;
+		}
+		return -1;
+	}
+	
+	public final int getFortIndex(L2Object activeObject)
+	{
+		return getFortIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
+	}
+	
+	public final int getFortIndex(int x, int y, int z)
+	{
+		Fort fort;
+		for (int i = 0; i < getForts().size(); i++)
+		{
+			fort = getForts().get(i);
+			if (fort != null && fort.checkIfInZone(x, y, z))
+				return i;
+		}
+		return -1;
+	}
+	
+	public final List<Fort> getForts()
+	{
+		if (_forts == null)
+			_forts = new FastList<Fort>();
+		return _forts;
+	}
+	
+	public void loadInstances()
+	{
+		_log.info("Initializing FortManager");
+		Connection con = null;
+		try
+		{
+			PreparedStatement statement;
+			ResultSet rs;
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			statement = con.prepareStatement("SELECT id FROM fort ORDER BY id");
+			rs = statement.executeQuery();
+			
+			while (rs.next())
+			{
+				getForts().add(new Fort(rs.getInt("id")));
+			}
+			
+			statement.close();
+			
+			_log.info("Loaded: " + getForts().size() + " fortress");
+			for (Fort fort : getForts())
+			{
+				fort.getSiege().getSiegeGuardManager().loadSiegeGuard();
+			}
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: loadFortData(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	public void updateReferences()
+	{
+	}
+	
+	public void activateInstances()
+	{
+		for (final Fort fort : _forts)
+		{
+			fort.activateInstance();
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final FortManager _instance = new FortManager();
+	}
 }

+ 416 - 388
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FortSiegeManager.java

@@ -44,392 +44,420 @@ import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
 
 public class FortSiegeManager
 {
-    private static final Logger _log = Logger.getLogger(FortSiegeManager.class.getName());
-
-    // =========================================================
-    private static FortSiegeManager _instance;
-    public static final FortSiegeManager getInstance()
-    {
-        if (_instance == null)
-        {
-            _log.info("Initializing FortSiegeManager");
-            _instance = new FortSiegeManager();
-            _instance.load();
-        }
-        return _instance;
-    }
-
-    // =========================================================
-    // Data Field
-    private int _attackerMaxClans                              = 500; // Max number of clans
-
-    // Fort Siege settings
-    private FastMap<Integer,FastList<SiegeSpawn>>  _commanderSpawnList;
-    private FastMap<Integer,FastList<CombatFlag>>  _flagList;
-    private int _flagMaxCount                                   = 1; // Changeable in fortsiege.properties
-    private int _siegeClanMinLevel                              = 4; // Changeable in fortsiege.properties
-    private int _siegeLength                                    = 60; // Time in minute. Changeable in fortsiege.properties
-    private int _countDownLength                                = 10; // Time in minute. Changeable in fortsiege.properties
-	private int _suspiciousMerchantRespawnDelay                 = 180; // Time in minute. Changeable in fortsiege.properties
-    private List<FortSiege> _sieges;
-
-    // =========================================================
-    // Constructor
-    private FortSiegeManager()
-    {
-    }
-
-    // =========================================================
-    // Method - Public
-    public final void addSiegeSkills(L2PcInstance character)
-    {
-        character.addSkill(SkillTable.getInstance().getInfo(246, 1), false);
-        character.addSkill(SkillTable.getInstance().getInfo(247, 1), false);
-    }
-
-    /**
-     * Return true if character summon<BR><BR>
-     * @param activeChar The L2Character of the character can summon
-     */
-    public final boolean checkIfOkToSummon(L2Character activeChar, boolean isCheckOnly)
-    {
-        if (!(activeChar instanceof L2PcInstance)) return false;
-
-        String text = "";
-        L2PcInstance player = (L2PcInstance)activeChar;
-        Fort fort = FortManager.getInstance().getFort(player);
-
-        if (fort == null || fort.getFortId() <= 0)
-            text = "You must be on fort ground to summon this";
-        else if (!fort.getSiege().getIsInProgress())
-            text = "You can only summon this during a siege.";
-        else if (player.getClanId() != 0 && fort.getSiege().getAttackerClan(player.getClanId()) == null)
-            text = "You can only summon this as a registered attacker.";
-        else
-            return true;
-
-        if (!isCheckOnly)
-            player.sendMessage(text);
-        return false;
-    }
-
-    /**
-     * Return true if the clan is registered or owner of a fort<BR><BR>
-     * @param clan The L2Clan of the player
-     */
-    public final boolean checkIsRegistered(L2Clan clan, int fortid)
-    {
-        if (clan == null) return false;
-
-        Connection con = null;
-        boolean register = false;
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-            PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM fortsiege_clans where clan_id=? and fort_id=?");
-            statement.setInt(1, clan.getClanId());
-            statement.setInt(2, fortid);
-            ResultSet rs = statement.executeQuery();
-
-            while (rs.next())
-            {
-                register = true;
-                break;
-            }
-
-            rs.close();
-            statement.close();
-        }
-        catch (Exception e)
-        {
-            _log.warning("Exception: checkIsRegistered(): " + e.getMessage());
-            e.printStackTrace();
-        }
-        finally
-        {
-            try {
-            	con.close(); 
-            }
-            catch (Exception e) 
-            {
-            	_log.warning(""+e.getMessage());
-            	e.printStackTrace();
-            }
-        }
-        return register;
-    }
-
-    public final void removeSiegeSkills(L2PcInstance character)
-    {
-        character.removeSkill(SkillTable.getInstance().getInfo(246, 1));
-        character.removeSkill(SkillTable.getInstance().getInfo(247, 1));
-    }
-
-    // =========================================================
-    // Method - Private
-    private final void load()
-    {
-    	InputStream is = null;
-        try {
-            is = new FileInputStream(new File(Config.FORTSIEGE_CONFIGURATION_FILE));
-            Properties siegeSettings = new Properties();
-            siegeSettings.load(is);
-            
-            // Siege setting
-            _attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
-            _flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
-            _siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "4"));
-            _siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "60"));
-            _countDownLength = Integer.decode(siegeSettings.getProperty("CountDownLength", "10"));
-            _suspiciousMerchantRespawnDelay = Integer.decode(siegeSettings.getProperty("SuspiciousMerchantRespawnDelay", "180"));
-
-            // Siege spawns settings
-            _commanderSpawnList = new FastMap<Integer,FastList<SiegeSpawn>>();
-            _flagList = new FastMap<Integer,FastList<CombatFlag>>();
-
-            for (Fort fort: FortManager.getInstance().getForts())
-            {
-            	FastList<SiegeSpawn> _commanderSpawns = new FastList<SiegeSpawn>();
-                FastList<CombatFlag> _flagSpawns = new FastList<CombatFlag>();
-                for (int i=1; i<5; i++)
-                {
-                    String _spawnParams = siegeSettings.getProperty(fort.getName() + "Commander" + Integer.toString(i), "");
-                    if (_spawnParams.length() == 0) break;
-                    StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
-
-                    try
-                    {
-                        int x = Integer.parseInt(st.nextToken());
-                        int y = Integer.parseInt(st.nextToken());
-                        int z = Integer.parseInt(st.nextToken());
-                        int heading = Integer.parseInt(st.nextToken());
-                        int npc_id = Integer.parseInt(st.nextToken());
-
-                        _commanderSpawns.add(new SiegeSpawn(fort.getFortId(),x,y,z,heading,npc_id,i));
-                    }
-                    catch (Exception e)
-                    {
-                        _log.warning("Error while loading commander(s) for "+fort.getName()+" fort.");
-                    }
-                }
-
-                _commanderSpawnList.put(fort.getFortId(), _commanderSpawns);
-                
-                for (int i=1; i<4; i++)
-                {
-                    String _spawnParams = siegeSettings.getProperty(fort.getName() + "Flag" + Integer.toString(i), "");
-                    if (_spawnParams.length() == 0) break;
-                    StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
-
-                    try
-                    {
-                        int x = Integer.parseInt(st.nextToken());
-                        int y = Integer.parseInt(st.nextToken());
-                        int z = Integer.parseInt(st.nextToken());
-                        int flag_id = Integer.parseInt(st.nextToken());
-
-                        _flagSpawns.add(new CombatFlag(fort.getFortId(),x,y,z,0,flag_id));
-                    }
-                    catch (Exception e)
-                    {
-                        _log.warning("Error while loading flag(s) for "+fort.getName()+" fort.");
-                    }
-                }
-                _flagList.put(fort.getFortId(), _flagSpawns); 
-            }
-
-        }
-        catch (Exception e)
-        {
-            //_initialized = false;
-            _log.warning("Error while loading fortsiege data."+e.getMessage());
-            e.printStackTrace();
-        }
-        finally
-        {
-        	try
-        	{
-        		is.close();
-        	}
-        	catch (Exception e)
-        	{
-        		_log.warning(""+e.getMessage());
-        		e.printStackTrace();
-        	}
-        }
-    }
-
-    // =========================================================
-    // Property - Public
-    public final FastList<SiegeSpawn> getCommanderSpawnList(int _fortId)
-    {
-        if (_commanderSpawnList.containsKey(_fortId))
-        {
-            return _commanderSpawnList.get(_fortId);
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    public final FastList<CombatFlag> getFlagList(int _fortId)
-    {
-        if (_flagList.containsKey(_fortId))
-            return _flagList.get(_fortId);
-        else
-            return null;
-    }
-    
-    public final int getAttackerMaxClans() { return _attackerMaxClans; }
-
-    public final int getFlagMaxCount() { return _flagMaxCount; }
-
-    public final int getSuspiciousMerchantRespawnDelay() { return _suspiciousMerchantRespawnDelay; }
-    
-    public final FortSiege getSiege(L2Object activeObject) { return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ()); }
-
-    public final FortSiege getSiege(int x, int y, int z)
-    {
-        for (Fort fort: FortManager.getInstance().getForts())
-            if (fort.getSiege().checkIfInZone(x, y, z)) return fort.getSiege();
-        return null;
-    }
-
-    public final int getSiegeClanMinLevel() { return _siegeClanMinLevel; }
-
-    public final int getSiegeLength() { return _siegeLength; }
-
-    public final int getCountDownLength() { return _countDownLength; }
-
-    public final List<FortSiege> getSieges()
-    {
-        if (_sieges == null) 
-        	_sieges = new FastList<FortSiege>();
-        return _sieges;
-    }
-
-    public final void addSiege(FortSiege fortSiege)
-    {
-    	if (_sieges == null)
-    		_sieges = new FastList<FortSiege>();
-    	_sieges.add(fortSiege);
-    }
-
-    public boolean isCombat(int itemId)
-    {
-        return ( itemId == 9819);
-    }
-    
-    public boolean activateCombatFlag(L2PcInstance player, L2ItemInstance item)
-    {
-        if (!checkIfCanPickup(player))
-            return false;
-        
-        Fort fort = FortManager.getInstance().getFort(player);
-        
-        FastList<CombatFlag> fcf =  _flagList.get(fort.getFortId());
-        for ( CombatFlag cf : fcf)
-        {
-            if ( cf.itemInstance == item)
-            {
-                cf.activate(player, item);
-            }
-        }
-        return true;
-    }
-    
-    public boolean checkIfCanPickup(L2PcInstance player)
-    {
-    	SystemMessage sm;
-    	sm = new SystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_OF_S1_HAS_FINISHED);
-    	sm.addItemName(9819);
-        // Cannot own 2 combat flag
-        if (player.isCombatFlagEquipped()) 
-        {
-        	player.sendPacket(sm);
-            return false;
-        }
-       
-        // here check if is siege is in progress
-        // here check if is siege is attacker
-        Fort fort = FortManager.getInstance().getFort(player);
-        
-        if (fort == null || fort.getFortId() <= 0)
-        {
-        	player.sendPacket(sm);
-            return false;
-        }
-        else if (!fort.getSiege().getIsInProgress())
-        {
-        	player.sendPacket(sm);
-            return false;
-        }
-        else if (fort.getSiege().getAttackerClan(player.getClan()) == null)
-        {
-        	player.sendPacket(sm);
-            return false;
-        }
-        return true;
-    }
-    
-    public void dropCombatFlag(L2PcInstance player)
-    {
-        Fort fort = FortManager.getInstance().getFort(player);
-
-        FastList<CombatFlag> fcf =  _flagList.get(fort.getFortId());
-
-        for ( CombatFlag cf : fcf)
-        {
-            if ( cf.playerId == player.getObjectId())
-            {
-                cf.dropIt();
-                if (fort.getSiege().getIsInProgress())
-                	cf.spawnMe();
-            }
-        }
-    }
-    
-    public class  SiegeSpawn
-    {
-        Location _location;
-        private int _npcId;
-        private int _heading;
-        private int _fortId;
-        private int _id;
-
-        public SiegeSpawn(int fort_id, int x, int y, int z, int heading, int npc_id, int id)
-        {
-            _fortId = fort_id;
-            _location = new Location(x,y,z,heading);
-            _heading = heading;
-            _npcId = npc_id;
-            _id = id;
-        }
-
-        public int getFortId()
-        {
-            return _fortId;
-        }
-
-        public int getNpcId()
-        {
-            return _npcId;
-        }
-
-        public int getHeading()
-        {
-            return _heading;
-        }
-
-        public int getId()
-        {
-            return _id;
-        }
-
-        public Location getLocation()
-        {
-            return _location;
-        }
-    }
+	private static final Logger _log = Logger.getLogger(FortSiegeManager.class.getName());
+	
+	public static final FortSiegeManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	// =========================================================
+	// Data Field
+	private int _attackerMaxClans = 500; // Max number of clans
+	
+	// Fort Siege settings
+	private FastMap<Integer, FastList<SiegeSpawn>> _commanderSpawnList;
+	private FastMap<Integer, FastList<CombatFlag>> _flagList;
+	private int _flagMaxCount = 1; // Changeable in fortsiege.properties
+	private int _siegeClanMinLevel = 4; // Changeable in fortsiege.properties
+	private int _siegeLength = 60; // Time in minute. Changeable in fortsiege.properties
+	private int _countDownLength = 10; // Time in minute. Changeable in fortsiege.properties
+	private int _suspiciousMerchantRespawnDelay = 180; // Time in minute. Changeable in fortsiege.properties
+	private List<FortSiege> _sieges;
+	
+	// =========================================================
+	// Constructor
+	private FortSiegeManager()
+	{
+		_log.info("Initializing FortSiegeManager");
+		load();
+	}
+	
+	// =========================================================
+	// Method - Public
+	public final void addSiegeSkills(L2PcInstance character)
+	{
+		character.addSkill(SkillTable.getInstance().getInfo(246, 1), false);
+		character.addSkill(SkillTable.getInstance().getInfo(247, 1), false);
+	}
+	
+	/**
+	 * Return true if character summon<BR><BR>
+	 * @param activeChar The L2Character of the character can summon
+	 */
+	public final boolean checkIfOkToSummon(L2Character activeChar, boolean isCheckOnly)
+	{
+		if (!(activeChar instanceof L2PcInstance))
+			return false;
+		
+		String text = "";
+		L2PcInstance player = (L2PcInstance) activeChar;
+		Fort fort = FortManager.getInstance().getFort(player);
+		
+		if (fort == null || fort.getFortId() <= 0)
+			text = "You must be on fort ground to summon this";
+		else if (!fort.getSiege().getIsInProgress())
+			text = "You can only summon this during a siege.";
+		else if (player.getClanId() != 0 && fort.getSiege().getAttackerClan(player.getClanId()) == null)
+			text = "You can only summon this as a registered attacker.";
+		else
+			return true;
+		
+		if (!isCheckOnly)
+			player.sendMessage(text);
+		return false;
+	}
+	
+	/**
+	 * Return true if the clan is registered or owner of a fort<BR><BR>
+	 * @param clan The L2Clan of the player
+	 */
+	public final boolean checkIsRegistered(L2Clan clan, int fortid)
+	{
+		if (clan == null)
+			return false;
+		
+		Connection con = null;
+		boolean register = false;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM fortsiege_clans where clan_id=? and fort_id=?");
+			statement.setInt(1, clan.getClanId());
+			statement.setInt(2, fortid);
+			ResultSet rs = statement.executeQuery();
+			
+			while (rs.next())
+			{
+				register = true;
+				break;
+			}
+			
+			rs.close();
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: checkIsRegistered(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+				_log.warning("" + e.getMessage());
+				e.printStackTrace();
+			}
+		}
+		return register;
+	}
+	
+	public final void removeSiegeSkills(L2PcInstance character)
+	{
+		character.removeSkill(SkillTable.getInstance().getInfo(246, 1));
+		character.removeSkill(SkillTable.getInstance().getInfo(247, 1));
+	}
+	
+	// =========================================================
+	// Method - Private
+	private final void load()
+	{
+		InputStream is = null;
+		try
+		{
+			is = new FileInputStream(new File(Config.FORTSIEGE_CONFIGURATION_FILE));
+			Properties siegeSettings = new Properties();
+			siegeSettings.load(is);
+			
+			// Siege setting
+			_attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
+			_flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
+			_siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "4"));
+			_siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "60"));
+			_countDownLength = Integer.decode(siegeSettings.getProperty("CountDownLength", "10"));
+			_suspiciousMerchantRespawnDelay = Integer.decode(siegeSettings.getProperty("SuspiciousMerchantRespawnDelay", "180"));
+			
+			// Siege spawns settings
+			_commanderSpawnList = new FastMap<Integer, FastList<SiegeSpawn>>();
+			_flagList = new FastMap<Integer, FastList<CombatFlag>>();
+			
+			for (Fort fort : FortManager.getInstance().getForts())
+			{
+				FastList<SiegeSpawn> _commanderSpawns = new FastList<SiegeSpawn>();
+				FastList<CombatFlag> _flagSpawns = new FastList<CombatFlag>();
+				for (int i = 1; i < 5; i++)
+				{
+					String _spawnParams = siegeSettings.getProperty(fort.getName() + "Commander" + Integer.toString(i), "");
+					if (_spawnParams.length() == 0)
+						break;
+					StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
+					
+					try
+					{
+						int x = Integer.parseInt(st.nextToken());
+						int y = Integer.parseInt(st.nextToken());
+						int z = Integer.parseInt(st.nextToken());
+						int heading = Integer.parseInt(st.nextToken());
+						int npc_id = Integer.parseInt(st.nextToken());
+						
+						_commanderSpawns.add(new SiegeSpawn(fort.getFortId(), x, y, z, heading, npc_id, i));
+					}
+					catch (Exception e)
+					{
+						_log.warning("Error while loading commander(s) for " + fort.getName() + " fort.");
+					}
+				}
+				
+				_commanderSpawnList.put(fort.getFortId(), _commanderSpawns);
+				
+				for (int i = 1; i < 4; i++)
+				{
+					String _spawnParams = siegeSettings.getProperty(fort.getName() + "Flag" + Integer.toString(i), "");
+					if (_spawnParams.length() == 0)
+						break;
+					StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
+					
+					try
+					{
+						int x = Integer.parseInt(st.nextToken());
+						int y = Integer.parseInt(st.nextToken());
+						int z = Integer.parseInt(st.nextToken());
+						int flag_id = Integer.parseInt(st.nextToken());
+						
+						_flagSpawns.add(new CombatFlag(fort.getFortId(), x, y, z, 0, flag_id));
+					}
+					catch (Exception e)
+					{
+						_log.warning("Error while loading flag(s) for " + fort.getName() + " fort.");
+					}
+				}
+				_flagList.put(fort.getFortId(), _flagSpawns);
+			}
+			
+		}
+		catch (Exception e)
+		{
+			//_initialized = false;
+			_log.warning("Error while loading fortsiege data." + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				is.close();
+			}
+			catch (Exception e)
+			{
+				_log.warning("" + e.getMessage());
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	// =========================================================
+	// Property - Public
+	public final FastList<SiegeSpawn> getCommanderSpawnList(int _fortId)
+	{
+		if (_commanderSpawnList.containsKey(_fortId))
+		{
+			return _commanderSpawnList.get(_fortId);
+		}
+		else
+		{
+			return null;
+		}
+	}
+	
+	public final FastList<CombatFlag> getFlagList(int _fortId)
+	{
+		if (_flagList.containsKey(_fortId))
+			return _flagList.get(_fortId);
+		else
+			return null;
+	}
+	
+	public final int getAttackerMaxClans()
+	{
+		return _attackerMaxClans;
+	}
+	
+	public final int getFlagMaxCount()
+	{
+		return _flagMaxCount;
+	}
+	
+	public final int getSuspiciousMerchantRespawnDelay()
+	{
+		return _suspiciousMerchantRespawnDelay;
+	}
+	
+	public final FortSiege getSiege(L2Object activeObject)
+	{
+		return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ());
+	}
+	
+	public final FortSiege getSiege(int x, int y, int z)
+	{
+		for (Fort fort : FortManager.getInstance().getForts())
+			if (fort.getSiege().checkIfInZone(x, y, z))
+				return fort.getSiege();
+		return null;
+	}
+	
+	public final int getSiegeClanMinLevel()
+	{
+		return _siegeClanMinLevel;
+	}
+	
+	public final int getSiegeLength()
+	{
+		return _siegeLength;
+	}
+	
+	public final int getCountDownLength()
+	{
+		return _countDownLength;
+	}
+	
+	public final List<FortSiege> getSieges()
+	{
+		if (_sieges == null)
+			_sieges = new FastList<FortSiege>();
+		return _sieges;
+	}
+	
+	public final void addSiege(FortSiege fortSiege)
+	{
+		if (_sieges == null)
+			_sieges = new FastList<FortSiege>();
+		_sieges.add(fortSiege);
+	}
+	
+	public boolean isCombat(int itemId)
+	{
+		return (itemId == 9819);
+	}
+	
+	public boolean activateCombatFlag(L2PcInstance player, L2ItemInstance item)
+	{
+		if (!checkIfCanPickup(player))
+			return false;
+		
+		Fort fort = FortManager.getInstance().getFort(player);
+		
+		FastList<CombatFlag> fcf = _flagList.get(fort.getFortId());
+		for (CombatFlag cf : fcf)
+		{
+			if (cf.itemInstance == item)
+			{
+				cf.activate(player, item);
+			}
+		}
+		return true;
+	}
+	
+	public boolean checkIfCanPickup(L2PcInstance player)
+	{
+		SystemMessage sm;
+		sm = new SystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_OF_S1_HAS_FINISHED);
+		sm.addItemName(9819);
+		// Cannot own 2 combat flag
+		if (player.isCombatFlagEquipped())
+		{
+			player.sendPacket(sm);
+			return false;
+		}
+		
+		// here check if is siege is in progress
+		// here check if is siege is attacker
+		Fort fort = FortManager.getInstance().getFort(player);
+		
+		if (fort == null || fort.getFortId() <= 0)
+		{
+			player.sendPacket(sm);
+			return false;
+		}
+		else if (!fort.getSiege().getIsInProgress())
+		{
+			player.sendPacket(sm);
+			return false;
+		}
+		else if (fort.getSiege().getAttackerClan(player.getClan()) == null)
+		{
+			player.sendPacket(sm);
+			return false;
+		}
+		return true;
+	}
+	
+	public void dropCombatFlag(L2PcInstance player)
+	{
+		Fort fort = FortManager.getInstance().getFort(player);
+		
+		FastList<CombatFlag> fcf = _flagList.get(fort.getFortId());
+		
+		for (CombatFlag cf : fcf)
+		{
+			if (cf.playerId == player.getObjectId())
+			{
+				cf.dropIt();
+				if (fort.getSiege().getIsInProgress())
+					cf.spawnMe();
+			}
+		}
+	}
+	
+	public class SiegeSpawn
+	{
+		Location _location;
+		private int _npcId;
+		private int _heading;
+		private int _fortId;
+		private int _id;
+		
+		public SiegeSpawn(int fort_id, int x, int y, int z, int heading, int npc_id, int id)
+		{
+			_fortId = fort_id;
+			_location = new Location(x, y, z, heading);
+			_heading = heading;
+			_npcId = npc_id;
+			_id = id;
+		}
+		
+		public int getFortId()
+		{
+			return _fortId;
+		}
+		
+		public int getNpcId()
+		{
+			return _npcId;
+		}
+		
+		public int getHeading()
+		{
+			return _heading;
+		}
+		
+		public int getId()
+		{
+			return _id;
+		}
+		
+		public Location getLocation()
+		{
+			return _location;
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final FortSiegeManager _instance = new FortSiegeManager();
+	}
 }

+ 200 - 233
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/FourSepulchersManager.java

@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ScheduledFuture;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javolution.util.FastList;
 import javolution.util.FastMap;
@@ -51,51 +52,63 @@ import net.sf.l2j.util.Rnd;
  * @author sandman
  * 
  */
-public class FourSepulchersManager extends GrandBossManager
+public class FourSepulchersManager
 {
-	private static FourSepulchersManager _instance;
+	protected static final Logger _log = Logger.getLogger(FourSepulchersManager.class.getName());
 	
 	private static final String QUEST_ID = "620_FourGoblets";
-
+	
 	private static final int ENTRANCE_PASS = 7075;
 	private static final int USED_PASS = 7261;
 	private static final int CHAPEL_KEY = 7260;
 	private static final int ANTIQUE_BROOCH = 7262;
-
+	
 	protected boolean _firstTimeRun;
 	protected boolean _inEntryTime = false;
 	protected boolean _inWarmUpTime = false;
 	protected boolean _inAttackTime = false;
 	protected boolean _inCoolDownTime = false;
-
+	
 	protected ScheduledFuture<?> _changeCoolDownTimeTask = null;
 	protected ScheduledFuture<?> _changeEntryTimeTask = null;
 	protected ScheduledFuture<?> _changeWarmUpTimeTask = null;
 	protected ScheduledFuture<?> _changeAttackTimeTask = null;
 	protected ScheduledFuture<?> _onPartyAnnihilatedTask = null;
 	
-	private int[][] _startHallSpawn = { { 181632, -85587, -7218 },
-	        { 179963, -88978, -7218 }, { 173217, -86132, -7218 },
-	        { 175608, -82296, -7218 } };
+	private int[][] _startHallSpawn = {
+			{ 181632, -85587, -7218 },
+			{ 179963, -88978, -7218 },
+			{ 173217, -86132, -7218 },
+			{ 175608, -82296, -7218 }
+	};
 	
 	private int[][][] _shadowSpawnLoc = {
-	        { { 25339, 191231, -85574, -7216, 33380 },
-	                { 25349, 189534, -88969, -7216, 32768 },
-	                { 25346, 173195, -76560, -7215, 49277 },
-	                { 25342, 175591, -72744, -7215, 49317 } },
-	        { { 25342, 191231, -85574, -7216, 33380 },
-	                { 25339, 189534, -88969, -7216, 32768 },
-	                { 25349, 173195, -76560, -7215, 49277 },
-	                { 25346, 175591, -72744, -7215, 49317 } },
-	        { { 25346, 191231, -85574, -7216, 33380 },
-	                { 25342, 189534, -88969, -7216, 32768 },
-	                { 25339, 173195, -76560, -7215, 49277 },
-	                { 25349, 175591, -72744, -7215, 49317 } },
-	        { { 25349, 191231, -85574, -7216, 33380 },
-	                { 25346, 189534, -88969, -7216, 32768 },
-	                { 25342, 173195, -76560, -7215, 49277 },
-	                { 25339, 175591, -72744, -7215, 49317 } }, };
-
+			{
+				{ 25339, 191231, -85574, -7216, 33380 },
+				{ 25349, 189534, -88969, -7216, 32768 },
+				{ 25346, 173195, -76560, -7215, 49277 },
+				{ 25342, 175591, -72744, -7215, 49317 }
+			},
+			{
+				{ 25342, 191231, -85574, -7216, 33380 },
+				{ 25339, 189534, -88969, -7216, 32768 },
+				{ 25349, 173195, -76560, -7215, 49277 },
+				{ 25346, 175591, -72744, -7215, 49317 }
+			},
+			{
+				{ 25346, 191231, -85574, -7216, 33380 },
+				{ 25342, 189534, -88969, -7216, 32768 },
+				{ 25339, 173195, -76560, -7215, 49277 },
+				{ 25349, 175591, -72744, -7215, 49317 }
+			},
+			{
+				{ 25349, 191231, -85574, -7216, 33380 },
+				{ 25346, 189534, -88969, -7216, 32768 },
+				{ 25342, 173195, -76560, -7215, 49277 },
+				{ 25339, 175591, -72744, -7215, 49317 }
+			},
+	};
+	
 	protected FastMap<Integer, Boolean> _archonSpawned = new FastMap<Integer, Boolean>();
 	protected FastMap<Integer, Boolean> _hallInUse = new FastMap<Integer, Boolean>();
 	protected FastMap<Integer, int[]> _startHallSpawns = new FastMap<Integer, int[]>();
@@ -113,28 +126,29 @@ public class FourSepulchersManager extends GrandBossManager
 	protected FastMap<Integer, FastList<L2Spawn>> _magicalMonsters = new FastMap<Integer, FastList<L2Spawn>>();
 	protected FastMap<Integer, FastList<L2Spawn>> _physicalMonsters = new FastMap<Integer, FastList<L2Spawn>>();
 	protected FastMap<Integer, FastList<L2SepulcherMonsterInstance>> _viscountMobs = new FastMap<Integer, FastList<L2SepulcherMonsterInstance>>();
-
+	
 	protected FastList<L2Spawn> _physicalSpawns;
 	protected FastList<L2Spawn> _magicalSpawns;
 	protected FastList<L2Spawn> _managers;
 	protected FastList<L2Spawn> _dukeFinalSpawns;
 	protected FastList<L2Spawn> _emperorsGraveSpawns;
 	protected FastList<L2Npc> _allMobs = new FastList<L2Npc>();
-
+	
 	protected long _attackTimeEnd = 0;
 	protected long _coolDownTimeEnd = 0;
 	protected long _entryTimeEnd = 0;
 	protected long _warmUpTimeEnd = 0;
-
+	
 	protected byte _newCycleMin = 55;
-
-	public static final FourSepulchersManager getInstance()
+	
+	private FourSepulchersManager()
 	{
-		if (_instance == null)
-			_instance = new FourSepulchersManager();
-		return _instance;
 	}
 	
+	public static final FourSepulchersManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
 	
 	public void init()
 	{
@@ -171,8 +185,6 @@ public class FourSepulchersManager extends GrandBossManager
 		timeSelector();
 	}
 	
-	
-	
 	// phase select on server launch
 	protected void timeSelector()
 	{
@@ -181,24 +193,24 @@ public class FourSepulchersManager extends GrandBossManager
 		// if current time >= time of entry beginning and if current time < time
 		// of entry beginning + time of entry end
 		if (currentTime >= _coolDownTimeEnd && currentTime < _entryTimeEnd) // entry
-																			// time
-																			// check
+		// time
+		// check
 		{
 			clean();
 			_changeEntryTimeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeEntryTime(), 0);
 			_log.info("FourSepulchersManager: Beginning in Entry time");
 		}
 		else if (currentTime >= _entryTimeEnd && currentTime < _warmUpTimeEnd) // warmup
-																				// time
-																				// check
+		// time
+		// check
 		{
 			clean();
 			_changeWarmUpTimeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeWarmUpTime(), 0);
 			_log.info("FourSepulchersManager: Beginning in WarmUp time");
 		}
 		else if (currentTime >= _warmUpTimeEnd && currentTime < _attackTimeEnd) // attack
-																				// time
-																				// check
+		// time
+		// check
 		{
 			clean();
 			_changeAttackTimeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeAttackTime(), 0);
@@ -213,8 +225,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
-	
 	// phase end times calculator
 	protected void timeCalculator()
 	{
@@ -228,13 +238,12 @@ public class FourSepulchersManager extends GrandBossManager
 		_attackTimeEnd = _warmUpTimeEnd + Config.FS_TIME_ATTACK * 60000;
 	}
 	
-	
 	public void clean()
 	{
-		for (int i=31921; i < 31925; i++)
+		for (int i = 31921; i < 31925; i++)
 		{
 			int[] Location = _startHallSpawns.get(i);
-			GrandBossManager.getInstance().getZone(Location[0],Location[1],Location[2]).oustAllPlayers();
+			GrandBossManager.getInstance().getZone(Location[0], Location[1], Location[2]).oustAllPlayers();
 		}
 		
 		deleteAllMobs();
@@ -257,7 +266,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	protected void spawnManagers()
 	{
 		_managers = new FastList<L2Spawn>();
@@ -272,61 +280,59 @@ public class FourSepulchersManager extends GrandBossManager
 			if (template1 == null)
 				continue;
 			try
-            {
-	            spawnDat = new L2Spawn(template1);
-
-	            spawnDat.setAmount(1);
-	            spawnDat.setRespawnDelay(60);
-	            switch (i)
-	            {
-	            	case 31921: // conquerors
-	            		spawnDat.setLocx(181061);
-	            		spawnDat.setLocy(-85595);
-	            		spawnDat.setLocz(-7200);
-	            		spawnDat.setHeading(-32584);
-	            		break;
-	            	case 31922: // emperors
-	            		spawnDat.setLocx(179292);
-	            		spawnDat.setLocy(-88981);
-	            		spawnDat.setLocz(-7200);
-	            		spawnDat.setHeading(-33272);
-	            		break;
-	            	case 31923: // sages
-	            		spawnDat.setLocx(173202);
-	            		spawnDat.setLocy(-87004);
-	            		spawnDat.setLocz(-7200);
-	            		spawnDat.setHeading(-16248);
-	            		break;
-	            	case 31924: // judges
-	            		spawnDat.setLocx(175606);
-	            		spawnDat.setLocy(-82853);
-	            		spawnDat.setLocz(-7200);
-	            		spawnDat.setHeading(-16248);
-	            		break;
-	            }
-	            _managers.add(spawnDat);
-	            SpawnTable.getInstance().addNewSpawn(spawnDat, false);
-	            spawnDat.doSpawn();
-	            spawnDat.startRespawn();
-	            _log.info("FourSepulchersManager: spawned "
-	            		+ spawnDat.getTemplate().getName());
-            }
-            catch (SecurityException e)
-            {
-	            e.printStackTrace();
-            }
-            catch (ClassNotFoundException e)
-            {
-	            e.printStackTrace();
-            }
-            catch (NoSuchMethodException e)
-            {
-	            e.printStackTrace();
-            }
+			{
+				spawnDat = new L2Spawn(template1);
+				
+				spawnDat.setAmount(1);
+				spawnDat.setRespawnDelay(60);
+				switch (i)
+				{
+					case 31921: // conquerors
+						spawnDat.setLocx(181061);
+						spawnDat.setLocy(-85595);
+						spawnDat.setLocz(-7200);
+						spawnDat.setHeading(-32584);
+						break;
+					case 31922: // emperors
+						spawnDat.setLocx(179292);
+						spawnDat.setLocy(-88981);
+						spawnDat.setLocz(-7200);
+						spawnDat.setHeading(-33272);
+						break;
+					case 31923: // sages
+						spawnDat.setLocx(173202);
+						spawnDat.setLocy(-87004);
+						spawnDat.setLocz(-7200);
+						spawnDat.setHeading(-16248);
+						break;
+					case 31924: // judges
+						spawnDat.setLocx(175606);
+						spawnDat.setLocy(-82853);
+						spawnDat.setLocz(-7200);
+						spawnDat.setHeading(-16248);
+						break;
+				}
+				_managers.add(spawnDat);
+				SpawnTable.getInstance().addNewSpawn(spawnDat, false);
+				spawnDat.doSpawn();
+				spawnDat.startRespawn();
+				_log.info("FourSepulchersManager: spawned " + spawnDat.getTemplate().getName());
+			}
+			catch (SecurityException e)
+			{
+				e.printStackTrace();
+			}
+			catch (ClassNotFoundException e)
+			{
+				e.printStackTrace();
+			}
+			catch (NoSuchMethodException e)
+			{
+				e.printStackTrace();
+			}
 		}
 	}
 	
-	
 	protected void initFixedInfo()
 	{
 		_startHallSpawns.put(31921, _startHallSpawn[0]);
@@ -410,7 +416,6 @@ public class FourSepulchersManager extends GrandBossManager
 		_victim.put(18157, 18165);
 	}
 	
-	
 	private void loadMysteriousBox()
 	{
 		Connection con = null;
@@ -446,20 +451,18 @@ public class FourSepulchersManager extends GrandBossManager
 				else
 				{
 					_log.warning("FourSepulchersManager.LoadMysteriousBox: Data missing in NPC table for ID: "
-					        + rset.getInt("npc_templateid") + ".");
+							+ rset.getInt("npc_templateid") + ".");
 				}
 			}
 			
 			rset.close();
 			statement.close();
-			_log.info("FourSepulchersManager: loaded "
-			        + _mysteriousBoxSpawns.size() + " Mysterious-Box spawns.");
+			_log.info("FourSepulchersManager: loaded " + _mysteriousBoxSpawns.size() + " Mysterious-Box spawns.");
 		}
 		catch (Exception e)
 		{
 			// problem with initializing spawn, go to next one
-			_log.warning("FourSepulchersManager.LoadMysteriousBox: Spawn could not be initialized: "
-			        + e);
+			_log.warning("FourSepulchersManager.LoadMysteriousBox: Spawn could not be initialized: " + e);
 		}
 		finally
 		{
@@ -473,7 +476,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	private void initKeyBoxSpawns()
 	{
 		L2Spawn spawnDat;
@@ -498,19 +500,17 @@ public class FourSepulchersManager extends GrandBossManager
 				}
 				else
 				{
-					_log.warning("FourSepulchersManager.InitKeyBoxSpawns: Data missing in NPC table for ID: "
-					        + _keyBoxNpc.get(keyNpcId) + ".");
+					_log.warning("FourSepulchersManager.InitKeyBoxSpawns: Data missing in NPC table for ID: " + _keyBoxNpc.get(keyNpcId)
+							+ ".");
 				}
 			}
 			catch (Exception e)
 			{
-				_log.warning("FourSepulchersManager.InitKeyBoxSpawns: Spawn could not be initialized: "
-				        + e);
+				_log.warning("FourSepulchersManager.InitKeyBoxSpawns: Spawn could not be initialized: " + e);
 			}
 		}
 	}
 	
-	
 	private void loadPhysicalMonsters()
 	{
 		_physicalMonsters.clear();
@@ -558,7 +558,7 @@ public class FourSepulchersManager extends GrandBossManager
 					else
 					{
 						_log.warning("FourSepulchersManager.LoadPhysicalMonsters: Data missing in NPC table for ID: "
-						        + rset2.getInt("npc_templateid") + ".");
+								+ rset2.getInt("npc_templateid") + ".");
 					}
 				}
 				
@@ -569,14 +569,12 @@ public class FourSepulchersManager extends GrandBossManager
 			
 			rset1.close();
 			statement1.close();
-			_log.info("FourSepulchersManager: loaded " + loaded
-			        + " Physical type monsters spawns.");
+			_log.info("FourSepulchersManager: loaded " + loaded + " Physical type monsters spawns.");
 		}
 		catch (Exception e)
 		{
 			// problem with initializing spawn, go to next one
-			_log.warning("FourSepulchersManager.LoadPhysicalMonsters: Spawn could not be initialized: "
-			        + e);
+			_log.warning("FourSepulchersManager.LoadPhysicalMonsters: Spawn could not be initialized: " + e);
 		}
 		finally
 		{
@@ -590,7 +588,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	private void loadMagicalMonsters()
 	{
 		
@@ -639,7 +636,7 @@ public class FourSepulchersManager extends GrandBossManager
 					else
 					{
 						_log.warning("FourSepulchersManager.LoadMagicalMonsters: Data missing in NPC table for ID: "
-						        + rset2.getInt("npc_templateid") + ".");
+								+ rset2.getInt("npc_templateid") + ".");
 					}
 				}
 				
@@ -650,14 +647,12 @@ public class FourSepulchersManager extends GrandBossManager
 			
 			rset1.close();
 			statement1.close();
-			_log.info("FourSepulchersManager: loaded " + loaded
-			        + " Magical type monsters spawns.");
+			_log.info("FourSepulchersManager: loaded " + loaded + " Magical type monsters spawns.");
 		}
 		catch (Exception e)
 		{
 			// problem with initializing spawn, go to next one
-			_log.warning("FourSepulchersManager.LoadMagicalMonsters: Spawn could not be initialized: "
-			        + e);
+			_log.warning("FourSepulchersManager.LoadMagicalMonsters: Spawn could not be initialized: " + e);
 		}
 		finally
 		{
@@ -671,7 +666,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	private void loadDukeMonsters()
 	{
 		_dukeFinalMobs.clear();
@@ -720,7 +714,7 @@ public class FourSepulchersManager extends GrandBossManager
 					else
 					{
 						_log.warning("FourSepulchersManager.LoadDukeMonsters: Data missing in NPC table for ID: "
-						        + rset2.getInt("npc_templateid") + ".");
+								+ rset2.getInt("npc_templateid") + ".");
 					}
 				}
 				
@@ -732,14 +726,12 @@ public class FourSepulchersManager extends GrandBossManager
 			
 			rset1.close();
 			statement1.close();
-			_log.info("FourSepulchersManager: loaded " + loaded
-			        + " Church of duke monsters spawns.");
+			_log.info("FourSepulchersManager: loaded " + loaded + " Church of duke monsters spawns.");
 		}
 		catch (Exception e)
 		{
 			// problem with initializing spawn, go to next one
-			_log.warning("FourSepulchersManager.LoadDukeMonsters: Spawn could not be initialized: "
-			        + e);
+			_log.warning("FourSepulchersManager.LoadDukeMonsters: Spawn could not be initialized: " + e);
 		}
 		finally
 		{
@@ -753,7 +745,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	private void loadEmperorsGraveMonsters()
 	{
 		
@@ -802,7 +793,7 @@ public class FourSepulchersManager extends GrandBossManager
 					else
 					{
 						_log.warning("FourSepulchersManager.LoadEmperorsGraveMonsters: Data missing in NPC table for ID: "
-						        + rset2.getInt("npc_templateid") + ".");
+								+ rset2.getInt("npc_templateid") + ".");
 					}
 				}
 				
@@ -813,14 +804,12 @@ public class FourSepulchersManager extends GrandBossManager
 			
 			rset1.close();
 			statement1.close();
-			_log.info("FourSepulchersManager: loaded " + loaded
-			        + " Emperor's grave NPC spawns.");
+			_log.info("FourSepulchersManager: loaded " + loaded + " Emperor's grave NPC spawns.");
 		}
 		catch (Exception e)
 		{
 			// problem with initializing spawn, go to next one
-			_log.warning("FourSepulchersManager.LoadEmperorsGraveMonsters: Spawn could not be initialized: "
-			        + e);
+			_log.warning("FourSepulchersManager.LoadEmperorsGraveMonsters: Spawn could not be initialized: " + e);
 		}
 		finally
 		{
@@ -834,7 +823,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	protected void initLocationShadowSpawns()
 	{
 		int locNo = Rnd.get(4);
@@ -864,18 +852,17 @@ public class FourSepulchersManager extends GrandBossManager
 				}
 				catch (Exception e)
 				{
-				    _log.log(Level.SEVERE, "Error on InitLocationShadowSpawns", e);
+					_log.log(Level.SEVERE, "Error on InitLocationShadowSpawns", e);
 				}
 			}
 			else
 			{
 				_log.warning("FourSepulchersManager.InitLocationShadowSpawns: Data missing in NPC table for ID: "
-				        + _shadowSpawnLoc[locNo][i][0] + ".");
+						+ _shadowSpawnLoc[locNo][i][0] + ".");
 			}
 		}
 	}
 	
-	
 	protected void initExecutionerSpawns()
 	{
 		L2Spawn spawnDat;
@@ -900,31 +887,27 @@ public class FourSepulchersManager extends GrandBossManager
 				}
 				else
 				{
-					_log.warning("FourSepulchersManager.InitExecutionerSpawns: Data missing in NPC table for ID: "
-					        + _victim.get(keyNpcId) + ".");
+					_log.warning("FourSepulchersManager.InitExecutionerSpawns: Data missing in NPC table for ID: " + _victim.get(keyNpcId)
+							+ ".");
 				}
 			}
 			catch (Exception e)
 			{
-				_log.warning("FourSepulchersManager.InitExecutionerSpawns: Spawn could not be initialized: "
-				        + e);
+				_log.warning("FourSepulchersManager.InitExecutionerSpawns: Spawn could not be initialized: " + e);
 			}
 		}
 	}
 	
-	
 	public boolean isEntryTime()
 	{
 		return _inEntryTime;
 	}
 	
-	
 	public boolean isAttackTime()
 	{
 		return _inAttackTime;
 	}
 	
-	
 	public synchronized void tryEntry(L2Npc npc, L2PcInstance player)
 	{
 		int npcId = npc.getNpcId();
@@ -940,12 +923,9 @@ public class FourSepulchersManager extends GrandBossManager
 			default:
 				if (!player.isGM())
 				{
-					_log.warning("Player " + player.getName() + "("
-					        + player.getObjectId()
-					        + ") tried to cheat in four sepulchers.");
-					Util.handleIllegalPlayerAction(player, "Warning!! Character "
-					        + player.getName()
-					        + " tried to enter four sepulchers with invalid npc id.", Config.DEFAULT_PUNISH);
+					_log.warning("Player " + player.getName() + "(" + player.getObjectId() + ") tried to cheat in four sepulchers.");
+					Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName()
+							+ " tried to enter four sepulchers with invalid npc id.", Config.DEFAULT_PUNISH);
 				}
 				return;
 		}
@@ -958,8 +938,7 @@ public class FourSepulchersManager extends GrandBossManager
 		
 		if (Config.FS_PARTY_MEMBER_COUNT > 1)
 		{
-			if (!player.isInParty()
-			        || player.getParty().getMemberCount() < Config.FS_PARTY_MEMBER_COUNT)
+			if (!player.isInParty() || player.getParty().getMemberCount() < Config.FS_PARTY_MEMBER_COUNT)
 			{
 				showHtmlFile(player, npcId + "-SP.htm", npc, null);
 				return;
@@ -994,31 +973,31 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 		else if (Config.FS_PARTY_MEMBER_COUNT <= 1 && player.isInParty())
 		{
-				if (!player.getParty().isLeader(player))
+			if (!player.getParty().isLeader(player))
+			{
+				showHtmlFile(player, npcId + "-NL.htm", npc, null);
+				return;
+			}
+			for (L2PcInstance mem : player.getParty().getPartyMembers())
+			{
+				QuestState qs = mem.getQuestState(QUEST_ID);
+				if (qs == null || (!qs.isStarted() && !qs.isCompleted()))
 				{
-					showHtmlFile(player, npcId + "-NL.htm", npc, null);
+					showHtmlFile(player, npcId + "-NS.htm", npc, mem);
 					return;
 				}
-				for (L2PcInstance mem : player.getParty().getPartyMembers())
+				if (mem.getInventory().getItemByItemId(ENTRANCE_PASS) == null)
 				{
-					QuestState qs = mem.getQuestState(QUEST_ID);
-					if (qs == null || (!qs.isStarted() && !qs.isCompleted()))
-					{
-						showHtmlFile(player, npcId + "-NS.htm", npc, mem);
-						return;
-					}
-					if (mem.getInventory().getItemByItemId(ENTRANCE_PASS) == null)
-					{
-						showHtmlFile(player, npcId + "-SE.htm", npc, mem);
-						return;
-					}
-					
-					if (player.getWeightPenalty() >= 3)
-					{
-						mem.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_LESS_THAN_80_PERCENT));
-						return;
-					}
+					showHtmlFile(player, npcId + "-SE.htm", npc, mem);
+					return;
+				}
+				
+				if (player.getWeightPenalty() >= 3)
+				{
+					mem.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_LESS_THAN_80_PERCENT));
+					return;
 				}
+			}
 		}
 		else
 		{
@@ -1052,7 +1031,6 @@ public class FourSepulchersManager extends GrandBossManager
 		entry(npcId, player);
 	}
 	
-	
 	private void entry(int npcId, L2PcInstance player)
 	{
 		int[] Location = _startHallSpawns.get(npcId);
@@ -1064,8 +1042,7 @@ public class FourSepulchersManager extends GrandBossManager
 			List<L2PcInstance> members = new FastList<L2PcInstance>();
 			for (L2PcInstance mem : player.getParty().getPartyMembers())
 			{
-				if (!mem.isDead()
-				        && Util.checkIfInRange(700, player, mem, true))
+				if (!mem.isDead() && Util.checkIfInRange(700, player, mem, true))
 				{
 					members.add(mem);
 				}
@@ -1073,7 +1050,7 @@ public class FourSepulchersManager extends GrandBossManager
 			
 			for (L2PcInstance mem : members)
 			{
-				GrandBossManager.getInstance().getZone(Location[0],Location[1],Location[2]).allowPlayerEntry(mem, 30);
+				GrandBossManager.getInstance().getZone(Location[0], Location[1], Location[2]).allowPlayerEntry(mem, 30);
 				driftx = Rnd.get(-80, 80);
 				drifty = Rnd.get(-80, 80);
 				mem.teleToLocation(Location[0] + driftx, Location[1] + drifty, Location[2]);
@@ -1101,8 +1078,7 @@ public class FourSepulchersManager extends GrandBossManager
 			List<L2PcInstance> members = new FastList<L2PcInstance>();
 			for (L2PcInstance mem : player.getParty().getPartyMembers())
 			{
-				if (!mem.isDead()
-				        && Util.checkIfInRange(700, player, mem, true))
+				if (!mem.isDead() && Util.checkIfInRange(700, player, mem, true))
 				{
 					members.add(mem);
 				}
@@ -1110,7 +1086,7 @@ public class FourSepulchersManager extends GrandBossManager
 			
 			for (L2PcInstance mem : members)
 			{
-				GrandBossManager.getInstance().getZone(Location[0],Location[1],Location[2]).allowPlayerEntry(mem, 30);
+				GrandBossManager.getInstance().getZone(Location[0], Location[1], Location[2]).allowPlayerEntry(mem, 30);
 				driftx = Rnd.get(-80, 80);
 				drifty = Rnd.get(-80, 80);
 				mem.teleToLocation(Location[0] + driftx, Location[1] + drifty, Location[2]);
@@ -1135,7 +1111,7 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 		else
 		{
-			GrandBossManager.getInstance().getZone(Location[0],Location[1],Location[2]).allowPlayerEntry(player, 30);
+			GrandBossManager.getInstance().getZone(Location[0], Location[1], Location[2]).allowPlayerEntry(player, 30);
 			driftx = Rnd.get(-80, 80);
 			drifty = Rnd.get(-80, 80);
 			player.teleToLocation(Location[0] + driftx, Location[1] + drifty, Location[2]);
@@ -1159,7 +1135,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	public void spawnMysteriousBox(int npcId)
 	{
 		if (!isAttackTime())
@@ -1172,7 +1147,7 @@ public class FourSepulchersManager extends GrandBossManager
 			spawnDat.stopRespawn();
 		}
 	}
-
+	
 	public void spawnMonster(int npcId)
 	{
 		if (!isAttackTime())
@@ -1249,8 +1224,7 @@ public class FourSepulchersManager extends GrandBossManager
 					}
 					catch (Exception e)
 					{
-						_log.warning("FourSepulchersManager.SpawnMonster: Spawn could not be initialized: "
-						        + e);
+						_log.warning("FourSepulchersManager.SpawnMonster: Spawn could not be initialized: " + e);
 					}
 					
 					spawnedKeyBoxMob = true;
@@ -1330,7 +1304,7 @@ public class FourSepulchersManager extends GrandBossManager
 		
 		return true;
 	}
-
+	
 	public void spawnKeyBox(L2Npc activeChar)
 	{
 		if (!isAttackTime())
@@ -1351,7 +1325,7 @@ public class FourSepulchersManager extends GrandBossManager
 			
 		}
 	}
-
+	
 	public void spawnExecutionerOfHalisha(L2Npc activeChar)
 	{
 		if (!isAttackTime())
@@ -1371,7 +1345,7 @@ public class FourSepulchersManager extends GrandBossManager
 			spawnDat.stopRespawn();
 		}
 	}
-
+	
 	public void spawnArchonOfHalisha(int npcId)
 	{
 		if (!isAttackTime())
@@ -1398,7 +1372,7 @@ public class FourSepulchersManager extends GrandBossManager
 			_archonSpawned.put(npcId, true);
 		}
 	}
-
+	
 	public void spawnEmperorsGraveNpc(int npcId)
 	{
 		if (!isAttackTime())
@@ -1416,7 +1390,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	protected void locationShadowSpawns()
 	{
 		int locNo = Rnd.get(4);
@@ -1438,7 +1411,6 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 	}
 	
-	
 	public void spawnShadow(int npcId)
 	{
 		if (!isAttackTime())
@@ -1457,7 +1429,7 @@ public class FourSepulchersManager extends GrandBossManager
 			}
 		}
 	}
-
+	
 	public void deleteAllMobs()
 	{
 		// _log.info("FourSepulchersManager.DeleteAllMobs: Try to delete " +
@@ -1472,7 +1444,7 @@ public class FourSepulchersManager extends GrandBossManager
 			}
 			catch (Exception e)
 			{
-			    _log.log(Level.SEVERE, "FourSepulchersManager: Failed deleting mob.", e);
+				_log.log(Level.SEVERE, "FourSepulchersManager: Failed deleting mob.", e);
 			}
 		}
 		_allMobs.clear();
@@ -1480,7 +1452,6 @@ public class FourSepulchersManager extends GrandBossManager
 		// " monsters.");
 	}
 	
-	
 	protected void closeAllDoors()
 	{
 		for (int doorId : _hallGateKeepers.values())
@@ -1490,16 +1461,16 @@ public class FourSepulchersManager extends GrandBossManager
 				L2DoorInstance door = DoorTable.getInstance().getDoor(doorId);
 				if (door != null)
 				{
-				    door.closeMe();
+					door.closeMe();
 				}
 				else
 				{
-				    _log.warning("FourSepulchersManager: Attempted to close undefined door. doorId: "+doorId);
+					_log.warning("FourSepulchersManager: Attempted to close undefined door. doorId: " + doorId);
 				}
 			}
 			catch (Exception e)
 			{
-			    _log.log(Level.SEVERE, "FourSepulchersManager: Failed closing door", e);
+				_log.log(Level.SEVERE, "FourSepulchersManager: Failed closing door", e);
 			}
 		}
 	}
@@ -1580,7 +1551,7 @@ public class FourSepulchersManager extends GrandBossManager
 		}
 		return min;
 	}
-
+	
 	public void managerSay(byte min)
 	{
 		// for attack phase, sending message every 5 minutes
@@ -1592,12 +1563,12 @@ public class FourSepulchersManager extends GrandBossManager
 			min = minuteSelect(min);
 			
 			String msg = min + " minute(s) have passed."; // now this is a
-															// proper message^^
+			// proper message^^
 			
 			if (min == 90)
 				msg = "Game over. The teleport will appear momentarily";
 			
-			for (L2Spawn temp: _managers)
+			for (L2Spawn temp : _managers)
 			{
 				if (temp == null)
 				{
@@ -1622,9 +1593,8 @@ public class FourSepulchersManager extends GrandBossManager
 		else if (_inEntryTime)
 		{
 			String msg1 = "You may now enter the Sepulcher";
-			String msg2 = "If you place your hand on the stone statue in front of each sepulcher,"
-			        + " you will be able to enter";
-			for (L2Spawn temp: _managers)
+			String msg2 = "If you place your hand on the stone statue in front of each sepulcher," + " you will be able to enter";
+			for (L2Spawn temp : _managers)
 			{
 				if (temp == null)
 				{
@@ -1641,7 +1611,7 @@ public class FourSepulchersManager extends GrandBossManager
 			}
 		}
 	}
-
+	
 	protected class ManagerSay implements Runnable
 	{
 		public void run()
@@ -1649,16 +1619,15 @@ public class FourSepulchersManager extends GrandBossManager
 			if (_inAttackTime)
 			{
 				Calendar tmp = Calendar.getInstance();
-				tmp.setTimeInMillis(Calendar.getInstance().getTimeInMillis()
-				        - _warmUpTimeEnd);
+				tmp.setTimeInMillis(Calendar.getInstance().getTimeInMillis() - _warmUpTimeEnd);
 				if (tmp.get(Calendar.MINUTE) + 5 < Config.FS_TIME_ATTACK)
 				{
 					managerSay((byte) tmp.get(Calendar.MINUTE)); // byte
-																	// because
-																	// minute
-																	// cannot be
-																	// more than
-																	// 59
+					// because
+					// minute
+					// cannot be
+					// more than
+					// 59
 					ThreadPoolManager.getInstance().scheduleGeneral(new ManagerSay(), 5 * 60000);
 				}
 				// attack time ending chat
@@ -1689,15 +1658,14 @@ public class FourSepulchersManager extends GrandBossManager
 			// time
 			// and then launching change time task
 			if (_firstTimeRun)
-				interval = _entryTimeEnd
-				        - Calendar.getInstance().getTimeInMillis();
+				interval = _entryTimeEnd - Calendar.getInstance().getTimeInMillis();
 			else
 				interval = Config.FS_TIME_ENTRY * 60000; // else use stupid
-															// method
-				
+			// method
+			
 			// launching saying process...
 			ThreadPoolManager.getInstance().scheduleGeneral(new ManagerSay(), 0);
-			_changeWarmUpTimeTask = ThreadPoolManager.getInstance().scheduleEffect(new ChangeWarmUpTime(),interval);
+			_changeWarmUpTimeTask = ThreadPoolManager.getInstance().scheduleEffect(new ChangeWarmUpTime(), interval);
 			if (_changeEntryTimeTask != null)
 			{
 				_changeEntryTimeTask.cancel(true);
@@ -1723,8 +1691,7 @@ public class FourSepulchersManager extends GrandBossManager
 			// current time
 			// and then launching change time task
 			if (_firstTimeRun)
-				interval = _warmUpTimeEnd
-				        - Calendar.getInstance().getTimeInMillis();
+				interval = _warmUpTimeEnd - Calendar.getInstance().getTimeInMillis();
 			else
 				interval = Config.FS_TIME_WARMUP * 60000;
 			_changeAttackTimeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeAttackTime(), interval);
@@ -1768,13 +1735,11 @@ public class FourSepulchersManager extends GrandBossManager
 					// looking for next shout time....
 					if (min % 5 == 0)// check if min can be divided by 5
 					{
-						_log.info(Calendar.getInstance().getTime()
-						        + " Atk announce scheduled to " + min
-						        + " minute of this hour.");
+						_log.info(Calendar.getInstance().getTime() + " Atk announce scheduled to " + min + " minute of this hour.");
 						Calendar inter = Calendar.getInstance();
 						inter.set(Calendar.MINUTE, (int) min);
 						ThreadPoolManager.getInstance().scheduleGeneral(new ManagerSay(), inter.getTimeInMillis()
-						        - Calendar.getInstance().getTimeInMillis());
+								- Calendar.getInstance().getTimeInMillis());
 						break;
 					}
 				}
@@ -1786,8 +1751,7 @@ public class FourSepulchersManager extends GrandBossManager
 			// current time
 			// and then launching change time task
 			if (_firstTimeRun)
-				interval = _attackTimeEnd
-				        - Calendar.getInstance().getTimeInMillis();
+				interval = _attackTimeEnd - Calendar.getInstance().getTimeInMillis();
 			else
 				interval = Config.FS_TIME_ATTACK * 60000;
 			_changeCoolDownTimeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeCoolDownTime(), interval);
@@ -1815,17 +1779,15 @@ public class FourSepulchersManager extends GrandBossManager
 			Calendar time = Calendar.getInstance();
 			// one hour = 55th min to 55 min of next hour, so we check for this,
 			// also check for first launch
-			if (Calendar.getInstance().get(Calendar.MINUTE) > _newCycleMin
-			        && !_firstTimeRun)
+			if (Calendar.getInstance().get(Calendar.MINUTE) > _newCycleMin && !_firstTimeRun)
 				time.set(Calendar.HOUR, Calendar.getInstance().get(Calendar.HOUR) + 1);
 			time.set(Calendar.MINUTE, _newCycleMin);
 			_log.info("FourSepulchersManager: Entry time: " + time.getTime());
 			if (_firstTimeRun)
 				_firstTimeRun = false; // cooldown phase ends event hour, so it
-										// will be not first run
-				
-			long interval = time.getTimeInMillis()
-			        - Calendar.getInstance().getTimeInMillis();
+			// will be not first run
+			
+			long interval = time.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
 			_changeEntryTimeTask = ThreadPoolManager.getInstance().scheduleGeneral(new ChangeEntryTime(), interval);
 			
 			if (_changeCoolDownTimeTask != null)
@@ -1840,9 +1802,8 @@ public class FourSepulchersManager extends GrandBossManager
 	{
 		return _hallGateKeepers;
 	}
-
-	public void showHtmlFile(L2PcInstance player, String file,
-	        L2Npc npc, L2PcInstance member)
+	
+	public void showHtmlFile(L2PcInstance player, String file, L2Npc npc, L2PcInstance member)
 	{
 		NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
 		html.setFile("data/html/SepulcherNpc/" + file);
@@ -1850,4 +1811,10 @@ public class FourSepulchersManager extends GrandBossManager
 			html.replace("%member%", member.getName());
 		player.sendPacket(html);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final FourSepulchersManager _instance = new FourSepulchersManager();
+	}
 }

+ 60 - 58
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/GrandBossManager.java

@@ -66,50 +66,44 @@ public class GrandBossManager
 	 * DELETE FROM grandboss_list
 	 */
 	private static final String DELETE_GRAND_BOSS_LIST = "DELETE FROM grandboss_list";
-
+	
 	/**
 	 * INSERT INTO grandboss_list (player_id,zone) VALUES (?,?)
 	 */
 	private static final String INSERT_GRAND_BOSS_LIST = "INSERT INTO grandboss_list (player_id,zone) VALUES (?,?)";
-
+	
 	/**
 	 * UPDATE grandboss_data set loc_x = ?, loc_y = ?, loc_z = ?, heading = ?, respawn_time = ?, currentHP = ?, currentMP = ?, status = ? where boss_id = ?
 	 */
 	private static final String UPDATE_GRAND_BOSS_DATA = "UPDATE grandboss_data set loc_x = ?, loc_y = ?, loc_z = ?, heading = ?, respawn_time = ?, currentHP = ?, currentMP = ?, status = ? where boss_id = ?";
-
+	
 	private static final String UPDATE_GRAND_BOSS_DATA2 = "UPDATE grandboss_data set status = ? where boss_id = ?";
 	
 	protected static Logger _log = Logger.getLogger(GrandBossManager.class.getName());
-
-	private static GrandBossManager _instance;
-
+	
 	protected static Map<Integer, L2GrandBossInstance> _bosses;
-
+	
 	protected static Map<Integer, StatsSet> _storedInfo;
-
+	
 	private Map<Integer, Integer> _bossStatus;
-
+	
 	private L2FastList<L2BossZone> _zones;
-
+	
 	public static GrandBossManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_log.info("Initializing GrandBossManager");
-			_instance = new GrandBossManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
-	public GrandBossManager()
+	
+	private GrandBossManager()
 	{
+		_log.info("Initializing GrandBossManager");
 		init();
 	}
-
+	
 	private void init()
 	{
 		_zones = new L2FastList<L2BossZone>();
-
+		
 		_bosses = new FastMap<Integer, L2GrandBossInstance>();
 		_storedInfo = new FastMap<Integer, StatsSet>();
 		_bossStatus = new FastMap<Integer, Integer>();
@@ -117,10 +111,10 @@ public class GrandBossManager
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-
+			
 			PreparedStatement statement = con.prepareStatement("SELECT * from grandboss_data ORDER BY boss_id");
 			ResultSet rset = statement.executeQuery();
-
+			
 			while (rset.next())
 			{
 				//Read all info from DB, and store it for AI to read and decide what to do
@@ -139,13 +133,13 @@ public class GrandBossManager
 				int true_MP = (int) MP;
 				info.set("currentMP", true_MP);
 				_bossStatus.put(bossId, rset.getInt("status"));
-
+				
 				_storedInfo.put(bossId, info);
 				info = null;
 			}
-
+			
 			_log.info("GrandBossManager: Loaded " + _storedInfo.size() + " Instances");
-
+			
 			rset.close();
 			statement.close();
 		}
@@ -169,7 +163,7 @@ public class GrandBossManager
 			}
 		}
 	}
-
+	
 	/*
 	 * Zone Functions
 	 */
@@ -177,39 +171,39 @@ public class GrandBossManager
 	public void initZones()
 	{
 		Connection con = null;
-
+		
 		FastMap<Integer, L2FastList<Integer>> zones = new FastMap<Integer, L2FastList<Integer>>();
-
+		
 		if (_zones == null)
 		{
 			_log.warning("GrandBossManager: Could not read Grand Boss zone data");
 			return;
 		}
-
+		
 		for (L2BossZone zone : _zones)
 		{
 			if (zone == null)
 				continue;
 			zones.put(zone.getId(), new L2FastList<Integer>());
 		}
-
+		
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-
+			
 			PreparedStatement statement = con.prepareStatement("SELECT * from grandboss_list ORDER BY player_id");
 			ResultSet rset = statement.executeQuery();
-
+			
 			while (rset.next())
 			{
 				int id = rset.getInt("player_id");
 				int zone_id = rset.getInt("zone");
 				zones.get(zone_id).add(id);
 			}
-
+			
 			rset.close();
 			statement.close();
-
+			
 			_log.info("GrandBossManager: Initialized " + _zones.size() + " Grand Boss Zones");
 		}
 		catch (SQLException e)
@@ -231,17 +225,17 @@ public class GrandBossManager
 			{
 			}
 		}
-
+		
 		for (L2BossZone zone : _zones)
 		{
 			if (zone == null)
 				continue;
 			zone.setAllowedPlayers(zones.get(zone.getId()));
 		}
-
+		
 		zones.clear();
 	}
-
+	
 	public void addZone(L2BossZone zone)
 	{
 		if (_zones != null)
@@ -249,7 +243,7 @@ public class GrandBossManager
 			_zones.add(zone);
 		}
 	}
-
+	
 	public final L2BossZone getZone(L2Character character)
 	{
 		if (_zones != null)
@@ -262,7 +256,7 @@ public class GrandBossManager
 		}
 		return null;
 	}
-
+	
 	public final L2BossZone getZone(int x, int y, int z)
 	{
 		if (_zones != null)
@@ -275,7 +269,7 @@ public class GrandBossManager
 		}
 		return null;
 	}
-
+	
 	public boolean checkIfInZone(String zoneType, L2Object obj)
 	{
 		L2BossZone temp = getZone(obj.getX(), obj.getY(), obj.getZ());
@@ -284,16 +278,18 @@ public class GrandBossManager
 		
 		return temp.getZoneName().equalsIgnoreCase(zoneType);
 	}
-
+	
 	public boolean checkIfInZone(L2PcInstance player)
 	{
-		if (player == null) return false;
+		if (player == null)
+			return false;
 		L2BossZone temp = getZone(player.getX(), player.getY(), player.getZ());
 		if (temp == null)
 			return false;
-
+		
 		return true;
 	}
+	
 	/*
 	 * The rest
 	 */
@@ -302,13 +298,13 @@ public class GrandBossManager
 	{
 		return _bossStatus.get(bossId);
 	}
-
+	
 	public void setBossStatus(int bossId, int status)
 	{
 		_bossStatus.remove(bossId);
 		_bossStatus.put(bossId, status);
 	}
-
+	
 	/*
 	 * Adds a L2GrandBossInstance to the list of bosses.
 	 */
@@ -322,17 +318,17 @@ public class GrandBossManager
 			_bosses.put(boss.getNpcId(), boss);
 		}
 	}
-
+	
 	public L2GrandBossInstance getBoss(int bossId)
 	{
 		return _bosses.get(bossId);
 	}
-
+	
 	public StatsSet getStatsSet(int bossId)
 	{
 		return _storedInfo.get(bossId);
 	}
-
+	
 	public void setStatsSet(int bossId, StatsSet info)
 	{
 		if (_storedInfo.containsKey(bossId))
@@ -340,7 +336,7 @@ public class GrandBossManager
 		_storedInfo.put(bossId, info);
 		storeToDb();
 	}
-
+	
 	private void storeToDb()
 	{
 		Connection con = null;
@@ -348,11 +344,11 @@ public class GrandBossManager
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-
+			
 			statement = con.prepareStatement(DELETE_GRAND_BOSS_LIST);
 			statement.executeUpdate();
 			statement.close();
-
+			
 			for (L2BossZone zone : _zones)
 			{
 				if (zone == null)
@@ -370,7 +366,7 @@ public class GrandBossManager
 					statement.close();
 				}
 			}
-
+			
 			for (Integer bossId : _storedInfo.keySet())
 			{
 				L2GrandBossInstance boss = _bosses.get(bossId);
@@ -421,7 +417,7 @@ public class GrandBossManager
 			}
 		}
 	}
-
+	
 	/**
 	 * Saves all Grand Boss info and then clears all info from memory,
 	 * including all schedules.
@@ -429,15 +425,21 @@ public class GrandBossManager
 	public void cleanUp()
 	{
 		storeToDb();
-
-		 _bosses.clear();
-		 _storedInfo.clear();
-		 _bossStatus.clear();
-		 _zones.clear();
+		
+		_bosses.clear();
+		_storedInfo.clear();
+		_bossStatus.clear();
+		_zones.clear();
 	}
 	
 	public L2FastList<L2BossZone> getZones()
 	{
 		return _zones;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final GrandBossManager _instance = new GrandBossManager();
+	}
 }

+ 25 - 20
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/InstanceManager.java

@@ -29,33 +29,32 @@ public class InstanceManager
 {
 	private final static Logger _log = Logger.getLogger(InstanceManager.class.getName());
 	private FastMap<Integer, Instance> _instanceList = new FastMap<Integer, Instance>();
-	private static InstanceManager _instance;
 	private int _dynamic = 300000;
-
+	
+	private InstanceManager()
+	{
+		_log.info("Initializing InstanceManager");
+		createWorld();
+	}
+	
 	public static final InstanceManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_log.info("Initializing InstanceManager");
-			_instance = new InstanceManager();
-			_instance.createWorld();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private void createWorld()
 	{
 		Instance themultiverse = new Instance(-1);
 		themultiverse.setName("multiverse");
 		_instanceList.put(-1, themultiverse);
 		_log.info("Multiverse Instance created");
-
+		
 		Instance universe = new Instance(0);
 		universe.setName("universe");
 		_instanceList.put(0, universe);
 		_log.info("Universe Instance created");
 	}
-
+	
 	public void destroyInstance(int instanceid)
 	{
 		if (instanceid <= 0)
@@ -70,17 +69,17 @@ public class InstanceManager
 			_instanceList.remove(instanceid);
 		}
 	}
-
+	
 	public Instance getInstance(int instanceid)
 	{
 		return _instanceList.get(instanceid);
 	}
 	
-	public FastMap<Integer,Instance> getInstances()
+	public FastMap<Integer, Instance> getInstances()
 	{
 		return _instanceList;
 	}
-
+	
 	public int getPlayerInstance(int objectId)
 	{
 		for (Instance temp : _instanceList.values())
@@ -92,22 +91,22 @@ public class InstanceManager
 		// 0 is default instance aka the world
 		return 0;
 	}
-
+	
 	public boolean createInstance(int id)
 	{
 		if (getInstance(id) != null)
 			return false;
-
+		
 		Instance instance = new Instance(id);
 		_instanceList.put(id, instance);
 		return true;
 	}
-
+	
 	public boolean createInstanceFromTemplate(int id, String template) throws FileNotFoundException
 	{
 		if (getInstance(id) != null)
 			return false;
-
+		
 		Instance instance = new Instance(id);
 		instance.loadInstanceTemplate(template);
 		_instanceList.put(id, instance);
@@ -121,7 +120,7 @@ public class InstanceManager
 	 */
 	public int createDynamicInstance(String template)
 	{
-
+		
 		while (getInstance(_dynamic) != null)
 		{
 			_dynamic++;
@@ -147,4 +146,10 @@ public class InstanceManager
 		_instanceList.put(_dynamic, instance);
 		return _dynamic;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final InstanceManager _instance = new InstanceManager();
+	}
 }

+ 14 - 19
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/ItemsOnGroundManager.java

@@ -42,8 +42,6 @@ public class ItemsOnGroundManager
 {
 	static final Logger _log = Logger.getLogger(ItemsOnGroundManager.class.getName());
 	
-	private static ItemsOnGroundManager _instance;
-	
 	protected ArrayList<L2ItemInstance> _items = null;
 	
 	private ItemsOnGroundManager()
@@ -52,16 +50,12 @@ public class ItemsOnGroundManager
 			_items = new ArrayList<L2ItemInstance>();
 		if (Config.SAVE_DROPPED_ITEM_INTERVAL > 0)
 			ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new storeInDb(), Config.SAVE_DROPPED_ITEM_INTERVAL, Config.SAVE_DROPPED_ITEM_INTERVAL);
+		load();
 	}
 	
 	public static final ItemsOnGroundManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ItemsOnGroundManager();
-			_instance.load();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private void load()
@@ -92,8 +86,7 @@ public class ItemsOnGroundManager
 			}
 			catch (Exception e)
 			{
-				_log.log(Level.SEVERE, "error while updating table ItemsOnGround "
-				        + e);
+				_log.log(Level.SEVERE, "error while updating table ItemsOnGround " + e);
 				e.printStackTrace();
 			}
 			finally
@@ -143,7 +136,7 @@ public class ItemsOnGroundManager
 					if (result.getLong(8) > -1)
 					{
 						if ((Config.AUTODESTROY_ITEM_AFTER > 0 && item.getItemType() != L2EtcItemType.HERB)
-						        || (Config.HERB_AUTO_DESTROY_TIME > 0 && item.getItemType() == L2EtcItemType.HERB))
+								|| (Config.HERB_AUTO_DESTROY_TIME > 0 && item.getItemType() == L2EtcItemType.HERB))
 							ItemsAutoDestroy.getInstance().addItem(item);
 					}
 				}
@@ -151,8 +144,7 @@ public class ItemsOnGroundManager
 			result.close();
 			s.close();
 			if (count > 0)
-				_log.info("ItemsOnGroundManager: restored " + count
-				        + " items.");
+				_log.info("ItemsOnGroundManager: restored " + count + " items.");
 			else
 				_log.info("Initializing ItemsOnGroundManager.");
 		}
@@ -212,8 +204,7 @@ public class ItemsOnGroundManager
 		}
 		catch (Exception e1)
 		{
-			_log.log(Level.SEVERE, "error while cleaning table ItemsOnGround "
-			        + e1);
+			_log.log(Level.SEVERE, "error while cleaning table ItemsOnGround " + e1);
 			e1.printStackTrace();
 		}
 		finally
@@ -279,8 +270,7 @@ public class ItemsOnGroundManager
 				}
 				catch (Exception e)
 				{
-					_log.log(Level.SEVERE, "error while inserting into table ItemsOnGround "
-					        + e);
+					_log.log(Level.SEVERE, "error while inserting into table ItemsOnGround " + e);
 					e.printStackTrace();
 				}
 				finally
@@ -295,8 +285,13 @@ public class ItemsOnGroundManager
 				}
 			}
 			if (Config.DEBUG)
-				_log.warning("ItemsOnGroundManager: " + _items.size()
-				        + " items on ground saved");
+				_log.warning("ItemsOnGroundManager: " + _items.size() + " items on ground saved");
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ItemsOnGroundManager _instance = new ItemsOnGroundManager();
+	}
 }

+ 379 - 371
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/MercTicketManager.java

@@ -33,7 +33,6 @@ import net.sf.l2j.gameserver.model.actor.instance.L2SiegeGuardInstance;
 import net.sf.l2j.gameserver.model.entity.Castle;
 import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 
-
 /**
  * @author yellowperil & Fulminus
  * This class is similar to the SiegeGuardManager, except it handles
@@ -51,375 +50,384 @@ import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
  */
 public class MercTicketManager
 {
-    protected static final Logger _log = Logger.getLogger(MercTicketManager.class.getName());
-
-    // =========================================================
-    private static MercTicketManager _instance;
-    public static final MercTicketManager getInstance()
-    {
-    	//CastleManager.getInstance();
-        if (_instance == null)
-        {
-    		_log.info("Initializing MercTicketManager");
-            _instance = new MercTicketManager();
-            _instance.load();
-        }
-        return _instance;
-    }
-    // =========================================================
-
-
-    // =========================================================
-    // Data Field
-    private List<L2ItemInstance> _droppedTickets;	// to keep track of items on the ground
-
-    //TODO move all these values into siege.properties
-    // max tickets per merc type = 10 + (castleid * 2)?
- 	// max ticker per castle = 40 + (castleid * 20)?
-     private static final int[] MAX_MERC_PER_TYPE = {
-            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Gludio
-            15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // Dion
-            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Giran
-            10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Oren
-            20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Aden
-            20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Innadril
-            20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Goddard
-            20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Rune
-            20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 // Schuttgart
-             };
-     private static final int[] MERCS_MAX_PER_CASTLE = {
-             100,  // Gludio
-            150,  // Dion
-            200, // Giran
-            300, // Oren
-            400, // Aden
-            400, // Innadril
-            400, // Goddard
-            400, // Rune
-            400  // Schuttgart
-    };
-    
-    private static final int[] ITEM_IDS = {
-	3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, 6047, 6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6295, 6296,	// Gludio
-	3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6245, 6246, 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6297, 6298,	// Dion
-	3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6255, 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, 6299, 6300,	// Giran
-	3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6301, 6302,	// Oren
-	4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 6155, 6156, 6157, 6158, 6159, 6160, 6161, 6162, 6163, 6164, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283, 6284, 6303, 6304,	// Aden
-	5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6305, 6306,	// Innadril
-	6779, 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6802, 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, 6792, 6793, 6794, 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, 6833,	// Goddard
-	7973, 7974, 7975, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7998, 7999, 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 8008, 8009, 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8024, 8025, 8026, 8027, 8028, 8029,	// Rune
-	7918, 7919, 7920, 7921, 7922, 7923, 7924, 7925, 7926, 7927, 7941, 7942, 7943, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7931, 7932, 7933, 7934, 7935, 7936, 7937, 7938, 7939, 7940, 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7958, 7959, 7960, 7961, 7962, 7963, 7964, 7965, 7966, 7967, 7968, 7969, 7970, 7971, 7972	// Schuttgart
+	protected static final Logger _log = Logger.getLogger(MercTicketManager.class.getName());
+	
+	public static final MercTicketManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	// =========================================================
+	
+	// =========================================================
+	// Data Field
+	private List<L2ItemInstance> _droppedTickets; // to keep track of items on the ground
+	
+	//TODO move all these values into siege.properties
+	// max tickets per merc type = 10 + (castleid * 2)?
+	// max ticker per castle = 40 + (castleid * 20)?
+	private static final int[] MAX_MERC_PER_TYPE = {
+			10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Gludio
+			15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // Dion
+			10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Giran
+			10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Oren
+			20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Aden
+			20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Innadril
+			20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Goddard
+			20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Rune
+			20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 // Schuttgart
 	};
-
-    private static final int[] NPC_IDS = {
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Gludio
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Dion
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Giran
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Oren
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Aden
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Innadril
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Goddard
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Rune
-           35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Schuttgart
-           };
-    
-    private static final int GUARDIAN_TYPES_COUNT = 52;
-
-    // =========================================================
-    // Constructor
-    public MercTicketManager()
-    {
-    }
-
-    // =========================================================
-    // Method - Public
-    // returns the castleId for the passed ticket item id
-    public int getTicketCastleId(int itemId)
-    {
-    	for (int i = 0; i < 9; i++) //CastleID`s from 1 to 9 minus;
-    	{ 
-    		for (int i2 = 0; i2 < 50; i2 += 10) //Simplified if statement;
-    			if ((itemId >= ITEM_IDS[i2 + i*GUARDIAN_TYPES_COUNT] &&  itemId <= ITEM_IDS[i2 + 9 + i*GUARDIAN_TYPES_COUNT]))
-    				return i + 1;
-    		if (itemId >= ITEM_IDS[50] &&  itemId <= ITEM_IDS[51])
-    			return i + 1;
-    	}
-    	return -1;
-    }
-
-    public void reload()
-    {
-    	getDroppedTickets().clear();
-    	load();
-    }
-
-    // =========================================================
-    // Method - Private
-    private final void load()
-    {
-        Connection con = null;
-        // load merc tickets into the world
-        try
-        {
-            PreparedStatement statement;
-            ResultSet rs;
-
-            con = L2DatabaseFactory.getInstance().getConnection();
-	        statement = con.prepareStatement("SELECT * FROM castle_siege_guards Where isHired = 1");
-	        rs = statement.executeQuery();
-
-	        int npcId;
-	        int itemId;
-	        int x,y,z;
-            int mercPlaced[] =  new int[20];
-	        // start index to begin the search for the itemId corresponding to this NPC
-	        // this will help with:
-	        //    a) skip unnecessary iterations in the search loop
-	        //    b) avoid finding the wrong itemId whenever tickets of different spawn the same npc!
-	        int startindex = 0;
-
-	        while (rs.next())
-	        {
-	        	npcId = rs.getInt("npcId");
-            	x = rs.getInt("x");
-            	y = rs.getInt("y");
-            	z = rs.getInt("z");
-            	Castle castle = CastleManager.getInstance().getCastle(x,y,z);
-            	if(castle != null)
-                {
-                    if (mercPlaced[castle.getCastleId()-1] >= MERCS_MAX_PER_CASTLE[castle.getCastleId()-1]) 
-                        continue;
-            		startindex = GUARDIAN_TYPES_COUNT * (castle.getCastleId()-1);
-                    mercPlaced[castle.getCastleId()-1] += 1;
-                }
-
-            	// find the FIRST ticket itemId with spawns the saved NPC in the saved location
-	        	for (int i = startindex; i < startindex + GUARDIAN_TYPES_COUNT; i++)
-	                if (NPC_IDS[i] == npcId) // Find the index of the item used
-	                {
-	    	        	// only handle tickets if a siege is not ongoing in this npc's castle
-
-	                	if((castle != null) && !(castle.getSiege().getIsInProgress()))
-	                	{
-	                		itemId = ITEM_IDS[i];
-		    	        	// create the ticket in the gameworld
-		    	    		L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
-		    	    		dropticket.setLocation(L2ItemInstance.ItemLocation.VOID);
-		    	    		dropticket.dropMe(null, x, y, z);
-		    	            dropticket.setDropTime(0); //avoids it from beeing removed by the auto item destroyer
-		    	            L2World.getInstance().storeObject(dropticket);
-		    	            getDroppedTickets().add(dropticket);
-	                	}
-	                	break;
-	                }
-	        }
-            statement.close();
-
-            _log.info("Loaded: " + getDroppedTickets().size() + " Mercenary Tickets");
-        }
-        catch (Exception e)
-        {
-            _log.warning("Exception: loadMercenaryData(): " + e.getMessage());
-            e.printStackTrace();
-        }
-        finally {try { con.close(); } catch (Exception e) {}}
-    }
-
-    // =========================================================
-    // Property - Public
-    /**
-     * Checks if the passed item has reached the limit of number of dropped
-     * tickets that this SPECIFIC item may have in its castle
-     */
-    public boolean isAtTypeLimit(int itemId)
-    {
-    	int limit = -1;
-    	// find the max value for this item
-    	for (int i=0;i<ITEM_IDS.length;i++)
-            if (ITEM_IDS[i] == itemId) // Find the index of the item used
-            {
-            	limit = MAX_MERC_PER_TYPE[i];
-            	break;
-            }
-
-    	if (limit <= 0)
-    		return true;
-
-    	int count = 0;
-    	for(L2ItemInstance ticket: getDroppedTickets())
-    	{
-    		if ( ticket != null && ticket.getItemId() == itemId)
-    			count++;
-    	}
-    	if(count >= limit)
-    		return true;
-    	return false;
-    }
-
-    /**
-     * Checks if the passed item belongs to a castle which has reached its limit
-     * of number of dropped tickets.
-     */
-    public boolean isAtCasleLimit(int itemId)
-    {
-    	int castleId = getTicketCastleId(itemId);
-    	if (castleId <= 0)
-    		return true;
-    	int limit = MERCS_MAX_PER_CASTLE[castleId-1];
-    	if (limit <= 0)
-    		return true;
-
-    	int count = 0;
-    	for(L2ItemInstance ticket: getDroppedTickets())
-    	{
-    		if ( (ticket != null) && (getTicketCastleId(ticket.getItemId()) == castleId) )
-    			count++;
-    	}
-    	if(count >= limit)
-    		return true;
-    	return false;
-    }
-    
-    public int getMaxAllowedMerc(int castleId)
-    {
-        return MERCS_MAX_PER_CASTLE[castleId-1]; 
-    }
-    
-    public boolean isTooCloseToAnotherTicket(int x, int y, int z)
-    {
-    	for (L2ItemInstance item : getDroppedTickets())
-    	{
-    		double dx = x - item.getX();
-            double dy = y - item.getY();
-            double dz = z - item.getZ();
-
-            if ((dx*dx + dy*dy + dz*dz) < 25*25) return true;
-    	}
-    	return false;
-    }
-    
-    /**
-     * addTicket actions
-     * 1) find the npc that needs to be saved in the mercenary spawns, given this item
-     * 2) Use the passed character's location info to add the spawn
-     * 3) create a copy of the item to drop in the world
-     * returns the id of the mercenary npc that was added to the spawn
-     * returns -1 if this fails.
-     */
-    public int addTicket(int itemId, L2PcInstance activeChar, String[] messages)
-    {
-    	int x = activeChar.getX();
-    	int y = activeChar.getY();
-    	int z = activeChar.getZ();
-    	int heading = activeChar.getHeading();
-
-        Castle castle = CastleManager.getInstance().getCastle(activeChar);
-        if (castle == null)		//this should never happen at this point
-        	return -1;
-        
-        for (int i = 0; i < ITEM_IDS.length; i++)
-        {
-            if (ITEM_IDS[i] == itemId) // Find the index of the item used
-            {
-            	spawnMercenary(NPC_IDS[i], x, y, z, 3000, messages, 0);
-
-                // Hire merc for this caslte.  NpcId is at the same index as the item used.
-                castle.getSiege().getSiegeGuardManager().hireMerc(x, y, z, heading, NPC_IDS[i]);
-
-                // create the ticket in the gameworld
-        		L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
-        		dropticket.setLocation(L2ItemInstance.ItemLocation.VOID);
-                dropticket.dropMe(null, x, y, z);
-                dropticket.setDropTime(0); //avoids it from beeing removed by the auto item destroyer
-                L2World.getInstance().storeObject(dropticket);	//add to the world
-                // and keep track of this ticket in the list
-                _droppedTickets.add(dropticket);
-
-                return NPC_IDS[i];
-            }
-        }
-        return -1;
-    }
-
-    private void spawnMercenary(int npcId, int x, int y, int z, int despawnDelay, String[] messages, int chatDelay)
-    {
-    	L2NpcTemplate template = NpcTable.getInstance().getTemplate(npcId);
-        if (template != null)
-        {
-            final L2SiegeGuardInstance npc = new L2SiegeGuardInstance(IdFactory.getInstance().getNextId(), template);
-            npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
-            npc.setDecayed(false);
-            npc.spawnMe(x, y, (z+20));
-
-            if (messages != null && messages.length >0 )
-            	AutoChatHandler.getInstance().registerChat(npc, messages, chatDelay);
-
-            if (despawnDelay > 0)
-            {
-	            ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
-	                public void run()
-	                {
-	                	npc.deleteMe();
-	                }
-	            }, despawnDelay);
-            }
-        }
-    }
-
-    /**
-     * Delete all tickets from a castle;
-     * remove the items from the world and remove references to them from this class
-     */
-    public void deleteTickets(int castleId)
-    {
-    	for (L2ItemInstance item: getDroppedTickets())
-    	{
-    		if ((item != null) && (getTicketCastleId(item.getItemId()) == castleId))
-    		{
-    			item.decayMe();
-    			L2World.getInstance().removeObject(item);
-
-    			// remove from the list
-    			getDroppedTickets().remove(item);
-    		}
-    	}
-    }
-
-
-    /**
-     * remove a single ticket and its associated spawn from the world
-     * (used when the castle lord picks up a ticket, for example)
-     */
-    public void removeTicket(L2ItemInstance item)
-    {
-    	int itemId = item.getItemId();
-    	int npcId = -1;
-
-    	// find the FIRST ticket itemId with spawns the saved NPC in the saved location
-    	for (int i=0;i<ITEM_IDS.length;i++)
-            if (ITEM_IDS[i] == itemId) // Find the index of the item used
-            {
-            	npcId = NPC_IDS[i];
-            	break;
-            }
-    	// find the castle where this item is
-    	Castle castle = CastleManager.getInstance().getCastleById(getTicketCastleId(itemId));
-
-    	if (npcId > 0 && castle != null)
-    	{
-    		(new SiegeGuardManager(castle)).removeMerc(npcId, item.getX(), item.getY(), item.getZ());
-    	}
-
-    	getDroppedTickets().remove(item);
-    }
-    public int[] getItemIds()
-    {
-        return ITEM_IDS;
-    }
-
-    public final List<L2ItemInstance> getDroppedTickets()
-    {
-        if (_droppedTickets == null) _droppedTickets = new FastList<L2ItemInstance>();
-        return _droppedTickets;
-    }
+	private static final int[] MERCS_MAX_PER_CASTLE = {
+			100, // Gludio
+			150, // Dion
+			200, // Giran
+			300, // Oren
+			400, // Aden
+			400, // Innadril
+			400, // Goddard
+			400, // Rune
+			400 // Schuttgart
+	};
+	
+	private static final int[] ITEM_IDS = {
+			3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, 6047, 6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6295, 6296,	// Gludio
+			3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6245, 6246, 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6297, 6298,	// Dion
+			3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6255, 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, 6299, 6300,	// Giran
+			3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6301, 6302,	// Oren
+			4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 6155, 6156, 6157, 6158, 6159, 6160, 6161, 6162, 6163, 6164, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283, 6284, 6303, 6304,	// Aden
+			5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6305, 6306,	// Innadril
+			6779, 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6802, 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, 6792, 6793, 6794, 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, 6833,	// Goddard
+			7973, 7974, 7975, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7998, 7999, 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 8008, 8009, 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8024, 8025, 8026, 8027, 8028, 8029,	// Rune
+			7918, 7919, 7920, 7921, 7922, 7923, 7924, 7925, 7926, 7927, 7941, 7942, 7943, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7931, 7932, 7933, 7934, 7935, 7936, 7937, 7938, 7939, 7940, 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7958, 7959, 7960, 7961, 7962, 7963, 7964, 7965, 7966, 7967, 7968, 7969, 7970, 7971, 7972	// Schuttgart
+	};
+	
+	private static final int[] NPC_IDS = {35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Gludio
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Dion
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Giran
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Oren
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Aden
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Innadril
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Goddard
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Rune
+			35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Schuttgart
+	};
+	
+	private static final int GUARDIAN_TYPES_COUNT = 52;
+	
+	// =========================================================
+	// Constructor
+	private MercTicketManager()
+	{
+		_log.info("Initializing MercTicketManager");
+		load();
+	}
+	
+	// =========================================================
+	// Method - Public
+	// returns the castleId for the passed ticket item id
+	public int getTicketCastleId(int itemId)
+	{
+		for (int i = 0; i < 9; i++) //CastleID`s from 1 to 9 minus;
+		{
+			for (int i2 = 0; i2 < 50; i2 += 10)
+				//Simplified if statement;
+				if ((itemId >= ITEM_IDS[i2 + i * GUARDIAN_TYPES_COUNT] && itemId <= ITEM_IDS[i2 + 9 + i * GUARDIAN_TYPES_COUNT]))
+					return i + 1;
+			if (itemId >= ITEM_IDS[50] && itemId <= ITEM_IDS[51])
+				return i + 1;
+		}
+		return -1;
+	}
+	
+	public void reload()
+	{
+		getDroppedTickets().clear();
+		load();
+	}
+	
+	// =========================================================
+	// Method - Private
+	private final void load()
+	{
+		Connection con = null;
+		// load merc tickets into the world
+		try
+		{
+			PreparedStatement statement;
+			ResultSet rs;
+			
+			con = L2DatabaseFactory.getInstance().getConnection();
+			statement = con.prepareStatement("SELECT * FROM castle_siege_guards Where isHired = 1");
+			rs = statement.executeQuery();
+			
+			int npcId;
+			int itemId;
+			int x, y, z;
+			int mercPlaced[] = new int[20];
+			// start index to begin the search for the itemId corresponding to this NPC
+			// this will help with:
+			//	a) skip unnecessary iterations in the search loop
+			//	b) avoid finding the wrong itemId whenever tickets of different spawn the same npc!
+			int startindex = 0;
+			
+			while (rs.next())
+			{
+				npcId = rs.getInt("npcId");
+				x = rs.getInt("x");
+				y = rs.getInt("y");
+				z = rs.getInt("z");
+				Castle castle = CastleManager.getInstance().getCastle(x, y, z);
+				if (castle != null)
+				{
+					if (mercPlaced[castle.getCastleId() - 1] >= MERCS_MAX_PER_CASTLE[castle.getCastleId() - 1])
+						continue;
+					startindex = GUARDIAN_TYPES_COUNT * (castle.getCastleId() - 1);
+					mercPlaced[castle.getCastleId() - 1] += 1;
+				}
+				
+				// find the FIRST ticket itemId with spawns the saved NPC in the saved location
+				for (int i = startindex; i < startindex + GUARDIAN_TYPES_COUNT; i++)
+					if (NPC_IDS[i] == npcId) // Find the index of the item used
+					{
+						// only handle tickets if a siege is not ongoing in this npc's castle
+						
+						if ((castle != null) && !(castle.getSiege().getIsInProgress()))
+						{
+							itemId = ITEM_IDS[i];
+							// create the ticket in the gameworld
+							L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
+							dropticket.setLocation(L2ItemInstance.ItemLocation.VOID);
+							dropticket.dropMe(null, x, y, z);
+							dropticket.setDropTime(0); //avoids it from beeing removed by the auto item destroyer
+							L2World.getInstance().storeObject(dropticket);
+							getDroppedTickets().add(dropticket);
+						}
+						break;
+					}
+			}
+			statement.close();
+			
+			_log.info("Loaded: " + getDroppedTickets().size() + " Mercenary Tickets");
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: loadMercenaryData(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	// =========================================================
+	// Property - Public
+	/**
+	 * Checks if the passed item has reached the limit of number of dropped
+	 * tickets that this SPECIFIC item may have in its castle
+	 */
+	public boolean isAtTypeLimit(int itemId)
+	{
+		int limit = -1;
+		// find the max value for this item
+		for (int i = 0; i < ITEM_IDS.length; i++)
+			if (ITEM_IDS[i] == itemId) // Find the index of the item used
+			{
+				limit = MAX_MERC_PER_TYPE[i];
+				break;
+			}
+		
+		if (limit <= 0)
+			return true;
+		
+		int count = 0;
+		for (L2ItemInstance ticket : getDroppedTickets())
+		{
+			if (ticket != null && ticket.getItemId() == itemId)
+				count++;
+		}
+		if (count >= limit)
+			return true;
+		return false;
+	}
+	
+	/**
+	 * Checks if the passed item belongs to a castle which has reached its limit
+	 * of number of dropped tickets.
+	 */
+	public boolean isAtCasleLimit(int itemId)
+	{
+		int castleId = getTicketCastleId(itemId);
+		if (castleId <= 0)
+			return true;
+		int limit = MERCS_MAX_PER_CASTLE[castleId - 1];
+		if (limit <= 0)
+			return true;
+		
+		int count = 0;
+		for (L2ItemInstance ticket : getDroppedTickets())
+		{
+			if ((ticket != null) && (getTicketCastleId(ticket.getItemId()) == castleId))
+				count++;
+		}
+		if (count >= limit)
+			return true;
+		return false;
+	}
+	
+	public int getMaxAllowedMerc(int castleId)
+	{
+		return MERCS_MAX_PER_CASTLE[castleId - 1];
+	}
+	
+	public boolean isTooCloseToAnotherTicket(int x, int y, int z)
+	{
+		for (L2ItemInstance item : getDroppedTickets())
+		{
+			double dx = x - item.getX();
+			double dy = y - item.getY();
+			double dz = z - item.getZ();
+			
+			if ((dx * dx + dy * dy + dz * dz) < 25 * 25)
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * addTicket actions
+	 * 1) find the npc that needs to be saved in the mercenary spawns, given this item
+	 * 2) Use the passed character's location info to add the spawn
+	 * 3) create a copy of the item to drop in the world
+	 * returns the id of the mercenary npc that was added to the spawn
+	 * returns -1 if this fails.
+	 */
+	public int addTicket(int itemId, L2PcInstance activeChar, String[] messages)
+	{
+		int x = activeChar.getX();
+		int y = activeChar.getY();
+		int z = activeChar.getZ();
+		int heading = activeChar.getHeading();
+		
+		Castle castle = CastleManager.getInstance().getCastle(activeChar);
+		if (castle == null) //this should never happen at this point
+			return -1;
+		
+		for (int i = 0; i < ITEM_IDS.length; i++)
+		{
+			if (ITEM_IDS[i] == itemId) // Find the index of the item used
+			{
+				spawnMercenary(NPC_IDS[i], x, y, z, 3000, messages, 0);
+				
+				// Hire merc for this caslte.  NpcId is at the same index as the item used.
+				castle.getSiege().getSiegeGuardManager().hireMerc(x, y, z, heading, NPC_IDS[i]);
+				
+				// create the ticket in the gameworld
+				L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
+				dropticket.setLocation(L2ItemInstance.ItemLocation.VOID);
+				dropticket.dropMe(null, x, y, z);
+				dropticket.setDropTime(0); //avoids it from beeing removed by the auto item destroyer
+				L2World.getInstance().storeObject(dropticket); //add to the world
+				// and keep track of this ticket in the list
+				_droppedTickets.add(dropticket);
+				
+				return NPC_IDS[i];
+			}
+		}
+		return -1;
+	}
+	
+	private void spawnMercenary(int npcId, int x, int y, int z, int despawnDelay, String[] messages, int chatDelay)
+	{
+		L2NpcTemplate template = NpcTable.getInstance().getTemplate(npcId);
+		if (template != null)
+		{
+			final L2SiegeGuardInstance npc = new L2SiegeGuardInstance(IdFactory.getInstance().getNextId(), template);
+			npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
+			npc.setDecayed(false);
+			npc.spawnMe(x, y, (z + 20));
+			
+			if (messages != null && messages.length > 0)
+				AutoChatHandler.getInstance().registerChat(npc, messages, chatDelay);
+			
+			if (despawnDelay > 0)
+			{
+				ThreadPoolManager.getInstance().scheduleGeneral(new Runnable() {
+					public void run()
+					{
+						npc.deleteMe();
+					}
+				}, despawnDelay);
+			}
+		}
+	}
+	
+	/**
+	 * Delete all tickets from a castle;
+	 * remove the items from the world and remove references to them from this class
+	 */
+	public void deleteTickets(int castleId)
+	{
+		for (L2ItemInstance item : getDroppedTickets())
+		{
+			if ((item != null) && (getTicketCastleId(item.getItemId()) == castleId))
+			{
+				item.decayMe();
+				L2World.getInstance().removeObject(item);
+				
+				// remove from the list
+				getDroppedTickets().remove(item);
+			}
+		}
+	}
+	
+	/**
+	 * remove a single ticket and its associated spawn from the world
+	 * (used when the castle lord picks up a ticket, for example)
+	 */
+	public void removeTicket(L2ItemInstance item)
+	{
+		int itemId = item.getItemId();
+		int npcId = -1;
+		
+		// find the FIRST ticket itemId with spawns the saved NPC in the saved location
+		for (int i = 0; i < ITEM_IDS.length; i++)
+			if (ITEM_IDS[i] == itemId) // Find the index of the item used
+			{
+				npcId = NPC_IDS[i];
+				break;
+			}
+		// find the castle where this item is
+		Castle castle = CastleManager.getInstance().getCastleById(getTicketCastleId(itemId));
+		
+		if (npcId > 0 && castle != null)
+		{
+			(new SiegeGuardManager(castle)).removeMerc(npcId, item.getX(), item.getY(), item.getZ());
+		}
+		
+		getDroppedTickets().remove(item);
+	}
+	
+	public int[] getItemIds()
+	{
+		return ITEM_IDS;
+	}
+	
+	public final List<L2ItemInstance> getDroppedTickets()
+	{
+		if (_droppedTickets == null)
+			_droppedTickets = new FastList<L2ItemInstance>();
+		return _droppedTickets;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final MercTicketManager _instance = new MercTicketManager();
+	}
 }

+ 213 - 244
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/PetitionManager.java

@@ -43,11 +43,10 @@ import net.sf.l2j.gameserver.util.StringUtil;
 public final class PetitionManager
 {
 	protected static final Logger _log = Logger.getLogger(PetitionManager.class.getName());
-	private static PetitionManager _instance;
-
+	
 	private Map<Integer, Petition> _pendingPetitions;
 	private Map<Integer, Petition> _completedPetitions;
-
+	
 	private static enum PetitionState
 	{
 		Pending,
@@ -60,7 +59,7 @@ public final class PetitionManager
 		In_Process,
 		Completed
 	}
-
+	
 	private static enum PetitionType
 	{
 		Immobility,
@@ -73,62 +72,56 @@ public final class PetitionManager
 		Operation_Related,
 		Other
 	}
-
+	
 	public static PetitionManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_log.info("Initializing PetitionManager");
-			_instance = new PetitionManager();
-		}
-
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	private class Petition
 	{
 		private long _submitTime = System.currentTimeMillis();
 		private long _endTime = -1;
-
+		
 		private int _id;
 		private PetitionType _type;
 		private PetitionState _state = PetitionState.Pending;
 		private String _content;
-
+		
 		private List<CreatureSay> _messageLog = new FastList<CreatureSay>();
-
+		
 		private L2PcInstance _petitioner;
 		private L2PcInstance _responder;
-
+		
 		public Petition(L2PcInstance petitioner, String petitionText, int petitionType)
 		{
 			petitionType--;
 			_id = IdFactory.getInstance().getNextId();
-			if(petitionType >= PetitionType.values().length)
+			if (petitionType >= PetitionType.values().length)
 			{
-				_log.warning("PetitionManager:Petition : invalid petition type (received type was +1) : "+ petitionType);
+				_log.warning("PetitionManager:Petition : invalid petition type (received type was +1) : " + petitionType);
 			}
 			_type = PetitionType.values()[petitionType];
 			_content = petitionText;
-
+			
 			_petitioner = petitioner;
 		}
-
-        protected boolean addLogMessage(CreatureSay cs)
+		
+		protected boolean addLogMessage(CreatureSay cs)
 		{
 			return _messageLog.add(cs);
 		}
-
+		
 		protected List<CreatureSay> getLogMessages()
 		{
 			return _messageLog;
 		}
-
+		
 		public boolean endPetitionConsultation(PetitionState endState)
 		{
 			setState(endState);
 			_endTime = System.currentTimeMillis();
-
+			
 			if (getResponder() != null && getResponder().isOnline() == 1)
 			{
 				if (endState == PetitionState.Responder_Reject)
@@ -137,83 +130,83 @@ public final class PetitionManager
 				}
 				else
 				{
-                    // Ending petition consultation with <Player>.
+					// Ending petition consultation with <Player>.
 					SystemMessage sm = new SystemMessage(SystemMessageId.PETITION_ENDED_WITH_C1);
 					sm.addString(getPetitioner().getName());
 					getResponder().sendPacket(sm);
-
+					
 					if (endState == PetitionState.Petitioner_Cancel)
 					{
-                        // Receipt No. <ID> petition cancelled.
+						// Receipt No. <ID> petition cancelled.
 						sm = new SystemMessage(SystemMessageId.RECENT_NO_S1_CANCELED);
 						sm.addNumber(getId());
 						getResponder().sendPacket(sm);
 					}
 				}
 			}
-
-            // End petition consultation and inform them, if they are still online.
+			
+			// End petition consultation and inform them, if they are still online.
 			if (getPetitioner() != null && getPetitioner().isOnline() == 1)
 				getPetitioner().sendPacket(new SystemMessage(SystemMessageId.THIS_END_THE_PETITION_PLEASE_PROVIDE_FEEDBACK));
-
+			
 			getCompletedPetitions().put(getId(), this);
 			return (getPendingPetitions().remove(getId()) != null);
 		}
-
+		
 		public String getContent()
 		{
 			return _content;
 		}
-
+		
 		public int getId()
 		{
 			return _id;
 		}
-
+		
 		public L2PcInstance getPetitioner()
 		{
 			return _petitioner;
 		}
-
+		
 		public L2PcInstance getResponder()
 		{
 			return _responder;
 		}
-
+		
 		public long getEndTime()
 		{
 			return _endTime;
 		}
-
+		
 		public long getSubmitTime()
 		{
 			return _submitTime;
 		}
-
+		
 		public PetitionState getState()
 		{
 			return _state;
 		}
-
+		
 		public String getTypeAsString()
 		{
 			return _type.toString().replace("_", " ");
 		}
-
+		
 		public void sendPetitionerPacket(L2GameServerPacket responsePacket)
 		{
 			if (getPetitioner() == null || getPetitioner().isOnline() == 0)
 			{
-                // Allows petitioners to see the results of their petition when
-                // they log back into the game.
-
+				// Allows petitioners to see the results of their petition when
+				// they log back into the game.
+				
 				//endPetitionConsultation(PetitionState.Petitioner_Missing);
 				return;
 			}
-
+			
 			getPetitioner().sendPacket(responsePacket);
 		}
-
+		
 		public void sendResponderPacket(L2GameServerPacket responsePacket)
 		{
 			if (getResponder() == null || getResponder().isOnline() == 0)
@@ -221,388 +214,364 @@ public final class PetitionManager
 				endPetitionConsultation(PetitionState.Responder_Missing);
 				return;
 			}
-
+			
 			getResponder().sendPacket(responsePacket);
 		}
-
+		
 		public void setState(PetitionState state)
 		{
 			_state = state;
 		}
-
+		
 		public void setResponder(L2PcInstance respondingAdmin)
 		{
-            if (getResponder() != null)
-                return;
-
+			if (getResponder() != null)
+				return;
+			
 			_responder = respondingAdmin;
 		}
 	}
-
-
+	
 	private PetitionManager()
 	{
+		_log.info("Initializing PetitionManager");
 		_pendingPetitions = new FastMap<Integer, Petition>();
 		_completedPetitions = new FastMap<Integer, Petition>();
 	}
-
+	
 	public void clearCompletedPetitions()
 	{
 		int numPetitions = getPendingPetitionCount();
-
+		
 		getCompletedPetitions().clear();
 		_log.info("PetitionManager: Completed petition data cleared. " + numPetitions + " petition(s) removed.");
 	}
-
+	
 	public void clearPendingPetitions()
 	{
 		int numPetitions = getPendingPetitionCount();
-
+		
 		getPendingPetitions().clear();
 		_log.info("PetitionManager: Pending petition queue cleared. " + numPetitions + " petition(s) removed.");
 	}
-
+	
 	public boolean acceptPetition(L2PcInstance respondingAdmin, int petitionId)
 	{
 		if (!isValidPetition(petitionId))
 			return false;
-
+		
 		Petition currPetition = getPendingPetitions().get(petitionId);
-
+		
 		if (currPetition.getResponder() != null)
 			return false;
-
+		
 		currPetition.setResponder(respondingAdmin);
 		currPetition.setState(PetitionState.In_Process);
-
-        // Petition application accepted. (Send to Petitioner)
+		
+		// Petition application accepted. (Send to Petitioner)
 		currPetition.sendPetitionerPacket(new SystemMessage(SystemMessageId.PETITION_APP_ACCEPTED));
-
-        // Petition application accepted. Reciept No. is <ID>
+		
+		// Petition application accepted. Reciept No. is <ID>
 		SystemMessage sm = new SystemMessage(SystemMessageId.PETITION_ACCEPTED_RECENT_NO_S1);
 		sm.addNumber(currPetition.getId());
 		currPetition.sendResponderPacket(sm);
-
-        // Petition consultation with <Player> underway.
+		
+		// Petition consultation with <Player> underway.
 		sm = new SystemMessage(SystemMessageId.STARTING_PETITION_WITH_C1);
 		sm.addString(currPetition.getPetitioner().getName());
 		currPetition.sendResponderPacket(sm);
 		return true;
 	}
-
+	
 	public boolean cancelActivePetition(L2PcInstance player)
 	{
-        for (Petition currPetition : getPendingPetitions().values())
-    	{
-            if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
-                return (currPetition.endPetitionConsultation(PetitionState.Petitioner_Cancel));
-
-            if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
-                return (currPetition.endPetitionConsultation(PetitionState.Responder_Cancel));
-        }
-
+		for (Petition currPetition : getPendingPetitions().values())
+		{
+			if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
+				return (currPetition.endPetitionConsultation(PetitionState.Petitioner_Cancel));
+			
+			if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
+				return (currPetition.endPetitionConsultation(PetitionState.Responder_Cancel));
+		}
+		
 		return false;
 	}
-
+	
 	public void checkPetitionMessages(L2PcInstance petitioner)
 	{
-        if (petitioner != null)
-    		for (Petition currPetition : getPendingPetitions().values())
-    		{
-                if (currPetition == null)
-                    continue;
-
-    			if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == petitioner.getObjectId())
-    			{
-    				for (CreatureSay logMessage : currPetition.getLogMessages())
-    					petitioner.sendPacket(logMessage);
-
-    				return;
-    			}
-    		}
+		if (petitioner != null)
+			for (Petition currPetition : getPendingPetitions().values())
+			{
+				if (currPetition == null)
+					continue;
+				
+				if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == petitioner.getObjectId())
+				{
+					for (CreatureSay logMessage : currPetition.getLogMessages())
+						petitioner.sendPacket(logMessage);
+					
+					return;
+				}
+			}
 	}
-
+	
 	public boolean endActivePetition(L2PcInstance player)
 	{
 		if (!player.isGM())
 			return false;
-
+		
 		for (Petition currPetition : getPendingPetitions().values())
-        {
-            if (currPetition == null)
-                continue;
-
+		{
+			if (currPetition == null)
+				continue;
+			
 			if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
 				return (currPetition.endPetitionConsultation(PetitionState.Completed));
-        }
-
+		}
+		
 		return false;
 	}
-
-    protected Map<Integer, Petition> getCompletedPetitions()
+	
+	protected Map<Integer, Petition> getCompletedPetitions()
 	{
 		return _completedPetitions;
 	}
-
-    protected Map<Integer, Petition> getPendingPetitions()
+	
+	protected Map<Integer, Petition> getPendingPetitions()
 	{
 		return _pendingPetitions;
 	}
-
+	
 	public int getPendingPetitionCount()
 	{
 		return getPendingPetitions().size();
 	}
-
+	
 	public int getPlayerTotalPetitionCount(L2PcInstance player)
 	{
-        if (player == null)
-            return 0;
-
+		if (player == null)
+			return 0;
+		
 		int petitionCount = 0;
-
+		
 		for (Petition currPetition : getPendingPetitions().values())
-        {
-            if (currPetition == null)
-                continue;
-
+		{
+			if (currPetition == null)
+				continue;
+			
 			if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
 				petitionCount++;
-        }
-
+		}
+		
 		for (Petition currPetition : getCompletedPetitions().values())
-        {
-            if (currPetition == null)
-                continue;
-
+		{
+			if (currPetition == null)
+				continue;
+			
 			if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
 				petitionCount++;
-        }
-
+		}
+		
 		return petitionCount;
 	}
-
+	
 	public boolean isPetitionInProcess()
 	{
 		for (Petition currPetition : getPendingPetitions().values())
-        {
-            if (currPetition == null)
-                continue;
-
+		{
+			if (currPetition == null)
+				continue;
+			
 			if (currPetition.getState() == PetitionState.In_Process)
 				return true;
-        }
-
+		}
+		
 		return false;
 	}
-
+	
 	public boolean isPetitionInProcess(int petitionId)
 	{
 		if (!isValidPetition(petitionId))
 			return false;
-
+		
 		Petition currPetition = getPendingPetitions().get(petitionId);
 		return (currPetition.getState() == PetitionState.In_Process);
 	}
-
+	
 	public boolean isPlayerInConsultation(L2PcInstance player)
 	{
-        if (player != null)
-    	    for (Petition currPetition : getPendingPetitions().values())
-    	    {
-                if (currPetition == null)
-                    continue;
-
-                if (currPetition.getState() != PetitionState.In_Process)
-                    continue;
-
-                if ((currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId()) ||
-                        (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId()))
-    	            return true;
-    	    }
-
+		if (player != null)
+			for (Petition currPetition : getPendingPetitions().values())
+			{
+				if (currPetition == null)
+					continue;
+				
+				if (currPetition.getState() != PetitionState.In_Process)
+					continue;
+				
+				if ((currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
+						|| (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId()))
+					return true;
+			}
+		
 		return false;
 	}
-
+	
 	public boolean isPetitioningAllowed()
 	{
 		return Config.PETITIONING_ALLOWED;
 	}
-
+	
 	public boolean isPlayerPetitionPending(L2PcInstance petitioner)
 	{
-        if (petitioner != null)
-    		for (Petition currPetition : getPendingPetitions().values())
-            {
-                if (currPetition == null)
-                    continue;
-
-    			if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == petitioner.getObjectId())
-    				return true;
-            }
-
+		if (petitioner != null)
+			for (Petition currPetition : getPendingPetitions().values())
+			{
+				if (currPetition == null)
+					continue;
+				
+				if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == petitioner.getObjectId())
+					return true;
+			}
+		
 		return false;
 	}
-
+	
 	private boolean isValidPetition(int petitionId)
 	{
 		return getPendingPetitions().containsKey(petitionId);
 	}
-
+	
 	public boolean rejectPetition(L2PcInstance respondingAdmin, int petitionId)
 	{
 		if (!isValidPetition(petitionId))
 			return false;
-
+		
 		Petition currPetition = getPendingPetitions().get(petitionId);
-
+		
 		if (currPetition.getResponder() != null)
 			return false;
-
+		
 		currPetition.setResponder(respondingAdmin);
 		return (currPetition.endPetitionConsultation(PetitionState.Responder_Reject));
 	}
-
+	
 	public boolean sendActivePetitionMessage(L2PcInstance player, String messageText)
 	{
 		//if (!isPlayerInConsultation(player))
 		//return false;
-
+		
 		CreatureSay cs;
-
+		
 		for (Petition currPetition : getPendingPetitions().values())
 		{
-            if (currPetition == null)
-                continue;
-
+			if (currPetition == null)
+				continue;
+			
 			if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
 			{
 				cs = new CreatureSay(player.getObjectId(), Say2.PETITION_PLAYER, player.getName(), messageText);
 				currPetition.addLogMessage(cs);
-
+				
 				currPetition.sendResponderPacket(cs);
 				currPetition.sendPetitionerPacket(cs);
 				return true;
 			}
-
+			
 			if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
 			{
 				cs = new CreatureSay(player.getObjectId(), Say2.PETITION_GM, player.getName(), messageText);
 				currPetition.addLogMessage(cs);
-
+				
 				currPetition.sendResponderPacket(cs);
 				currPetition.sendPetitionerPacket(cs);
 				return true;
 			}
 		}
-
+		
 		return false;
 	}
-
-	public void sendPendingPetitionList(L2PcInstance activeChar) {
-            final StringBuilder htmlContent = StringUtil.startAppend(
-                    400 + getPendingPetitionCount() * 300,
-                    "<html><body>" +
-                    "<center><font color=\"LEVEL\">Current Petitions</font><br><table width=\"300\">"
-                    );
+	
+	public void sendPendingPetitionList(L2PcInstance activeChar)
+	{
+		final StringBuilder htmlContent = StringUtil.startAppend(400 + getPendingPetitionCount() * 300, "<html><body>"
+				+ "<center><font color=\"LEVEL\">Current Petitions</font><br><table width=\"300\">");
 		SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM HH:mm z");
-
+		
 		if (getPendingPetitionCount() == 0)
 			htmlContent.append("<tr><td colspan=\"4\">There are no currently pending petitions.</td></tr>");
 		else
-			htmlContent.append("<tr><td></td><td><font color=\"999999\">Petitioner</font></td>" +
-			"<td><font color=\"999999\">Petition Type</font></td><td><font color=\"999999\">Submitted</font></td></tr>");
-
+			htmlContent.append("<tr><td></td><td><font color=\"999999\">Petitioner</font></td>"
+					+ "<td><font color=\"999999\">Petition Type</font></td><td><font color=\"999999\">Submitted</font></td></tr>");
+		
 		for (Petition currPetition : getPendingPetitions().values())
 		{
-            if (currPetition == null)
-                continue;
-
+			if (currPetition == null)
+				continue;
+			
 			htmlContent.append("<tr><td>");
-
-			if (currPetition.getState() != PetitionState.In_Process) {
-                            StringUtil.append(htmlContent,
-                                    "<button value=\"View\" action=\"bypass -h admin_view_petition ",
-                                    String.valueOf(currPetition.getId()),
-                                    "\" width=\"40\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">");
-                        } else {
+			
+			if (currPetition.getState() != PetitionState.In_Process)
+			{
+				StringUtil.append(htmlContent, "<button value=\"View\" action=\"bypass -h admin_view_petition ", String.valueOf(currPetition.getId()), "\" width=\"40\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">");
+			}
+			else
+			{
 				htmlContent.append("<font color=\"999999\">In Process</font>");
-                        }
-
-                        StringUtil.append(htmlContent,
-                                "</td><td>",
-                                currPetition.getPetitioner().getName(),
-                                "</td><td>",
-                                currPetition.getTypeAsString(),
-                                "</td><td>",
-                                dateFormat.format(new Date(currPetition.getSubmitTime())),
-                                "</td></tr>"
-                                );
+			}
+			
+			StringUtil.append(htmlContent, "</td><td>", currPetition.getPetitioner().getName(), "</td><td>", currPetition.getTypeAsString(), "</td><td>", dateFormat.format(new Date(currPetition.getSubmitTime())), "</td></tr>");
 		}
-
-		htmlContent.append("</table><br><button value=\"Refresh\" action=\"bypass -h admin_view_petitions\" width=\"50\" " +
-		                   "height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"><br><button value=\"Back\" action=\"bypass -h admin_admin\" " +
-		"width=\"40\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></center></body></html>");
-
+		
+		htmlContent.append("</table><br><button value=\"Refresh\" action=\"bypass -h admin_view_petitions\" width=\"50\" "
+				+ "height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"><br><button value=\"Back\" action=\"bypass -h admin_admin\" "
+				+ "width=\"40\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></center></body></html>");
+		
 		NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0);
 		htmlMsg.setHtml(htmlContent.toString());
 		activeChar.sendPacket(htmlMsg);
 	}
-
+	
 	public int submitPetition(L2PcInstance petitioner, String petitionText, int petitionType)
 	{
 		// Create a new petition instance and add it to the list of pending petitions.
 		Petition newPetition = new Petition(petitioner, petitionText, petitionType);
 		int newPetitionId = newPetition.getId();
 		getPendingPetitions().put(newPetitionId, newPetition);
-
+		
 		// Notify all GMs that a new petition has been submitted.
 		String msgContent = petitioner.getName() + " has submitted a new petition."; //(ID: " + newPetitionId + ").";
 		GmListTable.broadcastToGMs(new CreatureSay(petitioner.getObjectId(), Say2.HERO_VOICE, "Petition System", msgContent));
-
+		
 		return newPetitionId;
 	}
-
+	
 	public void viewPetition(L2PcInstance activeChar, int petitionId)
 	{
 		if (!activeChar.isGM())
 			return;
-
+		
 		if (!isValidPetition(petitionId))
 			return;
-
+		
 		Petition currPetition = getPendingPetitions().get(petitionId);
 		SimpleDateFormat dateFormat = new SimpleDateFormat("EEE dd MMM HH:mm z");
-                final String htmlContent = StringUtil.concat(
-                        "<html><body>" +
-                        "<center><br><font color=\"LEVEL\">Petition #",
-                        String.valueOf(currPetition.getId()),
-                        "</font><br1>" +
-                        "<img src=\"L2UI.SquareGray\" width=\"200\" height=\"1\"></center><br>" +
-                        "Submit Time: ",
-                        dateFormat.format(new Date(currPetition.getSubmitTime())),
-                        "<br1>" +
-                        "Petitioner: ",
-                        currPetition.getPetitioner().getName(),
-                        "<br1>" +
-                        "Petition Type: ",
-                        currPetition.getTypeAsString(),
-                        "<br>",
-                        currPetition.getContent(),
-                        "<br>" +
-                        "<center><button value=\"Accept\" action=\"bypass -h admin_accept_petition ",
-                        String.valueOf(currPetition.getId()),
-                        "\" width=\"50\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"><br1>" +
-                        "<button value=\"Reject\" action=\"bypass -h admin_reject_petition ",
-                        String.valueOf(currPetition.getId()),
-                        "\" width=\"50\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"><br>" +
-                        "<button value=\"Back\" action=\"bypass -h admin_view_petitions\" width=\"40\" height=\"15\" back=\"L2UI_ct1.button_df\" " +
-        		"fore=\"L2UI_ct1.button_df\"></center>" +
-                        "</body></html>"
-                        );
-
+		final String htmlContent = StringUtil.concat("<html><body>" + "<center><br><font color=\"LEVEL\">Petition #", String.valueOf(currPetition.getId()), "</font><br1>"
+				+ "<img src=\"L2UI.SquareGray\" width=\"200\" height=\"1\"></center><br>" + "Submit Time: ", dateFormat.format(new Date(currPetition.getSubmitTime())), "<br1>"
+				+ "Petitioner: ", currPetition.getPetitioner().getName(), "<br1>" + "Petition Type: ", currPetition.getTypeAsString(), "<br>", currPetition.getContent(), "<br>"
+				+ "<center><button value=\"Accept\" action=\"bypass -h admin_accept_petition ", String.valueOf(currPetition.getId()), "\" width=\"50\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"><br1>"
+				+ "<button value=\"Reject\" action=\"bypass -h admin_reject_petition ", String.valueOf(currPetition.getId()), "\" width=\"50\" height=\"15\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"><br>"
+				+ "<button value=\"Back\" action=\"bypass -h admin_view_petitions\" width=\"40\" height=\"15\" back=\"L2UI_ct1.button_df\" "
+				+ "fore=\"L2UI_ct1.button_df\"></center>" + "</body></html>");
+		
 		NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0);
 		htmlMsg.setHtml(htmlContent);
 		activeChar.sendPacket(htmlMsg);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final PetitionManager _instance = new PetitionManager();
+	}
 }

+ 145 - 147
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/QuestManager.java

@@ -27,63 +27,56 @@ import net.sf.l2j.gameserver.scripting.ScriptManager;
 
 public class QuestManager extends ScriptManager<Quest>
 {
-    protected static final Logger _log = Logger.getLogger(QuestManager.class.getName());
-
-    // =========================================================
-    private static QuestManager _instance;
-    public static final QuestManager getInstance()
-    {
-        if (_instance == null)
-        {
-    		_log.info("Initializing QuestManager");
-            _instance = new QuestManager();
-        }
-        return _instance;
-    }
-    // =========================================================
-
-
-    // =========================================================
-    // Data Field
-    private Map<String, Quest> _quests = new FastMap<String, Quest>();
-
-    // =========================================================
-    // Constructor
-    public QuestManager()
-    {
-    }
-
-    // =========================================================
-    // Method - Public
-    public final boolean reload(String questFolder)
-    {
-    	Quest q = getQuest(questFolder);
-    	if (q == null)
-    	{
-            return false;
-    	}
-    	return q.reload();
-    }
-    
-    /**
-     * Reloads a the quest given by questId.<BR>
-     * <B>NOTICE: Will only work if the quest name is equal the quest folder name</B>
-     * @param questId The id of the quest to be reloaded
-     * @return true if reload was successful, false otherwise
-     */
-    public final boolean reload(int questId)
-    {
-    	Quest q = this.getQuest(questId);
-    	if (q == null)
-    	{
-    		return false;
-    	}
-    	return q.reload();
-    }
-    
-    public final void reloadAllQuests()
-    {
-    	_log.info("Reloading Server Scripts");
+	protected static final Logger _log = Logger.getLogger(QuestManager.class.getName());
+	
+	public static final QuestManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	// =========================================================
+	
+	// =========================================================
+	// Data Field
+	private Map<String, Quest> _quests = new FastMap<String, Quest>();
+	
+	// =========================================================
+	// Constructor
+	private QuestManager()
+	{
+		_log.info("Initializing QuestManager");
+	}
+	
+	// =========================================================
+	// Method - Public
+	public final boolean reload(String questFolder)
+	{
+		Quest q = getQuest(questFolder);
+		if (q == null)
+		{
+			return false;
+		}
+		return q.reload();
+	}
+	
+	/**
+	 * Reloads a the quest given by questId.<BR>
+	 * <B>NOTICE: Will only work if the quest name is equal the quest folder name</B>
+	 * @param questId The id of the quest to be reloaded
+	 * @return true if reload was successful, false otherwise
+	 */
+	public final boolean reload(int questId)
+	{
+		Quest q = this.getQuest(questId);
+		if (q == null)
+		{
+			return false;
+		}
+		return q.reload();
+	}
+	
+	public final void reloadAllQuests()
+	{
+		_log.info("Reloading Server Scripts");
 		try
 		{
 			// unload all scripts
@@ -101,95 +94,100 @@ public class QuestManager extends ScriptManager<Quest>
 		{
 			_log.severe("Failed loading scripts.cfg, no script going to be loaded");
 		}
-    }
-    
-    public final void report()
-    {
-        _log.info("Loaded: " + _quests.size() + " quests");
-    }
-    
-    public final void save()
-    {
-    	for (Quest q: _quests.values())
-        {
-    		q.saveGlobalData();
-        }
-    }
-
-    // =========================================================
-    // Property - Public
-    public final Quest getQuest(String name)
-    {
+	}
+	
+	public final void report()
+	{
+		_log.info("Loaded: " + _quests.size() + " quests");
+	}
+	
+	public final void save()
+	{
+		for (Quest q : _quests.values())
+		{
+			q.saveGlobalData();
+		}
+	}
+	
+	// =========================================================
+	// Property - Public
+	public final Quest getQuest(String name)
+	{
 		return _quests.get(name);
-    }
-
-    public final Quest getQuest(int questId)
-    {
-    	for (Quest q: _quests.values())
-    	{
-    		if (q.getQuestIntId() == questId)
-    			return q;
-    	}
-    	return null;
-    }
-    
-
-    public final void addQuest(Quest newQuest)
-    {
-        if (newQuest == null)
-        {
-            throw new IllegalArgumentException("Quest argument cannot be null");
-        }
-    	Quest old = _quests.get(newQuest.getName());
-        
-        // FIXME: unloading the old quest at this point is a tad too late.
-        // the new quest has already initialized itself and read the data, starting
-        // an unpredictable number of tasks with that data.  The old quest will now
-        // save data which will never be read.
-        // However, requesting the newQuest to re-read the data is not necessarily a 
-        // good option, since the newQuest may have already started timers, spawned NPCs
-        // or taken any other action which it might re-take by re-reading the data. 
-        // the current solution properly closes the running tasks of the old quest but
-        // ignores the data; perhaps the least of all evils...
-        if (old != null)
-        {
-            old.unload();
-            _log.info("Replaced: ("+old.getName()+") with a new version ("+newQuest.getName()+")");
-            
-        }
-        _quests.put(newQuest.getName(), newQuest);
-    }
-    
-    public final boolean removeQuest(Quest q)
-    {
-        return _quests.remove(q.getName()) != null;
-    }
-    
-    /**
-     * @see net.sf.l2j.gameserver.scripting.ScriptManager#getAllManagedScripts()
-     */
-    @Override
-    public Iterable<Quest> getAllManagedScripts()
-    {
-        return _quests.values();
-    }
-
-    /**
-     * @see net.sf.l2j.gameserver.scripting.ScriptManager#unload(net.sf.l2j.gameserver.scripting.ManagedScript)
-     */
-    @Override
-    public boolean unload(Quest ms)
-    {
-        ms.saveGlobalData();
-        return this.removeQuest(ms);
-    }
-
-    /**
-     * @see net.sf.l2j.gameserver.scripting.ScriptManager#getScriptManagerName()
-     */
-    @Override
-    public String getScriptManagerName()
-    {
-        return "QuestManager";
-    }
+	}
+	
+	public final Quest getQuest(int questId)
+	{
+		for (Quest q : _quests.values())
+		{
+			if (q.getQuestIntId() == questId)
+				return q;
+		}
+		return null;
+	}
+	
+	public final void addQuest(Quest newQuest)
+	{
+		if (newQuest == null)
+		{
+			throw new IllegalArgumentException("Quest argument cannot be null");
+		}
+		Quest old = _quests.get(newQuest.getName());
+		
+		// FIXME: unloading the old quest at this point is a tad too late.
+		// the new quest has already initialized itself and read the data, starting
+		// an unpredictable number of tasks with that data.  The old quest will now
+		// save data which will never be read.
+		// However, requesting the newQuest to re-read the data is not necessarily a 
+		// good option, since the newQuest may have already started timers, spawned NPCs
+		// or taken any other action which it might re-take by re-reading the data. 
+		// the current solution properly closes the running tasks of the old quest but
+		// ignores the data; perhaps the least of all evils...
+		if (old != null)
+		{
+			old.unload();
+			_log.info("Replaced: (" + old.getName() + ") with a new version (" + newQuest.getName() + ")");
+			
+		}
+		_quests.put(newQuest.getName(), newQuest);
+	}
+	
+	public final boolean removeQuest(Quest q)
+	{
+		return _quests.remove(q.getName()) != null;
+	}
+	
+	/**
+	 * @see net.sf.l2j.gameserver.scripting.ScriptManager#getAllManagedScripts()
+	 */
+	@Override
+	public Iterable<Quest> getAllManagedScripts()
+	{
+		return _quests.values();
+	}
+	
+	/**
+	 * @see net.sf.l2j.gameserver.scripting.ScriptManager#unload(net.sf.l2j.gameserver.scripting.ManagedScript)
+	 */
+	@Override
+	public boolean unload(Quest ms)
+	{
+		ms.saveGlobalData();
+		return this.removeQuest(ms);
+	}
+	
+	/**
+	 * @see net.sf.l2j.gameserver.scripting.ScriptManager#getScriptManagerName()
+	 */
+	@Override
+	public String getScriptManagerName()
+	{
+		return "QuestManager";
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final QuestManager _instance = new QuestManager();
+	}
 }

+ 499 - 456
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/RaidBossSpawnManager.java

@@ -40,461 +40,504 @@ import net.sf.l2j.gameserver.templates.StatsSet;
 import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
 import net.sf.l2j.util.Rnd;
 
-public class RaidBossSpawnManager {
-
-    private static Logger _log = Logger.getLogger(RaidBossSpawnManager.class.getName());
-
-    private static RaidBossSpawnManager _instance;
-    protected static Map<Integer, L2RaidBossInstance> _bosses;
-    protected static Map<Integer, L2Spawn> _spawns;
-    protected static Map<Integer, StatsSet> _storedInfo;
-    protected static Map<Integer, ScheduledFuture<?>> _schedules;
-
-    public static enum StatusEnum {
-        ALIVE,
-        DEAD,
-        UNDEFINED
-    }
-
-    public RaidBossSpawnManager()
-    {
-        init();
-    }
-
-    public static RaidBossSpawnManager getInstance()
-    {
-        if (_instance == null)
-            _instance = new RaidBossSpawnManager();
-
-        return _instance;
-    }
-
-    private void init()
-    {
-        _bosses = new FastMap<Integer, L2RaidBossInstance>();
-        _schedules = new FastMap<Integer,ScheduledFuture<?>>();
-        _storedInfo = new FastMap<Integer, StatsSet>();
-        _spawns = new FastMap<Integer, L2Spawn>();
-
-        Connection con = null;
-
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-
-            PreparedStatement statement = con.prepareStatement("SELECT * from raidboss_spawnlist ORDER BY boss_id");
-            ResultSet rset = statement.executeQuery();
-
-            L2Spawn spawnDat;
-            L2NpcTemplate template;
-            long respawnTime;
-            while (rset.next())
-            {
-                template = getValidTemplate(rset.getInt("boss_id"));
-                if (template != null)
-                {
-                    spawnDat = new L2Spawn(template);
-                    spawnDat.setLocx(rset.getInt("loc_x"));
-                    spawnDat.setLocy(rset.getInt("loc_y"));
-                    spawnDat.setLocz(rset.getInt("loc_z"));
-                    spawnDat.setAmount(rset.getInt("amount"));
-                    spawnDat.setHeading(rset.getInt("heading"));
-                    spawnDat.setRespawnMinDelay(rset.getInt("respawn_min_delay"));
-                    spawnDat.setRespawnMaxDelay(rset.getInt("respawn_max_delay"));
-                    respawnTime = rset.getLong("respawn_time");
-
-                    addNewSpawn(spawnDat, respawnTime, rset.getDouble("currentHP"), rset.getDouble("currentMP"), false);
-                }
-                else
-                {
-                    _log.warning("RaidBossSpawnManager: Could not load raidboss #" + rset.getInt("boss_id") + " from DB");
-                }
-            }
-
-            _log.info("RaidBossSpawnManager: Loaded " + _bosses.size() + " Instances");
-            _log.info("RaidBossSpawnManager: Scheduled " + _schedules.size() + " Instances");
-
-            rset.close();
-            statement.close();
-        }
-        catch (SQLException e)
-        {
-            _log.warning("RaidBossSpawnManager: Couldnt load raidboss_spawnlist table");
-        }
-        catch (Exception e) {e.printStackTrace();}
-        finally
-        {
-            try {con.close();} catch(Exception e) {e.printStackTrace();}
-        }
-    }
-
-    private class spawnSchedule implements Runnable
-    {
-        private int bossId;
-
-        public spawnSchedule(int npcId)
-        {
-        	bossId = npcId;
-        }
-
-        public void run()
-        {
-            L2RaidBossInstance raidboss = null;
-
-            if (bossId == 25328)
-                raidboss = DayNightSpawnManager.getInstance().handleBoss(_spawns.get(bossId));
-            else
-                raidboss = (L2RaidBossInstance)_spawns.get(bossId).doSpawn();
-
-            if (raidboss != null)
-            {
-                raidboss.setRaidStatus(StatusEnum.ALIVE);
-
-                StatsSet info = new StatsSet();
-                info.set("currentHP", raidboss.getCurrentHp());
-                info.set("currentMP", raidboss.getCurrentMp());
-                info.set("respawnTime", 0L);
-
-                _storedInfo.put(bossId, info);
-
-                GmListTable.broadcastMessageToGMs("Spawning Raid Boss " + raidboss.getName());
-
-                _bosses.put(bossId, raidboss);
-            }
-
-            _schedules.remove(bossId);
-        }
-    }
-
-    public void updateStatus(L2RaidBossInstance boss, boolean isBossDead)
-    {
-        if (!_storedInfo.containsKey(boss.getNpcId()))
-            return;
-
-        StatsSet info = _storedInfo.get(boss.getNpcId());
-
-        if (isBossDead)
-        {
-            boss.setRaidStatus(StatusEnum.DEAD);
-
-            long respawnTime;
-            int RespawnMinDelay = boss.getSpawn().getRespawnMinDelay();
-            int RespawnMaxDelay = boss.getSpawn().getRespawnMaxDelay();
-            long respawn_delay = Rnd.get((int)(RespawnMinDelay*1000*Config.RAID_MIN_RESPAWN_MULTIPLIER),(int)(RespawnMaxDelay*1000*Config.RAID_MAX_RESPAWN_MULTIPLIER));
-            respawnTime = Calendar.getInstance().getTimeInMillis() + respawn_delay;
-
-            info.set("currentHP", boss.getMaxHp());
-            info.set("currentMP", boss.getMaxMp());
-            info.set("respawnTime", respawnTime);
-
-            _log.info("RaidBossSpawnManager: Updated " + boss.getName() + " respawn time to " + respawnTime);
-
-            if (!_schedules.containsKey(boss.getNpcId()))
-            {
-	            ScheduledFuture<?> futureSpawn;
-	            futureSpawn = ThreadPoolManager.getInstance().scheduleGeneral(new spawnSchedule(boss.getNpcId()), respawn_delay);
+public class RaidBossSpawnManager
+{
 	
-	            _schedules.put(boss.getNpcId(), futureSpawn);
-	            //To update immediately Database uncomment on the following line, to post the hour of respawn raid boss on your site for example or to envisage a crash landing of the waiter.
-	            updateDb();
-            }
-        }
-        else
-        {
-            boss.setRaidStatus(StatusEnum.ALIVE);
-
-            info.set("currentHP", boss.getCurrentHp());
-            info.set("currentMP", boss.getCurrentMp());
-            info.set("respawnTime", 0L);
-        }
-
-        _storedInfo.remove(boss.getNpcId());
-        _storedInfo.put(boss.getNpcId(), info);
-    }
-
-    public void addNewSpawn(L2Spawn spawnDat, long respawnTime, double currentHP, double currentMP, boolean storeInDb)
-    {
-    	if (spawnDat == null) return;
-    	if (_spawns.containsKey(spawnDat.getNpcid())) return;
-
-    	int bossId = spawnDat.getNpcid();
-    	long time = Calendar.getInstance().getTimeInMillis();
-
-        SpawnTable.getInstance().addNewSpawn(spawnDat, false);
-
-        if (respawnTime == 0L || (time > respawnTime))
-        {
-            L2RaidBossInstance raidboss = null;
-
-            if (bossId == 25328)
-                raidboss = DayNightSpawnManager.getInstance().handleBoss(spawnDat);
-            else
-                raidboss = (L2RaidBossInstance)spawnDat.doSpawn();
-
-            if (raidboss != null)
-            {
-                raidboss.setCurrentHp(currentHP);
-                raidboss.setCurrentMp(currentMP);
-                raidboss.setRaidStatus(StatusEnum.ALIVE);
-
-                _bosses.put(bossId, raidboss);
-
-                StatsSet info = new StatsSet();
-                info.set("currentHP", currentHP);
-                info.set("currentMP", currentMP);
-                info.set("respawnTime", 0L);
-
-                _storedInfo.put(bossId, info);
-            }
-        }
-        else
-        {
-            ScheduledFuture<?> futureSpawn;
-            long spawnTime = respawnTime - Calendar.getInstance().getTimeInMillis();
-
-            futureSpawn = ThreadPoolManager.getInstance().scheduleGeneral(new spawnSchedule(bossId), spawnTime);
-
-            _schedules.put(bossId, futureSpawn);
-        }
-
-        _spawns.put(bossId, spawnDat);
-
-        if (storeInDb)
-        {
-            Connection con = null;
-
-            try
-            {
-                con = L2DatabaseFactory.getInstance().getConnection();
-                PreparedStatement statement = con.prepareStatement("INSERT INTO raidboss_spawnlist (boss_id,amount,loc_x,loc_y,loc_z,heading,respawn_time,currentHp,currentMp) values(?,?,?,?,?,?,?,?,?)");
-                statement.setInt(1, spawnDat.getNpcid());
-                statement.setInt(2, spawnDat.getAmount());
-                statement.setInt(3, spawnDat.getLocx());
-                statement.setInt(4, spawnDat.getLocy());
-                statement.setInt(5, spawnDat.getLocz());
-                statement.setInt(6, spawnDat.getHeading());
-                statement.setLong(7, respawnTime);
-                statement.setDouble(8, currentHP);
-                statement.setDouble(9, currentMP);
-                statement.execute();
-                statement.close();
-            }
-            catch (Exception e)
-            {
-                // problem with storing spawn
-                _log.warning("RaidBossSpawnManager: Could not store raidboss #" + bossId + " in the DB:" + e);
-            }
-            finally
-            {
-                try { con.close(); } catch (Exception e) {}
-            }
-        }
-    }
-
-    public void deleteSpawn(L2Spawn spawnDat, boolean updateDb)
-    {
-    	if (spawnDat == null) return;
-    	if (!_spawns.containsKey(spawnDat.getNpcid())) return;
-
-    	int bossId = spawnDat.getNpcid();
-
-    	SpawnTable.getInstance().deleteSpawn(spawnDat, false);
-        _spawns.remove(bossId);
-
-        if (_bosses.containsKey(bossId))
-        	_bosses.remove(bossId);
-
-        if (_schedules.containsKey(bossId))
-        {
-           	ScheduledFuture<?> f = _schedules.get(bossId);
-           	f.cancel(true);
-           	_schedules.remove(bossId);
-        }
-
-        if (_storedInfo.containsKey(bossId))
-        	_storedInfo.remove(bossId);
-
-        if (updateDb)
-        {
-            Connection con = null;
-
-            try
-            {
-                con = L2DatabaseFactory.getInstance().getConnection();
-                PreparedStatement statement = con.prepareStatement("DELETE FROM raidboss_spawnlist WHERE boss_id=?");
-                statement.setInt(1, bossId);
-                statement.execute();
-                statement.close();
-            }
-            catch (Exception e)
-            {
-                // problem with deleting spawn
-                _log.warning("RaidBossSpawnManager: Could not remove raidboss #" + bossId + " from DB: " + e);
-            }
-            finally
-            {
-                try { con.close(); } catch (Exception e) {}
-            }
-        }
-    }
-
-    private void updateDb()
-    {
-        for (Integer bossId : _storedInfo.keySet())
-        {
-            Connection con = null;
-
-            try
-            {
-                con = L2DatabaseFactory.getInstance().getConnection();
-
-                L2RaidBossInstance boss = _bosses.get(bossId);
-
-                if (boss == null) continue;
-
-                if (boss.getRaidStatus().equals(StatusEnum.ALIVE))
-                    updateStatus(boss, false);
-
-                StatsSet info = _storedInfo.get(bossId);
-
-                if (info == null) continue;
-
-                PreparedStatement statement = con.prepareStatement("UPDATE raidboss_spawnlist set respawn_time = ?, currentHP = ?, currentMP = ? where boss_id = ?");
-                statement.setLong(1, info.getLong("respawnTime"));
-                statement.setDouble(2, info.getDouble("currentHP"));
-                statement.setDouble(3, info.getDouble("currentMP"));
-                statement.setInt(4, bossId);
-                statement.execute();
-
-                statement.close();
-            }
-            catch (SQLException e){ _log.warning("RaidBossSpawnManager: Couldnt update raidboss_spawnlist table");}
-            finally
-            {
-                try {con.close();} catch(Exception e) {e.printStackTrace();}
-            }
-        }
-    }
-
-    public String[] getAllRaidBossStatus()
-    {
-        String[] msg = new String[_bosses == null ? 0 : _bosses.size()];
-
-        if (_bosses == null)
-        {
-            msg[0] = "None";
-            return msg;
-        }
-
-        int index = 0;
-
-        for (int i : _bosses.keySet())
-        {
-            L2RaidBossInstance boss = _bosses.get(i);
-
-            msg[index++] = boss.getName() + ": " + boss.getRaidStatus().name();
-        }
-
-        return msg;
-    }
-
-    public String getRaidBossStatus(int bossId)
-    {
-        String msg = "RaidBoss Status....\n";
-
-        if (_bosses == null)
-        {
-            msg += "None";
-            return msg;
-        }
-
-        if (_bosses.containsKey(bossId))
-        {
-            L2RaidBossInstance boss = _bosses.get(bossId);
-
-            msg += boss.getName() + ": " + boss.getRaidStatus().name();
-        }
-
-        return msg;
-    }
-
-    public StatusEnum getRaidBossStatusId(int bossId)
-    {
-        if (_bosses.containsKey(bossId))
-        	return _bosses.get(bossId).getRaidStatus();
-        else
-        	if (_schedules.containsKey(bossId))
-        		return StatusEnum.DEAD;
-            else
-        		return StatusEnum.UNDEFINED;
-    }
-
-    public L2NpcTemplate getValidTemplate(int bossId)
-    {
-        L2NpcTemplate template = NpcTable.getInstance().getTemplate(bossId);
-        if (template == null) return null;
-        if (!template.type.equalsIgnoreCase("L2RaidBoss")) return null;
-        return template;
-    }
-
-    public void notifySpawnNightBoss(L2RaidBossInstance raidboss)
-    {
-        StatsSet info = new StatsSet();
-        info.set("currentHP", raidboss.getCurrentHp());
-        info.set("currentMP", raidboss.getCurrentMp());
-        info.set("respawnTime", 0L);
-
-        raidboss.setRaidStatus(StatusEnum.ALIVE);
-
-        _storedInfo.put(raidboss.getNpcId(), info);
-
-        GmListTable.broadcastMessageToGMs("Spawning Raid Boss " + raidboss.getName());
-
-        _bosses.put(raidboss.getNpcId(), raidboss);
-    }
-
-    public boolean isDefined(int bossId)
-    {
-    	return _spawns.containsKey(bossId);
-    }
-
-    public Map<Integer, L2RaidBossInstance> getBosses()
-    {
-        return _bosses;
-    }
-
-    public Map<Integer, L2Spawn> getSpawns()
-    {
-        return _spawns;
-    }
-
-    public void reloadBosses()
-    {
-        init();
-    }
-
-    /**
-     * Saves all raidboss status and then clears all info from memory,
-     * including all schedules.
-     */
-
-    public void cleanUp()
-    {
-        updateDb();
-
-        _bosses.clear();
-
-        if (_schedules != null)
-        {
-            for (Integer bossId : _schedules.keySet())
-            {
-            	ScheduledFuture<?> f = _schedules.get(bossId);
-                f.cancel(true);
-            }
-        }
-
-        _schedules.clear();
-        _storedInfo.clear();
-        _spawns.clear();
-    }
+	private static Logger _log = Logger.getLogger(RaidBossSpawnManager.class.getName());
+	
+	protected static Map<Integer, L2RaidBossInstance> _bosses;
+	protected static Map<Integer, L2Spawn> _spawns;
+	protected static Map<Integer, StatsSet> _storedInfo;
+	protected static Map<Integer, ScheduledFuture<?>> _schedules;
+	
+	public static enum StatusEnum
+	{
+		ALIVE,
+		DEAD,
+		UNDEFINED
+	}
+	
+	private RaidBossSpawnManager()
+	{
+		init();
+	}
+	
+	public static RaidBossSpawnManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private void init()
+	{
+		_bosses = new FastMap<Integer, L2RaidBossInstance>();
+		_schedules = new FastMap<Integer, ScheduledFuture<?>>();
+		_storedInfo = new FastMap<Integer, StatsSet>();
+		_spawns = new FastMap<Integer, L2Spawn>();
+		
+		Connection con = null;
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			PreparedStatement statement = con.prepareStatement("SELECT * from raidboss_spawnlist ORDER BY boss_id");
+			ResultSet rset = statement.executeQuery();
+			
+			L2Spawn spawnDat;
+			L2NpcTemplate template;
+			long respawnTime;
+			while (rset.next())
+			{
+				template = getValidTemplate(rset.getInt("boss_id"));
+				if (template != null)
+				{
+					spawnDat = new L2Spawn(template);
+					spawnDat.setLocx(rset.getInt("loc_x"));
+					spawnDat.setLocy(rset.getInt("loc_y"));
+					spawnDat.setLocz(rset.getInt("loc_z"));
+					spawnDat.setAmount(rset.getInt("amount"));
+					spawnDat.setHeading(rset.getInt("heading"));
+					spawnDat.setRespawnMinDelay(rset.getInt("respawn_min_delay"));
+					spawnDat.setRespawnMaxDelay(rset.getInt("respawn_max_delay"));
+					respawnTime = rset.getLong("respawn_time");
+					
+					addNewSpawn(spawnDat, respawnTime, rset.getDouble("currentHP"), rset.getDouble("currentMP"), false);
+				}
+				else
+				{
+					_log.warning("RaidBossSpawnManager: Could not load raidboss #" + rset.getInt("boss_id") + " from DB");
+				}
+			}
+			
+			_log.info("RaidBossSpawnManager: Loaded " + _bosses.size() + " Instances");
+			_log.info("RaidBossSpawnManager: Scheduled " + _schedules.size() + " Instances");
+			
+			rset.close();
+			statement.close();
+		}
+		catch (SQLException e)
+		{
+			_log.warning("RaidBossSpawnManager: Couldnt load raidboss_spawnlist table");
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	private class spawnSchedule implements Runnable
+	{
+		private int bossId;
+		
+		public spawnSchedule(int npcId)
+		{
+			bossId = npcId;
+		}
+		
+		public void run()
+		{
+			L2RaidBossInstance raidboss = null;
+			
+			if (bossId == 25328)
+				raidboss = DayNightSpawnManager.getInstance().handleBoss(_spawns.get(bossId));
+			else
+				raidboss = (L2RaidBossInstance) _spawns.get(bossId).doSpawn();
+			
+			if (raidboss != null)
+			{
+				raidboss.setRaidStatus(StatusEnum.ALIVE);
+				
+				StatsSet info = new StatsSet();
+				info.set("currentHP", raidboss.getCurrentHp());
+				info.set("currentMP", raidboss.getCurrentMp());
+				info.set("respawnTime", 0L);
+				
+				_storedInfo.put(bossId, info);
+				
+				GmListTable.broadcastMessageToGMs("Spawning Raid Boss " + raidboss.getName());
+				
+				_bosses.put(bossId, raidboss);
+			}
+			
+			_schedules.remove(bossId);
+		}
+	}
+	
+	public void updateStatus(L2RaidBossInstance boss, boolean isBossDead)
+	{
+		if (!_storedInfo.containsKey(boss.getNpcId()))
+			return;
+		
+		StatsSet info = _storedInfo.get(boss.getNpcId());
+		
+		if (isBossDead)
+		{
+			boss.setRaidStatus(StatusEnum.DEAD);
+			
+			long respawnTime;
+			int RespawnMinDelay = boss.getSpawn().getRespawnMinDelay();
+			int RespawnMaxDelay = boss.getSpawn().getRespawnMaxDelay();
+			long respawn_delay = Rnd.get((int) (RespawnMinDelay * 1000 * Config.RAID_MIN_RESPAWN_MULTIPLIER), (int) (RespawnMaxDelay * 1000 * Config.RAID_MAX_RESPAWN_MULTIPLIER));
+			respawnTime = Calendar.getInstance().getTimeInMillis() + respawn_delay;
+			
+			info.set("currentHP", boss.getMaxHp());
+			info.set("currentMP", boss.getMaxMp());
+			info.set("respawnTime", respawnTime);
+			
+			_log.info("RaidBossSpawnManager: Updated " + boss.getName() + " respawn time to " + respawnTime);
+			
+			if (!_schedules.containsKey(boss.getNpcId()))
+			{
+				ScheduledFuture<?> futureSpawn;
+				futureSpawn = ThreadPoolManager.getInstance().scheduleGeneral(new spawnSchedule(boss.getNpcId()), respawn_delay);
+				
+				_schedules.put(boss.getNpcId(), futureSpawn);
+				//To update immediately Database uncomment on the following line, to post the hour of respawn raid boss on your site for example or to envisage a crash landing of the waiter.
+				updateDb();
+			}
+		}
+		else
+		{
+			boss.setRaidStatus(StatusEnum.ALIVE);
+			
+			info.set("currentHP", boss.getCurrentHp());
+			info.set("currentMP", boss.getCurrentMp());
+			info.set("respawnTime", 0L);
+		}
+		
+		_storedInfo.remove(boss.getNpcId());
+		_storedInfo.put(boss.getNpcId(), info);
+	}
+	
+	public void addNewSpawn(L2Spawn spawnDat, long respawnTime, double currentHP, double currentMP, boolean storeInDb)
+	{
+		if (spawnDat == null)
+			return;
+		if (_spawns.containsKey(spawnDat.getNpcid()))
+			return;
+		
+		int bossId = spawnDat.getNpcid();
+		long time = Calendar.getInstance().getTimeInMillis();
+		
+		SpawnTable.getInstance().addNewSpawn(spawnDat, false);
+		
+		if (respawnTime == 0L || (time > respawnTime))
+		{
+			L2RaidBossInstance raidboss = null;
+			
+			if (bossId == 25328)
+				raidboss = DayNightSpawnManager.getInstance().handleBoss(spawnDat);
+			else
+				raidboss = (L2RaidBossInstance) spawnDat.doSpawn();
+			
+			if (raidboss != null)
+			{
+				raidboss.setCurrentHp(currentHP);
+				raidboss.setCurrentMp(currentMP);
+				raidboss.setRaidStatus(StatusEnum.ALIVE);
+				
+				_bosses.put(bossId, raidboss);
+				
+				StatsSet info = new StatsSet();
+				info.set("currentHP", currentHP);
+				info.set("currentMP", currentMP);
+				info.set("respawnTime", 0L);
+				
+				_storedInfo.put(bossId, info);
+			}
+		}
+		else
+		{
+			ScheduledFuture<?> futureSpawn;
+			long spawnTime = respawnTime - Calendar.getInstance().getTimeInMillis();
+			
+			futureSpawn = ThreadPoolManager.getInstance().scheduleGeneral(new spawnSchedule(bossId), spawnTime);
+			
+			_schedules.put(bossId, futureSpawn);
+		}
+		
+		_spawns.put(bossId, spawnDat);
+		
+		if (storeInDb)
+		{
+			Connection con = null;
+			
+			try
+			{
+				con = L2DatabaseFactory.getInstance().getConnection();
+				PreparedStatement statement = con.prepareStatement("INSERT INTO raidboss_spawnlist (boss_id,amount,loc_x,loc_y,loc_z,heading,respawn_time,currentHp,currentMp) values(?,?,?,?,?,?,?,?,?)");
+				statement.setInt(1, spawnDat.getNpcid());
+				statement.setInt(2, spawnDat.getAmount());
+				statement.setInt(3, spawnDat.getLocx());
+				statement.setInt(4, spawnDat.getLocy());
+				statement.setInt(5, spawnDat.getLocz());
+				statement.setInt(6, spawnDat.getHeading());
+				statement.setLong(7, respawnTime);
+				statement.setDouble(8, currentHP);
+				statement.setDouble(9, currentMP);
+				statement.execute();
+				statement.close();
+			}
+			catch (Exception e)
+			{
+				// problem with storing spawn
+				_log.warning("RaidBossSpawnManager: Could not store raidboss #" + bossId + " in the DB:" + e);
+			}
+			finally
+			{
+				try
+				{
+					con.close();
+				}
+				catch (Exception e)
+				{
+				}
+			}
+		}
+	}
+	
+	public void deleteSpawn(L2Spawn spawnDat, boolean updateDb)
+	{
+		if (spawnDat == null)
+			return;
+		if (!_spawns.containsKey(spawnDat.getNpcid()))
+			return;
+		
+		int bossId = spawnDat.getNpcid();
+		
+		SpawnTable.getInstance().deleteSpawn(spawnDat, false);
+		_spawns.remove(bossId);
+		
+		if (_bosses.containsKey(bossId))
+			_bosses.remove(bossId);
+		
+		if (_schedules.containsKey(bossId))
+		{
+			ScheduledFuture<?> f = _schedules.get(bossId);
+			f.cancel(true);
+			_schedules.remove(bossId);
+		}
+		
+		if (_storedInfo.containsKey(bossId))
+			_storedInfo.remove(bossId);
+		
+		if (updateDb)
+		{
+			Connection con = null;
+			
+			try
+			{
+				con = L2DatabaseFactory.getInstance().getConnection();
+				PreparedStatement statement = con.prepareStatement("DELETE FROM raidboss_spawnlist WHERE boss_id=?");
+				statement.setInt(1, bossId);
+				statement.execute();
+				statement.close();
+			}
+			catch (Exception e)
+			{
+				// problem with deleting spawn
+				_log.warning("RaidBossSpawnManager: Could not remove raidboss #" + bossId + " from DB: " + e);
+			}
+			finally
+			{
+				try
+				{
+					con.close();
+				}
+				catch (Exception e)
+				{
+				}
+			}
+		}
+	}
+	
+	private void updateDb()
+	{
+		for (Integer bossId : _storedInfo.keySet())
+		{
+			Connection con = null;
+			
+			try
+			{
+				con = L2DatabaseFactory.getInstance().getConnection();
+				
+				L2RaidBossInstance boss = _bosses.get(bossId);
+				
+				if (boss == null)
+					continue;
+				
+				if (boss.getRaidStatus().equals(StatusEnum.ALIVE))
+					updateStatus(boss, false);
+				
+				StatsSet info = _storedInfo.get(bossId);
+				
+				if (info == null)
+					continue;
+				
+				PreparedStatement statement = con.prepareStatement("UPDATE raidboss_spawnlist set respawn_time = ?, currentHP = ?, currentMP = ? where boss_id = ?");
+				statement.setLong(1, info.getLong("respawnTime"));
+				statement.setDouble(2, info.getDouble("currentHP"));
+				statement.setDouble(3, info.getDouble("currentMP"));
+				statement.setInt(4, bossId);
+				statement.execute();
+				
+				statement.close();
+			}
+			catch (SQLException e)
+			{
+				_log.warning("RaidBossSpawnManager: Couldnt update raidboss_spawnlist table");
+			}
+			finally
+			{
+				try
+				{
+					con.close();
+				}
+				catch (Exception e)
+				{
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+	
+	public String[] getAllRaidBossStatus()
+	{
+		String[] msg = new String[_bosses == null ? 0 : _bosses.size()];
+		
+		if (_bosses == null)
+		{
+			msg[0] = "None";
+			return msg;
+		}
+		
+		int index = 0;
+		
+		for (int i : _bosses.keySet())
+		{
+			L2RaidBossInstance boss = _bosses.get(i);
+			
+			msg[index++] = boss.getName() + ": " + boss.getRaidStatus().name();
+		}
+		
+		return msg;
+	}
+	
+	public String getRaidBossStatus(int bossId)
+	{
+		String msg = "RaidBoss Status....\n";
+		
+		if (_bosses == null)
+		{
+			msg += "None";
+			return msg;
+		}
+		
+		if (_bosses.containsKey(bossId))
+		{
+			L2RaidBossInstance boss = _bosses.get(bossId);
+			
+			msg += boss.getName() + ": " + boss.getRaidStatus().name();
+		}
+		
+		return msg;
+	}
+	
+	public StatusEnum getRaidBossStatusId(int bossId)
+	{
+		if (_bosses.containsKey(bossId))
+			return _bosses.get(bossId).getRaidStatus();
+		else if (_schedules.containsKey(bossId))
+			return StatusEnum.DEAD;
+		else
+			return StatusEnum.UNDEFINED;
+	}
+	
+	public L2NpcTemplate getValidTemplate(int bossId)
+	{
+		L2NpcTemplate template = NpcTable.getInstance().getTemplate(bossId);
+		if (template == null)
+			return null;
+		if (!template.type.equalsIgnoreCase("L2RaidBoss"))
+			return null;
+		return template;
+	}
+	
+	public void notifySpawnNightBoss(L2RaidBossInstance raidboss)
+	{
+		StatsSet info = new StatsSet();
+		info.set("currentHP", raidboss.getCurrentHp());
+		info.set("currentMP", raidboss.getCurrentMp());
+		info.set("respawnTime", 0L);
+		
+		raidboss.setRaidStatus(StatusEnum.ALIVE);
+		
+		_storedInfo.put(raidboss.getNpcId(), info);
+		
+		GmListTable.broadcastMessageToGMs("Spawning Raid Boss " + raidboss.getName());
+		
+		_bosses.put(raidboss.getNpcId(), raidboss);
+	}
+	
+	public boolean isDefined(int bossId)
+	{
+		return _spawns.containsKey(bossId);
+	}
+	
+	public Map<Integer, L2RaidBossInstance> getBosses()
+	{
+		return _bosses;
+	}
+	
+	public Map<Integer, L2Spawn> getSpawns()
+	{
+		return _spawns;
+	}
+	
+	public void reloadBosses()
+	{
+		init();
+	}
+	
+	/**
+	 * Saves all raidboss status and then clears all info from memory,
+	 * including all schedules.
+	 */
+	
+	public void cleanUp()
+	{
+		updateDb();
+		
+		_bosses.clear();
+		
+		if (_schedules != null)
+		{
+			for (Integer bossId : _schedules.keySet())
+			{
+				ScheduledFuture<?> f = _schedules.get(bossId);
+				f.cancel(true);
+			}
+		}
+		
+		_schedules.clear();
+		_storedInfo.clear();
+		_spawns.clear();
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final RaidBossSpawnManager _instance = new RaidBossSpawnManager();
+	}
 }

+ 351 - 316
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/SiegeManager.java

@@ -38,322 +38,357 @@ import net.sf.l2j.gameserver.model.actor.L2Character;
 import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
 import net.sf.l2j.gameserver.model.entity.Castle;
 import net.sf.l2j.gameserver.model.entity.Siege;
+
 public class SiegeManager
 {
-    private static final Logger _log = Logger.getLogger(SiegeManager.class.getName());
-
-    // =========================================================
-    private static SiegeManager _instance;
-    public static final SiegeManager getInstance()
-    {
-        if (_instance == null)
-        {
-    		_log.info("Initializing SiegeManager");
-        	_instance = new SiegeManager();
-        	_instance.load();
-        }
-        return _instance;
-    }
-
-    // =========================================================
-    // Data Field
-    private int _attackerMaxClans                              = 500; // Max number of clans
-    private int _attackerRespawnDelay                          = 0; // Time in ms. Changeable in siege.config
-    private int _defenderMaxClans                              = 500; // Max number of clans
-
-    // Siege settings
-    private FastMap<Integer,FastList<SiegeSpawn>>  _artefactSpawnList;
-    private FastMap<Integer,FastList<SiegeSpawn>>  _controlTowerSpawnList;
-
-    private int _flagMaxCount                                   = 1; // Changeable in siege.config
-    private int _siegeClanMinLevel                             = 5; // Changeable in siege.config
-    private int _siegeLength                                    = 120; // Time in minute. Changeable in siege.config
-
-    // =========================================================
-    // Constructor
-    private SiegeManager()
-    {
-    }
-
-    // =========================================================
-    // Method - Public
-    public final void addSiegeSkills(L2PcInstance character)
-    {
-    	for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(character.isNoble()))
-    	{
-    		character.addSkill(sk, false);
-    	}
-    }
-
-    /**
-     * Return true if character summon<BR><BR>
-     * @param activeChar The L2Character of the character can summon
-     */
-    public final boolean checkIfOkToSummon(L2Character activeChar, boolean isCheckOnly)
-    {
-        if (!(activeChar instanceof L2PcInstance)) return false;
-
-        String text = "";
-        L2PcInstance player = (L2PcInstance)activeChar;
-        Castle castle = CastleManager.getInstance().getCastle(player);
-
-        if (castle == null || castle.getCastleId() <= 0)
-            text = "You must be on castle ground to summon this";
-        else if (!castle.getSiege().getIsInProgress())
-            text = "You can only summon this during a siege.";
-        else if (player.getClanId() != 0 && castle.getSiege().getAttackerClan(player.getClanId()) == null)
-            text = "You can only summon this as a registered attacker.";
-        else
-            return true;
-
-        if (!isCheckOnly)
-            player.sendMessage(text);
-        return false;
-    }
-
-    /**
-     * Return true if the clan is registered or owner of a castle<BR><BR>
-     * @param clan The L2Clan of the player
-     */
-    public final boolean checkIsRegistered(L2Clan clan, int castleid)
-    {
-        if (clan == null) return false;
-
-        if (clan.getHasCastle() > 0) return true;
-
-        Connection con = null;
-        boolean register = false;
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-            PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM siege_clans where clan_id=? and castle_id=?");
-            statement.setInt(1, clan.getClanId());
-            statement.setInt(2, castleid);
-            ResultSet rs = statement.executeQuery();
-
-            while (rs.next())
-            {
-                register = true;
-                break;
-            }
-
-            rs.close();
-            statement.close();
-        }
-        catch (Exception e)
-        {
-            _log.warning("Exception: checkIsRegistered(): " + e.getMessage());
-            e.printStackTrace();
-        }
-        finally
-        {
-            try { con.close(); } catch (Exception e) {}
-        }
-        return register;
-    }
-
-    public final void removeSiegeSkills(L2PcInstance character)
-    {
-    	for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(character.isNoble()))
-    	{
-    		character.removeSkill(sk);
-    	}
-    }
-
-    // =========================================================
-    // Method - Private
-    private final void load()
-    {
-    	InputStream is = null;
-        try {
-            is = new FileInputStream(new File(Config.SIEGE_CONFIGURATION_FILE));
-            Properties siegeSettings = new Properties();
-            siegeSettings.load(is);
-
-            // Siege setting
-            _attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
-            _attackerRespawnDelay = Integer.decode(siegeSettings.getProperty("AttackerRespawn", "0"));
-            _defenderMaxClans = Integer.decode(siegeSettings.getProperty("DefenderMaxClans", "500"));
-            _flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
-            _siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "5"));
-            _siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "120"));
-
-            // Siege spawns settings
-            _controlTowerSpawnList = new FastMap<Integer,FastList<SiegeSpawn>>();
-            _artefactSpawnList = new FastMap<Integer,FastList<SiegeSpawn>>();
-
-            for (Castle castle: CastleManager.getInstance().getCastles())
-            {
-            	FastList<SiegeSpawn> _controlTowersSpawns = new FastList<SiegeSpawn>();
-
-            	for (int i=1; i<0xFF; i++)
-            	{
-            		String _spawnParams = siegeSettings.getProperty(castle.getName() + "ControlTower" + Integer.toString(i), "");
-
-            		if (_spawnParams.length() == 0) break;
-
-            		StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
-
-            		try
-            		{
-            			int x = Integer.parseInt(st.nextToken());
-            			int y = Integer.parseInt(st.nextToken());
-            			int z = Integer.parseInt(st.nextToken());
-            			int npc_id = Integer.parseInt(st.nextToken());
-            			int hp = Integer.parseInt(st.nextToken());
-
-            			_controlTowersSpawns.add(new SiegeSpawn(castle.getCastleId(),x,y,z,0,npc_id,hp));
-            		}
-            		catch (Exception e)
-            		{
-            			_log.warning("Error while loading control tower(s) for "+castle.getName()+" castle.");
-            		}
-            	}
-
-            	FastList<SiegeSpawn> _artefactSpawns = new FastList<SiegeSpawn>();
-
-            	for (int i=1; i<0xFF; i++)
-            	{
-            		String _spawnParams = siegeSettings.getProperty(castle.getName() + "Artefact" + Integer.toString(i), "");
-
-            		if (_spawnParams.length() == 0) break;
-
-            		StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
-
-            		try
-            		{
-            			int x = Integer.parseInt(st.nextToken());
-            			int y = Integer.parseInt(st.nextToken());
-            			int z = Integer.parseInt(st.nextToken());
-            			int heading = Integer.parseInt(st.nextToken());
-            			int npc_id = Integer.parseInt(st.nextToken());
-
-            			_artefactSpawns.add(new SiegeSpawn(castle.getCastleId(),x,y,z,heading,npc_id));
-            		}
-            		catch (Exception e)
-            		{
-            			_log.warning("Error while loading artefact(s) for "+castle.getName()+" castle.");
-            		}
-            	}
-
-            	_controlTowerSpawnList.put(castle.getCastleId(), _controlTowersSpawns);
-            	_artefactSpawnList.put(castle.getCastleId(), _artefactSpawns);
-            }
-
-        }
-        catch (Exception e)
-        {
-            //_initialized = false;
-            _log.warning("Error while loading siege data.");
-            e.printStackTrace();
-        }
-        finally
-        {
-        	try
-        	{
-                is.close();
-        	}
-        	catch (Exception e)
-        	{	
-        	}
-        }
-    }
-
-    // =========================================================
-    // Property - Public
-    public final FastList<SiegeSpawn> getArtefactSpawnList(int _castleId)
-    {
-    	if (_artefactSpawnList.containsKey(_castleId))
-    		return _artefactSpawnList.get(_castleId);
-    	else
-    		return null;
-    }
-
-    public final FastList<SiegeSpawn> getControlTowerSpawnList(int _castleId)
-    {
-    	if (_controlTowerSpawnList.containsKey(_castleId))
-    		return _controlTowerSpawnList.get(_castleId);
-    	else
-    		return null;
-    }
-
-    public final int getAttackerMaxClans() { return _attackerMaxClans; }
-
-    public final int getAttackerRespawnDelay() { return _attackerRespawnDelay; }
-
-    public final int getDefenderMaxClans() { return _defenderMaxClans; }
-
-    public final int getFlagMaxCount() { return _flagMaxCount; }
-
-    public final Siege getSiege(L2Object activeObject) { return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ()); }
-
-    public final Siege getSiege(int x, int y, int z)
-    {
-        for (Castle castle: CastleManager.getInstance().getCastles())
-            if (castle.getSiege().checkIfInZone(x, y, z)) return castle.getSiege();
-        return null;
-    }
-
-    public final int getSiegeClanMinLevel() { return _siegeClanMinLevel; }
-
-    public final int getSiegeLength() { return _siegeLength; }
-
-    public final List<Siege> getSieges()
-    {
-        FastList<Siege> sieges = new FastList<Siege>();
-        for (Castle castle: CastleManager.getInstance().getCastles())
-        	sieges.add(castle.getSiege());
-        return sieges;
-    }
-
-    public class  SiegeSpawn
-    {
-    	Location _location;
-    	private int _npcId;
-    	private int _heading;
-    	private int _castleId;
-    	private int _hp;
-
-    	public SiegeSpawn(int castle_id, int x, int y, int z, int heading, int npc_id)
-    	{
-    		_castleId = castle_id;
-    		_location = new Location(x,y,z,heading);
-    		_heading = heading;
-    		_npcId = npc_id;
-    	}
-
-    	public SiegeSpawn(int castle_id, int x, int y, int z, int heading, int npc_id, int hp)
-    	{
-    		_castleId = castle_id;
-    		_location = new Location(x,y,z,heading);
-    		_heading = heading;
-    		_npcId = npc_id;
-    		_hp = hp;
-    	}
-
-    	public int getCastleId()
-    	{
-    		return _castleId;
-    	}
-
-    	public int getNpcId()
-    	{
-    		return _npcId;
-    	}
-
-    	public int getHeading()
-    	{
-    		return _heading;
-    	}
-
-    	public int getHp()
-    	{
-    		return _hp;
-    	}
-
-    	public Location getLocation()
-    	{
-    		return _location;
-    	}
-    }
+	private static final Logger _log = Logger.getLogger(SiegeManager.class.getName());
+	
+	public static final SiegeManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	// =========================================================
+	// Data Field
+	private int _attackerMaxClans = 500; // Max number of clans
+	private int _attackerRespawnDelay = 0; // Time in ms. Changeable in siege.config
+	private int _defenderMaxClans = 500; // Max number of clans
+	
+	// Siege settings
+	private FastMap<Integer, FastList<SiegeSpawn>> _artefactSpawnList;
+	private FastMap<Integer, FastList<SiegeSpawn>> _controlTowerSpawnList;
+	
+	private int _flagMaxCount = 1; // Changeable in siege.config
+	private int _siegeClanMinLevel = 5; // Changeable in siege.config
+	private int _siegeLength = 120; // Time in minute. Changeable in siege.config
+	
+	// =========================================================
+	// Constructor
+	private SiegeManager()
+	{
+		_log.info("Initializing SiegeManager");
+		load();
+	}
+	
+	// =========================================================
+	// Method - Public
+	public final void addSiegeSkills(L2PcInstance character)
+	{
+		for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(character.isNoble()))
+		{
+			character.addSkill(sk, false);
+		}
+	}
+	
+	/**
+	 * Return true if character summon<BR><BR>
+	 * @param activeChar The L2Character of the character can summon
+	 */
+	public final boolean checkIfOkToSummon(L2Character activeChar, boolean isCheckOnly)
+	{
+		if (!(activeChar instanceof L2PcInstance))
+			return false;
+		
+		String text = "";
+		L2PcInstance player = (L2PcInstance) activeChar;
+		Castle castle = CastleManager.getInstance().getCastle(player);
+		
+		if (castle == null || castle.getCastleId() <= 0)
+			text = "You must be on castle ground to summon this";
+		else if (!castle.getSiege().getIsInProgress())
+			text = "You can only summon this during a siege.";
+		else if (player.getClanId() != 0 && castle.getSiege().getAttackerClan(player.getClanId()) == null)
+			text = "You can only summon this as a registered attacker.";
+		else
+			return true;
+		
+		if (!isCheckOnly)
+			player.sendMessage(text);
+		return false;
+	}
+	
+	/**
+	 * Return true if the clan is registered or owner of a castle<BR><BR>
+	 * @param clan The L2Clan of the player
+	 */
+	public final boolean checkIsRegistered(L2Clan clan, int castleid)
+	{
+		if (clan == null)
+			return false;
+		
+		if (clan.getHasCastle() > 0)
+			return true;
+		
+		Connection con = null;
+		boolean register = false;
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM siege_clans where clan_id=? and castle_id=?");
+			statement.setInt(1, clan.getClanId());
+			statement.setInt(2, castleid);
+			ResultSet rs = statement.executeQuery();
+			
+			while (rs.next())
+			{
+				register = true;
+				break;
+			}
+			
+			rs.close();
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			_log.warning("Exception: checkIsRegistered(): " + e.getMessage());
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+		return register;
+	}
+	
+	public final void removeSiegeSkills(L2PcInstance character)
+	{
+		for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(character.isNoble()))
+		{
+			character.removeSkill(sk);
+		}
+	}
+	
+	// =========================================================
+	// Method - Private
+	private final void load()
+	{
+		InputStream is = null;
+		try
+		{
+			is = new FileInputStream(new File(Config.SIEGE_CONFIGURATION_FILE));
+			Properties siegeSettings = new Properties();
+			siegeSettings.load(is);
+			
+			// Siege setting
+			_attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
+			_attackerRespawnDelay = Integer.decode(siegeSettings.getProperty("AttackerRespawn", "0"));
+			_defenderMaxClans = Integer.decode(siegeSettings.getProperty("DefenderMaxClans", "500"));
+			_flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
+			_siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "5"));
+			_siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "120"));
+			
+			// Siege spawns settings
+			_controlTowerSpawnList = new FastMap<Integer, FastList<SiegeSpawn>>();
+			_artefactSpawnList = new FastMap<Integer, FastList<SiegeSpawn>>();
+			
+			for (Castle castle : CastleManager.getInstance().getCastles())
+			{
+				FastList<SiegeSpawn> _controlTowersSpawns = new FastList<SiegeSpawn>();
+				
+				for (int i = 1; i < 0xFF; i++)
+				{
+					String _spawnParams = siegeSettings.getProperty(castle.getName() + "ControlTower" + Integer.toString(i), "");
+					
+					if (_spawnParams.length() == 0)
+						break;
+					
+					StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
+					
+					try
+					{
+						int x = Integer.parseInt(st.nextToken());
+						int y = Integer.parseInt(st.nextToken());
+						int z = Integer.parseInt(st.nextToken());
+						int npc_id = Integer.parseInt(st.nextToken());
+						int hp = Integer.parseInt(st.nextToken());
+						
+						_controlTowersSpawns.add(new SiegeSpawn(castle.getCastleId(), x, y, z, 0, npc_id, hp));
+					}
+					catch (Exception e)
+					{
+						_log.warning("Error while loading control tower(s) for " + castle.getName() + " castle.");
+					}
+				}
+				
+				FastList<SiegeSpawn> _artefactSpawns = new FastList<SiegeSpawn>();
+				
+				for (int i = 1; i < 0xFF; i++)
+				{
+					String _spawnParams = siegeSettings.getProperty(castle.getName() + "Artefact" + Integer.toString(i), "");
+					
+					if (_spawnParams.length() == 0)
+						break;
+					
+					StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
+					
+					try
+					{
+						int x = Integer.parseInt(st.nextToken());
+						int y = Integer.parseInt(st.nextToken());
+						int z = Integer.parseInt(st.nextToken());
+						int heading = Integer.parseInt(st.nextToken());
+						int npc_id = Integer.parseInt(st.nextToken());
+						
+						_artefactSpawns.add(new SiegeSpawn(castle.getCastleId(), x, y, z, heading, npc_id));
+					}
+					catch (Exception e)
+					{
+						_log.warning("Error while loading artefact(s) for " + castle.getName() + " castle.");
+					}
+				}
+				
+				_controlTowerSpawnList.put(castle.getCastleId(), _controlTowersSpawns);
+				_artefactSpawnList.put(castle.getCastleId(), _artefactSpawns);
+			}
+			
+		}
+		catch (Exception e)
+		{
+			//_initialized = false;
+			_log.warning("Error while loading siege data.");
+			e.printStackTrace();
+		}
+		finally
+		{
+			try
+			{
+				is.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
+	// =========================================================
+	// Property - Public
+	public final FastList<SiegeSpawn> getArtefactSpawnList(int _castleId)
+	{
+		if (_artefactSpawnList.containsKey(_castleId))
+			return _artefactSpawnList.get(_castleId);
+		else
+			return null;
+	}
+	
+	public final FastList<SiegeSpawn> getControlTowerSpawnList(int _castleId)
+	{
+		if (_controlTowerSpawnList.containsKey(_castleId))
+			return _controlTowerSpawnList.get(_castleId);
+		else
+			return null;
+	}
+	
+	public final int getAttackerMaxClans()
+	{
+		return _attackerMaxClans;
+	}
+	
+	public final int getAttackerRespawnDelay()
+	{
+		return _attackerRespawnDelay;
+	}
+	
+	public final int getDefenderMaxClans()
+	{
+		return _defenderMaxClans;
+	}
+	
+	public final int getFlagMaxCount()
+	{
+		return _flagMaxCount;
+	}
+	
+	public final Siege getSiege(L2Object activeObject)
+	{
+		return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ());
+	}
+	
+	public final Siege getSiege(int x, int y, int z)
+	{
+		for (Castle castle : CastleManager.getInstance().getCastles())
+			if (castle.getSiege().checkIfInZone(x, y, z))
+				return castle.getSiege();
+		return null;
+	}
+	
+	public final int getSiegeClanMinLevel()
+	{
+		return _siegeClanMinLevel;
+	}
+	
+	public final int getSiegeLength()
+	{
+		return _siegeLength;
+	}
+	
+	public final List<Siege> getSieges()
+	{
+		FastList<Siege> sieges = new FastList<Siege>();
+		for (Castle castle : CastleManager.getInstance().getCastles())
+			sieges.add(castle.getSiege());
+		return sieges;
+	}
+	
+	public class SiegeSpawn
+	{
+		Location _location;
+		private int _npcId;
+		private int _heading;
+		private int _castleId;
+		private int _hp;
+		
+		public SiegeSpawn(int castle_id, int x, int y, int z, int heading, int npc_id)
+		{
+			_castleId = castle_id;
+			_location = new Location(x, y, z, heading);
+			_heading = heading;
+			_npcId = npc_id;
+		}
+		
+		public SiegeSpawn(int castle_id, int x, int y, int z, int heading, int npc_id, int hp)
+		{
+			_castleId = castle_id;
+			_location = new Location(x, y, z, heading);
+			_heading = heading;
+			_npcId = npc_id;
+			_hp = hp;
+		}
+		
+		public int getCastleId()
+		{
+			return _castleId;
+		}
+		
+		public int getNpcId()
+		{
+			return _npcId;
+		}
+		
+		public int getHeading()
+		{
+			return _heading;
+		}
+		
+		public int getHp()
+		{
+			return _hp;
+		}
+		
+		public Location getLocation()
+		{
+			return _location;
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SiegeManager _instance = new SiegeManager();
+	}
 }

+ 70 - 66
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/TransformationManager.java

@@ -28,70 +28,74 @@ import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  */
 public class TransformationManager
 {
-    private static final Logger _log = Logger.getLogger(TransformationManager.class.getName());
-    
-    private static final TransformationManager INSTANCE = new TransformationManager();
-    
-    public static TransformationManager getInstance()
-    {
-        return INSTANCE;
-    }
-    
-    private Map<Integer, L2Transformation> _transformations;
-    
-    private TransformationManager()
-    {
-        _transformations = new FastMap<Integer, L2Transformation>();
-    }
-    
-    public void report()
-    {
-        _log.info("Loaded: "+this.getAllTransformations().size()+" transformations.");
-    }
-    
-    public boolean transformPlayer(int id, L2PcInstance player)
-    {
-        L2Transformation template = this.getTransformationById(id);
-        if (template != null)
-        {
-            L2Transformation trans = template.createTransformationForPlayer(player);
-            trans.start();
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-    
-    public boolean transformPlayer(int id, L2PcInstance player, long forceDuration)
-    {
-        L2Transformation template = this.getTransformationById(id);
-        if (template != null)
-        {
-            L2Transformation trans = template.createTransformationForPlayer(player);
-            trans.setDuration(forceDuration);
-            trans.start();
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-    
-    public L2Transformation getTransformationById(int id)
-    {
-        return _transformations.get(id);
-    }
-    
-    public L2Transformation registerTransformation(L2Transformation transformation)
-    {
-        return _transformations.put(transformation.getId() , transformation);
-    }
-    
-    public Collection<L2Transformation> getAllTransformations()
-    {
-        return _transformations.values();
-    }
+	private static final Logger _log = Logger.getLogger(TransformationManager.class.getName());
+	
+	public static TransformationManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private Map<Integer, L2Transformation> _transformations;
+	
+	private TransformationManager()
+	{
+		_transformations = new FastMap<Integer, L2Transformation>();
+	}
+	
+	public void report()
+	{
+		_log.info("Loaded: " + this.getAllTransformations().size() + " transformations.");
+	}
+	
+	public boolean transformPlayer(int id, L2PcInstance player)
+	{
+		L2Transformation template = this.getTransformationById(id);
+		if (template != null)
+		{
+			L2Transformation trans = template.createTransformationForPlayer(player);
+			trans.start();
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+	
+	public boolean transformPlayer(int id, L2PcInstance player, long forceDuration)
+	{
+		L2Transformation template = this.getTransformationById(id);
+		if (template != null)
+		{
+			L2Transformation trans = template.createTransformationForPlayer(player);
+			trans.setDuration(forceDuration);
+			trans.start();
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+	
+	public L2Transformation getTransformationById(int id)
+	{
+		return _transformations.get(id);
+	}
+	
+	public L2Transformation registerTransformation(L2Transformation transformation)
+	{
+		return _transformations.put(transformation.getId(), transformation);
+	}
+	
+	public Collection<L2Transformation> getAllTransformations()
+	{
+		return _transformations.values();
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final TransformationManager _instance = new TransformationManager();
+	}
 }

+ 70 - 80
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/ZoneManager.java

@@ -48,30 +48,24 @@ import org.w3c.dom.Node;
 public class ZoneManager
 {
 	private static final Logger _log = Logger.getLogger(ZoneManager.class.getName());
-
-	// =========================================================
-	private static ZoneManager _instance;
+	
 	private final FastList<L2ZoneType> _zones = new FastList<L2ZoneType>();
-
+	
 	public static final ZoneManager getInstance()
 	{
-		if (_instance == null)
-		{
-			_instance = new ZoneManager();
-		}
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	// =========================================================
 	// Data Field
-
+	
 	// =========================================================
 	// Constructor
-	public ZoneManager()
+	private ZoneManager()
 	{
 		load();
 	}
-
+	
 	public void reload()
 	{
 		// int zoneCount = 0;
@@ -88,34 +82,34 @@ public class ZoneManager
 			}
 		}
 		GrandBossManager.getInstance().getZones().clear();
-		_log.info("Removed zones in "+ count+ " regions.");
+		_log.info("Removed zones in " + count + " regions.");
 		// Load the zones
 		load();
 	}
-
+	
 	// =========================================================
 	// Method - Private
-
+	
 	private final void load()
 	{
 		_log.info("Loading zones...");
 		Connection con = null;
 		int zoneCount = 0;
 		_zones.clear();
-
+		
 		// Get the world regions
 		L2WorldRegion[][] worldRegions = L2World.getInstance().getAllWorldRegions();
-
+		
 		// Load the zone xml
 		try
 		{
 			// Get a sql connection here
 			con = L2DatabaseFactory.getInstance().getConnection();
-
+			
 			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 			factory.setValidating(false);
 			factory.setIgnoringComments(true);
-
+			
 			File file = new File(Config.DATAPACK_ROOT + "/data/zones/zone.xml");
 			if (!file.exists())
 			{
@@ -123,9 +117,9 @@ public class ZoneManager
 					_log.info("The zone.xml file is missing.");
 				return;
 			}
-
+			
 			Document doc = factory.newDocumentBuilder().parse(file);
-
+			
 			for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
 			{
 				if ("list".equalsIgnoreCase(n.getNodeName()))
@@ -140,11 +134,10 @@ public class ZoneManager
 							int maxZ = Integer.parseInt(attrs.getNamedItem("maxZ").getNodeValue());
 							String zoneType = attrs.getNamedItem("type").getNodeValue();
 							String zoneShape = attrs.getNamedItem("shape").getNodeValue();
-
-
+							
 							// Create the zone
 							L2ZoneType temp = null;
-
+							
 							if (zoneType.equals("FishingZone"))
 								temp = new L2FishingZone(zoneId);
 							else if (zoneType.equals("ClanHallZone"))
@@ -187,26 +180,25 @@ public class ZoneManager
 								temp = new L2WaterZone(zoneId);
 							else if (zoneType.equals("NoStoreZone"))
 								temp = new L2NoStoreZone(zoneId);
-
+							
 							// Check for unknown type
 							if (temp == null)
 							{
-								_log.warning("ZoneData: No such zone type: "
-								        + zoneType);
+								_log.warning("ZoneData: No such zone type: " + zoneType);
 								continue;
 							}
-
+							
 							// Get the zone shape from sql
 							try
 							{
 								PreparedStatement statement = null;
-
+								
 								// Set the correct query
 								statement = con.prepareStatement("SELECT x,y FROM zone_vertices WHERE id=? ORDER BY 'order' ASC ");
-
+								
 								statement.setInt(1, zoneId);
 								ResultSet rset = statement.executeQuery();
-
+								
 								// Create this zone. Parsing for cuboids is a
 								// bit different than for other polygons
 								// cuboids need exactly 2 points to be defined.
@@ -217,7 +209,7 @@ public class ZoneManager
 									int[] x = { 0, 0 };
 									int[] y = { 0, 0 };
 									boolean successfulLoad = true;
-
+									
 									for (int i = 0; i < 2; i++)
 									{
 										if (rset.next())
@@ -227,15 +219,14 @@ public class ZoneManager
 										}
 										else
 										{
-											_log.warning("ZoneData: Missing cuboid vertex in sql data for zone: "
-											        + zoneId);
+											_log.warning("ZoneData: Missing cuboid vertex in sql data for zone: " + zoneId);
 											rset.close();
 											statement.close();
 											successfulLoad = false;
 											break;
 										}
 									}
-
+									
 									if (successfulLoad)
 										temp.setZone(new ZoneCuboid(x[0], x[1], y[0], y[1], minZ, maxZ));
 									else
@@ -244,23 +235,22 @@ public class ZoneManager
 								else if (zoneShape.equalsIgnoreCase("NPoly"))
 								{
 									FastList<Integer> fl_x = new FastList<Integer>(), fl_y = new FastList<Integer>();
-
+									
 									// Load the rest
 									while (rset.next())
 									{
 										fl_x.add(rset.getInt("x"));
 										fl_y.add(rset.getInt("y"));
 									}
-
+									
 									// An nPoly needs to have at least 3
 									// vertices
-									if ((fl_x.size() == fl_y.size())
-									        && (fl_x.size() > 2))
+									if ((fl_x.size() == fl_y.size()) && (fl_x.size() > 2))
 									{
 										// Create arrays
 										int[] aX = new int[fl_x.size()];
 										int[] aY = new int[fl_y.size()];
-
+										
 										// This runs only at server startup so
 										// dont complain :>
 										for (int i = 0; i < fl_x.size(); i++)
@@ -268,14 +258,13 @@ public class ZoneManager
 											aX[i] = fl_x.get(i);
 											aY[i] = fl_y.get(i);
 										}
-
+										
 										// Create the zone
 										temp.setZone(new ZoneNPoly(aX, aY, minZ, maxZ));
 									}
 									else
 									{
-										_log.warning("ZoneData: Bad sql data for zone: "
-										        + zoneId);
+										_log.warning("ZoneData: Bad sql data for zone: " + zoneId);
 										rset.close();
 										statement.close();
 										continue;
@@ -290,14 +279,13 @@ public class ZoneManager
 									{
 										int zoneX = rset.getInt("x");
 										int zoneY = rset.getInt("y");
-
+										
 										// create the zone
 										temp.setZone(new ZoneCylinder(zoneX, zoneY, minZ, maxZ, zoneRad));
 									}
 									else
 									{
-										_log.warning("ZoneData: Bad sql data for zone: "
-										        + zoneId);
+										_log.warning("ZoneData: Bad sql data for zone: " + zoneId);
 										rset.close();
 										statement.close();
 										continue;
@@ -305,8 +293,7 @@ public class ZoneManager
 								}
 								else
 								{
-									_log.warning("ZoneData: Unknown shape: "
-									        + zoneShape);
+									_log.warning("ZoneData: Unknown shape: " + zoneShape);
 									rset.close();
 									statement.close();
 									continue;
@@ -317,10 +304,9 @@ public class ZoneManager
 							}
 							catch (Exception e)
 							{
-								_log.warning("ZoneData: Failed to load zone coordinates: "
-								        + e);
+								_log.warning("ZoneData: Failed to load zone coordinates: " + e);
 							}
-
+							
 							// Check for aditional parameters
 							for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
 							{
@@ -352,19 +338,17 @@ public class ZoneManager
 									{
 										if (Config.DEBUG)
 										{
-											_log.info("Zone (" + zoneId
-											        + ") added to: " + x + " "
-											        + y);
+											_log.info("Zone (" + zoneId + ") added to: " + x + " " + y);
 										}
 										worldRegions[x][y].addZone(temp);
 									}
 								}
 							}
-
+							
 							// Special managers for granbosses...
 							if (temp instanceof L2BossZone)
 								GrandBossManager.getInstance().addZone((L2BossZone) temp);
-
+							
 							// Increase the counter
 							zoneCount++;
 						}
@@ -387,7 +371,7 @@ public class ZoneManager
 			{
 			}
 		}
-
+		
 		_log.info("Done: loaded " + zoneCount + " zones.");
 	}
 	
@@ -421,7 +405,7 @@ public class ZoneManager
 	{
 		return getZones(object.getX(), object.getY(), object.getZ());
 	}
-
+	
 	/**
 	 * Returns all zones from given coordinates (plane)
 	 * 
@@ -440,7 +424,7 @@ public class ZoneManager
 		}
 		return temp;
 	}
-
+	
 	/**
 	 * Returns all zones from given coordinates 
 	 *
@@ -461,24 +445,30 @@ public class ZoneManager
 		return temp;
 	}
 	
-    public  final L2ArenaZone getArena(L2Character character)
-    {
-    	for (L2ZoneType temp : ZoneManager.getInstance().getZones(character.getX(), character.getY(), character.getZ()))
-    	{
-    		if (temp instanceof L2ArenaZone && temp.isCharacterInZone(character)) 
-    			return ((L2ArenaZone)temp);
-    	}
-
-    	return null;
-    }
-    
-    public final L2OlympiadStadiumZone getOlympiadStadium(L2Character character)
-    {
-    	for (L2ZoneType temp : ZoneManager.getInstance().getZones(character.getX(), character.getY(), character.getZ()))
-    	{
-    		if (temp instanceof L2OlympiadStadiumZone && temp.isCharacterInZone(character)) 
-    			return ((L2OlympiadStadiumZone)temp);
-    	}
-    	return null;
-    }
+	public final L2ArenaZone getArena(L2Character character)
+	{
+		for (L2ZoneType temp : ZoneManager.getInstance().getZones(character.getX(), character.getY(), character.getZ()))
+		{
+			if (temp instanceof L2ArenaZone && temp.isCharacterInZone(character))
+				return ((L2ArenaZone) temp);
+		}
+		
+		return null;
+	}
+	
+	public final L2OlympiadStadiumZone getOlympiadStadium(L2Character character)
+	{
+		for (L2ZoneType temp : ZoneManager.getInstance().getZones(character.getX(), character.getY(), character.getZ()))
+		{
+			if (temp instanceof L2OlympiadStadiumZone && temp.isCharacterInZone(character))
+				return ((L2OlympiadStadiumZone) temp);
+		}
+		return null;
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final ZoneManager _instance = new ZoneManager();
+	}
 }

+ 8 - 9
L2_GameServer/java/net/sf/l2j/gameserver/instancemanager/games/Lottery.java

@@ -35,7 +35,6 @@ public class Lottery
 	public static final long SECOND = 1000;
 	public static final long MINUTE = 60000;
 	
-	private static Lottery _instance;
 	protected static final Logger _log = Logger.getLogger(Lottery.class.getName());
 	
 	private static final String INSERT_LOTTERY = "INSERT INTO games(id, idnr, enddate, prize, newprize) VALUES (?, ?, ?, ?, ?)";
@@ -65,10 +64,7 @@ public class Lottery
 	
 	public static Lottery getInstance()
 	{
-		if (_instance == null)
-			_instance = new Lottery();
-		
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	public int getId()
@@ -511,10 +507,7 @@ public class Lottery
 	
 	public long[] checkTicket(int id, int enchant, int type2)
 	{
-		long res[] =
-		{
-			0, 0
-		};
+		long res[] = { 0, 0 };
 		
 		Connection con = null;
 		PreparedStatement statement;
@@ -597,4 +590,10 @@ public class Lottery
 		
 		return res;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final Lottery _instance = new Lottery();
+	}
 }

+ 12 - 14
L2_GameServer/java/net/sf/l2j/gameserver/lib/SqlUtils.java

@@ -25,17 +25,15 @@ public class SqlUtils
 {
 	private static Logger _log = Logger.getLogger(SqlUtils.class.getName());
 	
-	// =========================================================
-	// Data Field
-	private static SqlUtils _instance;
+	private SqlUtils()
+	{
+	}
 	
 	// =========================================================
 	// Property - Public
 	public static SqlUtils getInstance()
 	{
-		if (_instance == null)
-			_instance = new SqlUtils();
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	// =========================================================
@@ -50,10 +48,7 @@ public class SqlUtils
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-			query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[]
-			{
-				resultField
-			}, tableName, whereClause, true);
+			query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[] { resultField }, tableName, whereClause, true);
 			
 			PreparedStatement statement = con.prepareStatement(query);
 			ResultSet rset = statement.executeQuery();
@@ -93,10 +88,7 @@ public class SqlUtils
 		try
 		{
 			con = L2DatabaseFactory.getInstance().getConnection();
-			query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[]
-			{
-				resultField
-			}, tableName, whereClause, false);
+			query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[] { resultField }, tableName, whereClause, false);
 			PreparedStatement statement = con.prepareStatement(query);
 			ResultSet rset = statement.executeQuery();
 			
@@ -193,4 +185,10 @@ public class SqlUtils
 		_log.fine("Get all rows in query '" + query + "' in " + (System.currentTimeMillis() - start) + "ms");
 		return res;
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final SqlUtils _instance = new SqlUtils();
+	}
 }

+ 8 - 4
L2_GameServer/java/net/sf/l2j/gameserver/lib/memcache.java

@@ -25,11 +25,9 @@ public class memcache
 	private HashMap<Integer, Integer> _hmi;
 	private HashMap<Integer, Long> _lastAccess;
 	
-	private static final memcache _instance = new memcache();
-	
 	public static memcache getInstance()
 	{
-		return _instance;
+		return SingletonHolder._instance;
 	}
 	
 	private memcache()
@@ -59,7 +57,7 @@ public class memcache
 	public void set(String type, String key, int value)
 	{
 		int hash = (type + "->" + key).hashCode();
-		//	    _log.fine("Set memcache "+type+"("+key+")["+hash+"] to "+value);
+		//_log.fine("Set memcache "+type+"("+key+")["+hash+"] to "+value);
 		_hmi.put(hash, value);
 		_lastAccess.put(hash, System.currentTimeMillis());
 		checkExpired();
@@ -87,4 +85,10 @@ public class memcache
 		_log.fine("Get memcache " + type + "(" + key + ")[" + hash + "] = " + _hmi.get(hash));
 		return _hmi.get(hash);
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final memcache _instance = new memcache();
+	}
 }

+ 779 - 756
L2_GameServer/java/net/sf/l2j/gameserver/model/AutoChatHandler.java

@@ -46,80 +46,79 @@ import net.sf.l2j.util.Rnd;
  */
 public class AutoChatHandler implements SpawnListener
 {
-    protected static final Logger _log = Logger.getLogger(AutoChatHandler.class.getName());
-    private static AutoChatHandler _instance;
-
-    private static final long DEFAULT_CHAT_DELAY = 30000; // 30 secs by default
-
-    protected Map<Integer, AutoChatInstance> _registeredChats;
-
-    protected AutoChatHandler()
-    {
-        _registeredChats = new FastMap<Integer, AutoChatInstance>();
-        restoreChatData();
-        L2Spawn.addSpawnListener(this);
-    }
-
-    private void restoreChatData()
-    {
-        int numLoaded = 0;
-        Connection con = null;
-        PreparedStatement statement = null;
-        PreparedStatement statement2 = null;
-        ResultSet rs = null;
-        ResultSet rs2 = null;
-
-        try
-        {
-            con = L2DatabaseFactory.getInstance().getConnection();
-
-            statement = con.prepareStatement("SELECT * FROM auto_chat ORDER BY groupId ASC");
-            rs = statement.executeQuery();
-
-            while (rs.next())
-            {
-                numLoaded++;
-
-                statement2 = con.prepareStatement("SELECT * FROM auto_chat_text WHERE groupId=?");
-                statement2.setInt(1, rs.getInt("groupId"));
-                rs2 = statement2.executeQuery();
-
-                rs2.last();
-                String[] chatTexts = new String[rs2.getRow()];
-                int i = 0;
-                rs2.beforeFirst();
-
-                while (rs2.next())
-                {
-                    chatTexts[i++] = rs2.getString("chatText");
-                }
-
-                registerGlobalChat(rs.getInt("npcId"), chatTexts, rs.getLong("chatDelay"));
-
-                statement2.close();
-            }
-
-            statement.close();
-
-            if (Config.DEBUG)
-                _log.config("AutoChatHandler: Loaded " + numLoaded + " chat group(s) from the database.");
-        }
-        catch (Exception e)
-        {
-            _log.warning("AutoSpawnHandler: Could not restore chat data: " + e);
-        }
-        finally
-        {
-            try
-            {
-                con.close();
-            }
-            catch (Exception e)
-            {
-            }
-        }
-    }
-
+	protected static final Logger _log = Logger.getLogger(AutoChatHandler.class.getName());
+	
+	private static final long DEFAULT_CHAT_DELAY = 30000; // 30 secs by default
+	
+	protected Map<Integer, AutoChatInstance> _registeredChats;
+	
+	private AutoChatHandler()
+	{
+		_registeredChats = new FastMap<Integer, AutoChatInstance>();
+		restoreChatData();
+		L2Spawn.addSpawnListener(this);
+	}
+	
+	private void restoreChatData()
+	{
+		int numLoaded = 0;
+		Connection con = null;
+		PreparedStatement statement = null;
+		PreparedStatement statement2 = null;
+		ResultSet rs = null;
+		ResultSet rs2 = null;
+		
+		try
+		{
+			con = L2DatabaseFactory.getInstance().getConnection();
+			
+			statement = con.prepareStatement("SELECT * FROM auto_chat ORDER BY groupId ASC");
+			rs = statement.executeQuery();
+			
+			while (rs.next())
+			{
+				numLoaded++;
+				
+				statement2 = con.prepareStatement("SELECT * FROM auto_chat_text WHERE groupId=?");
+				statement2.setInt(1, rs.getInt("groupId"));
+				rs2 = statement2.executeQuery();
+				
+				rs2.last();
+				String[] chatTexts = new String[rs2.getRow()];
+				int i = 0;
+				rs2.beforeFirst();
+				
+				while (rs2.next())
+				{
+					chatTexts[i++] = rs2.getString("chatText");
+				}
+				
+				registerGlobalChat(rs.getInt("npcId"), chatTexts, rs.getLong("chatDelay"));
+				
+				statement2.close();
+			}
+			
+			statement.close();
+			
+			if (Config.DEBUG)
+				_log.config("AutoChatHandler: Loaded " + numLoaded + " chat group(s) from the database.");
+		}
+		catch (Exception e)
+		{
+			_log.warning("AutoSpawnHandler: Could not restore chat data: " + e);
+		}
+		finally
+		{
+			try
+			{
+				con.close();
+			}
+			catch (Exception e)
+			{
+			}
+		}
+	}
+	
 	public void reload()
 	{
 		// unregister all registered spawns
@@ -140,686 +139,710 @@ public class AutoChatHandler implements SpawnListener
 		// load
 		restoreChatData();
 	}
-    public static AutoChatHandler getInstance()
-    {
-        if (_instance == null) _instance = new AutoChatHandler();
-
-        return _instance;
-    }
-
-    public int size()
-    {
-        return _registeredChats.size();
-    }
-
-    /**
-     * Registers a globally active auto chat for ALL instances of the given NPC ID.
-     * <BR>
-     * Returns the associated auto chat instance.
-     *
-     * @param int npcId
-     * @param String[] chatTexts
-     * @param int chatDelay (-1 = default delay)
-     * @return AutoChatInstance chatInst
-     */
-    public AutoChatInstance registerGlobalChat(int npcId, String[] chatTexts, long chatDelay)
-    {
-        return registerChat(npcId, null, chatTexts, chatDelay);
-    }
-
-    /**
-     * Registers a NON globally-active auto chat for the given NPC instance, and adds to the currently
-     * assigned chat instance for this NPC ID, otherwise creates a new instance if
-     * a previous one is not found.
-     * <BR>
-     * Returns the associated auto chat instance.
-     *
-     * @param L2Npc npcInst
-     * @param String[] chatTexts
-     * @param int chatDelay (-1 = default delay)
-     * @return AutoChatInstance chatInst
-     */
-    public AutoChatInstance registerChat(L2Npc npcInst, String[] chatTexts, long chatDelay)
-    {
-        return registerChat(npcInst.getNpcId(), npcInst, chatTexts, chatDelay);
-    }
-
-    private final AutoChatInstance registerChat(int npcId, L2Npc npcInst, String[] chatTexts,
-                                                long chatDelay)
-    {
-        AutoChatInstance chatInst = null;
-
-        if (chatDelay < 0) chatDelay = DEFAULT_CHAT_DELAY;
-
-        if (_registeredChats.containsKey(npcId)) chatInst = _registeredChats.get(npcId);
-        else chatInst = new AutoChatInstance(npcId, chatTexts, chatDelay, (npcInst == null));
-
-        if (npcInst != null) chatInst.addChatDefinition(npcInst);
-
-        _registeredChats.put(npcId, chatInst);
-
-        return chatInst;
-    }
-
-    /**
-     * Removes and cancels ALL auto chat definition for the given NPC ID,
-     * and removes its chat instance if it exists.
-     *
-     * @param int npcId
-     * @return boolean removedSuccessfully
-     */
-    public boolean removeChat(int npcId)
-    {
-        AutoChatInstance chatInst = _registeredChats.get(npcId);
-
-        return removeChat(chatInst);
-    }
-
-    /**
-     * Removes and cancels ALL auto chats for the given chat instance.
-     *
-     * @param AutoChatInstance chatInst
-     * @return boolean removedSuccessfully
-     */
-    public boolean removeChat(AutoChatInstance chatInst)
-    {
-        if (chatInst == null) return false;
-
-        _registeredChats.remove(chatInst.getNPCId());
-        chatInst.setActive(false);
-
-        if (Config.DEBUG)
-            _log.config("AutoChatHandler: Removed auto chat for NPC ID " + chatInst.getNPCId());
-
-        return true;
-    }
-
-    /**
-     * Returns the associated auto chat instance either by the given NPC ID
-     * or object ID.
-     *
-     * @param int id
-     * @param boolean byObjectId
-     * @return AutoChatInstance chatInst
-     */
-    public AutoChatInstance getAutoChatInstance(int id, boolean byObjectId)
-    {
-        if (!byObjectId) return _registeredChats.get(id);
-        else for (AutoChatInstance chatInst : _registeredChats.values())
-            if (chatInst.getChatDefinition(id) != null) return chatInst;
-
-        return null;
-    }
-
-    /**
-     * Sets the active state of all auto chat instances to that specified,
-     * and cancels the scheduled chat task if necessary.
-     *
-     * @param boolean isActive
-     */
-    public void setAutoChatActive(boolean isActive)
-    {
-        for (AutoChatInstance chatInst : _registeredChats.values())
-            chatInst.setActive(isActive);
-    }
-
-    /**
-     * Used in conjunction with a SpawnListener, this method is called every time
-     * an NPC is spawned in the world.
-     * <BR><BR>
-     * If an auto chat instance is set to be "global", all instances matching the registered
-     * NPC ID will be added to that chat instance.
-     */
-    public void npcSpawned(L2Npc npc)
-    {
-        synchronized (_registeredChats)
-        {
-            if (npc == null) return;
-
-            int npcId = npc.getNpcId();
-
-            if (_registeredChats.containsKey(npcId))
-            {
-                AutoChatInstance chatInst = _registeredChats.get(npcId);
-
-                if (chatInst != null && chatInst.isGlobal()) chatInst.addChatDefinition(npc);
-            }
-        }
-    }
-
-    /**
-     * Auto Chat Instance
-     * <BR><BR>
-     * Manages the auto chat instances for a specific registered NPC ID.
-     *
-     * @author Tempy
-     */
-    public class AutoChatInstance
-    {
-        protected int _npcId;
-        private long _defaultDelay = DEFAULT_CHAT_DELAY;
-        private String[] _defaultTexts;
-        private boolean _defaultRandom = false;
-
-        private boolean _globalChat = false;
-        private boolean _isActive;
-
-        private Map<Integer, AutoChatDefinition> _chatDefinitions = new FastMap<Integer, AutoChatDefinition>();
-        protected ScheduledFuture<?> _chatTask;
-
-        protected AutoChatInstance(int npcId, String[] chatTexts, long chatDelay, boolean isGlobal)
-        {
-            _defaultTexts = chatTexts;
-            _npcId = npcId;
-            _defaultDelay = chatDelay;
-            _globalChat = isGlobal;
-
-            if (Config.DEBUG)
-                _log.config("AutoChatHandler: Registered auto chat for NPC ID " + _npcId
-                    + " (Global Chat = " + _globalChat + ").");
-
-            setActive(true);
-        }
-
-        protected AutoChatDefinition getChatDefinition(int objectId)
-        {
-            return _chatDefinitions.get(objectId);
-        }
-
-        protected AutoChatDefinition[] getChatDefinitions()
-        {
-            return _chatDefinitions.values().toArray(new AutoChatDefinition[_chatDefinitions.values().size()]);
-        }
-
-        /**
-         * Defines an auto chat for an instance matching this auto chat instance's registered NPC ID,
-         * and launches the scheduled chat task.
-         * <BR>
-         * Returns the object ID for the NPC instance, with which to refer
-         * to the created chat definition.
-         * <BR>
-         * <B>Note</B>: Uses pre-defined default values for texts and chat delays from the chat instance.
-         *
-         * @param L2Npc npcInst
-         * @return int objectId
-         */
-        public int addChatDefinition(L2Npc npcInst)
-        {
-            return addChatDefinition(npcInst, null, 0);
-        }
-
-        /**
-         * Defines an auto chat for an instance matching this auto chat instance's registered NPC ID,
-         * and launches the scheduled chat task.
-         * <BR>
-         * Returns the object ID for the NPC instance, with which to refer
-         * to the created chat definition.
-         *
-         * @param L2Npc npcInst
-         * @param String[] chatTexts
-         * @param int chatDelay
-         * @return int objectId
-         */
-        public int addChatDefinition(L2Npc npcInst, String[] chatTexts, long chatDelay)
-        {
-            int objectId = npcInst.getObjectId();
-            AutoChatDefinition chatDef = new AutoChatDefinition(this, npcInst, chatTexts, chatDelay);
-            if(npcInst instanceof L2SiegeGuardInstance)
-            	chatDef.setRandomChat(true);
-            _chatDefinitions.put(objectId, chatDef);
-            return objectId;
-        }
-
-        /**
-         * Removes a chat definition specified by the given object ID.
-         *
-         * @param int objectId
-         * @return boolean removedSuccessfully
-         */
-        public boolean removeChatDefinition(int objectId)
-        {
-            if (!_chatDefinitions.containsKey(objectId)) return false;
-
-            AutoChatDefinition chatDefinition = _chatDefinitions.get(objectId);
-            chatDefinition.setActive(false);
-
-            _chatDefinitions.remove(objectId);
-
-            return true;
-        }
-
-        /**
-         * Tests if this auto chat instance is active.
-         *
-         * @return boolean isActive
-         */
-        public boolean isActive()
-        {
-            return _isActive;
-        }
-
-        /**
-         * Tests if this auto chat instance applies to
-         * ALL currently spawned instances of the registered NPC ID.
-         *
-         * @return boolean isGlobal
-         */
-        public boolean isGlobal()
-        {
-            return _globalChat;
-        }
-
-        /**
-         * Tests if random order is the DEFAULT for new chat definitions.
-         *
-         * @return boolean isRandom
-         */
-        public boolean isDefaultRandom()
-        {
-            return _defaultRandom;
-        }
-
-        /**
-         * Tests if the auto chat definition given by its object ID is set to be random.
-         *
-         * @return boolean isRandom
-         */
-        public boolean isRandomChat(int objectId)
-        {
-            if (!_chatDefinitions.containsKey(objectId)) return false;
-
-            return _chatDefinitions.get(objectId).isRandomChat();
-        }
-
-        /**
-         * Returns the ID of the NPC type managed by this auto chat instance.
-         *
-         * @return int npcId
-         */
-        public int getNPCId()
-        {
-            return _npcId;
-        }
-
-        /**
-         * Returns the number of auto chat definitions stored for this instance.
-         *
-         * @return int definitionCount
-         */
-        public int getDefinitionCount()
-        {
-            return _chatDefinitions.size();
-        }
-
-        /**
-         * Returns a list of all NPC instances handled by this auto chat instance.
-         *
-         * @return L2NpcInstance[] npcInsts
-         */
-        public L2Npc[] getNPCInstanceList()
-        {
-            List<L2Npc> npcInsts = new FastList<L2Npc>();
-
-            for (AutoChatDefinition chatDefinition : _chatDefinitions.values())
-                npcInsts.add(chatDefinition._npcInstance);
-
-            return npcInsts.toArray(new L2Npc[npcInsts.size()]);
-        }
-
-        /**
-         * A series of methods used to get and set default values for new chat definitions.
-         */
-        public long getDefaultDelay()
-        {
-            return _defaultDelay;
-        }
-
-        public String[] getDefaultTexts()
-        {
-            return _defaultTexts;
-        }
-
-        public void setDefaultChatDelay(long delayValue)
-        {
-            _defaultDelay = delayValue;
-        }
-
-        public void setDefaultChatTexts(String[] textsValue)
-        {
-            _defaultTexts = textsValue;
-        }
-
-        public void setDefaultRandom(boolean randValue)
-        {
-            _defaultRandom = randValue;
-        }
-
-        /**
-         * Sets a specific chat delay for the specified auto chat definition given by its object ID.
-         *
-         * @param int objectId
-         * @param long delayValue
-         */
-        public void setChatDelay(int objectId, long delayValue)
-        {
-            AutoChatDefinition chatDef = getChatDefinition(objectId);
-
-            if (chatDef != null) chatDef.setChatDelay(delayValue);
-        }
-
-        /**
-         * Sets a specific set of chat texts for the specified auto chat definition given by its object ID.
-         *
-         * @param int objectId
-         * @param String[] textsValue
-         */
-        public void setChatTexts(int objectId, String[] textsValue)
-        {
-            AutoChatDefinition chatDef = getChatDefinition(objectId);
-
-            if (chatDef != null) chatDef.setChatTexts(textsValue);
-        }
-
-        /**
-         * Sets specifically to use random chat order for the auto chat definition given by its object ID.
-         *
-         * @param int objectId
-         * @param boolean randValue
-         */
-        public void setRandomChat(int objectId, boolean randValue)
-        {
-            AutoChatDefinition chatDef = getChatDefinition(objectId);
-
-            if (chatDef != null) chatDef.setRandomChat(randValue);
-        }
-
-        /**
-         * Sets the activity of ALL auto chat definitions handled by this chat instance.
-         *
-         * @param boolean isActive
-         */
-        public void setActive(boolean activeValue)
-        {
-            if (_isActive == activeValue) return;
-
-            _isActive = activeValue;
-
-            if (!isGlobal())
-            {
-                for (AutoChatDefinition chatDefinition : _chatDefinitions.values())
-                    chatDefinition.setActive(activeValue);
-
-                return;
-            }
-
-            if (isActive())
-            {
-                AutoChatRunner acr = new AutoChatRunner(_npcId, -1);
-                _chatTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(acr,
-                		_defaultDelay, _defaultDelay);
-            }
-            else
-            {
-                _chatTask.cancel(false);
-            }
-        }
-
-        /**
-         * Auto Chat Definition
-         * <BR><BR>
-         * Stores information about specific chat data for an instance of the NPC ID
-         * specified by the containing auto chat instance.
-         * <BR>
-         * Each NPC instance of this type should be stored in a subsequent AutoChatDefinition class.
-         *
-         * @author Tempy
-         */
-        private class AutoChatDefinition
-        {
-            protected int _chatIndex = 0;
-            protected L2Npc _npcInstance;
-
-            protected AutoChatInstance _chatInstance;
-
-            private long _chatDelay = 0;
-            private String[] _chatTexts = null;
-            private boolean _isActiveDefinition;
-            private boolean _randomChat;
-
-            protected AutoChatDefinition(AutoChatInstance chatInst, L2Npc npcInst,
-            		String[] chatTexts, long chatDelay)
-            {
-                _npcInstance = npcInst;
-
-                _chatInstance = chatInst;
-                _randomChat = chatInst.isDefaultRandom();
-
-                _chatDelay = chatDelay;
-                _chatTexts = chatTexts;
-
-                if (Config.DEBUG)
-                    _log.info("AutoChatHandler: Chat definition added for NPC ID "
-                        + _npcInstance.getNpcId() + " (Object ID = " + _npcInstance.getObjectId() + ").");
-
-                // If global chat isn't enabled for the parent instance,
-                // then handle the chat task locally.
-                if (!chatInst.isGlobal()) setActive(true);
-            }
-
-            protected AutoChatDefinition(AutoChatInstance chatInst, L2Npc npcInst)
-            {
-                this(chatInst, npcInst, null, -1);
-            }
-
-            protected String[] getChatTexts()
-            {
-                if (_chatTexts != null) return _chatTexts;
-                else return _chatInstance.getDefaultTexts();
-            }
-
-            private long getChatDelay()
-            {
-                if (_chatDelay > 0) return _chatDelay;
-                else return _chatInstance.getDefaultDelay();
-            }
-
-            private boolean isActive()
-            {
-                return _isActiveDefinition;
-            }
-
-            boolean isRandomChat()
-            {
-                return _randomChat;
-            }
-
-            void setRandomChat(boolean randValue)
-            {
-                _randomChat = randValue;
-            }
-
-            void setChatDelay(long delayValue)
-            {
-                _chatDelay = delayValue;
-            }
-
-            void setChatTexts(String[] textsValue)
-            {
-                _chatTexts = textsValue;
-            }
-
-            void setActive(boolean activeValue)
-            {
-                if (isActive() == activeValue) return;
-
-                if (activeValue)
-                {
-                    AutoChatRunner acr = new AutoChatRunner(_npcId, _npcInstance.getObjectId());
-                    if(getChatDelay() == 0)
-                    	// Schedule it set to 5Ms, isn't error, if use 0 sometine
-                    	// chatDefinition return null in AutoChatRunner
-                    	_chatTask = ThreadPoolManager.getInstance().scheduleGeneral(acr, 5);
-                    else
-                    	_chatTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate( acr,getChatDelay(),getChatDelay());
-                }
-                else
-                {
-                    _chatTask.cancel(false);
-                }
-
-                _isActiveDefinition = activeValue;
-            }
-        }
-
-        /**
-         * Auto Chat Runner
-         * <BR><BR>
-         * Represents the auto chat scheduled task for each chat instance.
-         *
-         * @author Tempy
-         */
-        private class AutoChatRunner implements Runnable
-        {
-            private int _runnerNpcId;
-            private int _objectId;
-
-            protected AutoChatRunner(int pNpcId, int pObjectId)
-            {
-            	_runnerNpcId = pNpcId;
-                _objectId = pObjectId;
-            }
-
-            public synchronized void run()
-            {
-                AutoChatInstance chatInst = _registeredChats.get(_runnerNpcId);
-                AutoChatDefinition[] chatDefinitions;
-
-                if (chatInst.isGlobal())
-                {
-                    chatDefinitions = chatInst.getChatDefinitions();
-                }
-                else
-                {
-                    AutoChatDefinition chatDef = chatInst.getChatDefinition(_objectId);
-
-                    if (chatDef == null)
-                    {
-                        _log.warning("AutoChatHandler: Auto chat definition is NULL for NPC ID "
-                            + _npcId + ".");
-                        return;
-                    }
-
-                    chatDefinitions = new AutoChatDefinition[] {chatDef};
-                }
-
-                if (Config.DEBUG)
-                    _log.info("AutoChatHandler: Running auto chat for " + chatDefinitions.length
-                        + " instances of NPC ID " + _npcId + "." + " (Global Chat = "
-                        + chatInst.isGlobal() + ")");
-
-                for (AutoChatDefinition chatDef : chatDefinitions)
-                {
-                    try
-                    {
-                        L2Npc chatNpc = chatDef._npcInstance;
-                        List<L2PcInstance> nearbyPlayers = new FastList<L2PcInstance>();
-                        List<L2PcInstance> nearbyGMs = new FastList<L2PcInstance>();
-
-                        for (L2Character player : chatNpc.getKnownList().getKnownCharactersInRadius(1500))
-                        {
-                            if (!(player instanceof L2PcInstance)) continue;
-
-                            if (((L2PcInstance) player).isGM()) nearbyGMs.add((L2PcInstance) player);
-                            else nearbyPlayers.add((L2PcInstance) player);
-                        }
-
-                        int maxIndex = chatDef.getChatTexts().length;
-                        int lastIndex = Rnd.nextInt(maxIndex);
-
-                        String creatureName = chatNpc.getName();
-                        String text;
-
-                        if (!chatDef.isRandomChat())
-                        {
-                            lastIndex = chatDef._chatIndex + 1;
-
-                            if (lastIndex == maxIndex) lastIndex = 0;
-
-                            chatDef._chatIndex = lastIndex;
-                        }
-
-                        text = chatDef.getChatTexts()[lastIndex];
-
-                        if (text == null) return;
-
-                        if (!nearbyPlayers.isEmpty())
-                        {
-                            int randomPlayerIndex = Rnd.nextInt(nearbyPlayers.size());
-
-                            L2PcInstance randomPlayer = nearbyPlayers.get(randomPlayerIndex);
-
-                            final int winningCabal = SevenSigns.getInstance().getCabalHighestScore();
-                            int losingCabal = SevenSigns.CABAL_NULL;
-
-                            if (winningCabal == SevenSigns.CABAL_DAWN) losingCabal = SevenSigns.CABAL_DUSK;
-                            else if (winningCabal == SevenSigns.CABAL_DUSK)
-                                losingCabal = SevenSigns.CABAL_DAWN;
-
-                            if (text.indexOf("%player_random%") > -1)
-                                text = text.replaceAll("%player_random%", randomPlayer.getName());
-
-                            if (text.indexOf("%player_cabal_winner%") > -1)
-                            {
-                                for (L2PcInstance nearbyPlayer : nearbyPlayers)
-                                {
-                                    if (SevenSigns.getInstance().getPlayerCabal(nearbyPlayer) == winningCabal)
-                                    {
-                                        text = text.replaceAll("%player_cabal_winner%",
-                                                               nearbyPlayer.getName());
-                                        break;
-                                    }
-                                }
-                            }
-
-                            if (text.indexOf("%player_cabal_loser%") > -1)
-                            {
-                                for (L2PcInstance nearbyPlayer : nearbyPlayers)
-                                {
-                                    if (SevenSigns.getInstance().getPlayerCabal(nearbyPlayer) == losingCabal)
-                                    {
-                                        text = text.replaceAll("%player_cabal_loser%",
-                                                               nearbyPlayer.getName());
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-
-                        if (text == null) return;
-
-                        if (text.contains("%player_cabal_loser%")
-                            || text.contains("%player_cabal_winner%")
-                            || text.contains("%player_random%")) return;
-
-                        CreatureSay cs = new CreatureSay(chatNpc.getObjectId(), Say2.ALL, creatureName, text);
-
-                        for (L2PcInstance nearbyPlayer : nearbyPlayers)
-                            nearbyPlayer.sendPacket(cs);
-                        for (L2PcInstance nearbyGM : nearbyGMs)
-                            nearbyGM.sendPacket(cs);
-
-                        if (Config.DEBUG)
-                            _log.fine("AutoChatHandler: Chat propogation for object ID "
-                                + chatNpc.getObjectId() + " (" + creatureName + ") with text '" + text
-                                + "' sent to " + nearbyPlayers.size() + " nearby players.");
-                    }
-                    catch (Exception e)
-                    {
-                        e.printStackTrace();
-                        return;
-                    }
-                }
-            }
-        }
-    }
+	
+	public static AutoChatHandler getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	public int size()
+	{
+		return _registeredChats.size();
+	}
+	
+	/**
+	 * Registers a globally active auto chat for ALL instances of the given NPC ID.
+	 * <BR>
+	 * Returns the associated auto chat instance.
+	 *
+	 * @param int npcId
+	 * @param String[] chatTexts
+	 * @param int chatDelay (-1 = default delay)
+	 * @return AutoChatInstance chatInst
+	 */
+	public AutoChatInstance registerGlobalChat(int npcId, String[] chatTexts, long chatDelay)
+	{
+		return registerChat(npcId, null, chatTexts, chatDelay);
+	}
+	
+	/**
+	 * Registers a NON globally-active auto chat for the given NPC instance, and adds to the currently
+	 * assigned chat instance for this NPC ID, otherwise creates a new instance if
+	 * a previous one is not found.
+	 * <BR>
+	 * Returns the associated auto chat instance.
+	 *
+	 * @param L2Npc npcInst
+	 * @param String[] chatTexts
+	 * @param int chatDelay (-1 = default delay)
+	 * @return AutoChatInstance chatInst
+	 */
+	public AutoChatInstance registerChat(L2Npc npcInst, String[] chatTexts, long chatDelay)
+	{
+		return registerChat(npcInst.getNpcId(), npcInst, chatTexts, chatDelay);
+	}
+	
+	private final AutoChatInstance registerChat(int npcId, L2Npc npcInst, String[] chatTexts, long chatDelay)
+	{
+		AutoChatInstance chatInst = null;
+		
+		if (chatDelay < 0)
+			chatDelay = DEFAULT_CHAT_DELAY;
+		
+		if (_registeredChats.containsKey(npcId))
+			chatInst = _registeredChats.get(npcId);
+		else
+			chatInst = new AutoChatInstance(npcId, chatTexts, chatDelay, (npcInst == null));
+		
+		if (npcInst != null)
+			chatInst.addChatDefinition(npcInst);
+		
+		_registeredChats.put(npcId, chatInst);
+		
+		return chatInst;
+	}
+	
+	/**
+	 * Removes and cancels ALL auto chat definition for the given NPC ID,
+	 * and removes its chat instance if it exists.
+	 *
+	 * @param int npcId
+	 * @return boolean removedSuccessfully
+	 */
+	public boolean removeChat(int npcId)
+	{
+		AutoChatInstance chatInst = _registeredChats.get(npcId);
+		return removeChat(chatInst);
+	}
+	
+	/**
+	 * Removes and cancels ALL auto chats for the given chat instance.
+	 *
+	 * @param AutoChatInstance chatInst
+	 * @return boolean removedSuccessfully
+	 */
+	public boolean removeChat(AutoChatInstance chatInst)
+	{
+		if (chatInst == null)
+			return false;
+		
+		_registeredChats.remove(chatInst.getNPCId());
+		chatInst.setActive(false);
+		
+		if (Config.DEBUG)
+			_log.config("AutoChatHandler: Removed auto chat for NPC ID " + chatInst.getNPCId());
+		
+		return true;
+	}
+	
+	/**
+	 * Returns the associated auto chat instance either by the given NPC ID
+	 * or object ID.
+	 *
+	 * @param int id
+	 * @param boolean byObjectId
+	 * @return AutoChatInstance chatInst
+	 */
+	public AutoChatInstance getAutoChatInstance(int id, boolean byObjectId)
+	{
+		if (!byObjectId)
+			return _registeredChats.get(id);
+		else
+			for (AutoChatInstance chatInst : _registeredChats.values())
+				if (chatInst.getChatDefinition(id) != null)
+					return chatInst;
+		
+		return null;
+	}
+	
+	/**
+	 * Sets the active state of all auto chat instances to that specified,
+	 * and cancels the scheduled chat task if necessary.
+	 *
+	 * @param boolean isActive
+	 */
+	public void setAutoChatActive(boolean isActive)
+	{
+		for (AutoChatInstance chatInst : _registeredChats.values())
+			chatInst.setActive(isActive);
+	}
+	
+	/**
+	 * Used in conjunction with a SpawnListener, this method is called every time
+	 * an NPC is spawned in the world.
+	 * <BR><BR>
+	 * If an auto chat instance is set to be "global", all instances matching the registered
+	 * NPC ID will be added to that chat instance.
+	 */
+	public void npcSpawned(L2Npc npc)
+	{
+		synchronized (_registeredChats)
+		{
+			if (npc == null)
+				return;
+			
+			int npcId = npc.getNpcId();
+			
+			if (_registeredChats.containsKey(npcId))
+			{
+				AutoChatInstance chatInst = _registeredChats.get(npcId);
+				
+				if (chatInst != null && chatInst.isGlobal())
+					chatInst.addChatDefinition(npc);
+			}
+		}
+	}
+	
+	/**
+	 * Auto Chat Instance
+	 * <BR><BR>
+	 * Manages the auto chat instances for a specific registered NPC ID.
+	 *
+	 * @author Tempy
+	 */
+	public class AutoChatInstance
+	{
+		protected int _npcId;
+		private long _defaultDelay = DEFAULT_CHAT_DELAY;
+		private String[] _defaultTexts;
+		private boolean _defaultRandom = false;
+		
+		private boolean _globalChat = false;
+		private boolean _isActive;
+		
+		private Map<Integer, AutoChatDefinition> _chatDefinitions = new FastMap<Integer, AutoChatDefinition>();
+		protected ScheduledFuture<?> _chatTask;
+		
+		protected AutoChatInstance(int npcId, String[] chatTexts, long chatDelay, boolean isGlobal)
+		{
+			_defaultTexts = chatTexts;
+			_npcId = npcId;
+			_defaultDelay = chatDelay;
+			_globalChat = isGlobal;
+			
+			if (Config.DEBUG)
+				_log.config("AutoChatHandler: Registered auto chat for NPC ID " + _npcId + " (Global Chat = " + _globalChat + ").");
+			
+			setActive(true);
+		}
+		
+		protected AutoChatDefinition getChatDefinition(int objectId)
+		{
+			return _chatDefinitions.get(objectId);
+		}
+		
+		protected AutoChatDefinition[] getChatDefinitions()
+		{
+			return _chatDefinitions.values().toArray(new AutoChatDefinition[_chatDefinitions.values().size()]);
+		}
+		
+		/**
+		 * Defines an auto chat for an instance matching this auto chat instance's registered NPC ID,
+		 * and launches the scheduled chat task.
+		 * <BR>
+		 * Returns the object ID for the NPC instance, with which to refer
+		 * to the created chat definition.
+		 * <BR>
+		 * <B>Note</B>: Uses pre-defined default values for texts and chat delays from the chat instance.
+		 *
+		 * @param L2Npc npcInst
+		 * @return int objectId
+		 */
+		public int addChatDefinition(L2Npc npcInst)
+		{
+			return addChatDefinition(npcInst, null, 0);
+		}
+		
+		/**
+		 * Defines an auto chat for an instance matching this auto chat instance's registered NPC ID,
+		 * and launches the scheduled chat task.
+		 * <BR>
+		 * Returns the object ID for the NPC instance, with which to refer
+		 * to the created chat definition.
+		 *
+		 * @param L2Npc npcInst
+		 * @param String[] chatTexts
+		 * @param int chatDelay
+		 * @return int objectId
+		 */
+		public int addChatDefinition(L2Npc npcInst, String[] chatTexts, long chatDelay)
+		{
+			int objectId = npcInst.getObjectId();
+			AutoChatDefinition chatDef = new AutoChatDefinition(this, npcInst, chatTexts, chatDelay);
+			if (npcInst instanceof L2SiegeGuardInstance)
+				chatDef.setRandomChat(true);
+			_chatDefinitions.put(objectId, chatDef);
+			return objectId;
+		}
+		
+		/**
+		 * Removes a chat definition specified by the given object ID.
+		 *
+		 * @param int objectId
+		 * @return boolean removedSuccessfully
+		 */
+		public boolean removeChatDefinition(int objectId)
+		{
+			if (!_chatDefinitions.containsKey(objectId))
+				return false;
+			
+			AutoChatDefinition chatDefinition = _chatDefinitions.get(objectId);
+			chatDefinition.setActive(false);
+			
+			_chatDefinitions.remove(objectId);
+			
+			return true;
+		}
+		
+		/**
+		 * Tests if this auto chat instance is active.
+		 *
+		 * @return boolean isActive
+		 */
+		public boolean isActive()
+		{
+			return _isActive;
+		}
+		
+		/**
+		 * Tests if this auto chat instance applies to
+		 * ALL currently spawned instances of the registered NPC ID.
+		 *
+		 * @return boolean isGlobal
+		 */
+		public boolean isGlobal()
+		{
+			return _globalChat;
+		}
+		
+		/**
+		 * Tests if random order is the DEFAULT for new chat definitions.
+		 *
+		 * @return boolean isRandom
+		 */
+		public boolean isDefaultRandom()
+		{
+			return _defaultRandom;
+		}
+		
+		/**
+		 * Tests if the auto chat definition given by its object ID is set to be random.
+		 *
+		 * @return boolean isRandom
+		 */
+		public boolean isRandomChat(int objectId)
+		{
+			if (!_chatDefinitions.containsKey(objectId))
+				return false;
+			
+			return _chatDefinitions.get(objectId).isRandomChat();
+		}
+		
+		/**
+		 * Returns the ID of the NPC type managed by this auto chat instance.
+		 *
+		 * @return int npcId
+		 */
+		public int getNPCId()
+		{
+			return _npcId;
+		}
+		
+		/**
+		 * Returns the number of auto chat definitions stored for this instance.
+		 *
+		 * @return int definitionCount
+		 */
+		public int getDefinitionCount()
+		{
+			return _chatDefinitions.size();
+		}
+		
+		/**
+		 * Returns a list of all NPC instances handled by this auto chat instance.
+		 *
+		 * @return L2NpcInstance[] npcInsts
+		 */
+		public L2Npc[] getNPCInstanceList()
+		{
+			List<L2Npc> npcInsts = new FastList<L2Npc>();
+			
+			for (AutoChatDefinition chatDefinition : _chatDefinitions.values())
+				npcInsts.add(chatDefinition._npcInstance);
+			
+			return npcInsts.toArray(new L2Npc[npcInsts.size()]);
+		}
+		
+		/**
+		 * A series of methods used to get and set default values for new chat definitions.
+		 */
+		public long getDefaultDelay()
+		{
+			return _defaultDelay;
+		}
+		
+		public String[] getDefaultTexts()
+		{
+			return _defaultTexts;
+		}
+		
+		public void setDefaultChatDelay(long delayValue)
+		{
+			_defaultDelay = delayValue;
+		}
+		
+		public void setDefaultChatTexts(String[] textsValue)
+		{
+			_defaultTexts = textsValue;
+		}
+		
+		public void setDefaultRandom(boolean randValue)
+		{
+			_defaultRandom = randValue;
+		}
+		
+		/**
+		 * Sets a specific chat delay for the specified auto chat definition given by its object ID.
+		 *
+		 * @param int objectId
+		 * @param long delayValue
+		 */
+		public void setChatDelay(int objectId, long delayValue)
+		{
+			AutoChatDefinition chatDef = getChatDefinition(objectId);
+			
+			if (chatDef != null)
+				chatDef.setChatDelay(delayValue);
+		}
+		
+		/**
+		 * Sets a specific set of chat texts for the specified auto chat definition given by its object ID.
+		 *
+		 * @param int objectId
+		 * @param String[] textsValue
+		 */
+		public void setChatTexts(int objectId, String[] textsValue)
+		{
+			AutoChatDefinition chatDef = getChatDefinition(objectId);
+			
+			if (chatDef != null)
+				chatDef.setChatTexts(textsValue);
+		}
+		
+		/**
+		 * Sets specifically to use random chat order for the auto chat definition given by its object ID.
+		 *
+		 * @param int objectId
+		 * @param boolean randValue
+		 */
+		public void setRandomChat(int objectId, boolean randValue)
+		{
+			AutoChatDefinition chatDef = getChatDefinition(objectId);
+			
+			if (chatDef != null)
+				chatDef.setRandomChat(randValue);
+		}
+		
+		/**
+		 * Sets the activity of ALL auto chat definitions handled by this chat instance.
+		 *
+		 * @param boolean isActive
+		 */
+		public void setActive(boolean activeValue)
+		{
+			if (_isActive == activeValue)
+				return;
+			
+			_isActive = activeValue;
+			
+			if (!isGlobal())
+			{
+				for (AutoChatDefinition chatDefinition : _chatDefinitions.values())
+					chatDefinition.setActive(activeValue);
+				
+				return;
+			}
+			
+			if (isActive())
+			{
+				AutoChatRunner acr = new AutoChatRunner(_npcId, -1);
+				_chatTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(acr, _defaultDelay, _defaultDelay);
+			}
+			else
+			{
+				_chatTask.cancel(false);
+			}
+		}
+		
+		/**
+		 * Auto Chat Definition
+		 * <BR><BR>
+		 * Stores information about specific chat data for an instance of the NPC ID
+		 * specified by the containing auto chat instance.
+		 * <BR>
+		 * Each NPC instance of this type should be stored in a subsequent AutoChatDefinition class.
+		 *
+		 * @author Tempy
+		 */
+		private class AutoChatDefinition
+		{
+			protected int _chatIndex = 0;
+			protected L2Npc _npcInstance;
+			
+			protected AutoChatInstance _chatInstance;
+			
+			private long _chatDelay = 0;
+			private String[] _chatTexts = null;
+			private boolean _isActiveDefinition;
+			private boolean _randomChat;
+			
+			protected AutoChatDefinition(AutoChatInstance chatInst, L2Npc npcInst, String[] chatTexts, long chatDelay)
+			{
+				_npcInstance = npcInst;
+				
+				_chatInstance = chatInst;
+				_randomChat = chatInst.isDefaultRandom();
+				
+				_chatDelay = chatDelay;
+				_chatTexts = chatTexts;
+				
+				if (Config.DEBUG)
+					_log.info("AutoChatHandler: Chat definition added for NPC ID " + _npcInstance.getNpcId() + " (Object ID = "
+							+ _npcInstance.getObjectId() + ").");
+				
+				// If global chat isn't enabled for the parent instance,
+				// then handle the chat task locally.
+				if (!chatInst.isGlobal())
+					setActive(true);
+			}
+			
+			protected AutoChatDefinition(AutoChatInstance chatInst, L2Npc npcInst)
+			{
+				this(chatInst, npcInst, null, -1);
+			}
+			
+			protected String[] getChatTexts()
+			{
+				if (_chatTexts != null)
+					return _chatTexts;
+				else
+					return _chatInstance.getDefaultTexts();
+			}
+			
+			private long getChatDelay()
+			{
+				if (_chatDelay > 0)
+					return _chatDelay;
+				else
+					return _chatInstance.getDefaultDelay();
+			}
+			
+			private boolean isActive()
+			{
+				return _isActiveDefinition;
+			}
+			
+			boolean isRandomChat()
+			{
+				return _randomChat;
+			}
+			
+			void setRandomChat(boolean randValue)
+			{
+				_randomChat = randValue;
+			}
+			
+			void setChatDelay(long delayValue)
+			{
+				_chatDelay = delayValue;
+			}
+			
+			void setChatTexts(String[] textsValue)
+			{
+				_chatTexts = textsValue;
+			}
+			
+			void setActive(boolean activeValue)
+			{
+				if (isActive() == activeValue)
+					return;
+				
+				if (activeValue)
+				{
+					AutoChatRunner acr = new AutoChatRunner(_npcId, _npcInstance.getObjectId());
+					if (getChatDelay() == 0)
+						// Schedule it set to 5Ms, isn't error, if use 0 sometine
+						// chatDefinition return null in AutoChatRunner
+						_chatTask = ThreadPoolManager.getInstance().scheduleGeneral(acr, 5);
+					else
+						_chatTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(acr, getChatDelay(), getChatDelay());
+				}
+				else
+				{
+					_chatTask.cancel(false);
+				}
+				
+				_isActiveDefinition = activeValue;
+			}
+		}
+		
+		/**
+		 * Auto Chat Runner
+		 * <BR><BR>
+		 * Represents the auto chat scheduled task for each chat instance.
+		 *
+		 * @author Tempy
+		 */
+		private class AutoChatRunner implements Runnable
+		{
+			private int _runnerNpcId;
+			private int _objectId;
+			
+			protected AutoChatRunner(int pNpcId, int pObjectId)
+			{
+				_runnerNpcId = pNpcId;
+				_objectId = pObjectId;
+			}
+			
+			public synchronized void run()
+			{
+				AutoChatInstance chatInst = _registeredChats.get(_runnerNpcId);
+				AutoChatDefinition[] chatDefinitions;
+				
+				if (chatInst.isGlobal())
+				{
+					chatDefinitions = chatInst.getChatDefinitions();
+				}
+				else
+				{
+					AutoChatDefinition chatDef = chatInst.getChatDefinition(_objectId);
+					
+					if (chatDef == null)
+					{
+						_log.warning("AutoChatHandler: Auto chat definition is NULL for NPC ID " + _npcId + ".");
+						return;
+					}
+					
+					chatDefinitions = new AutoChatDefinition[] { chatDef };
+				}
+				
+				if (Config.DEBUG)
+					_log.info("AutoChatHandler: Running auto chat for " + chatDefinitions.length + " instances of NPC ID " + _npcId + "."
+							+ " (Global Chat = " + chatInst.isGlobal() + ")");
+				
+				for (AutoChatDefinition chatDef : chatDefinitions)
+				{
+					try
+					{
+						L2Npc chatNpc = chatDef._npcInstance;
+						List<L2PcInstance> nearbyPlayers = new FastList<L2PcInstance>();
+						List<L2PcInstance> nearbyGMs = new FastList<L2PcInstance>();
+						
+						for (L2Character player : chatNpc.getKnownList().getKnownCharactersInRadius(1500))
+						{
+							if (!(player instanceof L2PcInstance))
+								continue;
+							
+							if (((L2PcInstance) player).isGM())
+								nearbyGMs.add((L2PcInstance) player);
+							else
+								nearbyPlayers.add((L2PcInstance) player);
+						}
+						
+						int maxIndex = chatDef.getChatTexts().length;
+						int lastIndex = Rnd.nextInt(maxIndex);
+						
+						String creatureName = chatNpc.getName();
+						String text;
+						
+						if (!chatDef.isRandomChat())
+						{
+							lastIndex = chatDef._chatIndex + 1;
+							
+							if (lastIndex == maxIndex)
+								lastIndex = 0;
+							
+							chatDef._chatIndex = lastIndex;
+						}
+						
+						text = chatDef.getChatTexts()[lastIndex];
+						
+						if (text == null)
+							return;
+						
+						if (!nearbyPlayers.isEmpty())
+						{
+							int randomPlayerIndex = Rnd.nextInt(nearbyPlayers.size());
+							
+							L2PcInstance randomPlayer = nearbyPlayers.get(randomPlayerIndex);
+							
+							final int winningCabal = SevenSigns.getInstance().getCabalHighestScore();
+							int losingCabal = SevenSigns.CABAL_NULL;
+							
+							if (winningCabal == SevenSigns.CABAL_DAWN)
+								losingCabal = SevenSigns.CABAL_DUSK;
+							else if (winningCabal == SevenSigns.CABAL_DUSK)
+								losingCabal = SevenSigns.CABAL_DAWN;
+							
+							if (text.indexOf("%player_random%") > -1)
+								text = text.replaceAll("%player_random%", randomPlayer.getName());
+							
+							if (text.indexOf("%player_cabal_winner%") > -1)
+							{
+								for (L2PcInstance nearbyPlayer : nearbyPlayers)
+								{
+									if (SevenSigns.getInstance().getPlayerCabal(nearbyPlayer) == winningCabal)
+									{
+										text = text.replaceAll("%player_cabal_winner%", nearbyPlayer.getName());
+										break;
+									}
+								}
+							}
+							
+							if (text.indexOf("%player_cabal_loser%") > -1)
+							{
+								for (L2PcInstance nearbyPlayer : nearbyPlayers)
+								{
+									if (SevenSigns.getInstance().getPlayerCabal(nearbyPlayer) == losingCabal)
+									{
+										text = text.replaceAll("%player_cabal_loser%", nearbyPlayer.getName());
+										break;
+									}
+								}
+							}
+						}
+						
+						if (text == null)
+							return;
+						
+						if (text.contains("%player_cabal_loser%") || text.contains("%player_cabal_winner%")
+								|| text.contains("%player_random%"))
+							return;
+						
+						CreatureSay cs = new CreatureSay(chatNpc.getObjectId(), Say2.ALL, creatureName, text);
+						
+						for (L2PcInstance nearbyPlayer : nearbyPlayers)
+							nearbyPlayer.sendPacket(cs);
+						for (L2PcInstance nearbyGM : nearbyGMs)
+							nearbyGM.sendPacket(cs);
+						
+						if (Config.DEBUG)
+							_log.fine("AutoChatHandler: Chat propogation for object ID " + chatNpc.getObjectId() + " (" + creatureName
+									+ ") with text '" + text + "' sent to " + nearbyPlayers.size() + " nearby players.");
+					}
+					catch (Exception e)
+					{
+						e.printStackTrace();
+						return;
+					}
+				}
+			}
+		}
+	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AutoChatHandler _instance = new AutoChatHandler();
+	}
 }

+ 191 - 219
L2_GameServer/java/net/sf/l2j/gameserver/model/AutoSpawnHandler.java

@@ -66,39 +66,34 @@ import net.sf.l2j.util.Rnd;
 public class AutoSpawnHandler
 {
 	protected static final Logger _log = Logger.getLogger(AutoSpawnHandler.class.getName());
-
-	private static AutoSpawnHandler _instance;
-
+	
 	private static final int DEFAULT_INITIAL_SPAWN = 30000; // 30 seconds after registration
 	private static final int DEFAULT_RESPAWN = 3600000; // 1 hour in millisecs
 	private static final int DEFAULT_DESPAWN = 3600000; // 1 hour in millisecs
-
+	
 	protected Map<Integer, AutoSpawnInstance> _registeredSpawns;
 	protected Map<Integer, ScheduledFuture<?>> _runningSpawns;
-
+	
 	protected boolean _activeState = true;
-
+	
 	private AutoSpawnHandler()
 	{
 		_registeredSpawns = new FastMap<Integer, AutoSpawnInstance>();
 		_runningSpawns = new FastMap<Integer, ScheduledFuture<?>>();
-
+		
 		restoreSpawnData();
 	}
-
+	
 	public static AutoSpawnHandler getInstance()
 	{
-		if (_instance == null)
-			_instance = new AutoSpawnHandler();
-
-		return _instance;
+		return SingletonHolder._instance;
 	}
-
+	
 	public final int size()
 	{
 		return _registeredSpawns.size();
 	}
-
+	
 	public void reload()
 	{
 		// stop all timers
@@ -126,116 +121,107 @@ public class AutoSpawnHandler
 	{
 		int numLoaded = 0;
 		Connection con = null;
-
+		
 		try
 		{
 			PreparedStatement statement = null;
 			PreparedStatement statement2 = null;
 			ResultSet rs = null;
 			ResultSet rs2 = null;
-
+			
 			con = L2DatabaseFactory.getInstance().getConnection();
-
+			
 			// Restore spawn group data, then the location data.
 			statement = con.prepareStatement("SELECT * FROM random_spawn ORDER BY groupId ASC");
 			rs = statement.executeQuery();
-
+			
 			while (rs.next())
 			{
 				// Register random spawn group, set various options on the
 				// created spawn instance.
-				AutoSpawnInstance spawnInst = registerSpawn(rs.getInt("npcId"),	rs.getInt("initialDelay"),
-						rs.getInt("respawnDelay"), rs.getInt("despawnDelay"));
-
+				AutoSpawnInstance spawnInst = registerSpawn(rs.getInt("npcId"), rs.getInt("initialDelay"), rs.getInt("respawnDelay"), rs.getInt("despawnDelay"));
+				
 				spawnInst.setSpawnCount(rs.getInt("count"));
 				spawnInst.setBroadcast(rs.getBoolean("broadcastSpawn"));
 				spawnInst.setRandomSpawn(rs.getBoolean("randomSpawn"));
 				numLoaded++;
-
+				
 				// Restore the spawn locations for this spawn group/instance.
 				statement2 = con.prepareStatement("SELECT * FROM random_spawn_loc WHERE groupId=?");
 				statement2.setInt(1, rs.getInt("groupId"));
 				rs2 = statement2.executeQuery();
-
+				
 				while (rs2.next())
 				{
 					// Add each location to the spawn group/instance.
-					spawnInst.addSpawnLocation(rs2.getInt("x"),
-							rs2.getInt("y"), rs2.getInt("z"),
-							rs2.getInt("heading"));
+					spawnInst.addSpawnLocation(rs2.getInt("x"), rs2.getInt("y"), rs2.getInt("z"), rs2.getInt("heading"));
 				}
-
+				
 				statement2.close();
 			}
-
+			
 			statement.close();
-
+			
 			if (Config.DEBUG)
-				_log.config("AutoSpawnHandler: Loaded " + numLoaded
-						+ " spawn group(s) from the database.");
-		} catch (Exception e)
+				_log.config("AutoSpawnHandler: Loaded " + numLoaded + " spawn group(s) from the database.");
+		}
+		catch (Exception e)
 		{
-			_log.warning("AutoSpawnHandler: Could not restore spawn data: "
-							+ e);
-		} finally
+			_log.warning("AutoSpawnHandler: Could not restore spawn data: " + e);
+		}
+		finally
 		{
 			try
 			{
 				con.close();
-			} catch (Exception e)
+			}
+			catch (Exception e)
 			{
 			}
 		}
 	}
-
+	
 	/**
 	 * Registers a spawn with the given parameters with the spawner, and marks
 	 * it as active. Returns a AutoSpawnInstance containing info about the
 	 * spawn.
 	 *
-	 * @param int
-	 *            npcId
-	 * @param int[][]
-	 *            spawnPoints
-	 * @param int
-	 *            initialDelay (If < 0 = default value)
-	 * @param int
-	 *            respawnDelay (If < 0 = default value)
-	 * @param int
-	 *            despawnDelay (If < 0 = default value or if = 0, function
-	 *            disabled)
+	 * @param int npcId
+	 * @param int[][] spawnPoints
+	 * @param int initialDelay (If < 0 = default value)
+	 * @param int respawnDelay (If < 0 = default value)
+	 * @param int despawnDelay (If < 0 = default value or if = 0, function disabled)
 	 * @return AutoSpawnInstance spawnInst
 	 */
-	public AutoSpawnInstance registerSpawn(int npcId, int[][] spawnPoints, int initialDelay, int respawnDelay,
-			int despawnDelay)
+	public AutoSpawnInstance registerSpawn(int npcId, int[][] spawnPoints, int initialDelay, int respawnDelay, int despawnDelay)
 	{
 		if (initialDelay < 0)
 			initialDelay = DEFAULT_INITIAL_SPAWN;
-
+		
 		if (respawnDelay < 0)
 			respawnDelay = DEFAULT_RESPAWN;
-
+		
 		if (despawnDelay < 0)
 			despawnDelay = DEFAULT_DESPAWN;
-
-		AutoSpawnInstance newSpawn = new AutoSpawnInstance(npcId, initialDelay,	respawnDelay, despawnDelay);
-
+		
+		AutoSpawnInstance newSpawn = new AutoSpawnInstance(npcId, initialDelay, respawnDelay, despawnDelay);
+		
 		if (spawnPoints != null)
 			for (int[] spawnPoint : spawnPoints)
 				newSpawn.addSpawnLocation(spawnPoint);
-
+		
 		int newId = IdFactory.getInstance().getNextId();
 		newSpawn._objectId = newId;
 		_registeredSpawns.put(newId, newSpawn);
-
+		
 		setSpawnActive(newSpawn, true);
-
+		
 		if (Config.DEBUG)
-			_log.config("AutoSpawnHandler: Registered auto spawn for NPC ID "+ npcId + " (Object ID = " + newId + ").");
-
+			_log.config("AutoSpawnHandler: Registered auto spawn for NPC ID " + npcId + " (Object ID = " + newId + ").");
+		
 		return newSpawn;
 	}
-
+	
 	/**
 	 * Registers a spawn with the given parameters with the spawner, and marks
 	 * it as active. Returns a AutoSpawnInstance containing info about the
@@ -243,167 +229,153 @@ public class AutoSpawnHandler
 	 * <B>Warning:</B> Spawn locations must be specified separately using
 	 * addSpawnLocation().
 	 *
-	 * @param int
-	 *            npcId
-	 * @param int
-	 *            initialDelay (If < 0 = default value)
-	 * @param int
-	 *            respawnDelay (If < 0 = default value)
-	 * @param int
-	 *            despawnDelay (If < 0 = default value or if = 0, function
-	 *            disabled)
+	 * @param int npcId
+	 * @param int initialDelay (If < 0 = default value)
+	 * @param int respawnDelay (If < 0 = default value)
+	 * @param int despawnDelay (If < 0 = default value or if = 0, function disabled)
 	 * @return AutoSpawnInstance spawnInst
 	 */
-	public AutoSpawnInstance registerSpawn(int npcId, int initialDelay,	int respawnDelay, int despawnDelay)
+	public AutoSpawnInstance registerSpawn(int npcId, int initialDelay, int respawnDelay, int despawnDelay)
 	{
 		return registerSpawn(npcId, null, initialDelay, respawnDelay, despawnDelay);
 	}
-
+	
 	/**
 	 * Remove a registered spawn from the list, specified by the given spawn
 	 * instance.
 	 *
-	 * @param AutoSpawnInstance
-	 *            spawnInst
+	 * @param AutoSpawnInstance spawnInst
 	 * @return boolean removedSuccessfully
 	 */
 	public boolean removeSpawn(AutoSpawnInstance spawnInst)
 	{
 		if (!isSpawnRegistered(spawnInst))
 			return false;
-
+		
 		try
 		{
 			// Try to remove from the list of registered spawns if it exists.
 			_registeredSpawns.remove(spawnInst.getNpcId());
-
+			
 			// Cancel the currently associated running scheduled task.
 			ScheduledFuture<?> respawnTask = _runningSpawns.remove(spawnInst._objectId);
 			respawnTask.cancel(false);
-
+			
 			if (Config.DEBUG)
-				_log.config("AutoSpawnHandler: Removed auto spawn for NPC ID "
-						+ spawnInst._npcId + " (Object ID = "
-						+ spawnInst._objectId + ").");
-		} catch (Exception e)
+				_log.config("AutoSpawnHandler: Removed auto spawn for NPC ID " + spawnInst._npcId + " (Object ID = " + spawnInst._objectId
+						+ ").");
+		}
+		catch (Exception e)
 		{
-			_log.warning("AutoSpawnHandler: Could not auto spawn for NPC ID "
-					+ spawnInst._npcId + " (Object ID = " + spawnInst._objectId
+			_log.warning("AutoSpawnHandler: Could not auto spawn for NPC ID " + spawnInst._npcId + " (Object ID = " + spawnInst._objectId
 					+ "): " + e);
 			return false;
 		}
-
+		
 		return true;
 	}
-
+	
 	/**
 	 * Remove a registered spawn from the list, specified by the given spawn
 	 * object ID.
 	 *
-	 * @param int
-	 *            objectId
+	 * @param int objectId
 	 * @return boolean removedSuccessfully
 	 */
 	public void removeSpawn(int objectId)
 	{
 		removeSpawn(_registeredSpawns.get(objectId));
 	}
-
+	
 	/**
 	 * Sets the active state of the specified spawn.
 	 *
-	 * @param AutoSpawnInstance
-	 *            spawnInst
-	 * @param boolean
-	 *            isActive
+	 * @param AutoSpawnInstance spawnInst
+	 * @param boolean isActive
 	 */
 	public void setSpawnActive(AutoSpawnInstance spawnInst, boolean isActive)
 	{
 		if (spawnInst == null)
 			return;
-
+		
 		int objectId = spawnInst._objectId;
-
+		
 		if (isSpawnRegistered(objectId))
 		{
 			ScheduledFuture<?> spawnTask = null;
-
+			
 			if (isActive)
 			{
 				AutoSpawner rs = new AutoSpawner(objectId);
-
+				
 				if (spawnInst._desDelay > 0)
-					spawnTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(rs,
-							spawnInst._initDelay, spawnInst._resDelay);
+					spawnTask = ThreadPoolManager.getInstance().scheduleEffectAtFixedRate(rs, spawnInst._initDelay, spawnInst._resDelay);
 				else
 					spawnTask = ThreadPoolManager.getInstance().scheduleEffect(rs, spawnInst._initDelay);
-
+				
 				_runningSpawns.put(objectId, spawnTask);
-			} else
+			}
+			else
 			{
 				AutoDespawner rd = new AutoDespawner(objectId);
 				spawnTask = _runningSpawns.remove(objectId);
-
+				
 				if (spawnTask != null)
 					spawnTask.cancel(false);
-
+				
 				ThreadPoolManager.getInstance().scheduleEffect(rd, 0);
 			}
-
+			
 			spawnInst.setSpawnActive(isActive);
 		}
 	}
-
+	
 	/**
 	 * Sets the active state of all auto spawn instances to that specified, and
 	 * cancels the scheduled spawn task if necessary.
 	 *
 	 * @param boolean
-	 *            isActive
+	 *			isActive
 	 */
 	public void setAllActive(boolean isActive)
 	{
 		if (_activeState == isActive)
 			return;
-
+		
 		for (AutoSpawnInstance spawnInst : _registeredSpawns.values())
 			setSpawnActive(spawnInst, isActive);
-
+		
 		_activeState = isActive;
 	}
-
+	
 	/**
 	 * Returns the number of milliseconds until the next occurrance of the given
 	 * spawn.
 	 *
-	 * @param AutoSpawnInstance
-	 *            spawnInst
-	 * @param long
-	 *            milliRemaining
+	 * @param AutoSpawnInstance spawnInst
+	 * @param long milliRemaining
 	 */
 	public final long getTimeToNextSpawn(AutoSpawnInstance spawnInst)
 	{
 		int objectId = spawnInst.getObjectId();
-
+		
 		if (!isSpawnRegistered(objectId))
 			return -1;
-
+		
 		return _runningSpawns.get(objectId).getDelay(TimeUnit.MILLISECONDS);
 	}
-
+	
 	/**
 	 * Attempts to return the AutoSpawnInstance associated with the given NPC or
 	 * Object ID type. <BR>
 	 * Note: If isObjectId == false, returns first instance for the specified
 	 * NPC ID.
 	 *
-	 * @param int
-	 *            id
-	 * @param boolean
-	 *            isObjectId
+	 * @param int id
+	 * @param boolean isObjectId
 	 * @return AutoSpawnInstance spawnInst
 	 */
-	public final AutoSpawnInstance getAutoSpawnInstance(int id,	boolean isObjectId)
+	public final AutoSpawnInstance getAutoSpawnInstance(int id, boolean isObjectId)
 	{
 		if (isObjectId)
 		{
@@ -418,42 +390,40 @@ public class AutoSpawnHandler
 		}
 		return null;
 	}
-
+	
 	public Map<Integer, AutoSpawnInstance> getAutoSpawnInstances(int npcId)
 	{
 		Map<Integer, AutoSpawnInstance> spawnInstList = new FastMap<Integer, AutoSpawnInstance>();
-
+		
 		for (AutoSpawnInstance spawnInst : _registeredSpawns.values())
 			if (spawnInst.getNpcId() == npcId)
 				spawnInstList.put(spawnInst.getObjectId(), spawnInst);
-
+		
 		return spawnInstList;
 	}
-
+	
 	/**
 	 * Tests if the specified object ID is assigned to an auto spawn.
 	 *
-	 * @param int
-	 *            objectId
+	 * @param int objectId
 	 * @return boolean isAssigned
 	 */
 	public final boolean isSpawnRegistered(int objectId)
 	{
 		return _registeredSpawns.containsKey(objectId);
 	}
-
+	
 	/**
 	 * Tests if the specified spawn instance is assigned to an auto spawn.
 	 *
-	 * @param AutoSpawnInstance
-	 *            spawnInst
+	 * @param AutoSpawnInstance spawnInst
 	 * @return boolean isAssigned
 	 */
 	public final boolean isSpawnRegistered(AutoSpawnInstance spawnInst)
 	{
 		return _registeredSpawns.containsValue(spawnInst);
 	}
-
+	
 	/**
 	 * AutoSpawner Class <BR>
 	 * <BR>
@@ -465,37 +435,36 @@ public class AutoSpawnHandler
 	private class AutoSpawner implements Runnable
 	{
 		private int _objectId;
-
+		
 		protected AutoSpawner(int objectId)
 		{
 			_objectId = objectId;
 		}
-
+		
 		public void run()
 		{
 			try
 			{
 				// Retrieve the required spawn instance for this spawn task.
 				AutoSpawnInstance spawnInst = _registeredSpawns.get(_objectId);
-
+				
 				// If the spawn is not scheduled to be active, cancel the spawn
 				// task.
 				if (!spawnInst.isSpawnActive())
 					return;
-
+				
 				Location[] locationList = spawnInst.getLocationList();
-
+				
 				// If there are no set co-ordinates, cancel the spawn task.
 				if (locationList.length == 0)
 				{
-					_log.info("AutoSpawnHandler: No location co-ords specified for spawn instance (Object ID = "
-							+ _objectId + ").");
+					_log.info("AutoSpawnHandler: No location co-ords specified for spawn instance (Object ID = " + _objectId + ").");
 					return;
 				}
-
+				
 				int locationCount = locationList.length;
 				int locationIndex = Rnd.nextInt(locationCount);
-
+				
 				/*
 				 * If random spawning is disabled, the spawn at the next set of
 				 * co-ordinates after the last. If the index is greater than the
@@ -504,29 +473,29 @@ public class AutoSpawnHandler
 				if (!spawnInst.isRandomSpawn())
 				{
 					locationIndex = spawnInst._lastLocIndex + 1;
-
+					
 					if (locationIndex == locationCount)
 						locationIndex = 0;
-
+					
 					spawnInst._lastLocIndex = locationIndex;
 				}
-
+				
 				// Set the X, Y and Z co-ordinates, where this spawn will take
 				// place.
 				final int x = locationList[locationIndex].getX();
 				final int y = locationList[locationIndex].getY();
 				final int z = locationList[locationIndex].getZ();
 				final int heading = locationList[locationIndex].getHeading();
-
+				
 				// Fetch the template for this NPC ID and create a new spawn.
 				L2NpcTemplate npcTemp = NpcTable.getInstance().getTemplate(spawnInst.getNpcId());
 				if (npcTemp == null)
 				{
-					_log.warning("Couldnt find NPC id" + spawnInst.getNpcId()+ " Try to update your DP");
+					_log.warning("Couldnt find NPC id" + spawnInst.getNpcId() + " Try to update your DP");
 					return;
 				}
 				L2Spawn newSpawn = new L2Spawn(npcTemp);
-
+				
 				newSpawn.setLocx(x);
 				newSpawn.setLocy(y);
 				newSpawn.setLocz(z);
@@ -537,65 +506,61 @@ public class AutoSpawnHandler
 				{
 					newSpawn.setRespawnDelay(spawnInst._resDelay);
 				}
-
+				
 				// Add the new spawn information to the spawn table, but do not
 				// store it.
 				SpawnTable.getInstance().addNewSpawn(newSpawn, false);
 				L2Npc npcInst = null;
-
+				
 				if (spawnInst._spawnCount == 1)
 				{
 					npcInst = newSpawn.doSpawn();
 					npcInst.setXYZ(npcInst.getX(), npcInst.getY(), npcInst.getZ());
 					spawnInst.addNpcInstance(npcInst);
-				} else
+				}
+				else
 				{
 					for (int i = 0; i < spawnInst._spawnCount; i++)
 					{
 						npcInst = newSpawn.doSpawn();
-
+						
 						// To prevent spawning of more than one NPC in the exact
 						// same spot,
 						// move it slightly by a small random offset.
-						npcInst.setXYZ(npcInst.getX() + Rnd.nextInt(50), npcInst.getY() + Rnd.nextInt(50),
-								npcInst.getZ());
-
+						npcInst.setXYZ(npcInst.getX() + Rnd.nextInt(50), npcInst.getY() + Rnd.nextInt(50), npcInst.getZ());
+						
 						// Add the NPC instance to the list of managed
 						// instances.
 						spawnInst.addNpcInstance(npcInst);
 					}
 				}
-
+				
 				String nearestTown = MapRegionTable.getInstance().getClosestTownName(npcInst);
-
+				
 				// Announce to all players that the spawn has taken place, with
 				// the nearest town location.
 				if (spawnInst.isBroadcasting())
-					Announcements.getInstance().announceToAll("The " + npcInst.getName() + " has spawned near "
-							+ nearestTown + "!");
-
+					Announcements.getInstance().announceToAll("The " + npcInst.getName() + " has spawned near " + nearestTown + "!");
+				
 				if (Config.DEBUG)
-					_log.info("AutoSpawnHandler: Spawned NPC ID "
-							+ spawnInst.getNpcId() + " at " + x + ", " + y
-							+ ", " + z + " (Near " + nearestTown + ") for "
-							+ (spawnInst.getRespawnDelay() / 60000)
-							+ " minute(s).");
-
+					_log.info("AutoSpawnHandler: Spawned NPC ID " + spawnInst.getNpcId() + " at " + x + ", " + y + ", " + z + " (Near "
+							+ nearestTown + ") for " + (spawnInst.getRespawnDelay() / 60000) + " minute(s).");
+				
 				// If there is no despawn time, do not create a despawn task.
 				if (spawnInst.getDespawnDelay() > 0)
 				{
 					AutoDespawner rd = new AutoDespawner(_objectId);
 					ThreadPoolManager.getInstance().scheduleAi(rd, spawnInst.getDespawnDelay() - 1000);
 				}
-			} catch (Exception e)
+			}
+			catch (Exception e)
 			{
-				_log.warning("AutoSpawnHandler: An error occurred while initializing spawn instance (Object ID = "
-								+ _objectId + "): " + e);
+				_log.warning("AutoSpawnHandler: An error occurred while initializing spawn instance (Object ID = " + _objectId + "): " + e);
 				e.printStackTrace();
 			}
 		}
 	}
-
+	
 	/**
 	 * AutoDespawner Class <BR>
 	 * <BR>
@@ -606,43 +571,43 @@ public class AutoSpawnHandler
 	private class AutoDespawner implements Runnable
 	{
 		private int _objectId;
-
+		
 		protected AutoDespawner(int objectId)
 		{
 			_objectId = objectId;
 		}
-
+		
 		public void run()
 		{
 			try
 			{
 				AutoSpawnInstance spawnInst = _registeredSpawns.get(_objectId);
-
+				
 				if (spawnInst == null)
 				{
-					_log.info("AutoSpawnHandler: No spawn registered for object ID = "+ _objectId + ".");
+					_log.info("AutoSpawnHandler: No spawn registered for object ID = " + _objectId + ".");
 					return;
 				}
-
+				
 				for (L2Npc npcInst : spawnInst.getNPCInstanceList())
 				{
 					if (npcInst == null)
 						continue;
-
+					
 					npcInst.deleteMe();
 					spawnInst.removeNpcInstance(npcInst);
-
+					
 					if (Config.DEBUG)
-						_log.info("AutoSpawnHandler: Spawns removed for spawn instance (Object ID = "+ _objectId + ").");
+						_log.info("AutoSpawnHandler: Spawns removed for spawn instance (Object ID = " + _objectId + ").");
 				}
-			} catch (Exception e)
+			}
+			catch (Exception e)
 			{
-				_log.warning("AutoSpawnHandler: An error occurred while despawning spawn (Object ID = "
-						+ _objectId + "): " + e);
+				_log.warning("AutoSpawnHandler: An error occurred while despawning spawn (Object ID = " + _objectId + "): " + e);
 			}
 		}
 	}
-
+	
 	/**
 	 * AutoSpawnInstance Class <BR>
 	 * <BR>
@@ -653,89 +618,89 @@ public class AutoSpawnHandler
 	public class AutoSpawnInstance
 	{
 		protected int _objectId;
-
+		
 		protected int _spawnIndex;
-
+		
 		protected int _npcId;
-
+		
 		protected int _initDelay;
-
+		
 		protected int _resDelay;
-
+		
 		protected int _desDelay;
-
+		
 		protected int _spawnCount = 1;
-
+		
 		protected int _lastLocIndex = -1;
-
+		
 		private List<L2Npc> _npcList = new FastList<L2Npc>();
-
+		
 		private List<Location> _locList = new FastList<Location>();
-
+		
 		private boolean _spawnActive;
-
+		
 		private boolean _randomSpawn = false;
-
+		
 		private boolean _broadcastAnnouncement = false;
-
-		protected AutoSpawnInstance(int npcId, int initDelay, int respawnDelay,	int despawnDelay)
+		
+		protected AutoSpawnInstance(int npcId, int initDelay, int respawnDelay, int despawnDelay)
 		{
 			_npcId = npcId;
 			_initDelay = initDelay;
 			_resDelay = respawnDelay;
 			_desDelay = despawnDelay;
 		}
-
+		
 		protected void setSpawnActive(boolean activeValue)
 		{
 			_spawnActive = activeValue;
 		}
-
+		
 		protected boolean addNpcInstance(L2Npc npcInst)
 		{
 			return _npcList.add(npcInst);
 		}
-
+		
 		protected boolean removeNpcInstance(L2Npc npcInst)
 		{
 			return _npcList.remove(npcInst);
 		}
-
+		
 		public int getObjectId()
 		{
 			return _objectId;
 		}
-
+		
 		public int getInitialDelay()
 		{
 			return _initDelay;
 		}
-
+		
 		public int getRespawnDelay()
 		{
 			return _resDelay;
 		}
-
+		
 		public int getDespawnDelay()
 		{
 			return _desDelay;
 		}
-
+		
 		public int getNpcId()
 		{
 			return _npcId;
 		}
-
+		
 		public int getSpawnCount()
 		{
 			return _spawnCount;
 		}
-
+		
 		public Location[] getLocationList()
 		{
 			return _locList.toArray(new Location[_locList.size()]);
 		}
-
+		
 		public L2Npc[] getNPCInstanceList()
 		{
 			L2Npc[] ret;
@@ -744,72 +709,79 @@ public class AutoSpawnHandler
 				ret = new L2Npc[_npcList.size()];
 				_npcList.toArray(ret);
 			}
-
+			
 			return ret;
 		}
-
+		
 		public L2Spawn[] getSpawns()
 		{
 			List<L2Spawn> npcSpawns = new FastList<L2Spawn>();
-
+			
 			for (L2Npc npcInst : _npcList)
 				npcSpawns.add(npcInst.getSpawn());
-
+			
 			return npcSpawns.toArray(new L2Spawn[npcSpawns.size()]);
 		}
-
+		
 		public void setSpawnCount(int spawnCount)
 		{
 			_spawnCount = spawnCount;
 		}
-
+		
 		public void setRandomSpawn(boolean randValue)
 		{
 			_randomSpawn = randValue;
 		}
-
+		
 		public void setBroadcast(boolean broadcastValue)
 		{
 			_broadcastAnnouncement = broadcastValue;
 		}
-
+		
 		public boolean isSpawnActive()
 		{
 			return _spawnActive;
 		}
-
+		
 		public boolean isRandomSpawn()
 		{
 			return _randomSpawn;
 		}
-
+		
 		public boolean isBroadcasting()
 		{
 			return _broadcastAnnouncement;
 		}
-
+		
 		public boolean addSpawnLocation(int x, int y, int z, int heading)
 		{
 			return _locList.add(new Location(x, y, z, heading));
 		}
-
+		
 		public boolean addSpawnLocation(int[] spawnLoc)
 		{
 			if (spawnLoc.length != 3)
 				return false;
-
+			
 			return addSpawnLocation(spawnLoc[0], spawnLoc[1], spawnLoc[2], -1);
 		}
-
+		
 		public Location removeSpawnLocation(int locIndex)
 		{
 			try
 			{
 				return _locList.remove(locIndex);
-			} catch (IndexOutOfBoundsException e)
+			}
+			catch (IndexOutOfBoundsException e)
 			{
 				return null;
 			}
 		}
 	}
+	
+	@SuppressWarnings("synthetic-access")
+	private static class SingletonHolder
+	{
+		protected static final AutoSpawnHandler _instance = new AutoSpawnHandler();
+	}
 }

Some files were not shown because too many files changed in this diff