Delay tasks for frequent packet broadcasts.

This commit is contained in:
MobiusDevelopment
2022-07-31 02:00:10 +00:00
parent 9280c9ca3a
commit b6fe06aa07
194 changed files with 4346 additions and 2781 deletions

View File

@@ -94,8 +94,8 @@ public class EffectList
private final Creature _owner;
/** Hidden buffs count, prevents iterations. */
private final AtomicInteger _hiddenBuffs = new AtomicInteger();
private ScheduledFuture<?> _effectIconsUpdate;
/** Delay task **/
private ScheduledFuture<?> _updateEffectIconTask;
/**
* Constructor for effect list.
@@ -1529,140 +1529,137 @@ public class EffectList
return;
}
// Check if the previous call hasnt finished, if so, don't send packets uselessly again.
if ((_effectIconsUpdate != null) && !_effectIconsUpdate.isDone())
if (_updateEffectIconTask == null)
{
return;
}
// Schedule the icon update packets 500miliseconds ahead, so it can gather-up most of the changes.
_effectIconsUpdate = ThreadPool.schedule(() ->
{
AbnormalStatusUpdate asu = null;
PartySpelled ps = null;
PartySpelled psSummon = null;
ExOlympiadSpelledInfo os = null;
boolean isSummon = false;
if (_owner.isPlayer())
_updateEffectIconTask = ThreadPool.schedule(() ->
{
if (_partyOnly)
{
_partyOnly = false;
}
else
{
asu = new AbnormalStatusUpdate();
}
AbnormalStatusUpdate asu = null;
PartySpelled ps = null;
PartySpelled psSummon = null;
ExOlympiadSpelledInfo os = null;
boolean isSummon = false;
if (_owner.isInParty())
if (_owner.isPlayer())
{
ps = new PartySpelled(_owner);
}
if (_owner.getActingPlayer().isInOlympiadMode() && _owner.getActingPlayer().isOlympiadStart())
{
os = new ExOlympiadSpelledInfo(_owner.getActingPlayer());
}
}
else if (_owner.isSummon())
{
isSummon = true;
ps = new PartySpelled(_owner);
psSummon = new PartySpelled(_owner);
}
// Buffs.
if (hasBuffs())
{
for (BuffInfo info : _buffs)
{
if (info.getSkill().isHealingPotionSkill())
if (_partyOnly)
{
shortBuffStatusUpdate(info);
_partyOnly = false;
}
else
{
asu = new AbnormalStatusUpdate();
}
if (_owner.isInParty())
{
ps = new PartySpelled(_owner);
}
if (_owner.getActingPlayer().isInOlympiadMode() && _owner.getActingPlayer().isOlympiadStart())
{
os = new ExOlympiadSpelledInfo(_owner.getActingPlayer());
}
}
else if (_owner.isSummon())
{
isSummon = true;
ps = new PartySpelled(_owner);
psSummon = new PartySpelled(_owner);
}
// Buffs.
if (hasBuffs())
{
for (BuffInfo info : _buffs)
{
if (info.getSkill().isHealingPotionSkill())
{
shortBuffStatusUpdate(info);
}
else
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
}
// Triggered buffs.
if (hasTriggered())
{
for (BuffInfo info : _triggered)
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
}
// Triggered buffs.
if (hasTriggered())
{
for (BuffInfo info : _triggered)
// Songs and dances.
if (hasDances())
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
// Songs and dances.
if (hasDances())
{
for (BuffInfo info : _dances)
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
// Toggles.
if (hasToggles())
{
for (BuffInfo info : _toggles)
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
// Debuffs.
if (hasDebuffs())
{
for (BuffInfo info : _debuffs)
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
if (asu != null)
{
_owner.sendPacket(asu);
}
if (ps != null)
{
if (_owner.isSummon())
{
final Player summonOwner = ((Summon) _owner).getOwner();
if (summonOwner != null)
for (BuffInfo info : _dances)
{
if (summonOwner.isInParty())
{
summonOwner.getParty().broadcastToPartyMembers(summonOwner, psSummon); // send to all member except summonOwner
summonOwner.sendPacket(ps); // now send to summonOwner
}
else
{
summonOwner.sendPacket(ps);
}
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
else if (_owner.isPlayer() && _owner.isInParty())
// Toggles.
if (hasToggles())
{
_owner.getParty().broadcastPacket(ps);
for (BuffInfo info : _toggles)
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
}
if (os != null)
{
final OlympiadGameTask game = OlympiadGameManager.getInstance().getOlympiadTask(_owner.getActingPlayer().getOlympiadGameId());
if ((game != null) && game.isBattleStarted())
// Debuffs.
if (hasDebuffs())
{
game.getZone().broadcastPacketToObservers(os);
for (BuffInfo info : _debuffs)
{
addIcon(info, asu, ps, psSummon, os, isSummon);
}
}
}
_effectIconsUpdate = null;
}, 500);
if (asu != null)
{
_owner.sendPacket(asu);
}
if (ps != null)
{
if (_owner.isSummon())
{
final Player summonOwner = ((Summon) _owner).getOwner();
if (summonOwner != null)
{
if (summonOwner.isInParty())
{
summonOwner.getParty().broadcastToPartyMembers(summonOwner, psSummon); // send to all member except summonOwner
summonOwner.sendPacket(ps); // now send to summonOwner
}
else
{
summonOwner.sendPacket(ps);
}
}
}
else if (_owner.isPlayer() && _owner.isInParty())
{
_owner.getParty().broadcastPacket(ps);
}
}
if (os != null)
{
final OlympiadGameTask game = OlympiadGameManager.getInstance().getOlympiadTask(_owner.getActingPlayer().getOlympiadGameId());
if ((game != null) && game.isBattleStarted())
{
game.getZone().broadcastPacketToObservers(os);
}
}
_updateEffectIconTask = null;
}, 300);
}
}
private void addIcon(BuffInfo info, AbnormalStatusUpdate asu, PartySpelled ps, PartySpelled psSummon, ExOlympiadSpelledInfo os, boolean isSummon)

View File

@@ -442,6 +442,8 @@ public class Player extends Playable
private long _lastAccess;
private long _uptime;
private ScheduledFuture<?> _skillListTask;
private boolean _subclassLock = false;
protected int _baseClass;
protected int _activeClass;
@@ -9932,77 +9934,84 @@ public class Player extends Playable
public void sendSkillList()
{
boolean isDisabled = false;
final SkillList sl = new SkillList();
for (Skill s : getAllSkills())
if (_skillListTask == null)
{
if ((s == null) || ((_transformation != null) && !s.isPassive()) || (hasTransformSkill(s.getId()) && s.isPassive()))
_skillListTask = ThreadPool.schedule(() ->
{
continue;
}
if (_clan != null)
{
isDisabled = s.isClanSkill() && (_clan.getReputationScore() < 0);
}
boolean isEnchantable = SkillData.getInstance().isEnchantable(s.getId());
if (isEnchantable)
{
final EnchantSkillLearn esl = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(s.getId());
if ((esl == null) || (s.getLevel() < esl.getBaseLevel()))
boolean isDisabled = false;
final SkillList skillList = new SkillList();
for (Skill skill : getAllSkills())
{
isEnchantable = false;
}
}
sl.addSkill(s.getDisplayId(), s.getDisplayLevel(), s.isPassive(), isDisabled, isEnchantable);
}
if (_transformation != null)
{
final Map<Integer, Integer> ts = new TreeMap<>();
for (SkillHolder holder : _transformation.getTemplate(this).getSkills())
{
ts.putIfAbsent(holder.getSkillId(), holder.getSkillLevel());
if (ts.get(holder.getSkillId()) < holder.getSkillLevel())
{
ts.put(holder.getSkillId(), holder.getSkillLevel());
}
}
for (AdditionalSkillHolder holder : _transformation.getTemplate(this).getAdditionalSkills())
{
if (getLevel() >= holder.getMinLevel())
{
ts.putIfAbsent(holder.getSkillId(), holder.getSkillLevel());
if (ts.get(holder.getSkillId()) < holder.getSkillLevel())
if ((skill == null) || ((_transformation != null) && !skill.isPassive()) || (hasTransformSkill(skill.getId()) && skill.isPassive()))
{
ts.put(holder.getSkillId(), holder.getSkillLevel());
continue;
}
if (_clan != null)
{
isDisabled = skill.isClanSkill() && (_clan.getReputationScore() < 0);
}
boolean isEnchantable = SkillData.getInstance().isEnchantable(skill.getId());
if (isEnchantable)
{
final EnchantSkillLearn esl = EnchantSkillGroupsData.getInstance().getSkillEnchantmentBySkillId(skill.getId());
if ((esl == null) || (skill.getLevel() < esl.getBaseLevel()))
{
isEnchantable = false;
}
}
skillList.addSkill(skill.getDisplayId(), skill.getDisplayLevel(), skill.isPassive(), isDisabled, isEnchantable);
}
if (_transformation != null)
{
final Map<Integer, Integer> ts = new TreeMap<>();
for (SkillHolder holder : _transformation.getTemplate(this).getSkills())
{
ts.putIfAbsent(holder.getSkillId(), holder.getSkillLevel());
if (ts.get(holder.getSkillId()) < holder.getSkillLevel())
{
ts.put(holder.getSkillId(), holder.getSkillLevel());
}
}
for (AdditionalSkillHolder holder : _transformation.getTemplate(this).getAdditionalSkills())
{
if (getLevel() >= holder.getMinLevel())
{
ts.putIfAbsent(holder.getSkillId(), holder.getSkillLevel());
if (ts.get(holder.getSkillId()) < holder.getSkillLevel())
{
ts.put(holder.getSkillId(), holder.getSkillLevel());
}
}
}
// Add collection skills.
if (_transformation.isFlying())
{
for (SkillLearn skill : SkillTreeData.getInstance().getCollectSkillTree().values())
{
if ((getKnownSkill(skill.getSkillId()) != null) && (!ts.containsKey(skill.getSkillId()) || (ts.get(skill.getSkillId()) < skill.getSkillLevel())))
{
ts.put(skill.getSkillId(), skill.getSkillLevel());
}
}
}
for (Entry<Integer, Integer> transformSkill : ts.entrySet())
{
final Skill sk = SkillData.getInstance().getSkill(transformSkill.getKey(), transformSkill.getValue());
addTransformSkill(sk);
skillList.addSkill(transformSkill.getKey(), transformSkill.getValue(), false, false, false);
}
}
}
// Add collection skills.
if (_transformation.isFlying())
{
for (SkillLearn skill : SkillTreeData.getInstance().getCollectSkillTree().values())
{
if ((getKnownSkill(skill.getSkillId()) != null) && (!ts.containsKey(skill.getSkillId()) || (ts.get(skill.getSkillId()) < skill.getSkillLevel())))
{
ts.put(skill.getSkillId(), skill.getSkillLevel());
}
}
}
for (Entry<Integer, Integer> transformSkill : ts.entrySet())
{
final Skill sk = SkillData.getInstance().getSkill(transformSkill.getKey(), transformSkill.getValue());
addTransformSkill(sk);
sl.addSkill(transformSkill.getKey(), transformSkill.getValue(), false, false, false);
}
sendPacket(skillList);
_skillListTask = null;
}, 300);
}
sendPacket(sl);
}
/**

View File

@@ -16,7 +16,11 @@
*/
package org.l2jmobius.gameserver.model.actor;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
import org.l2jmobius.Config;
import org.l2jmobius.commons.threads.ThreadPool;
import org.l2jmobius.commons.util.CommonUtil;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.ai.CreatureAI;
@@ -78,6 +82,9 @@ public abstract class Summon extends Playable
private boolean _previousFollowStatus = true;
protected boolean _restoreSummon = true;
private int _shotsMask = 0;
private ScheduledFuture<?> _abnormalEffectTask;
private ScheduledFuture<?> _statusUpdateTask;
private final AtomicInteger _statusUpdateValue = new AtomicInteger();
// @formatter:off
private static final int[] PASSIVE_SUMMONS =
@@ -194,7 +201,17 @@ public abstract class Summon extends Playable
@Override
public void updateAbnormalEffect()
{
World.getInstance().forEachVisibleObject(this, Player.class, player -> player.sendPacket(new SummonInfo(this, player, 1)));
if (_abnormalEffectTask == null)
{
_abnormalEffectTask = ThreadPool.schedule(() ->
{
if (isSpawned())
{
World.getInstance().forEachVisibleObject(this, Player.class, player -> player.sendPacket(new SummonInfo(this, player, 1)));
}
_abnormalEffectTask = null;
}, 50);
}
}
/**
@@ -837,18 +854,28 @@ public abstract class Summon extends Playable
return;
}
sendPacket(new PetInfo(this, value));
sendPacket(new PetStatusUpdate(this));
if (isSpawned())
_statusUpdateValue.set(value);
if (_statusUpdateTask == null)
{
broadcastNpcInfo(value);
_statusUpdateTask = ThreadPool.schedule(() ->
{
if (isSpawned())
{
sendPacket(new PetInfo(this, _statusUpdateValue.get()));
sendPacket(new PetStatusUpdate(this));
broadcastNpcInfo(_statusUpdateValue.get());
final Party party = _owner.getParty();
if (party != null)
{
party.broadcastToPartyMembers(_owner, new ExPartyPetWindowUpdate(this));
}
updateEffectIcons(true);
}
_statusUpdateTask = null;
}, 50);
}
final Party party = _owner.getParty();
if (party != null)
{
party.broadcastToPartyMembers(_owner, new ExPartyPetWindowUpdate(this));
}
updateEffectIcons(true);
}
public void broadcastNpcInfo(int value)