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

View File

@ -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();
}
}

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.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();
}
}

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

View File

@ -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();
}
}
}
}