2021-06-27 14:42:57 +02:00
package com.pretzel.dev.villagertradelimiter.listeners ;
import com.pretzel.dev.villagertradelimiter.VillagerTradeLimiter ;
2022-09-04 11:08:55 +02:00
import com.pretzel.dev.villagertradelimiter.data.CustomRecipe ;
2022-01-07 09:57:59 +01:00
import com.pretzel.dev.villagertradelimiter.data.PlayerData ;
2022-07-03 21:15:14 +02:00
import com.pretzel.dev.villagertradelimiter.lib.Util ;
2022-09-04 11:08:55 +02:00
import com.pretzel.dev.villagertradelimiter.nms.NMSVillager ;
import org.bukkit.* ;
import org.bukkit.entity.* ;
2021-06-27 14:42:57 +02:00
import org.bukkit.event.EventHandler ;
import org.bukkit.event.Listener ;
2022-09-04 11:08:55 +02:00
import org.bukkit.event.inventory.InventoryCloseEvent ;
import org.bukkit.event.inventory.InventoryType ;
2021-06-27 14:42:57 +02:00
import org.bukkit.event.player.PlayerInteractEntityEvent ;
2022-09-04 11:08:55 +02:00
import org.bukkit.inventory.* ;
2021-06-27 14:42:57 +02:00
import org.bukkit.potion.PotionEffect ;
import org.bukkit.potion.PotionEffectType ;
2022-09-04 11:08:55 +02:00
import java.util.* ;
2021-06-27 14:42:57 +02:00
public class PlayerListener implements Listener {
2022-09-04 11:08:55 +02:00
2021-06-27 16:24:05 +02:00
private final VillagerTradeLimiter instance ;
2022-09-04 11:08:55 +02:00
private final HashMap < Villager , ArrayList < CustomRecipe > > customRecipes ;
2021-06-27 14:42:57 +02:00
2022-01-11 10:22:52 +01:00
/ * *
* @param instance The instance of VillagerTradeLimiter . java
* /
2022-09-04 11:08:55 +02:00
public PlayerListener ( final VillagerTradeLimiter instance ) {
2021-06-27 14:42:57 +02:00
this . instance = instance ;
2022-09-04 11:08:55 +02:00
this . customRecipes = new HashMap < > ( ) ;
2021-06-27 14:42:57 +02:00
}
2022-01-07 09:57:59 +01:00
/** Handles when a player begins trading with a villager */
2021-06-27 14:42:57 +02:00
@EventHandler
2022-01-11 10:22:52 +01:00
public void onPlayerBeginTrading ( final PlayerInteractEntityEvent event ) {
2022-09-04 11:08:55 +02:00
if ( event . isCancelled ( ) ) return ; //Skips when the event is already cancelled
if ( ! ( event . getRightClicked ( ) instanceof final Villager villager ) ) return ; //Skips non-villager entity interactions
if ( villager . getRecipeCount ( ) = = 0 ) return ; //Skips when the villager has no trades
2022-04-11 03:32:26 +02:00
2022-01-22 02:56:44 +01:00
final Player player = event . getPlayer ( ) ;
2022-09-04 11:08:55 +02:00
final ItemStack heldItem = player . getInventory ( ) . getItem ( event . getHand ( ) ) ;
if ( instance . getSettings ( ) . shouldSkipNPC ( player , villager ) ) return ; //Skips when the player or villager is a Citizens NPC or Shopkeeper
if ( heldItem ! = null & & instance . getSettings ( ) . getIgnoreHeldItems ( ) . contains ( heldItem . getType ( ) . name ( ) . toLowerCase ( ) ) ) return ; //Skips when player is holding an ignored item
if ( instance . getSettings ( ) . getIgnoreWorlds ( ) . contains ( villager . getWorld ( ) . getName ( ) ) ) return ; //Skips when the villager is in an ignored world
//Skips and cancels the event when the player is in a disabled world
if ( instance . getSettings ( ) . getDisableTrading ( ) . contains ( player . getWorld ( ) . getName ( ) ) ) {
Util . sendMsg ( instance . getLang ( " trading.noworld " ) , player ) ;
event . setCancelled ( true ) ;
return ;
2022-04-11 03:32:26 +02:00
}
2021-09-16 07:35:21 +02:00
2022-09-04 11:08:55 +02:00
//Skips and cancels the event when the villager has a disabled profession
String profession = villager . getProfession ( ) . name ( ) . toLowerCase ( ) ;
if ( instance . getSettings ( ) . getDisableProfessions ( ) . contains ( profession ) ) {
Util . sendMsg ( instance . getLang ( " trading.noprofession " ) . replace ( " {profession} " , profession ) , player ) ;
event . setCancelled ( true ) ;
return ;
2021-06-27 14:42:57 +02:00
}
2022-01-11 10:22:52 +01:00
//Cancel the original event, and open the adjusted trade view
2022-01-07 09:57:59 +01:00
event . setCancelled ( true ) ;
2022-09-04 11:08:55 +02:00
instance . getPlayerData ( ) . putIfAbsent ( player . getUniqueId ( ) , new PlayerData ( ) ) ;
instance . getPlayerData ( ) . putIfAbsent ( villager . getUniqueId ( ) , new PlayerData ( ) ) ;
this . see ( villager , player , player ) ;
}
/** 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 ; //Skips non-merchant inventories
if ( ! ( event . getPlayer ( ) instanceof final Player player ) ) return ; //Skips non-players
if ( ! ( event . getInventory ( ) . getHolder ( ) instanceof final Villager villager ) ) return ; //Skips non-villagers
if ( instance . getSettings ( ) . shouldSkipNPC ( player , villager ) ) return ; //Skips NPCs
//Reset the villager's recipes to vanilla when a player is finished trading
resetVillager ( villager ) ;
}
private void resetVillager ( final Villager villager ) {
if ( ! customRecipes . containsKey ( villager ) ) return ;
ArrayList < CustomRecipe > recipes = customRecipes . get ( villager ) ;
for ( int i = 0 ; i < recipes . size ( ) ; i + + ) {
recipes . get ( i ) . reset ( ) ;
villager . setRecipe ( i , recipes . get ( i ) . getOriginal ( ) ) ;
2022-01-15 18:10:28 +01:00
}
2022-09-04 11:08:55 +02:00
}
2022-01-22 02:56:44 +01:00
2022-09-04 11:08:55 +02:00
public void onDisable ( ) {
//Reset the villager's recipes to vanilla when the plugin is disabled
for ( Villager villager : customRecipes . keySet ( ) ) resetVillager ( villager ) ;
customRecipes . clear ( ) ;
2021-06-27 14:42:57 +02:00
}
2022-01-07 09:57:59 +01:00
/ * *
* Opens the villager ' s trading menu , with the adjusted trades of another player ( or the same player )
* @param villager The villager whose trades you want to see
* @param player The player who calls the command , or the player that has begun trading
* @param other The other player to view trades for , or the player that has just begun trading
* /
public void see ( final Villager villager , final Player player , final OfflinePlayer other ) {
2022-07-03 21:15:14 +02:00
//Skips when the villager is in a disabled world
2022-09-04 11:08:55 +02:00
if ( instance . getSettings ( ) . getDisableTrading ( ) . contains ( villager . getWorld ( ) . getName ( ) ) ) {
2022-07-03 21:15:14 +02:00
Util . sendMsg ( instance . getLang ( " see.noworld " ) , player ) ;
return ;
}
2022-01-07 09:57:59 +01:00
//Wraps the villager and player into wrapper classes
2022-09-04 11:08:55 +02:00
if ( other = = null | | instance . getSettings ( ) . shouldSkipNPC ( player , villager ) ) return ; //Skips NPCs
2022-01-07 09:57:59 +01:00
//Calculates the player's total reputation and Hero of the Village discount
2022-09-04 11:08:55 +02:00
final NMSVillager nmsVillager = new NMSVillager ( villager ) ;
int totalReputation = nmsVillager . getTotalReputation ( other ) ;
double hotvDiscount = getHotvDiscount ( other ) ;
2022-01-07 09:57:59 +01:00
//Adjusts the recipe prices, MaxUses, and ingredients
2022-09-04 11:08:55 +02:00
final ArrayList < MerchantRecipe > originalRecipes = new ArrayList < > ( villager . getRecipes ( ) ) ;
final ArrayList < CustomRecipe > recipes = new ArrayList < > ( ) ;
for ( int i = 0 ; i < originalRecipes . size ( ) ; i + + ) {
recipes . add ( new CustomRecipe ( instance , other , villager , originalRecipes . get ( i ) ) ) ;
villager . setRecipe ( i , recipes . get ( i ) . getAdjusted ( ) ) ;
2022-01-07 09:57:59 +01:00
}
2022-09-04 11:08:55 +02:00
customRecipes . put ( villager , recipes ) ;
2021-12-15 21:30:01 +01:00
2022-09-10 05:32:49 +02:00
//Opens the trading window
2022-09-10 05:44:26 +02:00
boolean multipleTraders = instance . getSettings ( ) . getMultipleTraders ( ) ;
2022-09-10 05:32:49 +02:00
int delay = instance . getSettings ( ) . getTradeDelay ( ) ;
if ( delay > = 0 ) {
2022-09-10 05:44:26 +02:00
Bukkit . getScheduler ( ) . runTaskLater ( instance , ( ) - > player . openMerchant ( villager , multipleTraders ) , delay ) ;
2022-09-10 05:32:49 +02:00
} else {
2022-09-10 05:44:26 +02:00
player . openMerchant ( villager , multipleTraders ) ;
2022-09-10 05:32:49 +02:00
}
2021-12-21 07:56:02 +01:00
2022-09-10 05:32:49 +02:00
//Updates the prices
2022-09-04 11:08:55 +02:00
for ( int i = 0 ; i < villager . getRecipes ( ) . size ( ) ; i + + ) {
2022-09-10 05:32:49 +02:00
int discount = recipes . get ( i ) . getDiscount ( totalReputation , hotvDiscount ) ;
villager . getRecipe ( i ) . setSpecialPrice ( discount ) ;
2021-06-27 14:42:57 +02:00
}
}
2022-01-07 09:57:59 +01:00
/ * *
2022-09-04 11:08:55 +02:00
* @param other The player to check the hotv effect for
2022-01-07 09:57:59 +01:00
* @return The Hero of the Village discount factor , adjusted by config
* /
2022-09-04 11:08:55 +02:00
private double getHotvDiscount ( final OfflinePlayer other ) {
final Player player = other . getPlayer ( ) ;
2022-01-07 09:57:59 +01:00
if ( player = = null ) return 0 . 0 ;
final PotionEffectType effectType = PotionEffectType . HERO_OF_THE_VILLAGE ;
if ( ! player . hasPotionEffect ( effectType ) ) return 0 . 0 ;
final PotionEffect effect = player . getPotionEffect ( effectType ) ;
if ( effect = = null ) return 0 . 0 ;
2022-01-15 18:10:28 +01:00
//Calculates the discount factor from the player's current effect level or the defined maximum
2022-01-07 09:57:59 +01:00
int heroLevel = effect . getAmplifier ( ) + 1 ;
2022-09-04 11:08:55 +02:00
final int maxHeroLevel = instance . getGroupManager ( ) . getGroup ( other ) . getMaxHeroLevel ( ) ; ;
2022-01-07 09:57:59 +01:00
if ( maxHeroLevel = = 0 | | heroLevel = = 0 ) return 0 . 0 ;
if ( maxHeroLevel > 0 & & heroLevel > maxHeroLevel ) {
heroLevel = maxHeroLevel ;
2021-06-27 14:42:57 +02:00
}
2022-01-07 09:57:59 +01:00
return 0 . 0625 * ( heroLevel - 1 ) + 0 . 3 ;
}
2021-06-27 14:42:57 +02:00
2022-09-04 11:08:55 +02:00
2022-01-07 09:57:59 +01:00
/ * *
2022-09-04 11:08:55 +02:00
* @param villager The villager
* @return The list of original recipes for the villager
2022-01-07 09:57:59 +01:00
* /
2022-09-04 11:08:55 +02:00
public ArrayList < CustomRecipe > getCustomRecipes ( final Villager villager ) { return this . customRecipes . get ( villager ) ; }
2021-06-27 14:42:57 +02:00
}