Java tutorial
/** * Copyright (c) Lambda Innovation, 2013-2016 * This file is part of the AcademyCraft mod. * https://github.com/LambdaInnovation/AcademyCraft * Licensed under GPLv3, see project root for more information. */ package cn.academy.energy.client.app; import cn.academy.core.AcademyCraft; import cn.academy.core.client.ACRenderingHelper; import cn.academy.core.Resources; import cn.academy.energy.api.block.IWirelessMatrix; import cn.academy.energy.api.block.IWirelessNode; import cn.academy.energy.api.block.IWirelessUser; import cn.lambdalib.multiblock.BlockMulti; import cn.lambdalib.s11n.network.Future; import cn.lambdalib.util.client.HudUtils; import cn.lambdalib.util.client.RenderUtils; import cn.lambdalib.util.client.auxgui.AuxGui; import cn.lambdalib.util.client.font.IFont; import cn.lambdalib.util.client.font.IFont.Extent; import cn.lambdalib.util.client.font.IFont.FontOption; import cn.lambdalib.util.deprecated.LIFMLGameEventDispatcher; import cn.lambdalib.util.deprecated.LIHandler; import cn.lambdalib.util.helper.Color; import cn.lambdalib.util.helper.GameTimer; import cn.lambdalib.util.key.KeyManager; import cn.lambdalib.util.mc.ControlOverrider; import cn.lambdalib.util.mc.EntitySelectors; import cn.lambdalib.util.mc.Raytrace; import cpw.mods.fml.common.gameevent.InputEvent; import cpw.mods.fml.common.gameevent.InputEvent.MouseInputEvent; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatAllowedCharacters; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; import net.minecraft.world.World; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; /** * @author WeAthFolD */ public class FreqTransmitterUI extends AuxGui { private static final String OVERRIDE_GROUP = "AC_FreqTransmitter"; private abstract class State { boolean handlesKey; final long createTime; long timeout = 20000; public State(boolean _handlesKey) { handlesKey = _handlesKey; createTime = GameTimer.getTime(); } final boolean handlesKeyInput() { return handlesKey; } abstract void handleDraw(double w, double h); abstract void handleClicking(MovingObjectPosition result); void handleKeyInput(char ch, int kid) { } final long getDeltaTime() { return GameTimer.getTime() - createTime; } final void startTransmitting() { timeout = 3000; } } private static final Color BG_COLOR = new Color(0x77272727), GLOW_COLOR = new Color(0xaaffffff); private static final double GLOW_SIZE = 1; final IFont font = Resources.font(); EntityPlayer player; World world; State current; KeyEventDispatcher keyDispatcher; public FreqTransmitterUI() { player = Minecraft.getMinecraft().thePlayer; world = player.worldObj; LIFMLGameEventDispatcher.INSTANCE.registerKeyInput(keyDispatcher = new KeyEventDispatcher()); LIFMLGameEventDispatcher.INSTANCE.registerMouseInput(keyDispatcher); setState(new StateStart()); ControlOverrider.override(OVERRIDE_GROUP, KeyManager.MOUSE_LEFT, KeyManager.MOUSE_RIGHT); } @Override public boolean isConsistent() { return false; } private void setState(State next) { if (next == null) { this.dispose(); if (current.handlesKeyInput()) { ControlOverrider.endCompleteOverride(); } } else { if (current != null && current.handlesKeyInput()) { ControlOverrider.endCompleteOverride(); } if (next.handlesKeyInput()) { ControlOverrider.startCompleteOverride(); } } current = next; } private String local(String key) { return StatCollector.translateToLocal("ac.app.freq_transmitter." + key); } @Override public void onDisposed() { keyDispatcher.setDead(); ControlOverrider.endOverride(OVERRIDE_GROUP); } @Override public boolean isForeground() { return false; } @Override public void draw(ScaledResolution sr) { double width = sr.getScaledWidth_double(), height = sr.getScaledHeight_double(); AppFreqTransmitter app = AppFreqTransmitter.instance; GL11.glPushMatrix(); { GL11.glTranslated(15, 15, 0); final float isize = 18; final FontOption option = new FontOption(10); String str = app.getDisplayName(); double len = font.getTextWidth(str, option); drawBox(0, 0, 30 + len, 18); ResourceLocation icon = app.getIcon(); RenderUtils.loadTexture(icon); GL11.glColor4d(1, 1, 1, 1); HudUtils.rect(2, 0, isize, isize); font.draw(str, isize + 6, 4, option); } GL11.glPopMatrix(); current.handleDraw(width, height); long dt = current.getDeltaTime(); if (dt > current.timeout) { setState(new StateNotifyAndQuit("st")); } GL11.glColor4d(1, 1, 1, 1); } private static void drawBox(double x, double y, double width, double height) { BG_COLOR.bind(); HudUtils.colorRect(x, y, width, height); ACRenderingHelper.drawGlow(x, y, width, height, GLOW_SIZE, GLOW_COLOR); } private void drawTextBox(String str, double x, double y) { final double trimLength = 120; final FontOption option = new FontOption(10); Extent extent = font.drawSeperated_Sim(str, trimLength, option); final double X0 = x, Y0 = y, MARGIN = 5; drawBox(X0, Y0, MARGIN * 2 + extent.width + 25, MARGIN * 2 + extent.height); font.drawSeperated(str, X0 + MARGIN, Y0 + MARGIN, trimLength, option); } private class KeyEventDispatcher extends LIHandler<InputEvent> { @Override protected boolean onEvent(InputEvent event) { if (current != null) { if (event instanceof MouseInputEvent) { int mid = Mouse.getEventButton(); if (mid == 1 && Mouse.getEventButtonState()) { current.handleClicking(Raytrace.traceLiving(player, 4, EntitySelectors.nothing())); } } else { if (Keyboard.getEventKeyState()) { if (current.handlesKeyInput()) current.handleKeyInput(Keyboard.getEventCharacter(), Keyboard.getEventKey()); } } } else { AcademyCraft.log.error("Human is dead. Mismatch."); this.setDead(); } return true; } } // STATES private class StateNotify extends State { final String key; public StateNotify(String _key) { super(false); key = _key; } @Override public void handleDraw(double w, double h) { drawTextBox(local(key), w / 2 + 10, h / 2 + 10); } @Override void handleClicking(MovingObjectPosition result) { } } private class StateNotifyAndQuit extends StateNotify { public StateNotifyAndQuit(String _key) { super(_key); } @Override public void handleDraw(double w, double h) { super.handleDraw(w, h); if (this.getDeltaTime() > 1000L) { dispose(); } } } private class StateNotifyAndReturn extends StateNotify { final State toSwitch; public StateNotifyAndReturn(String _key, State _toSwitch) { super(_key); toSwitch = _toSwitch; } @Override public void handleDraw(double w, double h) { super.handleDraw(w, h); if (this.getDeltaTime() > 700L) { setState(toSwitch); } } } // S0 private class StateStart extends State { boolean started = false; public StateStart() { super(false); } @Override public void handleDraw(double w, double h) { drawTextBox(local("s0_0"), w / 2 + 10, h / 2 + 10); } @Override public void handleClicking(MovingObjectPosition result) { if (result == null) { setState(null); return; } if (started) return; int hx = result.blockX, hy = result.blockY, hz = result.blockZ; TileEntity te = world.getTileEntity(hx, hy, hz); if (te instanceof IWirelessNode) { setState(new StateAuthorizeNode((IWirelessNode) te)); } else if (te instanceof IWirelessMatrix) { started = true; IWirelessMatrix mat = (IWirelessMatrix) te; // Hard coded BlockMulti processing Block block = world.getBlock(hx, hy, hz); if (block instanceof BlockMulti) { mat = (IWirelessMatrix) ((BlockMulti) block).getOriginTile(te); if (mat == null) { setState(new StateNotifyAndQuit("e0")); return; } } final IWirelessMatrix mat2 = mat; startTransmitting(); Syncs.querySSID(mat, Future.create(ssid -> { if (current == StateStart.this) { if (ssid == null) { setState(new StateNotifyAndQuit("e0")); } else { setState(new StateAuthorize(mat2, ssid)); } } })); } else { setState(new StateNotifyAndQuit("e4")); } } } // S1 private class StateAuthorize extends State { final IWirelessMatrix matrix; final String ssid; String pass = ""; public StateAuthorize(IWirelessMatrix _matrix, String _ssid) { super(true); matrix = _matrix; ssid = _ssid; } @Override void handleDraw(double w, double h) { GL11.glPushMatrix(); GL11.glTranslated(w / 2 + 10, h / 2 - 10, 0); drawBox(0, 0, 140, 40); StringBuilder sb = new StringBuilder(); for (int i = 0; i < pass.length(); ++i) sb.append('*'); font.draw(String.format("SSID: %s", ssid), 10, 5, new FontOption(10, 0xffbfbfbf)); font.draw(String.format("PASS: %s", sb.toString()), 10, 15, new FontOption(10, 0xffffffff)); font.draw(local("s1_0"), 10, 25, new FontOption(10, 0xff30ffff)); GL11.glPopMatrix(); } @Override void handleClicking(MovingObjectPosition result) { // NO-OP } @Override void handleKeyInput(char ch, int kid) { if (ChatAllowedCharacters.isAllowedCharacter(ch)) { pass = pass + ch; } else if (kid == Keyboard.KEY_RETURN) { State state = new StateNotify("s1_1"); setState(state); state.startTransmitting(); Syncs.authorizeMatrix(matrix, pass, Future.create(result -> { if (state == FreqTransmitterUI.this.current) { if (result) { setState(new StateDoMatrixLink(matrix, pass)); } else { setState(new StateNotifyAndQuit("e1")); } } })); } else if (kid == Keyboard.KEY_BACK) { if (pass.length() > 0) pass = pass.substring(0, pass.length() - 1); } } } private class StateAuthorizeNode extends State { final IWirelessNode node; final String name; String pass = ""; public StateAuthorizeNode(IWirelessNode _node) { super(true); node = _node; name = node.getNodeName(); } @Override void handleDraw(double w, double h) { GL11.glPushMatrix(); GL11.glTranslated(w / 2 + 10, h / 2 - 10, 0); drawBox(0, 0, 140, 40); StringBuilder sb = new StringBuilder(); for (int i = 0; i < pass.length(); ++i) sb.append('*'); font.draw(String.format("NAME: %s", name), 10, 5, new FontOption(10, 0xffbfbfbf)); font.draw(String.format("PASS: %s", sb.toString()), 10, 15, new FontOption(10, 0xffffffff)); font.draw(local("s1_1"), 10, 25, new FontOption(10, 0xff30ffff)); GL11.glPopMatrix(); } @Override void handleClicking(MovingObjectPosition result) { // NO-OP } @Override void handleKeyInput(char ch, int kid) { if (ChatAllowedCharacters.isAllowedCharacter(ch)) { pass = pass + ch; } else if (kid == Keyboard.KEY_RETURN) { State state = new StateNotify("s1_1"); setState(state); state.startTransmitting(); Syncs.authorizeNode(node, pass, Future.create(result -> { if (state == FreqTransmitterUI.this.current) { if (result) { setState(new StateDoNodeLink(node, pass)); } else { setState(new StateNotifyAndQuit("e1")); } } })); } else if (kid == Keyboard.KEY_BACK) { if (pass.length() > 0) pass = pass.substring(0, pass.length() - 1); } } } //S2 private class StateDoMatrixLink extends State { final IWirelessMatrix matrix; final String pass; public StateDoMatrixLink(IWirelessMatrix _matrix, String _pass) { super(false); matrix = _matrix; pass = _pass; } @Override void handleDraw(double w, double h) { drawTextBox(local("s2_0"), w / 2 + 10, h / 2 + 10); } @Override void handleClicking(MovingObjectPosition result) { TileEntity tile; if (result == null || !((tile = world.getTileEntity(result.blockX, result.blockY, result.blockZ)) instanceof IWirelessNode)) { setState(new StateNotifyAndQuit("e4")); } else { IWirelessNode node = (IWirelessNode) tile; State state = new StateNotify("e5"); setState(state); state.startTransmitting(); Syncs.linkNodeToMatrix(node, matrix, pass, Future.create(res -> { if (FreqTransmitterUI.this.current == state) { if (res) { setState(new StateNotifyAndReturn("e6", StateDoMatrixLink.this)); } else { setState(new StateNotifyAndQuit("e2")); } } })); } } } //S3 private class StateDoNodeLink extends State { IWirelessNode node; String pass; public StateDoNodeLink(IWirelessNode _node, String _pass) { super(false); node = _node; pass = _pass; } @Override void handleDraw(double w, double h) { drawTextBox(local("s3_0"), w / 2 + 10, h / 2 + 10); } @Override void handleClicking(MovingObjectPosition r) { TileEntity tile; if (r == null || (tile = world.getTileEntity(r.blockX, r.blockY, r.blockZ)) == null) { setState(new StateNotifyAndQuit("e4")); return; } Block block = tile.getBlockType(); if (block instanceof BlockMulti) { tile = ((BlockMulti) block).getOriginTile(tile); } if (tile instanceof IWirelessUser) { State state = new StateNotify("e5"); setState(state); state.startTransmitting(); Syncs.linkUserToNode((IWirelessUser) tile, node, Future.create(res -> { if (FreqTransmitterUI.this.current == state) { if (res) { setState(new StateNotifyAndReturn("e6", StateDoNodeLink.this)); } else { setState(new StateNotifyAndQuit("e3")); } } })); } else { setState(new StateNotifyAndQuit("e4")); } } } }