package com.bioxx.tfc2.handlers;
import java.util.ArrayList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.PotionEffect;
import net.minecraft.world.GameType;
import net.minecraftforge.client.event.FOVUpdateEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import com.bioxx.jmapgen.IslandMap;
import com.bioxx.tfc2.Core;
import com.bioxx.tfc2.TFC;
import com.bioxx.tfc2.api.AnimalSpawnRegistry.SpawnEntry;
import com.bioxx.tfc2.api.TFCOptions;
import com.bioxx.tfc2.api.interfaces.IFood;
import com.bioxx.tfc2.api.interfaces.IFoodStatsTFC;
import com.bioxx.tfc2.api.interfaces.IUpdateInInventory;
import com.bioxx.tfc2.api.types.EnumFoodGroup;
import com.bioxx.tfc2.core.Food;
import com.bioxx.tfc2.core.Timekeeper;
import com.bioxx.tfc2.networking.client.CFoodPacket;
import com.bioxx.tfc2.potion.PotionTFC;
import com.bioxx.tfc2.world.WeatherManager;
import com.bioxx.tfc2.world.WorldGen;
public class EntityLivingHandler
{
public static final AttributeModifier THIRST = new AttributeModifier("Thirsty", -0.1, 2);
@SubscribeEvent
public void onEntityLivingUpdate(LivingUpdateEvent event)
{
if (event.getEntityLiving() instanceof EntityPlayerMP)
{
EntityPlayerMP player = (EntityPlayerMP)event.getEntityLiving();
//If the player enters the portal realm then set them to adventure mode to prevent altering the world
if(player.worldObj.provider.getDimension() == 2 && !player.capabilities.isCreativeMode && !player.isSpectator())
player.setGameType(GameType.ADVENTURE);
else if(player.worldObj.provider.getDimension() == 0 && !player.capabilities.isCreativeMode && !player.isSpectator())
{
IslandMap map = WorldGen.getInstance().getIslandMap((int)player.posX >> 12, (int)player.posZ >> 12);
if(map.getIslandData().isIslandUnlocked && !player.isSpectator())
player.setGameType(GameType.SURVIVAL);
else if(!player.isSpectator())
player.setGameType(GameType.ADVENTURE);
}
//Set Max Health
float newMaxHealth = getMaxHealth(player);
float oldMaxHealth = (float)player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getAttributeValue();
if(oldMaxHealth != newMaxHealth)
{
player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(newMaxHealth);
}
if(!player.worldObj.isRemote)
{
//Tick Item Updates
for(int i = 0; i < player.inventory.mainInventory.length; i++)
{
ItemStack is = player.inventory.mainInventory[i];
if(is != null)
{
if(is.getItem() instanceof IUpdateInInventory)
{
((IUpdateInInventory)is.getItem()).inventoryUpdate(player, is);
if(is.stackSize == 0)
player.inventory.mainInventory[i] = null;
}
if(is.getItem() instanceof IFood)
{
IFood food = (IFood)is.getItem();
long time = Food.getDecayTimer(is)-player.worldObj.getWorldTime();
if(time < 0)
{
int expiredAmt = (int)Math.min(1+(time / Food.getExpirationTimer(is))* (-1), is.stackSize);
expiredAmt = Math.max(expiredAmt, 0);
is.stackSize-=expiredAmt;
Food.setDecayTimer(is, Food.getDecayTimer(is)+Food.getExpirationTimer(is)*expiredAmt);
if(is.stackSize <= 0)
player.inventory.mainInventory[i] = null;
ItemStack out = food.onDecayed(is, player.worldObj, player.getPosition().getX(), player.getPosition().getY(), player.getPosition().getZ());
if(out != null)
{
out.stackSize = expiredAmt;
player.inventory.addItemStackToInventory(out);
}
}
}
}
}
//Drain Nutrition
NBTTagCompound tfcData = getEntityData(player.getEntityData());
if(!tfcData.hasKey("nutritionDrainTimer"))
tfcData.setLong("nutritionDrainTimer", Timekeeper.getInstance().getTotalTicks());
long timer = tfcData.getLong("nutritionDrainTimer");
IFoodStatsTFC food = (IFoodStatsTFC) player.getFoodStats();
if(Timekeeper.getInstance().getTotalTicks() > timer)
{
tfcData.setLong("nutritionDrainTimer", timer += 1000);
updateNutrition(tfcData, food, player);
updateThirst(tfcData, food, player);
updateHunger(tfcData, food, player);
TFC.network.sendTo(new CFoodPacket(food), player);
}
player.getEntityData().setTag("TFC2Data", tfcData);
if(food.getWaterLevel() < 5)
setThirsty(player, true);
else
setThirsty(player, false);
}
else
{
}
}
}
public void updateNutrition(NBTTagCompound tfcData, IFoodStatsTFC food, EntityPlayer player)
{
//Nutrition drains at a rate of 0.03 per hour. this should give roughly 27 days until zero
food.getNutritionMap().put(EnumFoodGroup.Fruit, food.getNutritionMap().get(EnumFoodGroup.Fruit)-0.03f);
food.getNutritionMap().put(EnumFoodGroup.Vegetable, food.getNutritionMap().get(EnumFoodGroup.Vegetable)-0.03f);
food.getNutritionMap().put(EnumFoodGroup.Grain, food.getNutritionMap().get(EnumFoodGroup.Grain)-0.03f);
food.getNutritionMap().put(EnumFoodGroup.Protein, food.getNutritionMap().get(EnumFoodGroup.Protein)-0.03f);
food.getNutritionMap().put(EnumFoodGroup.Dairy, food.getNutritionMap().get(EnumFoodGroup.Dairy)-0.03f);
}
public void updateThirst(NBTTagCompound tfcData, IFoodStatsTFC food, EntityPlayer player)
{
double temp = WeatherManager.getInstance().getTemperature(player.getPosition());
float thirst = 0.28f;
if(temp > 20)
{
temp -= 20;
thirst += thirst * (temp / 0.35);
}
food.setWaterLevel(Math.max(food.getWaterLevel()-thirst, 0));
}
public void updateHunger(NBTTagCompound tfcData, IFoodStatsTFC food, EntityPlayer player)
{
//Players suffer less natural hunger exhaustion as they increase in level
player.getFoodStats().addExhaustion(1.0f - Math.min(player.experienceLevel / 100f, 0.95f));
}
public NBTTagCompound getEntityData(NBTTagCompound playerData)
{
if(playerData == null)
return new NBTTagCompound();
return playerData.getCompoundTag("TFC2Data");
}
public static float getMaxHealth(EntityPlayer player)
{
IFoodStatsTFC food = (IFoodStatsTFC) player.getFoodStats();
float total = food.getNutritionMap().get(EnumFoodGroup.Fruit) + food.getNutritionMap().get(EnumFoodGroup.Vegetable) +
food.getNutritionMap().get(EnumFoodGroup.Grain) + food.getNutritionMap().get(EnumFoodGroup.Protein) +
food.getNutritionMap().get(EnumFoodGroup.Dairy);
total = total / 100;
return Math.min(20+(player.experienceLevel * TFCOptions.healthGainRate), TFCOptions.healthGainCap) * total;
}
public void setThirsty(EntityPlayer player, boolean b)
{
//Removed on port
IAttributeInstance iattributeinstance = player.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
if (iattributeinstance.hasModifier(THIRST))
{
iattributeinstance.removeModifier(THIRST);
player.removePotionEffect(PotionTFC.THIRST_POTION);
}
if (b)
{
iattributeinstance.applyModifier(THIRST);
player.setSprinting(false);
if(!player.isPotionActive(PotionTFC.THIRST_POTION))
player.addPotionEffect(new PotionEffect(PotionTFC.THIRST_POTION, 40, 0, false, false));
}
}
@SubscribeEvent
@SideOnly(Side.CLIENT)
public void handleFOV(FOVUpdateEvent event)
{
EntityPlayer player = event.getEntity();
// Calculate FOV based on the variable draw speed of the bow depending on player armor.
//Removed on port
/*if (player.isUsingItem() && player.getItemInUse().getItem() instanceof ItemCustomBow)
{
float fov = 1.0F;
int duration = player.getItemInUseDuration();
float speed = ItemCustomBow.getUseSpeed(player);
float force = duration / speed;
if (force > 1.0F)
{
force = 1.0F;
}
else
{
force *= force;
}
fov *= 1.0F - force * 0.15F;
event.newfov = fov;
}*/
}
@SubscribeEvent
public void onEntityDeath(LivingDeathEvent event)
{
EntityLivingBase entity = event.getEntityLiving();
if(event.getEntity().worldObj.isRemote)
return;
if (entity instanceof EntityPlayer)
{
//Removed on port
/*EntityPlayer player = (EntityPlayer) entity;
SkillStats skills = TFC_Core.getSkillStats(player);
PlayerInfo pi = PlayerManagerTFC.getInstance().getPlayerInfoFromPlayer(player);
pi.tempSkills = skills;
// Save the item in the back slot if keepInventory is set to true.
if (entity.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory") && player.inventory instanceof InventoryPlayerTFC)
{
pi.tempEquipment = ((InventoryPlayerTFC) player.inventory).extraEquipInventory.clone();
}*/
}
if(entity.getEntityData().hasKey("TFC2"))
{
NBTTagCompound nbt = entity.getEntityData().getCompoundTag("TFC2");
if(nbt.getBoolean("isWild"))
{
IslandMap map = Core.getMapForWorld(event.getEntity().getEntityWorld(), event.getEntity().getPosition());
SpawnEntry entry = map.getIslandData().animalEntries.get(nbt.getString("SpawnGroup"));
entry.removeAnimal();
}
}
}
@SubscribeEvent
public void onLivingDrop(LivingDropsEvent event)
{
boolean processed = false;
if (!event.getEntity().worldObj.isRemote && event.isRecentlyHit() && !(event.getEntity() instanceof EntityPlayer) && !(event.getEntity() instanceof EntityZombie))
{
if(event.getSource().getSourceOfDamage() instanceof EntityPlayer || event.getSource().isProjectile())
{
boolean foundFood = false;
processed = true;
ArrayList<EntityItem> drop = new ArrayList<EntityItem>();
EntityPlayer p = null;
if(event.getSource().getSourceOfDamage() instanceof EntityPlayer)
p = (EntityPlayer)event.getSource().getSourceOfDamage();
//Removed on port
/*else if(event.source.getSourceOfDamage() instanceof EntityProjectileTFC)
{
EntityProjectileTFC proj = (EntityProjectileTFC)event.source.getSourceOfDamage();
if(proj.shootingEntity instanceof EntityPlayer)
p = (EntityPlayer)proj.shootingEntity;
}*/
//Removed on port
/*for(EntityItem ei : event.drops)
{
ItemStack is = ei.getEntityItem();
if (is.getItem() instanceof IFood)
{
if(p == null)
continue;
foundFood = true;
int sweetMod = ((ItemFoodTFC) is.getItem()).getTasteSweetMod(is);
int sourMod = ((ItemFoodTFC) is.getItem()).getTasteSourMod(is);
int saltyMod = ((ItemFoodTFC) is.getItem()).getTasteSaltyMod(is);
int bitterMod = ((ItemFoodTFC) is.getItem()).getTasteBitterMod(is);
int umamiMod = ((ItemFoodTFC) is.getItem()).getTasteSavoryMod(is);
float oldWeight = Food.getWeight(is);
Food.setWeight(is, 0);
float newWeight = oldWeight * (TFC_Core.getSkillStats(p).getSkillMultiplier(Global.SKILL_BUTCHERING)+0.01f);
while (newWeight >= Global.FOOD_MIN_DROP_WEIGHT)
{
float fw = Helper.roundNumber(Math.min(Global.FOOD_MAX_WEIGHT, newWeight), 10);
if (fw < Global.FOOD_MAX_WEIGHT)
newWeight = 0;
newWeight -= fw;
ItemStack result = ItemFoodTFC.createTag(new ItemStack(is.getItem(), 1), fw);
if(sweetMod != 0) result.getTagCompound().setInteger("tasteSweetMod", sweetMod);
if(sourMod != 0) result.getTagCompound().setInteger("tasteSourMod", sourMod);
if(saltyMod != 0) result.getTagCompound().setInteger("tasteSaltyMod", saltyMod);
if(bitterMod != 0) result.getTagCompound().setInteger("tasteBitterMod", bitterMod);
if(umamiMod != 0) result.getTagCompound().setInteger("tasteUmamiMod", umamiMod);
drop.add(new EntityItem(event.getEntity().worldObj, event.getEntity().posX, event.getEntity().posY, event.getEntity().posZ, result));
}
}
else
{
drop.add(ei);
}
}
event.drops.clear();*/
event.getDrops().addAll(drop);
if(foundFood && p != null)
{
//Removed on port
//TFC_Core.getSkillStats(p).increaseSkill(Global.SKILL_BUTCHERING, 1);
}
}
}
//Removed on port
/*if (!processed && !(event.getEntity() instanceof EntityPlayer) && !(event.getEntity() instanceof EntityZombie))
{
ArrayList<EntityItem> drop = new ArrayList<EntityItem>();
for(EntityItem ei : event.drops)
{
if (!(ei.getEntityItem().getItem() instanceof IFood))
{
drop.add(ei);
}
}
event.drops.clear();
event.drops.addAll(drop);
}*/
}
}