VillagerTradeLimiter/src/com/pretzel/dev/villagertradelimiter/listeners/InventoryListener.java

150 lines
7.2 KiB
Java

package com.pretzel.dev.villagertradelimiter.listeners;
import com.pretzel.dev.villagertradelimiter.VillagerTradeLimiter;
import com.pretzel.dev.villagertradelimiter.data.Cooldown;
import com.pretzel.dev.villagertradelimiter.data.PlayerData;
import com.pretzel.dev.villagertradelimiter.settings.Settings;
import com.pretzel.dev.villagertradelimiter.wrappers.VillagerWrapper;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import java.time.Instant;
import java.util.Date;
public class InventoryListener implements Listener {
private final VillagerTradeLimiter instance;
private final Settings settings;
/**
* @param instance The instance of VillagerTradeLimiter.java
* @param settings The settings instance
*/
public InventoryListener(final VillagerTradeLimiter instance, final Settings settings) {
this.instance = instance;
this.settings = settings;
}
/** Handles when a player clicks in an inventory window */
@EventHandler
public void onPlayerClickInventory(final InventoryClickEvent event) {
if(event.getInventory().getType() != InventoryType.CHEST) return;
if(event.getInventory().getSize() != 9) return;
if(!(event.getWhoClicked() instanceof Player)) return;
if(settings.shouldSkipNPC(event.getWhoClicked())) return; //Skips NPCs
ItemStack barrier = event.getInventory().getItem(8);
if(barrier == null || !barrier.isSimilar(instance.getBarrier())) return;
//If the inventory matches the invsee inventory, cancel click events
event.setCancelled(true);
if(event.getCurrentItem() != null && event.getCurrentItem().isSimilar(instance.getBarrier())) {
Bukkit.getScheduler().runTaskLater(instance, () -> event.getWhoClicked().closeInventory(), 0L);
}
}
/** Handles when a player stops trading with a villager */
@EventHandler
public void onPlayerStopTrading(final InventoryCloseEvent event) {
//Don't do anything unless the player is actually finished trading with a villager
if(event.getInventory().getType() != InventoryType.MERCHANT) return;
if(!(event.getPlayer() instanceof Player)) return;
if(!(event.getInventory().getHolder() instanceof Villager)) return;
final Player player = (Player)event.getPlayer();
final Villager villager = (Villager)event.getInventory().getHolder();
if(settings.shouldSkipNPC(player) || settings.shouldSkipNPC(villager)) return; //Skips NPCs
//Reset the villager's NBT data when a player is finished trading
final PlayerData playerData = instance.getPlayerData().get(player.getUniqueId());
if(playerData == null) return;
final VillagerWrapper villagerWrapper = playerData.getTradingVillager();
if(villagerWrapper == null) return;
playerData.setTradingVillager(null);
villagerWrapper.reset();
}
/** Handles when a player successfully trades with a villager */
@EventHandler
public void onPlayerMakeTrade(final InventoryClickEvent event) {
if(event.getInventory().getType() != InventoryType.MERCHANT) return;
if(!(event.getInventory().getHolder() instanceof Villager)) return;
if(!(event.getWhoClicked() instanceof Player)) return;
if(event.getRawSlot() != 2) return;
final Player player = (Player)event.getWhoClicked();
final Villager villager = (Villager)event.getInventory().getHolder();
if(settings.shouldSkipNPC(player) || settings.shouldSkipNPC(villager)) return; //Skips NPCs
//Get the items involved in the trade
final ItemStack result = event.getCurrentItem();
ItemStack ingredient1 = event.getInventory().getItem(0);
ItemStack ingredient2 = event.getInventory().getItem(1);
if(result == null || result.getType() == Material.AIR) return;
if(ingredient1 == null) ingredient1 = new ItemStack(Material.AIR, 1);
if(ingredient2 == null) ingredient2 = new ItemStack(Material.AIR, 1);
//Check if there is a cooldown set for the trade
final ConfigurationSection overrides = instance.getCfg().getConfigurationSection("Overrides");
if(overrides == null) return;
final String type = settings.getType(result, ingredient1, ingredient2);
String cooldownStr = instance.getCfg().getString("Cooldown", "0");
cooldownStr = overrides.getString(type+".Cooldown", cooldownStr);
String restockStr = instance.getCfg().getString("Restock", "0");
restockStr = overrides.getString(type+".Restock", restockStr);
if(cooldownStr.equals("0") && restockStr.equals("0")) return;
//Get the selected recipe by the items in the slots
final MerchantRecipe selectedRecipe = getSelectedRecipe(villager, ingredient1, ingredient2, result);
if(selectedRecipe == null) {
event.setCancelled(true);
return;
}
//Add a cooldown to the trade if the player has reached the max uses
final PlayerData playerData = instance.getPlayerData().get(player.getUniqueId());
final PlayerData villagerData = instance.getPlayerData().get(villager.getUniqueId());
if(playerData == null || playerData.getTradingVillager() == null) return;
Bukkit.getScheduler().runTaskLater(instance, () -> {
int uses = selectedRecipe.getUses();
final String time = Cooldown.formatTime(Date.from(Instant.now()));
if(uses >= selectedRecipe.getMaxUses()) {
if(!playerData.getTradingCooldowns().containsKey(type)) {
playerData.getTradingCooldowns().put(type, time);
}
if(villagerData != null && !villagerData.getTradingCooldowns().containsKey(type)) {
villagerData.getTradingCooldowns().put(type, time);
}
}
}, 1);
}
/**
* @param villager The villager to get the recipe from
* @param ingredient1 The item in the first ingredient slot of the trade interface
* @param ingredient2 The item in the second ingredient slot of the trade interface
* @param result The item in the result slot of the trade interface
* @return The villager's recipe that matches the items in the slots
*/
private MerchantRecipe getSelectedRecipe(final Villager villager, final ItemStack ingredient1, final ItemStack ingredient2, final ItemStack result) {
for(MerchantRecipe recipe : villager.getRecipes()) {
final ItemStack item1 = recipe.getIngredients().get(0);
final ItemStack item2 = recipe.getIngredients().get(1);
if(!recipe.getResult().isSimilar(result)) continue;
if((item1.isSimilar(ingredient1) && item2.isSimilar(ingredient2)) || (item1.isSimilar(ingredient2) && item2.isSimilar(ingredient1)))
return recipe;
}
return null;
}
}