package joshie.harvest.quests.town.festivals.starry;
import joshie.harvest.api.HFApi;
import joshie.harvest.api.npc.NPC;
import joshie.harvest.api.npc.NPCEntity;
import joshie.harvest.api.npc.task.HFTask;
import joshie.harvest.api.npc.task.TaskElement;
import joshie.harvest.api.npc.task.TaskSpeech;
import joshie.harvest.api.npc.task.TaskWait;
import joshie.harvest.api.quests.Selection;
import joshie.harvest.buildings.HFBuildings;
import joshie.harvest.cooking.HFCooking;
import joshie.harvest.cooking.item.ItemMeal.Meal;
import joshie.harvest.core.HFCore;
import joshie.harvest.core.block.BlockStand.Stand;
import joshie.harvest.core.helpers.TextHelper;
import joshie.harvest.core.tile.TilePlate;
import joshie.harvest.quests.town.festivals.QuestStarryNight;
import joshie.harvest.quests.town.festivals.contest.ContestEntries;
import joshie.harvest.town.TownHelper;
import joshie.harvest.town.data.TownData;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.translation.I18n;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.eventhandler.Event.Result;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
import static joshie.harvest.cooking.item.ItemMeal.Meal.*;
import static joshie.harvest.quests.town.festivals.QuestStarryNight.GOODBYE;
import static joshie.harvest.quests.town.festivals.QuestStarryNight.WELCOME;
public class StarryNightData extends Selection<QuestStarryNight> {
//TODO: Add locations for the plates
private static final BlockPos[] plates = new BlockPos[] { new BlockPos(10, 2, 13), new BlockPos(10, 2, 14), new BlockPos(10, 2, 15), new BlockPos(10, 2, 16), new BlockPos(10, 2, 17), new BlockPos(10, 2, 18) };
private static final Meal[] meals = new Meal[] { FISH_GRILLED, POTSTICKER, RISOTTO, SASHIMI_CHIRASHI, DUMPLINGS, STEW_PUMPKIN, STIR_FRY };
private static final String prefix = "harvestfestival.quest.festival.starry.night";
private static final String[] lines2 = new String[] { "harvestfestival.quest.festival.starry.night.ready", "harvestfestival.quest.festival.starry.night.go", "harvestfestival.quest.festival.starry.night.no"};
private boolean completed;
private boolean chat;
private NPC invited;
public StarryNightData() {
super("harvestfestival.quest.festival.starry.night.what", "harvestfestival.quest.festival.starry.night.invite", "harvestfestival.quest.festival.starry.night.chat");
}
@Override
public String[] getText(@Nonnull EntityPlayer player, QuestStarryNight quest) {
return invited == null ? lines : lines2;
}
public Selection getSelection(long time) {
return !chat && (invited == null || time >= 18000L || time < 6000L) ? this : null;
}
@SuppressWarnings("deprecation")
@SideOnly(Side.CLIENT)
public String getLocalized(String quest, Object... format) {
if (format.length == 0) return I18n.translateToLocal(prefix + "." + quest.replace("_", ""));
else return I18n.translateToLocalFormatted(prefix + "." + quest.replace("_", ""), format);
}
@SideOnly(Side.CLIENT)
public String getLocalizedScript(NPC npc) {
if (chat) return null;
else if (invited == null) return TextHelper.getSpeech(npc, "festival.starry.night.invite");
else if (!completed && invited == npc) return TextHelper.getSpeech(npc, "festival.starry.night.start");
else return invited == npc ? TextHelper.getSpeech(npc, "festival.starry.night.tonight") : null;
}
public boolean isChatting() {
if (chat) {
chat = false;
return true;
} else return false;
}
public boolean isFinished() {
return completed;
}
public boolean isInvited(NPCEntity npc) {
return invited != null && (invited == npc.getNPC() || invited.getFamily().contains(npc.getNPC()));
}
private void spawnPlateAtLocation(EntityPlayer player, World world, Set<Meal> used, BlockPos pos) {
world.setBlockState(pos, HFCore.STAND.getStateFromEnum(Stand.PLATE));
TileEntity tile = world.getTileEntity(pos);
if (tile instanceof TilePlate) {
((TilePlate)tile).setContents(HFCooking.MEAL.getCreativeStack(ContestEntries.getNextEntry(player, used, meals)));
}
}
private void startSequence(EntityPlayer player, NPCEntity entity) {
Set<Meal> used = new HashSet<>();
TownData data = TownHelper.getClosestTownToEntity(player, false);
Set<BlockPos> positions = new HashSet<>();
BlockPos playerPlate = data.getCoordinatesFromOffset(HFBuildings.FESTIVAL_GROUNDS, plates[0]);
BlockPos npcPlate = data.getCoordinatesFromOffset(HFBuildings.FESTIVAL_GROUNDS, plates[1]);
if (playerPlate != null) positions.add(playerPlate);
if (npcPlate != null) positions.add(npcPlate);
Set<NPC> family = entity.getNPC().getFamily(); //Family
for (int i = 2; i < family.size() + 2; i++) {
BlockPos pos = data.getCoordinatesFromOffset(HFBuildings.FESTIVAL_GROUNDS, plates[i]);
if (pos != null) positions.add(pos);
}
positions.stream().forEach(pos -> spawnPlateAtLocation(player, player.worldObj, used, pos));
HFApi.player.getRelationsForPlayer(player).affectRelationship(entity.getNPC(), 5000);
for (NPC npc: family) {
HFApi.player.getRelationsForPlayer(player).affectRelationship(npc, 2500);
}
//Have all the npcs walk to their seat and sit down
//Have the main person thank everyone for coming tonight and make a speech
//Have everyone dig in to their meal
entity.setPath(TaskSpeech.of(WELCOME), TaskWait.of(1), new ConsumeFood(positions, false), TaskSpeech.of(GOODBYE), new ConsumeFood(positions, true));
}
@HFTask("starry")
public static class ConsumeFood extends TaskElement {
private Set<BlockPos> positions;
private boolean destroy;
public ConsumeFood(Set<BlockPos> pos, boolean destroy) {
this.positions = pos;
this.destroy = destroy;
}
@Override
public void execute(NPCEntity npc) {
super.execute(npc);
for (BlockPos pos: positions) {
if (destroy) npc.getAsEntity().worldObj.setBlockToAir(pos);
else {
TileEntity tile = npc.getAsEntity().worldObj.getTileEntity(pos);
if (tile instanceof TilePlate) {
((TilePlate) tile).setContents(null);
}
}
}
/*
if (destroy) { //Complete this quest too
QuestStarryNight quest = TownHelper.getClosestTownToEntity(npc, false).getQuests().getAQuest(HFFestivals.STARRY_NIGHT.getQuest());
if (quest != null) {
TownHelper.getClosestTownToEntity(npc, false).getQuests().markCompleted(npc.worldObj, null, quest, false);
}
} */
}
@Override
public void readFromNBT(NBTTagCompound tag) {
destroy = tag.getBoolean("Destroy");
positions = new HashSet<>();
NBTTagList list = tag.getTagList("Positions", 10);
for (int i = 0; i < list.tagCount(); i++) {
NBTTagCompound nbt = list.getCompoundTagAt(i);
BlockPos pos = BlockPos.fromLong(nbt.getLong("Position"));
positions.add(pos);
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
tag.setBoolean("Destroy", destroy);
NBTTagList list = new NBTTagList();
for (BlockPos pos: positions) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setLong("Position", pos.toLong());
list.appendTag(nbt);
}
tag.setTag("Positions", list);
return tag;
}
}
@Override
public Result onSelected(EntityPlayer player, NPCEntity entity, QuestStarryNight quest, int option) {
if (invited == null) {
//Option1 = Invite to Starry Night
if (option == 1) invited = entity.getNPC();
else chat = true;
} else {
if (option == 1) {
chat = true;
completed = true;
startSequence(player, entity);
} else return Result.DENY;
}
quest.syncData(player); //Resync to client
//Option2 = Chat
return Result.ALLOW;
}
/////////////////////////////// Saving and Loading /////////////////////////////////
public static StarryNightData fromNBT(NBTTagCompound tag) {
StarryNightData data = new StarryNightData();
data.chat = tag.getBoolean("Chatting");
data.completed = tag.getBoolean("Completed");
if (tag.hasKey("NPC")) data.invited = NPC.REGISTRY.get(new ResourceLocation(tag.getString("NPC")));
return data;
}
public NBTTagCompound toNBT() {
NBTTagCompound tag = new NBTTagCompound();
tag.setBoolean("Completed", completed);
tag.setBoolean("Chatting", chat);
if (invited != null) tag.setString("NPC", invited.getResource().toString());
return tag;
}
}