<commit_before>package com.phylogeny.extrabitmanipulation.client.eventhandler;

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Cylinder;
import org.lwjgl.util.glu.Disk;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.glu.Quadric;
import org.lwjgl.util.glu.Sphere;

import com.phylogeny.extrabitmanipulation.ExtraBitManipulation;
import com.phylogeny.extrabitmanipulation.api.ChiselsAndBitsAPIAccess;
import com.phylogeny.extrabitmanipulation.client.shape.Prism;
import com.phylogeny.extrabitmanipulation.config.ConfigShapeRender;
import com.phylogeny.extrabitmanipulation.config.ConfigShapeRenderPair;
import com.phylogeny.extrabitmanipulation.helper.SculptSettingsHelper;
import com.phylogeny.extrabitmanipulation.item.ItemBitWrench;
import com.phylogeny.extrabitmanipulation.item.ItemBitToolBase;
import com.phylogeny.extrabitmanipulation.item.ItemSculptingTool;
import com.phylogeny.extrabitmanipulation.packet.PacketCycleBitWrenchMode;
import com.phylogeny.extrabitmanipulation.packet.PacketSculpt;
import com.phylogeny.extrabitmanipulation.reference.Configs;
import com.phylogeny.extrabitmanipulation.reference.NBTKeys;
import com.phylogeny.extrabitmanipulation.reference.Reference;
import com.phylogeny.extrabitmanipulation.reference.Utility;
import com.phylogeny.extrabitmanipulation.shape.Shape;

import mod.chiselsandbits.api.APIExceptions.CannotBeChiseled;
import mod.chiselsandbits.api.IBitAccess;
import mod.chiselsandbits.api.IBitLocation;
import mod.chiselsandbits.api.IChiselAndBitsAPI;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiNewChat;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;
import net.minecraft.util.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class ClientEventHandler
{
	private int frameCounter;
	private Vec3 drawnStartPoint = null;
	private static final ResourceLocation ARROW_HEAD = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/ArrowHead.png");
	private static final ResourceLocation ARROW_BIDIRECTIONAL = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/ArrowBidirectional.png");
	private static final ResourceLocation ARROW_CYCLICAL = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/ArrowCyclical.png");
	private static final ResourceLocation CIRCLE = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/Circle.png");
	private static final ResourceLocation INVERSION = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/Inversion.png");
	private static final int[] DIRECTION_FORWARD = new int[]{2, 0, 5, 4, 1, 3};
	private static final int[] DIRECTION_BACKWARD = new int[]{1, 4, 0, 5, 3, 2};
	private static final int[] AXIS_FORWARD = new int[]{2, 3, 4, 5, 0, 1};
	private static final int[] AXIS_BACKWARD = new int[]{4, 5, 0, 1, 2, 3};
	private static final int[] SHAPE_CURVED = new int[]{1, 2, 0, 0, 0, 0, 0};
	private static final int[] SHAPE_FLAT = new int[]{4, 4, 4, 4, 5, 6, 3};
	
	
	@SubscribeEvent
	public void interceptMouseInput(MouseEvent event)
	{
		EntityPlayer player = Minecraft.getMinecraft().thePlayer;
		if (event.dwheel != 0)
		{
			ItemStack stack = player.getCurrentEquippedItem();
			if (stack != null && stack.getItem() instanceof ItemBitToolBase)
			{
				boolean forward = event.dwheel < 0;
				if (player.isSneaking())
				{
					if (stack.getItem() instanceof ItemBitWrench)
					{
						ExtraBitManipulation.packetNetwork.sendToServer(new PacketCycleBitWrenchMode(forward));
					}
					else
					{
						cycleSemiDiameter(player, stack, forward);
					}
					event.setCanceled(true);
				}
				else if (GuiScreen.isCtrlKeyDown() || GuiScreen.isAltKeyDown())
				{
					if (GuiScreen.isCtrlKeyDown())
					{
						cycleRotation(player, stack, forward);
					}
					else
					{
						cycleWallThickness(player, stack, forward);
					}
					event.setCanceled(true);
				}
			}
			else
			{
				drawnStartPoint = null;
			}
		}
		else if ((GuiScreen.isCtrlKeyDown() || GuiScreen.isAltKeyDown()) && event.buttonstate)
		{
			ItemStack stack = player.inventory.getCurrentItem();
			if (stack != null)
			{
				Item item = stack.getItem();
				if (item != null && item instanceof ItemSculptingTool)
				{
					if (GuiScreen.isCtrlKeyDown())
					{
						if (event.button == 1)
						{
							cycleShapeType(player, stack, item);
						}
						if (event.button == 0)
						{
							toggleBitGridTargeted(player, stack);
						}
					}
					else
					{
						if (event.button == 1)
						{
							toggleHollowShape(player, stack);
						}
						if (event.button == 0)
						{
							toggleOpenEnds(player, stack);
						}
					}
					event.setCanceled(true);
				}
			}
		}
		else if (event.button == 0)
		{
			if (!player.capabilities.allowEdit) return;
			ItemStack stack = player.inventory.getCurrentItem();
			if (stack != null)
			{
				Item item = stack.getItem();
				if (event.buttonstate && item instanceof ItemBitWrench)
				{
					event.setCanceled(true);
				}
				else if (item != null && item instanceof ItemSculptingTool)
				{
					boolean drawnMode = SculptSettingsHelper.getMode(player, stack.getTagCompound()) == 2;
					if (!drawnMode)
					{
						drawnStartPoint = null;
					}
					if (event.buttonstate || (drawnMode && drawnStartPoint != null))
					{
						ItemSculptingTool toolItem = (ItemSculptingTool) item;
						boolean removeBits = toolItem.removeBits();
						MovingObjectPosition target = Minecraft.getMinecraft().objectMouseOver;
						if (target != null && target.typeOfHit != MovingObjectPosition.MovingObjectType.MISS)
						{
							if (target.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK)
							{
								BlockPos pos = target.getBlockPos();
								EnumFacing side = target.sideHit;
								Vec3 hit = target.hitVec;
								boolean swingTool = true;
								if (drawnMode && event.buttonstate && drawnStartPoint != null)
								{
									event.setCanceled(true);
									return;
								}
								if (!player.isSneaking() && drawnMode && event.buttonstate)
								{
									IBitLocation bitLoc = ChiselsAndBitsAPIAccess.apiInstance.getBitPos((float) hit.xCoord - pos.getX(),
											(float) hit.yCoord - pos.getY(), (float) hit.zCoord - pos.getZ(), side, pos, false);
									if (bitLoc != null)
									{
										int x = pos.getX();
										int y = pos.getY();
										int z = pos.getZ();
										float x2 = x + bitLoc.getBitX() * Utility.PIXEL_F;
										float y2 = y + bitLoc.getBitY() * Utility.PIXEL_F;
										float z2 = z + bitLoc.getBitZ() * Utility.PIXEL_F;
										if (!removeBits)
										{
											x2 += side.getFrontOffsetX() * Utility.PIXEL_F;
											y2 += side.getFrontOffsetY() * Utility.PIXEL_F;
											z2 += side.getFrontOffsetZ() * Utility.PIXEL_F;
										}
										drawnStartPoint = new Vec3(x2, y2, z2);
									}
									else
									{
										drawnStartPoint = null;
										swingTool = false;
									}
								}
								else
								{
									if (player.isSneaking())
									{
										IChiselAndBitsAPI api = ChiselsAndBitsAPIAccess.apiInstance;
										IBitLocation bitLoc = api.getBitPos((float) hit.xCoord - pos.getX(), (float) hit.yCoord - pos.getY(),
												(float) hit.zCoord - pos.getZ(), side, pos, false);
										if (bitLoc != null)
										{
											try
											{
												IBitAccess bitAccess = api.getBitAccess(player.worldObj, pos);
												ItemStack bitStack = bitAccess.getBitAt(bitLoc.getBitX(), bitLoc.getBitY(), bitLoc.getBitZ()).getItemStack(1);
												SculptSettingsHelper.setBitStack(player, stack, removeBits, bitStack);
												if ((removeBits ? Configs.sculptSetBitWire : Configs.sculptSetBitSpade).shouldDisplayInChat())
												{
													printChatMessageWithDeletion((removeBits ? "Removing only " : "Sculpting with ")
															+ bitStack.getDisplayName().substring(15));
												}
											}
											catch (CannotBeChiseled e)
											{
												event.setCanceled(true);
												return;
											}
										}
									}
									else if (!player.isSneaking() || removeBits || drawnMode)
									{
										swingTool = toolItem.sculptBlocks(stack, player, player.worldObj, pos, side, hit, drawnStartPoint);
										ExtraBitManipulation.packetNetwork.sendToServer(new PacketSculpt(pos, side, hit, drawnStartPoint));
									}
									if (drawnMode && !event.buttonstate)
									{
										drawnStartPoint = null;
									}
								}
								if (swingTool) player.swingItem();
								event.setCanceled(true);
							}
						}
						else if (player.isSneaking() && event.buttonstate && removeBits)
						{
							SculptSettingsHelper.setBitStack(player, stack, true, null);
							if ((removeBits ? Configs.sculptSetBitWire : Configs.sculptSetBitSpade).shouldDisplayInChat())
							{
								printChatMessageWithDeletion("Removing any/all bits");
							}
						}
						else if (drawnMode)
						{
							drawnStartPoint = null;
						}
					}
				}
			}
		}
		if (!event.isCanceled() && event.button == 1 && event.buttonstate)
		{
			ItemStack stack = player.inventory.getCurrentItem();
			if (stack != null)
			{
				Item item = stack.getItem();
				if (item != null && item instanceof ItemSculptingTool)
				{
					cycleMode(player, stack, !player.isSneaking());
				}
			}
		}
	}
	
	private void cycleMode(EntityPlayer player, ItemStack stack, boolean forward)
	{
		int mode = ((ItemSculptingTool) stack.getItem()).cycleData(SculptSettingsHelper.getMode(player,
				stack.getTagCompound()), forward, ItemSculptingTool.MODE_TITLES.length);
		SculptSettingsHelper.setMode(player, stack, mode);
		if (Configs.sculptMode.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getModeText(mode));
		}
	}
	
	private void cycleRotation(EntityPlayer player, ItemStack stack, boolean forward)
	{
		NBTTagCompound nbt = stack.hasTagCompound() ? stack.getTagCompound() : new NBTTagCompound();
		int rotation = SculptSettingsHelper.getRotation(player, nbt);
		int shapeType = SculptSettingsHelper.getShapeType(player, nbt, ((ItemSculptingTool) stack.getItem()).isCurved());
		rotation = shapeType == 2 || shapeType > 4 ? (forward ? DIRECTION_FORWARD[rotation] : DIRECTION_BACKWARD[rotation])
				: (forward ? AXIS_FORWARD[rotation] : AXIS_BACKWARD[rotation]);
		SculptSettingsHelper.setRotation(player, stack, rotation);
		if (Configs.sculptRotation.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getRotationText(rotation));
		}
	}
	
	private void cycleShapeType(EntityPlayer player, ItemStack stack, Item item)
	{
		boolean isCurved = ((ItemSculptingTool) item).isCurved();
		NBTTagCompound nbt = stack.hasTagCompound() ? stack.getTagCompound() : new NBTTagCompound();
		int shapeType = SculptSettingsHelper.getShapeType(player, nbt, isCurved);
		shapeType = isCurved ? SHAPE_CURVED[shapeType] : SHAPE_FLAT[shapeType];
		SculptSettingsHelper.setShapeType(player, stack, isCurved, shapeType);
		if ((isCurved ? Configs.sculptShapeTypeCurved : Configs.sculptShapeTypeFlat).shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getShapeTypeText(shapeType));
		}
	}
	
	private void toggleBitGridTargeted(EntityPlayer player, ItemStack stack)
	{
		boolean targetBitGrid = !SculptSettingsHelper.isBitGridTargeted(player, stack.getTagCompound());
		SculptSettingsHelper.setBitGridTargeted(player, stack, targetBitGrid);
		if (Configs.sculptTargetBitGridVertexes.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getBitGridTargetedText(targetBitGrid));
		}
	}
	
	private void cycleSemiDiameter(EntityPlayer player, ItemStack stack, boolean forward)
	{
		int semiDiameter = ((ItemBitToolBase) stack.getItem()).cycleData(SculptSettingsHelper.getSemiDiameter(player, stack.getTagCompound()),
				forward, Configs.maxSemiDiameter);
		SculptSettingsHelper.setSemiDiameter(player, stack, semiDiameter);
		if (Configs.sculptSemiDiameter.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getSemiDiameterText(player, stack.getTagCompound(), semiDiameter));
		}
	}
	
	private void toggleHollowShape(EntityPlayer player, ItemStack stack)
	{
		boolean isHollowShape = !SculptSettingsHelper.isHollowShape(player, stack.getTagCompound());
		SculptSettingsHelper.setHollowShape(player, stack, isHollowShape);
		if (Configs.sculptHollowShape.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getHollowShapeText(isHollowShape));
		}
	}
	
	private void toggleOpenEnds(EntityPlayer player, ItemStack stack)
	{
		boolean areEndsOpen = !SculptSettingsHelper.areEndsOpen(player, stack.getTagCompound());
		SculptSettingsHelper.setEndsOpen(player, stack, areEndsOpen);
		if (Configs.sculptOpenEnds.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getOpenEndsText(areEndsOpen));
		}
	}
	
	private void cycleWallThickness(EntityPlayer player, ItemStack stack, boolean forward)
	{
		int wallThickness = ((ItemBitToolBase) stack.getItem()).cycleData(SculptSettingsHelper.getWallThickness(player, stack.getTagCompound()),
				forward, Configs.maxWallThickness);
		SculptSettingsHelper.setWallThickness(player, stack, wallThickness);
		if (Configs.sculptWallThickness.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getWallThicknessText(wallThickness));
		}
	}
	
	private void printChatMessageWithDeletion(String text)
	{
		GuiNewChat chatGUI = Minecraft.getMinecraft().ingameGUI.getChatGUI();
		chatGUI.printChatMessageWithOptionalDeletion(new ChatComponentText(text), 627250);
	}
	
	@SubscribeEvent
	public void cancelBoundingBoxDraw(DrawBlockHighlightEvent event)
	{
		ItemStack itemStack = event.player.inventory.getCurrentItem();
		if (itemStack != null)
		{
			Item item = itemStack.getItem();
			if (item != null && item instanceof ItemSculptingTool
					&& SculptSettingsHelper.getMode(event.player, itemStack.getTagCompound()) == 1)
			{
				event.setCanceled(true);
			}
		}
	}
	
	@SubscribeEvent
	public void renderBoxesSpheresAndOverlays(RenderWorldLastEvent event)
	{
		if (!Configs.disableOverlays)
		{
			EntityPlayer player = Minecraft.getMinecraft().thePlayer;
			World world = player.worldObj;
			ItemStack stack = player.getCurrentEquippedItem();
			if (stack != null)
			{
				MovingObjectPosition target = Minecraft.getMinecraft().objectMouseOver;
				if (target != null && target.typeOfHit.equals(MovingObjectType.BLOCK)
						&& stack.getItem() instanceof ItemBitToolBase)
				{
					IChiselAndBitsAPI api = ChiselsAndBitsAPIAccess.apiInstance;
					float ticks = event.partialTicks;
	        		double playerX = player.lastTickPosX + (player.posX - player.lastTickPosX) * ticks;
	        		double playerY = player.lastTickPosY + (player.posY - player.lastTickPosY) * ticks;
	        		double playerZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * ticks;
	        		EnumFacing dir = target.sideHit;
	                Tessellator t = Tessellator.getInstance();
	                WorldRenderer wr = t.getWorldRenderer();
	                BlockPos pos = target.getBlockPos();
	                int x = pos.getX();
	                int y = pos.getY();
	                int z = pos.getZ();
	                double diffX = playerX - x;
					double diffY = playerY - y;
					double diffZ = playerZ - z;
					Vec3 hit = target.hitVec;
					if (stack.getItem() instanceof ItemBitWrench && api.isBlockChiseled(world, target.getBlockPos()))
					{
						int mode = SculptSettingsHelper.getMode(player, stack.getTagCompound());
						frameCounter++;
		                int side = dir.ordinal();
		                boolean upDown = side <= 1;
		                boolean eastWest = side >= 4;
		                boolean northSouth = !upDown && !eastWest;
		                AxisAlignedBB box = new AxisAlignedBB(eastWest ? hit.xCoord : x, upDown ? hit.yCoord : y, northSouth ? hit.zCoord : z,
		                		eastWest ? hit.xCoord : x + 1, upDown ? hit.yCoord : y + 1, northSouth ? hit.zCoord : z + 1);
		                
		                int offsetX = Math.abs(dir.getFrontOffsetX());<commit_msg>Fixed bug with wrench mode cycling and bug with using sculpting tool controls while holding the wrench.<commit_after>package com.phylogeny.extrabitmanipulation.client.eventhandler;

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Cylinder;
import org.lwjgl.util.glu.Disk;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.glu.Quadric;
import org.lwjgl.util.glu.Sphere;

import com.phylogeny.extrabitmanipulation.ExtraBitManipulation;
import com.phylogeny.extrabitmanipulation.api.ChiselsAndBitsAPIAccess;
import com.phylogeny.extrabitmanipulation.client.shape.Prism;
import com.phylogeny.extrabitmanipulation.config.ConfigShapeRender;
import com.phylogeny.extrabitmanipulation.config.ConfigShapeRenderPair;
import com.phylogeny.extrabitmanipulation.helper.SculptSettingsHelper;
import com.phylogeny.extrabitmanipulation.item.ItemBitWrench;
import com.phylogeny.extrabitmanipulation.item.ItemBitToolBase;
import com.phylogeny.extrabitmanipulation.item.ItemSculptingTool;
import com.phylogeny.extrabitmanipulation.packet.PacketCycleBitWrenchMode;
import com.phylogeny.extrabitmanipulation.packet.PacketSculpt;
import com.phylogeny.extrabitmanipulation.reference.Configs;
import com.phylogeny.extrabitmanipulation.reference.NBTKeys;
import com.phylogeny.extrabitmanipulation.reference.Reference;
import com.phylogeny.extrabitmanipulation.reference.Utility;
import com.phylogeny.extrabitmanipulation.shape.Shape;

import mod.chiselsandbits.api.APIExceptions.CannotBeChiseled;
import mod.chiselsandbits.api.IBitAccess;
import mod.chiselsandbits.api.IBitLocation;
import mod.chiselsandbits.api.IChiselAndBitsAPI;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiNewChat;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;
import net.minecraft.util.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class ClientEventHandler
{
	private int frameCounter;
	private Vec3 drawnStartPoint = null;
	private static final ResourceLocation ARROW_HEAD = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/ArrowHead.png");
	private static final ResourceLocation ARROW_BIDIRECTIONAL = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/ArrowBidirectional.png");
	private static final ResourceLocation ARROW_CYCLICAL = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/ArrowCyclical.png");
	private static final ResourceLocation CIRCLE = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/Circle.png");
	private static final ResourceLocation INVERSION = new ResourceLocation(Reference.GROUP_ID, "textures/overlays/Inversion.png");
	private static final int[] DIRECTION_FORWARD = new int[]{2, 0, 5, 4, 1, 3};
	private static final int[] DIRECTION_BACKWARD = new int[]{1, 4, 0, 5, 3, 2};
	private static final int[] AXIS_FORWARD = new int[]{2, 3, 4, 5, 0, 1};
	private static final int[] AXIS_BACKWARD = new int[]{4, 5, 0, 1, 2, 3};
	private static final int[] SHAPE_CURVED = new int[]{1, 2, 0, 0, 0, 0, 0};
	private static final int[] SHAPE_FLAT = new int[]{4, 4, 4, 4, 5, 6, 3};
	
	
	@SubscribeEvent
	public void interceptMouseInput(MouseEvent event)
	{
		EntityPlayer player = Minecraft.getMinecraft().thePlayer;
		if (event.dwheel != 0)
		{
			ItemStack stack = player.getCurrentEquippedItem();
			if (stack != null && stack.getItem() instanceof ItemBitToolBase)
			{
				boolean forward = event.dwheel < 0;
				if (player.isSneaking())
				{
					if (stack.getItem() instanceof ItemBitWrench)
					{
						ExtraBitManipulation.packetNetwork.sendToServer(new PacketCycleBitWrenchMode(forward));
					}
					else
					{
						cycleSemiDiameter(player, stack, forward);
					}
					event.setCanceled(true);
				}
				else if (stack.getItem() instanceof ItemSculptingTool
						&& (GuiScreen.isCtrlKeyDown() || GuiScreen.isAltKeyDown()))
				{
					if (GuiScreen.isCtrlKeyDown())
					{
						cycleRotation(player, stack, forward);
					}
					else
					{
						cycleWallThickness(player, stack, forward);
					}
					event.setCanceled(true);
				}
			}
			else
			{
				drawnStartPoint = null;
			}
		}
		else if ((GuiScreen.isCtrlKeyDown() || GuiScreen.isAltKeyDown()) && event.buttonstate)
		{
			ItemStack stack = player.inventory.getCurrentItem();
			if (stack != null)
			{
				Item item = stack.getItem();
				if (item != null && item instanceof ItemSculptingTool)
				{
					if (GuiScreen.isCtrlKeyDown())
					{
						if (event.button == 1)
						{
							cycleShapeType(player, stack, item);
						}
						if (event.button == 0)
						{
							toggleBitGridTargeted(player, stack);
						}
					}
					else
					{
						if (event.button == 1)
						{
							toggleHollowShape(player, stack);
						}
						if (event.button == 0)
						{
							toggleOpenEnds(player, stack);
						}
					}
					event.setCanceled(true);
				}
			}
		}
		else if (event.button == 0)
		{
			if (!player.capabilities.allowEdit) return;
			ItemStack stack = player.inventory.getCurrentItem();
			if (stack != null)
			{
				Item item = stack.getItem();
				if (event.buttonstate && item instanceof ItemBitWrench)
				{
					event.setCanceled(true);
				}
				else if (item != null && item instanceof ItemSculptingTool)
				{
					boolean drawnMode = SculptSettingsHelper.getMode(player, stack.getTagCompound()) == 2;
					if (!drawnMode)
					{
						drawnStartPoint = null;
					}
					if (event.buttonstate || (drawnMode && drawnStartPoint != null))
					{
						ItemSculptingTool toolItem = (ItemSculptingTool) item;
						boolean removeBits = toolItem.removeBits();
						MovingObjectPosition target = Minecraft.getMinecraft().objectMouseOver;
						if (target != null && target.typeOfHit != MovingObjectPosition.MovingObjectType.MISS)
						{
							if (target.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK)
							{
								BlockPos pos = target.getBlockPos();
								EnumFacing side = target.sideHit;
								Vec3 hit = target.hitVec;
								boolean swingTool = true;
								if (drawnMode && event.buttonstate && drawnStartPoint != null)
								{
									event.setCanceled(true);
									return;
								}
								if (!player.isSneaking() && drawnMode && event.buttonstate)
								{
									IBitLocation bitLoc = ChiselsAndBitsAPIAccess.apiInstance.getBitPos((float) hit.xCoord - pos.getX(),
											(float) hit.yCoord - pos.getY(), (float) hit.zCoord - pos.getZ(), side, pos, false);
									if (bitLoc != null)
									{
										int x = pos.getX();
										int y = pos.getY();
										int z = pos.getZ();
										float x2 = x + bitLoc.getBitX() * Utility.PIXEL_F;
										float y2 = y + bitLoc.getBitY() * Utility.PIXEL_F;
										float z2 = z + bitLoc.getBitZ() * Utility.PIXEL_F;
										if (!removeBits)
										{
											x2 += side.getFrontOffsetX() * Utility.PIXEL_F;
											y2 += side.getFrontOffsetY() * Utility.PIXEL_F;
											z2 += side.getFrontOffsetZ() * Utility.PIXEL_F;
										}
										drawnStartPoint = new Vec3(x2, y2, z2);
									}
									else
									{
										drawnStartPoint = null;
										swingTool = false;
									}
								}
								else
								{
									if (player.isSneaking())
									{
										IChiselAndBitsAPI api = ChiselsAndBitsAPIAccess.apiInstance;
										IBitLocation bitLoc = api.getBitPos((float) hit.xCoord - pos.getX(), (float) hit.yCoord - pos.getY(),
												(float) hit.zCoord - pos.getZ(), side, pos, false);
										if (bitLoc != null)
										{
											try
											{
												IBitAccess bitAccess = api.getBitAccess(player.worldObj, pos);
												ItemStack bitStack = bitAccess.getBitAt(bitLoc.getBitX(), bitLoc.getBitY(), bitLoc.getBitZ()).getItemStack(1);
												SculptSettingsHelper.setBitStack(player, stack, removeBits, bitStack);
												if ((removeBits ? Configs.sculptSetBitWire : Configs.sculptSetBitSpade).shouldDisplayInChat())
												{
													printChatMessageWithDeletion((removeBits ? "Removing only " : "Sculpting with ")
															+ bitStack.getDisplayName().substring(15));
												}
											}
											catch (CannotBeChiseled e)
											{
												event.setCanceled(true);
												return;
											}
										}
									}
									else if (!player.isSneaking() || removeBits || drawnMode)
									{
										swingTool = toolItem.sculptBlocks(stack, player, player.worldObj, pos, side, hit, drawnStartPoint);
										ExtraBitManipulation.packetNetwork.sendToServer(new PacketSculpt(pos, side, hit, drawnStartPoint));
									}
									if (drawnMode && !event.buttonstate)
									{
										drawnStartPoint = null;
									}
								}
								if (swingTool) player.swingItem();
								event.setCanceled(true);
							}
						}
						else if (player.isSneaking() && event.buttonstate && removeBits)
						{
							SculptSettingsHelper.setBitStack(player, stack, true, null);
							if ((removeBits ? Configs.sculptSetBitWire : Configs.sculptSetBitSpade).shouldDisplayInChat())
							{
								printChatMessageWithDeletion("Removing any/all bits");
							}
						}
						else if (drawnMode)
						{
							drawnStartPoint = null;
						}
					}
				}
			}
		}
		if (!event.isCanceled() && event.button == 1 && event.buttonstate)
		{
			ItemStack stack = player.inventory.getCurrentItem();
			if (stack != null)
			{
				Item item = stack.getItem();
				if (item != null && item instanceof ItemSculptingTool)
				{
					cycleMode(player, stack, !player.isSneaking());
				}
			}
		}
	}
	
	private void cycleMode(EntityPlayer player, ItemStack stack, boolean forward)
	{
		int mode = ((ItemSculptingTool) stack.getItem()).cycleData(SculptSettingsHelper.getMode(player,
				stack.getTagCompound()), forward, ItemSculptingTool.MODE_TITLES.length);
		SculptSettingsHelper.setMode(player, stack, mode);
		if (Configs.sculptMode.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getModeText(mode));
		}
	}
	
	private void cycleRotation(EntityPlayer player, ItemStack stack, boolean forward)
	{
		NBTTagCompound nbt = stack.hasTagCompound() ? stack.getTagCompound() : new NBTTagCompound();
		int rotation = SculptSettingsHelper.getRotation(player, nbt);
		int shapeType = SculptSettingsHelper.getShapeType(player, nbt, ((ItemSculptingTool) stack.getItem()).isCurved());
		rotation = shapeType == 2 || shapeType > 4 ? (forward ? DIRECTION_FORWARD[rotation] : DIRECTION_BACKWARD[rotation])
				: (forward ? AXIS_FORWARD[rotation] : AXIS_BACKWARD[rotation]);
		SculptSettingsHelper.setRotation(player, stack, rotation);
		if (Configs.sculptRotation.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getRotationText(rotation));
		}
	}
	
	private void cycleShapeType(EntityPlayer player, ItemStack stack, Item item)
	{
		boolean isCurved = ((ItemSculptingTool) item).isCurved();
		NBTTagCompound nbt = stack.hasTagCompound() ? stack.getTagCompound() : new NBTTagCompound();
		int shapeType = SculptSettingsHelper.getShapeType(player, nbt, isCurved);
		shapeType = isCurved ? SHAPE_CURVED[shapeType] : SHAPE_FLAT[shapeType];
		SculptSettingsHelper.setShapeType(player, stack, isCurved, shapeType);
		if ((isCurved ? Configs.sculptShapeTypeCurved : Configs.sculptShapeTypeFlat).shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getShapeTypeText(shapeType));
		}
	}
	
	private void toggleBitGridTargeted(EntityPlayer player, ItemStack stack)
	{
		boolean targetBitGrid = !SculptSettingsHelper.isBitGridTargeted(player, stack.getTagCompound());
		SculptSettingsHelper.setBitGridTargeted(player, stack, targetBitGrid);
		if (Configs.sculptTargetBitGridVertexes.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getBitGridTargetedText(targetBitGrid));
		}
	}
	
	private void cycleSemiDiameter(EntityPlayer player, ItemStack stack, boolean forward)
	{
		int semiDiameter = ((ItemBitToolBase) stack.getItem()).cycleData(SculptSettingsHelper.getSemiDiameter(player, stack.getTagCompound()),
				forward, Configs.maxSemiDiameter);
		SculptSettingsHelper.setSemiDiameter(player, stack, semiDiameter);
		if (Configs.sculptSemiDiameter.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getSemiDiameterText(player, stack.getTagCompound(), semiDiameter));
		}
	}
	
	private void toggleHollowShape(EntityPlayer player, ItemStack stack)
	{
		boolean isHollowShape = !SculptSettingsHelper.isHollowShape(player, stack.getTagCompound());
		SculptSettingsHelper.setHollowShape(player, stack, isHollowShape);
		if (Configs.sculptHollowShape.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getHollowShapeText(isHollowShape));
		}
	}
	
	private void toggleOpenEnds(EntityPlayer player, ItemStack stack)
	{
		boolean areEndsOpen = !SculptSettingsHelper.areEndsOpen(player, stack.getTagCompound());
		SculptSettingsHelper.setEndsOpen(player, stack, areEndsOpen);
		if (Configs.sculptOpenEnds.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getOpenEndsText(areEndsOpen));
		}
	}
	
	private void cycleWallThickness(EntityPlayer player, ItemStack stack, boolean forward)
	{
		int wallThickness = ((ItemBitToolBase) stack.getItem()).cycleData(SculptSettingsHelper.getWallThickness(player, stack.getTagCompound()),
				forward, Configs.maxWallThickness);
		SculptSettingsHelper.setWallThickness(player, stack, wallThickness);
		if (Configs.sculptWallThickness.shouldDisplayInChat())
		{
			printChatMessageWithDeletion(SculptSettingsHelper.getWallThicknessText(wallThickness));
		}
	}
	
	private void printChatMessageWithDeletion(String text)
	{
		GuiNewChat chatGUI = Minecraft.getMinecraft().ingameGUI.getChatGUI();
		chatGUI.printChatMessageWithOptionalDeletion(new ChatComponentText(text), 627250);
	}
	
	@SubscribeEvent
	public void cancelBoundingBoxDraw(DrawBlockHighlightEvent event)
	{
		ItemStack itemStack = event.player.inventory.getCurrentItem();
		if (itemStack != null)
		{
			Item item = itemStack.getItem();
			if (item != null && item instanceof ItemSculptingTool
					&& SculptSettingsHelper.getMode(event.player, itemStack.getTagCompound()) == 1)
			{
				event.setCanceled(true);
			}
		}
	}
	
	@SubscribeEvent
	public void renderBoxesSpheresAndOverlays(RenderWorldLastEvent event)
	{
		if (!Configs.disableOverlays)
		{
			EntityPlayer player = Minecraft.getMinecraft().thePlayer;
			World world = player.worldObj;
			ItemStack stack = player.getCurrentEquippedItem();
			if (stack != null)
			{
				MovingObjectPosition target = Minecraft.getMinecraft().objectMouseOver;
				if (target != null && target.typeOfHit.equals(MovingObjectType.BLOCK)
						&& stack.getItem() instanceof ItemBitToolBase)
				{
					IChiselAndBitsAPI api = ChiselsAndBitsAPIAccess.apiInstance;
					float ticks = event.partialTicks;
	        		double playerX = player.lastTickPosX + (player.posX - player.lastTickPosX) * ticks;
	        		double playerY = player.lastTickPosY + (player.posY - player.lastTickPosY) * ticks;
	        		double playerZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * ticks;
	        		EnumFacing dir = target.sideHit;
	                Tessellator t = Tessellator.getInstance();
	                WorldRenderer wr = t.getWorldRenderer();
	                BlockPos pos = target.getBlockPos();
	                int x = pos.getX();
	                int y = pos.getY();
	                int z = pos.getZ();
	                double diffX = playerX - x;
					double diffY = playerY - y;
					double diffZ = playerZ - z;
					Vec3 hit = target.hitVec;
					if (stack.getItem() instanceof ItemBitWrench && api.isBlockChiseled(world, target.getBlockPos()))
					{
						int mode = !stack.hasTagCompound() ? 0 : stack.getTagCompound().getInteger(NBTKeys.MODE);
						frameCounter++;
		                int side = dir.ordinal();
		                boolean upDown = side <= 1;
		                boolean eastWest = side >= 4;
		                boolean northSouth = !upDown && !eastWest;
		                AxisAlignedBB box = new AxisAlignedBB(eastWest ? hit.xCoord : x, upDown ? hit.yCoord : y, northSouth ? hit.zCoord : z,
		                		eastWest ? hit.xCoord : x + 1, upDown ? hit.yCoord : y + 1, northSouth ? hit.zCoord : z + 1);
		                
		                int offsetX = Math.abs(dir.getFrontOffsetX());
{'fraction_non_alphanumeric': 0.10745455072631854, 'fraction_numerical': 0.004726144567833222, 'mean_word_length': 3.5633765546440856, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1469120', 'n_tokens_mistral': 13699, 'n_tokens_neox': 10861, 'n_words': 1951}