Break down player knownlist packet broadcasts in small timed bursts.

This commit is contained in:
MobiusDevelopment 2020-02-09 11:00:17 +00:00
parent d012499998
commit 60b928e969
5 changed files with 49 additions and 52 deletions

View File

@ -944,5 +944,4 @@ abstract class AbstractAI implements Ctrl
{ {
return _intention; return _intention;
} }
} }

View File

@ -26,14 +26,12 @@ import static org.l2jmobius.gameserver.ai.CtrlIntention.AI_INTENTION_REST;
import java.util.EmptyStackException; import java.util.EmptyStackException;
import java.util.Stack; import java.util.Stack;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.Skill; import org.l2jmobius.gameserver.model.Skill;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Creature.AIAccessor; import org.l2jmobius.gameserver.model.actor.Creature.AIAccessor;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.instance.StaticObjectInstance; import org.l2jmobius.gameserver.model.actor.instance.StaticObjectInstance;
import org.l2jmobius.gameserver.model.actor.knownlist.WorldObjectKnownList.KnownListAsynchronousUpdateTask;
public class PlayerAI extends CreatureAI public class PlayerAI extends CreatureAI
{ {
@ -336,7 +334,10 @@ public class PlayerAI extends CreatureAI
@Override @Override
protected void onEvtArrivedRevalidate() protected void onEvtArrivedRevalidate()
{ {
ThreadPool.execute(new KnownListAsynchronousUpdateTask(_actor)); if (_actor != null)
{
_actor.getKnownList().updateKnownObjects();
}
super.onEvtArrivedRevalidate(); super.onEvtArrivedRevalidate();
} }
} }

View File

@ -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.SiegeFlagInstance;
import org.l2jmobius.gameserver.model.actor.instance.SummonInstance; import org.l2jmobius.gameserver.model.actor.instance.SummonInstance;
import org.l2jmobius.gameserver.model.actor.knownlist.CreatureKnownList; 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.stat.CreatureStat;
import org.l2jmobius.gameserver.model.actor.status.CreatureStatus; import org.l2jmobius.gameserver.model.actor.status.CreatureStatus;
import org.l2jmobius.gameserver.model.actor.templates.CreatureTemplate; import org.l2jmobius.gameserver.model.actor.templates.CreatureTemplate;
@ -5638,7 +5637,7 @@ public abstract class Creature extends WorldObject implements ISkillsHolder
if (updateKnownObjects) if (updateKnownObjects)
{ {
ThreadPool.execute(new KnownListAsynchronousUpdateTask(this)); getKnownList().updateKnownObjects();
} }
} }

View File

@ -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. // 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()) 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()) if (!player.getAppearance().isInvisible() && !player.inObserverMode())
{ {
// Send Server-Client Packet DeleteObject to the PlayerInstance // 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 else // All other objects has to be removed
{ {
// Send Server-Client Packet DeleteObject to the PlayerInstance // Send Server-Client Packet DeleteObject to the PlayerInstance
activeChar.sendPacket(new DeleteObject(object)); activeChar.sendPacket(new DeleteObject(object));
} }

View File

@ -19,10 +19,11 @@ package org.l2jmobius.gameserver.model.actor.knownlist;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; 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.World;
import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature; 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.BoatInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.util.Util; import org.l2jmobius.gameserver.util.Util;
@ -116,14 +117,33 @@ public class WorldObjectKnownList
private final void findCloseObjects() 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 // Go through all visible WorldObject near the Creature
for (WorldObject object : World.getInstance().getVisibleObjects(_activeObject)) for (WorldObject object : World.getInstance().getVisibleObjects(_activeObject))
{
// Delay is broken down to 100ms intervals.
// With the random time added it gives at least 50ms between tasks.
if (delay >= 5000)
{
delay = 0;
}
delay += 100;
// 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(() ->
{ {
if (object == null) if (object == null)
{ {
continue; return;
} }
// Try to add object to active object's known objects // Try to add object to active object's known objects
@ -136,16 +156,17 @@ public class WorldObjectKnownList
{ {
object.getKnownList().addKnownObject(_activeObject); 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 // Go through all visible WorldObject near the Creature
for (WorldObject playable : World.getInstance().getVisiblePlayers(_activeObject)) for (WorldObject playable : World.getInstance().getVisiblePlayers(_activeObject))
{ {
if (playable == null) if (playable == null)
{ {
continue; return;
} }
// Try to add object to active object's known objects // Try to add object to active object's known objects
@ -166,23 +187,20 @@ public class WorldObjectKnownList
continue; continue;
} }
// Remove all invisible object // Remove all invisible objects
// Remove all too far object // Remove all too far objects
if (!object.isVisible() || !Util.checkIfInRange(getDistanceToForgetObject(object), _activeObject, object, true)) if (!object.isVisible() || !Util.checkIfInRange(getDistanceToForgetObject(object), _activeObject, object, true))
{ {
if ((object instanceof BoatInstance) && (_activeObject instanceof PlayerInstance)) if ((object instanceof BoatInstance) && (_activeObject instanceof PlayerInstance))
{ {
if (((BoatInstance) object).getVehicleDeparture() == null) if (((BoatInstance) object).getVehicleDeparture() == null)
{ {
// continue;
} }
else if (((PlayerInstance) _activeObject).isInBoat())
if (((PlayerInstance) _activeObject).isInBoat())
{ {
if (((PlayerInstance) _activeObject).getBoat() == object) if (((PlayerInstance) _activeObject).getBoat() != object)
{
//
}
else
{ {
removeKnownObject(object); removeKnownObject(object);
} }
@ -222,23 +240,4 @@ public class WorldObjectKnownList
{ {
return _knownObjects; 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();
}
}
}
} }