Tous les collages #37822 Brut Modifier

fix for craft lag

public java v1 · immuable
#37822 ·publié 2006-01-21 15:29 UTC
corps du collage affiché
Index: C:/workspace/L2_GameServer/java/config/altsettings.properties===================================================================--- C:/workspace/L2_GameServer/java/config/altsettings.properties	(revision 2151)+++ C:/workspace/L2_GameServer/java/config/altsettings.properties	(working copy)@@ -20,6 +20,11 @@ # - players get EXP/SP for crafting AltGameCreation = False +# Alt game creation XP/SP based on mana+# new XP/SP reward system, calculation based on+# mana used to craft item+AltGameCreationByMana = False+ # Alternative skill learn rules: # - all classes can learn all skills # - skills of another class costs x2 SPIndex: C:/workspace/L2_GameServer/java/net/sf/l2j/Config.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/Config.java	(revision 2151)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/Config.java	(working copy)@@ -72,8 +72,11 @@          /** Thread pools size */     public static int THREAD_P_HIGH;+    public static int THREAD_P_MEDHIGH;     public static int THREAD_P_MED;     public static int THREAD_P_LOW;+    public static int THREAD_P_AI;+    public static int THREAD_P_CRAFT;              /** Auto-loot? */     public static boolean AUTO_LOOT;@@ -83,10 +86,16 @@      /** Global chat state */     public static String  DEFAULT_GLOBAL_CHAT;+         /** For test servers - evrybody has admin rights */     public static boolean EVERYBODY_HAS_ADMIN_RIGHTS;+     /** Alternative game crafting */     public static boolean ALT_GAME_CREATION;+    +    /** Reward XP/SP to crafter based on mana **/+    public static boolean ALT_GAME_CREATION_BY_MANA;+         /** Alternative game skill learning */     public static boolean ALT_GAME_SKILL_LEARN;     /** Cancel ATTACK/cast by hit */@@ -388,8 +397,10 @@          public static int      EXECUTOR_PRI_LOW;     public static int      EXECUTOR_PRI_MED;+    public static int      EXECUTOR_PRI_MEDHIGH;     public static int      EXECUTOR_PRI_HIGH;-+    public static int      EXECUTOR_PRI_AI;+    public static int      EXECUTOR_PRI_CRAFT;      	public static enum IdFactoryType     {@@ -583,8 +594,11 @@  	            AUTODELETE_INVALID_QUEST_DATA   = Boolean.valueOf(serverSettings.getProperty("AutoDeleteInvalidQuestData", "False")); 	            THREAD_P_HIGH                   = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeHigh", "4"));-	            THREAD_P_MED                    = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeMed", "10"));-	            THREAD_P_LOW                    = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeLow", "4"));+	            THREAD_P_MEDHIGH                = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeMedHigh","4"));+                THREAD_P_MED                    = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeMed",  "4"));+	            THREAD_P_LOW                    = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeLow",   "4"));+	            THREAD_P_AI                     = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeAi",    "4"));	            +	            THREAD_P_CRAFT                  = Integer.parseInt(serverSettings.getProperty("ThreadPoolSizeCraft", "4")); 	             	            MAXIMUM_ONLINE_USERS        = Integer.parseInt(serverSettings.getProperty("MaximumOnlineUsers", "100")); 	            @@ -617,7 +631,10 @@                                  EXECUTOR_PRI_LOW = Integer.parseInt(serverSettings.getProperty("ExecutorPriLow", "-1"));                 EXECUTOR_PRI_MED = Integer.parseInt(serverSettings.getProperty("ExecutorPriMed", "0"));-                EXECUTOR_PRI_HIGH = Integer.parseInt(serverSettings.getProperty("ExecutorPriHigh", "1"));+                EXECUTOR_PRI_MEDHIGH = Integer.parseInt(serverSettings.getProperty("ExecutorPriMedHigh", "1"));+                EXECUTOR_PRI_HIGH = Integer.parseInt(serverSettings.getProperty("ExecutorPriHigh", "2"));+                EXECUTOR_PRI_AI = Integer.parseInt(serverSettings.getProperty("ExecutorPriAi", "0"));+                EXECUTOR_PRI_CRAFT = Integer.parseInt(serverSettings.getProperty("ExecutorPriCraft", "0"));                 	        } 	        catch (Exception e) 	        {@@ -718,7 +735,7 @@ 	             	            STARTING_ADENA      = Integer.parseInt(otherSettings.getProperty("StartingAdena", "100")); 	            UNSTUCK_INTERVAL    = Integer.parseInt(otherSettings.getProperty("UnstuckInterval", "300"));-+	                             /* Player protection after teleport or login */                 PLAYER_SPAWN_PROTECTION = Integer.parseInt(otherSettings.getProperty("PlayerSpawnProtection", "0")); 	            @@ -787,25 +804,26 @@ 	            altSettings.load(is); 	            is.close(); 	            -	            ALT_GAME_TIREDNESS      = Boolean.parseBoolean(altSettings.getProperty("AltGameTiredness", "false"));-	            ALT_GAME_CREATION       = Boolean.parseBoolean(altSettings.getProperty("AltGameCreation", "false"));-	            ALT_GAME_SKILL_LEARN    = Boolean.parseBoolean(altSettings.getProperty("AltGameSkillLearn", "false"));-	            ALT_GAME_CANCEL_BOW     = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("bow") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");-	            ALT_GAME_CANCEL_CAST    = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("cast") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");-	            ALT_GAME_SHIELD_BLOCKS  = Boolean.parseBoolean(altSettings.getProperty("AltShieldBlocks", "false"));-	            ALT_GAME_DELEVEL        = Boolean.parseBoolean(altSettings.getProperty("Delevel", "true"));-	            ALT_GAME_MOB_ATTACK_AI  = Boolean.parseBoolean(altSettings.getProperty("AltGameMobAttackAI", "false"));-	            ALT_GAME_SKILL_FORMULAS = altSettings.getProperty("AltGameSkillFormulas", "none");-	            ALT_GAME_EXPONENT_XP    = Float.parseFloat(altSettings.getProperty("AltGameExponentXp", "0."));-	            ALT_GAME_EXPONENT_SP    = Float.parseFloat(altSettings.getProperty("AltGameExponentSp", "0."));-	            ALLOW_CLASS_MASTERS     = Boolean.valueOf(altSettings.getProperty("AllowClassMasters", "False"));-	            ALT_GAME_FREIGHTS       = Boolean.parseBoolean(altSettings.getProperty("AltGameFreights", "false"));-	            ALT_GAME_FREIGHT_PRICE  = Integer.parseInt(altSettings.getProperty("AltGameFreightPrice", "1000"));-	            ALT_GAME_SKILL_HIT_RATE = Float.parseFloat(altSettings.getProperty("AltGameSkillHitRate", "1."));-	            ENABLE_RATE_HP          = Boolean.parseBoolean(altSettings.getProperty("EnableRateHp", "false"));-	            IS_CRAFTING_ENABLED     = Boolean.parseBoolean(altSettings.getProperty("CraftingEnabled", "true"));-	            SP_BOOK_NEEDED          = Boolean.parseBoolean(altSettings.getProperty("SpBookNeeded", "true"));-	            AUTO_LOOT               = altSettings.getProperty("AutoLoot").equalsIgnoreCase("True");+	            ALT_GAME_TIREDNESS         = Boolean.parseBoolean(altSettings.getProperty("AltGameTiredness", "false"));+	            ALT_GAME_CREATION          = Boolean.parseBoolean(altSettings.getProperty("AltGameCreation", "false"));+                ALT_GAME_CREATION_BY_MANA  = Boolean.parseBoolean(altSettings.getProperty("AltGameCreationByMana", "false"));+	            ALT_GAME_SKILL_LEARN       = Boolean.parseBoolean(altSettings.getProperty("AltGameSkillLearn", "false"));+	            ALT_GAME_CANCEL_BOW        = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("bow") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");+	            ALT_GAME_CANCEL_CAST       = altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("cast") || altSettings.getProperty("AltGameCancelByHit", "Cast").equalsIgnoreCase("all");+	            ALT_GAME_SHIELD_BLOCKS     = Boolean.parseBoolean(altSettings.getProperty("AltShieldBlocks", "false"));+	            ALT_GAME_DELEVEL           = Boolean.parseBoolean(altSettings.getProperty("Delevel", "true"));+	            ALT_GAME_MOB_ATTACK_AI     = Boolean.parseBoolean(altSettings.getProperty("AltGameMobAttackAI", "false"));+	            ALT_GAME_SKILL_FORMULAS    = altSettings.getProperty("AltGameSkillFormulas", "none");+	            ALT_GAME_EXPONENT_XP       = Float.parseFloat(altSettings.getProperty("AltGameExponentXp", "0."));+	            ALT_GAME_EXPONENT_SP       = Float.parseFloat(altSettings.getProperty("AltGameExponentSp", "0."));+	            ALLOW_CLASS_MASTERS        = Boolean.valueOf(altSettings.getProperty("AllowClassMasters", "False"));+	            ALT_GAME_FREIGHTS          = Boolean.parseBoolean(altSettings.getProperty("AltGameFreights", "false"));+	            ALT_GAME_FREIGHT_PRICE     = Integer.parseInt(altSettings.getProperty("AltGameFreightPrice", "1000"));+	            ALT_GAME_SKILL_HIT_RATE    = Float.parseFloat(altSettings.getProperty("AltGameSkillHitRate", "1."));+	            ENABLE_RATE_HP             = Boolean.parseBoolean(altSettings.getProperty("EnableRateHp", "false"));+	            IS_CRAFTING_ENABLED        = Boolean.parseBoolean(altSettings.getProperty("CraftingEnabled", "true"));+	            SP_BOOK_NEEDED             = Boolean.parseBoolean(altSettings.getProperty("SpBookNeeded", "true"));+	            AUTO_LOOT                  = altSettings.getProperty("AutoLoot").equalsIgnoreCase("True");                 ALT_GAME_KARMA_PLAYER_CAN_BE_KILLED_IN_PEACEZONE    = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanBeKilledInPeaceZone", "false"));                 ALT_GAME_KARMA_PLAYER_CAN_SHOP                      = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanShop", "true"));                 ALT_GAME_KARMA_PLAYER_CAN_TELEPORT                  = Boolean.valueOf(altSettings.getProperty("AltKarmaPlayerCanTeleport", "true"));Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/SpawnTable.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/SpawnTable.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/SpawnTable.java	(working copy)@@ -53,7 +53,6 @@      private SpawnTable()     {-                 fillSpawnTable();     } @@ -90,6 +89,7 @@                     }                     else                     {+                        try {                         spawnDat = new L2Spawn(template1);                         spawnDat.setId(rset.getInt("id"));                         spawnDat.setAmount(rset.getInt("count"));@@ -106,10 +106,15 @@                                                  if (spawnDat.getId() > _highestId)                             _highestId = spawnDat.getId();-                    }+                        } catch (Exception e) +                        {+                          _log.warning("_npcSpawnCount: "+_npcSpawnCount + " _spawntable.size(): " + _spawntable.size()+ " spawnDat id: "+rset.getInt("id"));+                          _log.warning("SpawnTable: Data missing in NPC table for ID: " + rset.getInt("npc_templateid") + ".");+                        };+                   }                 }                 else {-                    _log.warning("SpawnTable: Data missing in NPC table for ID: " + rset.getInt("npc_templateid") + ".");+                    _log.warning("@@@@SpawnTable: Data missing in NPC table for ID: " + rset.getInt("npc_templateid") + ".");                 }             } @@ -119,7 +124,9 @@         catch (Exception e)         {             // problem with initializing spawn, go to next one-            _log.warning("SpawnTable: Spawn could not be initialized: " + e);+            _log.warning("####SpawnTable: Spawn could not be initialized: " + e);+            _log.warning("Spawntable problem details: ");+            _log.warning("_npcSpawnCount: "+_npcSpawnCount + " _spawntable.size(): " + _spawntable.size());         }         finally         {Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/SelectorThread.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/SelectorThread.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/SelectorThread.java	(working copy)@@ -146,7 +146,7 @@ 		this._hostname = hostname; 		this._port = port; 		this.setDaemon(true);-		this.setPriority(Thread.NORM_PRIORITY+1);+		this.setPriority(Thread.NORM_PRIORITY+2); 		// write buffers (HeapByteBuffer is much faster for our perposes) 		writeBuffers = new ByteBuffer[WRITE_BUF_HASH_SIZE]; 		for (int i=0; i < WRITE_BUF_HASH_SIZE; i++) {@@ -723,7 +723,7 @@             packetHistory.clear();             byteHistory.clear();             -            packetMonitor   = ClientScheduler.getInstance().scheduleLowAtFixedRate(+            packetMonitor   = ClientScheduler.getInstance().scheduleMedAtFixedRate(                 new Runnable()                 {                     public void run()Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/RequestRestartPoint.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/RequestRestartPoint.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/RequestRestartPoint.java	(working copy)@@ -67,16 +67,16 @@         {             try             {-                Location loc;-                if (requestedPointType == 2) // to castle-                    loc = MapRegionTable.getInstance().getTeleToLocation(activeChar, MapRegionTable.TeleportWhereType.Castle);-                else if (requestedPointType == 3) // to siege HQ-                    loc = MapRegionTable.getInstance().getTeleToLocation(activeChar, MapRegionTable.TeleportWhereType.SiegeFlag);-                else if (requestedPointType == 4 || // Fixed or-                        activeChar.isFestivalParticipant()) // Player is a festival participant-                    loc = new Location(activeChar.getX(), activeChar.getY(), activeChar.getZ()); // spawn them where they died-                else-                    loc = MapRegionTable.getInstance().getTeleToLocation(activeChar, MapRegionTable.TeleportWhereType.ClosestTown);+                    Location loc;+                    if (requestedPointType == 2) // to castle+                        loc = MapRegionTable.getInstance().getTeleToLocation(activeChar, MapRegionTable.TeleportWhereType.Castle);+                    else if (requestedPointType == 3) // to siege HQ+                        loc = MapRegionTable.getInstance().getTeleToLocation(activeChar, MapRegionTable.TeleportWhereType.SiegeFlag);+                    else if (requestedPointType == 4 || // Fixed or+                            activeChar.isFestivalParticipant()) // Player is a festival participant+                        loc = new Location(activeChar.getX(), activeChar.getY(), activeChar.getZ()); // spawn them where they died+                    else+                        loc = MapRegionTable.getInstance().getTeleToLocation(activeChar, MapRegionTable.TeleportWhereType.ClosestTown);                  //Teleport and revive                 MapRegionTable.getInstance().teleToLocation(activeChar, loc);@@ -94,8 +94,8 @@         if (activeChar == null)             return;             //SystemMessage sm2 = new SystemMessage(614);-	    //sm2.addString("type:"+requestedPointType);-	    //activeChar.sendPacket(sm2);+	    //sm2.addString("type:"+requestedPointType);+	    //activeChar.sendPacket(sm2);                  if (activeChar.isFakeDeath())         {@@ -113,21 +113,21 @@                     && castle.getSiege().checkIsAttacker(activeChar.getClan()))             {                 // Schedule respawn delay for attacker-                ClientScheduler.getInstance().scheduleLow(new DeathTask(activeChar), castle.getSiege().getAttackerRespawnDelay());+                ClientScheduler.getInstance().scheduleMed(new DeathTask(activeChar), castle.getSiege().getAttackerRespawnDelay());                 sm.addString("You will be re-spawned in " + castle.getSiege().getAttackerRespawnDelay()/1000 + " seconds");                 activeChar.sendPacket(sm);             }             else             {                 // Schedule respawn delay for defender with penalty for CT lose-                ClientScheduler.getInstance().scheduleLow(new DeathTask(activeChar), castle.getSiege().getDefenderRespawnDelay());+                ClientScheduler.getInstance().scheduleMed(new DeathTask(activeChar), castle.getSiege().getDefenderRespawnDelay());                 sm.addString("You will be re-spawned in " + castle.getSiege().getDefenderRespawnDelay()/1000 + " seconds");                 activeChar.sendPacket(sm);             }             return;         }         -        ClientScheduler.getInstance().scheduleLow(new DeathTask(activeChar), 1);+        ClientScheduler.getInstance().scheduleMed(new DeathTask(activeChar), 1);     }          Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/EnterWorld.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/EnterWorld.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/EnterWorld.java	(working copy)@@ -75,7 +75,7 @@                  if(activeChar.isGM())         {-            activeChar.setInvisible();+            //activeChar.setInvisible();         }                  if (Config.PLAYER_SPAWN_PROTECTION > 0)@@ -187,9 +187,9 @@                  if(activeChar.isGM())         {-            activeChar.sendMessage("Hide is default for builder");-            activeChar.setMessageRefusal(true);-            activeChar.sendMessage("Message refusal mode");+            activeChar.sendMessage("Admins are not cowards!");+            activeChar.sendMessage("We don't hide and we don't refuse questions from players!");+            activeChar.setMessageRefusal(false);         } 	}     Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/RequestRecipeItemMakeSelf.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/RequestRecipeItemMakeSelf.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/clientpackets/RequestRecipeItemMakeSelf.java	(working copy)@@ -19,8 +19,10 @@ package net.sf.l2j.gameserver.clientpackets;  import java.nio.ByteBuffer;+import java.util.logging.Logger;  import net.sf.l2j.gameserver.ClientThread;+import net.sf.l2j.gameserver.GameServer; import net.sf.l2j.gameserver.RecipeController; import net.sf.l2j.gameserver.model.L2PcInstance; @@ -33,7 +35,7 @@ public class RequestRecipeItemMakeSelf extends ClientBasePacket  {     private static final String _C__AF_REQUESTRECIPEITEMMAKESELF = "[C] AF RequestRecipeItemMakeSelf";-	//private static Logger _log = Logger.getLogger(RequestSellItem.class.getName());+    private static final Logger _log = Logger.getLogger(RequestRecipeItemMakeSelf.class.getName());  	private final int _id; 	/**@@ -60,6 +62,7 @@         if (activeChar.isInCraftMode())         {             activeChar.sendMessage("Currently in Craft Mode");+            _log.warning("Currently in Craft Mode");             return;         }         Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2SiegeGuardInstance.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2SiegeGuardInstance.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2SiegeGuardInstance.java	(working copy)@@ -133,8 +133,8 @@      */     public void onAction(L2PcInstance player)     {-      //  if (player == null)-      //      return;+        if (player == null)+            return;          		if (this != player.getTarget()) 		{Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Potion.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Potion.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Potion.java	(working copy)@@ -24,7 +24,6 @@ import net.sf.l2j.Config; import net.sf.l2j.gameserver.ClientScheduler; - /**  *   * This class ...@@ -65,15 +64,13 @@ 				{ 					double nowHp = _instance.getCurrentHp(); 					if(_duration == 0)-					{ 						stopPotionHpRegeneration();-					}-					if (_duration != 0)+					else 					{ 						nowHp     += _effect; 						_instance.setCurrentHp(nowHp);-						_duration = _duration - (_milliseconds / 1000);-						setCurrentHpPotion2();+						_duration -= (_milliseconds / 1000);+						if(_duration==0) stopPotionHpRegeneration(); 					} 				} 			}@@ -100,13 +97,6 @@ 		if (Config.DEBUG) _log.fine("Potion HP regen stop"); 	} -	public void setCurrentHpPotion2()-	{-		if (_duration == 0)-		{-			stopPotionHpRegeneration();-		}-	} 	public void setCurrentHpPotion1(L2Character activeChar, int item) 	{ 		_potion = item;@@ -114,23 +104,8 @@  		switch (_potion) 		{-			case (1540): -				double nowHp = activeChar.getCurrentHp();-				nowHp+=435;-				if (nowHp>= activeChar.getMaxHp())-				{-					nowHp = activeChar.getMaxHp();-				}-				activeChar.setCurrentHp(nowHp);-			case (728):	-				double nowMp = activeChar.getMaxMp();-				nowMp+=435;-				if (nowMp>= activeChar.getMaxMp())-				{-					nowMp = activeChar.getMaxMp();-				}-				activeChar.setCurrentMp(nowMp);-				break;+			case (1540): activeChar.setCurrentHp(java.lang.Math.min(activeChar.getCurrentHp()+435,(double)activeChar.getMaxHp()));break;+			case (728) : activeChar.setCurrentMp(java.lang.Math.min(activeChar.getCurrentMp()+435,(double)activeChar.getMaxMp()));break; 			case (726): 				_milliseconds = 500; 				_duration = 15;@@ -157,16 +132,13 @@ 				{ 					double nowMp = _instance.getCurrentMp(); 					if(_duration == 0)+                        stopPotionMpRegeneration();+                    else 					{-						stopPotionMpRegeneration();-					}-					if (_duration != 0)-					{ 						nowMp+=_effect; 						_instance.setCurrentMp(nowMp); 						_duration=(_duration-(_milliseconds/1000));-						setCurrentMpPotion2();-						+                        if(_duration == 0) stopPotionMpRegeneration(); 					} 				} 			}@@ -179,7 +151,7 @@ 	 	private void startPotionMpRegeneration(L2Character activeChar) 	{-		_potionmpRegTask = ClientScheduler.getInstance().scheduleMedAtFixedRate(+		_potionmpRegTask = ClientScheduler.getInstance().scheduleMedHighAtFixedRate( 				new PotionMpHealing(activeChar), 1000, _milliseconds); 		if (Config.DEBUG) _log.fine("Potion MP regen Started"); 	}@@ -195,14 +167,6 @@ 		if (Config.DEBUG) _log.fine("Potion MP regen stop"); 	} -	public void setCurrentMpPotion2()-	{-		if (_duration == 0)-		{-			stopPotionMpRegeneration();-		}-	}-	 	public void setCurrentMpPotion1(L2Character activeChar, int item) 	{ 		_potion = item;Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/actor/character/CharStatus.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/actor/character/CharStatus.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/actor/character/CharStatus.java	(working copy)@@ -197,7 +197,7 @@             int period = Formulas.getInstance().getRegeneratePeriod(getActiveChar());              // Create the HP/MP/CP Regeneration task-            _RegTask = ClientScheduler.getInstance().scheduleMedAtFixedRate(new RegenTask(), period, period);+            _RegTask = ClientScheduler.getInstance().scheduleMedHighAtFixedRate(new RegenTask(), period, period);         }     } Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2MonsterInstance.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2MonsterInstance.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2MonsterInstance.java	(working copy)@@ -28,7 +28,7 @@ import net.sf.l2j.gameserver.model.actor.monster.MonsterKnownList; import net.sf.l2j.gameserver.templates.L2NpcTemplate; import net.sf.l2j.gameserver.util.MinionList;-+import net.sf.l2j.gameserver.ai.CtrlIntention; /**  * This class manages all Monsters.  * @@ -108,18 +108,27 @@                     {                         minionList.maintainMinions(); 			//must be fixed. class exception.-                        //for(L2MinionInstance minion : minionList.getSpawnedMinions())-                        //    minion.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this);+                        for(L2MinionInstance minion : minionList.getSpawnedMinions())+                        {+                            if(minion==null) {+                                _log.warning("minion=null, spawnedMinions: "+minionList.countSpawnedMinions());+                                continue;+                            }+                            +                            //minion.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this);+                        };                     }-                    catch (Throwable e) +                    catch (Exception e)                      {-                        _log.log(Level.SEVERE, "", e);+                        _log.log(Level.SEVERE, "%%%%%", e);+                        e.printStackTrace();                     }                 }             }, getMaintenanceInterval()); 		} 		catch ( NullPointerException e ) 		{+            _log.log(Level.SEVERE, "", e); 		}		 	}     Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Clan.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Clan.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Clan.java	(working copy)@@ -83,7 +83,11 @@     public L2Clan(int clanId)     {         _clanId = clanId;-        restore();+        try+        {restore();} catch (Exception e) +        {+            _log.warning("Exception in L2Clan constructor, restore() failed: "+e);+        }      }          /**@@ -96,6 +100,11 @@     {         _clanId = clanId;         _name = clanName;+        if(leader==null)+        {+            _log.warning("Clan '"+clanName + "' id "+clanId+" has no leader (null), attempting to setNewLeader()");+            _log.warning("New leader now: "+getLeaderName());+        };         setLeader(leader);     }     @@ -118,6 +127,7 @@ 	 */ 	public int getLeaderId() 	{+        if (_leader==null) setNewLeader(); 		return _leader.getObjectId(); 	}     /**@@ -125,6 +135,7 @@      */     public L2ClanMember getLeader()     {+        if (_leader==null) setNewLeader();         return _leader;     } 	/**@@ -135,6 +146,7 @@ 		_leader = leader; 		_members.put(leader.getName(), leader); 	}+     	public void setNewLeader() 	{ 	    int maxLevel = 0;@@ -160,7 +172,8 @@ 	 */ 	public String getLeaderName() 	{-		return _leader.getName();+		if (_leader==null) setNewLeader();+        return _leader.getName(); 	}  	/**Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Skill.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Skill.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Skill.java	(working copy)@@ -159,7 +159,8 @@         DRAIN_SOUL,                  // unimplemented-        NOTDONE;+        NOTDONE,+        MDAM_ELEMENTAL;                  private final Class<? extends L2Skill> clazz;         Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Character.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Character.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/model/L2Character.java	(working copy)@@ -210,7 +210,7 @@     {         decayMe();     }-    +     public void onTeleported()     {         setIsTeleporting(false);@@ -218,7 +218,7 @@         spawnMe(getPosition().getX(), getPosition().getY(), getPosition().getZ());          if (_IsPendingRevive) doRevive();-+                 // Modify the position of the pet if necessary         if(getPet() != null) getPet().teleToLocation(getPosition().getX() + Rnd.get(-100,100), getPosition().getY() + Rnd.get(-100,100), getPosition().getZ());     }@@ -253,6 +253,7 @@         for (L2PcInstance player : knownPlayers)         {             if (player == null || player == this) continue;+            if(getDistance(player.getX(),player.getY()) > 2000) continue;             player.sendPacket(mov);             if(Config.DEVELOPER && getDistance(player.getX(),player.getY()) > 1500) _log.warning("broadcastPacket: Too far player see event!");         }@@ -290,6 +291,7 @@                 temp.sendPacket(su);     } +     /**      * Not Implemented.<BR><BR>      *@@ -321,12 +323,12 @@         setIsAttacked(false);         setIsTeleporting(true);         setTarget(null);--        x += Rnd.get(-70, 70);-        y += Rnd.get(-70, 70);+       +        x += Rnd.get(-70,70);+        y += Rnd.get(-70,70);         z += 5; -        if (Config.DEBUG) _log.fine("Teleporting to: " + x + ", " + y + ", " + z);+        if (Config.DEBUG) _log.fine("Teleporting to: "+x+", "+y+", "+z);          // Send a Server->Client packet TeleportToLocationt to the L2Character AND to all L2PcInstance in the _KnownPlayers of the L2Character         broadcastPacket(new TeleportToLocation(this, x, y, z));@@ -396,7 +398,7 @@                         {                             // If L2PcInstance doesn't have enough MP, stop the attack -                            ClientScheduler.getInstance().scheduleMed(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);+                            ClientScheduler.getInstance().scheduleAi(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);                              sendPacket(new SystemMessage(SystemMessage.NOT_ENOUGH_MP)); @@ -416,7 +418,7 @@                 else                 {                     // Cancel the action because the bow can't be re-use at this moment-                    ClientScheduler.getInstance().scheduleMed(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);+                    ClientScheduler.getInstance().scheduleAi(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), 1000);                      ActionFailed af = new ActionFailed();                     sendPacket(af);@@ -502,7 +504,7 @@         int reuse = weaponItem==null ? 0 : weaponItem.getAttackReuseDelay();          // Notify AI with EVT_READY_TO_ACT-        ClientScheduler.getInstance().scheduleMed(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), sAtk+reuse);+        ClientScheduler.getInstance().scheduleAi(new NotifyAITask(CtrlEvent.EVT_READY_TO_ACT), sAtk+reuse);     }      /**@@ -578,7 +580,7 @@         }          // Create a new hit task with Medium priority-        ClientScheduler.getInstance().scheduleMed(new HitTask(target, damage1, crit1, miss1, attack._soulshot, shld1), sAtk);+        ClientScheduler.getInstance().scheduleMedHigh(new HitTask(target, damage1, crit1, miss1, attack._soulshot, shld1), sAtk);          // Calculate and set the disable delay of the bow in function of the Attack Speed         _disableBowAttackEndTime = (sAtk+reuse)/GameTimeController.MILLIS_IN_TICK + GameTimeController.getGameTicks();@@ -648,10 +650,10 @@         }          // Create a new hit task with Medium priority for hit 1-        ClientScheduler.getInstance().scheduleMed(new HitTask(target, damage1, crit1, miss1, attack._soulshot, shld1), 650);+        ClientScheduler.getInstance().scheduleMedHigh(new HitTask(target, damage1, crit1, miss1, attack._soulshot, shld1), 650);          // Create a new hit task with Medium priority for hit 2 with a higher delay-        ClientScheduler.getInstance().scheduleMed(new HitTask(target, damage2, crit2, miss2, attack._soulshot, shld2), 1250);+        ClientScheduler.getInstance().scheduleMedHigh(new HitTask(target, damage2, crit2, miss2, attack._soulshot, shld2), 1250);          // Add those hits to the Server-Client packet Attack         attack.addHit(target, damage1, miss1, crit1, shld1);@@ -795,7 +797,7 @@         }          // Create a new hit task with Medium priority-        ClientScheduler.getInstance().scheduleMed(new HitTask(target, damage1, crit1, miss1, attack._soulshot, shld1), 980);+        ClientScheduler.getInstance().scheduleMedHigh(new HitTask(target, damage1, crit1, miss1, attack._soulshot, shld1), 980);          // Add this hit to the Server-Client packet Attack         attack.addHit(target, damage1, miss1, crit1, shld1);@@ -974,7 +976,7 @@         if (reuseDelay > 10)         {             disableSkill(skill.getId());-            ClientScheduler.getInstance().scheduleMed(new EnableSkill(skill.getId()), reuseDelay);+            ClientScheduler.getInstance().scheduleMedHigh(new EnableSkill(skill.getId()), reuseDelay);         }          // launch the magic in skillTime milliseconds@@ -989,7 +991,7 @@              // Disable all skills during the casting time and create a task EnableAllSkills with Medium priority to enable all skills at the end of the cating time             disableAllSkills();-            ClientScheduler.getInstance().scheduleMed(new EnableAllSkills(skill), skillTime);+            ClientScheduler.getInstance().scheduleMedHigh(new EnableAllSkills(skill), skillTime);                          if (_skillCast != null)             {@@ -998,7 +1000,7 @@             }              // Create a task MagicUseTask with Medium priority to launch the MagicSkill at the end of the casting time-            _skillCast = ClientScheduler.getInstance().scheduleMed(new MagicUseTask(targets, skill), skillTime);+            _skillCast = ClientScheduler.getInstance().scheduleMedHigh(new MagicUseTask(targets, skill), skillTime);         }         else         {@@ -1056,26 +1058,26 @@         _NotifyQuestOfDeathList.clear();         getAttackByList().clear();     }-        +     /** Sets HP, MP and CP and revives the L2Character. */     public void doRevive()     {         if (!isTeleporting())         {             setIsPendingRevive(false);-+                     _Status.setCurrentCp(getMaxCp() * Config.RESPAWN_RESTORE_CP);-            _Status.setCurrentHp(getMaxHp() * Config.RESPAWN_RESTORE_HP);-            _Status.setCurrentMp(getMaxMp() * Config.RESPAWN_RESTORE_MP);-            -            // Start broadcast status -            broadcastPacket(new SocialAction(getObjectId(), 15)); -            broadcastPacket(new Revive(this));-        }+        _Status.setCurrentHp(getMaxHp() * Config.RESPAWN_RESTORE_HP);+        _Status.setCurrentMp(getMaxMp() * Config.RESPAWN_RESTORE_MP);+        +        // Start broadcast status +        broadcastPacket(new SocialAction(getObjectId(), 15)); +        broadcastPacket(new Revive(this));+    }         else             setIsPendingRevive(true);     }-+             /** Revives the L2Character using skill. */     public void doRevive(L2Skill skill) { doRevive(); }         @@ -3261,7 +3263,7 @@         // Create a task to notify the AI that L2Character arrives at a check point of the movement        if (tm > 3000)-           ClientScheduler.getInstance().scheduleMed( new NotifyAITask(CtrlEvent.EVT_ARRIVED_REVALIDATE), 2000);+           ClientScheduler.getInstance().scheduleAi( new NotifyAITask(CtrlEvent.EVT_ARRIVED_REVALIDATE), 2000);         // the CtrlEvent.EVT_ARRIVED will be sent when the character will actually arrive        // to destination by GameTimeControllerIndex: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/GameServer.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/GameServer.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/GameServer.java	(working copy)@@ -134,12 +134,27 @@ import net.sf.l2j.gameserver.script.faenor.FaenorScriptEngine; import net.sf.l2j.status.Status; import net.sf.l2j.gameserver.taskmanager.TaskManager;+import net.sf.l2j.gameserver.ClientScheduler; ++class Finalizator implements Runnable+{+    public void run() +    { +        System.runFinalization();+        //Runtime.getRuntime().gc();+        Runtime.getRuntime().runFinalization();+    };+};+++ /**  * This class ...  *  * @version $Revision: 1.29.2.15.2.19 $ $Date: 2005/04/05 19:41:23 $  */+ public class GameServer { 	private static final Logger _log = Logger.getLogger(GameServer.class.getName());@@ -176,8 +191,7 @@     	return _selectorThread;     } --	public GameServer() throws Exception+    public GameServer() throws Exception 	{         gameServer = this; 		_log.finest("used mem:" + getUsedMemoryMB()+"MB" );@@ -428,7 +442,14 @@                  _log.config("IdFactory: Free ObjectID's remaining: " + IdFactory.getInstance().size()); -		System.gc();+        System.runFinalization();+        System.gc();+        System.runFinalization();+        System.gc();+        Runtime.getRuntime().gc();+        Runtime.getRuntime().runFinalization();+        ClientScheduler.getInstance().scheduleLowAtFixedRate(new Finalizator(),60,60);+         		// maxMemory is the upper limit the jvm can use, totalMemory the size of the current allocation pool, freeMemory the unused memory in the allocation pool 		long freeMem = (Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory()) / 1024 / 1024; 		long totalMem = Runtime.getRuntime().maxMemory() / 1024 / 1024;Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ItemTable.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ItemTable.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ItemTable.java	(working copy)@@ -31,7 +31,11 @@ import net.sf.l2j.L2DatabaseFactory; import net.sf.l2j.gameserver.idfactory.IdFactory; import net.sf.l2j.gameserver.model.L2ItemInstance;+import net.sf.l2j.gameserver.model.L2PcInstance;+import net.sf.l2j.gameserver.model.L2Skill; import net.sf.l2j.gameserver.model.L2World;+import net.sf.l2j.gameserver.serverpackets.ActionFailed;+import net.sf.l2j.gameserver.serverpackets.SystemMessage; import net.sf.l2j.gameserver.skills.SkillsEngine; import net.sf.l2j.gameserver.templates.L2Armor; import net.sf.l2j.gameserver.templates.L2ArmorType;@@ -603,7 +607,8 @@ 		 		return temp; 	 	}-+    +     	/** 	 * Returns a dummy (fr = factice) item.<BR><BR> 	 * <U><I>Concept :</I></U><BR>@@ -634,5 +639,36 @@ 		return temp; 	 	} -	++    public L2ItemInstance createItemByCrafting(int itemId,L2PcInstance crafter,L2PcInstance customer,int price)+    {+        int skillLevel = crafter.getSkillLevel(L2Skill.SKILL_CRAFTING);+        if (skillLevel <= 0)+        {+            crafter.sendPacket(new ActionFailed());+            return null;+        }+        +        if (customer==null)  customer=crafter;+        +        // here we decided that crafting is possible so we can proceed+        crafter.isInCraftMode(true);+        +        if (customer.getAdena() < price)+        {+            customer.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));+            return null;+        }+            +        +        // Create and Init the L2ItemInstance corresponding to the Item Identifier+        L2ItemInstance temp = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);+        if (Config.DEBUG) _log.fine("ItemTable: Item created  oid:" + temp.getObjectId()+ " itemid:" + itemId);+        +        // Add the L2ItemInstance object to _allObjects of L2world+        L2World.getInstance().storeObject(temp);+        +        return temp;    +    }+     }Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2AttackableAI.java	(working copy)@@ -244,7 +244,7 @@ 		// If not idle - create an AI task (schedule onEvtThink repeatedly) 		if (aiTask == null) 		{-			aiTask = ClientScheduler.getInstance().scheduleLowAtFixedRate(this, 1000, 1000);+			aiTask = ClientScheduler.getInstance().scheduleAiAtFixedRate(this, 1000, 1000); 		} 		 	}Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SummonAI.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SummonAI.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SummonAI.java	(working copy)@@ -16,7 +16,7 @@  *  * http://www.gnu.org/copyleft/gpl.html  */-package net.sf.l2j.gameserver.ai;+package net.sf.l2j.gameserver.ai;   import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK; import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_CAST;Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/L2SiegeGuardAI.java	(working copy)@@ -21,6 +21,7 @@ import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE; import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_ATTACK; import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_IDLE;+import static net.sf.l2j.gameserver.ai.CtrlIntention.AI_INTENTION_FOLLOW;  import java.util.Random; import java.util.concurrent.Future;@@ -40,8 +41,7 @@ import net.sf.l2j.gameserver.model.L2PcInstance; import net.sf.l2j.gameserver.model.L2SiegeGuardInstance; import net.sf.l2j.gameserver.model.L2Skill;--+import java.lang.Math; /**  * This class manages AI of L2Attackable.<BR><BR>  * @@ -80,18 +80,16 @@     {         super(accessor);         -        _attack_timeout = Integer.MAX_VALUE;+        _attack_timeout = java.lang.Math.min(Integer.MAX_VALUE,MAX_ATTACK_TIMEOUT);         _globalAggro = -10; // 10 seconds timeout of ATTACK after respawn                  attackRange  = ((L2Attackable)_actor).getPhysicalAttackRange();     }     -         public void run()      {         // Launch actions corresponding to the Event Think         onEvtThink();-             }          /**@@ -163,11 +161,17 @@             // Check if actor is not dead             if(!_actor.isAlikeDead())             {-                L2Attackable npc = (L2Attackable)_actor;-                +                // remove from knownlist all dead or alikedead players+                for(L2PcInstance in:((L2Attackable)_actor).getKnownList().getKnownPlayers())+                {+                  if(in.isAlikeDead()) ((L2Attackable)_actor).getKnownList().removeKnownObject(in);+                }+                 // If its _knownPlayer isn't empty set the Intention to AI_INTENTION_ACTIVE-                if(npc.getKnownList().getKnownPlayers().size() > 0)+                if(((L2Attackable)_actor).getKnownList().getKnownPlayers().size() > 0)+                {                     intention = AI_INTENTION_ACTIVE;+                }                 else                     intention = AI_INTENTION_IDLE;             }@@ -197,7 +201,7 @@         // If not idle - create an AI task (schedule onEvtThink repeatedly)         if (aiTask == null)         {-            aiTask = ClientScheduler.getInstance().scheduleLowAtFixedRate(this, 1000, 1000);+            aiTask = ClientScheduler.getInstance().scheduleAiAtFixedRate(this, 1000, 1000);         }     }     @@ -562,11 +566,22 @@     { //      if(getIntention() != AI_INTENTION_IDLE && (!_actor.isVisible() || !_actor.hasAI() || !_actor.isKnownPlayers())) //          setIntention(AI_INTENTION_IDLE);+        +        // Check if the actor can't use skills and if a thinking action isn't already in progress+      if (thinking || _actor.isAllSkillsDisabled())+        return;+        +      if((!_actor.isVisible()) || (!_actor.hasAI()))+          setIntention(AI_INTENTION_IDLE); +      if((getIntention() == AI_INTENTION_FOLLOW) && (_actor.getKnownList().getKnownPlayers().isEmpty()))+          setIntention(AI_INTENTION_IDLE);+      +      if(getIntention() == AI_INTENTION_IDLE)+        return;+         // Check if the actor can't use skills and if a thinking action isn't already in progress-        if (thinking || _actor.isAllSkillsDisabled())-            return;-        +               // Start thinking action         thinking = true;         @@ -599,6 +614,12 @@      */     protected void onEvtAttacked(L2Character attacker)     {+        if(attacker==null) +            {+              _log.warning("L2SiegeGuardAI.java: onEvtAttacked(L2Character attacker)   ->  attacker=null, RETURNING with setting attacktimeout");+              _attack_timeout = GameTimeController.getGameTicks();+              return;+            }         // Calculate the attack timeout         _attack_timeout = MAX_ATTACK_TIMEOUT + GameTimeController.getGameTicks();         @@ -655,9 +676,8 @@                 if (!_actor.isRunning())                     _actor.setRunning(); -                L2SiegeGuardInstance sGuard = (L2SiegeGuardInstance)_actor;-                double homeX = target.getX() - sGuard.getHomeX();-                double homeY = target.getY() - sGuard.getHomeY();+                double homeX = target.getX() - ((L2SiegeGuardInstance)_actor).getHomeX();+                double homeY = target.getY() - ((L2SiegeGuardInstance)_actor).getHomeY();                                  // Check if the L2SiegeGuardInstance is not too far from its home location                 if (homeX*homeX+homeY*homeY < 1200*1200)Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/AbstractAI.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/AbstractAI.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ai/AbstractAI.java	(working copy)@@ -714,7 +714,7 @@                  // Create and Launch an AI Follow Task to execute every 1s 		_follow_target = target;-        _follow_task = ClientScheduler.getInstance().scheduleMedAtFixedRate(new FollowTask(), 5, FOLLOW_INTERVAL);+        _follow_task = ClientScheduler.getInstance().scheduleAiAtFixedRate(new FollowTask(), 5, FOLLOW_INTERVAL);     }  	/**@@ -732,7 +732,7 @@ 	    }  	    _follow_target = target;-	    _follow_task = ClientScheduler.getInstance().scheduleMedAtFixedRate(new FollowTask(range), 5, ATTACK_FOLLOW_INTERVAL);+	    _follow_task = ClientScheduler.getInstance().scheduleAiAtFixedRate(new FollowTask(range), 5, ATTACK_FOLLOW_INTERVAL); 	}  	/**Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/RecipeController.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/RecipeController.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/RecipeController.java	(working copy)@@ -16,8 +16,20 @@  *  * http://www.gnu.org/copyleft/gpl.html  */+++++ package net.sf.l2j.gameserver;-+/////+////+///+//     This file is now overcomented to explain all the changes+//     in detail. Feel free to remove them if it makes you happy+///+////+///// import java.io.BufferedReader; import java.io.File; import java.io.FileReader;@@ -55,524 +67,690 @@  public class RecipeController {-	protected static Logger _log = Logger.getLogger(RecipeController.class.getName());-	private static RecipeController _instance;+    protected static Logger _log = Logger.getLogger(RecipeController.class.getName());+    private static RecipeController _instance;+    +    private Map<Integer, L2RecipeList> _lists;+    +	protected static Map<L2PcInstance, RecipeItemMaker> activeMakers = Collections.synchronizedMap(new WeakHashMap<L2PcInstance,RecipeItemMaker>()); 	-	private Map<Integer, L2RecipeList> _lists;-	-	protected static Map<L2PcInstance, ReceipeItemMaker> activeMakers = Collections.synchronizedMap(new WeakHashMap<L2PcInstance,ReceipeItemMaker>());-	     protected static final Random _rnd = new Random();-	-	public static RecipeController getInstance()-	{-		if (_instance == null)-		{-			_instance = new RecipeController();-		}-		return _instance;-	}-	-	public RecipeController()-	{-		_lists = new FastMap<Integer, L2RecipeList>();-		String line = null;-		LineNumberReader lnr = null;-		-		try-		{-			File recipesData = new File(Config.DATAPACK_ROOT, "data/recipes.csv");-			lnr = new LineNumberReader(new BufferedReader( new FileReader(recipesData)));-			-			while ((line=lnr.readLine()) != null)-			{-				if (line.trim().length() == 0 || line.startsWith("#"))-				{-					continue;-				}-				-				parseList(line);-				-			}-			_log.config("RecipeController: Loaded "+_lists.size()+" Recipes.");-		}-		catch (Exception e)-		{-			if (lnr != null)-			{-				_log.log(Level.WARNING, "error while creating recipe controller in linenr: "+lnr.getLineNumber(), e);-			}-			else-			{-				_log.warning("No recipes were found in data folder");-			}-		}+    +    public static RecipeController getInstance()+    {+        if (_instance == null)+        {+            _instance = new RecipeController();+        }+        return _instance;+    }+    +    public RecipeController()+    {+        _lists = new FastMap<Integer, L2RecipeList>();+        String line = null;+        LineNumberReader lnr = null;+        +        try+        {+            File recipesData = new File(Config.DATAPACK_ROOT, "data/recipes.csv");+            lnr = new LineNumberReader(new BufferedReader( new FileReader(recipesData)));+            +            while ((line=lnr.readLine()) != null)+            {+                if (line.trim().length() == 0 || line.startsWith("#"))+                {+                    continue;+                }+                +                parseList(line);+                +            }+            _log.config("RecipeController: Loaded "+_lists.size()+" Recipes.");+        }+        catch (Exception e)+        {+            if (lnr != null)+            {+                _log.log(Level.WARNING, "error while creating recipe controller in linenr: "+lnr.getLineNumber(), e);+            }+            else+            {+                _log.warning("No recipes were found in data folder");+            }+        }         finally         {             try { lnr.close(); } catch (Exception e) { }         }-	}-	-	public int getRecipesCount()-	{-		return _lists.size();-	}-	-	public L2RecipeList getRecipeList(int listId)-	{-		return _lists.get(listId);-	}-	-	public L2RecipeList getRecipeByItemId(int itemId)-	{-		for (int i = 0; i < _lists.size(); i++)-		{-			L2RecipeList find = _lists.get(new Integer(i));-			if (find.getRecipeId() == itemId)-			{-				return find;-			}-		}-		return null;-	}-	-	public synchronized void requestBookOpen(L2PcInstance player)-	{						-		if (!Config.ALT_GAME_CREATION){-			RecipeBookItemList response = new RecipeBookItemList();-			response.addRecipes(player.getRecipeBook());-			player.sendPacket(response);-			return;-		}-        ReceipeItemMaker maker = activeMakers.get(player);+    }+    +    public int getRecipesCount()+    {+        return _lists.size();+    }+    public L2RecipeList getRecipeList(int listId)+    {+        return _lists.get(listId);+    }+    public L2RecipeList getRecipeByItemId(int itemId)+    {+        for (int i = 0; i < _lists.size(); i++)+        {+            L2RecipeList find = _lists.get(new Integer(i));+            if (find.getRecipeId() == itemId)+            {+                return find;+            }+        }+        return null;+    }+    +    public synchronized void requestBookOpen(L2PcInstance player)+    {                       +        RecipeItemMaker maker=null;++        // @@todo: this must be removed, but also made sure it will happen only if realy crafting +        if (Config.ALT_GAME_CREATION) +        {+            maker = activeMakers.get(player);+            if(!player.isInCraftMode() && maker!=null) +            {+                activeMakers.remove(player);+                if (Config.DEBUG) +                    _log.fine("removed "+player.getName()+" from activeMakers by force, trust only isInCraftMode for acurate state");+            }+        }+                 if (maker == null) {-        	RecipeBookItemList response = new RecipeBookItemList();-        	response.addRecipes(player.getRecipeBook());-        	player.sendPacket(response);-        	return;+            RecipeBookItemList response = new RecipeBookItemList();+            response.addRecipes(player.getRecipeBook());+            player.sendPacket(response);+            return;         }-        if (maker.timeReady <= GameTimeController.getGameTicks()) {-        	maker.run();-        	return;-        }+        +        if (Config.DEBUG) _log.fine("requestBookOpen:  Busy creating");         SystemMessage sm = new SystemMessage(614);          sm.addString("You are busy creating ");         sm.addItemName(maker.recipeList.getItemId());         player.sendPacket(sm);         return;-	}-	-	public synchronized void requestManufactureItem(L2PcInstance manufacturer, int recipeListId, L2PcInstance player)-	{-		L2RecipeList recipeList = getRecipeList(recipeListId-1);-		-		SystemMessage sm = new SystemMessage(614);+    }+    +    public synchronized void requestManufactureItem(L2PcInstance manufacturer, int recipeListId, L2PcInstance customer)+    {+        L2RecipeList recipeList = getRecipeList(recipeListId-1);+        SystemMessage sm = new SystemMessage(614);         -    		 manufacturer.isInCraftMode(true);-		if ((recipeList == null) || (recipeList.getRecipes().length == 0))-		{-			sm = new SystemMessage(614); -			sm.addString("No recipe for: " + recipeListId);-			player.sendPacket(sm);-        		manufacturer.isInCraftMode(false);-			return;-		}-		if (!Config.ALT_GAME_CREATION) {-			new ReceipeItemMaker(manufacturer, recipeList, player);-		} else {-			ReceipeItemMaker maker = activeMakers.get(manufacturer);-			if (maker != null)-			{-				sm = new SystemMessage(614); -				sm.addString("Manufacturer are busy creating.");-				sm.addItemName(recipeList.getItemId());-				player.sendPacket(sm);-            			manufacturer.isInCraftMode(false);-				return;-			}-			maker = new ReceipeItemMaker(manufacturer, recipeList, player);-			if (maker.isValid)-				activeMakers.put(manufacturer, maker);-		}-	}-	public synchronized void requestMakeItem(L2PcInstance player, int recipeListId)-	{-		L2RecipeList recipeList = getRecipeList(recipeListId-1);-		-		SystemMessage sm = new SystemMessage(614);+        if(manufacturer.isInCraftMode()) +            {+                if(Config.DEBUG) _log.fine("requestManufactureItem called but manufacturer is in craft mode");+                sm = new SystemMessage(614); +                sm.addString("Manufacturer is busy.");+                sm.addItemName(recipeList.getItemId());+                customer.sendPacket(sm);+                return;+            }         -    		player.isInCraftMode(true);-		if ((recipeList == null) || (recipeList.getRecipes().length == 0))-		{-			sm = new SystemMessage(614); -			sm.addString("No recipe for: " + recipeListId);-			player.sendPacket(sm);-            player.isInCraftMode(false);-			return;-		}-		if (!Config.ALT_GAME_CREATION) {-			new ReceipeItemMaker(player, recipeList, null);-		} else {-			ReceipeItemMaker maker = activeMakers.get(player);-			if (maker != null)-			{-				sm = new SystemMessage(614); -				sm.addString("You are busy creating ");-				sm.addItemName(recipeList.getItemId());-				player.sendPacket(sm);-                player.isInCraftMode(false);-				return;-			}-			maker = new ReceipeItemMaker(player, recipeList, null);-			if (maker.isValid)-				activeMakers.put(player, maker);-		}-	}-	-	public synchronized void requestMakeItemAbort(L2PcInstance player)-	{-		activeMakers.remove(player);-	}-	-	private void parseList(String line)-	{-		StringTokenizer st = new StringTokenizer(line,";");-		List<L2RecipeInstance> recipePartList = new FastList<L2RecipeInstance>();-		-		String recipeName = st.nextToken();-		int id = Integer.parseInt(st.nextToken());-		int recipeId = Integer.parseInt(st.nextToken());-		int level = Integer.parseInt(st.nextToken());-		-		//material-		StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");-		while (st2.hasMoreTokens())-		{-			StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");-			int rpItemId = Integer.parseInt(st3.nextToken());-			int quantity = Integer.parseInt(st3.nextToken());-			L2RecipeInstance rp = new L2RecipeInstance(rpItemId, quantity);-			recipePartList.add(rp);-			//recipe.addRecipe(rp);-		}-		-		int itemId = Integer.parseInt(st.nextToken());-		int count = Integer.parseInt(st.nextToken());-		-		//npc fee-		/*String notdoneyet = */ st.nextToken();-		-		int mpCost = Integer.parseInt(st.nextToken());-		int successRate = Integer.parseInt(st.nextToken());-		-		L2RecipeList recipeList = new L2RecipeList(id,level,recipeId,recipeName,successRate,mpCost,itemId,count);-		for (L2RecipeInstance recipePart : recipePartList)-		{-			recipeList.addRecipe(recipePart);-		}-		_lists.put(new Integer(_lists.size()), recipeList);-	}-	-	-	-	-	class ReceipeItemMaker implements Runnable-	{-		int   timeReady;-		final L2PcInstance player;-		final L2PcInstance target;-		final L2RecipeList recipeList;-		final List<L2ItemInstance> items;-		int   materialsRefPrice;-		int   totalItems;-		int   usedItems;-		int   price;-		boolean isValid;-		-		ReceipeItemMaker(L2PcInstance player, L2RecipeList recipeList, L2PcInstance target )-		{-			this.player = player;-			this.target = target;-			this.recipeList = recipeList;-			this.items = new FastList<L2ItemInstance>();-			-			int skillLevel = player.getSkillLevel(L2Skill.SKILL_CRAFTING);-			if (skillLevel <= 0)-			{-				player.sendPacket(new ActionFailed());-                player.isInCraftMode(false);-				return;-			}-			-			if ((recipeList == null) || (recipeList.getRecipes().length == 0))-			{-				SystemMessage sm = new SystemMessage(614); -				sm.addString("No such recipe");-				player.sendPacket(sm);-                player.isInCraftMode(false);-				return;-			}-			-			if (target != null)-			{-			    for (L2ManufactureItem temp : player.getCreateList().getList())-			    {-				if (temp.getRecipeId() == recipeList.getId())-				{-				    price = temp.getCost();-				    if (target.getAdena() < price)-				    {-					target.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));-					player.isInCraftMode(false);-					return;-				    }-				    break;-				}-			    }-			}-			if (recipeList.getLevel()>skillLevel)-			{-				SystemMessage sm = new SystemMessage(614); -				sm.addString("Need skill level "+recipeList.getLevel());-				player.sendPacket(sm);-                player.isInCraftMode(false);-				return;-			}-			/*-			 if (recipeList.getAdenaCost()>activeChar.getAdena())-			 {-			 SystemMessage sm = new SystemMessage(614); -			 sm.addString("Need "+recipeList.getAdenaCost()+" Adena");-			 activeChar.sendPacket(sm);-			 return;-			 }*/-			-			L2RecipeInstance[] recipes = recipeList.getRecipes();-			-			Inventory inv = null;-			if (target == null)-			    inv = player.getInventory();-			else-			    inv = target.getInventory();-			-			for (L2RecipeInstance recipe : recipes)-			{-				if (recipe.getQuantity() != 0)-				{-					L2ItemInstance invItem = inv.getItemByItemId(recipe.getItemId());-					if ((invItem == null) || (recipe.getQuantity()>invItem.getCount()))-					{-						SystemMessage sm = new SystemMessage(614); -						sm.addString("You dont have the right elements for making this item");-						if (target == null)-						    player.sendPacket(sm);-						else-						    target.sendPacket(sm);-                        player.isInCraftMode(false);-						return;-					}-				}-			}-			-			if (!Config.ALT_GAME_CREATION)-			{-				if (player.getCurrentMp() < recipeList.getMpCost())-				{-					if (Config.DEBUG) _log.fine("not enough mana");-					SystemMessage sm = new SystemMessage(SystemMessage.NOT_ENOUGH_MP); -					if (target == null)-					    player.sendPacket(sm);-					else-					    target.sendPacket(sm);-					timeReady = GameTimeController.getGameTicks();-                    player.isInCraftMode(false);-					return;-				}-			}-			-			for (L2RecipeInstance recipe : recipes)-			{-				if (recipe.getQuantity() != 0)-				{-					L2ItemInstance invItem = inv.getItemByItemId(recipe.getItemId());-					invItem = inv.dropItem(invItem, recipe.getQuantity());-					items.add(invItem);-					materialsRefPrice += invItem.getReferencePrice()*invItem.getCount();-					totalItems += invItem.getCount();-				}-			}-			-			isValid = true; -			-			timeReady = GameTimeController.TICKS_PER_SECOND + GameTimeController.getGameTicks();-			ClientScheduler.getInstance().scheduleLow(this, 1100);-		}-		-		public void run()-		{-            player.isInCraftMode(true);+        // now we can allow crafting+        manufacturer.isInCraftMode(true);+        +        if ((recipeList == null) || (recipeList.getRecipes().length == 0))+        {+            _log.warning("I bet this can never happen normally, "++                         "cause customer can order only listed recipes, which are 100% in manufacturer's recipe book");             -			if ( Config.IS_CRAFTING_ENABLED ) {-				double currentPlayerMp = player.getCurrentMp(); -				if (currentPlayerMp < recipeList.getMpCost()) {-					if (Config.DEBUG) _log.fine("not enough mana");-					SystemMessage sm = new SystemMessage(SystemMessage.NOT_ENOUGH_MP); -					if (target == null)-					    player.sendPacket(sm);-					else-					    target.sendPacket(sm);-					timeReady = GameTimeController.getGameTicks();-                    player.isInCraftMode(false);-					return;-				}-				-				int gameTicks = GameTimeController.getGameTicks();	-				if (timeReady > gameTicks)+            sm = new SystemMessage(614); +            sm.addString("No recipe for: " + recipeListId);+            customer.sendPacket(sm);+            manufacturer.isInCraftMode(false);+            return;+        }++        if (Config.ALT_GAME_CREATION) +        {+            RecipeItemMaker maker = activeMakers.get(manufacturer);+            if (maker != null)+            {+                if(!manufacturer.isInCraftMode())                 {-                    player.isInCraftMode(false);-					return;+                    if(Config.DEBUG) +                    {+                        _log.fine(maker.manufacturer.getName() + " is in activeMakers but not IsInCraftmode");+                        _log.fine("decision: isincraftmode() is right, activeMakers wrong, removing from activeMakers");+                    }+                    activeMakers.remove(manufacturer);+                } else+                {+                    sm = new SystemMessage(614); +                    sm.addString("Manufacturer is busy.");+                    sm.addItemName(recipeList.getItemId());+                    customer.sendPacket(sm);+                    manufacturer.isInCraftMode(false);+                    return;                 }-				-				timeReady = gameTicks + (int)(15 * player.getMReuseRate(player.getKnownSkill(172)) * GameTimeController.TICKS_PER_SECOND);			-				-				if (!Config.ALT_GAME_CREATION || items.isEmpty()) {-					player.reduceCurrentMp(recipeList.getMpCost());-					-					StatusUpdate su = new StatusUpdate(player.getObjectId());-					-					L2ItemInstance createdItem = ItemTable.getInstance().createItem(recipeList.getItemId());-					createdItem.setCount(recipeList.getCount());-					-					int randCheck = _rnd.nextInt(100);-					if(recipeList.getSuccessRate() <= randCheck ) {-						SystemMessage sm = new SystemMessage(614);-						sm.addString("Item(s) failed to create");-						player.sendPacket(sm);-                        player.isInCraftMode(false);-					}-					else {		-						int createdItemCount = createdItem.getCount();-						SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ITEM);-						sm.addItemName(createdItem.getItemId());-						sm.addNumber(createdItemCount);-						//sm.addString("Item(s) created");-						if (target == null)-						{-						    player.getInventory().addItem(createdItem);-						    player.sendPacket(sm);-						    su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());-						} else -						{-						    if (price > 0) {-							target.reduceAdena(price);-							player.addAdena(price);-							L2ItemInstance adenaupdate = player.getInventory().findItemByItemId(57);-							InventoryUpdate iu = new InventoryUpdate();-							iu.addModifiedItem(adenaupdate);-							player.sendPacket(iu);-							SystemMessage sm2 = new SystemMessage(SystemMessage.DISSAPEARED_ADENA);-							sm2.addNumber(price);-							target.sendPacket(sm2);-							sm2 = new SystemMessage(SystemMessage.EARNED_ADENA);-							sm2.addNumber(price);-							player.sendPacket(sm2);-						    }-						    target.getInventory().addItem(createdItem);-						    target.sendPacket(sm);-						    StatusUpdate su2 = new StatusUpdate(target.getObjectId());-						    su2.addAttribute(StatusUpdate.CUR_LOAD, target.getCurrentLoad());-						    target.sendPacket(su2);-						}-						-						-						if (Config.ALT_GAME_CREATION) {-							int skillLevel = player.getSkillLevel(L2Skill.SKILL_CRAFTING);-							int receipeLevel = recipeList.getLevel();-							int exp = createdItem.getReferencePrice()*createdItemCount;-							// one variation-							exp -= materialsRefPrice;-							if (exp < 0) exp = 0;-							// another variation-							// exp /= receipeLevel-							for (int i=skillLevel; i > receipeLevel; i--)-								exp /= 4;-							int sp = exp / 10;-                            player.addExpAndSp((int)player.calcStat(Stats.EXPSP_RATE, exp * Config.RATE_XP, null, null), -                                               (int)player.calcStat(Stats.EXPSP_RATE, sp * Config.RATE_SP, null, null));-						}-					}				-					activeMakers.remove(player);-                    player.isInCraftMode(false);-					-					su.addAttribute(StatusUpdate.CUR_MP, (int) player.getCurrentMp());-					player.sendPacket(su);-					if (target == null){-					    player.sendPacket(new ItemList(player, false));-					    player.sendPacket(new RecipeItemMakeInfo(recipeList.getId(),player));-					} else-					{-					    target.sendPacket(new ItemList(target, false));-					    target.sendPacket(new RecipeShopItemInfo(player.getObjectId(),recipeList.getId()));-					}-				} -				else {-					double currentMp = player.getCurrentMp(); -					if (currentMp < recipeList.getMpCost()) {-						if (Config.DEBUG) _log.fine("not enough mana");-						SystemMessage sm = new SystemMessage(SystemMessage.NOT_ENOUGH_MP); -						if (target == null)-						    player.sendPacket(sm);-						else-						    target.sendPacket(sm);-						timeReady = GameTimeController.getGameTicks();-                        player.isInCraftMode(false);-						return;-					}-					player.setCurrentMp(currentMp - recipeList.getMpCost());-					-					int numItems = player.getSkillLevel(172);-					while (numItems > 0 && !items.isEmpty()) {-						L2ItemInstance item = items.get(0);-						-						int count = item.getCount();-						if (count >= numItems) count = numItems;-						-						item.setCount(item.getCount() - count);-						if (item.getCount() <= 0) items.remove(0);-						-						numItems -= count;-						usedItems += count;-						-						SystemMessage sm = new SystemMessage(368);-						sm.addNumber(count);-						sm.addItemName(item.getItemId());-						if (target == null)-						    player.sendPacket(sm);-						else-						    target.sendPacket(sm);-						-                        player.isInCraftMode(false);-					}-					-					int delay = (timeReady-gameTicks) * GameTimeController.MILLIS_IN_TICK;-					MagicSkillUser msk = new MagicSkillUser(player, 1050, 1, delay, 0);-					player.broadcastPacket(msk);-					SetupGauge sg = new SetupGauge(0, delay);-					player.sendPacket(sg);				-					-					ClientScheduler.getInstance().scheduleLow(this, 100+delay);-				}-			}-			else {-				// crafting is disabled...-				SystemMessage sm = new SystemMessage(614);-				sm.addString("Crafting is currently disabled.");-				if (target == null)-				    player.sendPacket(sm);-				else-				    target.sendPacket(sm);-                player.isInCraftMode(false);-			}-		}-	}+            }+            +            maker = new RecipeItemMaker(manufacturer, recipeList, customer);+            +            if (maker!=null && manufacturer!=null && maker.isValid)+                activeMakers.put(manufacturer, maker);+        } else // for regular crafting we don't use activeMakers+            new RecipeItemMaker(manufacturer, recipeList, customer);+    }+    public synchronized void requestMakeItem(L2PcInstance manufacturer, int recipeListId)+    {+        L2RecipeList recipeList = getRecipeList(recipeListId-1);+        +        SystemMessage sm = new SystemMessage(614);+        +        if ((recipeList == null) || (recipeList.getRecipes().length == 0))+        {+            sm = new SystemMessage(614); +            sm.addString("No recipe for: " + recipeListId);+            manufacturer.sendPacket(sm);+            return;+        }++        if(manufacturer.isInCraftMode()) +        {+            sm = new SystemMessage(614); +            sm.addString("You are busy creating ");+            sm.addItemName(recipeList.getItemId());+            manufacturer.sendPacket(sm);+            return;+        } +        +        if (Config.ALT_GAME_CREATION) +        {+            RecipeItemMaker maker = activeMakers.get(manufacturer);+            if (maker != null)+                activeMakers.remove(manufacturer);+            +            maker = new RecipeItemMaker(manufacturer, recipeList, null);+            +            if (manufacturer!=null && maker!=null && maker.isValid)+                activeMakers.put(manufacturer, maker);+        } else+        {+            new RecipeItemMaker(manufacturer, recipeList, null);+        }+    }+    public synchronized void requestMakeItemAbort(L2PcInstance manufacturer)+    {+        manufacturer.isInCraftMode(false);+        if (Config.DEBUG) _log.fine(manufacturer.getName()+" IsInCraftMode(false)");++        if(Config.ALT_GAME_CREATION && activeMakers!=null) +        {+            if(activeMakers.get(manufacturer)!=null) activeMakers.remove(manufacturer);+            if (Config.DEBUG) +                _log.fine("requestMakeItemAbort called - removing " +manufacturer.getName() +" from activeMakers ");+        }+    }+    +    private void parseList(String line)+    {+        StringTokenizer st = new StringTokenizer(line,";");+        List<L2RecipeInstance> recipePartList = new FastList<L2RecipeInstance>();+        +        String recipeName = st.nextToken();+        int id = Integer.parseInt(st.nextToken());+        int recipeId = Integer.parseInt(st.nextToken());+        int level = Integer.parseInt(st.nextToken());+        +        //material+        StringTokenizer st2 = new StringTokenizer(st.nextToken(), "[],");+        while (st2.hasMoreTokens())+        {+            StringTokenizer st3 = new StringTokenizer(st2.nextToken(), "()");+            int rpItemId = Integer.parseInt(st3.nextToken());+            int quantity = Integer.parseInt(st3.nextToken());+            L2RecipeInstance rp = new L2RecipeInstance(rpItemId, quantity);+            recipePartList.add(rp);+            //recipe.addRecipe(rp);+        }+        +        int itemId = Integer.parseInt(st.nextToken());+        int count = Integer.parseInt(st.nextToken());+        +        //npc fee+        /*String notdoneyet = */ st.nextToken();+        +        int mpCost = Integer.parseInt(st.nextToken());+        int successRate = Integer.parseInt(st.nextToken());+        +        L2RecipeList recipeList = new L2RecipeList(id,level,recipeId,recipeName,successRate,mpCost,itemId,count);+        for (L2RecipeInstance recipePart : recipePartList)+        {+            recipeList.addRecipe(recipePart);+        }+        _lists.put(new Integer(_lists.size()), recipeList);+    }+    +    class RecipeItemMaker implements Runnable+    {+        int   timeReady;+        final L2PcInstance manufacturer;+        final L2PcInstance customer;+        final L2RecipeList recipeList;+        final List<L2ItemInstance> items;+        final int skillLevel;+        int   creationPasses;+        int   materialsRefPrice;+        int   totalItems;+        int   usedItems;+        int   price;+        boolean isValid;+        +        +        RecipeItemMaker(L2PcInstance manufacturer, L2RecipeList recipeList, L2PcInstance customer )+        {+            this.manufacturer = manufacturer;+            this.customer = customer;+            this.recipeList = recipeList;+            this.items = new FastList<L2ItemInstance>();+            this.skillLevel = manufacturer.getSkillLevel(L2Skill.SKILL_CRAFTING);+            +            // crafting is disabled...+            if (!Config.IS_CRAFTING_ENABLED)+            {+                SystemMessage sm = new SystemMessage(614);+                sm.addString("Crafting is currently disabled.");+                if (customer == null)+                    manufacturer.sendPacket(sm);+                else+                    customer.sendPacket(sm);+                manufacturer.isInCraftMode(false);+                return;+            }+            +            if (manufacturer.isInCraftMode())+            {+                if(Config.DEBUG) _log.fine("manufacturer.isInCraftMode()==true, in RecipeItemMaker constructor");+                SystemMessage sm = new SystemMessage(614);+                +                if (customer == null)+                {+                    sm.addString("You are busy crafting");+                    manufacturer.sendPacket(sm);+                }+                else+                {+                    sm.addString("Manufacturer is busy crafting");+                    customer.sendPacket(sm);+                };+                return;+            }+            +            if (skillLevel <= 0)+            {+                manufacturer.sendPacket(new ActionFailed());+                manufacturer.isInCraftMode(false);+                +                if(customer!=null) +                {+                    customer.sendPacket(new ActionFailed());+                    if(Config.DEBUG) +                        _log.warning("skillLevel <= 0 and customer!=null, so why can manufacturer open manufacture shop if he has no skill?");+                }+                return;+            }+            +            if ((recipeList == null) || (recipeList.getRecipes().length == 0))+            {+                SystemMessage sm = new SystemMessage(614); +                sm.addString("No such recipe");+                manufacturer.sendPacket(sm);++                if(customer!=null) +                {+                    customer.sendPacket(sm);+                    if(Config.DEBUG) +                        _log.warning("customer!=null, so why can manufacturer offer manufacture for item if he has no recipe ?");+                }++                return;+            }+            +            if (customer != null)+            {+                for (L2ManufactureItem temp : manufacturer.getCreateList().getList())+                    if (temp.getRecipeId() == recipeList.getId())+                    {+                        price = temp.getCost();+                        if (customer.getAdena() < price)+                            {+                                customer.sendPacket(new SystemMessage(SystemMessage.YOU_NOT_ENOUGH_ADENA));+                                return;+                            }+                        break;+                }+            }+            +            if (recipeList.getLevel()>skillLevel)+            {+                SystemMessage sm = new SystemMessage(614); +                sm.addString("Need skill level "+recipeList.getLevel());+                manufacturer.sendPacket(sm);+                return;+            }+            +            L2RecipeInstance[] recipes = recipeList.getRecipes();+            +            Inventory inv = null;+            +            if (customer == null)+                inv = manufacturer.getInventory();+            else+                inv = customer.getInventory();+            +            for (L2RecipeInstance recipe : recipes)+            {+                if (recipe.getQuantity() != 0)+                {+                    L2ItemInstance invItem = inv.getItemByItemId(recipe.getItemId());+                    if ((invItem == null) || (recipe.getQuantity()>invItem.getCount()))+                    {+                        SystemMessage sm = new SystemMessage(614); +                        sm.addString("You dont have the right elements for making this item");+                        +                        if (customer == null) manufacturer.sendPacket(sm);+                            else customer.sendPacket(sm);+                        +                        return;+                    }+                }+            }+            +            if (manufacturer.getCurrentMp() < recipeList.getMpCost())+            {+                if (Config.DEBUG) _log.fine("not enough mana in RecipeItemMaker constructor");+                SystemMessage sm = new SystemMessage(SystemMessage.NOT_ENOUGH_MP); +                if (customer == null)+                    manufacturer.sendPacket(sm);+                else+                    customer.sendPacket(sm);++                return;+            }+            +            creationPasses=0;+            for (L2RecipeInstance recipe : recipes)+            {+                if (recipe.getQuantity() != 0)+                {+                    L2ItemInstance invItem = inv.getItemByItemId(recipe.getItemId());+                    invItem = inv.dropItem(invItem, recipe.getQuantity());+                    items.add(invItem);+                    materialsRefPrice += invItem.getReferencePrice()*invItem.getCount();+                    totalItems += invItem.getCount();+                    creationPasses+=invItem.getCount()/skillLevel;+                    if((invItem.getCount()%skillLevel)>0) creationPasses++;+                }+            }++            if(Config.DEBUG)+            {+                _log.warning("calculated creation passes: "+creationPasses);+            +                if(creationPasses==0) +                {+                    creationPasses++;+                    _log.warning("creationPasses was ZERO so creationPasses++  and it is now " + creationPasses);+                }+            }+            isValid = true; +            +            manufacturer.isInCraftMode(true); // here we say craf mode started, no reason to do it sooner, just makes problems+            +            //ClientScheduler.scheduleCraftAction(this, 100);+            run();  // for not-alternative crafting -> no reason why not craft immediately, cause it uses really little cpu+                    // and will never make lag ... scheduled things tend to make lag, things that are immediately done don't if you +                    // have sufficient cpu anyway ...  how long can craft take ? few nanoseconds ?+                    // and for ALT_CRAFTING=true,  first run is innitial, and takes no time also,  and on end, if needed, another run+                    // is scheduled+            +        }+        public void run()+        {+            if (!Config.ALT_GAME_CREATION || items.isEmpty())   // this method does the actual creation of item,+            {                                                   // it is called immediately for normal crafting,  +                completeCreation();                             // cause normal crafting does not take time, bug gives no XP/SP+                manufacturer.isInCraftMode(false);              // for ALT_CRAFTING it is called only when all items are "equiped"+                                                                // thru multiple scheduled runs using +                                                                // ClientScheduler.ScheduleCraftAction()  - separate thread pool+                                                                // there should be no thread launching at all ++                if(Config.DEBUG) +                {+                    _log.warning("MP_Cost:  "+recipeList.getMpCost()+" ");+                    _log.warning("passes:   "+creationPasses+" ");+                    _log.warning("mana/pass:"+recipeList.getMpCost()/creationPasses+" ");+                    _log.warning("error:    "+(recipeList.getMpCost()-((recipeList.getMpCost()/creationPasses)*creationPasses)));+                }+                +                return;+            }+            +            +            // all this code is for ALT_GAME_CREATION only+            // previous code was very confusing, which led+            // to "craft lag" due to misunderstanding of +            // "crafting" in normal mode.+            // normal mode takes no time but gives no XP/SP+            // ALT_MODE takes time but gives XP/SP as reward+            // ---------------------------------------------+            // run() is scheduled multiple times, +            // (equiping) skillLevel items on every run, until +            // all items are "equiped", and then on next run,+            // completeCreation() will produce the result+            // and remove equiped  materials from inventory+            //  +            // on every run() part of mana is deducted from+            // manufacturer, amount is calculated as sum of +            // all item counts from recipe.++            double currentManufacturerMp = manufacturer.getCurrentMp();          // we need player to have only mana needed +            if (currentManufacturerMp < ((double)recipeList.getMpCost()/(double)creationPasses))                                                                     +            {                                                                     // for this pass, next pass is in 1 second+                if (Config.DEBUG) _log.warning("not enough mana in run()");      // so we can allow mp regen to help manufacturer+                SystemMessage sm = new SystemMessage(SystemMessage.NOT_ENOUGH_MP); +                if (customer == null)+                    manufacturer.sendPacket(sm);+                else+                    customer.sendPacket(sm);+                +                manufacturer.isInCraftMode(false);+                activeMakers.remove(manufacturer);+                return;+            }+                +                +            manufacturer.reduceCurrentMp((double)recipeList.getMpCost()/(double)creationPasses);+            +            int numItems = skillLevel;+            +            while (numItems > 0 && !items.isEmpty())  // equip # of items we can in one run()  +            {                                         // if players complain they lose items during craft on server crashes, try+                L2ItemInstance item = items.get(0);   // not to item.remove(), but instead copy it somehow and return if crafting +                int count = item.getCount();          // did not finish for some reason ?? umh don't know how it works really+                                                      // when is sql db updated ? all the time ? sometimes ?+                +                if (count >= numItems) count = numItems; +                item.setCount(item.getCount() - count);+                if (item.getCount() <= 0) items.remove(0);+                numItems -= count;+                usedItems += count;+                        +                SystemMessage sm = new SystemMessage(368);+                sm.addNumber(count);+                sm.addItemName(item.getItemId());+                +                if (customer == null) manufacturer.sendPacket(sm);+                    else customer.sendPacket(sm);+            }+                    +            int delay = ((int)(manufacturer.getMReuseRate(manufacturer.getKnownSkill(L2Skill.SKILL_CRAFTING)) * GameTimeController.TICKS_PER_SECOND)) * GameTimeController.MILLIS_IN_TICK;++            MagicSkillUser msk = new MagicSkillUser(manufacturer, 1050, 1, delay, 0);+            manufacturer.broadcastPacket(msk);++            SetupGauge sg = new SetupGauge(0, delay);+            manufacturer.sendPacket(sg);                ++            StatusUpdate su = new StatusUpdate(manufacturer.getObjectId());+            su.addAttribute(StatusUpdate.CUR_MP, (int) manufacturer.getCurrentMp());+            manufacturer.sendPacket(su);+//          // this works but it makes craft of level1 items very fast for alt mode ... uhm +//          // I'd allow that, cause crafting "braided hemp" is not very fun and you need to do it+//          // in huge quantities, even if you are high level, so you get no XP/SP+//          // but it's not my call        +//            if (items.isEmpty()) +//            {+//                if(Config.DEBUG) _log.fine("saved "+delay+" miliseconds");+//                completeCreation();+//                manufacturer.isInCraftMode(false);+//                activeMakers.remove(manufacturer);                +//            } else+            ClientScheduler.scheduleCraftAction(this, 1+delay);  // Craft thread pool has nothing to do with other pools, so+                                                                 // only way this can make any kind of lag is when CPU usage is 100%+                                                                 // when nobody is "in craft mode"  scheduled tasks for +                                                                 // craft thread pool must be 0 or we have a bug again :/+        }+        +        private void completeCreation()        // this is where real item production is done+        {  +            int createdItemCount=0;+            if(Config.DEBUG) +                _log.fine(manufacturer.getName()+" : completeCreation() ");+            +            if(!Config.ALT_GAME_CREATION)       // we reduce Mp in run() for ALT_GAME_CREATION +                manufacturer.reduceCurrentMp(recipeList.getMpCost());+            +            StatusUpdate su = new StatusUpdate(manufacturer.getObjectId());+            +            L2ItemInstance createdItem = ItemTable.getInstance().createItem(recipeList.getItemId());+            createdItem.setCount(recipeList.getCount());+            +            int randCheck = _rnd.nextInt(100);+            +            if(recipeList.getSuccessRate() <= randCheck ) +            {+                SystemMessage sm = new SystemMessage(614);+                sm.addString("Item(s) failed to create");+                manufacturer.sendPacket(sm);+                manufacturer.isInCraftMode(false);+                if(Config.ALT_GAME_CREATION && activeMakers.get(manufacturer)!=null) activeMakers.remove(manufacturer);+            } else +            {   // item succesfully created    +                createdItemCount = createdItem.getCount();+                SystemMessage sm = new SystemMessage(SystemMessage.EARNED_ITEM);+                sm.addItemName(createdItem.getItemId());+                sm.addNumber(createdItemCount);+                +                if (customer == null)+                {+                    manufacturer.getInventory().addItem(createdItem);+                    manufacturer.sendPacket(sm);+                    su.addAttribute(StatusUpdate.CUR_LOAD, manufacturer.getCurrentLoad());+                } else +                {+                    if (price > 0) +                    {+                        customer.reduceAdena(price);+                        manufacturer.addAdena(price);+                        L2ItemInstance adenaupdate = manufacturer.getInventory().findItemByItemId(57);+                        InventoryUpdate iu = new InventoryUpdate();+                        iu.addModifiedItem(adenaupdate);+                        manufacturer.sendPacket(iu);+                        SystemMessage sm2 = new SystemMessage(SystemMessage.DISSAPEARED_ADENA);+                        sm2.addNumber(price);+                        customer.sendPacket(sm2);+                        sm2 = new SystemMessage(SystemMessage.EARNED_ADENA);+                        sm2.addNumber(price);+                        manufacturer.sendPacket(sm2);+                    }+                +                    customer.getInventory().addItem(createdItem);+                    customer.sendPacket(sm);+                    StatusUpdate su2 = new StatusUpdate(customer.getObjectId());+                    su2.addAttribute(StatusUpdate.CUR_LOAD, customer.getCurrentLoad());+                    customer.sendPacket(su2);+                }+            }+                +            if (Config.ALT_GAME_CREATION)              +            {+                int RecipeLevel = recipeList.getLevel();+                int exp;+                int sp;+                +                // if sitting, default formula, standing my new formula based on MP used to craft item(s)+                if(!Config.ALT_GAME_CREATION_BY_MANA)  // standard formula, tried to fix but no luck+                {+                    exp = createdItem.getReferencePrice()*createdItemCount;+                    //   ensure at least some profit+                    materialsRefPrice=(int)((double)materialsRefPrice*(double)0.96);+                    +                    // one variation+                    if(Config.DEBUG) +                    {+                      _log.fine("BASED ON ITEM PRICE - MATERIALS PRICE");+                      _log.fine("createdItemCount: "+createdItemCount);+                      _log.fine("exp:              "+exp);+                      _log.fine("referent price:   "+createdItem.getReferencePrice());+                      _log.fine("referent total:   "+createdItem.getReferencePrice()*createdItemCount);+                      _log.fine("materials price:  "+materialsRefPrice);+                      _log.fine("exp:              "+(exp-materialsRefPrice));+                    }+                +                    exp -= materialsRefPrice;  ++                    if (exp < 0) exp = 0;+    +                    exp/=RecipeLevel;+                    +                    for (int i=skillLevel; i > RecipeLevel; i--) exp /= 4;++                    sp = exp / 10;+                    +                    if(Config.DEBUG) _log.fine("exp with mods:    "+exp);+                    +                } else+                {+                    exp=2*(recipeList.getLevel() * recipeList.getMpCost())+                        /skillLevel;+                    +                    sp = exp / 10;+                    +                    // one variation+                    if(Config.DEBUG) +                    {+                      _log.fine("NEW METHOD - BASED ON MANA");+                      _log.fine("createdItemCount: "+createdItemCount);+                      _log.fine("exp:              "+exp);+                    }+                    +                }+                manufacturer.addExpAndSp((int)manufacturer.calcStat(Stats.EXPSP_RATE, exp * Config.RATE_XP, null, null), +                                  (int)manufacturer.calcStat(Stats.EXPSP_RATE, sp * Config.RATE_SP, null, null));+            +                if(activeMakers.get(manufacturer)!=null) activeMakers.remove(manufacturer);+            }+            +            manufacturer.isInCraftMode(false);++            su.addAttribute(StatusUpdate.CUR_MP, (int) manufacturer.getCurrentMp());+            manufacturer.sendPacket(su);+            if (customer == null){+                manufacturer.sendPacket(new ItemList(manufacturer, false));+                manufacturer.sendPacket(new RecipeItemMakeInfo(recipeList.getId(),manufacturer));+            } else+            {+                customer.sendPacket(new ItemList(customer, false));+                customer.sendPacket(new RecipeShopItemInfo(manufacturer.getObjectId(),recipeList.getId()));+            }+        }  +    } }Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ClientScheduler.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ClientScheduler.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/ClientScheduler.java	(working copy)@@ -31,16 +31,6 @@ import net.sf.l2j.Config; import net.sf.l2j.gameserver.clientpackets.ClientBasePacket; -/**- * This class permit to create 3 Threads pools and to add to it tasks to execute in function of their priority (HIGH, MEDIUM,LOW).<BR><BR>- * - * <B><U> Threads pools </U> :</B><BR><BR>- * <li> A pool containing 4 Hight Threads </li>- * <li> A pool containing 10 Medium Threads </li>- * <li> A pool containing 4 Low priority Threads </li><BR><BR>- * - */- public final class ClientScheduler { 	static Logger _log = Logger.getLogger(ClientScheduler.class.getName());@@ -53,8 +43,11 @@ 	private static final ClientScheduler _instance = new ClientScheduler(); 	 	private final ScheduledThreadPoolExecutor _executorHighPriority;+    private final ScheduledThreadPoolExecutor _executorMedHighPriority; 	private final ScheduledThreadPoolExecutor _executorMedPriority; 	private final ScheduledThreadPoolExecutor _executorLowPriority;+    private final ScheduledThreadPoolExecutor _executorAi;+    private final ScheduledThreadPoolExecutor _executorCraft;   	/**@@ -67,15 +60,18 @@ 	 	 	/**-	 * Create a pool of 4 Hight Threads, a pool of 10 Medium Threads, and a pool of 4 Low priority Threads to execute Task.<BR><BR>+	 * Create a pool of 4 Hight Threads, a pool of 4 Medium Threads, and a pool of 4 Low priority Threads to execute Task.<BR><BR> 	 */ 	private ClientScheduler() 	{ 		if (Config.ASSERT) assert _instance == null; 		 		_executorHighPriority = new ScheduledThreadPoolExecutor(Config.THREAD_P_HIGH, new ThrFactory(Config.EXECUTOR_PRI_HIGH, "PoolHIGH"));-		_executorMedPriority = new ScheduledThreadPoolExecutor(Config.THREAD_P_MED, new ThrFactory(Config.EXECUTOR_PRI_MED, "PoolMED"));+        _executorMedHighPriority = new ScheduledThreadPoolExecutor(Config.THREAD_P_HIGH, new ThrFactory(Config.EXECUTOR_PRI_HIGH-1, "PoolHIGH"));+        _executorMedPriority = new ScheduledThreadPoolExecutor(Config.THREAD_P_MED, new ThrFactory(Config.EXECUTOR_PRI_MED, "PoolMED")); 		_executorLowPriority = new ScheduledThreadPoolExecutor(Config.THREAD_P_LOW, new ThrFactory(Config.EXECUTOR_PRI_LOW, "PoolLOW"));+        _executorAi = new ScheduledThreadPoolExecutor(Config.THREAD_P_MED, new ThrFactory((Config.EXECUTOR_PRI_HIGH-1), "PoolMED"));+        _executorCraft = new ScheduledThreadPoolExecutor(Config.THREAD_P_MED, new ThrFactory((Config.EXECUTOR_PRI_MED-1), "PoolLOW")); 	} 	 	/**@@ -83,17 +79,26 @@ 	 */ 	public void closeAll() 	{-		try { _executorHighPriority.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+		try { _executorHighPriority.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+        try { _executorMedHighPriority.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); } 		try { _executorMedPriority.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); } 		try { _executorLowPriority.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+        try { _executorAi.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+        try { _executorCraft.shutdown(); } catch (Throwable t) { _log.log(Level.WARNING, "", t); } 		-		try { _executorHighPriority.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+		try { _executorHighPriority.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+        try { _executorMedHighPriority.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); } 		try { _executorMedPriority.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); } 		try { _executorLowPriority.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+        try { _executorAi.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); }+        try { _executorCraft.awaitTermination(1000, TimeUnit.MILLISECONDS); } catch (Throwable t) { _log.log(Level.WARNING, "", t); } 		 		_executorHighPriority.shutdownNow();-		_executorHighPriority.shutdownNow();-		_executorHighPriority.shutdownNow();+		_executorMedHighPriority.shutdownNow();+        _executorMedPriority.shutdownNow();+		_executorLowPriority.shutdownNow();+        _executorAi.shutdownNow();+        _executorCraft.shutdownNow(); 	} 	 	@@ -105,7 +110,10 @@ 		TaskPriority pr = pkt.getPriority(); 		 		if (pr == null)-			pr = PR_LOW;+        {+            _log.warning("Packet without priority defaulted to PR_LOW: "+pkt.getType());+            pr = PR_LOW;+        } 		 		// Add a task to one of the pool of thread in function of its priority (HIGH, MEDIUM,LOW) 		// This has effect equivalent to schedule(command, 0, anyUnit)@@ -121,9 +129,9 @@ 			_instance._executorMedPriority.execute(pkt); 			return; 		case PR_LOW:-		default:-			_instance._executorLowPriority.execute(pkt);-			return;+        default:+            _instance._executorLowPriority.execute(pkt);+            return; 		} 	} 	@@ -146,8 +154,9 @@ 		{ 		case PR_HIGH:   return scheduleHighAtFixedRate(r, initial, delay); 		case PR_MEDIUM: return scheduleMedAtFixedRate(r, initial, delay);-		default:-		case PR_LOW:    return scheduleLowAtFixedRate(r, initial, delay);+        case PR_LOW:    return scheduleLowAtFixedRate(r, initial, delay);+        default:+          return scheduleLowAtFixedRate(r, initial, delay); 		} 	} @@ -169,7 +178,42 @@ 		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ } 	} -	+    /**+     * Create a MedHigh priority task that is executed after an initial time (in ms) and each delay ms.<BR><BR>+     *   +     * @param r The task to launch+     * @param initial The initial delay (in ms) after what the task is executed for the first time+     * @param delay The delay (in ms) between 2 consecutive executions of the task+     * +     */+    public ScheduledFuture scheduleMedHighAtFixedRate(Runnable r, long initial, long delay)+    {+        try+        {+        if (delay < 0) delay = 0;+        return _executorMedHighPriority.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);+        } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }+    }++    public ScheduledFuture scheduleAiAtFixedRate(Runnable r, long initial, long delay)+    {+        try+        {+        if (delay < 0) delay = 0;+        return _executorAi.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);+        } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }+    }++    public ScheduledFuture scheduleCraftAtFixedRate(Runnable r, long initial, long delay)+    {+        try+        {+        if (delay < 0) delay = 0;+        return _executorCraft.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);+        } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }+    }++     	/** 	 * Create a Medium priority task that is executed after an initial time (in ms) and each delay ms.<BR><BR> 	 *    @@ -231,8 +275,9 @@ 		{ 		case PR_HIGH:   return scheduleHigh(r, delay); 		case PR_MEDIUM: return scheduleMed(r, delay);+        case PR_LOW:    return scheduleLow(r, delay); 		default:-		case PR_LOW:    return scheduleLow(r, delay);+            return scheduleLow(r,delay); 		} 	} @@ -254,7 +299,22 @@ 		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ } 	} -	+    /**+     * Create a Medium priority task that is executed after an initial time (in ms).<BR><BR>+     *   +     * @param r The task to launch+     * @param initial The initial delay (in ms) after what the task is executed for the first time+     * @param delay The delay (in ms) between 2 consecutive executions of the task+     * +     */+    public ScheduledFuture scheduleMedHigh(Runnable r, long delay)+    {+        try+        {+        if (delay < 0) delay = 0;+        return _executorMedHighPriority.schedule(r, delay, TimeUnit.MILLISECONDS);+        } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }+    }	 	/** 	 * Create a Medium priority task that is executed after an initial time (in ms).<BR><BR> 	 *   @@ -263,6 +323,7 @@ 	 * @param delay The delay (in ms) between 2 consecutive executions of the task 	 *  	 */+     	public ScheduledFuture scheduleMed(Runnable r, long delay) 	{ 		try@@ -289,7 +350,24 @@ 		} catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ } 	} -	+    public ScheduledFuture scheduleAi(Runnable r, long delay)+    {+        try+        {+        if (delay < 0) delay = 0;+        return _executorAi.schedule(r, delay, TimeUnit.MILLISECONDS);+        } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }+    }+    +    public ScheduledFuture scheduleCraft(Runnable r, long delay)+    {+        try+        {+        if (delay < 0) delay = 0;+        return _executorCraft.schedule(r, delay, TimeUnit.MILLISECONDS);+        } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ }+    }+     	class ThrFactory implements ThreadFactory  	{ 		private final String _prefix;@@ -316,30 +394,49 @@     {         return new String[] {             "HIGH ("+Config.EXECUTOR_PRI_HIGH+")",-            "ActiveThreads:   "+_executorHighPriority.getActiveCount(),-            "CompletedTasks:  "+_executorHighPriority.getCompletedTaskCount(),-            "getCorePoolSize: "+_executorHighPriority.getCorePoolSize(),-            "MaximumPoolSize: "+_executorHighPriority.getMaximumPoolSize(),-            "LargestPoolSize: "+_executorHighPriority.getLargestPoolSize(),-            "PoolSize:        "+_executorHighPriority.getPoolSize(),-            "ScheduledTasks:  "+(_executorHighPriority.getTaskCount() - _executorHighPriority.getCompletedTaskCount()),-            "MEDIUM ("+Config.EXECUTOR_PRI_MED+")",-            "ActiveThreads:   "+_executorMedPriority.getActiveCount(),-            "CompletedTasks:  "+_executorMedPriority.getCompletedTaskCount(),-            "getCorePoolSize: "+_executorMedPriority.getCorePoolSize(),-            "MaximumPoolSize: "+_executorMedPriority.getMaximumPoolSize(),-            "LargestPoolSize: "+_executorMedPriority.getLargestPoolSize(),-            "PoolSize:        "+_executorMedPriority.getPoolSize(),-            "ScheduledTasks:  "+(_executorMedPriority.getTaskCount() - _executorMedPriority.getCompletedTaskCount()),+            "ActiveThreads:    "+_executorHighPriority.getActiveCount(),+            "CompletedTasks:   "+_executorHighPriority.getCompletedTaskCount(),+            "ScheduledTasks:   "+(_executorHighPriority.getTaskCount() - _executorHighPriority.getCompletedTaskCount()),+            "TaskCount(total): "+_executorHighPriority.getTaskCount(),+            "PoolSize:         "+_executorHighPriority.getPoolSize(),+            "",+            "MedHigh ("+Config.EXECUTOR_PRI_MEDHIGH+")",+            "ActiveThreads:    "+_executorMedHighPriority.getActiveCount(),+            "CompletedTasks:   "+_executorMedHighPriority.getCompletedTaskCount(),+            "ScheduledTasks:   "+(_executorMedHighPriority.getTaskCount() - _executorMedHighPriority.getCompletedTaskCount()),+            "TaskCount(total): "+_executorMedHighPriority.getTaskCount(),+            "PoolSize:         "+_executorMedHighPriority.getPoolSize(),+            "",+            "MEDIUM ("+(Config.EXECUTOR_PRI_MED)+")",+            "ActiveThreads:    "+_executorMedPriority.getActiveCount(),+            "CompletedTasks:   "+_executorMedPriority.getCompletedTaskCount(),+            "ScheduledTasks:   "+(_executorMedPriority.getTaskCount() - _executorMedPriority.getCompletedTaskCount()),+            "TaskCount(total): "+_executorMedPriority.getTaskCount(),+            "PoolSize:         "+_executorMedPriority.getPoolSize(),+            "",             "LOW ("+Config.EXECUTOR_PRI_LOW+")",-            "ActiveThreads:   "+_executorLowPriority.getActiveCount(),-            "CompletedTasks:  "+_executorLowPriority.getCompletedTaskCount(),-            "getCorePoolSize: "+_executorLowPriority.getCorePoolSize(),-            "MaximumPoolSize: "+_executorLowPriority.getMaximumPoolSize(),-            "LargestPoolSize: "+_executorLowPriority.getLargestPoolSize(),-            "PoolSize:        "+_executorLowPriority.getPoolSize(),-            "ScheduledTasks:  "+(_executorLowPriority.getTaskCount() - _executorLowPriority.getCompletedTaskCount())+            "ActiveThreads:    "+_executorLowPriority.getActiveCount(),+            "CompletedTasks:   "+_executorLowPriority.getCompletedTaskCount(),+            "ScheduledTasks:   "+(_executorLowPriority.getTaskCount() - _executorLowPriority.getCompletedTaskCount()),+            "TaskCount(total): "+_executorLowPriority.getTaskCount(),+            "PoolSize:         "+_executorLowPriority.getPoolSize(),+            "",+            "AI ("+Config.EXECUTOR_PRI_AI+")",+            "ActiveThreads:    "+_executorAi.getActiveCount(),+            "CompletedTasks:   "+_executorAi.getCompletedTaskCount(),+            "ScheduledTasks:   "+(_executorAi.getTaskCount() - _executorAi.getCompletedTaskCount()),       +            "TaskCount(total): "+_executorAi.getTaskCount(),+            "PoolSize:         "+_executorAi.getPoolSize(),+            "",+            "CRAFT ("+Config.EXECUTOR_PRI_CRAFT+")",+            "ActiveThreads:    "+_executorCraft.getActiveCount(),+            "CompletedTasks:   "+_executorCraft.getCompletedTaskCount(),+            "ScheduledTasks:   "+(_executorCraft.getTaskCount() - _executorCraft.getCompletedTaskCount()),       +            "TaskCount(total): "+_executorCraft.getTaskCount(),+            "PoolSize:         "+_executorCraft.getPoolSize(),+            ""         };+             }  @@ -348,4 +445,14 @@         return getInstance().scheduleLow(event, delay);     }     +    public static ScheduledFuture scheduleAiAction(Runnable event, long delay)+    {+        return getInstance().scheduleAi(event, delay);+    }++    public static ScheduledFuture scheduleCraftAction(Runnable event, long delay)+    {+        return getInstance().scheduleCraft(event, delay);+    }+     }Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/taskmanager/tasks/TaskCleanUp.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/taskmanager/tasks/TaskCleanUp.java	(revision 2151)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/taskmanager/tasks/TaskCleanUp.java	(working copy)@@ -1,35 +0,0 @@-/**- * - */-package net.sf.l2j.gameserver.taskmanager.tasks;--import net.sf.l2j.gameserver.taskmanager.Task;-import net.sf.l2j.gameserver.taskmanager.TaskManager;-import net.sf.l2j.gameserver.taskmanager.TaskTypes;-import net.sf.l2j.gameserver.taskmanager.TaskManager.ExecutedTask;--/**- * @author Tempy- *- */-public final class TaskCleanUp extends Task-{-    public static String NAME = "CleanUp";-    -    public String getName()-    {-        return NAME;-    }--    public void onTimeElapsed(ExecutedTask task)-    {-        System.runFinalization();-        System.gc();-    }-    -    public void initializate()-    {-        super.initializate();-        TaskManager.addUniqueTask(NAME, TaskTypes.TYPE_FIXED_SHEDULED, "0", "1800000", "");-    }-}Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/taskmanager/TaskManager.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/taskmanager/TaskManager.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/taskmanager/TaskManager.java	(working copy)@@ -24,7 +24,6 @@ import javolution.util.FastMap; import net.sf.l2j.L2DatabaseFactory; import net.sf.l2j.gameserver.ClientScheduler;-import net.sf.l2j.gameserver.taskmanager.tasks.TaskCleanUp; import net.sf.l2j.gameserver.taskmanager.tasks.TaskJython; import net.sf.l2j.gameserver.taskmanager.tasks.TaskRecom; import net.sf.l2j.gameserver.taskmanager.tasks.TaskRestart;@@ -163,7 +162,6 @@          private void initializate()     {-        registerTask(new TaskCleanUp());         registerTask(new TaskJython());         registerTask(new TaskRecom());         registerTask(new TaskRestart());Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/script/EngineInterface.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/script/EngineInterface.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/script/EngineInterface.java	(working copy)@@ -44,6 +44,9 @@ public interface EngineInterface {     //*  keep the references of Singletons to prevent garbage collection+    //   garbage collector will never 'collect' what is still  "alive" in ram so why "preventing" ?+    //   if you don't use it, let it be collected, if you use it, don't fear -> it will not be collected.+         public CharNameTable _charNametable = CharNameTable.getInstance();      public IdFactory _idFactory = IdFactory.getInstance();Index: C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/GameTimeController.java===================================================================--- C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/GameTimeController.java	(revision 2156)+++ C:/workspace/L2_GameServer/java/net/sf/l2j/gameserver/GameTimeController.java	(working copy)@@ -72,7 +72,7 @@ 		_timer = new TimerThread(); 		_timer.start(); -		ClientScheduler.getInstance().scheduleLowAtFixedRate(+		ClientScheduler.getInstance().scheduleMedHighAtFixedRate( 				new TimerWatcher(), 0, 1000); 		ClientScheduler.getInstance().scheduleLowAtFixedRate( 				new BroadcastSunState(), 0, 60*60*1000@@ -151,7 +151,7 @@ 		// Create a task to update the _knownObject and _knowPlayers of each L2Character that finished its movement and of their already known L2Object  		// then notify AI with EVT_ARRIVED 		if (ended != null)-			ClientScheduler.getInstance().scheduleLow(new MovingObjectArrived(ended), 10);+			ClientScheduler.getInstance().scheduleMed(new MovingObjectArrived(ended), 10); 		 	} 	@@ -169,7 +169,7 @@ 		{ 			super("TimerThread"); 			setDaemon(true);-			setPriority(MAX_PRIORITY);+			setPriority(MAX_PRIORITY-1); 			_stop = false; 			_error = null; 		}