use of com.playmonumenta.scriptedquests.trades.NpcTrade in project scripted-quests by TeamMonumenta.
the class NpcTradeManager method onSuccessfulTrade.
/* This is a successful trade - clicking with an empty cursor on a valid result item */
private void onSuccessfulTrade(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
MerchantInventory merchInv = (MerchantInventory) event.getInventory();
PlayerTradeContext context = mOpenTrades.get(player.getUniqueId());
/*
* Have to manually compute which slot this was because merchInv.getSelectedIndex returns the wrong index
* if the player leaves the trade on the first slot but puts in materials for one of the other trades
*/
MerchantRecipe recipe = merchInv.getSelectedRecipe();
List<MerchantRecipe> recipes = merchInv.getMerchant().getRecipes();
int selectedIndex = recipes.indexOf(recipe);
if (selectedIndex < 0) {
player.sendMessage(ChatColor.YELLOW + "BUG! Somehow the recipe you selected couldn't be found. Please report this, and include which villager and what you were trading for");
} else {
NpcTrade trade = context.getSlotProperties().get(selectedIndex);
if (trade != null) {
trade.doActions(new QuestContext(Plugin.getInstance(), player, context.getVillager()));
}
}
}
use of com.playmonumenta.scriptedquests.trades.NpcTrade 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);
}
}
}
Aggregations