Search in sources :

Example 1 with NpcTrader

use of com.playmonumenta.scriptedquests.trades.NpcTrader in project scripted-quests by TeamMonumenta.

the class NpcTradeManager method reload.

/*
	 * If sender is non-null, it will be sent debugging information
	 */
public void reload(Plugin plugin, CommandSender sender) {
    mTraders.clear();
    QuestUtils.loadScriptedQuests(plugin, "traders", sender, (object) -> {
        // Load this file into a NpcTrader object
        NpcTrader trader = new NpcTrader(object);
        if (mTraders.containsKey(trader.getNpcName())) {
            throw new Exception(trader.getNpcName() + "' already exists!");
        }
        mTraders.put(trader.getNpcName(), trader);
        return trader.getNpcName();
    });
}
Also used : NpcTrader(com.playmonumenta.scriptedquests.trades.NpcTrader)

Example 2 with NpcTrader

use of com.playmonumenta.scriptedquests.trades.NpcTrader in project scripted-quests by TeamMonumenta.

the class NpcTradeManager method trade.

/**
 * Initiates a player trade with a villager. Instead of trading with the villager directly,
 * we generate a fake merchant to do the trading. We override this trade event for multiple reasons:
 * <li>This allows multiple players to trade with the same villager at the same time</li>
 * <li>This way, the villager does not gain any trade experience</li>
 * <li>We can filter out randomly-generated vanilla trades, and hide trades based on quest prerequisites</li>
 * @param plugin Used for metadata
 * @param villager The villager to trade with
 * @param player The player trading
 * @param event The interact event that initiated the trade
 */
public void trade(Plugin plugin, Villager villager, Player player, PlayerInteractEntityEvent event) {
    ArrayList<MerchantRecipe> trades = new ArrayList<>();
    NpcTrader trader = mTraders.get(QuestNpc.squashNpcName(villager.getName()));
    StringBuilder lockedSlots = new StringBuilder();
    StringBuilder vanillaSlots = new StringBuilder();
    boolean modified = false;
    // We don't want any vanilla trades to occur, regardless of if trades were changed or not.
    // As a side-effect, right-clicking a villager will not activate interactables
    // This is fine for now, but if we ever want interactables to work on villagers, we need to change this
    event.setCancelled(true);
    Map<Integer, NpcTrade> slotProperties = new HashMap<>();
    // We need to tag the outer loop so inner loops can continue it
    recipes: for (int i = 0; i < villager.getRecipeCount(); i++) {
        MerchantRecipe recipe = villager.getRecipe(i);
        // Remove vanilla trades (those with a regular emerald in any slot)
        List<ItemStack> items = recipe.getIngredients();
        items.add(recipe.getResult());
        for (ItemStack item : items) {
            if (item != null && item.getType() == Material.EMERALD && !item.hasItemMeta()) {
                // Found emerald with no item data
                if (vanillaSlots.length() != 0) {
                    vanillaSlots.append(", ");
                }
                vanillaSlots.append(i);
                modified = true;
                continue recipes;
            }
        }
        // Remove unmatched prereq trades
        if (trader != null) {
            NpcTrade trade = trader.getTrade(i);
            if (trade != null) {
                if (!trade.prerequisiteMet(new QuestContext(plugin, player, villager))) {
                    if (lockedSlots.length() != 0) {
                        lockedSlots.append(", ");
                    }
                    lockedSlots.append(i);
                    modified = true;
                    continue;
                } else {
                    slotProperties.put(trades.size(), trade);
                }
            }
        }
        // This trade was not filtered by any of the above checks. Add to the fake merchant
        trades.add(recipe);
    }
    if (modified && player.getGameMode() == GameMode.CREATIVE && player.isOp()) {
        player.sendMessage(ChatColor.GOLD + "Some trader slots were not shown to you:");
        if (lockedSlots.length() > 0) {
            player.sendMessage(ChatColor.GOLD + "These slots were locked by quest scores: " + lockedSlots);
        }
        if (vanillaSlots.length() > 0) {
            player.sendMessage(ChatColor.GOLD + "These slots contained a vanilla emerald: " + vanillaSlots);
        }
        player.sendMessage(ChatColor.GOLD + "This message only appears to operators in creative mode");
    }
    /*
		 * If this villager still has trades, create a temporary fake merchant to interact with the player
		 * This allows multiple players to trade with the same NPC at the same time, and also gives score-limited trades
		 */
    if (trades.size() > 0) {
        List<TradeWindowOpenEvent.Trade> eventTrades = new ArrayList<>();
        for (int i = 0; i < trades.size(); i++) {
            NpcTrade npcTrade = slotProperties.get(i);
            eventTrades.add(new TradeWindowOpenEvent.Trade(trades.get(i), npcTrade != null ? npcTrade.getActions() : null));
        }
        TradeWindowOpenEvent tradeEvent = new TradeWindowOpenEvent(player, eventTrades);
        Bukkit.getPluginManager().callEvent(tradeEvent);
        if (!tradeEvent.isCancelled() && !tradeEvent.getTrades().isEmpty()) {
            new BukkitRunnable() {

                @Override
                public void run() {
                    Merchant merchant = Bukkit.createMerchant(villager.getName());
                    final List<TradeWindowOpenEvent.Trade> newEventTrades = tradeEvent.getTrades();
                    Map<Integer, NpcTrade> newSlotProperties = new HashMap<>();
                    for (int i = 0; i < newEventTrades.size(); i++) {
                        NpcTrade npcTrade = new NpcTrade(i, new QuestPrerequisites(), newEventTrades.get(i).getActions());
                        newSlotProperties.put(i, npcTrade);
                    }
                    merchant.setRecipes(newEventTrades.stream().map(TradeWindowOpenEvent.Trade::getRecipe).collect(Collectors.toList()));
                    mOpenTrades.put(player.getUniqueId(), new PlayerTradeContext(newSlotProperties, villager, merchant));
                    player.openMerchant(merchant, true);
                }
            }.runTaskLater(plugin, 1);
        }
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NpcTrade(com.playmonumenta.scriptedquests.trades.NpcTrade) Merchant(org.bukkit.inventory.Merchant) ArrayList(java.util.ArrayList) List(java.util.List) NpcTrader(com.playmonumenta.scriptedquests.trades.NpcTrader) MerchantRecipe(org.bukkit.inventory.MerchantRecipe) TradeWindowOpenEvent(com.playmonumenta.scriptedquests.trades.TradeWindowOpenEvent) QuestContext(com.playmonumenta.scriptedquests.quests.QuestContext) BukkitRunnable(org.bukkit.scheduler.BukkitRunnable) QuestPrerequisites(com.playmonumenta.scriptedquests.quests.components.QuestPrerequisites) NpcTrade(com.playmonumenta.scriptedquests.trades.NpcTrade) ItemStack(org.bukkit.inventory.ItemStack) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

NpcTrader (com.playmonumenta.scriptedquests.trades.NpcTrader)2 QuestContext (com.playmonumenta.scriptedquests.quests.QuestContext)1 QuestPrerequisites (com.playmonumenta.scriptedquests.quests.components.QuestPrerequisites)1 NpcTrade (com.playmonumenta.scriptedquests.trades.NpcTrade)1 TradeWindowOpenEvent (com.playmonumenta.scriptedquests.trades.TradeWindowOpenEvent)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 ItemStack (org.bukkit.inventory.ItemStack)1 Merchant (org.bukkit.inventory.Merchant)1 MerchantRecipe (org.bukkit.inventory.MerchantRecipe)1 BukkitRunnable (org.bukkit.scheduler.BukkitRunnable)1