meliortt2
Members-
Posts
2 -
Joined
-
Last visited
-
Feedback
0%
About meliortt2

Profile Information
-
Gender
Male
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
meliortt2's Achievements
Iron Initiate (1/17)
-
Rare
-
-
Rare
-
Rare
Recent Badges
-
I want to purchase a classic server package of 520 542 557
-
/* * Copyright (c) 2013 L2jMobius * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.l2jmobius.gameserver.taskmanagers; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.logging.Level; import java.util.logging.Logger; import org.l2jmobius.commons.threads.ThreadPool; import org.l2jmobius.gameserver.config.custom.AutoPlayConfig; import org.l2jmobius.gameserver.data.xml.PetSkillData; import org.l2jmobius.gameserver.handler.IItemHandler; import org.l2jmobius.gameserver.handler.ItemHandler; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Playable; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.instance.Guard; import org.l2jmobius.gameserver.model.item.EtcItem; import org.l2jmobius.gameserver.model.item.ItemTemplate; import org.l2jmobius.gameserver.model.item.instance.Item; import org.l2jmobius.gameserver.model.skill.AbnormalType; import org.l2jmobius.gameserver.model.skill.BuffInfo; import org.l2jmobius.gameserver.model.skill.Skill; import org.l2jmobius.gameserver.model.skill.holders.SkillHolder; import org.l2jmobius.gameserver.model.skill.targets.TargetType; import org.l2jmobius.gameserver.model.zone.ZoneId; /** * @author Mobius (optimized by AI) */ public class AutoUseTaskManager { private static final Logger LOG = Logger.getLogger(AutoUseTaskManager.class.getName()); private static final Set<AutoUse> POOLS = ConcurrentHashMap.newKeySet(); private static final int POOL_SIZE = 200; private static final int TASK_DELAY = 300; private static final int REUSE_MARGIN_TIME = 3; protected AutoUseTaskManager() { } /** * 内部任务类,每个池绑定一个独立任务 */ private class AutoUse implements Runnable { private final Set<Player> _players; private volatile ScheduledFuture<?> _future; private volatile boolean _cancelled = false; public AutoUse(Set<Player> players) { _players = players; } public void setFuture(ScheduledFuture<?> future) { _future = future; } public Set<Player> getPlayers() { return _players; } /** * 取消任务并从全局池中移除自身 */ public void cancelTask() { if (_cancelled) { return; } _cancelled = true; if (_future != null) { _future.cancel(false); } POOLS.remove(this); } @Override public void run() { // 防止任务被取消后仍执行 if (_cancelled) { return; } try { if (_players.isEmpty()) { cancelTask(); return; } // 使用迭代器安全遍历 for (Iterator<Player> it = _players.iterator(); it.hasNext();) { Player player = it.next(); if (!player.isOnline() || (player.isInOfflineMode() && !player.isOfflinePlay())) { it.remove(); continue; } // 跳过不可操作状态 if (player.isSitting() || player.isStunned() || player.isSleeping() || player.isParalyzed() || player.isAfraid() || player.isAlikeDead() || player.isMounted() || (player.isTransformed() && player.getTransformation().isRiding())) { continue; } final boolean isInPeaceZone = player.isInsideZone(ZoneId.PEACE); // 自动物品 if (AutoPlayConfig.ENABLE_AUTO_ITEM && !isInPeaceZone) { processAutoItems(player); } // 自动药水 if (AutoPlayConfig.ENABLE_AUTO_POTION && !isInPeaceZone) { processAutoPotion(player); } // 自动技能(Buff 和攻击) if (AutoPlayConfig.ENABLE_AUTO_SKILL) { processAutoBuffs(player, isInPeaceZone); if (player.isAutoPlaying()) { processAutoSkills(player); } } } // 若池已空,则取消任务 if (_players.isEmpty()) { cancelTask(); } } catch (Throwable t) { LOG.log(Level.SEVERE, "Error in AutoUse task for pool: " + _players, t); } } // ---------- 各处理逻辑拆分 ---------- private void processAutoItems(Player player) { Set<Integer> supplyItems = player.getAutoUseSettings().getAutoSupplyItems(); if (supplyItems == null || supplyItems.isEmpty()) { return; } for (Iterator<Integer> it = supplyItems.iterator(); it.hasNext();) { Integer itemId = it.next(); if (player.isTeleporting()) { break; // 传送中停止处理物品 } final Item item = player.getInventory().getItemByItemId(itemId.intValue()); if (item == null) { it.remove(); continue; } final ItemTemplate template = item.getTemplate(); if ((template == null) || !template.checkCondition(player, player, false)) { continue; } final SkillHolder[] skills = template.getSkills(); if (skills != null) { boolean canUse = true; for (SkillHolder holder : skills) { Skill skill = holder.getSkill(); if (!skill.isActive()) { continue; } if (player.isAffectedBySkill(skill.getId()) || player.hasSkillReuse(skill.getReuseHashCode()) || !skill.checkCondition(player, player, false)) { canUse = false; break; } } if (!canUse) { continue; } } final int reuseDelay = item.getReuseDelay(); if ((reuseDelay <= 0) || (player.getItemRemainingReuseTime(item.getObjectId()) <= 0)) { final IItemHandler handler = ItemHandler.getInstance().getHandler(item.getEtcItem()); if ((handler != null) && handler.onItemUse(player, item, false) && (reuseDelay > 0)) { player.addTimeStampItem(item, reuseDelay); } } } } private void processAutoPotion(Player player) { final int itemId = player.getAutoUseSettings().getAutoPotionItem(); if (itemId <= 0) { return; } if (player.getCurrentHpPercent() >= player.getAutoPlaySettings().getAutoPotionPercent()) { return; } final Item item = player.getInventory().getItemByItemId(itemId); if (item == null) { player.getAutoUseSettings().setAutoPotionItem(0); return; } final int reuseDelay = item.getReuseDelay(); if ((reuseDelay <= 0) || (player.getItemRemainingReuseTime(item.getObjectId()) <= 0)) { final EtcItem etcItem = item.getEtcItem(); final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem); if ((handler != null) && handler.onItemUse(player, item, false) && (reuseDelay > 0)) { player.addTimeStampItem(item, reuseDelay); } } } private void processAutoBuffs(Player player, boolean isInPeaceZone) { Set<Integer> autoBuffs = player.getAutoUseSettings().getAutoBuffs(); if (autoBuffs == null || autoBuffs.isEmpty()) { return; } for (Iterator<Integer> it = autoBuffs.iterator(); it.hasNext();) { Integer skillId = it.next(); // 处于和平区域则跳过当前 Buff(而不是 break) if (isInPeaceZone) { continue; } if (player.isCastingNow() || player.isAttackingNow() || player.isTeleporting()) { continue; } Playable pet = null; Skill skill = player.getKnownSkill(skillId); if (skill == null) { if (player.hasServitor() || player.hasPet()) { final Summon summon = player.getSummon(); skill = summon.getKnownSkill(skillId); if (skill == null) { skill = PetSkillData.getInstance().getKnownSkill(summon, skillId); } if (skill != null) { pet = summon; } } if (skill == null) { it.remove(); // 技能不存在则移除 continue; } } final WorldObject target = player.getTarget(); if (!canCastBuff(player, target, skill)) { continue; } final Playable caster = pet != null ? pet : player; if ((target != null) && target.isPlayable()) { final Player targetPlayer = target.asPlayer(); if (((targetPlayer.getPvpFlag() == 0) && (targetPlayer.getKarma() <= 0)) || (targetPlayer.getParty() == caster.getParty())) { caster.doCast(skill); } else { if (!caster.getEffectList().isAffectedBySkill(skill.getId())) { final WorldObject savedTarget = target; caster.setTarget(caster); caster.doCast(skill); caster.setTarget(savedTarget); } } } else { final WorldObject savedTarget = target; caster.setTarget(caster); caster.doCast(skill); caster.setTarget(savedTarget); } } } private void processAutoSkills(Player player) { final int count = player.getAutoUseSettings().getAutoSkills().size(); if (count == 0) { return; } for (int i = 0; i < count; i++) { if (player.isCastingNow() || player.isTeleporting()) { return; // 正在施法或传送则停止本轮技能尝试 } Playable pet = null; final WorldObject target = player.getTarget(); final Integer skillId = player.getAutoUseSettings().getNextSkillId(); if (skillId == null) { break; } Skill skill = player.getKnownSkill(skillId); if (skill == null) { if (player.hasServitor() || player.hasPet()) { final Summon summon = player.getSummon(); skill = summon.getKnownSkill(skillId); if (skill == null) { skill = PetSkillData.getInstance().getKnownSkill(summon, skillId); } if (skill != null) { pet = summon; pet.setTarget(target); } } if (skill == null) { // 移除无效技能 player.getAutoUseSettings().getAutoSkills().remove(skillId); player.getAutoUseSettings().resetSkillOrder(); break; // 列表变化,重置顺序并退出本轮 } } // 如果目标是玩家自身,则跳过该技能(继续下一个) if (target == player) { player.getAutoUseSettings().incrementSkillOrder(); continue; } // 检查目标有效性 if ((target == null) || target.asCreature().isDead()) { // 清除队列技能 if (player.getQueuedSkill() != null) { player.setQueuedSkill(null, false, false); } player.getAutoUseSettings().incrementSkillOrder(); continue; // 跳过当前技能,尝试下一个 } if (target.isInsideZone(ZoneId.PEACE) || !target.isAutoAttackable(player)) { player.getAutoUseSettings().incrementSkillOrder(); continue; } if (target instanceof Guard) { final int targetMode = player.getAutoPlaySettings().getNextTargetMode(); if ((targetMode != 3 /* NPC */) && (targetMode != 0 /* Any Target */)) { player.getAutoUseSettings().incrementSkillOrder(); continue; } } // 前进到下一个技能(默认+1,若实际施法则在后续可能因冷却等跳过) player.getAutoUseSettings().incrementSkillOrder(); final Playable caster = pet != null ? pet : player; if (!canUseMagic(caster, target, skill)) { continue; } caster.useMagic(skill, true, false); break; // 成功施法后退出本轮循环 } } // ---------- 条件判断方法 ---------- private boolean canCastBuff(Player player, WorldObject target, Skill skill) { if ((target != null) && target.isCreature() && target.asCreature().isAlikeDead() && (skill.getTargetType() != TargetType.SELF) && (skill.getTargetType() != TargetType.CORPSE) && (skill.getTargetType() != TargetType.PC_BODY)) { return false; } final Playable playableTarget = (target == null) || !target.isPlayable() || (skill.getTargetType() == TargetType.SELF) ? player : target.asPlayable(); if ((player != playableTarget) && (player.calculateDistance3D(playableTarget) > skill.getCastRange())) { return false; } if (!canUseMagic(player, playableTarget, skill)) { return false; } final BuffInfo buffInfo = playableTarget.getEffectList().getBuffInfoBySkillId(skill.getId()); final BuffInfo abnormalBuffInfo = playableTarget.getEffectList().getBuffInfoByAbnormalType(skill.getAbnormalType()); if (abnormalBuffInfo != null) { if (buffInfo != null) { return (abnormalBuffInfo.getSkill().getId() == buffInfo.getSkill().getId()) && ((buffInfo.getTime() <= REUSE_MARGIN_TIME) || (buffInfo.getSkill().getLevel() < skill.getLevel())); } return (abnormalBuffInfo.getSkill().getAbnormalLevel() < skill.getAbnormalLevel()) || abnormalBuffInfo.isAbnormalType(AbnormalType.NONE); } return buffInfo == null; } private boolean canUseMagic(Playable playable, WorldObject target, Skill skill) { if ((skill.getItemConsumeCount() > 0) && (playable.getInventory().getInventoryItemCount(skill.getItemConsumeId(), -1) < skill.getItemConsumeCount())) { return false; } if (playable.isPlayer() && (playable.asPlayer().getCharges() < skill.getChargeConsumeCount())) { return false; } final int mpConsume = skill.getMpInitialConsume() + skill.getMpConsume(); if ((mpConsume > 0) && (playable.getCurrentMp() < mpConsume)) { return false; } if ((skill.getId() == 254) && (target != null) && target.isMonster() && target.asMonster().isSpoiled()) { return false; } return !playable.isSkillDisabled(skill) && skill.checkCondition(playable, target, false); } } // ---------- 公开管理方法 ---------- public synchronized void startAutoUseTask(Player player) { // 检查玩家是否已存在 for (AutoUse au : POOLS) { if (au.getPlayers().contains(player)) { return; } } // 尝试加入已有池 for (AutoUse au : POOLS) { if (au.getPlayers().size() < POOL_SIZE) { au.getPlayers().add(player); return; } } // 创建新池 final Set<Player> newPool = ConcurrentHashMap.newKeySet(POOL_SIZE); newPool.add(player); final AutoUse task = new AutoUse(newPool); final ScheduledFuture<?> future = ThreadPool.schedulePriorityTaskAtFixedRate(task, TASK_DELAY, TASK_DELAY); task.setFuture(future); POOLS.add(task); } public synchronized void stopAutoUseTask(Player player) { player.getAutoUseSettings().resetSkillOrder(); for (Iterator<AutoUse> it = POOLS.iterator(); it.hasNext();) { AutoUse au = it.next(); if (au.getPlayers().remove(player)) { if (au.getPlayers().isEmpty()) { au.cancelTask(); // 内部会从 POOLS 移除自身 } return; } } } public static AutoUseTaskManager getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { protected static final AutoUseTaskManager INSTANCE = new AutoUseTaskManager(); } }
