BloodMagic/src/main/java/WayofTime/bloodmagic/util/Utils.java

718 lines
23 KiB
Java

package WayofTime.bloodmagic.util;
import java.util.ArrayList;
import net.minecraft.block.Block;
import net.minecraft.block.BlockPortal;
import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.Potion;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.ISpecialArmor;
import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidBlock;
import net.minecraftforge.fluids.IFluidHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import WayofTime.bloodmagic.api.BlockStack;
import WayofTime.bloodmagic.api.altar.EnumAltarComponent;
import WayofTime.bloodmagic.network.BloodMagicPacketHandler;
import WayofTime.bloodmagic.network.PlayerVelocityPacketProcessor;
import WayofTime.bloodmagic.registry.ModBlocks;
import WayofTime.bloodmagic.tile.TileInventory;
import com.google.common.collect.Iterables;
public class Utils
{
public static NBTTagCompound getPersistentDataTag(EntityPlayer player)
{
NBTTagCompound forgeData = player.getEntityData().getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG);
NBTTagCompound beaconData = forgeData.getCompoundTag("BloodMagic");
//Creates/sets the tags if they don't exist
if (!forgeData.hasKey("BloodMagic"))
forgeData.setTag("BloodMagic", beaconData);
if (!player.getEntityData().hasKey(EntityPlayer.PERSISTED_NBT_TAG))
player.getEntityData().setTag(EntityPlayer.PERSISTED_NBT_TAG, forgeData);
return beaconData;
}
public static void setPlayerSpeedFromServer(EntityPlayer player, double motionX, double motionY, double motionZ)
{
if (!player.worldObj.isRemote && player instanceof EntityPlayerMP)
{
BloodMagicPacketHandler.sendTo(new PlayerVelocityPacketProcessor(motionX, motionY, motionZ), (EntityPlayerMP) player);
}
}
public static boolean isInteger(String integer)
{
try
{
Integer.parseInt(integer);
} catch (NumberFormatException e)
{
return false;
} catch (NullPointerException e)
{
return false;
}
// only got here if we didn't return false
return true;
}
/**
* @param tile
* - The {@link TileInventory} to input the item to
* @param player
* - The player to take the item from.
* @return {@code true} if the ItemStack is inserted, {@code false}
* otherwise
* @see #insertItemToTile(TileInventory, EntityPlayer, int)
*/
public static boolean insertItemToTile(TileInventory tile, EntityPlayer player)
{
return insertItemToTile(tile, player, 0);
}
/**
* Used for inserting an ItemStack with a stacksize of 1 to a tile's
* inventory at slot 0
* <p/>
* EG: Block Altar
*
* @param tile
* - The {@link TileInventory} to input the item to
* @param player
* - The player to take the item from.
* @param slot
* - The slot to attempt to insert to
* @return {@code true} if the ItemStack is inserted, {@code false}
* otherwise
*/
public static boolean insertItemToTile(TileInventory tile, EntityPlayer player, int slot)
{
if (tile.getStackInSlot(slot) == null && player.getHeldItemMainhand() != null)
{
ItemStack input = player.getHeldItemMainhand().copy();
input.stackSize = 1;
player.getHeldItemMainhand().stackSize--;
tile.setInventorySlotContents(slot, input);
return true;
} else if (tile.getStackInSlot(slot) != null && player.getHeldItemMainhand() == null)
{
if (!tile.getWorld().isRemote)
{
EntityItem invItem = new EntityItem(tile.getWorld(), player.posX, player.posY + 0.25, player.posZ, tile.getStackInSlot(slot));
tile.getWorld().spawnEntityInWorld(invItem);
}
tile.clear();
return false;
}
return false;
}
/**
* Gets a default block for each type of {@link EnumAltarComponent}
*
* @param component
* - The Component to provide a block for.
* @return The default Block for the EnumAltarComponent
*/
public static Block getBlockForComponent(EnumAltarComponent component)
{
switch (component)
{
case GLOWSTONE:
return Blocks.glowstone;
case BLOODSTONE:
return ModBlocks.bloodStoneBrick;
case BEACON:
return Blocks.beacon;
case BLOODRUNE:
return ModBlocks.bloodRune;
case CRYSTAL:
return ModBlocks.crystal;
case NOTAIR:
return Blocks.stonebrick;
default:
return Blocks.air;
}
}
public static float getModifiedDamage(EntityLivingBase attackedEntity, DamageSource source, float amount)
{
if (!attackedEntity.isEntityInvulnerable(source))
{
if (amount <= 0)
return 0;
amount = applyArmor(attackedEntity, Iterables.toArray(attackedEntity.getEquipmentAndArmor(), ItemStack.class), source, amount);
if (amount <= 0)
return 0;
amount = applyPotionDamageCalculations(attackedEntity, source, amount);
return amount;
}
return 0;
}
public static float applyArmor(EntityLivingBase entity, ItemStack[] inventory, DamageSource source, double damage)
{
damage *= 25;
ArrayList<ArmorProperties> dmgVals = new ArrayList<ArmorProperties>();
for (int x = 0; x < inventory.length; x++)
{
ItemStack stack = inventory[x];
if (stack == null)
{
continue;
}
ArmorProperties prop = null;
if (stack.getItem() instanceof ISpecialArmor)
{
ISpecialArmor armor = (ISpecialArmor) stack.getItem();
prop = armor.getProperties(entity, stack, source, damage / 25D, x).copy();
} else if (stack.getItem() instanceof ItemArmor && !source.isUnblockable())
{
ItemArmor armor = (ItemArmor) stack.getItem();
prop = new ArmorProperties(0, armor.damageReduceAmount / 25D, Integer.MAX_VALUE);
}
if (prop != null)
{
prop.Slot = x;
dmgVals.add(prop);
}
}
if (dmgVals.size() > 0)
{
ArmorProperties[] props = dmgVals.toArray(new ArmorProperties[dmgVals.size()]);
int level = props[0].Priority;
double ratio = 0;
for (ArmorProperties prop : props)
{
if (level != prop.Priority)
{
damage -= (damage * ratio);
ratio = 0;
level = prop.Priority;
}
ratio += prop.AbsorbRatio;
}
damage -= (damage * ratio);
}
return (float) (damage / 25.0F);
}
public static float applyPotionDamageCalculations(EntityLivingBase attackedEntity, DamageSource source, float damage)
{
Potion resistance = MobEffects.resistance;
if (source.isDamageAbsolute())
{
return damage;
} else
{
if (attackedEntity.isPotionActive(resistance) && source != DamageSource.outOfWorld)
{
int i = (attackedEntity.getActivePotionEffect(resistance).getAmplifier() + 1) * 5;
int j = 25 - i;
float f = damage * (float) j;
damage = f / 25.0F;
}
if (damage <= 0.0F)
{
return 0.0F;
} else
{
int k = EnchantmentHelper.getEnchantmentModifierDamage(attackedEntity.getArmorInventoryList(), source);
if (k > 20)
{
k = 20;
}
if (k > 0 && k <= 20)
{
int l = 25 - k;
float f1 = damage * (float) l;
damage = f1 / 25.0F;
}
return damage;
}
}
}
/**
* Used to determine if stack1 can be placed into stack2. If stack2 is null
* and stack1 isn't null, returns true. Ignores stack size
*
* @param stack1
* Stack that is placed into a slot
* @param stack2
* Slot content that stack1 is placed into
* @return True if they can be combined
*/
public static boolean canCombine(ItemStack stack1, ItemStack stack2)
{
if (stack1 == null)
{
return false;
}
if (stack2 == null)
{
return true;
}
if (stack1.isItemStackDamageable() ^ stack2.isItemStackDamageable())
{
return false;
}
return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() && ItemStack.areItemStackTagsEqual(stack1, stack2);
}
/**
* @param stack1
* Stack that is placed into a slot
* @param stack2
* Slot content that stack1 is placed into
* @return Stacks after stacking
*/
public static ItemStack[] combineStacks(ItemStack stack1, ItemStack stack2, int transferMax)
{
ItemStack[] returned = new ItemStack[2];
if (canCombine(stack1, stack2))
{
int transferedAmount = Math.min(transferMax, stack2 == null ? stack1.stackSize : Math.min(stack2.getMaxStackSize() - stack2.stackSize, stack1.stackSize));
if (transferedAmount > 0)
{
ItemStack copyStack = stack1.splitStack(transferedAmount);
if (stack2 == null)
{
stack2 = copyStack;
} else
{
stack2.stackSize += transferedAmount;
}
}
}
returned[0] = stack1;
returned[1] = stack2;
return returned;
}
/**
* @param stack1
* Stack that is placed into a slot
* @param stack2
* Slot content that stack1 is placed into
* @return Stacks after stacking
*/
public static ItemStack[] combineStacks(ItemStack stack1, ItemStack stack2)
{
ItemStack[] returned = new ItemStack[2];
if (canCombine(stack1, stack2))
{
int transferedAmount = stack2 == null ? stack1.stackSize : Math.min(stack2.getMaxStackSize() - stack2.stackSize, stack1.stackSize);
if (transferedAmount > 0)
{
ItemStack copyStack = stack1.splitStack(transferedAmount);
if (stack2 == null)
{
stack2 = copyStack;
} else
{
stack2.stackSize += transferedAmount;
}
}
}
returned[0] = stack1;
returned[1] = stack2;
return returned;
}
public static ItemStack insertStackIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir)
{
if (stack == null)
{
return null;
}
boolean[] canBeInserted = new boolean[inventory.getSizeInventory()];
if (inventory instanceof ISidedInventory)
{
int[] array = ((ISidedInventory) inventory).getSlotsForFace(dir);
for (int in : array)
{
canBeInserted[in] = inventory.isItemValidForSlot(in, stack) && ((ISidedInventory) inventory).canInsertItem(in, stack, dir);
}
} else
{
for (int i = 0; i < canBeInserted.length; i++)
{
canBeInserted[i] = inventory.isItemValidForSlot(i, stack);
}
}
for (int i = 0; i < inventory.getSizeInventory(); i++)
{
if (!canBeInserted[i])
{
continue;
}
ItemStack[] combinedStacks = combineStacks(stack, inventory.getStackInSlot(i));
stack = combinedStacks[0];
inventory.setInventorySlotContents(i, combinedStacks[1]);
if (stack.stackSize <= 0)
{
return stack;
}
}
return stack;
}
public static boolean canInsertStackFullyIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir)
{
return canInsertStackFullyIntoInventory(stack, inventory, dir, false, 0);
}
public static boolean canInsertStackFullyIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir, boolean fillToLimit, int limit)
{
if (stack == null)
{
return true;
}
int itemsLeft = stack.stackSize;
boolean[] canBeInserted = new boolean[inventory.getSizeInventory()];
if (inventory instanceof ISidedInventory)
{
int[] array = ((ISidedInventory) inventory).getSlotsForFace(dir);
for (int in : array)
{
canBeInserted[in] = inventory.isItemValidForSlot(in, stack) && ((ISidedInventory) inventory).canInsertItem(in, stack, dir);
}
} else
{
for (int i = 0; i < canBeInserted.length; i++)
{
canBeInserted[i] = inventory.isItemValidForSlot(i, stack);
}
}
int numberMatching = 0;
if (fillToLimit)
{
for (int i = 0; i < inventory.getSizeInventory(); i++)
{
if (!canBeInserted[i])
{
continue;
}
ItemStack invStack = inventory.getStackInSlot(i);
if (invStack != null && canCombine(stack, invStack))
{
numberMatching += invStack.stackSize;
}
}
}
if (fillToLimit && limit < stack.stackSize + numberMatching)
{
return false;
}
for (int i = 0; i < inventory.getSizeInventory(); i++)
{
if (!canBeInserted[i])
{
continue;
}
ItemStack invStack = inventory.getStackInSlot(i);
boolean canCombine = canCombine(stack, invStack);
if (canCombine)
{
if (invStack == null)
{
itemsLeft = 0;
} else
{
itemsLeft -= (invStack.getMaxStackSize() - invStack.stackSize);
}
}
if (itemsLeft <= 0)
{
return true;
}
}
return false;
}
public static ItemStack insertStackIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir, int limit)
{
if (stack == null)
{
return null;
}
boolean[] canBeInserted = new boolean[inventory.getSizeInventory()];
if (inventory instanceof ISidedInventory)
{
int[] array = ((ISidedInventory) inventory).getSlotsForFace(dir);
for (int in : array)
{
canBeInserted[in] = ((ISidedInventory) inventory).canInsertItem(in, stack, dir);
}
} else
{
for (int i = 0; i < canBeInserted.length; i++)
{
canBeInserted[i] = true;
}
}
int numberMatching = 0;
for (int i = 0; i < inventory.getSizeInventory(); i++)
{
if (!canBeInserted[i])
{
continue;
}
ItemStack invStack = inventory.getStackInSlot(i);
if (invStack != null && canCombine(stack, invStack))
{
numberMatching += invStack.stackSize;
}
}
if (numberMatching >= limit)
{
return stack;
}
int newLimit = limit - numberMatching;
for (int i = 0; i < inventory.getSizeInventory(); i++)
{
if (!canBeInserted[i])
{
continue;
}
int prevStackSize = stack.stackSize;
ItemStack[] combinedStacks = combineStacks(stack, inventory.getStackInSlot(i), newLimit);
stack = combinedStacks[0];
inventory.setInventorySlotContents(i, combinedStacks[1]);
newLimit -= (prevStackSize - stack.stackSize);
if (newLimit <= 0 || stack.stackSize <= 0)
{
return stack;
}
}
return stack;
}
public static boolean isBlockLiquid(IBlockState state)
{
return (state instanceof IFluidBlock || state.getMaterial().isLiquid());
}
public static boolean swapLocations(World initialWorld, BlockPos initialPos, World finalWorld, BlockPos finalPos)
{
TileEntity initialTile = initialWorld.getTileEntity(initialPos);
TileEntity finalTile = finalWorld.getTileEntity(finalPos);
NBTTagCompound initialTag = new NBTTagCompound();
NBTTagCompound finalTag = new NBTTagCompound();
if (initialTile != null)
initialTile.writeToNBT(initialTag);
if (finalTile != null)
finalTile.writeToNBT(finalTag);
BlockStack initialStack = BlockStack.getStackFromPos(initialWorld, initialPos);
BlockStack finalStack = BlockStack.getStackFromPos(finalWorld, finalPos);
if ((initialStack.getBlock().equals(Blocks.air) && finalStack.getBlock().equals(Blocks.air)) || initialStack.getBlock() instanceof BlockPortal || finalStack.getBlock() instanceof BlockPortal)
return false;
initialWorld.playSound(initialPos.getX(), initialPos.getY(), initialPos.getZ(), SoundEvents.entity_endermen_teleport, SoundCategory.AMBIENT, 1.0F, 1.0F, false);
finalWorld.playSound(finalPos.getX(), finalPos.getY(), finalPos.getZ(), SoundEvents.entity_endermen_teleport, SoundCategory.AMBIENT, 1.0F, 1.0F, false);
//Finally, we get to do something! (CLEARING TILES)
if (finalStack.getBlock() != null)
finalWorld.removeTileEntity(finalPos);
if (initialStack.getBlock() != null)
initialWorld.removeTileEntity(initialPos);
//TILES CLEARED
IBlockState initialBlockState = initialWorld.getBlockState(initialPos);
IBlockState finalBlockState = finalWorld.getBlockState(finalPos);
finalWorld.setBlockState(finalPos, initialBlockState, 3);
if (initialTile != null)
{
TileEntity newTileInitial = TileEntity.createTileEntity(FMLCommonHandler.instance().getMinecraftServerInstance(), initialTag);
finalWorld.setTileEntity(finalPos, newTileInitial);
newTileInitial.setPos(finalPos);
newTileInitial.setWorldObj(finalWorld);
}
initialWorld.setBlockState(initialPos, finalBlockState, 3);
if (finalTile != null)
{
TileEntity newTileFinal = TileEntity.createTileEntity(FMLCommonHandler.instance().getMinecraftServerInstance(), finalTag);
initialWorld.setTileEntity(initialPos, newTileFinal);
newTileFinal.setPos(initialPos);
newTileFinal.setWorldObj(initialWorld);
}
initialWorld.notifyNeighborsOfStateChange(initialPos, finalStack.getBlock());
finalWorld.notifyNeighborsOfStateChange(finalPos, initialStack.getBlock());
return true;
}
//Shamelessly ripped off of CoFH Lib
public static boolean fillContainerFromHandler(World world, IFluidHandler handler, EntityPlayer player, FluidStack tankFluid)
{
ItemStack container = player.getHeldItemMainhand();
if (FluidContainerRegistry.isEmptyContainer(container))
{
ItemStack returnStack = FluidContainerRegistry.fillFluidContainer(tankFluid, container);
FluidStack fluid = FluidContainerRegistry.getFluidForFilledItem(returnStack);
if (fluid == null || returnStack == null)
{
return false;
}
if (!player.capabilities.isCreativeMode)
{
if (container.stackSize == 1)
{
container = container.copy();
player.inventory.setInventorySlotContents(player.inventory.currentItem, returnStack);
} else if (!player.inventory.addItemStackToInventory(returnStack))
{
return false;
}
handler.drain(EnumFacing.UP, fluid.amount, true);
container.stackSize--;
if (container.stackSize <= 0)
{
container = null;
}
} else
{
handler.drain(EnumFacing.UP, fluid.amount, true);
}
return true;
}
return false;
}
//Shamelessly ripped off of CoFH Lib
public static boolean fillHandlerWithContainer(World world, IFluidHandler handler, EntityPlayer player)
{
ItemStack container = player.getHeldItemMainhand();
FluidStack fluid = FluidContainerRegistry.getFluidForFilledItem(container);
if (fluid != null)
{
if (handler.fill(EnumFacing.UP, fluid, false) == fluid.amount || player.capabilities.isCreativeMode)
{
if (world.isRemote)
{
return true;
}
handler.fill(EnumFacing.UP, fluid, true);
if (!player.capabilities.isCreativeMode)
{
player.inventory.setInventorySlotContents(player.inventory.currentItem, consumeItem(container));
}
return true;
}
}
return false;
}
//Shamelessly ripped off of CoFH Lib
public static ItemStack consumeItem(ItemStack stack)
{
Item item = stack.getItem();
boolean largerStack = stack.stackSize > 1;
if (largerStack)
{
stack.stackSize -= 1;
}
if (item.hasContainerItem(stack))
{
ItemStack ret = item.getContainerItem(stack);
if (ret == null)
{
return null;
}
if (ret.isItemStackDamageable() && ret.getItemDamage() > ret.getMaxDamage())
{
ret = null;
}
return ret;
}
return largerStack ? stack : null;
}
}