Java tutorial
/** * 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 @ [01/11/2015, 18:25:54 (GMT)] */ package vazkii.botania.common.item; import java.util.EnumMap; import java.util.Map; import javax.annotation.Nonnull; import org.lwjgl.opengl.GL11; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; 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.lexicon.multiblock.Multiblock; import vazkii.botania.common.Botania; import vazkii.botania.common.core.helper.ItemNBTHelper; import vazkii.botania.common.core.helper.MathHelper; import vazkii.botania.common.core.helper.Vector3; import vazkii.botania.common.item.equipment.tool.ToolCommons; import vazkii.botania.common.lib.LibItemNames; public class ItemSextant extends ItemMod { private static final String TAG_SOURCE_X = "sourceX"; private static final String TAG_SOURCE_Y = "sourceY"; private static final String TAG_SOURCE_Z = "sourceZ"; public ItemSextant() { super(LibItemNames.SEXTANT); setMaxStackSize(1); } @Nonnull @Override public EnumAction getItemUseAction(ItemStack par1ItemStack) { return EnumAction.BOW; } @Override public int getMaxItemUseDuration(ItemStack par1ItemStack) { return 72000; } @Override public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) { if (getMaxItemUseDuration(stack) - count < 10 || !(living instanceof EntityPlayer)) return; int x = ItemNBTHelper.getInt(stack, TAG_SOURCE_X, 0); int y = ItemNBTHelper.getInt(stack, TAG_SOURCE_Y, -1); int z = ItemNBTHelper.getInt(stack, TAG_SOURCE_Z, 0); if (y != -1) { Vector3 source = new Vector3(x, y, z); double radius = calculateRadius(stack, (EntityPlayer) living); if (count % 10 == 0) for (int i = 0; i < 360; i++) { float radian = (float) (i * Math.PI / 180); double xp = x + Math.cos(radian) * radius; double zp = z + Math.sin(radian) * radius; Botania.proxy.wispFX(xp + 0.5, source.y + 1, zp + 0.5, 0F, 1F, 1F, 0.3F, -0.01F); } } } @Override public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase living, int time) { if (!(living instanceof EntityPlayer)) return; double radius = calculateRadius(stack, (EntityPlayer) living); if (radius > 1) { int x = ItemNBTHelper.getInt(stack, TAG_SOURCE_X, 0); int y = ItemNBTHelper.getInt(stack, TAG_SOURCE_Y, -1); int z = ItemNBTHelper.getInt(stack, TAG_SOURCE_Z, 0); if (y != -1) Botania.proxy.setMultiblock(world, x, y, z, radius, Blocks.COBBLESTONE); } } @Nonnull @Override public ActionResult<ItemStack> onItemRightClick(@Nonnull ItemStack par1ItemStack, World world, EntityPlayer player, EnumHand hand) { Botania.proxy.removeSextantMultiblock(); if (!player.isSneaking()) { RayTraceResult pos = ToolCommons.raytraceFromEntity(world, player, false, 128); if (pos != null && pos.entityHit == null && pos.getBlockPos() != null) { if (!world.isRemote) { ItemNBTHelper.setInt(par1ItemStack, TAG_SOURCE_X, pos.getBlockPos().getX()); ItemNBTHelper.setInt(par1ItemStack, TAG_SOURCE_Y, pos.getBlockPos().getY()); ItemNBTHelper.setInt(par1ItemStack, TAG_SOURCE_Z, pos.getBlockPos().getZ()); } } else ItemNBTHelper.setInt(par1ItemStack, TAG_SOURCE_Y, -1); player.setActiveHand(hand); } return ActionResult.newResult(EnumActionResult.SUCCESS, par1ItemStack); } public static double calculateRadius(ItemStack stack, EntityPlayer player) { int x = ItemNBTHelper.getInt(stack, TAG_SOURCE_X, 0); int y = ItemNBTHelper.getInt(stack, TAG_SOURCE_Y, -1); int z = ItemNBTHelper.getInt(stack, TAG_SOURCE_Z, 0); Vector3 source = new Vector3(x, y, z); Botania.proxy.wispFX(source.x + 0.5, source.y + 1, source.z + 0.5, 1F, 0F, 0F, 0.2F, -0.1F); Vector3 centerVec = Vector3.fromEntityCenter(player); Vector3 diffVec = source.subtract(centerVec); Vector3 lookVec = new Vector3(player.getLookVec()); double mul = diffVec.y / lookVec.y; lookVec = lookVec.multiply(mul).add(centerVec); lookVec = new Vector3(net.minecraft.util.math.MathHelper.floor_double(lookVec.x), lookVec.y, net.minecraft.util.math.MathHelper.floor_double(lookVec.z)); return MathHelper.pointDistancePlane(source.x, source.z, lookVec.x, lookVec.z); } @SideOnly(Side.CLIENT) public static void renderHUD(ScaledResolution resolution, EntityPlayer player, ItemStack stack) { ItemStack onUse = player.getActiveItemStack(); int time = player.getItemInUseCount(); if (onUse == stack && stack.getItem().getMaxItemUseDuration(stack) - time >= 10) { double radius = calculateRadius(stack, player); FontRenderer font = Minecraft.getMinecraft().fontRendererObj; int x = resolution.getScaledWidth() / 2 + 30; int y = resolution.getScaledHeight() / 2; String s = "" + (int) radius; font.drawStringWithShadow(s, x - font.getStringWidth(s) / 2, y - 4, 0xFFFFFF); if (radius > 0) { radius += 4; GlStateManager.disableTexture2D(); GL11.glLineWidth(3F); GL11.glBegin(GL11.GL_LINE_STRIP); GlStateManager.color(0F, 1F, 1F, 1F); for (int i = 0; i < 361; i++) { float radian = (float) (i * Math.PI / 180); double xp = x + Math.cos(radian) * radius; double yp = y + Math.sin(radian) * radius; GL11.glVertex2d(xp, yp); } GL11.glEnd(); GlStateManager.enableTexture2D(); } } } public static class MultiblockSextant extends Multiblock { @Override public Map<EnumFacing, Multiblock> createRotations() { Map<EnumFacing, Multiblock> ret = new EnumMap<>(EnumFacing.class); for (EnumFacing e : EnumFacing.VALUES) { ret.put(e, this); } return ret; } } }