/**
* 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 @ [Jan 20, 2014, 7:42:46 PM (GMT)]
*/
package vazkii.botania.common.item;
import java.awt.Color;
import java.util.List;
import javax.annotation.Nonnull;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCommandBlock;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.resources.I18n;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
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.client.model.ModelLoader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import vazkii.botania.api.internal.VanillaPacketDispatcher;
import vazkii.botania.api.sound.BotaniaSoundEvents;
import vazkii.botania.api.state.BotaniaStateProps;
import vazkii.botania.api.wand.ICoordBoundItem;
import vazkii.botania.api.wand.ITileBound;
import vazkii.botania.api.wand.IWandBindable;
import vazkii.botania.api.wand.IWandable;
import vazkii.botania.common.Botania;
import vazkii.botania.common.achievement.ModAchievements;
import vazkii.botania.common.block.BlockPistonRelay;
import vazkii.botania.common.block.ModBlocks;
import vazkii.botania.common.block.tile.TileEnchanter;
import vazkii.botania.common.core.handler.ConfigHandler;
import vazkii.botania.common.core.helper.ItemNBTHelper;
import vazkii.botania.common.core.helper.Vector3;
import vazkii.botania.common.lib.LibItemNames;
public class ItemTwigWand extends Item16Colors implements ICoordBoundItem {
private static final String TAG_COLOR1 = "color1";
private static final String TAG_COLOR2 = "color2";
private static final String TAG_BOUND_TILE_X = "boundTileX";
private static final String TAG_BOUND_TILE_Y = "boundTileY";
private static final String TAG_BOUND_TILE_Z = "boundTileZ";
private static final String TAG_BIND_MODE = "bindMode";
private static final BlockPos UNBOUND_POS = new BlockPos(0, -1, 0);
public ItemTwigWand() {
super(LibItemNames.TWIG_WAND);
setMaxStackSize(1);
addPropertyOverride(new ResourceLocation("botania", "bindmode"), (stack, worldIn, entityIn) -> getBindMode(stack) ? 1 : 0);
}
@Nonnull
@Override
public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, float par8, float par9, float par10) {
ItemStack stack = player.getHeldItem(hand);
Block block = world.getBlockState(pos).getBlock();
BlockPos boundPos = getBoundTile(stack);
TileEntity boundTile = world.getTileEntity(boundPos);
if(player.isSneaking()) {
// Try to complete a binding
if(boundPos.getY() != -1 && !pos.equals(boundPos)) {
if (boundTile instanceof IWandBindable) {
if(((IWandBindable) boundTile).bindTo(player, stack, pos, side)) {
Vector3 orig = new Vector3(boundPos.getX() + 0.5, boundPos.getY() + 0.5, boundPos.getZ() + 0.5);
Vector3 end = new Vector3(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
doParticleBeam(world, orig, end);
VanillaPacketDispatcher.dispatchTEToNearbyPlayers(world, boundPos);
setBoundTile(stack, UNBOUND_POS);
}
return EnumActionResult.SUCCESS;
} else {
setBoundTile(stack, UNBOUND_POS);
}
}
if(player.canPlayerEdit(pos, side, stack)
&& (!(block instanceof BlockCommandBlock) || player.canUseCommandBlock())
&& block.rotateBlock(world, pos, side)) {
player.swingArm(hand);
return EnumActionResult.SUCCESS;
}
}
if(block == Blocks.LAPIS_BLOCK && ConfigHandler.enchanterEnabled) {
EnumFacing.Axis axis = null;
if(TileEnchanter.canEnchanterExist(world, pos, EnumFacing.Axis.X))
axis = EnumFacing.Axis.X;
else if(TileEnchanter.canEnchanterExist(world, pos, EnumFacing.Axis.Z))
axis = EnumFacing.Axis.Z;
if(axis != null) {
if(!world.isRemote) {
world.setBlockState(pos, ModBlocks.enchanter.getDefaultState().withProperty(BotaniaStateProps.ENCHANTER_DIRECTION, axis), 1 | 2);
player.addStat(ModAchievements.enchanterMake, 1);
world.playSound(null, pos, BotaniaSoundEvents.enchanterForm, SoundCategory.BLOCKS, 0.5F, 0.6F);
} else {
for(int i = 0; i < 50; i++) {
float red = (float) Math.random();
float green = (float) Math.random();
float blue = (float) Math.random();
double x = (Math.random() - 0.5) * 6;
double y = (Math.random() - 0.5) * 6;
double z = (Math.random() - 0.5) * 6;
float velMul = 0.07F;
Botania.proxy.wispFX(pos.getX() + 0.5 + x, pos.getY() + 0.5 + y, pos.getZ() + 0.5 + z, red, green, blue, (float) Math.random() * 0.15F + 0.15F, (float) -x * velMul, (float) -y * velMul, (float) -z * velMul);
}
}
return EnumActionResult.SUCCESS;
}
return EnumActionResult.PASS;
}
if(block instanceof IWandable) {
TileEntity tile = world.getTileEntity(pos);
boolean bindable = tile instanceof IWandBindable;
boolean wanded;
if(getBindMode(stack) && bindable && player.isSneaking() && ((IWandBindable) tile).canSelect(player, stack, pos, side)) {
if(boundPos.equals(pos))
setBoundTile(stack, UNBOUND_POS);
else setBoundTile(stack, pos);
if(world.isRemote) {
player.swingArm(hand);
player.playSound(BotaniaSoundEvents.ding, 0.11F, 1F);
}
wanded = true;
} else {
wanded = ((IWandable) block).onUsedByWand(player, stack, world, pos, side);
if(wanded && world.isRemote)
player.swingArm(hand);
}
return wanded ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;
}
if(((BlockPistonRelay) ModBlocks.pistonRelay).playerPositions.containsKey(player.getUniqueID()) && !world.isRemote) {
BlockPistonRelay.DimWithPos bindPos = ((BlockPistonRelay) ModBlocks.pistonRelay).playerPositions.get(player.getUniqueID());
BlockPistonRelay.DimWithPos currentPos = new BlockPistonRelay.DimWithPos(world.provider.getDimension(), pos);
((BlockPistonRelay) ModBlocks.pistonRelay).playerPositions.remove(player.getUniqueID());
((BlockPistonRelay) ModBlocks.pistonRelay).mappedPositions.put(bindPos, currentPos);
BlockPistonRelay.WorldData.get(world).markDirty();
world.playSound(null, player.posX, player.posY, player.posZ, BotaniaSoundEvents.ding, SoundCategory.PLAYERS, 1F, 1F);
return EnumActionResult.SUCCESS;
}
return EnumActionResult.PASS;
}
public static void doParticleBeam(World world, Vector3 orig, Vector3 end) {
if(!world.isRemote)
return;
Vector3 diff = end.subtract(orig);
Vector3 movement = diff.normalize().multiply(0.05);
int iters = (int) (diff.mag() / movement.mag());
float huePer = 1F / iters;
float hueSum = (float) Math.random();
Vector3 currentPos = orig;
for(int i = 0; i < iters; i++) {
float hue = i * huePer + hueSum;
Color color = Color.getHSBColor(hue, 1F, 1F);
float r = color.getRed() / 255F;
float g = color.getGreen() / 255F;
float b = color.getBlue() / 255F;
Botania.proxy.setSparkleFXNoClip(true);
Botania.proxy.sparkleFX(currentPos.x, currentPos.y, currentPos.z, r, g, b, 0.5F, 4);
Botania.proxy.setSparkleFXNoClip(false);
currentPos = currentPos.add(movement);
}
}
@Override
public void onUpdate(ItemStack par1ItemStack, World world, Entity par3Entity, int par4, boolean par5) {
BlockPos coords = getBoundTile(par1ItemStack);
TileEntity tile = world.getTileEntity(coords);
if(tile == null || !(tile instanceof IWandBindable))
setBoundTile(par1ItemStack, UNBOUND_POS);
}
@Nonnull
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, @Nonnull EnumHand hand) {
ItemStack stack = player.getHeldItem(hand);
if(player.isSneaking()) {
if(!world.isRemote)
setBindMode(stack, !getBindMode(stack));
else player.playSound(BotaniaSoundEvents.ding, 0.1F, 1F);
}
return ActionResult.newResult(EnumActionResult.SUCCESS, stack);
}
@Override
public void getSubItems(@Nonnull Item item, CreativeTabs tab, NonNullList<ItemStack> stacks) {
for(int i = 0; i < 16; i++)
stacks.add(forColors(i, i));
}
@Nonnull
@Override
public String getUnlocalizedName(ItemStack par1ItemStack) {
return getUnlocalizedNameLazy(par1ItemStack);
}
@SideOnly(Side.CLIENT)
@Override
public void addInformation(ItemStack stack, EntityPlayer p, List<String> list, boolean adv) {
list.add(I18n.format(getModeString(stack)));
}
@Nonnull
@Override
public EnumRarity getRarity(ItemStack par1ItemStack) {
return EnumRarity.RARE;
}
public static ItemStack forColors(int color1, int color2) {
ItemStack stack = new ItemStack(ModItems.twigWand);
ItemNBTHelper.setInt(stack, TAG_COLOR1, color1);
ItemNBTHelper.setInt(stack, TAG_COLOR2, color2);
return stack;
}
public static int getColor1(ItemStack stack) {
return ItemNBTHelper.getInt(stack, TAG_COLOR1, 0);
}
public static int getColor2(ItemStack stack) {
return ItemNBTHelper.getInt(stack, TAG_COLOR2, 0);
}
public static void setBoundTile(ItemStack stack, BlockPos pos) {
ItemNBTHelper.setInt(stack, TAG_BOUND_TILE_X, pos.getX());
ItemNBTHelper.setInt(stack, TAG_BOUND_TILE_Y, pos.getY());
ItemNBTHelper.setInt(stack, TAG_BOUND_TILE_Z, pos.getZ());
}
public static BlockPos getBoundTile(ItemStack stack) {
int x = ItemNBTHelper.getInt(stack, TAG_BOUND_TILE_X, 0);
int y = ItemNBTHelper.getInt(stack, TAG_BOUND_TILE_Y, -1);
int z = ItemNBTHelper.getInt(stack, TAG_BOUND_TILE_Z, 0);
return new BlockPos(x, y, z);
}
public static boolean getBindMode(ItemStack stack) {
return ItemNBTHelper.getBoolean(stack, TAG_BIND_MODE, true);
}
public static void setBindMode(ItemStack stack, boolean bindMode) {
ItemNBTHelper.setBoolean(stack, TAG_BIND_MODE, bindMode);
}
public static String getModeString(ItemStack stack) {
return "botaniamisc.wandMode." + (getBindMode(stack) ? "bind" : "function");
}
@Override
public BlockPos getBinding(ItemStack stack) {
BlockPos bound = getBoundTile(stack);
if(bound.getY() != -1)
return bound;
RayTraceResult pos = Minecraft.getMinecraft().objectMouseOver;
if(pos != null && pos.typeOfHit == RayTraceResult.Type.BLOCK) {
TileEntity tile = Minecraft.getMinecraft().world.getTileEntity(pos.getBlockPos());
if(tile != null && tile instanceof ITileBound) {
BlockPos coords = ((ITileBound) tile).getBinding();
return coords;
}
}
return null;
}
@SideOnly(Side.CLIENT)
@Override
public void registerModels() {
ModelLoader.setCustomModelResourceLocation(this, 0, new ModelResourceLocation(getRegistryName(), "inventory"));
}
}