diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/AbstractAI.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/AbstractAI.java index c93d880320..1246e8e150 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/AbstractAI.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/AbstractAI.java @@ -944,5 +944,4 @@ abstract class AbstractAI implements Ctrl { return _intention; } - } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/PlayerAI.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/PlayerAI.java index b72f90e04e..f3e2a1c8fb 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/PlayerAI.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/ai/PlayerAI.java @@ -26,14 +26,12 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST; import java.util.EmptyStackException; import java.util.Stack; -import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.model.Skill; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature.AIAccessor; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.StaticObjectInstance; -import org.l2jmobius.gameserver.model.actor.knownlist.WorldObjectKnownList.KnownListAsynchronousUpdateTask; public class PlayerAI extends CreatureAI { @@ -336,7 +334,10 @@ public class PlayerAI extends CreatureAI @Override protected void onEvtArrivedRevalidate() { - ThreadPool.execute(new KnownListAsynchronousUpdateTask(_actor)); + if (_actor != null) + { + _actor.getKnownList().updateKnownObjects(); + } super.onEvtArrivedRevalidate(); } } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java index f61c57e9b6..6973533fbd 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -81,7 +81,6 @@ import org.l2jmobius.gameserver.model.actor.instance.RiftInvaderInstance; import org.l2jmobius.gameserver.model.actor.instance.SiegeFlagInstance; import org.l2jmobius.gameserver.model.actor.instance.SummonInstance; import org.l2jmobius.gameserver.model.actor.knownlist.CreatureKnownList; -import org.l2jmobius.gameserver.model.actor.knownlist.WorldObjectKnownList.KnownListAsynchronousUpdateTask; import org.l2jmobius.gameserver.model.actor.stat.CreatureStat; import org.l2jmobius.gameserver.model.actor.status.CreatureStatus; import org.l2jmobius.gameserver.model.actor.templates.CreatureTemplate; @@ -5638,7 +5637,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder if (updateKnownObjects) { - ThreadPool.execute(new KnownListAsynchronousUpdateTask(this)); + getKnownList().updateKnownObjects(); } } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/PlayerKnownList.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/PlayerKnownList.java index 5415dca8cc..9503c1e1cd 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/PlayerKnownList.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/PlayerKnownList.java @@ -254,8 +254,8 @@ public class PlayerKnownList extends PlayableKnownList // TEMP FIX: If player is not visible don't send packets broadcast to all his KnowList. This will avoid GM detection with l2net and olympiad's crash. We can now find old problems with invisible mode. if ((player != null) && !activeChar.isGM()) - { // GM has to receive remove however because he can see any invisible or inobservermode player - + { + // GM has to receive remove however because he can see any invisible or inobservermode player if (!player.getAppearance().isInvisible() && !player.inObserverMode()) { // Send Server-Client Packet DeleteObject to the PlayerInstance @@ -269,7 +269,6 @@ public class PlayerKnownList extends PlayableKnownList } else // All other objects has to be removed { - // Send Server-Client Packet DeleteObject to the PlayerInstance activeChar.sendPacket(new DeleteObject(object)); } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/WorldObjectKnownList.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/WorldObjectKnownList.java index a3b7905e8c..2315c3438e 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/WorldObjectKnownList.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/gameserver/model/actor/knownlist/WorldObjectKnownList.java @@ -19,10 +19,11 @@ package org.l2jmobius.gameserver.model.actor.knownlist; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.l2jmobius.commons.concurrent.ThreadPool; +import org.l2jmobius.commons.util.Rnd; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Creature; -import org.l2jmobius.gameserver.model.actor.Playable; import org.l2jmobius.gameserver.model.actor.instance.BoatInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.util.Util; @@ -116,36 +117,56 @@ public class WorldObjectKnownList private final void findCloseObjects() { - if (_activeObject instanceof Playable) + if (_activeObject == null) { + return; + } + + if (_activeObject.isPlayable()) + { + int delay = 0; + // Go through all visible WorldObject near the Creature for (WorldObject object : World.getInstance().getVisibleObjects(_activeObject)) { - if (object == null) + // Delay is broken down to 100ms intervals. + // With the random time added it gives at least 50ms between tasks. + if (delay >= 5000) { - continue; + delay = 0; } + delay += 100; - // Try to add object to active object's known objects - // PlayableInstance sees everything - addKnownObject(object); - - // Try to add active object to object's known objects - // Only if object is a Creature and active object is a PlayableInstance - if (object instanceof Creature) + // Send packets asynchronously. (Obviously heavier on CPU, but significantly reduces network spikes.) + // On retail there is a similar, if not greater, delay as well. + ThreadPool.schedule(() -> { - object.getKnownList().addKnownObject(_activeObject); - } + if (object == null) + { + return; + } + + // Try to add object to active object's known objects + // PlayableInstance sees everything + addKnownObject(object); + + // Try to add active object to object's known objects + // Only if object is a Creature and active object is a PlayableInstance + if (object instanceof Creature) + { + object.getKnownList().addKnownObject(_activeObject); + } + }, delay + Rnd.get(50)); // Add additional 0-49ms in case of overlapping tasks on heavy load. } } - else if (_activeObject != null) + else { // Go through all visible WorldObject near the Creature for (WorldObject playable : World.getInstance().getVisiblePlayers(_activeObject)) { if (playable == null) { - continue; + return; } // Try to add object to active object's known objects @@ -166,23 +187,20 @@ public class WorldObjectKnownList continue; } - // Remove all invisible object - // Remove all too far object + // Remove all invisible objects + // Remove all too far objects if (!object.isVisible() || !Util.checkIfInRange(getDistanceToForgetObject(object), _activeObject, object, true)) { if ((object instanceof BoatInstance) && (_activeObject instanceof PlayerInstance)) { if (((BoatInstance) object).getVehicleDeparture() == null) { - // + continue; } - else if (((PlayerInstance) _activeObject).isInBoat()) + + if (((PlayerInstance) _activeObject).isInBoat()) { - if (((PlayerInstance) _activeObject).getBoat() == object) - { - // - } - else + if (((PlayerInstance) _activeObject).getBoat() != object) { removeKnownObject(object); } @@ -222,23 +240,4 @@ public class WorldObjectKnownList { return _knownObjects; } - - public static class KnownListAsynchronousUpdateTask implements Runnable - { - private final WorldObject _obj; - - public KnownListAsynchronousUpdateTask(WorldObject obj) - { - _obj = obj; - } - - @Override - public void run() - { - if (_obj != null) - { - _obj.getKnownList().updateKnownObjects(); - } - } - } }