diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/buffer/main.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/buffer/main.html index f7d4292fb7..576f1bab79 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/buffer/main.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/buffer/main.html @@ -8,27 +8,7 @@
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/dropsearch/main.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/dropsearch/main.html new file mode 100644 index 0000000000..da14b779c7 --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/dropsearch/main.html @@ -0,0 +1,90 @@ + + + + + + +
+ + + + + +
+ %navigation% + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Drop Search
+
+
     1. Input item name or partial name to search for items.
     2. Choose item icon to search for drops.
     3. Select an NPC, you can see it's location on the world map.
+ + + + + +
ItemName:
+
+
+
+ + %searchResult% +
+ + %pages% +
+
+ + + + +
+ + + + + + + + + + +
LINEAGE II - COMMUNITY BOARD
+
+
+ + \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/gatekeeper/main.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/gatekeeper/main.html index 0af8719137..97d0100160 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/gatekeeper/main.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/gatekeeper/main.html @@ -8,27 +8,7 @@
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/home.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/home.html index 7e0fab8c44..a6ef43c6ec 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/home.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/home.html @@ -8,27 +8,7 @@
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/agathions.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/agathions.html index 0848d9d09b..aa00514cd3 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/agathions.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/agathions.html @@ -8,27 +8,7 @@
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/main.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/main.html index 685ed560bd..e28e4480e0 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/main.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/merchant/main.html @@ -8,27 +8,7 @@
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/navigation.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/navigation.html new file mode 100644 index 0000000000..0892c63763 --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/navigation.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/main.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/main.html index 84c72ad750..a1ac36655e 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/main.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/main.html @@ -8,27 +8,7 @@
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/thankyou.html b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/thankyou.html index d9028c5ac0..4064c0c599 100644 --- a/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/thankyou.html +++ b/L2J_Mobius_Underground/dist/game/data/html/CommunityBoard/Custom/premium/thankyou.html @@ -8,27 +8,7 @@ "); + builder.append(""); + builder.append(""); + builder.append(""); + builder.append(""); + builder.append(""); + builder.append(""); + } + + html = html.replace("%searchResult%", builder.toString()); + builder.setLength(0); + + builder.append(""); + for (page = 1; page <= pages; page++) + { + builder.append(""); + } + builder.append(""); + html = html.replace("%pages%", builder.toString()); + break; + } + case "_bbs_npc_trace": + { + int npcId = Integer.parseInt(params[1]); + List spawnList = SpawnsData.getInstance().getNpcSpawns(npc -> npc.getId() == npcId); + if (spawnList.isEmpty()) + { + player.sendMessage("cant find any spawn maybe boss or instance mob"); + } + else + { + NpcSpawnTemplate spawn = spawnList.get(Rnd.get(spawnList.size())); + player.getRadar().addMarker(spawn.getSpawnLocation().getX(), spawn.getSpawnLocation().getY(), spawn.getSpawnLocation().getZ()); + } + break; + } + } + + if (html != null) + { + html = html.replace("%navigation%", navigation); + CommunityBoardHandler.separateAndSend(html, player); + } + + return false; + } + + /** + * @param itemName + * @return + */ + private String buildItemSearchResult(String itemName) + { + int limit = 0; + Set existInDropData = DROP_INDEX_CACHE.keySet(); + List items = new ArrayList<>(); + for (L2Item item : ItemTable.getInstance().getAllItems()) + { + if (item == null) + { + continue; + } + + if (!existInDropData.contains(item.getId())) + { + continue; + } + + if (item.getName().toLowerCase().contains(itemName.toLowerCase())) + { + items.add(item); + limit++; + } + + if (limit == 14) + { + break; + } + } + + if (items.isEmpty()) + { + return ""; + } + + int line = 0; + + StringBuilder builder = new StringBuilder(items.size() * 28); + int i = 0; + for (L2Item item : items) + { + i++; + if (i == 1) + { + line++; + builder.append(""); + } + + builder.append(""); + builder.append(""); + + if (i == 2) + { + builder.append(""); + i = 0; + } + } + + if ((i % 2) == 1) + { + builder.append(""); + } + + if (line < 7) + { + for (i = 0; i < (7 - line); i++) + { + builder.append(""); + } + } + + return builder.toString(); + } + + /** + * @param params + * @return + */ + private String buildItemName(String[] params) + { + StringJoiner joiner = new StringJoiner(" "); + for (int i = 1; i < params.length; i++) + { + joiner.add(params[i]); + } + return joiner.toString(); + } + + @Override + public String[] getCommunityBoardCommands() + { + return COMMAND; + } +} diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/HomeBoard.java b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/HomeBoard.java index b5b294ab82..afd9e334f8 100644 --- a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/HomeBoard.java +++ b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/HomeBoard.java @@ -20,10 +20,17 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; +import java.util.function.BiPredicate; +import java.util.function.Predicate; import com.l2jmobius.Config; import com.l2jmobius.commons.database.DatabaseFactory; +import com.l2jmobius.commons.util.CommonUtil; import com.l2jmobius.gameserver.cache.HtmCache; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; import com.l2jmobius.gameserver.data.xml.impl.BuyListData; @@ -32,13 +39,15 @@ import com.l2jmobius.gameserver.data.xml.impl.SkillData; import com.l2jmobius.gameserver.handler.CommunityBoardHandler; import com.l2jmobius.gameserver.handler.IParseBoardHandler; import com.l2jmobius.gameserver.instancemanager.PremiumManager; +import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.skills.Skill; -import com.l2jmobius.gameserver.model.skills.SkillCaster; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.BuyList; import com.l2jmobius.gameserver.network.serverpackets.ExBuySellList; +import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.ShowBoard; /** @@ -49,38 +58,71 @@ public final class HomeBoard implements IParseBoardHandler { // SQL Queries private static final String COUNT_FAVORITES = "SELECT COUNT(*) AS favorites FROM `bbs_favorites` WHERE `playerId`=?"; + private static final String NAVIGATION_PATH = "data/html/CommunityBoard/Custom/navigation.html"; private static final String[] COMMANDS = { "_bbshome", "_bbstop", - "_bbsmultisell", - "_bbssell", - "_bbsteleport", - "_bbspremium", - "_bbsbuff", - "_bbsheal" }; + private static final String[] CUSTOM_COMMANDS = + { + Config.PREMIUM_SYSTEM_ENABLED && Config.COMMUNITY_PREMIUM_SYSTEM_ENABLED ? "_bbspremium" : null, + Config.COMMUNITYBOARD_ENABLE_MULTISELLS ? "_bbsmultisell" : null, + Config.COMMUNITYBOARD_ENABLE_MULTISELLS ? "_bbssell" : null, + Config.COMMUNITYBOARD_ENABLE_TELEPORTS ? "_bbsteleport" : null, + Config.COMMUNITYBOARD_ENABLE_BUFFS ? "_bbsbuff" : null, + Config.COMMUNITYBOARD_ENABLE_HEAL ? "_bbsheal" : null + }; + + //@formatter:off + public static final BiPredicate COMBAT_CHECK = (command, activeChar) -> + CommonUtil.contains(CUSTOM_COMMANDS, command) && + (activeChar.isInCombat() || activeChar.isInDuel() || activeChar.isInOlympiadMode() || activeChar.isInsideZone(ZoneId.SIEGE) || activeChar.isInsideZone(ZoneId.PVP)); + //@formatter:on + + public static final Predicate KARMAR_CHECK = player -> Config.COMMUNITYBOARD_KARMA_DISABLED && (player.getReputation() < 0); + @Override public String[] getCommunityBoardCommands() { - return COMMANDS; + List commands = new ArrayList<>(); + commands.addAll(Arrays.asList(COMMANDS)); + commands.addAll(Arrays.asList(CUSTOM_COMMANDS)); + return commands.stream().filter(Objects::nonNull).toArray(String[]::new); } @Override public boolean parseCommunityBoardCommand(String command, L2PcInstance activeChar) { + // Old custom conditions check move to here + if (COMBAT_CHECK.test(command, activeChar)) + { + activeChar.sendMessage("You can't use the Community Board right now."); + return false; + } + + if (KARMAR_CHECK.test(activeChar)) + { + activeChar.sendMessage("Players with Karma cannot use the Community Board."); + return false; + } + + String returnHtml = null; + final String navigation = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), NAVIGATION_PATH); if (command.equals("_bbshome") || command.equals("_bbstop")) { final String customPath = Config.CUSTOM_CB_ENABLED ? "Custom/" : ""; CommunityBoardHandler.getInstance().addBypass(activeChar, "Home", command); - String html = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/" + customPath + "home.html"); - html = html.replaceAll("%fav_count%", Integer.toString(getFavoriteCount(activeChar))); - html = html.replaceAll("%region_count%", Integer.toString(getRegionCount(activeChar))); - html = html.replaceAll("%clan_count%", Integer.toString(ClanTable.getInstance().getClanCount())); - CommunityBoardHandler.separateAndSend(html, activeChar); + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/" + customPath + "home.html"); + if (!Config.CUSTOM_CB_ENABLED) + { + returnHtml = returnHtml.replaceAll("%fav_count%", Integer.toString(getFavoriteCount(activeChar))); + returnHtml = returnHtml.replaceAll("%region_count%", Integer.toString(getRegionCount(activeChar))); + returnHtml = returnHtml.replaceAll("%clan_count%", Integer.toString(ClanTable.getInstance().getClanCount())); + } } else if (command.startsWith("_bbstop;")) { @@ -88,53 +130,26 @@ public final class HomeBoard implements IParseBoardHandler final String path = command.replace("_bbstop;", ""); if ((path.length() > 0) && path.endsWith(".html")) { - CommunityBoardHandler.separateAndSend(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/" + customPath + path), activeChar); + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/" + customPath + path); } } - - // ------------------------ - // Custom Community Board - // ------------------------ - - if (Config.CUSTOM_CB_ENABLED) - { - if (Config.COMMUNITYBOARD_COMBAT_DISABLED && (activeChar.isInCombat() || activeChar.isInDuel() || activeChar.isInOlympiadMode() || activeChar.isInsideZone(ZoneId.SIEGE) || activeChar.isInsideZone(ZoneId.PVP))) - { - activeChar.sendMessage("You can't use the Community Board right now."); - return false; - } - if (Config.COMMUNITYBOARD_KARMA_DISABLED && (activeChar.getReputation() < 0)) - { - activeChar.sendMessage("Players with Karma cannot use the Community Board."); - return false; - } - } - else - { - return false; - } - - if (Config.COMMUNITYBOARD_ENABLE_MULTISELLS && command.startsWith("_bbsmultisell")) + else if (command.startsWith("_bbsmultisell")) { final String fullBypass = command.replace("_bbsmultisell;", ""); final String[] buypassOptions = fullBypass.split(","); final int multisellId = Integer.parseInt(buypassOptions[0]); final String page = buypassOptions[1]; - final String html = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"); - CommunityBoardHandler.separateAndSend(html, activeChar); + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"); MultisellData.getInstance().separateAndSend(multisellId, activeChar, null, false); - return true; } - else if (Config.COMMUNITYBOARD_ENABLE_MULTISELLS && command.startsWith("_bbssell")) + else if (command.startsWith("_bbssell")) { final String page = command.replace("_bbssell;", ""); - final String html = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"); - CommunityBoardHandler.separateAndSend(html, activeChar); + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"); activeChar.sendPacket(new BuyList(BuyListData.getInstance().getBuyList(423), activeChar.getAdena(), 0)); activeChar.sendPacket(new ExBuySellList(activeChar, false)); - return true; } - else if (Config.COMMUNITYBOARD_ENABLE_TELEPORTS && command.startsWith("_bbsteleport")) + else if (command.startsWith("_bbsteleport")) { final String fullBypass = command.replace("_bbsteleport;", ""); final String[] buypassOptions = fullBypass.split(","); @@ -152,7 +167,7 @@ public final class HomeBoard implements IParseBoardHandler activeChar.teleToLocation(x, y, z, 0); } } - else if (Config.COMMUNITYBOARD_ENABLE_BUFFS && command.startsWith("_bbsbuff")) + else if (command.startsWith("_bbsbuff")) { final String fullBypass = command.replace("_bbsbuff;", ""); final String[] buypassOptions = fullBypass.split(";"); @@ -165,44 +180,36 @@ public final class HomeBoard implements IParseBoardHandler else { activeChar.destroyItemByItemId("CB_Buff", Config.COMMUNITYBOARD_CURRENCY, Config.COMMUNITYBOARD_BUFF_PRICE * buffCount, activeChar, true); + final L2PetInstance pet = activeChar.getPet(); + List targets = new ArrayList<>(4); + targets.add(activeChar); + if (pet != null) + { + targets.add(pet); + } + + activeChar.getServitors().values().stream().forEach(targets::add); + for (int i = 0; i < buffCount; i++) { final Skill skill = SkillData.getInstance().getSkill(Integer.parseInt(buypassOptions[i].split(",")[0]), Integer.parseInt(buypassOptions[i].split(",")[1])); - if (Config.COMMUNITYBOARD_CAST_ANIMATIONS) + + targets.stream().filter(target -> !target.isSummon() || !skill.isSharedWithSummon()).forEach(target -> { - SkillCaster.triggerCast(activeChar, activeChar, skill); - if (activeChar.getServitors().size() > 0) + skill.applyEffects(activeChar, target); + if (Config.COMMUNITYBOARD_CAST_ANIMATIONS) { - for (L2Summon summon : activeChar.getServitors().values()) - { - SkillCaster.triggerCast(summon, summon, skill); - } + activeChar.sendPacket(new MagicSkillUse(activeChar, target, skill.getId(), skill.getLevel(), skill.getHitTime(), skill.getReuseDelay())); + // not recommend broadcast + // activeChar.broadcastPacket(new MagicSkillUse(activeChar, target, skill.getId(), skill.getLevel(), skill.getHitTime(), skill.getReuseDelay())); } - if (activeChar.hasPet()) - { - SkillCaster.triggerCast(activeChar.getPet(), activeChar.getPet(), skill); - } - } - else - { - skill.applyEffects(activeChar, activeChar); - if (activeChar.getServitors().size() > 0) - { - for (L2Summon summon : activeChar.getServitors().values()) - { - skill.applyEffects(summon, summon); - } - } - if (activeChar.hasPet()) - { - skill.applyEffects(activeChar.getPet(), activeChar.getPet()); - } - } + }); } } - CommunityBoardHandler.separateAndSend(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"), activeChar); + + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"); } - else if (Config.COMMUNITYBOARD_ENABLE_HEAL && command.startsWith("_bbsheal")) + else if (command.startsWith("_bbsheal")) { final String page = command.replace("_bbsheal;", ""); if (activeChar.getInventory().getInventoryItemCount(Config.COMMUNITYBOARD_CURRENCY, -1) < (Config.COMMUNITYBOARD_HEAL_PRICE)) @@ -229,9 +236,10 @@ public final class HomeBoard implements IParseBoardHandler } activeChar.sendMessage("You used heal!"); } - CommunityBoardHandler.separateAndSend(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"), activeChar); + + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/" + page + ".html"); } - else if (Config.PREMIUM_SYSTEM_ENABLED && Config.COMMUNITY_PREMIUM_SYSTEM_ENABLED && command.startsWith("_bbspremium")) + else if (command.startsWith("_bbspremium")) { final String fullBypass = command.replace("_bbspremium;", ""); final String[] buypassOptions = fullBypass.split(","); @@ -245,9 +253,18 @@ public final class HomeBoard implements IParseBoardHandler activeChar.destroyItemByItemId("CB_Premium", Config.COMMUNITY_PREMIUM_COIN_ID, Config.COMMUNITY_PREMIUM_PRICE_PER_DAY * premiumDays, activeChar, true); PremiumManager.getInstance().addPremiumTime(activeChar.getAccountName(), premiumDays, TimeUnit.DAYS); activeChar.sendMessage("Your account will now have premium status until " + new SimpleDateFormat("dd.MM.yyyy HH:mm").format(PremiumManager.getInstance().getPremiumExpiration(activeChar.getAccountName())) + "."); - CommunityBoardHandler.separateAndSend(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/premium/thankyou.html"), activeChar); + returnHtml = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/CommunityBoard/Custom/premium/thankyou.html"); } } + + if (returnHtml != null) + { + if (Config.CUSTOM_CB_ENABLED) + { + returnHtml = returnHtml.replace("%navigation%", navigation); + } + CommunityBoardHandler.separateAndSend(returnHtml, activeChar); + } return false; }
- - - - - - - - - - - - - - - - - - - - -
+ %navigation%
diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/MasterHandler.java b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/MasterHandler.java index 7c48bbb637..911d3c4898 100644 --- a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/MasterHandler.java +++ b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/MasterHandler.java @@ -168,6 +168,7 @@ import handlers.chathandlers.ChatTrade; import handlers.chathandlers.ChatWhisper; import handlers.chathandlers.ChatWorld; import handlers.communityboard.ClanBoard; +import handlers.communityboard.DropSearchBoard; import handlers.communityboard.FavoriteBoard; import handlers.communityboard.FriendsBoard; import handlers.communityboard.HomeBoard; @@ -485,6 +486,7 @@ public class MasterHandler MailBoard.class, MemoBoard.class, RegionBoard.class, + DropSearchBoard.class, }, { // Item Handlers diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/DropSearchBoard.java b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/DropSearchBoard.java new file mode 100644 index 0000000000..19d01e448e --- /dev/null +++ b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/communityboard/DropSearchBoard.java @@ -0,0 +1,327 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package handlers.communityboard; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.StringJoiner; + +import com.l2jmobius.commons.util.Rnd; +import com.l2jmobius.gameserver.cache.HtmCache; +import com.l2jmobius.gameserver.data.xml.impl.NpcData; +import com.l2jmobius.gameserver.data.xml.impl.SpawnsData; +import com.l2jmobius.gameserver.datatables.ItemTable; +import com.l2jmobius.gameserver.handler.CommunityBoardHandler; +import com.l2jmobius.gameserver.handler.IParseBoardHandler; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate; +import com.l2jmobius.gameserver.model.drops.DropListScope; +import com.l2jmobius.gameserver.model.drops.GeneralDropItem; +import com.l2jmobius.gameserver.model.drops.GroupedGeneralDropItem; +import com.l2jmobius.gameserver.model.drops.IDropItem; +import com.l2jmobius.gameserver.model.itemcontainer.Inventory; +import com.l2jmobius.gameserver.model.items.L2Item; +import com.l2jmobius.gameserver.model.spawns.NpcSpawnTemplate; + +/** + * @author yksdtc + */ +public class DropSearchBoard implements IParseBoardHandler +{ + private static final String NAVIGATION_PATH = "data/html/CommunityBoard/Custom/navigation.html"; + private static final String[] COMMAND = + { + "_bbs_search_item", + "_bbs_search_drop", + "_bbs_npc_trace" + }; + + class DropHolder + { + int itemId; + int npcId; + byte npcLevel; + long basemin; + long basemax; + double baseGroupChance; + double basechance; + boolean isSweep; + + public DropHolder(L2NpcTemplate npc, GeneralDropItem item, double groupChance, boolean isSweep) + { + itemId = item.getItemId(); + npcId = npc.getId(); + npcLevel = npc.getLevel(); + basemin = item.getMin(); + basemax = item.getMax(); + baseGroupChance = groupChance; + basechance = item.getChance(); + this.isSweep = isSweep; + } + + /** + * only for debug'/; + */ + @Override + public String toString() + { + return "DropHolder [itemId=" + itemId + ", npcId=" + npcId + ", npcLevel=" + npcLevel + ", basemin=" + basemin + ", basemax=" + basemax + ", baseGroupChance=" + baseGroupChance + ", basechance=" + basechance + ", isSweep=" + isSweep + "]"; + } + } + + private final Map> DROP_INDEX_CACHE = new HashMap<>(); + + // nonsupport items + private final Set BLOCK_ID = new HashSet<>(); + { + BLOCK_ID.add(Inventory.ADENA_ID); + } + + public DropSearchBoard() + { + buildDropIndex(); + } + + private void buildDropIndex() + { + NpcData.getInstance().getTemplates(npc -> npc.getDropLists() != null).forEach(npcTemplate -> + { + for (Entry> entry : npcTemplate.getDropLists().entrySet()) + { + entry.getValue().forEach(idrop -> + { + if (idrop instanceof GroupedGeneralDropItem) + { + GroupedGeneralDropItem ggd = (GroupedGeneralDropItem) idrop; + ggd.getItems().stream().forEach(gd -> addToDropList(npcTemplate, gd, ggd.getChance(), entry.getKey() == DropListScope.CORPSE)); + } + else + { + GeneralDropItem gd = (GeneralDropItem) idrop; + addToDropList(npcTemplate, gd, 100.0, entry.getKey() == DropListScope.CORPSE); + } + }); + } + }); + + DROP_INDEX_CACHE.values().stream().forEach(l -> l.sort((d1, d2) -> Byte.valueOf(d1.npcLevel).compareTo(Byte.valueOf(d2.npcLevel)))); + } + + private void addToDropList(L2NpcTemplate npcTemplate, GeneralDropItem gd, double groupChance, boolean isSweep) + { + if (BLOCK_ID.contains(gd.getItemId())) + { + return; + } + + List dropList = DROP_INDEX_CACHE.get(gd.getItemId()); + if (dropList == null) + { + dropList = new ArrayList<>(); + DROP_INDEX_CACHE.put(gd.getItemId(), dropList); + } + + dropList.add(new DropHolder(npcTemplate, gd, groupChance, isSweep)); + } + + @Override + public boolean parseCommunityBoardCommand(String command, L2PcInstance player) + { + final String navigation = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), NAVIGATION_PATH); + String[] params = command.split(" "); + String html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/CommunityBoard/Custom/dropsearch/main.html"); + switch (params[0]) + { + case "_bbs_search_item": + { + String itemName = buildItemName(params); + String result = buildItemSearchResult(itemName); + html = html.replace("%searchResult%", result); + break; + } + case "_bbs_search_drop": + { + final DecimalFormat chanceFormat = new DecimalFormat("0.00##"); + int itemId = Integer.parseInt(params[1]); + int page = Integer.parseInt(params[2]); + List list = DROP_INDEX_CACHE.get(itemId); + int pages = list.size() / 14; + if (pages == 0) + { + pages++; + } + + int start = (page - 1) * 14; + int end = Math.min(list.size() - 1, start + 14); + StringBuilder builder = new StringBuilder(); + for (int index = start; index <= end; index++) + { + DropHolder dropHolder = list.get(index); + builder.append("
").append(dropHolder.npcLevel).append("").append("").append("&@").append(dropHolder.npcId).append(";").append("").append("").append(dropHolder.basemin).append("-").append(dropHolder.basemax).append("").append(chanceFormat.format((dropHolder.basechance * dropHolder.baseGroupChance) / 100)).append("%").append("").append(dropHolder.isSweep ? "Sweep" : "Drop").append("
").append("").append(page).append("").append("
No Match
"); + builder.append(""); + builder.append("&#").append(item.getId()).append(";"); + builder.append("