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; }