// Path: src/main/java/com/nisovin/shopkeepers/compat/NMSManager.java
// public final class NMSManager {
// 
// 	private static NMSCallProvider provider;
// 
// 	public static NMSCallProvider getProvider() {
// 		return NMSManager.provider;
// 	}
// 
// 	public static void load(Plugin plugin) {
// 		final String packageName = plugin.getServer().getClass().getPackage().getName();
// 		String cbversion = packageName.substring(packageName.lastIndexOf('.') + 1);
// 		try {
// 			final Class<?> clazz = Class.forName("com.nisovin.shopkeepers.compat." + cbversion + ".NMSHandler");
// 			if (NMSCallProvider.class.isAssignableFrom(clazz)) {
// 				NMSManager.provider = (NMSCallProvider) clazz.getConstructor().newInstance();
// 			} else {
// 				throw new Exception("Nope");
// 			}
// 		} catch (final Exception e) {
// 			Log.severe("Potentially incompatible server version: " + cbversion);
// 			Log.severe("Shopkeepers is trying to run in 'compatibility mode'.");
// 			Log.info("Check for updates at: " + plugin.getDescription().getWebsite());
// 
// 			try {
// 				NMSManager.provider = new FailedHandler();
// 			} catch (Exception e_u) {
// 				// uncomment for debugging:
// 				// e_u.printStackTrace();
// 			}
// 		}
// 	}
// }
// 
// Path: src/main/java/com/nisovin/shopkeepers/shopobjects/DefaultShopObjectTypes.java
// public class DefaultShopObjectTypes {
// 
// 	private final LivingEntityObjectTypes livingEntityObjectTypes = new LivingEntityObjectTypes();
// 	private final ShopObjectType signShopObjectType = new SignShopObjectType();
// 	private final ShopObjectType citizensShopObjectType = new CitizensShopObjectType();
// 
// 	// TODO maybe change object type permissions to 'shopkeeper.object.<type>'?
// 
// 	public DefaultShopObjectTypes() {
// 	}
// 
// 	public List<ShopObjectType> getAllObjectTypes() {
// 		List<ShopObjectType> shopObjectTypes = new ArrayList<ShopObjectType>();
// 		shopObjectTypes.addAll(livingEntityObjectTypes.getAllObjectTypes());
// 		shopObjectTypes.add(signShopObjectType);
// 		shopObjectTypes.add(citizensShopObjectType);
// 		return shopObjectTypes;
// 	}
// 
// 	public LivingEntityObjectTypes getLivingEntityObjectTypes() {
// 		return livingEntityObjectTypes;
// 	}
// 
// 	public ShopObjectType getSignShopObjectType() {
// 		return signShopObjectType;
// 	}
// 
// 	public ShopObjectType getCitizensShopObjectType() {
// 		return citizensShopObjectType;
// 	}
// 
// 	// STATICS (for convenience):
// 
// 	public static ShopObjectType SIGN() {
// 		return ShopkeepersPlugin.getInstance().getDefaultShopObjectTypes().getSignShopObjectType();
// 	}
// 
// 	public static ShopObjectType CITIZEN() {
// 		return ShopkeepersPlugin.getInstance().getDefaultShopObjectTypes().getCitizensShopObjectType();
// 	}
// }


import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.entity.CreeperPowerEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.entity.EntityTeleportEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.PigZapEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.entity.SheepDyeWoolEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.projectiles.ProjectileSource;
import com.nisovin.shopkeepers.compat.NMSManager;
import com.nisovin.shopkeepers.shopobjects.DefaultShopObjectTypes;
package com.nisovin.shopkeepers;



class LivingEntityShopListener implements Listener {

	// the radius around lightning strikes in which villagers turn into witches
	private static final int VILLAGER_ZAP_RADIUS = 7; // minecraft wiki says 3-4, we use 7 to be safe

	private final ShopkeepersPlugin plugin;

	LivingEntityShopListener(ShopkeepersPlugin plugin) {
		this.plugin = plugin;
	}

	@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = false)
	void onEntityInteract(PlayerInteractEntityEvent event) {
		if (!(event.getRightClicked() instanceof LivingEntity)) return;
		LivingEntity shopEntity = (LivingEntity) event.getRightClicked();
		Player player = event.getPlayer();
		String playerName = player.getName();
		Log.debug("Player " + playerName + " is interacting with entity at " + shopEntity.getLocation());
		Shopkeeper shopkeeper = plugin.getShopkeeperByEntity(shopEntity); // also check for citizens npc shopkeepers

		if (event.isCancelled() && !Settings.bypassShopInteractionBlocking) {
			Log.debug("  Cancelled by another plugin");
		} else if (shopkeeper != null) {
			// only trigger shopkeeper interaction for main-hand events:
			if (NMSManager.getProvider().isMainHandInteraction(event)) {
				shopkeeper.onPlayerInteraction(player);
			}

			// if citizens npc: don't cancel the event, let Citizens perform other actions as appropriate
// Path: src/main/java/com/nisovin/shopkeepers/compat/NMSManager.java
// public final class NMSManager {
// 
// 	private static NMSCallProvider provider;
// 
// 	public static NMSCallProvider getProvider() {
// 		return NMSManager.provider;
// 	}
// 
// 	public static void load(Plugin plugin) {
// 		final String packageName = plugin.getServer().getClass().getPackage().getName();
// 		String cbversion = packageName.substring(packageName.lastIndexOf('.') + 1);
// 		try {
// 			final Class<?> clazz = Class.forName("com.nisovin.shopkeepers.compat." + cbversion + ".NMSHandler");
// 			if (NMSCallProvider.class.isAssignableFrom(clazz)) {
// 				NMSManager.provider = (NMSCallProvider) clazz.getConstructor().newInstance();
// 			} else {
// 				throw new Exception("Nope");
// 			}
// 		} catch (final Exception e) {
// 			Log.severe("Potentially incompatible server version: " + cbversion);
// 			Log.severe("Shopkeepers is trying to run in 'compatibility mode'.");
// 			Log.info("Check for updates at: " + plugin.getDescription().getWebsite());
// 
// 			try {
// 				NMSManager.provider = new FailedHandler();
// 			} catch (Exception e_u) {
// 				// uncomment for debugging:
// 				// e_u.printStackTrace();
// 			}
// 		}
// 	}
// }
// 
// Path: src/main/java/com/nisovin/shopkeepers/shopobjects/DefaultShopObjectTypes.java
// public class DefaultShopObjectTypes {
// 
// 	private final LivingEntityObjectTypes livingEntityObjectTypes = new LivingEntityObjectTypes();
// 	private final ShopObjectType signShopObjectType = new SignShopObjectType();
// 	private final ShopObjectType citizensShopObjectType = new CitizensShopObjectType();
// 
// 	// TODO maybe change object type permissions to 'shopkeeper.object.<type>'?
// 
// 	public DefaultShopObjectTypes() {
// 	}
// 
// 	public List<ShopObjectType> getAllObjectTypes() {
// 		List<ShopObjectType> shopObjectTypes = new ArrayList<ShopObjectType>();
// 		shopObjectTypes.addAll(livingEntityObjectTypes.getAllObjectTypes());
// 		shopObjectTypes.add(signShopObjectType);
// 		shopObjectTypes.add(citizensShopObjectType);
// 		return shopObjectTypes;
// 	}
// 
// 	public LivingEntityObjectTypes getLivingEntityObjectTypes() {
// 		return livingEntityObjectTypes;
// 	}
// 
// 	public ShopObjectType getSignShopObjectType() {
// 		return signShopObjectType;
// 	}
// 
// 	public ShopObjectType getCitizensShopObjectType() {
// 		return citizensShopObjectType;
// 	}
// 
// 	// STATICS (for convenience):
// 
// 	public static ShopObjectType SIGN() {
// 		return ShopkeepersPlugin.getInstance().getDefaultShopObjectTypes().getSignShopObjectType();
// 	}
// 
// 	public static ShopObjectType CITIZEN() {
// 		return ShopkeepersPlugin.getInstance().getDefaultShopObjectTypes().getCitizensShopObjectType();
// 	}
// }


// Path: src/main/java/com/nisovin/shopkeepers/LivingEntityShopListener.java
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.entity.CreeperPowerEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.entity.EntityTeleportEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.PigZapEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.entity.SheepDyeWoolEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.projectiles.ProjectileSource;
import com.nisovin.shopkeepers.compat.NMSManager;
import com.nisovin.shopkeepers.shopobjects.DefaultShopObjectTypes;

package com.nisovin.shopkeepers;



class LivingEntityShopListener implements Listener {

	// the radius around lightning strikes in which villagers turn into witches
	private static final int VILLAGER_ZAP_RADIUS = 7; // minecraft wiki says 3-4, we use 7 to be safe

	private final ShopkeepersPlugin plugin;

	LivingEntityShopListener(ShopkeepersPlugin plugin) {
		this.plugin = plugin;
	}

	@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = false)
	void onEntityInteract(PlayerInteractEntityEvent event) {
		if (!(event.getRightClicked() instanceof LivingEntity)) return;
		LivingEntity shopEntity = (LivingEntity) event.getRightClicked();
		Player player = event.getPlayer();
		String playerName = player.getName();
		Log.debug("Player " + playerName + " is interacting with entity at " + shopEntity.getLocation());
		Shopkeeper shopkeeper = plugin.getShopkeeperByEntity(shopEntity); // also check for citizens npc shopkeepers

		if (event.isCancelled() && !Settings.bypassShopInteractionBlocking) {
			Log.debug("  Cancelled by another plugin");
		} else if (shopkeeper != null) {
			// only trigger shopkeeper interaction for main-hand events:
			if (NMSManager.getProvider().isMainHandInteraction(event)) {
				shopkeeper.onPlayerInteraction(player);
			}

			// if citizens npc: don't cancel the event, let Citizens perform other actions as appropriate
			if (shopkeeper.getShopObject().getObjectType() != DefaultShopObjectTypes.CITIZEN()) {