package joshie.harvest.quests.town.festivals.contest.animal; import com.google.common.collect.Lists; import joshie.harvest.api.HFApi; import joshie.harvest.api.animals.AnimalStats; import joshie.harvest.api.npc.NPC; import joshie.harvest.buildings.HFBuildings; import joshie.harvest.core.helpers.EntityHelper; import joshie.harvest.quests.base.QuestAnimalContest; import joshie.harvest.quests.town.festivals.contest.ContestEntries; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.apache.commons.lang3.tuple.Pair; import java.lang.reflect.InvocationTargetException; import java.util.*; public class AnimalContestEntries<E extends EntityAnimal> extends ContestEntries<E, AnimalContestEntry, QuestAnimalContest> { private final Class<E> entityClass; private final String[] names; private Set<String> used; public AnimalContestEntries(Class<E> entity, BlockPos[] locations, NPC[] npcs, String[] names) { super(locations, npcs); this.entityClass = entity; this.names = names; } @Override public List<Pair<E, Integer>> getAvailableEntries(EntityPlayer player) { //Validate the existing entries validateExistingEntries(player.worldObj); //Grab the list of closest List<Pair<E, Integer>> list = Lists.newArrayList(); for (int i = 0; i < locations.length; i++) { BlockPos location = locations[i]; int stall = i + 1; if (!isEntered(stall)) { BlockPos target = HFApi.towns.getTownForEntity(player).getCoordinatesFromOffset(HFBuildings.FESTIVAL_GROUNDS, location); E animal = getClosestAnimal(player.worldObj, target); if (animal != null) { Pair<E, Integer> pair = Pair.of(animal, stall); if (!list.contains(pair)) { list.add(pair); } } } } return list; } @Override public void enter(EntityPlayer player, E animal, int stall) { UUID playerUUID = EntityHelper.getPlayerUUID(player); UUID animalUUID = EntityHelper.getEntityUUID(animal); //Wipe out any entries that match the exist Iterator<AnimalContestEntry> it = entries.iterator(); while (it.hasNext()) { AnimalContestEntry entry = it.next(); if (entry.getStall() == stall || playerUUID.equals(entry.getPlayerUUID()) || animalUUID.equals(entry.getAnimalUUID())) { it.remove(); } } entries.add(new AnimalContestEntry(playerUUID, animalUUID, stall)); selecting.remove(playerUUID); } @Override public List<Pair<String, Integer>> getAvailableEntryNames(EntityPlayer player) { List<Pair<String, Integer>> list = new ArrayList<>(); for (Pair<E, Integer> pair: getAvailableEntries(player)) { list.add(Pair.of(pair.getKey().getName(), pair.getValue())); } return list; } private E createEntity(World world) { E entity = null; try { if (entityClass != null) { entity = entityClass.getConstructor(new Class[]{World.class}).newInstance(world); } } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { /**/} return entity; } @Override protected void createEntry(EntityPlayer player, World world, BlockPos pos, int stall) { E animal = createEntity(world); animal.setPositionAndUpdate(pos.getX(), pos.getY(), pos.getZ()); animal.setCustomNameTag(getNextEntry(player, used, names)); world.spawnEntityInWorld(animal); AnimalStats stats = EntityHelper.getStats(animal); if (stats != null) { animal.setEntityInvulnerable(true); stats.setProduced(5); //Forbid the animal making products stats.setDead(); //Autokill the animal the next day if it somehow persists stats.affectHappiness(world.rand.nextInt(20000)); //Give the animal a random happiness } entries.add(new AnimalContestEntry(getNextEntry(player, usedNPCS, npcs), EntityHelper.getEntityUUID(animal), stall)); } @SuppressWarnings("ConstantConditions") //After this is called, we need to sync up the entries to the clients @Override public void startContest(EntityPlayer player) { World world = player.worldObj; if (entries.size() < 4) { used = new HashSet<>(); entries.stream().forEach(e -> used.add(e.getName(world))); } super.startContest(player); } @Override protected AnimalContestEntry fromNBT(NBTTagCompound tag) { return AnimalContestEntry.fromNBT(tag); } private E getClosestAnimal(World world, BlockPos pos) { List<E> animals = EntityHelper.getEntities(entityClass, world, pos, 5D, 5D); double d0 = -1.0D; E closest = null; for (E animal: animals) { if (animal.isDead || animal.isAirBorne) continue; double d1 = animal.getDistanceSq(pos); if ((d1 < 5D * 5D) && (d0 == -1.0D || d1 < d0)) { d0 = d1; closest = animal; } } return closest; } @Override public void complete(World world) { entries.stream().filter(entry -> entry.getPlayerUUID() == null).forEach(entry -> { E animal = EntityHelper.getAnimalFromUUID(world, entry.getAnimalUUID()); if (animal != null) { animal.setDead(); } }); } }