package playercommands; import com.aionemu.gameserver.controllers.observer.ItemUseObserver; import com.aionemu.gameserver.dataholders.DataManager; import com.aionemu.gameserver.model.TaskId; import com.aionemu.gameserver.model.gameobjects.Item; import com.aionemu.gameserver.model.gameobjects.player.Player; import com.aionemu.gameserver.model.templates.item.actions.DecomposeAction; import com.aionemu.gameserver.model.templates.item.actions.ItemActions; import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE; import com.aionemu.gameserver.utils.ChatUtil; import com.aionemu.gameserver.utils.PacketSendUtility; import com.aionemu.gameserver.utils.ThreadPoolManager; import com.aionemu.gameserver.utils.chathandlers.PlayerCommand; /** * @author Neon */ public class Decompose extends PlayerCommand { public Decompose() { super("decompose", "Opens decomposable items."); setSyntaxInfo(" [count] - Decomposes the specified item (default: all, optional: number of items to decompose)."); } @Override public void execute(Player player, String... params) { if (params.length == 0) { sendInfo(player); return; } Item item = player.getInventory().getFirstItemByItemId(ChatUtil.getItemId(params[0])); if (item == null) { PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_NO_TARGET_ITEM()); return; } long count = params.length == 1 ? Long.MAX_VALUE : Long.parseLong(params[1]); ItemActions itemActions = item.getItemTemplate().getActions(); DecomposeAction decomposeAction = itemActions == null ? null : itemActions.getItemActions().stream().filter(a -> a instanceof DecomposeAction).map(DecomposeAction.class::cast).findAny().orElse(null); if (decomposeAction == null || DataManager.DECOMPOSABLE_ITEMS_DATA.getSelectableItems(item.getItemId()) != null) { // exclude selectable decomposables PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_IT_CAN_NOT_BE_DECOMPOSED(item.getItemTemplate().getL10n())); return; } if (!decomposeAction.canAct(player, item, item)) return; startTask(player, item.getItemId(), count, decomposeAction); } private void startTask(Player player, int itemId, long count, DecomposeAction decomposeAction) { player.getController().addTask(TaskId.SKILL_USE, ThreadPoolManager.getInstance().scheduleAtFixedRate(new Runnable() { long remainingCount = count; long totalCount = 0; ItemUseObserver observer; { // use observer to abort task on move, attack, die, item use, etc. observer = new ItemUseObserver() { @Override public void itemused(Item item) { if (item.getItemId() != itemId) abort(); } @Override public void abort() { cancelTask(player, observer, "Decomposing aborted: Processed " + Math.max(0, totalCount - 1) + "x " + ChatUtil.item(itemId) + "."); } }; player.getObserveController().addObserver(observer); } @Override public void run() { Item item = player.getInventory().getFirstItemByItemId(itemId); remainingCount = Math.min(player.getInventory().getItemCountByItemId(itemId), remainingCount); if (item == null || remainingCount <= 0) { cancelTask(player, observer, "Decomposing finished: Processed " + totalCount + "x " + ChatUtil.item(itemId) + "."); return; } if (!decomposeAction.canAct(player, item, item)) { cancelTask(player, observer, "Decomposing aborted: Processed " + totalCount + "x " + ChatUtil.item(itemId) + "."); return; } player.getObserveController().notifyItemuseObservers(item); // cancel hide decomposeAction.act(player, item, item); remainingCount--; totalCount++; } }, 10, DecomposeAction.USAGE_DELAY + 100)); } private void cancelTask(Player player, ItemUseObserver observer, String message) { player.getController().cancelTask(TaskId.SKILL_USE); player.getObserveController().removeObserver(observer); sendInfo(player, message); } }