package joshie.harvest.npcs;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import joshie.harvest.HarvestFestival;
import joshie.harvest.api.buildings.BuildingLocation;
import joshie.harvest.api.npc.INPCHelper;
import joshie.harvest.api.npc.ISchedule;
import joshie.harvest.api.npc.NPC;
import joshie.harvest.api.npc.RelationStatus;
import joshie.harvest.api.npc.gift.IGiftHandler.Quality;
import joshie.harvest.api.npc.greeting.Script;
import joshie.harvest.api.npc.schedule.ScheduleBuilder;
import joshie.harvest.api.quests.Selection;
import joshie.harvest.api.shops.Shop;
import joshie.harvest.cooking.HFCooking;
import joshie.harvest.core.HFTrackers;
import joshie.harvest.core.handlers.GuiHandler;
import joshie.harvest.core.helpers.EntityHelper;
import joshie.harvest.core.helpers.TextHelper;
import joshie.harvest.core.util.annotations.HFApiImplementation;
import joshie.harvest.npcs.entity.*;
import joshie.harvest.npcs.gift.GiftRegistry;
import joshie.harvest.npcs.schedule.Schedule;
import joshie.harvest.player.PlayerTrackerServer;
import joshie.harvest.shops.HFShops;
import joshie.harvest.shops.gui.ShopSelection;
import joshie.harvest.town.TownHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.registry.IForgeRegistry;
import net.minecraftforge.fml.common.registry.RegistryBuilder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@HFApiImplementation
public class NPCHelper implements INPCHelper {
//TODO: Remove in 0.7+
public static final IForgeRegistry<NPC> OLD_REGISTRY = new RegistryBuilder<NPC>().setName(new ResourceLocation("harvestfestival", "npcs")).setType(NPC.class).setIDRange(0, 32000).create();
private static final Cache<EntityPlayer, Map<Shop, ShopSelection>> selections = CacheBuilder.newBuilder().build();
public static final NPCHelper INSTANCE = new NPCHelper();
private final GiftRegistry gifts = new GiftRegistry();
@Override
public GiftRegistry getGifts() {
return gifts;
}
@Override
public ItemStack getStackForNPC(NPC npc) {
return HFNPCs.SPAWNER_NPC.getStackFromObject(npc);
}
@Override
public String getRandomSpeech(NPC npc, String text, int maximumAlternatives, Object... data) {
return TextHelper.getRandomSpeech(npc, text, maximumAlternatives, data);
}
@Override
public ISchedule buildSchedule(ScheduleBuilder builder) {
return new Schedule(builder);
}
@Override
public void forceScriptOpen(EntityPlayer player, EntityAgeable npc, Script script) {
player.openGui(HarvestFestival.instance, GuiHandler.FORCED_NPC, player.worldObj, npc.getEntityId(), Script.REGISTRY.getValues().indexOf(script), -1);
}
public static BlockPos getCoordinatesForLocation(EntityNPCHuman npc, @Nonnull BuildingLocation location) {
return npc.getHomeTown().getCoordinatesFor(location);
}
public static Selection getShopSelection(World worldObj, BlockPos pos, NPC npc, EntityPlayer player) {
return new ShopSelection(npc.getShop(worldObj, pos, player), player);
}
public static BlockPos getHomeForEntity(EntityNPC entity) {
NPC npc = entity.getNPC(); //Shorthand
return npc.getHome() == null ? null : TownHelper.getClosestTownToEntity(entity, false).getCoordinatesFor(npc.getHome());
}
@SuppressWarnings("unchecked")
public static <N extends EntityNPC> N getEntityForNPC(World world, NPC npc) {
if (npc == HFNPCs.MINER) {
return (N) new EntityNPCMiner(world, npc);
}else if (npc == HFNPCs.CARPENTER) {
return (N) new EntityNPCBuilder(world, npc);
} else if (npc == HFNPCs.GODDESS) {
return (N) new EntityNPCGoddess(world, npc);
} else return (N) new EntityNPCVillager(world, npc);
}
@Nullable
public static Entity getNPCIfExists(WorldServer server, BlockPos pos, NPC npc) {
UUID uuid = TownHelper.getClosestTownToBlockPos(server, pos, false).getID();
List<EntityNPC> npcs = EntityHelper.getEntities(EntityNPC.class, server, pos, 128D, 256D);
for (EntityNPC entity: npcs) {
if (entity.getNPC() == npc && entity.getHome().equals(uuid)) return entity;
}
return npc == HFNPCs.CARPENTER ? server.getEntityFromUuid(uuid) : null;
}
private static boolean canPlayerOpenShop(NPC npc, Shop shop, @Nonnull EntityPlayer player) {
return (!player.worldObj.isRemote && HFTrackers.<PlayerTrackerServer>getPlayerTrackerFromPlayer(player).getRelationships().isStatusMet(npc, RelationStatus.MET) || player.worldObj.isRemote) && (shop.canBuyFromShop(player) || shop.canSellToShop(player));
}
public static boolean isShopOpen(EntityNPC npc, World world, @Nonnull EntityPlayer player) {
Shop shop = npc.getNPC().getShop(world, new BlockPos(npc), player); //Grab the shop
return (shop != null && isShopOpen(world, npc, player, shop) && canPlayerOpenShop(npc.getNPC(), shop, player)) && (shop.getContents().size() > 0);
}
public static int getGuiIDForNPC(EntityNPC npc, World world, @Nonnull EntityPlayer player) {
return !npc.isBusy() && isShopOpen(npc, world, player) ? GuiHandler.SHOP_WELCOME: GuiHandler.NPC;
}
public static Quality getGiftValue(NPC npc, ItemStack stack) {
if (stack.getItem() == HFCooking.MEAL && !stack.hasTagCompound()) return Quality.DISLIKE;
else return npc.getGiftValue(stack);
}
@SuppressWarnings("unchecked")
public static boolean isShopOpen(World world, EntityAgeable npc, @Nullable EntityPlayer player, Shop shop) {
return HFShops.TWENTY_FOUR_HOUR_SHOPPING || shop.getOpeningHandler().isOpen(world, npc, player, shop);
}
@Nullable
@SuppressWarnings("deprecation")
public static NPC getNPCFromUUID(UUID uuid) {
for (NPC npc: NPC.REGISTRY.values()) {
if (npc.getUUID().equals(uuid)) return npc;
}
return null;
}
}