Java tutorial
/** * This class was created by <Vazkii>. It's distributed as * part of the Psi Mod. Get the Source Code in github: * https://github.com/Vazkii/Psi * * Psi is Open Source and distributed under the * Psi License: http://psi.vazkii.us/license.php * * File Created @ [13/01/2016, 23:05:26 (GMT)] */ package vazkii.psi.client.gui; import java.awt.Color; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector2f; import com.google.common.collect.ImmutableSet; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.settings.KeyBinding; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import vazkii.psi.api.PsiAPI; import vazkii.psi.api.cad.ICAD; import vazkii.psi.api.cad.ISocketable; import vazkii.psi.api.cad.ISocketableController; import vazkii.psi.client.core.handler.KeybindHandler; import vazkii.psi.common.core.handler.PlayerDataHandler; import vazkii.psi.common.lib.LibResources; import vazkii.psi.common.network.Message; import vazkii.psi.common.network.NetworkHandler; import vazkii.psi.common.network.message.MessageChangeControllerSlot; import vazkii.psi.common.network.message.MessageChangeSocketableSlot; public class GuiSocketSelect extends GuiScreen { private static final ResourceLocation[] signs = new ResourceLocation[] { new ResourceLocation(String.format(LibResources.GUI_SIGN, 0)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 1)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 2)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 3)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 4)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 5)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 6)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 7)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 8)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 9)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 10)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 11)), new ResourceLocation(String.format(LibResources.GUI_SIGN, 12)) }; int timeIn = 0; int slotSelected = -1; ItemStack controllerStack; ISocketableController controller; ItemStack[] controlledStacks; int controlSlot; ItemStack socketableStack; ISocketable socketable; List<Integer> slots; public GuiSocketSelect(ItemStack stack) { mc = Minecraft.getMinecraft(); if (stack.getItem() instanceof ISocketable) setSocketable(stack); else if (stack.getItem() instanceof ISocketableController) { controllerStack = stack; controller = (ISocketableController) stack.getItem(); controlledStacks = controller.getControlledStacks(mc.thePlayer, stack); controlSlot = controller.getDefaultControlSlot(controllerStack); if (controlSlot >= controlledStacks.length) controlSlot = 0; setSocketable(controlledStacks.length == 0 ? null : controlledStacks[controlSlot]); } } public void setSocketable(ItemStack stack) { slots = new ArrayList(); if (stack == null) return; socketableStack = stack; socketable = (ISocketable) stack.getItem(); for (int i = 0; i < ISocketable.MAX_SLOTS; i++) if (socketable.showSlotInRadialMenu(stack, i)) slots.add(i); } @Override public void drawScreen(int mx, int my, float partialTicks) { super.drawScreen(mx, my, partialTicks); GlStateManager.pushMatrix(); GlStateManager.disableTexture2D(); int x = width / 2; int y = height / 2; int maxRadius = 80; boolean mouseIn = true; float angle = mouseAngle(x, y, mx, my); int highlight = 5; GlStateManager.enableBlend(); GlStateManager.shadeModel(GL11.GL_SMOOTH); int segments = slots.size(); float totalDeg = 0; float degPer = 360F / segments; List<int[]> stringPositions = new ArrayList(); ItemStack cadStack = PsiAPI.getPlayerCAD(Minecraft.getMinecraft().thePlayer); slotSelected = -1; for (int seg = 0; seg < segments; seg++) { boolean mouseInSector = mouseIn && angle > totalDeg && angle < totalDeg + degPer; float radius = Math.max(0F, Math.min((timeIn + partialTicks - seg * 6F / segments) * 40F, maxRadius)); GL11.glBegin(GL11.GL_TRIANGLE_FAN); float gs = 0.25F; if (seg % 2 == 0) gs += 0.1F; float r = gs; float g = gs; float b = gs; float a = 0.4F; if (mouseInSector) { slotSelected = seg; if (cadStack != null) { ICAD cad = (ICAD) cadStack.getItem(); Color color = new Color(cad.getSpellColor(cadStack)); r = color.getRed() / 255F; g = color.getGreen() / 255F; b = color.getBlue() / 255F; } } GlStateManager.color(r, g, b, a); GL11.glVertex2i(x, y); for (float i = degPer; i >= 0; i--) { float rad = (float) ((i + totalDeg) / 180F * Math.PI); double xp = x + Math.cos(rad) * radius; double yp = y + Math.sin(rad) * radius; if (i == (int) (degPer / 2)) stringPositions.add(new int[] { seg, (int) xp, (int) yp, mouseInSector ? 'n' : 'r' }); GL11.glVertex2d(xp, yp); } totalDeg += degPer; GL11.glVertex2i(x, y); GL11.glEnd(); if (mouseInSector) radius -= highlight; } GlStateManager.shadeModel(GL11.GL_FLAT); GlStateManager.enableTexture2D(); for (int[] pos : stringPositions) { int slot = slots.get(pos[0]); int xp = pos[1]; int yp = pos[2]; char c = (char) pos[3]; ItemStack stack = socketable.getBulletInSocket(socketableStack, slot); if (stack != null) { int xsp = xp - 4; int ysp = yp; String name = "\u00a7" + c + stack.getDisplayName(); int width = fontRendererObj.getStringWidth(name); double mod = 0.6; int xdp = (int) ((xp - x) * mod + x); int ydp = (int) ((yp - y) * mod + y); mc.getRenderItem().renderItemIntoGUI(stack, xdp - 8, ydp - 8); if (xsp < x) xsp -= width - 8; if (ysp < y) ysp -= 9; fontRendererObj.drawStringWithShadow(name, xsp, ysp, 0xFFFFFF); mod = 0.8; xdp = (int) ((xp - x) * mod + x); ydp = (int) ((yp - y) * mod + y); mc.renderEngine.bindTexture(signs[slot]); drawModalRectWithCustomSizedTexture(xdp - 8, ydp - 8, 0, 0, 16, 16, 16, 16); } } float stime = 5F; float fract = Math.min(stime, timeIn + partialTicks) / stime; float s = 3F * fract; GlStateManager.enableRescaleNormal(); GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); RenderHelper.enableGUIStandardItemLighting(); if (controlledStacks != null && controlledStacks.length > 0) { int xs = width / 2 - 18 * controlledStacks.length / 2; int ys = height / 2; for (int i = 0; i < controlledStacks.length; i++) { float yoff = 25F + maxRadius; if (i == controlSlot) yoff += 5F; GlStateManager.translate(0, -yoff * fract, 0F); mc.getRenderItem().renderItemAndEffectIntoGUI(controlledStacks[i], xs + i * 18, ys); GlStateManager.translate(0, yoff * fract, 0F); } } if (socketableStack != null) { GlStateManager.scale(s, s, s); GlStateManager.translate(x / s - 8, y / s - 8, 0); mc.getRenderItem().renderItemAndEffectIntoGUI(socketableStack, 0, 0); } RenderHelper.disableStandardItemLighting(); GlStateManager.disableBlend(); GlStateManager.disableRescaleNormal(); GlStateManager.popMatrix(); } @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { super.mouseClicked(mouseX, mouseY, mouseButton); if (controllerStack != null && controlledStacks.length > 0) { if (mouseButton == 0) { controlSlot++; if (controlSlot >= controlledStacks.length) controlSlot = 0; } else if (mouseButton == 1) { controlSlot--; if (controlSlot < 0) controlSlot = controlledStacks.length - 1; } setSocketable(controlledStacks[controlSlot]); } } @Override public void updateScreen() { super.updateScreen(); if (!isKeyDown(KeybindHandler.keybind)) { mc.displayGuiScreen(null); if (slotSelected != -1) { int slot = slots.get(slotSelected); PlayerDataHandler.get(mc.thePlayer).stopLoopcast(); Message message = null; if (controllerStack != null) message = new MessageChangeControllerSlot(controlSlot, slot); else message = new MessageChangeSocketableSlot(slot); NetworkHandler.INSTANCE.sendToServer(message); } } ImmutableSet<KeyBinding> set = ImmutableSet.of(mc.gameSettings.keyBindForward, mc.gameSettings.keyBindLeft, mc.gameSettings.keyBindBack, mc.gameSettings.keyBindRight, mc.gameSettings.keyBindSneak, mc.gameSettings.keyBindSprint, mc.gameSettings.keyBindJump); for (KeyBinding k : set) KeyBinding.setKeyBindState(k.getKeyCode(), isKeyDown(k)); timeIn++; } public boolean isKeyDown(KeyBinding keybind) { int key = keybind.getKeyCode(); if (key < 0) { int button = 100 + key; return Mouse.isButtonDown(button); } return Keyboard.isKeyDown(key); } @Override public boolean doesGuiPauseGame() { return false; } private static float mouseAngle(int x, int y, int mx, int my) { Vector2f baseVec = new Vector2f(1F, 0F); Vector2f mouseVec = new Vector2f(mx - x, my - y); float ang = (float) (Math.acos(Vector2f.dot(baseVec, mouseVec) / (baseVec.length() * mouseVec.length())) * (180F / Math.PI)); return my < y ? 360F - ang : ang; } }