package slimeknights.tconstruct.gadgets.item;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.play.server.SPacketSetPassengers;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.EnumHelper;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import slimeknights.mantle.client.gui.GuiElement;
import slimeknights.mantle.item.ItemArmorTooltip;
import slimeknights.tconstruct.common.TinkerNetwork;
import slimeknights.tconstruct.gadgets.TinkerGadgets;
import slimeknights.tconstruct.library.Util;
import slimeknights.tconstruct.library.capability.piggyback.CapabilityTinkerPiggyback;
import slimeknights.tconstruct.library.capability.piggyback.ITinkerPiggyback;
import slimeknights.tconstruct.library.capability.piggyback.TinkerPiggybackSerializer;
import slimeknights.tconstruct.library.client.Icons;
import slimeknights.tconstruct.library.potion.TinkerPotion;
public class ItemPiggybackPack extends ItemArmorTooltip {
// todo: turn this into a config
private static final int MAX_ENTITY_STACK = 3; // how many entities can be carried at once
public static ArmorMaterial PIGGYBACK_MATERIAL = EnumHelper.addArmorMaterial("PIGGYBACK", Util.resource("piggyback"), 0, new int[]{0, 0, 0, 0}, 0, SoundEvents.BLOCK_SLIME_PLACE, 0);
public ItemPiggybackPack() {
super(PIGGYBACK_MATERIAL, 0, EntityEquipmentSlot.CHEST);
this.setMaxStackSize(16);
MinecraftForge.EVENT_BUS.register(this);
}
@Nonnull
@Override
public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) {
return new ActionResult<ItemStack>(EnumActionResult.PASS, itemStackIn);
}
@Override
public boolean itemInteractionForEntity(ItemStack stack, EntityPlayer playerIn, EntityLivingBase target, EnumHand hand) {
// is the chest slot empty?
ItemStack chestArmor = playerIn.getItemStackFromSlot(this.armorType);
// need enough space to exchange the chest armor
if(chestArmor != null && chestArmor.getItem() != this && playerIn.inventory.getFirstEmptyStack() == -1) {
// not enough inventory space
return false;
}
if(pickupEntity(playerIn, target)) {
// unequip old armor
if(chestArmor != null && chestArmor.getItem() != this) {
ItemHandlerHelper.giveItemToPlayer(playerIn, chestArmor);
chestArmor = null;
}
// we could pick it up just fine, check if we need to "equip" more of the item
if(chestArmor == null) {
playerIn.setItemStackToSlot(this.armorType, stack.splitStack(1));
}
else if(chestArmor.stackSize < getEntitiesCarriedCount(playerIn)) {
stack.splitStack(1);
chestArmor.stackSize++;
}
// successfully picked up an entity
return true;
}
return false;
}
public boolean pickupEntity(EntityPlayer player, Entity target) {
if(player.getEntityWorld().isRemote) {
return false;
}
// silly players, clicking on entities they're already carrying or riding
if(target.getRidingEntity() == player || player.getRidingEntity() == target) {
return false;
}
int count = 0;
Entity toRide = player;
while(toRide.isBeingRidden() && count < MAX_ENTITY_STACK) {
toRide = toRide.getPassengers().get(0);
count++;
// don't allow more than 1 player, that can easily cause endless loops with riding detection for some reason.
if(toRide instanceof EntityPlayer && target instanceof EntityPlayer) {
return false;
}
}
// can only ride one entity each
if(!toRide.isBeingRidden() && count < MAX_ENTITY_STACK) {
// todo: possibly throw off all passengers of the target
if(target.startRiding(toRide, true)) {
if(player instanceof EntityPlayerMP) {
TinkerNetwork.sendPacket(player, new SPacketSetPassengers(player));
}
return true;
}
}
return false;
}
public int getEntitiesCarriedCount(EntityLivingBase player) {
int count = 0;
Entity ridden = player;
while(ridden.isBeingRidden()) {
count++;
ridden = ridden.getPassengers().get(0);
}
return count;
}
public void matchCarriedEntitiesToCount(EntityLivingBase player, int maxCount) {
int count = 0;
// get top rider
Entity ridden = player;
while(ridden.isBeingRidden()) {
ridden = ridden.getPassengers().get(0);
count++;
if(count > maxCount) {
ridden.dismountRidingEntity();
}
}
}
@Override
public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) {
if(entityIn instanceof EntityLivingBase) {
EntityLivingBase entityLivingBase = (EntityLivingBase) entityIn;
if(entityLivingBase.getItemStackFromSlot(EntityEquipmentSlot.CHEST) == stack && entityIn.isBeingRidden()) {
int amplifier = getEntitiesCarriedCount(entityLivingBase) - 1;
entityLivingBase.addPotionEffect(new PotionEffect(CarryPotionEffect.INSTANCE, 1, amplifier, true, false));
}
}
}
@SubscribeEvent
public void attachCapability(AttachCapabilitiesEvent.Entity event) {
if(event.getEntity() instanceof EntityPlayer) {
event.addCapability(Util.getResource("piggyback"), new TinkerPiggybackSerializer((EntityPlayer) event.getEntity()));
}
}
public static class CarryPotionEffect extends TinkerPotion {
public static final CarryPotionEffect INSTANCE = new CarryPotionEffect();
public static final String UUID = "ff4de63a-2b24-11e6-b67b-9e71128cae77";
protected CarryPotionEffect() {
super(Util.getResource("carry"), false, true);
this.registerPotionAttributeModifier(SharedMonsterAttributes.MOVEMENT_SPEED, UUID, -0.05D, 2);
}
@Override
public boolean isReady(int duration, int amplifier) {
return true; // check every tick
}
@Override
public void performEffect(@Nonnull EntityLivingBase entityLivingBaseIn, int p_76394_2_) {
ItemStack chestArmor = entityLivingBaseIn.getItemStackFromSlot(EntityEquipmentSlot.CHEST);
if(chestArmor == null) {
TinkerGadgets.piggybackPack.matchCarriedEntitiesToCount(entityLivingBaseIn, 0);
}
else if(chestArmor.getItem() == TinkerGadgets.piggybackPack) {
TinkerGadgets.piggybackPack.matchCarriedEntitiesToCount(entityLivingBaseIn, chestArmor.stackSize);
if(!entityLivingBaseIn.getEntityWorld().isRemote) {
if(entityLivingBaseIn.hasCapability(CapabilityTinkerPiggyback.PIGGYBACK, null)) {
ITinkerPiggyback piggyback = entityLivingBaseIn.getCapability(CapabilityTinkerPiggyback.PIGGYBACK, null);
piggyback.updatePassengers();
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void renderInventoryEffect(int x, int y, PotionEffect effect, Minecraft mc) {
renderHUDEffect(x, y, effect, mc, 1f);
}
@Override
@SideOnly(Side.CLIENT)
public void renderHUDEffect(int x, int y, PotionEffect effect, Minecraft mc, float alpha) {
mc.getTextureManager().bindTexture(Icons.ICON);
GuiElement element;
switch(effect.getAmplifier()) {
case 0:
element = Icons.ICON_PIGGYBACK_1;
break;
case 1:
element = Icons.ICON_PIGGYBACK_2;
break;
case 2:
element = Icons.ICON_PIGGYBACK_3;
break;
default:
element = Icons.ICON_PIGGYBACK_3;
break;
}
element.draw(x + 6, y + 7);
}
}
}