/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Jul 19, 2014, 10:46:14 PM (GMT)]
*/
package vazkii.botania.common.item;
import java.util.List;
import javax.annotation.Nonnull;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.resources.I18n;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.NonNullList;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import vazkii.botania.api.internal.IManaBurst;
import vazkii.botania.api.mana.BurstProperties;
import vazkii.botania.api.mana.ILaputaImmobile;
import vazkii.botania.api.mana.ILensEffect;
import vazkii.botania.api.mana.ITinyPlanetExcempt;
import vazkii.botania.api.sound.BotaniaSoundEvents;
import vazkii.botania.client.core.handler.ModelHandler;
import vazkii.botania.common.achievement.ModAchievements;
import vazkii.botania.common.core.helper.ItemNBTHelper;
import vazkii.botania.common.core.helper.MathHelper;
import vazkii.botania.common.entity.EntityManaBurst;
import vazkii.botania.common.lib.LibItemNames;
public class ItemLaputaShard extends ItemMod implements ILensEffect, ITinyPlanetExcempt {
private static final String TAG_BLOCK = "_block";
private static final String TAG_BLOCK_NAME = "_blockname";
private static final String TAG_META = "_meta";
private static final String TAG_TILE = "_tile";
private static final String TAG_X = "_x";
private static final String TAG_Y = "_y";
private static final String TAG_Y_START = "_yStart";
private static final String TAG_Z = "_z";
private static final String TAG_POINTY = "_pointy";
private static final String TAG_HEIGHTSCALE = "_heightscale";
private static final String TAG_ITERATION_I = "iterationI";
private static final String TAG_ITERATION_J = "iterationJ";
private static final String TAG_ITERATION_K = "iterationK";
private static final int BASE_RANGE = 14;
private static final int BASE_OFFSET = 42;
public ItemLaputaShard() {
super(LibItemNames.LAPUTA_SHARD);
setHasSubtypes(true);
}
@Override
@SideOnly(Side.CLIENT)
public void getSubItems(@Nonnull Item item, CreativeTabs tab, NonNullList<ItemStack> list) {
super.getSubItems(item, tab, list);
for(int i = 0; i < 4; i++)
list.add(new ItemStack(item, 1, (i + 1) * 5 - 1));
}
@SideOnly(Side.CLIENT)
@Override
public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean adv) {
list.add(I18n.format("botaniamisc.shardLevel", I18n.format("botania.roman" + (stack.getItemDamage() + 1))));
}
@Nonnull
@Override
public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, float par8, float par9, float par10) {
if(!world.isRemote && pos.getY() < 160 && !world.provider.doesWaterVaporize()) {
world.playSound(null, pos, BotaniaSoundEvents.laputaStart, SoundCategory.BLOCKS, 1.0F + world.rand.nextFloat(), world.rand.nextFloat() * 0.7F + 1.3F);
ItemStack stack = player.getHeldItem(hand);
spawnBurstFirst(world, pos, stack);
if(stack.getItemDamage() == 19)
player.addStat(ModAchievements.l20ShardUse, 1);
stack.shrink(1);
}
return EnumActionResult.SUCCESS;
}
public void spawnBurstFirst(World world, BlockPos pos, ItemStack lens) {
int range = BASE_RANGE + lens.getItemDamage();
boolean pointy = world.rand.nextDouble() < 0.25;
double heightscale = (world.rand.nextDouble() + 0.5) * ((double)BASE_RANGE / (double)range);
spawnBurst(world, pos, lens, pointy, heightscale);
}
public void spawnBurst(World world, BlockPos pos, ItemStack lens) {
boolean pointy = ItemNBTHelper.getBoolean(lens, TAG_POINTY, false);
double heightscale = ItemNBTHelper.getDouble(lens, TAG_HEIGHTSCALE, 1);
spawnBurst(world, pos, lens, pointy, heightscale);
}
public void spawnBurst(World world, BlockPos pos, ItemStack lens, boolean pointy, double heightscale) {
int range = BASE_RANGE + lens.getItemDamage();
int i = ItemNBTHelper.getInt(lens, TAG_ITERATION_I, 0);
int j = ItemNBTHelper.getInt(lens, TAG_ITERATION_J, BASE_OFFSET - BASE_RANGE / 2);
int k = ItemNBTHelper.getInt(lens, TAG_ITERATION_K, 0);
if(j <= -BASE_RANGE * 2)
j = BASE_OFFSET - BASE_RANGE / 2;
if(k >= range * 2 + 1)
k = 0;
if(!world.isRemote) {
for(; i < range * 2 + 1; i++) {
for(; j > -BASE_RANGE * 2; j--) {
for(; k < range * 2 + 1; k++) {
BlockPos pos_ = pos.add(-range + i, -BASE_RANGE + j, -range + k);
if(inRange(pos_, pos, range, heightscale, pointy)) {
IBlockState state = world.getBlockState(pos_);
Block block = state.getBlock();
if(!block.isAir(state, world, pos_) && !block.isReplaceable(world, pos_) && !(block instanceof BlockFalling) && (!(block instanceof ILaputaImmobile) || ((ILaputaImmobile) block).canMove(world, pos_)) && state.getBlockHardness(world, pos_) != -1) {
TileEntity tile = world.getTileEntity(pos_);
if(tile != null) {
TileEntity newTile = block.createTileEntity(world, state);
world.setTileEntity(pos_, newTile);
}
world.setBlockToAir(pos_);
world.playEvent(2001, pos_, Block.getStateId(state));
ItemStack copyLens = new ItemStack(this, 1, lens.getItemDamage());
ItemNBTHelper.setString(copyLens, TAG_BLOCK_NAME, Block.REGISTRY.getNameForObject(block).toString());
ItemNBTHelper.setInt(copyLens, TAG_META, block.getMetaFromState(state));
NBTTagCompound cmp = new NBTTagCompound();
if(tile != null)
tile.writeToNBT(cmp);
ItemNBTHelper.setCompound(copyLens, TAG_TILE, cmp);
ItemNBTHelper.setInt(copyLens, TAG_X, pos.getX());
ItemNBTHelper.setInt(copyLens, TAG_Y, pos.getY());
ItemNBTHelper.setInt(copyLens, TAG_Y_START, pos_.getY());
ItemNBTHelper.setInt(copyLens, TAG_Z, pos.getZ());
ItemNBTHelper.setBoolean(copyLens, TAG_POINTY, pointy);
ItemNBTHelper.setDouble(copyLens, TAG_HEIGHTSCALE, heightscale);
ItemNBTHelper.setInt(copyLens, TAG_ITERATION_I, i);
ItemNBTHelper.setInt(copyLens, TAG_ITERATION_J, j);
ItemNBTHelper.setInt(copyLens, TAG_ITERATION_K, k);
EntityManaBurst burst = getBurst(world, pos_, copyLens);
world.spawnEntity(burst);
return;
}
}
}
k = 0;
}
j = BASE_OFFSET - BASE_RANGE / 2;
}
}
}
private boolean inRange(BlockPos pos, BlockPos srcPos, int range, double heightscale, boolean pointy) {
if(pos.getY() >= srcPos.getY())
return MathHelper.pointDistanceSpace(pos.getX(), 0, pos.getZ(), srcPos.getX(), 0, srcPos.getZ()) < range;
else if(!pointy)
return MathHelper.pointDistanceSpace(pos.getX(), pos.getY() / heightscale, pos.getZ(), srcPos.getX(), srcPos.getY() / heightscale, srcPos.getZ()) < range;
else return MathHelper.pointDistanceSpace(pos.getX(), 0, pos.getZ(), srcPos.getX(), 0, srcPos.getZ()) < range - (srcPos.getY() - pos.getY()) / heightscale;
}
public EntityManaBurst getBurst(World world, BlockPos pos, ItemStack stack) {
EntityManaBurst burst = new EntityManaBurst(world);
burst.posX = pos.getX() + 0.5;
burst.posY = pos.getY() + 0.5;
burst.posZ = pos.getZ() + 0.5;
burst.setColor(0x00EAFF);
burst.setMana(1);
burst.setStartingMana(1);
burst.setMinManaLoss(0);
burst.setManaLossPerTick(0F);
burst.setGravity(0F);
burst.setMotion(0, 0.5, 0);
burst.setSourceLens(stack);
return burst;
}
@Override
public void apply(ItemStack stack, BurstProperties props) {}
@Override
public boolean collideBurst(IManaBurst burst, RayTraceResult pos, boolean isManaBlock, boolean dead, ItemStack stack) {
return false;
}
@Override
public void updateBurst(IManaBurst burst, ItemStack stack) {
double speed = 0.35;
int targetDistance = BASE_OFFSET;
EntityThrowable entity = (EntityThrowable) burst;
if(!entity.world.isRemote) {
entity.motionX = 0;
entity.motionY = speed;
entity.motionZ = 0;
final int spawnTicks = 2;
final int placeTicks = net.minecraft.util.math.MathHelper.floor(targetDistance / speed);
ItemStack lens = burst.getSourceLens();
if(burst.getTicksExisted() == spawnTicks) {
int x = ItemNBTHelper.getInt(lens, TAG_X, 0);
int y = ItemNBTHelper.getInt(lens, TAG_Y, -1);
int z = ItemNBTHelper.getInt(lens, TAG_Z, 0);
if(y != -1)
spawnBurst(entity.world, new BlockPos(x, y, z), lens);
} else if(burst.getTicksExisted() == placeTicks) {
int x = net.minecraft.util.math.MathHelper.floor(entity.posX);
int y = ItemNBTHelper.getInt(lens, TAG_Y_START, -1) + targetDistance;
int z = net.minecraft.util.math.MathHelper.floor(entity.posZ);
BlockPos pos = new BlockPos(x, y, z);
if(entity.world.isAirBlock(pos)) {
Block block = Blocks.AIR;
if (lens.hasTagCompound()) {
if (lens.getTagCompound().hasKey(TAG_BLOCK_NAME)) {
block = Block.getBlockFromName(ItemNBTHelper.getString(lens, TAG_BLOCK_NAME, ""));
} else if (lens.getTagCompound().hasKey(TAG_BLOCK)) {
// Attempt to read legacy tag (integer ID) if string block ID is absent
block = Block.getBlockById(ItemNBTHelper.getInt(lens, TAG_BLOCK, 0));
}
}
int meta = ItemNBTHelper.getInt(lens, TAG_META, 0);
TileEntity tile = null;
NBTTagCompound tilecmp = ItemNBTHelper.getCompound(lens, TAG_TILE, false);
if(tilecmp.hasKey("id"))
tile = TileEntity.create(entity.world, tilecmp);
entity.world.setBlockState(pos, block.getStateFromMeta(meta), 1 | 2);
entity.world.playEvent(2001, pos, Block.getStateId(block.getStateFromMeta(meta)));
if(tile != null) {
tile.setPos(pos);
entity.world.setTileEntity(pos, tile);
}
}
entity.setDead();
}
}
}
@Override
public boolean doParticles(IManaBurst burst, ItemStack stack) {
EntityThrowable entity = (EntityThrowable) burst;
ItemStack lens = burst.getSourceLens();
String id = ItemNBTHelper.getString(lens, TAG_BLOCK_NAME, "minecraft:air");
Block b = Block.getBlockFromName(id);
int meta = ItemNBTHelper.getInt(lens, TAG_META, 0);
entity.world.spawnParticle(EnumParticleTypes.BLOCK_CRACK, entity.posX, entity.posY, entity.posZ, entity.motionX, entity.motionY, entity.motionZ, Block.getStateId(b.getStateFromMeta(meta)));
return true;
}
@Override
public boolean shouldPull(ItemStack stack) {
return false;
}
@SideOnly(Side.CLIENT)
@Override
public void registerModels() {
ModelHandler.registerItemAllMeta(this, 20);
}
}