Bläddra i källkod

BETA: Reworked `DecayTaskManager`.
* Changed "too old corpse" condition on retail its 2 seconds before corpse disappears.

Reviewed by: !UnAfraid, !Adry_85

Nos 11 år sedan
förälder
incheckning
c79b2cfbdb

+ 3 - 2
L2J_Server_BETA/dist/game/config/NPC.properties

@@ -101,8 +101,9 @@ DefaultCorpseTime = 7
 # Default: 10
 SpoiledCorpseExtendTime = 10
 
-# Default: 15000
-MaxSweeperTime = 15000
+# The time allowed to use a corpse consume skill before the corpse decays.
+# Default: 2000
+CorpseConsumeSkillAllowedTimeBeforeDecay = 2000
 
 # ---------------------------------------------------------------------------
 # Guards

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/Config.java

@@ -808,7 +808,7 @@ public final class Config
 	public static int DECAY_TIME_TASK;
 	public static int DEFAULT_CORPSE_TIME;
 	public static int SPOILED_CORPSE_EXTEND_TIME;
-	public static int MAX_SWEEPER_TIME;
+	public static int CORPSE_CONSUME_SKILL_ALLOWED_TIME_BEFORE_DECAY;
 	public static boolean GUARD_ATTACK_AGGRO_MOB;
 	public static boolean ALLOW_WYVERN_UPGRADER;
 	public static List<Integer> LIST_PET_RENT_NPC;
@@ -2043,7 +2043,7 @@ public final class Config
 			DECAY_TIME_TASK = NPC.getInt("DecayTimeTask", 5000);
 			DEFAULT_CORPSE_TIME = NPC.getInt("DefaultCorpseTime", 7);
 			SPOILED_CORPSE_EXTEND_TIME = NPC.getInt("SpoiledCorpseExtendTime", 10);
-			MAX_SWEEPER_TIME = NPC.getInt("MaxSweeperTime", 15000);
+			CORPSE_CONSUME_SKILL_ALLOWED_TIME_BEFORE_DECAY = NPC.getInt("CorpseConsumeSkillAllowedTimeBeforeDecay", 2000);
 			GUARD_ATTACK_AGGRO_MOB = NPC.getBoolean("GuardAttackAggroMob", false);
 			ALLOW_WYVERN_UPGRADER = NPC.getBoolean("AllowWyvernUpgrader", false);
 			String[] listPetRentNpc = NPC.getString("ListPetRentNpc", "30827").split(",");

+ 4 - 4
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Attackable.java

@@ -1220,15 +1220,15 @@ public class L2Attackable extends L2Npc
 	}
 	
 	/**
-	 * Check if the corpse is too old.
+	 * Checks if the corpse is too old.
 	 * @param attacker the player to validate
-	 * @param time the time to check
+	 * @param remainingTime the time to check
 	 * @param sendMessage if {@code true} will send a message of corpse too old
 	 * @return {@code true} if the corpse is too old
 	 */
-	public boolean isOldCorpse(L2PcInstance attacker, int time, boolean sendMessage)
+	public boolean isOldCorpse(L2PcInstance attacker, int remainingTime, boolean sendMessage)
 	{
-		if (DecayTaskManager.getInstance().getTasks().containsKey(this) && ((System.currentTimeMillis() - DecayTaskManager.getInstance().getTasks().get(this)) > time))
+		if (isDead() && (DecayTaskManager.getInstance().getRemainingTime(this) < remainingTime))
 		{
 			if (sendMessage && (attacker != null))
 			{

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Decoy.java

@@ -69,7 +69,7 @@ public abstract class L2Decoy extends L2Character
 	
 	public void stopDecay()
 	{
-		DecayTaskManager.getInstance().cancelDecayTask(this);
+		DecayTaskManager.getInstance().cancel(this);
 	}
 	
 	@Override

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Npc.java

@@ -1365,7 +1365,7 @@ public class L2Npc extends L2Character
 		_currentRHandId = getTemplate().getRHandId();
 		_currentCollisionHeight = getTemplate().getfCollisionHeight();
 		_currentCollisionRadius = getTemplate().getfCollisionRadius();
-		DecayTaskManager.getInstance().addDecayTask(this);
+		DecayTaskManager.getInstance().add(this);
 		return true;
 	}
 	
@@ -1513,7 +1513,7 @@ public class L2Npc extends L2Character
 	{
 		if (!isDecayed())
 		{
-			DecayTaskManager.getInstance().cancelDecayTask(this);
+			DecayTaskManager.getInstance().cancel(this);
 			onDecay();
 		}
 	}

+ 3 - 3
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/L2Summon.java

@@ -374,7 +374,7 @@ public abstract class L2Summon extends L2Playable
 			getOwner().reviveRequest(getOwner(), null, true, 100);
 		}
 		
-		DecayTaskManager.getInstance().addDecayTask(this);
+		DecayTaskManager.getInstance().add(this);
 		return true;
 	}
 	
@@ -386,14 +386,14 @@ public abstract class L2Summon extends L2Playable
 		}
 		if (!decayed)
 		{
-			DecayTaskManager.getInstance().addDecayTask(this);
+			DecayTaskManager.getInstance().add(this);
 		}
 		return true;
 	}
 	
 	public void stopDecay()
 	{
-		DecayTaskManager.getInstance().cancelDecayTask(this);
+		DecayTaskManager.getInstance().cancel(this);
 	}
 	
 	@Override

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2DecoyInstance.java

@@ -62,7 +62,7 @@ public class L2DecoyInstance extends L2Decoy
 			_HateSpam = null;
 		}
 		_totalLifeTime = 0;
-		DecayTaskManager.getInstance().addDecayTask(this);
+		DecayTaskManager.getInstance().add(this);
 		return true;
 	}
 	

+ 2 - 2
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2PetInstance.java

@@ -688,7 +688,7 @@ public class L2PetInstance extends L2Summon
 		}
 		stopFeed();
 		sendPacket(SystemMessageId.MAKE_SURE_YOU_RESSURECT_YOUR_PET_WITHIN_24_HOURS);
-		DecayTaskManager.getInstance().addDecayTask(this);
+		DecayTaskManager.getInstance().add(this);
 		// do not decrease exp if is in duel, arena
 		L2PcInstance owner = getOwner();
 		if ((owner != null) && !owner.isInDuel() && (!isInsideZone(ZoneId.PVP) || isInsideZone(ZoneId.SIEGE)))
@@ -706,7 +706,7 @@ public class L2PetInstance extends L2Summon
 		super.doRevive();
 		
 		// stopDecay
-		DecayTaskManager.getInstance().cancelDecayTask(this);
+		DecayTaskManager.getInstance().cancel(this);
 		startFeed();
 		if (!isHungry())
 		{

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/actor/instance/L2TrapInstance.java

@@ -373,7 +373,7 @@ public final class L2TrapInstance extends L2Npc
 	
 	public void stopDecay()
 	{
-		DecayTaskManager.getInstance().cancelDecayTask(this);
+		DecayTaskManager.getInstance().cancel(this);
 	}
 	
 	/**

+ 1 - 1
L2J_Server_BETA/java/com/l2jserver/gameserver/model/conditions/ConditionPlayerCanSweep.java

@@ -71,7 +71,7 @@ public class ConditionPlayerCanSweep extends Condition
 								if (target.isSpoil())
 								{
 									canSweep = target.checkSpoilOwner(sweeper, true);
-									canSweep &= !target.isOldCorpse(sweeper, Config.MAX_SWEEPER_TIME, true);
+									canSweep &= !target.isOldCorpse(sweeper, Config.CORPSE_CONSUME_SKILL_ALLOWED_TIME_BEFORE_DECAY, true);
 									canSweep &= sweeper.getInventory().checkInventorySlotsAndWeight(target.getSpoilLootItems(), true, true);
 								}
 								else

+ 101 - 73
L2J_Server_BETA/java/com/l2jserver/gameserver/taskmanager/DecayTaskManager.java

@@ -18,97 +18,130 @@
  */
 package com.l2jserver.gameserver.taskmanager;
 
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javolution.util.FastMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 import com.l2jserver.Config;
-import com.l2jserver.gameserver.ThreadPoolManager;
 import com.l2jserver.gameserver.model.actor.L2Attackable;
 import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
 
 /**
- * @author la2 Lets drink to code!
+ * @author Nos
  */
-public class DecayTaskManager
+public final class DecayTaskManager
 {
-	protected static final Logger _log = Logger.getLogger(DecayTaskManager.class.getName());
+	private final ScheduledExecutorService _decayExecutor = Executors.newSingleThreadScheduledExecutor();
 	
-	protected final Map<L2Character, Long> _decayTasks = new FastMap<L2Character, Long>().shared();
+	protected final Map<L2Character, ScheduledFuture<?>> _decayTasks = new ConcurrentHashMap<>();
 	
-	protected DecayTaskManager()
+	/**
+	 * Adds a decay task for the specified character.<br>
+	 * <br>
+	 * If the decay task already exists it cancels it and re-adds it.
+	 * @param character the character
+	 */
+	public void add(L2Character character)
 	{
-		ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new DecayScheduler(), 10000, Config.DECAY_TIME_TASK);
+		if (character == null)
+		{
+			return;
+		}
+		
+		long delay;
+		if (character.getTemplate() instanceof L2NpcTemplate)
+		{
+			delay = ((L2NpcTemplate) character.getTemplate()).getCorpseTime();
+		}
+		else
+		{
+			delay = Config.DEFAULT_CORPSE_TIME;
+		}
+		
+		if ((character instanceof L2Attackable) && (((L2Attackable) character).isSpoil() || ((L2Attackable) character).isSeeded()))
+		{
+			delay += Config.SPOILED_CORPSE_EXTEND_TIME;
+		}
+		
+		add(character, delay, TimeUnit.SECONDS);
 	}
 	
-	public static DecayTaskManager getInstance()
+	/**
+	 * Adds a decay task for the specified character.<br>
+	 * <br>
+	 * If the decay task already exists it cancels it and re-adds it.
+	 * @param character the character
+	 * @param delay the delay
+	 * @param timeUnit the time unit of the delay parameter
+	 */
+	public void add(L2Character character, long delay, TimeUnit timeUnit)
 	{
-		return SingletonHolder._instance;
+		ScheduledFuture<?> decayTask = _decayExecutor.schedule(new DecayTask(character), delay, TimeUnit.SECONDS);
+		
+		decayTask = _decayTasks.put(character, decayTask);
+		// if decay task already existed cancel it so we use the new time
+		if (decayTask != null)
+		{
+			if (!decayTask.cancel(false))
+			{
+				// old decay task was completed while canceling it remove and cancel the new one
+				decayTask = _decayTasks.remove(character);
+				if (decayTask != null)
+				{
+					decayTask.cancel(false);
+				}
+			}
+		}
 	}
 	
-	public void addDecayTask(L2Character actor)
+	/**
+	 * Cancels the decay task of the specified character.
+	 * @param character the character
+	 */
+	public void cancel(L2Character character)
 	{
-		_decayTasks.put(actor, System.currentTimeMillis());
+		final ScheduledFuture<?> decayTask = _decayTasks.remove(character);
+		if (decayTask != null)
+		{
+			decayTask.cancel(false);
+		}
 	}
 	
-	public void cancelDecayTask(L2Character actor)
+	/**
+	 * Gets the remaining time of the specified character's decay task.
+	 * @param character the character
+	 * @return if a decay task exists the remaining time, {@code Long.MAX_VALUE} otherwise
+	 */
+	public long getRemainingTime(L2Character character)
 	{
-		_decayTasks.remove(actor);
+		final ScheduledFuture<?> decayTask = _decayTasks.get(character);
+		if (decayTask != null)
+		{
+			return decayTask.getDelay(TimeUnit.MILLISECONDS);
+		}
+		
+		return Long.MAX_VALUE;
 	}
 	
-	protected class DecayScheduler implements Runnable
+	private class DecayTask implements Runnable
 	{
+		private final L2Character _character;
+		
+		protected DecayTask(L2Character character)
+		{
+			_character = character;
+		}
+		
 		@Override
 		public void run()
 		{
-			final long current = System.currentTimeMillis();
-			try
-			{
-				final Iterator<Entry<L2Character, Long>> it = _decayTasks.entrySet().iterator();
-				Entry<L2Character, Long> e;
-				L2Character actor;
-				Long next;
-				int delay;
-				while (it.hasNext())
-				{
-					e = it.next();
-					actor = e.getKey();
-					next = e.getValue();
-					if ((actor == null) || (next == null))
-					{
-						continue;
-					}
-					if (actor.getTemplate() instanceof L2NpcTemplate)
-					{
-						delay = ((L2NpcTemplate) actor.getTemplate()).getCorpseTime() * 1000;
-					}
-					else
-					{
-						delay = Config.DEFAULT_CORPSE_TIME * 1000;
-					}
-					
-					if ((actor instanceof L2Attackable) && (((L2Attackable) actor).isSpoil() || ((L2Attackable) actor).isSeeded()))
-					{
-						delay += Config.SPOILED_CORPSE_EXTEND_TIME * 1000;
-					}
-					
-					if ((current - next) > delay)
-					{
-						actor.onDecay();
-						it.remove();
-					}
-				}
-			}
-			catch (Exception e)
-			{
-				// TODO: Find out the reason for exception. Unless caught here, mob decay would stop.
-				_log.log(Level.WARNING, "Error in DecayScheduler: " + e.getMessage(), e);
-			}
+			_decayTasks.remove(_character);
+			_character.onDecay();
 		}
 	}
 	
@@ -124,28 +157,23 @@ public class DecayTaskManager
 		ret.append("Tasks dump:");
 		ret.append(Config.EOL);
 		
-		Long current = System.currentTimeMillis();
-		for (L2Character actor : _decayTasks.keySet())
+		for (Entry<L2Character, ScheduledFuture<?>> entry : _decayTasks.entrySet())
 		{
 			ret.append("Class/Name: ");
-			ret.append(actor.getClass().getSimpleName());
+			ret.append(entry.getKey().getClass().getSimpleName());
 			ret.append('/');
-			ret.append(actor.getName());
+			ret.append(entry.getKey().getName());
 			ret.append(" decay timer: ");
-			ret.append(current - _decayTasks.get(actor));
+			ret.append(entry.getValue().getDelay(TimeUnit.MILLISECONDS));
 			ret.append(Config.EOL);
 		}
 		
 		return ret.toString();
 	}
 	
-	/**
-	 * <u><b><font color="FF0000">Read only</font></b></u>
-	 * @return
-	 */
-	public Map<L2Character, Long> getTasks()
+	public static DecayTaskManager getInstance()
 	{
-		return _decayTasks;
+		return SingletonHolder._instance;
 	}
 	
 	private static class SingletonHolder