테스트

aion-server 4.8

Gitteol
최고관리자 · 1 · 💬 0 클론/새로받기
 4.8 61f661d · 1 commits 새로받기(Pull)
game-server/src/com/aionemu/gameserver/model/templates/item/actions/DecomposeAction.java
package com.aionemu.gameserver.model.templates.item.actions;

import java.util.*;
import java.util.stream.Collectors;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.commons.utils.Rnd;
import com.aionemu.gameserver.controllers.observer.ItemUseObserver;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.model.Chance;
import com.aionemu.gameserver.model.Race;
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.*;
import com.aionemu.gameserver.network.aion.serverpackets.SM_FIRST_SHOW_DECOMPOSABLE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ITEM_USAGE_ANIMATION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.services.item.ItemPacketService.ItemAddType;
import com.aionemu.gameserver.services.item.ItemPacketService.ItemUpdateType;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.services.item.ItemService.ItemUpdatePredicate;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.ThreadPoolManager;

/**
 * @author oslo(a00441234)
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "DecomposeAction")
public class DecomposeAction extends AbstractItemAction {

	private static final Logger log = LoggerFactory.getLogger(DecomposeAction.class);
	public static final int USAGE_DELAY = 3000;
	private static Map<Race, int[]> chunkEarth = new HashMap<>();
	private static Map<Race, int[]> chunkSand = new HashMap<>();
	private static Map<Race, int[]> premiumOphidanRecipe = new HashMap<>();

	private static int[] chunkRock = { 152000104, 152000107, 152000113, 152000204, 152000207, 152000214, 152000307, 152000309, 152000311, 152000313,
		152000315, 152000317, 152000320, 152000322, 152000324 };

	private static int[] chunkGemstone = { 152000112, 152000116, 152000212, 152000213, 152000217, 152000326, 152000327, 152000328 };

	private static int[] scrolls = { 164000073, 164000134, 164000076, 164000079, 164000122, 164000131, 164000118 };

	private static int[] potion = { 162000045, 162000079, 162000016, 162000021, 162000027, 162000023 };

	private static int[] lesser_potions = { 162000003, 162000008, 162000042, 162000022, 162000013, 162000018, 162000047 };

	private static int[] potion_50 = { 162000075, 162000076, 162000077, 162000078, 162000079, 162000080, 162000081 };

	private static int[] illusion_godstones = { 168000161, 168000162, 168000163, 168000164, 168000165, 168000166, 168000167, 168000168, 168000169,
		168000170, 168000171, 168000172, 168000173, 168000174, 168000175, 168000176, 168000177 };

	static {
		chunkEarth.put(Race.ASMODIANS,
			new int[] { 152000051, 152000052, 152000053, 152000054, 152000055, 152000056, 152000057, 152000058, 152000059, 152000061, 152000062, 152000063,
				152000101, 152000102, 152000104, 152000107, 152000113, 152000201, 152000202, 152000204, 152000207, 152000214, 152000451, 152000453, 152000455,
				152000457, 152000459, 152000461, 152000463, 152000465, 152000468, 152000470, 152000551, 152000552, 152000553, 152000554, 152000556, 152000651,
				152000652, 152000653, 152000654, 152000656, 152000751, 152000752, 152000753, 152000754, 152000755, 152000756, 152000757, 152000758, 152000759,
				152000760, 152000762, 152000763, 152000851, 152000852, 152000853, 152000854, 152000855, 152000856, 152000857, 152000858, 152000860, 152000861,
				152001051, 152001052, 152001053, 152001055, 152001056 });
		chunkEarth.put(Race.ELYOS,
			new int[] { 152000001, 152000002, 152000003, 152000004, 152000005, 152000006, 152000007, 152000008, 152000009, 152000010, 152000011, 152000012,
				152000101, 152000102, 152000104, 152000107, 152000113, 152000201, 152000202, 152000204, 152000207, 152000214, 152000401, 152000403, 152000405,
				152000407, 152000409, 152000411, 152000413, 152000415, 152000417, 152000419, 152000501, 152000502, 152000503, 152000504, 152000505, 152000601,
				152000602, 152000603, 152000604, 152000605, 152000701, 152000702, 152000703, 152000704, 152000705, 152000706, 152000707, 152000708, 152000709,
				152000710, 152000711, 152000712, 152000801, 152000802, 152000803, 152000804, 152000805, 152000806, 152000807, 152000808, 152000809, 152000810,
				152001001, 152001002, 152001003, 152001004, 152001005 });

		chunkSand.put(Race.ASMODIANS,
			new int[] { 152000452, 152000454, 152000301, 152000302, 152000303, 152000456, 152000458, 152000103, 152000203, 152000304, 152000305, 152000306,
				152000460, 152000462, 152000105, 152000205, 152000307, 152000309, 152000311, 152000464, 152000466, 152000108, 152000208, 152000313, 152000315,
				152000317, 152000469, 152000471, 152000114, 152000215, 152000320, 152000322, 152000324 });
		chunkSand.put(Race.ELYOS,
			new int[] { 152000402, 152000404, 152000301, 152000302, 152000303, 152000406, 152000408, 152000103, 152000203, 152000304, 152000305, 152000306,
				152000410, 152000412, 152000105, 152000205, 152000307, 152000309, 152000311, 152000414, 152000416, 152000108, 152000208, 152000313, 152000315,
				152000317, 152000418, 152000420, 152000114, 152000215, 152000320, 152000322, 152000324 });

		premiumOphidanRecipe.put(Race.ASMODIANS,
			new int[] { 152230698, 152230699, 152230700, 152230701, 152230702, 152230703, 152230704, 152230759, 152230760, 152230761, 152230762, 152230763,
				152230764, 152230839, 152230840, 152230841, 152230842, 152230843, 152230844, 152230845, 152231021, 152231022, 152231023, 152231107, 152231108,
				152231253, 152231254, 152231255, 152231256, 152231257, 152231258, 152231313, 152231314, 152231315, 152231316, 152231317, 152231318, 152231385,
				152231386, 152231387, 152231388, 152231389, 152231390, 152231403, 152231404, 152231405, 152231406, 152231407, 152231408, 152231421, 152231422,
				152231423, 152231424, 152231425, 152231426, 152231439, 152231440, 152231441, 152231442, 152231443, 152231444, 152231566 });
		premiumOphidanRecipe.put(Race.ELYOS,
			new int[] { 152220709, 152220710, 152220711, 152220712, 152220713, 152220714, 152220715, 152220770, 152220771, 152220772, 152220773, 152220774,
				152220775, 152220850, 152220851, 152220852, 152220853, 152220854, 152220855, 152220856, 152221032, 152221033, 152221034, 152221118, 152221119,
				152221264, 152221265, 152221266, 152221267, 152221268, 152221269, 152221324, 152221325, 152221326, 152221327, 152221328, 152221329, 152221396,
				152221397, 152221398, 152221399, 152221400, 152221401, 152221414, 152221415, 152221416, 152221417, 152221418, 152221419, 152221432, 152221433,
				152221434, 152221435, 152221436, 152221437, 152221450, 152221451, 152221452, 152221453, 152221454, 152221455, 152221576 });
	}

	@Override
	public boolean canAct(Player player, Item parentItem, Item targetItem, Object... params) {
		if (player.isDead() || !player.isSpawned())
			return false;
		List<ExtractedItemsCollection> itemsCollections = null;
		itemsCollections = DataManager.DECOMPOSABLE_ITEMS_DATA.getInfoByItemId(parentItem.getItemId());
		if (itemsCollections == null || itemsCollections.isEmpty()) {
			if (DataManager.DECOMPOSABLE_ITEMS_DATA.getSelectableItems(parentItem.getItemId()) != null) // selectable decomposable
				return true;
			PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_IT_CAN_NOT_BE_DECOMPOSED(parentItem.getL10n()));
			return false;
		}
		if (player.getInventory().isFull() || player.getInventory().isFullSpecialCube() && containsSpecialCubeItems(itemsCollections, player)) {
			PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_INVENTORY_IS_FULL());
			return false;
		}
		return true;
	}

	@Override
	public void act(final Player player, final Item parentItem, final Item targetItem, Object... params) {
		player.getController().cancelUseItem();
		Collection<ResultedItem> selectable = DataManager.DECOMPOSABLE_ITEMS_DATA.getSelectableItems(parentItem.getItemId());
		if (selectable != null) {
			selectable.removeIf(item -> !item.isObtainableFor(player));
			PacketSendUtility.sendPacket(player, new SM_FIRST_SHOW_DECOMPOSABLE(parentItem.getObjectId(), selectable));
			return;
		}
		List<ExtractedItemsCollection> itemsCollections = DataManager.DECOMPOSABLE_ITEMS_DATA.getInfoByItemId(parentItem.getItemId());
		Collection<ExtractedItemsCollection> levelSuitableItems = filterItemsByLevel(player, itemsCollections);
		final ExtractedItemsCollection selectedCollection = Chance.selectElement(levelSuitableItems);
		if (selectedCollection.getRandomItems().isEmpty() && selectedCollection.getItems().stream().noneMatch(i -> i.isObtainableFor(player))) {
			log.warn(
				"Empty decomposable " + parentItem.getItemId() + " for " + player + ", class: " + player.getPlayerClass() + ", level: " + player.getLevel());
			PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_FAILED(parentItem.getL10n()));
			return;
		}

		PacketSendUtility.broadcastPacket(player,
			new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), parentItem.getObjectId(), parentItem.getItemId(), USAGE_DELAY, 0, 0), true);

		final ItemUseObserver observer = new ItemUseObserver() {

			@Override
			public void abort() {
				player.getController().cancelTask(TaskId.ITEM_USE);
				player.removeItemCoolDown(parentItem.getItemTemplate().getUseLimits().getDelayId());
				PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_CANCELED(parentItem.getL10n()));
				PacketSendUtility.broadcastPacket(player,
					new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), parentItem.getObjectId(), parentItem.getItemTemplate().getTemplateId(), 0, 2, 0), true);
				player.getObserveController().removeObserver(this);
			}

		};

		player.getObserveController().attach(observer);
		player.getController().addTask(TaskId.ITEM_USE, ThreadPoolManager.getInstance().schedule(new Runnable() {

			@Override
			public void run() {
				player.getObserveController().removeObserver(observer);
				boolean validAction = postValidate(player, parentItem);
				if (validAction) {
					PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_SUCCEED(parentItem.getL10n()));
					for (ResultedItem resultItem : selectedCollection.getItems()) {
						if (resultItem.isObtainableFor(player)) {
							int count = Rnd.get(resultItem.getMinCount(), resultItem.getMaxCount());
							ItemService.addItem(player, resultItem.getItemId(), count, true,
								new ItemUpdatePredicate(ItemAddType.DECOMPOSABLE, ItemUpdateType.INC_ITEM_COLLECT));
						}
					}
					for (RandomItem randomItem : selectedCollection.getRandomItems()) {
						RandomType randomType = randomItem.getType();
						if (randomType != null) {
							int randomId = 0;
							int i = 0;
							int itemLvl = parentItem.getItemTemplate().getLevel();
							switch (randomItem.getType()) {
								case ENCHANTMENT:
									do {
										randomId = 166000191 + Math.round(itemLvl / 100f) + Rnd.nextInt(4);
										i++;
										if (i > 50) {
											randomId = 0;
											break;
										}
									} while (!isValidItemId(randomId));
									break;
								case MANASTONE:
								case MANASTONE_COMMON_GRADE_10:
								case MANASTONE_COMMON_GRADE_20:
								case MANASTONE_COMMON_GRADE_30:
								case MANASTONE_COMMON_GRADE_40:
								case MANASTONE_COMMON_GRADE_50:
								case MANASTONE_COMMON_GRADE_60:
								case MANASTONE_COMMON_GRADE_70:
								case MANASTONE_RARE_GRADE_10:
								case MANASTONE_RARE_GRADE_20:
								case MANASTONE_RARE_GRADE_30:
								case MANASTONE_RARE_GRADE_40:
								case MANASTONE_RARE_GRADE_50:
								case MANASTONE_RARE_GRADE_60:
								case MANASTONE_RARE_GRADE_70:
								case MANASTONE_LEGEND_GRADE_10:
								case MANASTONE_LEGEND_GRADE_20:
								case MANASTONE_LEGEND_GRADE_30:
								case MANASTONE_LEGEND_GRADE_40:
								case MANASTONE_LEGEND_GRADE_50:
								case MANASTONE_LEGEND_GRADE_60:
								case MANASTONE_LEGEND_GRADE_70:
									if (randomType == RandomType.MANASTONE) // stone level near or equal to item level (if 1, near player level)
										itemLvl = itemLvl % 10 == 0 ? itemLvl : ((int) Math.ceil((itemLvl == 1 ? player.getLevel() : itemLvl) / 10f) * 10);
									else
										itemLvl = randomType.getLevel();
									List<ItemTemplate> stones = DataManager.ITEM_DATA.getManastones(itemLvl);
									if (stones == null) {
										log.warn("No lv" + itemLvl + " manastones found for decomposable random type " + randomItem.getType());
										break;
									}
									if (randomType != RandomType.MANASTONE) {
										final ItemQuality itemQuality;
										if (randomType.name().contains("RARE"))
											itemQuality = ItemQuality.RARE;
										else if (randomType.name().contains("LEGEND"))
											itemQuality = ItemQuality.LEGEND;
										else
											itemQuality = ItemQuality.COMMON;
										List<ItemTemplate> selectedStones = stones.stream()
											.filter(t -> t.getItemQuality() == itemQuality && !t.getName().contains(" MP ")).collect(Collectors.toList());
										randomId = Rnd.get(selectedStones).getTemplateId();
									} else {
										List<ItemTemplate> selectedStones = stones.stream()
											.filter(t -> t.getItemQuality() != ItemQuality.LEGEND && !t.getName().contains(" MP ")).collect(Collectors.toList());
										randomId = Rnd.get(selectedStones).getTemplateId();
									}
									break;
								case SPECIAL_MANASTONE_RARE_GRADE:
								case SPECIAL_MANASTONE_LEGEND_GRADE:
								case SPECIAL_MANASTONE_UNIQUE_GRADE:
								case SPECIAL_MANASTONE_EPIC_GRADE:
									List<ItemTemplate> ancientStones = DataManager.ITEM_DATA.getAncientManastones(randomType.getLevel());
									if (ancientStones == null) {
										log.warn("No ancient manastones found for decomposable random type " + randomItem.getType());
										break;
									}
									final ItemQuality itemQuality;
									if (randomType.name().contains("RARE"))
										itemQuality = ItemQuality.RARE;
									else if (randomType.name().contains("LEGEND"))
										itemQuality = ItemQuality.LEGEND;
									else if (randomType.name().contains("UNIQUE"))
										itemQuality = ItemQuality.UNIQUE;
									else if (randomType.name().contains("EPIC"))
										itemQuality = ItemQuality.EPIC;
									else
										itemQuality = ItemQuality.COMMON;
									List<ItemTemplate> selectedStones = ancientStones.stream()
										.filter(t -> t.getItemQuality() == itemQuality && !t.getName().contains(" MP ")).collect(Collectors.toList());
									randomId = Rnd.get(selectedStones).getTemplateId();
									break;
								case CHUNK_EARTH:
									int[] earth = chunkEarth.get(player.getRace());
									randomId = Rnd.get(earth);
									break;
								case CHUNK_SAND:
									int[] sand = chunkSand.get(player.getRace());
									randomId = Rnd.get(sand);
									break;
								case PREMIUM_OPHIDAN_RECIPE:
									int[] recipe = premiumOphidanRecipe.get(player.getRace());
									randomId = Rnd.get(recipe);
									break;
								case CHUNK_ROCK:
									randomId = Rnd.get(chunkRock);
									break;
								case CHUNK_GEMSTONE:
									randomId = Rnd.get(chunkGemstone);
									break;
								case SCROLLS:
									randomId = Rnd.get(scrolls);
									break;
								case POTION:
									randomId = Rnd.get(potion);
									break;
								case LESSER_POTIONS:
									randomId = Rnd.get(lesser_potions);
									break;
								case POTION_50:
									randomId = Rnd.get(potion_50);
									break;
								case ILLUSION_GODSTONE:
									randomId = Rnd.get(illusion_godstones);
									break;
								case ANCIENTITEMS:
									do {
										randomId = Rnd.get(186000051, 186000066);
										i++;
										if (i > 50) {
											randomId = 0;
											break;
										}
									} while (!isValidItemId(randomId));
									break;
								case ANCIENT_CROWN:
									do {
										randomId = Rnd.get(186000051, 186000054);
										i++;
										if (i > 50) {
											randomId = 0;
											break;
										}
									} while (!isValidItemId(randomId));
									break;
								case ANCIENT_GOBLET:
									do {
										randomId = Rnd.get(186000055, 186000058);
										i++;
										if (i > 50) {
											randomId = 0;
											break;
										}
									} while (!isValidItemId(randomId));
									break;
								case ANCIENT_SEAL:
									do {
										randomId = Rnd.get(186000059, 186000062);
										i++;
										if (i > 50) {
											randomId = 0;
											break;
										}
									} while (!isValidItemId(randomId));
									break;
								case ANCIENT_ICON:
									do {
										randomId = Rnd.get(186000063, 186000066);
										i++;
										if (i > 50) {
											randomId = 0;
											break;
										}
									} while (!isValidItemId(randomId));
									break;
							}
							if (randomId != 0) {
								int count = Rnd.get(randomItem.getMinCount(), randomItem.getMaxCount());
								ItemService.addItem(player, randomId, count, true,
									new ItemUpdatePredicate(ItemAddType.DECOMPOSABLE, ItemUpdateType.INC_ITEM_COLLECT));
							}
						}
					}
				}
				PacketSendUtility.broadcastPacket(player,
					new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), parentItem.getObjectId(), parentItem.getItemId(), 0, validAction ? 1 : 2, 0), true);
			}

			boolean postValidate(Player player, Item parentItem) {
				if (!canAct(player, parentItem, targetItem)) {
					return false;
				}
				if (!player.getInventory().decreaseByObjectId(parentItem.getObjectId(), 1)) {
					PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_DECOMPOSE_ITEM_NO_TARGET_ITEM());
					return false;
				}
				return true;
			}

		}, USAGE_DELAY));
	}

	/**
	 * Add to result collection only items wich suits player's level
	 */
	private Collection<ExtractedItemsCollection> filterItemsByLevel(Player player, List<ExtractedItemsCollection> itemsCollections) {
		if (itemsCollections == null) {
			return null;
		}
		int playerLevel = player.getLevel();
		Collection<ExtractedItemsCollection> result = new ArrayList<>();
		for (ExtractedItemsCollection collection : itemsCollections) {
			if (collection.getMinLevel() > playerLevel || collection.getMaxLevel() < playerLevel) {
				continue;
			}
			result.add(collection);
		}
		return result;
	}

	private boolean containsSpecialCubeItems(List<ExtractedItemsCollection> itemGroups, Player player) {
		for (ExtractedItemsCollection items : itemGroups) {
			if (items.getMinLevel() > player.getLevel() || items.getMaxLevel() < player.getLevel())
				continue;
			for (ResultedItem item : items.getItems()) {
				if (item.isObtainableFor(player)) {
					ItemTemplate template = DataManager.ITEM_DATA.getItemTemplate(item.getItemId());
					if (template == null)
						log.error("Detected invalid item id during decompose action " + item.getItemId());
					else if (template.getExtraInventoryId() > 0)
						return true;
				}
			}
		}
		return false;
	}

	public static void validateRandomItemIds() {
		for (int[] itemIds : chunkEarth.values())
			validateItemIds(itemIds);
		for (int[] itemIds : chunkSand.values())
			validateItemIds(itemIds);
		validateItemIds(chunkRock, chunkGemstone, scrolls, potion, lesser_potions, potion_50, illusion_godstones);
	}

	private static void validateItemIds(int[]... itemIds) {
		for (int[] ids : itemIds) {
			for (int itemId : ids)
				if (!isValidItemId(itemId))
					throw new IllegalArgumentException("Decomposable random reward item ID is invalid: " + itemId);
		}
	}

	private static boolean isValidItemId(int itemId) {
		return DataManager.ITEM_DATA.getItemTemplate(itemId) != null;
	}
}

📎 첨부파일

댓글 작성 권한이 없습니다.
🏆 포인트 랭킹 TOP 10
순위 닉네임 포인트
1 no_profile 타키야겐지쪽지보내기 자기소개 아이디로 검색 전체게시물 102,949
2 no_profile 동가리쪽지보내기 자기소개 아이디로 검색 전체게시물 63,733
3 no_profile 라프텔쪽지보내기 자기소개 아이디로 검색 전체게시물 51,771
4 no_profile 불멸의행복쪽지보내기 자기소개 아이디로 검색 전체게시물 36,923
5 서번트쪽지보내기 자기소개 아이디로 검색 전체게시물 35,011
6 no_profile 닥터스쪽지보내기 자기소개 아이디로 검색 전체게시물 29,470
7 no_profile 검은고양이쪽지보내기 자기소개 아이디로 검색 전체게시물 29,097
8 no_profile Revolution쪽지보내기 자기소개 아이디로 검색 전체게시물 28,199
9 no_profile 보거스쪽지보내기 자기소개 아이디로 검색 전체게시물 26,731
10 no_profile 호롤롤로쪽지보내기 자기소개 아이디로 검색 전체게시물 17,020
알림 0