iter = method.instructions.iterator();
+ while (iter.hasNext())
+ {
+ AbstractInsnNode insn = iter.next();
+ insns.add(insn);
+
+ if (insn instanceof TypeInsnNode && insn.getOpcode() == Opcodes.NEW && insns.getLast() != null)
+ {
+ TypeInsnNode typeNode = (TypeInsnNode)insn;
+ if (!found && (Obf.EntityRenderer.obf.equals(typeNode.desc) || Obf.EntityRenderer.ref.equals(typeNode.desc)))
+ {
+ LiteLoaderLogger.info("MinecraftTransformer found INIT injection point, this is good.");
+ found = true;
+
+ insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftTransformer.TWEAKCLASS, Obf.init.name, "()V", false));
+ insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftTransformer.TWEAKCLASS, Obf.postInit.name, "()V", false));
+ }
+ }
+
+ if (LiteLoaderTweaker.loadingBarEnabled())
+ {
+ if (insn instanceof LdcInsnNode)
+ {
+ LdcInsnNode ldcInsn = (LdcInsnNode)insn;
+ if ("textures/blocks".equals(ldcInsn.cst))
+ {
+ insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Obf.LoadingBar.ref, "initTextures", "()V", false));
+ }
+ }
+
+ insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Obf.LoadingBar.ref, "incrementProgress", "()V", false));
+ }
+ }
+
+ method.instructions = insns;
+
+ if (!found) LiteLoaderLogger.severe("MinecraftTransformer failed to find INIT injection point, the game will probably crash pretty soon.");
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/client/util/PrivateFieldsClient.java b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/PrivateFieldsClient.java
new file mode 100644
index 00000000..d8529eee
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/PrivateFieldsClient.java
@@ -0,0 +1,22 @@
+package com.mumfrey.liteloader.client.util;
+
+import java.util.Map;
+
+import com.mumfrey.liteloader.core.runtime.Obf;
+import com.mumfrey.liteloader.util.PrivateFields;
+
+import net.minecraft.tileentity.TileEntity;
+
+@SuppressWarnings("rawtypes")
+public final class PrivateFieldsClient extends PrivateFields
+{
+ private PrivateFieldsClient(Class
owner, Obf obf)
+ {
+ super(owner, obf);
+ }
+
+ // CHECKSTYLE:OFF
+
+ public static final PrivateFieldsClient tileEntityNameToClassMap = new PrivateFieldsClient(TileEntity.class, Obf.tileEntityNameToClassMap);
+ public static final PrivateFieldsClient tileEntityClassToNameMap = new PrivateFieldsClient(TileEntity.class, Obf.tileEntityClassToNameMap);
+}
\ No newline at end of file
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconAbsolute.java b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconAbsolute.java
new file mode 100644
index 00000000..1f01788c
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconAbsolute.java
@@ -0,0 +1,128 @@
+package com.mumfrey.liteloader.client.util.render;
+
+import com.mumfrey.liteloader.util.render.IconTextured;
+
+import net.minecraft.util.ResourceLocation;
+
+public class IconAbsolute implements IconTextured
+{
+ private ResourceLocation textureResource;
+
+ private String displayText;
+
+ private int texMapSize = 256;
+
+ private int width;
+ private int height;
+
+ private int uPos, vPos;
+
+ private float uCoord;
+ private float uCoord2;
+ private float vCoord;
+ private float vCoord2;
+
+ public IconAbsolute(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord, float uCoord2,
+ float vCoord2)
+ {
+ this(textureResource, displayText, width, height, uCoord, vCoord, uCoord2, vCoord2, 256);
+ }
+
+ public IconAbsolute(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord, float uCoord2,
+ float vCoord2, int texMapSize)
+ {
+ this.textureResource = textureResource;
+ this.displayText = displayText;
+ this.width = width;
+ this.height = height;
+
+ this.uPos = (int)uCoord;
+ this.vPos = (int)vCoord;
+
+ this.texMapSize = texMapSize;
+ this.uCoord = uCoord / this.texMapSize;
+ this.uCoord2 = uCoord2 / this.texMapSize;
+ this.vCoord = vCoord / this.texMapSize;
+ this.vCoord2 = vCoord2 / this.texMapSize;
+ }
+
+ @Override
+ public String getDisplayText()
+ {
+ return this.displayText;
+ }
+
+ @Override
+ public ResourceLocation getTextureResource()
+ {
+ return this.textureResource;
+ }
+
+ @Override
+ public int getIconWidth()
+ {
+ return this.width;
+ }
+
+ @Override
+ public int getIconHeight()
+ {
+ return this.height;
+ }
+
+ @Override
+ public int getUPos()
+ {
+ return this.uPos;
+ }
+
+ @Override
+ public int getVPos()
+ {
+ return this.vPos;
+ }
+
+ @Override
+ public float getMinU()
+ {
+ return this.uCoord;
+ }
+
+ @Override
+ public float getMaxU()
+ {
+ return this.uCoord2 - Float.MIN_VALUE;
+ }
+
+ @Override
+ public float getInterpolatedU(double slice)
+ {
+ float uSize = this.uCoord2 - this.uCoord;
+ return this.uCoord + uSize * ((float)slice / 16.0F) - Float.MIN_VALUE;
+ }
+
+ @Override
+ public float getMinV()
+ {
+ return this.vCoord;
+ }
+
+ @Override
+ public float getMaxV()
+ {
+ return this.vCoord2 - Float.MIN_VALUE;
+ }
+
+ @Override
+ public float getInterpolatedV(double slice)
+ {
+ float vSize = this.vCoord2 - this.vCoord;
+ return this.vCoord + vSize * ((float)slice / 16.0F) - Float.MIN_VALUE;
+ }
+
+ @Override
+ public String getIconName()
+ {
+ return this.displayText;
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconAbsoluteClickable.java b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconAbsoluteClickable.java
new file mode 100644
index 00000000..26fbb032
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconAbsoluteClickable.java
@@ -0,0 +1,20 @@
+package com.mumfrey.liteloader.client.util.render;
+
+import net.minecraft.util.ResourceLocation;
+
+import com.mumfrey.liteloader.util.render.IconClickable;
+
+public abstract class IconAbsoluteClickable extends IconAbsolute implements IconClickable
+{
+ public IconAbsoluteClickable(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord,
+ float uCoord2, float vCoord2)
+ {
+ super(textureResource, displayText, width, height, uCoord, vCoord, uCoord2, vCoord2);
+ }
+
+ public IconAbsoluteClickable(ResourceLocation textureResource, String displayText, int width, int height, float uCoord, float vCoord,
+ float uCoord2, float vCoord2, int texMapSize)
+ {
+ super(textureResource, displayText, width, height, uCoord, vCoord, uCoord2, vCoord2, texMapSize);
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconTiled.java b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconTiled.java
new file mode 100644
index 00000000..83cf2a13
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/client/util/render/IconTiled.java
@@ -0,0 +1,140 @@
+package com.mumfrey.liteloader.client.util.render;
+
+import com.mumfrey.liteloader.util.render.Icon;
+
+import net.minecraft.util.ResourceLocation;
+
+public class IconTiled implements Icon
+{
+ private ResourceLocation textureResource;
+
+ protected int iconID;
+
+ protected int iconU;
+ protected int iconV;
+ private int width;
+ private int height;
+ private float uCoord;
+ private float uCoord2;
+ private float vCoord;
+ private float vCoord2;
+
+ private int textureWidth, textureHeight;
+
+ public IconTiled(ResourceLocation textureResource, int id)
+ {
+ this(textureResource, id, 16);
+ }
+
+ public IconTiled(ResourceLocation textureResource, int id, int iconSize)
+ {
+ this(textureResource, id, iconSize, 0);
+ }
+
+ public IconTiled(ResourceLocation textureResource, int id, int iconSize, int yOffset)
+ {
+ this(textureResource, id, iconSize, (id % (256 / iconSize)) * iconSize, (id / (256 / iconSize)) * iconSize + yOffset);
+ }
+
+ public IconTiled(ResourceLocation textureResource, int id, int iconSize, int iconU, int iconV)
+ {
+ this(textureResource, id, iconU, iconV, iconSize, iconSize, 256, 256);
+ }
+
+ public IconTiled(ResourceLocation textureResource, int id, int iconU, int iconV, int width, int height, int textureWidth, int textureHeight)
+ {
+ this.iconID = id;
+ this.textureResource = textureResource;
+
+ this.textureWidth = textureWidth;
+ this.textureHeight = textureHeight;
+
+ this.width = width;
+ this.height = height;
+
+ this.init(iconU, iconV);
+ }
+
+ protected void init(int iconU, int iconV)
+ {
+ this.iconU = iconU;
+ this.iconV = iconV;
+
+ this.uCoord = (float)iconU / (float)this.textureWidth;
+ this.uCoord2 = (float)(iconU + this.width) / (float)this.textureWidth;
+ this.vCoord = (float)iconV / (float)this.textureHeight;
+ this.vCoord2 = (float)(iconV + this.height) / (float)this.textureHeight;
+ }
+
+ public ResourceLocation getTextureResource()
+ {
+ return this.textureResource;
+ }
+
+ public int getIconID()
+ {
+ return this.iconID;
+ }
+
+ public void setIconID(int id)
+ {
+ this.iconID = id;
+ this.init((id % 16) * 16, (id / 16) * 16);
+ }
+
+ @Override
+ public int getIconWidth()
+ {
+ return this.width;
+ }
+
+ @Override
+ public int getIconHeight()
+ {
+ return this.height;
+ }
+
+ @Override
+ public float getMinU()
+ {
+ return this.uCoord;
+ }
+
+ @Override
+ public float getMaxU()
+ {
+ return this.uCoord2 - Float.MIN_VALUE;
+ }
+
+ @Override
+ public float getInterpolatedU(double slice)
+ {
+ float uSize = this.uCoord2 - this.uCoord;
+ return this.uCoord + uSize * ((float)slice / 16.0F) - Float.MIN_VALUE;
+ }
+
+ @Override
+ public float getMinV()
+ {
+ return this.vCoord;
+ }
+
+ @Override
+ public float getMaxV()
+ {
+ return this.vCoord2 - Float.MIN_VALUE;
+ }
+
+ @Override
+ public float getInterpolatedV(double slice)
+ {
+ float vSize = this.vCoord2 - this.vCoord;
+ return this.vCoord + vSize * ((float)slice / 16.0F) - Float.MIN_VALUE;
+ }
+
+ @Override
+ public String getIconName()
+ {
+ return this.textureResource + "_" + this.iconID;
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/gl/GL.java b/liteloader/src/client/java/com/mumfrey/liteloader/gl/GL.java
new file mode 100644
index 00000000..33d83415
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/gl/GL.java
@@ -0,0 +1,1296 @@
+package com.mumfrey.liteloader.gl;
+
+import java.nio.ByteBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.GlStateManager.TexGen;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLU;
+
+/**
+ * Convenience class for working with Mojang's GLStateManager:
+ *
+ * It would be pretty tolerable to work with GLStateManager as a static
+ * import were it not for the fact that you still need to import the GL
+ * namespaces themselves from LWJGL in order to get the constants, and also have
+ * to deal with the fact that GLStateManager's methods don't have "gl-style"
+ * names, making it annoying to work with. This class is designed to function as
+ * an adapter to allow changeover to be more painless. Using this class means
+ * that the following code:
+ *
+ * glEnable(GL_BLEND);
+ * glAlphaFunc(GL_GREATER, 0.0F);
+ *
+ * becomes:
+ *
+ * glEnableBlend();
+ * glAlphaFunc(GL_GREATER, 0.0F);
+ *
+ * Notice that the glAlphaFunc invocation remains unchanged, and the
+ * glEnable call simply gets replaced with a logical equivalent which
+ * invokes the GLStateManager method behind the scenes.
+ *
+ * To use this class, simply replace existing static imports in your classes
+ * with this single static import, then change glEnable and
+ * glDisable calls accordingly.
+ *
+ * @author Adam Mummery-Smith
+ */
+public class GL
+{
+ // GL11
+ public static final int GL_ACCUM = 0x100;
+ public static final int GL_LOAD = 0x101;
+ public static final int GL_RETURN = 0x102;
+ public static final int GL_MULT = 0x103;
+ public static final int GL_ADD = 0x104;
+ public static final int GL_NEVER = 0x200;
+ public static final int GL_LESS = 0x201;
+ public static final int GL_EQUAL = 0x202;
+ public static final int GL_LEQUAL = 0x203;
+ public static final int GL_GREATER = 0x204;
+ public static final int GL_NOTEQUAL = 0x205;
+ public static final int GL_GEQUAL = 0x206;
+ public static final int GL_ALWAYS = 0x207;
+ public static final int GL_CURRENT_BIT = 0x1;
+ public static final int GL_POINT_BIT = 0x2;
+ public static final int GL_LINE_BIT = 0x4;
+ public static final int GL_POLYGON_BIT = 0x8;
+ public static final int GL_POLYGON_STIPPLE_BIT = 0x10;
+ public static final int GL_PIXEL_MODE_BIT = 0x20;
+ public static final int GL_LIGHTING_BIT = 0x40;
+ public static final int GL_FOG_BIT = 0x80;
+ public static final int GL_DEPTH_BUFFER_BIT = 0x100;
+ public static final int GL_ACCUM_BUFFER_BIT = 0x200;
+ public static final int GL_STENCIL_BUFFER_BIT = 0x400;
+ public static final int GL_VIEWPORT_BIT = 0x800;
+ public static final int GL_TRANSFORM_BIT = 0x1000;
+ public static final int GL_ENABLE_BIT = 0x2000;
+ public static final int GL_COLOR_BUFFER_BIT = 0x4000;
+ public static final int GL_HINT_BIT = 0x8000;
+ public static final int GL_EVAL_BIT = 0x10000;
+ public static final int GL_LIST_BIT = 0x20000;
+ public static final int GL_TEXTURE_BIT = 0x40000;
+ public static final int GL_SCISSOR_BIT = 0x80000;
+ public static final int GL_ALL_ATTRIB_BITS = 0xfffff;
+ public static final int GL_POINTS = 0x0;
+ public static final int GL_LINES = 0x1;
+ public static final int GL_LINE_LOOP = 0x2;
+ public static final int GL_LINE_STRIP = 0x3;
+ public static final int GL_TRIANGLES = 0x4;
+ public static final int GL_TRIANGLE_STRIP = 0x5;
+ public static final int GL_TRIANGLE_FAN = 0x6;
+ public static final int GL_QUADS = 0x7;
+ public static final int GL_QUAD_STRIP = 0x8;
+ public static final int GL_POLYGON = 0x9;
+ public static final int GL_ZERO = 0x0;
+ public static final int GL_ONE = 0x1;
+ public static final int GL_SRC_COLOR = 0x300;
+ public static final int GL_ONE_MINUS_SRC_COLOR = 0x301;
+ public static final int GL_SRC_ALPHA = 0x302;
+ public static final int GL_ONE_MINUS_SRC_ALPHA = 0x303;
+ public static final int GL_DST_ALPHA = 0x304;
+ public static final int GL_ONE_MINUS_DST_ALPHA = 0x305;
+ public static final int GL_DST_COLOR = 0x306;
+ public static final int GL_ONE_MINUS_DST_COLOR = 0x307;
+ public static final int GL_SRC_ALPHA_SATURATE = 0x308;
+ public static final int GL_CONSTANT_COLOR = 0x8001;
+ public static final int GL_ONE_MINUS_CONSTANT_COLOR = 0x8002;
+ public static final int GL_CONSTANT_ALPHA = 0x8003;
+ public static final int GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004;
+ public static final int GL_TRUE = 0x1;
+ public static final int GL_FALSE = 0x0;
+ public static final int GL_CLIP_PLANE0 = 0x3000;
+ public static final int GL_CLIP_PLANE1 = 0x3001;
+ public static final int GL_CLIP_PLANE2 = 0x3002;
+ public static final int GL_CLIP_PLANE3 = 0x3003;
+ public static final int GL_CLIP_PLANE4 = 0x3004;
+ public static final int GL_CLIP_PLANE5 = 0x3005;
+ public static final int GL_BYTE = 0x1400;
+ public static final int GL_UNSIGNED_BYTE = 0x1401;
+ public static final int GL_SHORT = 0x1402;
+ public static final int GL_UNSIGNED_SHORT = 0x1403;
+ public static final int GL_INT = 0x1404;
+ public static final int GL_UNSIGNED_INT = 0x1405;
+ public static final int GL_FLOAT = 0x1406;
+ public static final int GL_2_BYTES = 0x1407;
+ public static final int GL_3_BYTES = 0x1408;
+ public static final int GL_4_BYTES = 0x1409;
+ public static final int GL_DOUBLE = 0x140a;
+ public static final int GL_NONE = 0x0;
+ public static final int GL_FRONT_LEFT = 0x400;
+ public static final int GL_FRONT_RIGHT = 0x401;
+ public static final int GL_BACK_LEFT = 0x402;
+ public static final int GL_BACK_RIGHT = 0x403;
+ public static final int GL_FRONT = 0x404;
+ public static final int GL_BACK = 0x405;
+ public static final int GL_LEFT = 0x406;
+ public static final int GL_RIGHT = 0x407;
+ public static final int GL_FRONT_AND_BACK = 0x408;
+ public static final int GL_AUX0 = 0x409;
+ public static final int GL_AUX1 = 0x40a;
+ public static final int GL_AUX2 = 0x40b;
+ public static final int GL_AUX3 = 0x40c;
+ public static final int GL_NO_ERROR = 0x0;
+ public static final int GL_INVALID_ENUM = 0x500;
+ public static final int GL_INVALID_VALUE = 0x501;
+ public static final int GL_INVALID_OPERATION = 0x502;
+ public static final int GL_STACK_OVERFLOW = 0x503;
+ public static final int GL_STACK_UNDERFLOW = 0x504;
+ public static final int GL_OUT_OF_MEMORY = 0x505;
+ public static final int GL_2D = 0x600;
+ public static final int GL_3D = 0x601;
+ public static final int GL_3D_COLOR = 0x602;
+ public static final int GL_3D_COLOR_TEXTURE = 0x603;
+ public static final int GL_4D_COLOR_TEXTURE = 0x604;
+ public static final int GL_PASS_THROUGH_TOKEN = 0x700;
+ public static final int GL_POINT_TOKEN = 0x701;
+ public static final int GL_LINE_TOKEN = 0x702;
+ public static final int GL_POLYGON_TOKEN = 0x703;
+ public static final int GL_BITMAP_TOKEN = 0x704;
+ public static final int GL_DRAW_PIXEL_TOKEN = 0x705;
+ public static final int GL_COPY_PIXEL_TOKEN = 0x706;
+ public static final int GL_LINE_RESET_TOKEN = 0x707;
+ public static final int GL_EXP = 0x800;
+ public static final int GL_EXP2 = 0x801;
+ public static final int GL_CW = 0x900;
+ public static final int GL_CCW = 0x901;
+ public static final int GL_COEFF = 0xa00;
+ public static final int GL_ORDER = 0xa01;
+ public static final int GL_DOMAIN = 0xa02;
+ public static final int GL_CURRENT_COLOR = 0xb00;
+ public static final int GL_CURRENT_INDEX = 0xb01;
+ public static final int GL_CURRENT_NORMAL = 0xb02;
+ public static final int GL_CURRENT_TEXTURE_COORDS = 0xb03;
+ public static final int GL_CURRENT_RASTER_COLOR = 0xb04;
+ public static final int GL_CURRENT_RASTER_INDEX = 0xb05;
+ public static final int GL_CURRENT_RASTER_TEXTURE_COORDS = 0xb06;
+ public static final int GL_CURRENT_RASTER_POSITION = 0xb07;
+ public static final int GL_CURRENT_RASTER_POSITION_VALID = 0xb08;
+ public static final int GL_CURRENT_RASTER_DISTANCE = 0xb09;
+ public static final int GL_POINT_SMOOTH = 0xb10;
+ public static final int GL_POINT_SIZE = 0xb11;
+ public static final int GL_POINT_SIZE_RANGE = 0xb12;
+ public static final int GL_POINT_SIZE_GRANULARITY = 0xb13;
+ public static final int GL_LINE_SMOOTH = 0xb20;
+ public static final int GL_LINE_WIDTH = 0xb21;
+ public static final int GL_LINE_WIDTH_RANGE = 0xb22;
+ public static final int GL_LINE_WIDTH_GRANULARITY = 0xb23;
+ public static final int GL_LINE_STIPPLE = 0xb24;
+ public static final int GL_LINE_STIPPLE_PATTERN = 0xb25;
+ public static final int GL_LINE_STIPPLE_REPEAT = 0xb26;
+ public static final int GL_LIST_MODE = 0xb30;
+ public static final int GL_MAX_LIST_NESTING = 0xb31;
+ public static final int GL_LIST_BASE = 0xb32;
+ public static final int GL_LIST_INDEX = 0xb33;
+ public static final int GL_POLYGON_MODE = 0xb40;
+ public static final int GL_POLYGON_SMOOTH = 0xb41;
+ public static final int GL_POLYGON_STIPPLE = 0xb42;
+ public static final int GL_EDGE_FLAG = 0xb43;
+ public static final int GL_CULL_FACE = 0xb44;
+ public static final int GL_CULL_FACE_MODE = 0xb45;
+ public static final int GL_FRONT_FACE = 0xb46;
+ public static final int GL_LIGHTING = 0xb50;
+ public static final int GL_LIGHT_MODEL_LOCAL_VIEWER = 0xb51;
+ public static final int GL_LIGHT_MODEL_TWO_SIDE = 0xb52;
+ public static final int GL_LIGHT_MODEL_AMBIENT = 0xb53;
+ public static final int GL_SHADE_MODEL = 0xb54;
+ public static final int GL_COLOR_MATERIAL_FACE = 0xb55;
+ public static final int GL_COLOR_MATERIAL_PARAMETER = 0xb56;
+ public static final int GL_COLOR_MATERIAL = 0xb57;
+ public static final int GL_FOG = 0xb60;
+ public static final int GL_FOG_INDEX = 0xb61;
+ public static final int GL_FOG_DENSITY = 0xb62;
+ public static final int GL_FOG_START = 0xb63;
+ public static final int GL_FOG_END = 0xb64;
+ public static final int GL_FOG_MODE = 0xb65;
+ public static final int GL_FOG_COLOR = 0xb66;
+ public static final int GL_DEPTH_RANGE = 0xb70;
+ public static final int GL_DEPTH_TEST = 0xb71;
+ public static final int GL_DEPTH_WRITEMASK = 0xb72;
+ public static final int GL_DEPTH_CLEAR_VALUE = 0xb73;
+ public static final int GL_DEPTH_FUNC = 0xb74;
+ public static final int GL_ACCUM_CLEAR_VALUE = 0xb80;
+ public static final int GL_STENCIL_TEST = 0xb90;
+ public static final int GL_STENCIL_CLEAR_VALUE = 0xb91;
+ public static final int GL_STENCIL_FUNC = 0xb92;
+ public static final int GL_STENCIL_VALUE_MASK = 0xb93;
+ public static final int GL_STENCIL_FAIL = 0xb94;
+ public static final int GL_STENCIL_PASS_DEPTH_FAIL = 0xb95;
+ public static final int GL_STENCIL_PASS_DEPTH_PASS = 0xb96;
+ public static final int GL_STENCIL_REF = 0xb97;
+ public static final int GL_STENCIL_WRITEMASK = 0xb98;
+ public static final int GL_MATRIX_MODE = 0xba0;
+ public static final int GL_NORMALIZE = 0xba1;
+ public static final int GL_VIEWPORT = 0xba2;
+ public static final int GL_MODELVIEW_STACK_DEPTH = 0xba3;
+ public static final int GL_PROJECTION_STACK_DEPTH = 0xba4;
+ public static final int GL_TEXTURE_STACK_DEPTH = 0xba5;
+ public static final int GL_MODELVIEW_MATRIX = 0xba6;
+ public static final int GL_PROJECTION_MATRIX = 0xba7;
+ public static final int GL_TEXTURE_MATRIX = 0xba8;
+ public static final int GL_ATTRIB_STACK_DEPTH = 0xbb0;
+ public static final int GL_CLIENT_ATTRIB_STACK_DEPTH = 0xbb1;
+ public static final int GL_ALPHA_TEST = 0xbc0;
+ public static final int GL_ALPHA_TEST_FUNC = 0xbc1;
+ public static final int GL_ALPHA_TEST_REF = 0xbc2;
+ public static final int GL_DITHER = 0xbd0;
+ public static final int GL_BLEND_DST = 0xbe0;
+ public static final int GL_BLEND_SRC = 0xbe1;
+ public static final int GL_BLEND = 0xbe2;
+ public static final int GL_LOGIC_OP_MODE = 0xbf0;
+ public static final int GL_INDEX_LOGIC_OP = 0xbf1;
+ public static final int GL_COLOR_LOGIC_OP = 0xbf2;
+ public static final int GL_AUX_BUFFERS = 0xc00;
+ public static final int GL_DRAW_BUFFER = 0xc01;
+ public static final int GL_READ_BUFFER = 0xc02;
+ public static final int GL_SCISSOR_BOX = 0xc10;
+ public static final int GL_SCISSOR_TEST = 0xc11;
+ public static final int GL_INDEX_CLEAR_VALUE = 0xc20;
+ public static final int GL_INDEX_WRITEMASK = 0xc21;
+ public static final int GL_COLOR_CLEAR_VALUE = 0xc22;
+ public static final int GL_COLOR_WRITEMASK = 0xc23;
+ public static final int GL_INDEX_MODE = 0xc30;
+ public static final int GL_RGBA_MODE = 0xc31;
+ public static final int GL_DOUBLEBUFFER = 0xc32;
+ public static final int GL_STEREO = 0xc33;
+ public static final int GL_RENDER_MODE = 0xc40;
+ public static final int GL_PERSPECTIVE_CORRECTION_HINT = 0xc50;
+ public static final int GL_POINT_SMOOTH_HINT = 0xc51;
+ public static final int GL_LINE_SMOOTH_HINT = 0xc52;
+ public static final int GL_POLYGON_SMOOTH_HINT = 0xc53;
+ public static final int GL_FOG_HINT = 0xc54;
+ public static final int GL_TEXTURE_GEN_S = 0xc60;
+ public static final int GL_TEXTURE_GEN_T = 0xc61;
+ public static final int GL_TEXTURE_GEN_R = 0xc62;
+ public static final int GL_TEXTURE_GEN_Q = 0xc63;
+ public static final int GL_PIXEL_MAP_I_TO_I = 0xc70;
+ public static final int GL_PIXEL_MAP_S_TO_S = 0xc71;
+ public static final int GL_PIXEL_MAP_I_TO_R = 0xc72;
+ public static final int GL_PIXEL_MAP_I_TO_G = 0xc73;
+ public static final int GL_PIXEL_MAP_I_TO_B = 0xc74;
+ public static final int GL_PIXEL_MAP_I_TO_A = 0xc75;
+ public static final int GL_PIXEL_MAP_R_TO_R = 0xc76;
+ public static final int GL_PIXEL_MAP_G_TO_G = 0xc77;
+ public static final int GL_PIXEL_MAP_B_TO_B = 0xc78;
+ public static final int GL_PIXEL_MAP_A_TO_A = 0xc79;
+ public static final int GL_PIXEL_MAP_I_TO_I_SIZE = 0xcb0;
+ public static final int GL_PIXEL_MAP_S_TO_S_SIZE = 0xcb1;
+ public static final int GL_PIXEL_MAP_I_TO_R_SIZE = 0xcb2;
+ public static final int GL_PIXEL_MAP_I_TO_G_SIZE = 0xcb3;
+ public static final int GL_PIXEL_MAP_I_TO_B_SIZE = 0xcb4;
+ public static final int GL_PIXEL_MAP_I_TO_A_SIZE = 0xcb5;
+ public static final int GL_PIXEL_MAP_R_TO_R_SIZE = 0xcb6;
+ public static final int GL_PIXEL_MAP_G_TO_G_SIZE = 0xcb7;
+ public static final int GL_PIXEL_MAP_B_TO_B_SIZE = 0xcb8;
+ public static final int GL_PIXEL_MAP_A_TO_A_SIZE = 0xcb9;
+ public static final int GL_UNPACK_SWAP_BYTES = 0xcf0;
+ public static final int GL_UNPACK_LSB_FIRST = 0xcf1;
+ public static final int GL_UNPACK_ROW_LENGTH = 0xcf2;
+ public static final int GL_UNPACK_SKIP_ROWS = 0xcf3;
+ public static final int GL_UNPACK_SKIP_PIXELS = 0xcf4;
+ public static final int GL_UNPACK_ALIGNMENT = 0xcf5;
+ public static final int GL_PACK_SWAP_BYTES = 0xd00;
+ public static final int GL_PACK_LSB_FIRST = 0xd01;
+ public static final int GL_PACK_ROW_LENGTH = 0xd02;
+ public static final int GL_PACK_SKIP_ROWS = 0xd03;
+ public static final int GL_PACK_SKIP_PIXELS = 0xd04;
+ public static final int GL_PACK_ALIGNMENT = 0xd05;
+ public static final int GL_MAP_COLOR = 0xd10;
+ public static final int GL_MAP_STENCIL = 0xd11;
+ public static final int GL_INDEX_SHIFT = 0xd12;
+ public static final int GL_INDEX_OFFSET = 0xd13;
+ public static final int GL_RED_SCALE = 0xd14;
+ public static final int GL_RED_BIAS = 0xd15;
+ public static final int GL_ZOOM_X = 0xd16;
+ public static final int GL_ZOOM_Y = 0xd17;
+ public static final int GL_GREEN_SCALE = 0xd18;
+ public static final int GL_GREEN_BIAS = 0xd19;
+ public static final int GL_BLUE_SCALE = 0xd1a;
+ public static final int GL_BLUE_BIAS = 0xd1b;
+ public static final int GL_ALPHA_SCALE = 0xd1c;
+ public static final int GL_ALPHA_BIAS = 0xd1d;
+ public static final int GL_DEPTH_SCALE = 0xd1e;
+ public static final int GL_DEPTH_BIAS = 0xd1f;
+ public static final int GL_MAX_EVAL_ORDER = 0xd30;
+ public static final int GL_MAX_LIGHTS = 0xd31;
+ public static final int GL_MAX_CLIP_PLANES = 0xd32;
+ public static final int GL_MAX_TEXTURE_SIZE = 0xd33;
+ public static final int GL_MAX_PIXEL_MAP_TABLE = 0xd34;
+ public static final int GL_MAX_ATTRIB_STACK_DEPTH = 0xd35;
+ public static final int GL_MAX_MODELVIEW_STACK_DEPTH = 0xd36;
+ public static final int GL_MAX_NAME_STACK_DEPTH = 0xd37;
+ public static final int GL_MAX_PROJECTION_STACK_DEPTH = 0xd38;
+ public static final int GL_MAX_TEXTURE_STACK_DEPTH = 0xd39;
+ public static final int GL_MAX_VIEWPORT_DIMS = 0xd3a;
+ public static final int GL_MAX_CLIENT_ATTRIB_STACK_DEPTH = 0xd3b;
+ public static final int GL_SUBPIXEL_BITS = 0xd50;
+ public static final int GL_INDEX_BITS = 0xd51;
+ public static final int GL_RED_BITS = 0xd52;
+ public static final int GL_GREEN_BITS = 0xd53;
+ public static final int GL_BLUE_BITS = 0xd54;
+ public static final int GL_ALPHA_BITS = 0xd55;
+ public static final int GL_DEPTH_BITS = 0xd56;
+ public static final int GL_STENCIL_BITS = 0xd57;
+ public static final int GL_ACCUM_RED_BITS = 0xd58;
+ public static final int GL_ACCUM_GREEN_BITS = 0xd59;
+ public static final int GL_ACCUM_BLUE_BITS = 0xd5a;
+ public static final int GL_ACCUM_ALPHA_BITS = 0xd5b;
+ public static final int GL_NAME_STACK_DEPTH = 0xd70;
+ public static final int GL_AUTO_NORMAL = 0xd80;
+ public static final int GL_MAP1_COLOR_4 = 0xd90;
+ public static final int GL_MAP1_INDEX = 0xd91;
+ public static final int GL_MAP1_NORMAL = 0xd92;
+ public static final int GL_MAP1_TEXTURE_COORD_1 = 0xd93;
+ public static final int GL_MAP1_TEXTURE_COORD_2 = 0xd94;
+ public static final int GL_MAP1_TEXTURE_COORD_3 = 0xd95;
+ public static final int GL_MAP1_TEXTURE_COORD_4 = 0xd96;
+ public static final int GL_MAP1_VERTEX_3 = 0xd97;
+ public static final int GL_MAP1_VERTEX_4 = 0xd98;
+ public static final int GL_MAP2_COLOR_4 = 0xdb0;
+ public static final int GL_MAP2_INDEX = 0xdb1;
+ public static final int GL_MAP2_NORMAL = 0xdb2;
+ public static final int GL_MAP2_TEXTURE_COORD_1 = 0xdb3;
+ public static final int GL_MAP2_TEXTURE_COORD_2 = 0xdb4;
+ public static final int GL_MAP2_TEXTURE_COORD_3 = 0xdb5;
+ public static final int GL_MAP2_TEXTURE_COORD_4 = 0xdb6;
+ public static final int GL_MAP2_VERTEX_3 = 0xdb7;
+ public static final int GL_MAP2_VERTEX_4 = 0xdb8;
+ public static final int GL_MAP1_GRID_DOMAIN = 0xdd0;
+ public static final int GL_MAP1_GRID_SEGMENTS = 0xdd1;
+ public static final int GL_MAP2_GRID_DOMAIN = 0xdd2;
+ public static final int GL_MAP2_GRID_SEGMENTS = 0xdd3;
+ public static final int GL_TEXTURE_1D = 0xde0;
+ public static final int GL_TEXTURE_2D = 0xde1;
+ public static final int GL_FEEDBACK_BUFFER_POINTER = 0xdf0;
+ public static final int GL_FEEDBACK_BUFFER_SIZE = 0xdf1;
+ public static final int GL_FEEDBACK_BUFFER_TYPE = 0xdf2;
+ public static final int GL_SELECTION_BUFFER_POINTER = 0xdf3;
+ public static final int GL_SELECTION_BUFFER_SIZE = 0xdf4;
+ public static final int GL_TEXTURE_WIDTH = 0x1000;
+ public static final int GL_TEXTURE_HEIGHT = 0x1001;
+ public static final int GL_TEXTURE_INTERNAL_FORMAT = 0x1003;
+ public static final int GL_TEXTURE_BORDER_COLOR = 0x1004;
+ public static final int GL_TEXTURE_BORDER = 0x1005;
+ public static final int GL_DONT_CARE = 0x1100;
+ public static final int GL_FASTEST = 0x1101;
+ public static final int GL_NICEST = 0x1102;
+ public static final int GL_LIGHT0 = 0x4000;
+ public static final int GL_LIGHT1 = 0x4001;
+ public static final int GL_LIGHT2 = 0x4002;
+ public static final int GL_LIGHT3 = 0x4003;
+ public static final int GL_LIGHT4 = 0x4004;
+ public static final int GL_LIGHT5 = 0x4005;
+ public static final int GL_LIGHT6 = 0x4006;
+ public static final int GL_LIGHT7 = 0x4007;
+ public static final int GL_AMBIENT = 0x1200;
+ public static final int GL_DIFFUSE = 0x1201;
+ public static final int GL_SPECULAR = 0x1202;
+ public static final int GL_POSITION = 0x1203;
+ public static final int GL_SPOT_DIRECTION = 0x1204;
+ public static final int GL_SPOT_EXPONENT = 0x1205;
+ public static final int GL_SPOT_CUTOFF = 0x1206;
+ public static final int GL_CONSTANT_ATTENUATION = 0x1207;
+ public static final int GL_LINEAR_ATTENUATION = 0x1208;
+ public static final int GL_QUADRATIC_ATTENUATION = 0x1209;
+ public static final int GL_COMPILE = 0x1300;
+ public static final int GL_COMPILE_AND_EXECUTE = 0x1301;
+ public static final int GL_CLEAR = 0x1500;
+ public static final int GL_AND = 0x1501;
+ public static final int GL_AND_REVERSE = 0x1502;
+ public static final int GL_COPY = 0x1503;
+ public static final int GL_AND_INVERTED = 0x1504;
+ public static final int GL_NOOP = 0x1505;
+ public static final int GL_XOR = 0x1506;
+ public static final int GL_OR = 0x1507;
+ public static final int GL_NOR = 0x1508;
+ public static final int GL_EQUIV = 0x1509;
+ public static final int GL_INVERT = 0x150a;
+ public static final int GL_OR_REVERSE = 0x150b;
+ public static final int GL_COPY_INVERTED = 0x150c;
+ public static final int GL_OR_INVERTED = 0x150d;
+ public static final int GL_NAND = 0x150e;
+ public static final int GL_SET = 0x150f;
+ public static final int GL_EMISSION = 0x1600;
+ public static final int GL_SHININESS = 0x1601;
+ public static final int GL_AMBIENT_AND_DIFFUSE = 0x1602;
+ public static final int GL_COLOR_INDEXES = 0x1603;
+ public static final int GL_MODELVIEW = 0x1700;
+ public static final int GL_PROJECTION = 0x1701;
+ public static final int GL_TEXTURE = 0x1702;
+ public static final int GL_COLOR = 0x1800;
+ public static final int GL_DEPTH = 0x1801;
+ public static final int GL_STENCIL = 0x1802;
+ public static final int GL_COLOR_INDEX = 0x1900;
+ public static final int GL_STENCIL_INDEX = 0x1901;
+ public static final int GL_DEPTH_COMPONENT = 0x1902;
+ public static final int GL_RED = 0x1903;
+ public static final int GL_GREEN = 0x1904;
+ public static final int GL_BLUE = 0x1905;
+ public static final int GL_ALPHA = 0x1906;
+ public static final int GL_RGB = 0x1907;
+ public static final int GL_RGBA = 0x1908;
+ public static final int GL_LUMINANCE = 0x1909;
+ public static final int GL_LUMINANCE_ALPHA = 0x190a;
+ public static final int GL_BITMAP = 0x1a00;
+ public static final int GL_POINT = 0x1b00;
+ public static final int GL_LINE = 0x1b01;
+ public static final int GL_FILL = 0x1b02;
+ public static final int GL_RENDER = 0x1c00;
+ public static final int GL_FEEDBACK = 0x1c01;
+ public static final int GL_SELECT = 0x1c02;
+ public static final int GL_FLAT = 0x1d00;
+ public static final int GL_SMOOTH = 0x1d01;
+ public static final int GL_KEEP = 0x1e00;
+ public static final int GL_REPLACE = 0x1e01;
+ public static final int GL_INCR = 0x1e02;
+ public static final int GL_DECR = 0x1e03;
+ public static final int GL_VENDOR = 0x1f00;
+ public static final int GL_RENDERER = 0x1f01;
+ public static final int GL_VERSION = 0x1f02;
+ public static final int GL_EXTENSIONS = 0x1f03;
+ public static final int GL_S = 0x2000;
+ public static final int GL_T = 0x2001;
+ public static final int GL_R = 0x2002;
+ public static final int GL_Q = 0x2003;
+ public static final int GL_MODULATE = 0x2100;
+ public static final int GL_DECAL = 0x2101;
+ public static final int GL_TEXTURE_ENV_MODE = 0x2200;
+ public static final int GL_TEXTURE_ENV_COLOR = 0x2201;
+ public static final int GL_TEXTURE_ENV = 0x2300;
+ public static final int GL_EYE_LINEAR = 0x2400;
+ public static final int GL_OBJECT_LINEAR = 0x2401;
+ public static final int GL_SPHERE_MAP = 0x2402;
+ public static final int GL_TEXTURE_GEN_MODE = 0x2500;
+ public static final int GL_OBJECT_PLANE = 0x2501;
+ public static final int GL_EYE_PLANE = 0x2502;
+ public static final int GL_NEAREST = 0x2600;
+ public static final int GL_LINEAR = 0x2601;
+ public static final int GL_NEAREST_MIPMAP_NEAREST = 0x2700;
+ public static final int GL_LINEAR_MIPMAP_NEAREST = 0x2701;
+ public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702;
+ public static final int GL_LINEAR_MIPMAP_LINEAR = 0x2703;
+ public static final int GL_TEXTURE_MAG_FILTER = 0x2800;
+ public static final int GL_TEXTURE_MIN_FILTER = 0x2801;
+ public static final int GL_TEXTURE_WRAP_S = 0x2802;
+ public static final int GL_TEXTURE_WRAP_T = 0x2803;
+ public static final int GL_CLAMP = 0x2900;
+ public static final int GL_REPEAT = 0x2901;
+ public static final int GL_CLIENT_PIXEL_STORE_BIT = 0x1;
+ public static final int GL_CLIENT_VERTEX_ARRAY_BIT = 0x2;
+ public static final int GL_ALL_CLIENT_ATTRIB_BITS = 0xffffffff;
+ public static final int GL_POLYGON_OFFSET_FACTOR = 0x8038;
+ public static final int GL_POLYGON_OFFSET_UNITS = 0x2a00;
+ public static final int GL_POLYGON_OFFSET_POINT = 0x2a01;
+ public static final int GL_POLYGON_OFFSET_LINE = 0x2a02;
+ public static final int GL_POLYGON_OFFSET_FILL = 0x8037;
+ public static final int GL_ALPHA4 = 0x803b;
+ public static final int GL_ALPHA8 = 0x803c;
+ public static final int GL_ALPHA12 = 0x803d;
+ public static final int GL_ALPHA16 = 0x803e;
+ public static final int GL_LUMINANCE4 = 0x803f;
+ public static final int GL_LUMINANCE8 = 0x8040;
+ public static final int GL_LUMINANCE12 = 0x8041;
+ public static final int GL_LUMINANCE16 = 0x8042;
+ public static final int GL_LUMINANCE4_ALPHA4 = 0x8043;
+ public static final int GL_LUMINANCE6_ALPHA2 = 0x8044;
+ public static final int GL_LUMINANCE8_ALPHA8 = 0x8045;
+ public static final int GL_LUMINANCE12_ALPHA4 = 0x8046;
+ public static final int GL_LUMINANCE12_ALPHA12 = 0x8047;
+ public static final int GL_LUMINANCE16_ALPHA16 = 0x8048;
+ public static final int GL_INTENSITY = 0x8049;
+ public static final int GL_INTENSITY4 = 0x804a;
+ public static final int GL_INTENSITY8 = 0x804b;
+ public static final int GL_INTENSITY12 = 0x804c;
+ public static final int GL_INTENSITY16 = 0x804d;
+ public static final int GL_R3_G3_B2 = 0x2a10;
+ public static final int GL_RGB4 = 0x804f;
+ public static final int GL_RGB5 = 0x8050;
+ public static final int GL_RGB8 = 0x8051;
+ public static final int GL_RGB10 = 0x8052;
+ public static final int GL_RGB12 = 0x8053;
+ public static final int GL_RGB16 = 0x8054;
+ public static final int GL_RGBA2 = 0x8055;
+ public static final int GL_RGBA4 = 0x8056;
+ public static final int GL_RGB5_A1 = 0x8057;
+ public static final int GL_RGBA8 = 0x8058;
+ public static final int GL_RGB10_A2 = 0x8059;
+ public static final int GL_RGBA12 = 0x805a;
+ public static final int GL_RGBA16 = 0x805b;
+ public static final int GL_TEXTURE_RED_SIZE = 0x805c;
+ public static final int GL_TEXTURE_GREEN_SIZE = 0x805d;
+ public static final int GL_TEXTURE_BLUE_SIZE = 0x805e;
+ public static final int GL_TEXTURE_ALPHA_SIZE = 0x805f;
+ public static final int GL_TEXTURE_LUMINANCE_SIZE = 0x8060;
+ public static final int GL_TEXTURE_INTENSITY_SIZE = 0x8061;
+ public static final int GL_PROXY_TEXTURE_1D = 0x8063;
+ public static final int GL_PROXY_TEXTURE_2D = 0x8064;
+ public static final int GL_TEXTURE_PRIORITY = 0x8066;
+ public static final int GL_TEXTURE_RESIDENT = 0x8067;
+ public static final int GL_TEXTURE_BINDING_1D = 0x8068;
+ public static final int GL_TEXTURE_BINDING_2D = 0x8069;
+ public static final int GL_VERTEX_ARRAY = 0x8074;
+ public static final int GL_NORMAL_ARRAY = 0x8075;
+ public static final int GL_COLOR_ARRAY = 0x8076;
+ public static final int GL_INDEX_ARRAY = 0x8077;
+ public static final int GL_TEXTURE_COORD_ARRAY = 0x8078;
+ public static final int GL_EDGE_FLAG_ARRAY = 0x8079;
+ public static final int GL_VERTEX_ARRAY_SIZE = 0x807a;
+ public static final int GL_VERTEX_ARRAY_TYPE = 0x807b;
+ public static final int GL_VERTEX_ARRAY_STRIDE = 0x807c;
+ public static final int GL_NORMAL_ARRAY_TYPE = 0x807e;
+ public static final int GL_NORMAL_ARRAY_STRIDE = 0x807f;
+ public static final int GL_COLOR_ARRAY_SIZE = 0x8081;
+ public static final int GL_COLOR_ARRAY_TYPE = 0x8082;
+ public static final int GL_COLOR_ARRAY_STRIDE = 0x8083;
+ public static final int GL_INDEX_ARRAY_TYPE = 0x8085;
+ public static final int GL_INDEX_ARRAY_STRIDE = 0x8086;
+ public static final int GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088;
+ public static final int GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089;
+ public static final int GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808a;
+ public static final int GL_EDGE_FLAG_ARRAY_STRIDE = 0x808c;
+ public static final int GL_VERTEX_ARRAY_POINTER = 0x808e;
+ public static final int GL_NORMAL_ARRAY_POINTER = 0x808f;
+ public static final int GL_COLOR_ARRAY_POINTER = 0x8090;
+ public static final int GL_INDEX_ARRAY_POINTER = 0x8091;
+ public static final int GL_TEXTURE_COORD_ARRAY_POINTER = 0x8092;
+ public static final int GL_EDGE_FLAG_ARRAY_POINTER = 0x8093;
+ public static final int GL_V2F = 0x2a20;
+ public static final int GL_V3F = 0x2a21;
+ public static final int GL_C4UB_V2F = 0x2a22;
+ public static final int GL_C4UB_V3F = 0x2a23;
+ public static final int GL_C3F_V3F = 0x2a24;
+ public static final int GL_N3F_V3F = 0x2a25;
+ public static final int GL_C4F_N3F_V3F = 0x2a26;
+ public static final int GL_T2F_V3F = 0x2a27;
+ public static final int GL_T4F_V4F = 0x2a28;
+ public static final int GL_T2F_C4UB_V3F = 0x2a29;
+ public static final int GL_T2F_C3F_V3F = 0x2a2a;
+ public static final int GL_T2F_N3F_V3F = 0x2a2b;
+ public static final int GL_T2F_C4F_N3F_V3F = 0x2a2c;
+ public static final int GL_T4F_C4F_N3F_V4F = 0x2a2d;
+ public static final int GL_LOGIC_OP = 0xbf1;
+ public static final int GL_TEXTURE_COMPONENTS = 0x1003;
+
+ // GL12
+ public static final int GL_TEXTURE_BINDING_3D = 0x806a;
+ public static final int GL_PACK_SKIP_IMAGES = 0x806b;
+ public static final int GL_PACK_IMAGE_HEIGHT = 0x806c;
+ public static final int GL_UNPACK_SKIP_IMAGES = 0x806d;
+ public static final int GL_UNPACK_IMAGE_HEIGHT = 0x806e;
+ public static final int GL_TEXTURE_3D = 0x806f;
+ public static final int GL_PROXY_TEXTURE_3D = 0x8070;
+ public static final int GL_TEXTURE_DEPTH = 0x8071;
+ public static final int GL_TEXTURE_WRAP_R = 0x8072;
+ public static final int GL_MAX_3D_TEXTURE_SIZE = 0x8073;
+ public static final int GL_BGR = 0x80e0;
+ public static final int GL_BGRA = 0x80e1;
+ public static final int GL_UNSIGNED_BYTE_3_3_2 = 0x8032;
+ public static final int GL_UNSIGNED_BYTE_2_3_3_REV = 0x8362;
+ public static final int GL_UNSIGNED_SHORT_5_6_5 = 0x8363;
+ public static final int GL_UNSIGNED_SHORT_5_6_5_REV = 0x8364;
+ public static final int GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033;
+ public static final int GL_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365;
+ public static final int GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034;
+ public static final int GL_UNSIGNED_SHORT_1_5_5_5_REV = 0x8366;
+ public static final int GL_UNSIGNED_INT_8_8_8_8 = 0x8035;
+ public static final int GL_UNSIGNED_INT_8_8_8_8_REV = 0x8367;
+ public static final int GL_UNSIGNED_INT_10_10_10_2 = 0x8036;
+ public static final int GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368;
+ public static final int GL_RESCALE_NORMAL = 0x803a;
+ public static final int GL_LIGHT_MODEL_COLOR_CONTROL = 0x81f8;
+ public static final int GL_SINGLE_COLOR = 0x81f9;
+ public static final int GL_SEPARATE_SPECULAR_COLOR = 0x81fa;
+ public static final int GL_CLAMP_TO_EDGE = 0x812f;
+ public static final int GL_TEXTURE_MIN_LOD = 0x813a;
+ public static final int GL_TEXTURE_MAX_LOD = 0x813b;
+ public static final int GL_TEXTURE_BASE_LEVEL = 0x813c;
+ public static final int GL_TEXTURE_MAX_LEVEL = 0x813d;
+ public static final int GL_MAX_ELEMENTS_VERTICES = 0x80e8;
+ public static final int GL_MAX_ELEMENTS_INDICES = 0x80e9;
+ public static final int GL_ALIASED_POINT_SIZE_RANGE = 0x846d;
+ public static final int GL_ALIASED_LINE_WIDTH_RANGE = 0x846e;
+ public static final int GL_SMOOTH_POINT_SIZE_RANGE = 0xb12;
+ public static final int GL_SMOOTH_POINT_SIZE_GRANULARITY = 0xb13;
+ public static final int GL_SMOOTH_LINE_WIDTH_RANGE = 0xb22;
+ public static final int GL_SMOOTH_LINE_WIDTH_GRANULARITY = 0xb23;
+
+ // GL13
+ public static final int GL_TEXTURE0 = 0x84c0;
+ public static final int GL_TEXTURE1 = 0x84c1;
+ public static final int GL_TEXTURE2 = 0x84c2;
+ public static final int GL_TEXTURE3 = 0x84c3;
+ public static final int GL_TEXTURE4 = 0x84c4;
+ public static final int GL_TEXTURE5 = 0x84c5;
+ public static final int GL_TEXTURE6 = 0x84c6;
+ public static final int GL_TEXTURE7 = 0x84c7;
+ public static final int GL_TEXTURE8 = 0x84c8;
+ public static final int GL_TEXTURE9 = 0x84c9;
+ public static final int GL_TEXTURE10 = 0x84ca;
+ public static final int GL_TEXTURE11 = 0x84cb;
+ public static final int GL_TEXTURE12 = 0x84cc;
+ public static final int GL_TEXTURE13 = 0x84cd;
+ public static final int GL_TEXTURE14 = 0x84ce;
+ public static final int GL_TEXTURE15 = 0x84cf;
+ public static final int GL_TEXTURE16 = 0x84d0;
+ public static final int GL_TEXTURE17 = 0x84d1;
+ public static final int GL_TEXTURE18 = 0x84d2;
+ public static final int GL_TEXTURE19 = 0x84d3;
+ public static final int GL_TEXTURE20 = 0x84d4;
+ public static final int GL_TEXTURE21 = 0x84d5;
+ public static final int GL_TEXTURE22 = 0x84d6;
+ public static final int GL_TEXTURE23 = 0x84d7;
+ public static final int GL_TEXTURE24 = 0x84d8;
+ public static final int GL_TEXTURE25 = 0x84d9;
+ public static final int GL_TEXTURE26 = 0x84da;
+ public static final int GL_TEXTURE27 = 0x84db;
+ public static final int GL_TEXTURE28 = 0x84dc;
+ public static final int GL_TEXTURE29 = 0x84dd;
+ public static final int GL_TEXTURE30 = 0x84de;
+ public static final int GL_TEXTURE31 = 0x84df;
+ public static final int GL_ACTIVE_TEXTURE = 0x84e0;
+ public static final int GL_CLIENT_ACTIVE_TEXTURE = 0x84e1;
+ public static final int GL_MAX_TEXTURE_UNITS = 0x84e2;
+ public static final int GL_NORMAL_MAP = 0x8511;
+ public static final int GL_REFLECTION_MAP = 0x8512;
+ public static final int GL_TEXTURE_CUBE_MAP = 0x8513;
+ public static final int GL_TEXTURE_BINDING_CUBE_MAP = 0x8514;
+ public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
+ public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
+ public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
+ public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
+ public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
+ public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a;
+ public static final int GL_PROXY_TEXTURE_CUBE_MAP = 0x851b;
+ public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851c;
+ public static final int GL_COMPRESSED_ALPHA = 0x84e9;
+ public static final int GL_COMPRESSED_LUMINANCE = 0x84ea;
+ public static final int GL_COMPRESSED_LUMINANCE_ALPHA = 0x84eb;
+ public static final int GL_COMPRESSED_INTENSITY = 0x84ec;
+ public static final int GL_COMPRESSED_RGB = 0x84ed;
+ public static final int GL_COMPRESSED_RGBA = 0x84ee;
+ public static final int GL_TEXTURE_COMPRESSION_HINT = 0x84ef;
+ public static final int GL_TEXTURE_COMPRESSED_IMAGE_SIZE = 0x86a0;
+ public static final int GL_TEXTURE_COMPRESSED = 0x86a1;
+ public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS = 0x86a2;
+ public static final int GL_COMPRESSED_TEXTURE_FORMATS = 0x86a3;
+ public static final int GL_MULTISAMPLE = 0x809d;
+ public static final int GL_SAMPLE_ALPHA_TO_COVERAGE = 0x809e;
+ public static final int GL_SAMPLE_ALPHA_TO_ONE = 0x809f;
+ public static final int GL_SAMPLE_COVERAGE = 0x80a0;
+ public static final int GL_SAMPLE_BUFFERS = 0x80a8;
+ public static final int GL_SAMPLES = 0x80a9;
+ public static final int GL_SAMPLE_COVERAGE_VALUE = 0x80aa;
+ public static final int GL_SAMPLE_COVERAGE_INVERT = 0x80ab;
+ public static final int GL_MULTISAMPLE_BIT = 0x20000000;
+ public static final int GL_TRANSPOSE_MODELVIEW_MATRIX = 0x84e3;
+ public static final int GL_TRANSPOSE_PROJECTION_MATRIX = 0x84e4;
+ public static final int GL_TRANSPOSE_TEXTURE_MATRIX = 0x84e5;
+ public static final int GL_TRANSPOSE_COLOR_MATRIX = 0x84e6;
+ public static final int GL_COMBINE = 0x8570;
+ public static final int GL_COMBINE_RGB = 0x8571;
+ public static final int GL_COMBINE_ALPHA = 0x8572;
+ public static final int GL_SOURCE0_RGB = 0x8580;
+ public static final int GL_SOURCE1_RGB = 0x8581;
+ public static final int GL_SOURCE2_RGB = 0x8582;
+ public static final int GL_SOURCE0_ALPHA = 0x8588;
+ public static final int GL_SOURCE1_ALPHA = 0x8589;
+ public static final int GL_SOURCE2_ALPHA = 0x858a;
+ public static final int GL_OPERAND0_RGB = 0x8590;
+ public static final int GL_OPERAND1_RGB = 0x8591;
+ public static final int GL_OPERAND2_RGB = 0x8592;
+ public static final int GL_OPERAND0_ALPHA = 0x8598;
+ public static final int GL_OPERAND1_ALPHA = 0x8599;
+ public static final int GL_OPERAND2_ALPHA = 0x859a;
+ public static final int GL_RGB_SCALE = 0x8573;
+ public static final int GL_ADD_SIGNED = 0x8574;
+ public static final int GL_INTERPOLATE = 0x8575;
+ public static final int GL_SUBTRACT = 0x84e7;
+ public static final int GL_CONSTANT = 0x8576;
+ public static final int GL_PRIMARY_COLOR = 0x8577;
+ public static final int GL_PREVIOUS = 0x8578;
+ public static final int GL_DOT3_RGB = 0x86ae;
+ public static final int GL_DOT3_RGBA = 0x86af;
+ public static final int GL_CLAMP_TO_BORDER = 0x812d;
+
+ // GL14
+ public static final int GL_GENERATE_MIPMAP = 0x8191;
+ public static final int GL_GENERATE_MIPMAP_HINT = 0x8192;
+ public static final int GL_DEPTH_COMPONENT16 = 0x81a5;
+ public static final int GL_DEPTH_COMPONENT24 = 0x81a6;
+ public static final int GL_DEPTH_COMPONENT32 = 0x81a7;
+ public static final int GL_TEXTURE_DEPTH_SIZE = 0x884a;
+ public static final int GL_DEPTH_TEXTURE_MODE = 0x884b;
+ public static final int GL_TEXTURE_COMPARE_MODE = 0x884c;
+ public static final int GL_TEXTURE_COMPARE_FUNC = 0x884d;
+ public static final int GL_COMPARE_R_TO_TEXTURE = 0x884e;
+ public static final int GL_FOG_COORDINATE_SOURCE = 0x8450;
+ public static final int GL_FOG_COORDINATE = 0x8451;
+ public static final int GL_FRAGMENT_DEPTH = 0x8452;
+ public static final int GL_CURRENT_FOG_COORDINATE = 0x8453;
+ public static final int GL_FOG_COORDINATE_ARRAY_TYPE = 0x8454;
+ public static final int GL_FOG_COORDINATE_ARRAY_STRIDE = 0x8455;
+ public static final int GL_FOG_COORDINATE_ARRAY_POINTER = 0x8456;
+ public static final int GL_FOG_COORDINATE_ARRAY = 0x8457;
+ public static final int GL_POINT_SIZE_MIN = 0x8126;
+ public static final int GL_POINT_SIZE_MAX = 0x8127;
+ public static final int GL_POINT_FADE_THRESHOLD_SIZE = 0x8128;
+ public static final int GL_POINT_DISTANCE_ATTENUATION = 0x8129;
+ public static final int GL_COLOR_SUM = 0x8458;
+ public static final int GL_CURRENT_SECONDARY_COLOR = 0x8459;
+ public static final int GL_SECONDARY_COLOR_ARRAY_SIZE = 0x845a;
+ public static final int GL_SECONDARY_COLOR_ARRAY_TYPE = 0x845b;
+ public static final int GL_SECONDARY_COLOR_ARRAY_STRIDE = 0x845c;
+ public static final int GL_SECONDARY_COLOR_ARRAY_POINTER = 0x845d;
+ public static final int GL_SECONDARY_COLOR_ARRAY = 0x845e;
+ public static final int GL_BLEND_DST_RGB = 0x80c8;
+ public static final int GL_BLEND_SRC_RGB = 0x80c9;
+ public static final int GL_BLEND_DST_ALPHA = 0x80ca;
+ public static final int GL_BLEND_SRC_ALPHA = 0x80cb;
+ public static final int GL_INCR_WRAP = 0x8507;
+ public static final int GL_DECR_WRAP = 0x8508;
+ public static final int GL_TEXTURE_FILTER_CONTROL = 0x8500;
+ public static final int GL_TEXTURE_LOD_BIAS = 0x8501;
+ public static final int GL_MAX_TEXTURE_LOD_BIAS = 0x84fd;
+ public static final int GL_MIRRORED_REPEAT = 0x8370;
+ public static final int GL_BLEND_COLOR = 0x8005;
+ public static final int GL_BLEND_EQUATION = 0x8009;
+ public static final int GL_FUNC_ADD = 0x8006;
+ public static final int GL_FUNC_SUBTRACT = 0x800a;
+ public static final int GL_FUNC_REVERSE_SUBTRACT = 0x800b;
+ public static final int GL_MIN = 0x8007;
+ public static final int GL_MAX = 0x8008;
+
+ // GL15
+ public static final int GL_ARRAY_BUFFER = 0x8892;
+ public static final int GL_ELEMENT_ARRAY_BUFFER = 0x8893;
+ public static final int GL_ARRAY_BUFFER_BINDING = 0x8894;
+ public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
+ public static final int GL_VERTEX_ARRAY_BUFFER_BINDING = 0x8896;
+ public static final int GL_NORMAL_ARRAY_BUFFER_BINDING = 0x8897;
+ public static final int GL_COLOR_ARRAY_BUFFER_BINDING = 0x8898;
+ public static final int GL_INDEX_ARRAY_BUFFER_BINDING = 0x8899;
+ public static final int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = 0x889a;
+ public static final int GL_EDGE_FLAG_ARRAY_BUFFER_BINDING = 0x889b;
+ public static final int GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING = 0x889c;
+ public static final int GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING = 0x889d;
+ public static final int GL_WEIGHT_ARRAY_BUFFER_BINDING = 0x889e;
+ public static final int GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889f;
+ public static final int GL_STREAM_DRAW = 0x88e0;
+ public static final int GL_STREAM_READ = 0x88e1;
+ public static final int GL_STREAM_COPY = 0x88e2;
+ public static final int GL_STATIC_DRAW = 0x88e4;
+ public static final int GL_STATIC_READ = 0x88e5;
+ public static final int GL_STATIC_COPY = 0x88e6;
+ public static final int GL_DYNAMIC_DRAW = 0x88e8;
+ public static final int GL_DYNAMIC_READ = 0x88e9;
+ public static final int GL_DYNAMIC_COPY = 0x88ea;
+ public static final int GL_READ_ONLY = 0x88b8;
+ public static final int GL_WRITE_ONLY = 0x88b9;
+ public static final int GL_READ_WRITE = 0x88ba;
+ public static final int GL_BUFFER_SIZE = 0x8764;
+ public static final int GL_BUFFER_USAGE = 0x8765;
+ public static final int GL_BUFFER_ACCESS = 0x88bb;
+ public static final int GL_BUFFER_MAPPED = 0x88bc;
+ public static final int GL_BUFFER_MAP_POINTER = 0x88bd;
+ public static final int FOG_COORD_SRC = 0x8450;
+ public static final int GL_FOG_COORD = 0x8451;
+ public static final int GL_CURRENT_FOG_COORD = 0x8453;
+ public static final int GL_FOG_COORD_ARRAY_TYPE = 0x8454;
+ public static final int GL_FOG_COORD_ARRAY_STRIDE = 0x8455;
+ public static final int GL_FOG_COORD_ARRAY_POINTER = 0x8456;
+ public static final int GL_FOG_COORD_ARRAY = 0x8457;
+ public static final int GL_FOG_COORD_ARRAY_BUFFER_BINDING = 0x889d;
+ public static final int GL_SRC0_RGB = 0x8580;
+ public static final int GL_SRC1_RGB = 0x8581;
+ public static final int GL_SRC2_RGB = 0x8582;
+ public static final int GL_SRC0_ALPHA = 0x8588;
+ public static final int GL_SRC1_ALPHA = 0x8589;
+ public static final int GL_SRC2_ALPHA = 0x858a;
+
+ public static void glPushAttrib()
+ {
+ // GL_ENABLE_BIT | GL_LIGHTING_BIT
+ GlStateManager.pushAttrib();
+ }
+
+ public static void glPushAttrib(int mask)
+ {
+ GL11.glPushAttrib(mask);
+ }
+
+ public static void glPopAttrib()
+ {
+ GlStateManager.popAttrib();
+ }
+
+ public static void glDisableAlphaTest()
+ {
+ GlStateManager.disableAlpha();
+ }
+
+ public static void glEnableAlphaTest()
+ {
+ GlStateManager.enableAlpha();
+ }
+
+ public static void glAlphaFunc(int func, float ref)
+ {
+ GlStateManager.alphaFunc(func, ref);
+ }
+
+ public static void glEnableLighting()
+ {
+ GlStateManager.enableLighting();
+ }
+
+ public static void glDisableLighting()
+ {
+ GlStateManager.disableLighting();
+ }
+
+ public static void glEnableLight(int light)
+ {
+ GlStateManager.enableLight(light); // TODO OBF MCPTEST enableBooleanStateAt - enableLight
+ }
+
+ public static void glDisableLight(int light)
+ {
+ GlStateManager.disableLight(light); // TODO OBF MCPTEST disableBooleanStateAt - disableLight
+ }
+
+ public static void glLight(int light, int pname, FloatBuffer params)
+ {
+ GL11.glLight(light, pname, params);
+ }
+
+ public static void glLightModel(int pname, FloatBuffer params)
+ {
+ GL11.glLightModel(pname, params);
+ }
+
+ public static void glLightModeli(int pname, int param)
+ {
+ GL11.glLightModeli(pname, param);
+ }
+
+ public static void glEnableColorMaterial()
+ {
+ GlStateManager.enableColorMaterial();
+ }
+
+ public static void glDisableColorMaterial()
+ {
+ GlStateManager.disableColorMaterial();
+ }
+
+ public static void glColorMaterial(int face, int mode)
+ {
+ GlStateManager.colorMaterial(face, mode);
+ }
+
+ public static void glDisableDepthTest()
+ {
+ GlStateManager.disableDepth();
+ }
+
+ public static void glEnableDepthTest()
+ {
+ GlStateManager.enableDepth();
+ }
+
+ public static void glDepthFunc(int func)
+ {
+ GlStateManager.depthFunc(func);
+ }
+
+ public static void glDepthMask(boolean flag)
+ {
+ GlStateManager.depthMask(flag);
+ }
+
+ public static void glDisableBlend()
+ {
+ GlStateManager.disableBlend();
+ }
+
+ public static void glEnableBlend()
+ {
+ GlStateManager.enableBlend();
+ }
+
+ public static void glBlendFunc(int sfactor, int dfactor)
+ {
+ GlStateManager.blendFunc(sfactor, dfactor);
+ }
+
+ public static void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha)
+ {
+ GlStateManager.tryBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+ }
+
+ public static void glEnableFog()
+ {
+ GlStateManager.enableFog();
+ }
+
+ public static void glDisableFog()
+ {
+ GlStateManager.disableFog();
+ }
+
+ public static void glSetFogMode(int mode)
+ {
+ GlStateManager.setFog(mode);
+ }
+
+ public static void glSetFogDensity(float density)
+ {
+ GlStateManager.setFogDensity(density);
+ }
+
+ public static void glSetFogStart(float start)
+ {
+ GlStateManager.setFogStart(start);
+ }
+
+ public static void glSetFogEnd(float end)
+ {
+ GlStateManager.setFogEnd(end);
+ }
+
+ public static void glSetFogColour(FloatBuffer colour)
+ {
+ GL11.glFog(GL_FOG_COLOR, colour);
+ }
+
+ public static void glFogi(int pname, int param)
+ {
+ GL11.glFogi(pname, param);
+ }
+
+ public static void glFogf(int pname, float param)
+ {
+ GL11.glFogf(pname, param);
+ }
+
+ public static void glEnableCulling()
+ {
+ GlStateManager.enableCull();
+ }
+
+ public static void glDisableCulling()
+ {
+ GlStateManager.disableCull();
+ }
+
+ public static void glCullFace(int mode)
+ {
+ GlStateManager.cullFace(mode);
+ }
+
+ public static void glEnablePolygonOffset()
+ {
+ GlStateManager.enablePolygonOffset();
+ }
+
+ public static void glDisablePolygonOffset()
+ {
+ GlStateManager.disablePolygonOffset();
+ }
+
+ public static void glPolygonOffset(float factor, float units)
+ {
+ GlStateManager.doPolygonOffset(factor, units);
+ }
+
+ public static void glEnableColorLogic()
+ {
+ GlStateManager.enableColorLogic();
+ }
+
+ public static void glDisableColorLogic()
+ {
+ GlStateManager.disableColorLogic();
+ }
+
+ public static void glLogicOp(int opcode)
+ {
+ GlStateManager.colorLogicOp(opcode);
+ }
+
+ public static void glEnableTexGenCoord(TexGen tex)
+ {
+ GlStateManager.enableTexGenCoord(tex);
+ }
+
+ public static void glDisableTexGenCoord(TexGen tex)
+ {
+ GlStateManager.disableTexGenCoord(tex);
+ }
+
+ public static void glTexGeni(TexGen tex, int mode)
+ {
+ GlStateManager.texGen(tex, mode);
+ }
+
+ public static void glTexGen(TexGen tex, int pname, FloatBuffer params)
+ {
+ GlStateManager.func_179105_a(tex, pname, params);
+ }
+
+ public static void glSetActiveTextureUnit(int texture)
+ {
+ GlStateManager.setActiveTexture(texture);
+ }
+
+ public static void glEnableTexture2D()
+ {
+ GlStateManager.enableTexture2D(); // TODO OBF MCPTEST func_179098_w - enableTexture2D
+ }
+
+ public static void glDisableTexture2D()
+ {
+ GlStateManager.disableTexture2D(); // TODO OBF MCPTEST func_179090_x - disableTexture2D
+ }
+
+ public static int glGenTextures()
+ {
+ return GlStateManager.generateTexture(); // TODO OBF MCPTEST func_179146_y - generateTexture
+ }
+
+ public static void glDeleteTextures(int textureName)
+ {
+ GlStateManager.deleteTexture(textureName); // TODO OBF MCPTEST func_179150_h - deleteTexture
+ }
+
+ public static void glBindTexture2D(int textureName)
+ {
+ GlStateManager.bindTexture(textureName); // TODO OBF MCPTEST func_179144_i - bindTexture
+ }
+
+ public static void glEnableNormalize()
+ {
+ GlStateManager.enableNormalize();
+ }
+
+ public static void glDisableNormalize()
+ {
+ GlStateManager.disableNormalize();
+ }
+
+ public static void glShadeModel(int mode)
+ {
+ GlStateManager.shadeModel(mode);
+ }
+
+ public static void glEnableRescaleNormal()
+ {
+ GlStateManager.enableRescaleNormal();
+ }
+
+ public static void glDisableRescaleNormal()
+ {
+ GlStateManager.disableRescaleNormal();
+ }
+
+ public static void glViewport(int x, int y, int width, int height)
+ {
+ GlStateManager.viewport(x, y, width, height);
+ }
+
+ public static void glColorMask(boolean red, boolean green, boolean blue, boolean alpha)
+ {
+ GlStateManager.colorMask(red, green, blue, alpha);
+ }
+
+ public static void glClearDepth(double depth)
+ {
+ GlStateManager.clearDepth(depth);
+ }
+
+ public static void glClearColor(float red, float green, float blue, float alpha)
+ {
+ GlStateManager.clearColor(red, green, blue, alpha);
+ }
+
+ public static void glClear(int mask)
+ {
+ GlStateManager.clear(mask);
+ }
+
+ public static void glMatrixMode(int mode)
+ {
+ GlStateManager.matrixMode(mode);
+ }
+
+ public static void glLoadIdentity()
+ {
+ GlStateManager.loadIdentity();
+ }
+
+ public static void glPushMatrix()
+ {
+ GlStateManager.pushMatrix();
+ }
+
+ public static void glPopMatrix()
+ {
+ GlStateManager.popMatrix();
+ }
+
+ public static void glGetFloat(int pname, FloatBuffer params)
+ {
+ GlStateManager.getFloat(pname, params);
+ }
+
+ public static float glGetFloat(int pname)
+ {
+ return GL11.glGetFloat(pname);
+ }
+
+ public static void glGetDouble(int pname, DoubleBuffer params)
+ {
+ GL11.glGetDouble(pname, params);
+ }
+
+ public static double glGetDouble(int pname)
+ {
+ return GL11.glGetDouble(pname);
+ }
+
+ public static void glGetInteger(int pname, IntBuffer params)
+ {
+ GL11.glGetInteger(pname, params);
+ }
+
+ public static int glGetInteger(int pname)
+ {
+ return GL11.glGetInteger(pname);
+ }
+
+ public static void glGetBoolean(int pname, ByteBuffer params)
+ {
+ GL11.glGetBoolean(pname, params);
+ }
+
+ public static boolean glGetBoolean(int pname)
+ {
+ return GL11.glGetBoolean(pname);
+ }
+
+ public static void gluProject(float objx, float objy, float objz, FloatBuffer modelMatrix, FloatBuffer projMatrix, IntBuffer viewport,
+ FloatBuffer winPos)
+ {
+ GLU.gluProject(objx, objy, objz, modelMatrix, projMatrix, viewport, winPos);
+ }
+
+ public static void gluPerspective(float fovy, float aspect, float zNear, float zFar)
+ {
+ GLU.gluPerspective(fovy, aspect, zNear, zFar);
+ }
+
+ public static void glOrtho(double left, double right, double bottom, double top, double zNear, double zFar)
+ {
+ GlStateManager.ortho(left, right, bottom, top, zNear, zFar);
+ }
+
+ public static void glRotatef(float angle, float x, float y, float z)
+ {
+ GlStateManager.rotate(angle, x, y, z);
+ }
+
+ public static void glRotated(double angle, double x, double y, double z)
+ {
+ GL11.glRotated(angle, x, y, z);
+ }
+
+ public static void glScalef(float x, float y, float z)
+ {
+ GlStateManager.scale(x, y, z);
+ }
+
+ public static void glScaled(double x, double y, double z)
+ {
+ GlStateManager.scale(x, y, z);
+ }
+
+ public static void glTranslatef(float x, float y, float z)
+ {
+ GlStateManager.translate(x, y, z);
+ }
+
+ public static void glTranslated(double x, double y, double z)
+ {
+ GlStateManager.translate(x, y, z);
+ }
+
+ public static void glMultMatrix(FloatBuffer m)
+ {
+ GlStateManager.multMatrix(m);
+ }
+
+ public static void glColor4f(float red, float green, float blue, float alpha)
+ {
+ GlStateManager.color(red, green, blue, alpha);
+ }
+
+ public static void glColor3f(float red, float green, float blue)
+ {
+ GlStateManager.color(red, green, blue, 1.0F);
+ }
+
+ public static void glResetColor()
+ {
+ GlStateManager.resetColor();
+ }
+
+ public static void glCallList(int list)
+ {
+ GlStateManager.callList(list);
+ }
+
+ public static void glCallLists(IntBuffer lists)
+ {
+ GL11.glCallLists(lists);
+ }
+
+ public static void glNewList(int list, int mode)
+ {
+ GL11.glNewList(list, mode);
+ }
+
+ public static void glEndList()
+ {
+ GL11.glEndList();
+ }
+
+ public static void glLineWidth(float width)
+ {
+ GL11.glLineWidth(width);
+ }
+
+ public static void glPolygonMode(int face, int mode)
+ {
+ GL11.glPolygonMode(face, mode);
+ }
+
+ public static void glPixelStorei(int pname, int param)
+ {
+ GL11.glPixelStorei(pname, param);
+ }
+
+ public static void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer pixels)
+ {
+ GL11.glReadPixels(x, y, width, height, format, type, pixels);
+ }
+
+ public static void glGetTexImage(int target, int level, int format, int type, ByteBuffer pixels)
+ {
+ GL11.glGetTexImage(target, level, format, type, pixels);
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/gl/GLClippingPlanes.java b/liteloader/src/client/java/com/mumfrey/liteloader/gl/GLClippingPlanes.java
new file mode 100644
index 00000000..a7d4c76b
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/gl/GLClippingPlanes.java
@@ -0,0 +1,193 @@
+package com.mumfrey.liteloader.gl;
+
+import static org.lwjgl.opengl.GL11.*;
+
+import java.nio.DoubleBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.util.Rectangle;
+
+/**
+ * OpenGL clipping plane convenience functions. We prefer to clip rectangular
+ * GUI regions in Minecraft using clipping rather than scissor because scissor
+ * is a nuisance to work with, primarily because it works in "window" (OpenGL
+ * window) coordinates and doesn't respect the current transformation matrix.
+ * Using clipping planes we can specify clipping edges in "Minecraft screen
+ * coordinates", can optionally clip on only one or two axes, and also don't
+ * need to worry about the current transform.
+ *
+ * @author Adam Mummery-Smith
+ */
+public final class GLClippingPlanes
+{
+ public enum Plane
+ {
+ LEFT(GL_CLIP_PLANE0),
+ RIGHT(GL_CLIP_PLANE1),
+ TOP(GL_CLIP_PLANE2),
+ BOTTOM(GL_CLIP_PLANE3);
+
+ final int plane;
+ final int sign;
+
+ private Plane(int plane)
+ {
+ this.plane = plane;
+ this.sign = (plane % 2 == 0) ? -1 : 1;
+ }
+ }
+
+ private static final int STACK_DEPTH = 1;
+ private static final int STACK_FRAME_SIZE = 128;
+
+ private static DoubleBuffer doubleBuffer = BufferUtils.createByteBuffer(STACK_FRAME_SIZE * STACK_DEPTH).asDoubleBuffer();
+
+ private static int clippingPlaneFlags = 0;
+
+ private static int totalClippingPlanes = glGetInteger(GL_MAX_CLIP_PLANES);
+
+// private static int frame = 0;
+
+ static
+ {
+ for (int f = 0; f < STACK_DEPTH; f++)
+ {
+ // Clipping normals
+ GLClippingPlanes.doubleBuffer.put(1).put(0).put(0).put(0);
+ GLClippingPlanes.doubleBuffer.put(-1).put(0).put(0).put(0);
+ GLClippingPlanes.doubleBuffer.put(0).put(1).put(0).put(0);
+ GLClippingPlanes.doubleBuffer.put(0).put(-1).put(0).put(0);
+ }
+ }
+
+ private GLClippingPlanes() {}
+
+ /**
+ * Get the total number of available clipping planes on the platform
+ */
+ public static int glGetTotalClippingPlanes()
+ {
+ return GLClippingPlanes.totalClippingPlanes;
+ }
+
+ /**
+ * Enable OpenGL clipping planes (uses planes 0, 1, 2 and 3)
+ *
+ * @param left Left edge clip or -1 to not use this plane
+ * @param right Right edge clip or -1 to not use this plane
+ * @param top Top edge clip or -1 to not use this plane
+ * @param bottom Bottom edge clip or -1 to not use this plane
+ */
+ public static void glEnableClipping(int left, int right, int top, int bottom)
+ {
+ GLClippingPlanes.clippingPlaneFlags = 0;
+
+ glEnableClipping(GL_CLIP_PLANE0, left, -1);
+ glEnableClipping(GL_CLIP_PLANE1, right, 1);
+ glEnableClipping(GL_CLIP_PLANE2, top, -1);
+ glEnableClipping(GL_CLIP_PLANE3, bottom, 1);
+ }
+
+ /**
+ * Enable OpenGL clipping planes (uses planes 0, 1, 2 and 3)
+ *
+ * @param rect Clipping rectangle
+ */
+ public static void glEnableClipping(Rectangle rect)
+ {
+ GLClippingPlanes.clippingPlaneFlags = 0;
+
+ glEnableClipping(GL_CLIP_PLANE0, rect.getX(), -1);
+ glEnableClipping(GL_CLIP_PLANE1, rect.getX() + rect.getWidth(), 1);
+ glEnableClipping(GL_CLIP_PLANE2, rect.getY(), -1);
+ glEnableClipping(GL_CLIP_PLANE3, rect.getY() + rect.getHeight(), 1);
+ }
+
+ /**
+ * Enable horizontal clipping planes (left and right) (uses planes 0, 1)
+ *
+ * @param left Left edge clip or -1 to not use this plane
+ * @param right Right edge clip or -1 to not use this plane
+ */
+ public static void glEnableHorizontalClipping(int left, int right)
+ {
+ glEnableClipping(GL_CLIP_PLANE0, left, -1);
+ glEnableClipping(GL_CLIP_PLANE1, right, 1);
+ }
+
+ /**
+ * Enable vertical clipping planes (top and bottom) (uses planes 2, 3)
+ *
+ * @param top Top edge clip or -1 to not use this plane
+ * @param bottom Bottom edge clip or -1 to not use this plane
+ */
+ public static void glEnableVerticalClipping(int top, int bottom)
+ {
+ glEnableClipping(GL_CLIP_PLANE2, top, -1);
+ glEnableClipping(GL_CLIP_PLANE3, bottom, 1);
+ }
+
+ /**
+ * @param plane
+ * @param value
+ */
+ public static void glEnableClipping(int plane, int value)
+ {
+ if (plane < GL_CLIP_PLANE0 || plane >= (GL_CLIP_PLANE0 + GLClippingPlanes.totalClippingPlanes))
+ {
+ throw new IllegalArgumentException("Invalid clipping plane enum specified GL_CLIP_PLANE" + (plane - GL_CLIP_PLANE0));
+ }
+
+ glEnableClipping(plane, value, (plane % 2 == 0) ? -1 : 1);
+ }
+
+ /**
+ * @param plane
+ * @param value
+ */
+ public static void glEnableClipping(Plane plane, int value)
+ {
+ glEnableClipping(plane.plane, value, plane.sign);
+ }
+
+ /**
+ * Enable clipping on a particular axis
+ *
+ * @param plane Clipping plane to enable
+ * @param value Clipping plane position
+ * @param sign Sign of the position
+ */
+ private static void glEnableClipping(int plane, int value, int sign)
+ {
+ if (value == -1) return;
+
+ int offset = (plane - GL_CLIP_PLANE0) << 2;
+ GLClippingPlanes.doubleBuffer.put(offset + 3, value * sign).position(offset);
+ GLClippingPlanes.clippingPlaneFlags |= plane;
+
+ glClipPlane(plane, GLClippingPlanes.doubleBuffer);
+ glEnable(plane);
+ }
+
+ /**
+ * Enable clipping planes which were previously enabled
+ */
+ public static void glEnableClipping()
+ {
+ if ((GLClippingPlanes.clippingPlaneFlags & GL_CLIP_PLANE0) == GL_CLIP_PLANE0) glEnable(GL_CLIP_PLANE0);
+ if ((GLClippingPlanes.clippingPlaneFlags & GL_CLIP_PLANE1) == GL_CLIP_PLANE1) glEnable(GL_CLIP_PLANE1);
+ if ((GLClippingPlanes.clippingPlaneFlags & GL_CLIP_PLANE2) == GL_CLIP_PLANE2) glEnable(GL_CLIP_PLANE2);
+ if ((GLClippingPlanes.clippingPlaneFlags & GL_CLIP_PLANE3) == GL_CLIP_PLANE3) glEnable(GL_CLIP_PLANE3);
+ }
+
+ /**
+ * Disable OpenGL clipping planes (uses planes 2, 3, 4 and 5)
+ */
+ public static void glDisableClipping()
+ {
+ glDisable(GL_CLIP_PLANE3);
+ glDisable(GL_CLIP_PLANE2);
+ glDisable(GL_CLIP_PLANE1);
+ glDisable(GL_CLIP_PLANE0);
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/resources/InternalResourcePack.java b/liteloader/src/client/java/com/mumfrey/liteloader/resources/InternalResourcePack.java
new file mode 100644
index 00000000..331221e7
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/resources/InternalResourcePack.java
@@ -0,0 +1,119 @@
+package com.mumfrey.liteloader.resources;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.minecraft.client.resources.IResourcePack;
+import net.minecraft.client.resources.data.IMetadataSection;
+import net.minecraft.client.resources.data.IMetadataSerializer;
+import net.minecraft.util.ResourceLocation;
+
+/**
+ * Resource pack which returns resources using Class::getResourceAsStream() on
+ * the specified class.
+ *
+ * @author Adam Mummery-Smith
+ */
+public class InternalResourcePack implements IResourcePack
+{
+ /**
+ * Domains supported by this resource pack
+ */
+ private final Set resourceDomains = new HashSet();
+
+ /**
+ * Name of this resource pack
+ */
+ private final String packName;
+
+ /**
+ * Class to execute getResourceAsStream() upon
+ */
+ private final Class> resourceClass;
+
+ /**
+ * @param name
+ * @param resourceClass
+ * @param domains
+ */
+ public InternalResourcePack(String name, Class> resourceClass, String... domains)
+ {
+ if (domains.length < 1) throw new IllegalArgumentException("No domains specified for internal resource pack");
+
+ this.packName = name;
+ this.resourceClass = resourceClass;
+
+ for (String domain : domains)
+ this.resourceDomains.add(domain);
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.IResourcePack
+ * #getInputStream(net.minecraft.util.ResourceLocation)
+ */
+ @Override
+ public InputStream getInputStream(ResourceLocation resourceLocation) throws IOException
+ {
+ return this.getResourceStream(resourceLocation);
+ }
+
+ /**
+ * @param resourceLocation
+ */
+ private InputStream getResourceStream(ResourceLocation resourceLocation)
+ {
+ return this.resourceClass.getResourceAsStream(String.format("/assets/%s/%s",
+ resourceLocation.getResourceDomain(), resourceLocation.getResourcePath()));
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.IResourcePack#resourceExists(
+ * net.minecraft.util.ResourceLocation)
+ */
+ @Override
+ public boolean resourceExists(ResourceLocation resourceLocation)
+ {
+ return this.getResourceStream(resourceLocation) != null;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.IResourcePack#getResourceDomains()
+ */
+ @Override
+ public Set getResourceDomains()
+ {
+ return this.resourceDomains;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.IResourcePack#getPackMetadata(
+ * net.minecraft.client.resources.data.IMetadataSerializer,
+ * java.lang.String)
+ */
+ @Override
+ public IMetadataSection getPackMetadata(IMetadataSerializer par1MetadataSerializer, String par2Str) throws IOException
+ {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.IResourcePack#getPackImage()
+ */
+ @Override
+ public BufferedImage getPackImage() throws IOException
+ {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.IResourcePack#getPackName()
+ */
+ @Override
+ public String getPackName()
+ {
+ return this.packName;
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/resources/ModResourcePack.java b/liteloader/src/client/java/com/mumfrey/liteloader/resources/ModResourcePack.java
new file mode 100644
index 00000000..f8fa5acc
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/resources/ModResourcePack.java
@@ -0,0 +1,59 @@
+package com.mumfrey.liteloader.resources;
+
+import java.io.File;
+import java.io.IOException;
+
+import net.minecraft.client.resources.FileResourcePack;
+import net.minecraft.client.resources.data.IMetadataSection;
+import net.minecraft.client.resources.data.IMetadataSerializer;
+
+/**
+ * Resource pack which wraps a mod file
+ *
+ * @author Adam Mummery-Smith
+ */
+public class ModResourcePack extends FileResourcePack
+{
+ /**
+ * Display name, only shows up in debug output
+ */
+ private final String name;
+
+ /**
+ * @param name Friendly name
+ * @param modFile
+ */
+ public ModResourcePack(String name, File modFile)
+ {
+ super(modFile);
+ this.name = name;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.AbstractResourcePack#getPackMetadata(
+ * net.minecraft.client.resources.data.IMetadataSerializer,
+ * java.lang.String)
+ */
+ @Override
+ public IMetadataSection getPackMetadata(IMetadataSerializer metadataSerializer, String metadataSectionName) throws IOException
+ {
+ try
+ {
+ // This will fail when fetching pack.mcmeta if there isn't one in the mod file, since we don't care we
+ // just catch the exception and return null instead
+ return super.getPackMetadata(metadataSerializer, metadataSectionName);
+ }
+ catch (Exception ex) {}
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.AbstractResourcePack#getPackName()
+ */
+ @Override
+ public String getPackName()
+ {
+ return this.name;
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/resources/ModResourcePackDir.java b/liteloader/src/client/java/com/mumfrey/liteloader/resources/ModResourcePackDir.java
new file mode 100644
index 00000000..5efba35f
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/resources/ModResourcePackDir.java
@@ -0,0 +1,59 @@
+package com.mumfrey.liteloader.resources;
+
+import java.io.File;
+import java.io.IOException;
+
+import net.minecraft.client.resources.FolderResourcePack;
+import net.minecraft.client.resources.data.IMetadataSection;
+import net.minecraft.client.resources.data.IMetadataSerializer;
+
+/**
+ * Resource pack which wraps a mod directory on the classpath
+ *
+ * @author Adam Mummery-Smith
+ */
+public class ModResourcePackDir extends FolderResourcePack
+{
+ /**
+ * Display name, only shows up in debug output
+ */
+ private final String name;
+
+ /**
+ * @param name Friendly name
+ * @param modFile
+ */
+ public ModResourcePackDir(String name, File modFile)
+ {
+ super(modFile);
+ this.name = name;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.AbstractResourcePack#getPackMetadata(
+ * net.minecraft.client.resources.data.IMetadataSerializer,
+ * java.lang.String)
+ */
+ @Override
+ public IMetadataSection getPackMetadata(IMetadataSerializer metadataSerializer, String metadataSectionName) throws IOException
+ {
+ try
+ {
+ // This will fail when fetching pack.mcmeta if there isn't one in the mod file, since we don't care we
+ // just catch the exception and return null instead
+ return super.getPackMetadata(metadataSerializer, metadataSectionName);
+ }
+ catch (Exception ex) {}
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see net.minecraft.client.resources.AbstractResourcePack#getPackName()
+ */
+ @Override
+ public String getPackName()
+ {
+ return this.name;
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/util/InputManager.java b/liteloader/src/client/java/com/mumfrey/liteloader/util/InputManager.java
new file mode 100644
index 00000000..76be35bd
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/util/InputManager.java
@@ -0,0 +1,361 @@
+package com.mumfrey.liteloader.util;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import net.java.games.input.Component;
+import net.java.games.input.Controller;
+import net.java.games.input.Event;
+import net.java.games.input.EventQueue;
+import net.minecraft.client.settings.KeyBinding;
+import net.minecraft.profiler.Profiler;
+
+import com.mumfrey.liteloader.common.GameEngine;
+import com.mumfrey.liteloader.core.LiteLoader;
+import com.mumfrey.liteloader.launch.LoaderEnvironment;
+import com.mumfrey.liteloader.launch.LoaderProperties;
+import com.mumfrey.liteloader.util.jinput.ComponentRegistry;
+
+/**
+ * Mod input class, aggregates functionality from LiteLoader's mod key
+ * registration functions and JInputLib.
+ *
+ * @author Adam Mummery-Smith
+ */
+public final class InputManager extends Input
+{
+ private GameEngine, ?> engine;
+
+ /**
+ *
+ */
+ private Profiler profiler;
+
+ /**
+ * File in which we will store mod key mappings
+ */
+ private final File keyMapSettingsFile;
+
+ /**
+ * Properties object which stores mod key mappings
+ */
+ private final Properties keyMapSettings = new Properties();
+
+ /**
+ * List of all registered mod keys
+ */
+ private final List modKeyBindings = new ArrayList();
+
+ /**
+ * Map of mod key bindings to their key codes, stored so that we don't need
+ * to cast from string in the properties file every tick.
+ */
+ private final Map storedModKeyBindings = new HashMap();
+
+ /**
+ * JInput component registry
+ */
+ private final ComponentRegistry jInputComponentRegistry;
+
+ /**
+ * List of handlers for JInput components
+ */
+ private final Map componentEvents = new HashMap();
+
+ /**
+ * JInput Controllers to poll
+ */
+ private Controller[] pollControllers = new Controller[0];
+
+ /**
+ *
+ */
+ public InputManager(LoaderEnvironment environment, LoaderProperties properties)
+ {
+ if (LiteLoader.getInstance() != null && LiteLoader.getInput() != null)
+ {
+ throw new IllegalStateException("Only one instance of Input is allowed, use LiteLoader.getInput() to get the active instance");
+ }
+
+ this.keyMapSettingsFile = new File(environment.getCommonConfigFolder(), "liteloader.keys.properties");
+ this.jInputComponentRegistry = new ComponentRegistry();
+
+ if (!properties.getAndStoreBooleanProperty(LoaderProperties.OPTION_JINPUT_DISABLE, false))
+ {
+ this.jInputComponentRegistry.enumerate();
+ }
+ }
+
+ @Override
+ public void onInit()
+ {
+ if (this.keyMapSettingsFile.exists())
+ {
+ try
+ {
+ this.keyMapSettings.load(new FileReader(this.keyMapSettingsFile));
+ }
+ catch (Exception ex) {}
+ }
+ }
+
+ @Override
+ public void onPostInit(GameEngine, ?> engine)
+ {
+ this.engine = engine;
+ this.profiler = engine.getProfiler();
+ }
+
+ /**
+ * Register a key for a mod
+ *
+ * @param binding
+ */
+ @Override
+ public void registerKeyBinding(KeyBinding binding)
+ {
+ List keyBindings = this.engine.getKeyBindings();
+
+ if (!keyBindings.contains(binding))
+ {
+ if (this.keyMapSettings.containsKey(binding.getKeyDescription()))
+ {
+ try
+ {
+ int code = Integer.parseInt(this.keyMapSettings.getProperty(binding.getKeyDescription(), String.valueOf(binding.getKeyCode())));
+ binding.setKeyCode(code);
+ }
+ catch (NumberFormatException ex) {}
+ }
+
+ keyBindings.add(binding);
+
+ this.engine.setKeyBindings(keyBindings);
+ this.modKeyBindings.add(binding);
+
+ this.updateBinding(binding);
+ this.storeBindings();
+
+ KeyBinding.resetKeyBindingArrayAndHash();
+ }
+ }
+
+ /**
+ * Unregisters a registered keybind with the game settings class, thus
+ * removing it from the "controls" screen.
+ *
+ * @param binding
+ */
+ @Override
+ public void unRegisterKeyBinding(KeyBinding binding)
+ {
+ List keyBindings = this.engine.getKeyBindings();
+
+ if (keyBindings.contains(binding))
+ {
+ keyBindings.remove(binding);
+ this.engine.setKeyBindings(keyBindings);
+
+ this.modKeyBindings.remove(binding);
+
+ KeyBinding.resetKeyBindingArrayAndHash();
+ }
+ }
+
+ /**
+ * Checks for changed mod keybindings and stores any that have changed
+ */
+ @Override
+ public void onTick(boolean clock, float partialTicks, boolean inGame)
+ {
+ this.profiler.startSection("keybindings");
+ if (clock)
+ {
+ boolean updated = false;
+
+ for (KeyBinding binding : this.modKeyBindings)
+ {
+ if (binding.getKeyCode() != this.storedModKeyBindings.get(binding))
+ {
+ this.updateBinding(binding);
+ updated = true;
+ }
+ }
+
+ if (updated) this.storeBindings();
+ }
+
+ this.pollControllers();
+ this.profiler.endSection();
+ }
+
+ /**
+ * @param binding
+ */
+ private void updateBinding(KeyBinding binding)
+ {
+ this.keyMapSettings.setProperty(binding.getKeyDescription(), String.valueOf(binding.getKeyCode()));
+ this.storedModKeyBindings.put(binding, Integer.valueOf(binding.getKeyCode()));
+ }
+
+ @Override
+ public void onShutDown()
+ {
+ this.storeBindings();
+ }
+
+ /**
+ * Writes mod bindings to disk
+ */
+ @Override
+ public void storeBindings()
+ {
+ try
+ {
+ this.keyMapSettings.store(new FileWriter(this.keyMapSettingsFile),
+ "Mod key mappings for LiteLoader mods, stored here to avoid losing settings stored in options.txt");
+ }
+ catch (IOException ex) {}
+ }
+
+ /**
+ * Gets the underlying JInput component registry
+ */
+ @Override
+ public ComponentRegistry getComponentRegistry()
+ {
+ return this.jInputComponentRegistry;
+ }
+
+ /**
+ * Returns a handle to the event described by descriptor (or null if no
+ * component is found matching the descriptor. Retrieving an event via this
+ * method adds the controller (if found) to the polling list and causes it
+ * to raise events against the specified handler.
+ *
+ * This method returns an {@link InputEvent} which is passed as an
+ * argument to the relevant callback on the supplied handler in order to
+ * identify the event. For example:
+ *
+ * this.joystickButton = input.getEvent(descriptor, this);
+ *
+ * then in onAxisEvent
+ *
+ * if (source == this.joystickButton) // do something with button
+ *
+ *
+ * @param descriptor
+ * @param handler
+ */
+ @Override
+ public InputEvent getEvent(String descriptor, InputHandler handler)
+ {
+ if (handler == null) return null;
+ Component component = this.jInputComponentRegistry.getComponent(descriptor);
+ Controller controller = this.jInputComponentRegistry.getController(descriptor);
+ return this.addEventHandler(controller, component, handler);
+ }
+
+ /**
+ * Get events for all components which match the supplied descriptor
+ *
+ * @param descriptor
+ * @param handler
+ */
+ @Override
+ public InputEvent[] getEvents(String descriptor, InputHandler handler)
+ {
+ List events = new ArrayList();
+ Controller controller = this.jInputComponentRegistry.getController(descriptor);
+ if (controller != null)
+ {
+ for (Component component : controller.getComponents())
+ {
+ events.add(this.addEventHandler(controller, component, handler));
+ }
+ }
+
+ return events.toArray(new InputEvent[0]);
+ }
+
+ /**
+ * @param controller
+ * @param component
+ * @param handler
+ */
+ private InputEvent addEventHandler(Controller controller, Component component, InputHandler handler)
+ {
+ if (controller != null && component != null && handler != null)
+ {
+ this.addController(controller);
+
+ InputEvent event = new InputEvent(controller, component, handler);
+ this.componentEvents.put(component, event.link(this.componentEvents.get(component)));
+
+ return event;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param controller
+ */
+ private void addController(Controller controller)
+ {
+ Set controllers = this.getActiveControllers();
+ controllers.add(controller);
+ this.setActiveControllers(controllers);
+ }
+
+ /**
+ *
+ */
+ private Set getActiveControllers()
+ {
+ Set allControllers = new HashSet();
+ for (Controller controller : this.pollControllers)
+ allControllers.add(controller);
+ return allControllers;
+ }
+
+ /**
+ * @param controllers
+ */
+ private void setActiveControllers(Set controllers)
+ {
+ this.pollControllers = controllers.toArray(new Controller[controllers.size()]);
+ }
+
+ /**
+ *
+ */
+ private void pollControllers()
+ {
+ for (Controller controller : this.pollControllers)
+ {
+ controller.poll();
+ EventQueue controllerQueue = controller.getEventQueue();
+
+ for (Event event = new Event(); controllerQueue.getNextEvent(event); )
+ {
+ Component cmp = event.getComponent();
+
+ InputEvent inputEvent = this.componentEvents.get(cmp);
+ if (inputEvent != null)
+ {
+ inputEvent.onEvent(event);
+ }
+ }
+ }
+ }
+}
diff --git a/liteloader/src/client/java/com/mumfrey/liteloader/util/ModUtilities.java b/liteloader/src/client/java/com/mumfrey/liteloader/util/ModUtilities.java
new file mode 100644
index 00000000..e28fb761
--- /dev/null
+++ b/liteloader/src/client/java/com/mumfrey/liteloader/util/ModUtilities.java
@@ -0,0 +1,253 @@
+package com.mumfrey.liteloader.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+
+import com.mumfrey.liteloader.client.ducks.*;
+import com.mumfrey.liteloader.client.overlays.IMinecraft;
+import com.mumfrey.liteloader.client.util.PrivateFieldsClient;
+import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.entity.Render;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
+import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
+import net.minecraft.entity.Entity;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.RegistrySimple;
+import net.minecraft.util.ResourceLocation;
+
+/**
+ * A small collection of useful functions for mods
+ *
+ * @author Adam Mummery-Smith
+ */
+public abstract class ModUtilities
+{
+ /**
+ * @return true if FML is present in the current environment
+ */
+ public static boolean fmlIsPresent()
+ {
+ return ObfuscationUtilities.fmlIsPresent();
+ }
+
+ public static void setWindowSize(int width, int height)
+ {
+ try
+ {
+ Minecraft mc = Minecraft.getMinecraft();
+ Display.setDisplayMode(new DisplayMode(width, height));
+ ((IMinecraft)mc).onResizeWindow(width, height);
+ Display.setVSyncEnabled(mc.gameSettings.enableVsync);
+ }
+ catch (LWJGLException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Add a renderer map entry for the specified entity class
+ *
+ * @param entityClass
+ * @param renderer
+ */
+ public static void addRenderer(Class extends Entity> entityClass, Render renderer)
+ {
+ RenderManager renderManager = Minecraft.getMinecraft().getRenderManager();
+
+ Map, Render> entityRenderMap = ((IRenderManager)renderManager).getRenderMap();
+ if (entityRenderMap != null)
+ {
+ entityRenderMap.put(entityClass, renderer);
+ }
+ else
+ {
+ LiteLoaderLogger.warning("Attempted to set renderer %s for entity class %s but the operation failed",
+ renderer.getClass().getSimpleName(), entityClass.getSimpleName());
+ }
+ }
+
+ public static void addRenderer(Class extends TileEntity> tileEntityClass, TileEntitySpecialRenderer renderer)
+ {
+ TileEntityRendererDispatcher tileEntityRenderer = TileEntityRendererDispatcher.instance;
+
+ try
+ {
+ Map, TileEntitySpecialRenderer> specialRendererMap
+ = ((ITileEntityRendererDispatcher)tileEntityRenderer).getSpecialRenderMap();
+ specialRendererMap.put(tileEntityClass, renderer);
+ renderer.setRendererDispatcher(tileEntityRenderer);
+ }
+ catch (Exception ex)
+ {
+ LiteLoaderLogger.warning("Attempted to set renderer %s for tile entity class %s but the operation failed",
+ renderer.getClass().getSimpleName(), tileEntityClass.getSimpleName());
+ }
+ }
+
+ /**
+ * Add a block to the blocks registry
+ *
+ * @param blockId Block ID to insert
+ * @param blockName Block identifier
+ * @param block Block to register
+ * @param force Force insertion even if the operation is blocked by FMl
+ */
+ public static void addBlock(int blockId, ResourceLocation blockName, Block block, boolean force)
+ {
+ Block existingBlock = (Block)Block.blockRegistry.getObject(blockName);
+
+ try
+ {
+ Block.blockRegistry.register(blockId, blockName, block);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ if (!force) throw new IllegalArgumentException("Could not register block '" + blockName + "', the operation was blocked by FML.", ex);
+
+ ModUtilities.removeObjectFromRegistry(Block.blockRegistry, blockName);
+ Block.blockRegistry.register(blockId, blockName, block);
+ }
+
+ if (existingBlock != null)
+ {
+ try
+ {
+ for (Field field : Blocks.class.getDeclaredFields())
+ {
+ field.setAccessible(true);
+ if (field.isAccessible() && Block.class.isAssignableFrom(field.getType()))
+ {
+ Block fieldValue = (Block)field.get(null);
+ if (fieldValue == existingBlock)
+ {
+ ModUtilities.setFinalStaticField(field, block);
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Add an item to the items registry
+ *
+ * @param itemId Item ID to insert
+ * @param itemName Item identifier
+ * @param item Item to register
+ * @param force Force insertion even if the operation is blocked by FMl
+ */
+ public static void addItem(int itemId, ResourceLocation itemName, Item item, boolean force)
+ {
+ Item existingItem = (Item)Item.itemRegistry.getObject(itemName);
+
+ try
+ {
+ Item.itemRegistry.register(itemId, itemName, item);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ if (!force) throw new IllegalArgumentException("Could not register item '" + itemName + "', the operation was blocked by FML.", ex);
+
+ ModUtilities.removeObjectFromRegistry(Block.blockRegistry, itemName);
+ Item.itemRegistry.register(itemId, itemName, item);
+ }
+
+ if (existingItem != null)
+ {
+ try
+ {
+ for (Field field : Items.class.getDeclaredFields())
+ {
+ field.setAccessible(true);
+ if (field.isAccessible() && Item.class.isAssignableFrom(field.getType()))
+ {
+ Item fieldValue = (Item)field.get(null);
+ if (fieldValue == existingItem)
+ {
+ ModUtilities.setFinalStaticField(field, item);
+ }
+ }
+ }
+ }
+ catch (Exception ex) {}
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void addTileEntity(String entityName, Class extends TileEntity> tileEntityClass)
+ {
+ try
+ {
+ Map> nameToClassMap = PrivateFieldsClient.tileEntityNameToClassMap.get(null);
+ Map, String> classToNameMap = PrivateFieldsClient.tileEntityClassToNameMap.get(null);
+ nameToClassMap.put(entityName, tileEntityClass);
+ classToNameMap.put(tileEntityClass, entityName);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ private static V removeObjectFromRegistry(RegistrySimple registry, K key)
+ {
+ if (registry == null) return null;
+
+ IObjectIntIdentityMap underlyingIntegerMap = null;
+
+ if (registry instanceof INamespacedRegistry)
+ {
+ underlyingIntegerMap = ((INamespacedRegistry)registry).getUnderlyingMap();
+ }
+
+ Map registryObjects = ((IRegistrySimple)registry).getRegistryObjects();
+ if (registryObjects != null)
+ {
+ V existingValue = registryObjects.get(key);
+ if (existingValue != null)
+ {
+ registryObjects.remove(key);
+
+ if (underlyingIntegerMap != null)
+ {
+ IdentityHashMap identityMap = underlyingIntegerMap.getIdentityMap();
+ List objectList = underlyingIntegerMap.getObjectList();
+ if (identityMap != null) identityMap.remove(existingValue);
+ if (objectList != null) objectList.remove(existingValue);
+ }
+
+ return existingValue;
+ }
+ }
+
+ return null;
+ }
+
+ private static void setFinalStaticField(Field field, Object value)
+ throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
+ {
+ Field modifiers = Field.class.getDeclaredField("modifiers");
+ modifiers.setAccessible(true);
+ modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(null, value);
+ }
+}
diff --git a/liteloader/src/client/resources/mixins.liteloader.client.json b/liteloader/src/client/resources/mixins.liteloader.client.json
new file mode 100644
index 00000000..bed9cc0b
--- /dev/null
+++ b/liteloader/src/client/resources/mixins.liteloader.client.json
@@ -0,0 +1,23 @@
+{
+ "required": true,
+ "minVersion": "0.4.10",
+ "package": "com.mumfrey.liteloader.client.mixin",
+ "refmap": "mixins.liteloader.client.refmap.json",
+ "mixins": [
+ "MixinMinecraft",
+ "MixinSession",
+ "MixinEntityRenderer",
+ "MixinRenderManager",
+ "MixinGuiIngame",
+ "MixinEntityPlayerSP",
+ "MixinFramebuffer",
+ "MixinIntegratedServer",
+ "MixinScreenShotHelper",
+ "MixinRealmsMainScreen",
+ "MixinNetHandlerLoginClient",
+ "MixinRegistrySimple",
+ "MixinRegistryNamespaced",
+ "MixinTileEntityRendererDispatcher",
+ "MixinSimpleReloadableResourceManager"
+ ]
+}
\ No newline at end of file
diff --git a/liteloader/src/debug/java/com/mumfrey/liteloader/debug/LoginManager.java b/liteloader/src/debug/java/com/mumfrey/liteloader/debug/LoginManager.java
new file mode 100644
index 00000000..7c56e93a
--- /dev/null
+++ b/liteloader/src/debug/java/com/mumfrey/liteloader/debug/LoginManager.java
@@ -0,0 +1,458 @@
+package com.mumfrey.liteloader.debug;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.net.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.swing.JOptionPane;
+
+import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.gson.annotations.SerializedName;
+import com.mojang.authlib.Agent;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.UserType;
+import com.mojang.authlib.exceptions.AuthenticationException;
+import com.mojang.authlib.exceptions.InvalidCredentialsException;
+import com.mojang.authlib.properties.Property;
+import com.mojang.authlib.properties.PropertyMap;
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
+import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
+
+/**
+ * Manages login requests against Yggdrasil for use in MCP
+ *
+ * @author Adam Mummery-Smith
+ */
+public class LoginManager
+{
+ /**
+ * Gson instance for serialising and deserialising the authentication data
+ */
+ private static Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+ /**
+ * Authentication service
+ */
+ private YggdrasilAuthenticationService authService;
+
+ /**
+ * Authentication agent
+ */
+ private YggdrasilUserAuthentication authentication;
+
+ /**
+ * JSON file to load/save auth data from
+ */
+ private File jsonFile;
+
+ /**
+ * Username read from the auth JSON file, we use this as the default in the
+ * login dialog in case login fails. This is stored in the JSON even if
+ * authentication is not successful so that we can display the same username
+ * next time.
+ */
+ private String defaultUsername;
+
+ /**
+ * Minecraft screen name read from the auth JSON file. Use this as default
+ * in case the login fails or is skipped (when offline) so that at least the
+ * Minecraft client has a sensible display name.
+ *
+ * Defaults to user.name when not specified
+ */
+ private String defaultDisplayName = System.getProperty("user.name");
+
+ /**
+ * True if login should not be attempted, skips the authentication attempt
+ * and the login dialog.
+ */
+ private boolean offline = false;
+
+ /**
+ * If authentication fails with token then the first attempt will be to use
+ * the user/pass specified on the command line (if any). This flag is set
+ * after that first attempt so that we know to display the login
+ * dialog anyway (eg. the login on the command line was bad).
+ */
+ private boolean forceShowLoginDialog = false;
+
+ /**
+ * ctor
+ *
+ * @param jsonFile
+ */
+ public LoginManager(File jsonFile)
+ {
+ this.jsonFile = jsonFile;
+
+ this.resetAuth();
+ this.load();
+ }
+
+ /**
+ * When authenticaion fails, we regenerate the auth service and agent
+ * because trying again with the same client data will fail.
+ */
+ public void resetAuth()
+ {
+ this.authService = new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString());
+ this.authentication = new YggdrasilUserAuthentication(this.authService, Agent.MINECRAFT);
+ }
+
+ /**
+ * Load auth data from the json file
+ */
+ private void load()
+ {
+ if (this.jsonFile != null && this.jsonFile.exists())
+ {
+ FileReader fileReader = null;
+
+ try
+ {
+ fileReader = new FileReader(this.jsonFile);
+ AuthData authData = LoginManager.gson.fromJson(fileReader, AuthData.class);
+
+ if (authData != null && authData.validate())
+ {
+ LiteLoaderLogger.info("Initialising Yggdrasil authentication service with client token: %s", authData.getClientToken());
+ this.authService = new YggdrasilAuthenticationService(Proxy.NO_PROXY, authData.getClientToken());
+ this.authentication = new YggdrasilUserAuthentication(this.authService, Agent.MINECRAFT);
+ authData.loadFromStorage(this.authentication);
+ this.offline = authData.workOffline();
+ this.defaultUsername = authData.getUsername();
+ this.defaultDisplayName = authData.getDisplayName();
+ }
+ }
+ catch (IOException ex) {}
+ finally
+ {
+ try
+ {
+ if (fileReader != null) fileReader.close();
+ }
+ catch (IOException ex) {}
+ }
+ }
+ }
+
+ /**
+ * Save auth data to the JSON file
+ */
+ private void save()
+ {
+ if (this.jsonFile != null)
+ {
+ FileWriter fileWriter = null;
+
+ try
+ {
+ fileWriter = new FileWriter(this.jsonFile);
+
+ AuthData authData = new AuthData(this.authService, this.authentication, this.offline, this.defaultUsername, this.defaultDisplayName);
+ LoginManager.gson.toJson(authData, fileWriter);
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ if (fileWriter != null) fileWriter.close();
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Attempt to login. If authentication data are found on disk then tries
+ * first to log in with the stored token. If the token login fails then
+ * attempts to log in with the username and password specified. If no user
+ * or pass are specified or if they fail then displays a login dialog to
+ * allow the user to login. If login succeeds then the token is stored on
+ * disk and the method returns.
+ *
+ * If the user presses cancel in the login dialog then the method returns
+ * false.
+ *
+ * @param username User name to log in with if token login fails, if null
+ * displays the login dialog immediately
+ * @param password Password to log in with if token login fails, if null
+ * displays the login dialog immediately
+ * @param remainingTries Number of loops to go through before giving up,
+ * decremented for each try, specify -1 for unlimited
+ * @return false if the user presses cancel in the login dialog, otherwise
+ * returns true
+ */
+ public boolean login(String username, String password, int remainingTries)
+ {
+ if (this.offline || remainingTries == 0)
+ {
+ LiteLoaderLogger.info("LoginManager is set to work offline, skipping login");
+ return false;
+ }
+
+ LiteLoaderLogger.info("Remaining login tries: %s", remainingTries > 0 ? remainingTries : "unlimited");
+
+ try
+ {
+ LiteLoaderLogger.info("Attempting login, contacting Mojang auth servers...");
+
+ this.authentication.logIn();
+
+ if (this.authentication.isLoggedIn())
+ {
+ LiteLoaderLogger.info("LoginManager logged in successfully. Can play online = %s", this.authentication.canPlayOnline());
+ this.save();
+ return true;
+ }
+
+ LiteLoaderLogger.info("LoginManager failed to log in, unspecified status.");
+ }
+ catch (InvalidCredentialsException ex)
+ {
+ LiteLoaderLogger.info("Authentication agent reported invalid credentials: %s", ex.getMessage());
+ this.resetAuth();
+
+ if (remainingTries > 1)
+ {
+ if (username == null)
+ {
+ username = this.defaultUsername;
+ }
+
+ if (this.forceShowLoginDialog || username == null || password == null)
+ {
+ LoginPanel loginPanel = LoginPanel.getLoginPanel(username, password, this.forceShowLoginDialog ? ex.getMessage() : null);
+ boolean dialogResult = loginPanel.showModalDialog();
+ this.offline = loginPanel.workOffline();
+ this.defaultUsername = loginPanel.getUsername();
+
+ if (!dialogResult)
+ {
+ LiteLoaderLogger.info("User cancelled login dialog");
+ return false;
+ }
+
+ if (this.offline)
+ {
+ if (JOptionPane.showConfirmDialog(null, "You have chosen to work offline. "
+ + "You will never be prompted to log in again.
"
+ + "If you would like to re-enable login please delete the file .auth.json "
+ + "from the working dir
"
+ + "or press Cancel to return to the login dialog.",
+ "Confirm work offline",
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.INFORMATION_MESSAGE) == JOptionPane.CANCEL_OPTION)
+ {
+ this.offline = false;
+ remainingTries = Math.max(remainingTries, 3);
+ }
+ }
+
+ username = loginPanel.getUsername();
+ password = loginPanel.getPassword();
+ this.save();
+ }
+
+ if (!Strings.isNullOrEmpty(username) && !Strings.isNullOrEmpty(password))
+ {
+ this.authentication.setUsername(username);
+ this.authentication.setPassword(password);
+ }
+
+ this.forceShowLoginDialog = true;
+ this.login(username, password, --remainingTries);
+ }
+ }
+ catch (AuthenticationException ex)
+ {
+ ex.printStackTrace();
+ }
+
+ this.save();
+ return false;
+ }
+
+ /**
+ * Get whether user logged in
+ */
+ public boolean isLoggedIn()
+ {
+ return this.authentication.isLoggedIn();
+ }
+
+ /**
+ * Get whether we are able to play online or not
+ */
+ public boolean canPlayOnline()
+ {
+ return this.authentication.canPlayOnline();
+ }
+
+ /**
+ * Get the profile name (minecraft player name) from login
+ */
+ public String getProfileName()
+ {
+ GameProfile selectedProfile = this.authentication.getSelectedProfile();
+ return selectedProfile != null ? selectedProfile.getName() : this.defaultDisplayName;
+ }
+
+ /**
+ * Get the profile name (minecraft player name) from login
+ */
+ public String getUUID()
+ {
+ GameProfile selectedProfile = this.authentication.getSelectedProfile();
+ return selectedProfile != null ? selectedProfile.getId().toString().replace("-", "") : this.defaultDisplayName;
+ }
+
+ /**
+ * Get the session token
+ */
+ public String getAuthenticatedToken()
+ {
+ String accessToken = this.authentication.getAuthenticatedToken();
+ return accessToken != null ? accessToken : "-";
+ }
+
+ public String getUserType()
+ {
+ UserType userType = this.authentication.getUserType();
+ return (userType != null ? userType : UserType.LEGACY).toString().toLowerCase();
+ }
+
+ public String getUserProperties()
+ {
+ PropertyMap userProperties = this.authentication.getUserProperties();
+ return userProperties != null ? (new GsonBuilder()).registerTypeAdapter(PropertyMap.class,
+ new UserPropertiesSerializer()).create().toJson(userProperties) : "{}";
+ }
+
+ class UserPropertiesSerializer implements JsonSerializer
+ {
+ @Override
+ public JsonElement serialize(PropertyMap propertyMap, Type argType, JsonSerializationContext context)
+ {
+ JsonObject result = new JsonObject();
+
+ for (String key : propertyMap.keySet())
+ {
+ JsonArray values = new JsonArray();
+ for (Property property : propertyMap.get(key))
+ {
+ values.add(new JsonPrimitive(property.getValue()));
+ }
+
+ result.add(key, values);
+ }
+
+ return result;
+ }
+ }
+
+
+ /**
+ * Struct for Gson serialisation of authenticaion settings
+ *
+ * @author Adam Mummery-Smith
+ */
+ class AuthData
+ {
+ @SerializedName("clientToken")
+ private String clientToken;
+
+ @SerializedName("workOffline")
+ private boolean workOffline;
+
+ @SerializedName("authData")
+ private Map credentials;
+
+ public AuthData()
+ {
+ // default ctor for Gson
+ }
+
+ public AuthData(YggdrasilAuthenticationService authService, YggdrasilUserAuthentication authentication, boolean workOffline,
+ String defaultUserName, String defaultDisplayName)
+ {
+ this.clientToken = authService.getClientToken();
+ this.credentials = authentication.saveForStorage();
+ this.workOffline = workOffline;
+
+ if (defaultUserName != null && !this.credentials.containsKey("username"))
+ {
+ this.credentials.put("username", defaultUserName);
+ }
+
+ if (defaultDisplayName != null && !this.credentials.containsKey("displayName"))
+ {
+ this.credentials.put("displayName", defaultDisplayName);
+ }
+ }
+
+ /**
+ * Called after Gson deserialisation to check that deserialisation was
+ * successful.
+ */
+ public boolean validate()
+ {
+ if (this.clientToken == null) this.clientToken = UUID.randomUUID().toString();
+ if (this.credentials == null) this.credentials = new HashMap();
+ return true;
+ }
+
+ public String getClientToken()
+ {
+ return this.clientToken;
+ }
+
+ public void setClientToken(String clientToken)
+ {
+ this.clientToken = clientToken;
+ }
+
+ public void loadFromStorage(YggdrasilUserAuthentication authentication)
+ {
+ authentication.loadFromStorage(this.credentials);
+ }
+
+ public boolean workOffline()
+ {
+ return this.workOffline;
+ }
+
+ public String getUsername()
+ {
+ return this.credentials != null ? this.credentials.get("username").toString() : null;
+ }
+
+ public String getDisplayName()
+ {
+ return this.credentials != null && this.credentials.containsKey("displayName")
+ ? this.credentials.get("displayName").toString() : System.getProperty("user.name");
+ }
+ }
+}
diff --git a/liteloader/src/debug/java/com/mumfrey/liteloader/debug/LoginPanel.java b/liteloader/src/debug/java/com/mumfrey/liteloader/debug/LoginPanel.java
new file mode 100644
index 00000000..5614e8ba
--- /dev/null
+++ b/liteloader/src/debug/java/com/mumfrey/liteloader/debug/LoginPanel.java
@@ -0,0 +1,366 @@
+package com.mumfrey.liteloader.debug;
+
+import static javax.swing.WindowConstants.*;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.TitledBorder;
+
+/**
+ * JPanel displayed in a JDialog to prompt the user for login credentials for
+ * minecraft.
+ *
+ * @author Adam Mummery-Smith
+ */
+public class LoginPanel extends JPanel
+{
+ private static final long serialVersionUID = 1L;
+
+ private GridBagLayout panelLoginLayout;
+
+ private JPanel panelTitle;
+ private JPanel panelCentre;
+ private JPanel panelPadding;
+ private JPanel panelBottom;
+ private JLabel lblTitle;
+ private JLabel lblSubTitle;
+ private JLabel lblMessage;
+ private JLabel lblUserName;
+ private JLabel lblPassword;
+ private TextField txtUsername;
+ private TextField txtPassword;
+ private JButton btnLogin;
+ private JButton btnCancel;
+ private JCheckBox chkOffline;
+
+ private JDialog dialog;
+
+ private ListFocusTraversal tabOrder = new ListFocusTraversal();
+
+ private boolean dialogResult = false;
+
+ public LoginPanel(String username, String password, String error)
+ {
+ Color backColour = new Color(102, 118, 144);
+
+ this.setFocusable(false);
+ this.setPreferredSize(new Dimension(400, 260));
+ this.setBackground(new Color(105, 105, 105));
+ this.setLayout(new BorderLayout(0, 0));
+
+ this.panelTitle = new JPanel();
+ this.panelTitle.setBackground(backColour);
+ this.panelTitle.setPreferredSize(new Dimension(400, 64));
+ this.panelTitle.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
+
+ this.panelBottom = new JPanel();
+ this.panelBottom.setBackground(backColour);
+ this.panelBottom.setPreferredSize(new Dimension(400, 32));
+ this.panelBottom.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
+
+ this.panelPadding = new JPanel();
+ this.panelPadding.setBorder(new EmptyBorder(4, 8, 8, 8));
+ this.panelPadding.setOpaque(false);
+ this.panelPadding.setLayout(new BorderLayout(0, 0));
+
+ this.panelCentre = new JPanel();
+ this.panelCentre.setOpaque(false);
+ this.panelCentre.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Yggdrasil Login",
+ TitledBorder.LEADING, TitledBorder.TOP, null, Color.WHITE));
+ this.panelLoginLayout = new GridBagLayout();
+ this.panelLoginLayout.columnWidths = new int[] {30, 80, 120, 120, 30};
+ this.panelLoginLayout.rowHeights = new int[] {24, 32, 32, 32};
+ this.panelLoginLayout.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
+ this.panelLoginLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0};
+ this.panelCentre.setLayout(this.panelLoginLayout);
+
+ this.lblTitle = new JLabel("Log in to minecraft.net");
+ this.lblTitle.setBorder(new EmptyBorder(4, 16, 0, 16));
+ this.lblTitle.setFont(new Font("Tahoma", Font.BOLD, 18));
+ this.lblTitle.setForeground(Color.WHITE);
+ this.lblTitle.setPreferredSize(new Dimension(400, 26));
+
+ this.lblSubTitle = new JLabel("Your password will not be stored, logging in with Yggdrasil");
+ this.lblSubTitle.setBorder(new EmptyBorder(0, 16, 0, 16));
+ this.lblSubTitle.setForeground(Color.WHITE);
+ this.lblSubTitle.setPreferredSize(new Dimension(400, 16));
+
+ this.lblMessage = new JLabel("Enter your login details for minecraft.net");
+ this.lblMessage.setForeground(Color.WHITE);
+
+ this.lblUserName = new JLabel("User name");
+ this.lblUserName.setForeground(Color.WHITE);
+
+ this.lblPassword = new JLabel("Password");
+ this.lblPassword.setForeground(Color.WHITE);
+
+ this.txtUsername = new TextField();
+ this.txtUsername.setPreferredSize(new Dimension(200, 22));
+ this.txtUsername.setText(username);
+
+ this.txtPassword = new TextField();
+ this.txtPassword.setEchoChar('*');
+ this.txtPassword.setPreferredSize(new Dimension(200, 22));
+ this.txtPassword.setText(password);
+
+ this.btnLogin = new JButton("Log in");
+ this.btnLogin.addActionListener(new ActionListener()
+ {
+ @Override public void actionPerformed(ActionEvent e)
+ {
+ LoginPanel.this.onLoginClick();
+ }
+ });
+
+ this.btnCancel = new JButton("Cancel");
+ this.btnCancel.addActionListener(new ActionListener()
+ {
+ @Override public void actionPerformed(ActionEvent e)
+ {
+ LoginPanel.this.onCancelClick();
+ }
+ });
+
+ this.chkOffline = new JCheckBox("Never ask me to log in (always run offline)");
+ this.chkOffline.setPreferredSize(new Dimension(380, 23));
+ this.chkOffline.setForeground(Color.WHITE);
+ this.chkOffline.setOpaque(false);
+ this.chkOffline.addActionListener(new ActionListener()
+ {
+ @Override public void actionPerformed(ActionEvent e)
+ {
+ LoginPanel.this.onOfflineCheckedChanged();
+ }
+ });
+
+ GridBagConstraints lblMessageConstraints = new GridBagConstraints();
+ lblMessageConstraints.anchor = GridBagConstraints.WEST;
+ lblMessageConstraints.gridwidth = 2;
+ lblMessageConstraints.insets = new Insets(0, 0, 5, 5);
+ lblMessageConstraints.gridx = 2;
+ lblMessageConstraints.gridy = 0;
+
+ GridBagConstraints lblUserNameConstraints = new GridBagConstraints();
+ lblUserNameConstraints.anchor = GridBagConstraints.WEST;
+ lblUserNameConstraints.fill = GridBagConstraints.VERTICAL;
+ lblUserNameConstraints.insets = new Insets(0, 0, 5, 5);
+ lblUserNameConstraints.gridx = 1;
+ lblUserNameConstraints.gridy = 1;
+
+ GridBagConstraints lblPasswordConstraints = new GridBagConstraints();
+ lblPasswordConstraints.anchor = GridBagConstraints.WEST;
+ lblPasswordConstraints.fill = GridBagConstraints.VERTICAL;
+ lblPasswordConstraints.insets = new Insets(0, 0, 5, 5);
+ lblPasswordConstraints.gridx = 1;
+ lblPasswordConstraints.gridy = 2;
+
+ GridBagConstraints txtUsernameConstraints = new GridBagConstraints();
+ txtUsernameConstraints.gridwidth = 2;
+ txtUsernameConstraints.fill = GridBagConstraints.HORIZONTAL;
+ txtUsernameConstraints.insets = new Insets(0, 0, 5, 0);
+ txtUsernameConstraints.gridx = 2;
+ txtUsernameConstraints.gridy = 1;
+
+ GridBagConstraints txtPasswordConstraints = new GridBagConstraints();
+ txtPasswordConstraints.gridwidth = 2;
+ txtPasswordConstraints.insets = new Insets(0, 0, 5, 0);
+ txtPasswordConstraints.fill = GridBagConstraints.HORIZONTAL;
+ txtPasswordConstraints.gridx = 2;
+ txtPasswordConstraints.gridy = 2;
+
+ GridBagConstraints btnLoginConstraints = new GridBagConstraints();
+ btnLoginConstraints.fill = GridBagConstraints.HORIZONTAL;
+ btnLoginConstraints.gridx = 3;
+ btnLoginConstraints.gridy = 3;
+
+ GridBagConstraints btnCancelConstraints = new GridBagConstraints();
+ btnCancelConstraints.anchor = GridBagConstraints.EAST;
+ btnCancelConstraints.insets = new Insets(0, 0, 0, 5);
+ btnCancelConstraints.gridx = 2;
+ btnCancelConstraints.gridy = 3;
+
+ this.add(this.panelTitle, BorderLayout.NORTH);
+ this.add(this.panelPadding, BorderLayout.CENTER);
+ this.add(this.panelBottom, BorderLayout.SOUTH);
+
+ this.panelPadding.add(this.panelCentre);
+
+ this.panelTitle.add(this.lblTitle);
+ this.panelTitle.add(this.lblSubTitle);
+
+ this.panelCentre.add(this.lblMessage, lblMessageConstraints);
+ this.panelCentre.add(this.lblUserName, lblUserNameConstraints);
+ this.panelCentre.add(this.lblPassword, lblPasswordConstraints);
+ this.panelCentre.add(this.txtUsername, txtUsernameConstraints);
+ this.panelCentre.add(this.txtPassword, txtPasswordConstraints);
+ this.panelCentre.add(this.btnLogin, btnLoginConstraints);
+ this.panelCentre.add(this.btnCancel, btnCancelConstraints);
+
+ this.panelBottom.add(this.chkOffline);
+
+ this.tabOrder.add(this.txtUsername);
+ this.tabOrder.add(this.txtPassword);
+ this.tabOrder.add(this.btnLogin);
+ this.tabOrder.add(this.btnCancel);
+ this.tabOrder.add(this.chkOffline);
+
+ if (error != null)
+ {
+ this.lblMessage.setText(error);
+ this.lblMessage.setForeground(new Color(255, 180, 180));
+ }
+ }
+
+ protected void onShowDialog()
+ {
+ if (this.txtUsername.getText().length() > 0)
+ {
+ if (this.txtPassword.getText().length() > 0)
+ {
+ this.txtUsername.select(0, this.txtUsername.getText().length());
+ }
+ else
+ {
+ this.txtPassword.requestFocusInWindow();
+ }
+ }
+ }
+
+ protected void onLoginClick()
+ {
+ this.dialogResult = true;
+ this.dialog.setVisible(false);
+ }
+
+ protected void onCancelClick()
+ {
+ this.dialog.setVisible(false);
+ }
+
+ protected void onOfflineCheckedChanged()
+ {
+ boolean selected = this.chkOffline.isSelected();
+ this.btnLogin.setText(selected ? "Work Offline" : "Log In");
+ this.txtUsername.setEnabled(!selected);
+ this.txtPassword.setEnabled(!selected);
+ }
+
+ /**
+ * @param dialog
+ */
+ public void setDialog(JDialog dialog)
+ {
+ this.dialog = dialog;
+
+ this.dialog.addWindowListener(new WindowAdapter()
+ {
+ @Override
+ public void windowOpened(WindowEvent e)
+ {
+ LoginPanel.this.onShowDialog();
+ }
+ });
+
+ this.dialog.getRootPane().setDefaultButton(this.btnLogin);
+ this.dialog.setFocusTraversalPolicy(this.tabOrder);
+ }
+
+ public boolean showModalDialog()
+ {
+ this.dialog.setVisible(true);
+ this.dialog.dispose();
+ return this.dialogResult;
+ }
+
+ public String getUsername()
+ {
+ return this.txtUsername.getText();
+ }
+
+ public String getPassword()
+ {
+ return this.txtPassword.getText();
+ }
+
+ public boolean workOffline()
+ {
+ return this.chkOffline.isSelected();
+ }
+
+ public static LoginPanel getLoginPanel(String username, String password, String error)
+ {
+ if (username == null) username = "";
+ if (password == null) password = "";
+
+ final JDialog dialog = new JDialog();
+ final LoginPanel panel = new LoginPanel(username, password, error);
+ panel.setDialog(dialog);
+
+ dialog.setContentPane(panel);
+ dialog.setTitle("Yggdrasil Login");
+ dialog.setResizable(false);
+ dialog.pack();
+ dialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+ dialog.setLocationRelativeTo(null);
+ dialog.setModal(true);
+
+ return panel;
+ }
+
+ class ListFocusTraversal extends FocusTraversalPolicy
+ {
+ private final List components = new ArrayList();
+
+ void add(Component component)
+ {
+ this.components.add(component);
+ }
+
+ @Override
+ public Component getComponentAfter(Container container, Component component)
+ {
+ int index = this.components.indexOf(component) + 1;
+ if (index >= this.components.size()) return this.components.get(0);
+ return this.components.get(index);
+ }
+
+ @Override
+ public Component getComponentBefore(Container container, Component component)
+ {
+ int index = this.components.indexOf(component) - 1;
+ if (index < 0) return this.getLastComponent(container);
+ return this.components.get(index);
+ }
+
+ @Override
+ public Component getFirstComponent(Container container)
+ {
+ return this.components.get(0);
+ }
+
+ @Override
+ public Component getLastComponent(Container container)
+ {
+ return this.components.get(this.components.size() - 1);
+ }
+
+ @Override
+ public Component getDefaultComponent(Container container)
+ {
+ return this.getFirstComponent(container);
+ }
+ }
+}
diff --git a/liteloader/src/debug/java/com/mumfrey/liteloader/debug/Start.java b/liteloader/src/debug/java/com/mumfrey/liteloader/debug/Start.java
new file mode 100644
index 00000000..7e3240d3
--- /dev/null
+++ b/liteloader/src/debug/java/com/mumfrey/liteloader/debug/Start.java
@@ -0,0 +1,204 @@
+package com.mumfrey.liteloader.debug;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import net.minecraft.launchwrapper.Launch;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
+import com.mumfrey.liteloader.launch.LiteLoaderTweakerServer;
+import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
+
+/**
+ * Wrapper class for LaunchWrapper Main class, which logs in using Yggdrasil
+ * first so that online shizzle can be tested.
+ *
+ * @author Adam Mummery-Smith
+ */
+public abstract class Start
+{
+ /**
+ * Number of times to retry Yggdrasil login
+ */
+ private static final int LOGIN_RETRIES = 5;
+
+ /**
+ * Arguments which are allowed to have multiple occurrences
+ */
+ private static final Set MULTI_VALUE_ARGS = ImmutableSet.of(
+ "--tweakClass"
+ );
+
+ /**
+ * Entry point.
+ *
+ * @param args
+ */
+ public static void main(String[] args)
+ {
+ System.setProperty("mcpenv", "true");
+ Launch.main(Start.processArgs(args));
+ }
+
+ /**
+ * Process the launch-time args, since we may be being launched by
+ * GradleStart we need to parse out any values passed in and ensure we
+ * replace them with our own.
+ */
+ private static String[] processArgs(String[] args)
+ {
+ List unqualifiedArgs = new ArrayList();
+ Map> qualifiedArgs = new HashMap>();
+
+ Start.parseArgs(args, unqualifiedArgs, qualifiedArgs);
+
+ if (Start.hasArg(unqualifiedArgs, "server"))
+ {
+ Start.addRequiredArgsServer(args, unqualifiedArgs, qualifiedArgs);
+ }
+ else
+ {
+ Start.addRequiredArgsClient(args, unqualifiedArgs, qualifiedArgs);
+ }
+
+ args = Start.combineArgs(args, unqualifiedArgs, qualifiedArgs);
+
+ return args;
+ }
+
+ private static boolean hasArg(List args, String target)
+ {
+ for (String arg : args)
+ {
+ if (target.equalsIgnoreCase(arg))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Read the args from the command line into the qualified and unqualified
+ * collections.
+ */
+ private static void parseArgs(String[] args, List unqualifiedArgs, Map> qualifiedArgs)
+ {
+ String qualifier = null;
+ for (String arg : args)
+ {
+ boolean isQualifier = arg.startsWith("-");
+
+ if (isQualifier)
+ {
+ if (qualifier != null) unqualifiedArgs.add(qualifier);
+ qualifier = arg;
+ }
+ else if (qualifier != null)
+ {
+ Start.addArg(qualifiedArgs, qualifier, arg);
+ qualifier = null;
+ }
+ else
+ {
+ unqualifiedArgs.add(arg);
+ }
+ }
+
+ if (qualifier != null) unqualifiedArgs.add(qualifier);
+ }
+
+ private static void addRequiredArgsClient(String[] args, List unqualifiedArgs, Map> qualifiedArgs)
+ {
+ LoginManager loginManager = Start.doLogin(qualifiedArgs);
+
+ File gameDir = new File(System.getProperty("user.dir"));
+ File assetsDir = new File(gameDir, "assets");
+
+ Start.addArg(qualifiedArgs, "--tweakClass", LiteLoaderTweaker.class.getName());
+ Start.addArg(qualifiedArgs, "--username", loginManager.getProfileName());
+ Start.addArg(qualifiedArgs, "--uuid", loginManager.getUUID());
+ Start.addArg(qualifiedArgs, "--accessToken", loginManager.getAuthenticatedToken());
+ Start.addArg(qualifiedArgs, "--userType", loginManager.getUserType());
+ Start.addArg(qualifiedArgs, "--userProperties", loginManager.getUserProperties());
+ Start.addArg(qualifiedArgs, "--version", "mcp");
+ Start.addArg(qualifiedArgs, "--gameDir", gameDir.getAbsolutePath());
+ Start.addArg(qualifiedArgs, "--assetIndex", LiteLoaderTweaker.VERSION);
+ Start.addArg(qualifiedArgs, "--assetsDir", assetsDir.getAbsolutePath());
+ }
+
+ private static void addRequiredArgsServer(String[] args, List unqualifiedArgs, Map> qualifiedArgs)
+ {
+ File gameDir = new File(System.getProperty("user.dir"));
+
+ Start.addArg(qualifiedArgs, "--tweakClass", LiteLoaderTweakerServer.class.getName());
+ Start.addArg(qualifiedArgs, "--version", "mcp");
+ Start.addArg(qualifiedArgs, "--gameDir", gameDir.getAbsolutePath());
+ }
+
+ private static LoginManager doLogin(Map> qualifiedArgs)
+ {
+ File loginJson = new File(new File(System.getProperty("user.dir")), ".auth.json");
+ LoginManager loginManager = new LoginManager(loginJson);
+
+ String usernameFromCmdLine = Start.getArg(qualifiedArgs, "--username");
+ String passwordFromCmdLine = Start.getArg(qualifiedArgs, "--password");
+
+ loginManager.login(usernameFromCmdLine, passwordFromCmdLine, Start.LOGIN_RETRIES);
+
+ LiteLoaderLogger.info("Launching game as %s", loginManager.getProfileName());
+
+ return loginManager;
+ }
+
+ private static void addArg(Map> qualifiedArgs, String qualifier, String arg)
+ {
+ Set args = qualifiedArgs.get(qualifier);
+
+ if (args == null)
+ {
+ args = new HashSet();
+ qualifiedArgs.put(qualifier, args);
+ }
+
+ if (!Start.MULTI_VALUE_ARGS.contains(qualifier))
+ {
+ args.clear();
+ }
+
+ args.add(arg);
+ }
+
+ private static String getArg(Map> qualifiedArgs, String arg)
+ {
+ if (qualifiedArgs.containsKey(arg))
+ {
+ return qualifiedArgs.get(arg).iterator().next();
+ }
+
+ return null;
+ }
+
+ private static String[] combineArgs(String[] args, List unqualifiedArgs, Map> qualifiedArgs)
+ {
+ for (Entry> qualifiedArg : qualifiedArgs.entrySet())
+ {
+ for (String argValue : qualifiedArg.getValue())
+ {
+ unqualifiedArgs.add(qualifiedArg.getKey());
+ if (!Strings.isNullOrEmpty(argValue)) unqualifiedArgs.add(argValue);
+ }
+ }
+
+ return unqualifiedArgs.toArray(args);
+ }
+}
diff --git a/liteloader/src/debug/resources/obfuscation.properties b/liteloader/src/debug/resources/obfuscation.properties
new file mode 100644
index 00000000..e5d91592
--- /dev/null
+++ b/liteloader/src/debug/resources/obfuscation.properties
@@ -0,0 +1,69 @@
+field_71424_I=mcProfiler
+field_78729_o=entityRenderMap
+field_110546_b=reloadListeners
+field_147393_d=networkManager
+field_82596_a=registryObjects
+field_148759_a=underlyingIntegerMap
+field_148749_a=identityMap
+field_148748_b=objectList
+field_147559_m=mapSpecialRenderers
+field_145855_i=nameToClassMap
+field_145853_j=classToNameMap
+field_71428_T=timer
+field_71424_I=mcProfiler
+field_71425_J=running
+field_110449_ao=defaultResourcePacks
+field_71475_ae=serverName
+field_71477_af=serverPort
+field_147712_ad=shaderResourceLocations
+field_147713_ae=shaderIndex
+field_175083_ad=useShader
+field_149528_b=view
+field_70163_u=posY
+field_148919_a=chatComponent
+func_148833_a=processPacket
+func_71411_J=runGameLoop
+func_71407_l=runTick
+func_78480_b=updateCameraAndRender
+func_78471_a=renderWorld
+func_175180_a=renderGameOverlay
+func_76320_a=startSection
+func_76319_b=endSection
+func_76318_c=endStartSection
+func_148545_a=createPlayerForUser
+func_72368_a=recreatePlayerEntity
+func_72355_a=initializeConnectionToPlayer
+func_72377_c=playerLoggedIn
+func_72367_e=playerLoggedOut
+func_71384_a=startGame
+func_71197_b=startServer
+func_71256_s=startServerThread
+func_71165_d=sendChatMessage
+func_147119_ah=updateFramebufferSize
+func_147615_c=framebufferRender
+func_178038_a=framebufferRenderExt
+func_147612_c=bindFramebufferTexture
+func_146230_a=drawChat
+func_179086_m=clear
+func_175068_a=renderWorldPass
+func_148256_e=getProfile
+func_148260_a=saveScreenshot
+func_148822_b=isFramebufferEnabled
+func_147939_a=doRenderEntity
+func_76986_a=doRender
+func_71370_a=resize
+func_175069_a=loadShader
+func_78481_a=getFOVModifier
+func_78479_a=setupCameraTransform
+func_147693_a=loadSoundResource
+func_180784_a=onBlockClicked
+func_180236_a=activateBlockOrUseItem
+func_147346_a=processPlayerBlockPlacement
+func_175087_a=handleAnimation
+func_147345_a=processPlayerDigging
+func_71190_q=updateTimeLightAndEntities
+func_180031_a=checkThreadAndEnqueue
+func_147347_a=processPlayer
+func_174976_a=renderSky
+func_180437_a=renderCloudsCheck
+func_78468_a=setupFog
\ No newline at end of file
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/Configurable.java b/liteloader/src/main/java/com/mumfrey/liteloader/Configurable.java
new file mode 100644
index 00000000..f73ac2de
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/Configurable.java
@@ -0,0 +1,20 @@
+package com.mumfrey.liteloader;
+
+import com.mumfrey.liteloader.modconfig.ConfigPanel;
+
+/**
+ * Interface for mods which want to provide a configuration panel inside the
+ * "mod info" screen.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface Configurable
+{
+ /**
+ * Get the class of the configuration panel to use, the returned class must
+ * have a default (no-arg) constructor
+ *
+ * @return configuration panel class
+ */
+ public abstract Class extends ConfigPanel> getConfigPanelClass();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/LiteMod.java b/liteloader/src/main/java/com/mumfrey/liteloader/LiteMod.java
new file mode 100644
index 00000000..4df09ec4
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/LiteMod.java
@@ -0,0 +1,40 @@
+package com.mumfrey.liteloader;
+
+import java.io.File;
+
+import com.mumfrey.liteloader.api.Listener;
+import com.mumfrey.liteloader.modconfig.Exposable;
+
+/**
+ * Base interface for mods
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface LiteMod extends Exposable, Listener
+{
+ /**
+ * Get the mod version string
+ *
+ * @return the mod version as a string
+ */
+ public abstract String getVersion();
+
+ /**
+ * Do startup stuff here, minecraft is not fully initialised when this
+ * function is called so mods must not interact with minecraft in any
+ * way here.
+ *
+ * @param configPath Configuration path to use
+ */
+ public abstract void init(File configPath);
+
+ /**
+ * Called when the loader detects that a version change has happened since
+ * this mod was last loaded.
+ *
+ * @param version new version
+ * @param configPath Path for the new version-specific config
+ * @param oldConfigPath Path for the old version-specific config
+ */
+ public abstract void upgradeSettings(String version, File configPath, File oldConfigPath);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/PacketHandler.java b/liteloader/src/main/java/com/mumfrey/liteloader/PacketHandler.java
new file mode 100644
index 00000000..6c4ada21
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/PacketHandler.java
@@ -0,0 +1,32 @@
+package com.mumfrey.liteloader;
+
+import java.util.List;
+
+import net.minecraft.network.INetHandler;
+import net.minecraft.network.Packet;
+
+/**
+ * Interface for mods which want to handle raw packets
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface PacketHandler extends LiteMod
+{
+ /**
+ * Get list of packets to handle
+ */
+ public List> getHandledPackets();
+
+ /**
+ * @param netHandler The vanilla nethandler which will handle this packet if
+ * not cancelled
+ * @param packet Incoming packet
+ * @return True to allow further processing of this packet, including other
+ * PacketHandlers and eventually the vanilla netHandler, to inhibit
+ * further processing return false. You may choose to return false and
+ * then invoke the vanilla handler method on the supplied INetHandler
+ * if you wish to inhibit later PacketHandlers but preserve vanilla
+ * behaviour.
+ */
+ public abstract boolean handlePacket(INetHandler netHandler, Packet packet);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/Permissible.java b/liteloader/src/main/java/com/mumfrey/liteloader/Permissible.java
new file mode 100644
index 00000000..5b8a7cad
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/Permissible.java
@@ -0,0 +1,55 @@
+package com.mumfrey.liteloader;
+
+import com.mumfrey.liteloader.permissions.PermissionsManager;
+import com.mumfrey.liteloader.permissions.PermissionsManagerClient;
+
+/**
+ * Interface for mods which use the ClientPermissions system
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface Permissible extends LiteMod
+{
+ /**
+ * Returns the node name of the mod, replicated permissions will be of the
+ * form mod..permission.node so this method must return a valid name
+ * for use in permission nodes. This method must also return the same value
+ * every time it is called since permissible names are not necessarily
+ * cached.
+ *
+ * @return Permissible name
+ */
+ public abstract String getPermissibleModName();
+
+ /**
+ * The mod version to replicate to the server
+ *
+ * @return Mod version as a float
+ */
+ public abstract float getPermissibleModVersion();
+
+ /**
+ * Called by the permissions manager at initialisation to instruct the mod
+ * to populate the list of permissions it supports. This method should call
+ * back against the supplied permissions manager to register the permissions
+ * to be sent to the server when connecting.
+ *
+ * @param permissionsManager Client permissions manager
+ */
+ public abstract void registerPermissions(PermissionsManagerClient permissionsManager);
+
+ /**
+ * Called when the permissions set is cleared
+ *
+ * @param manager
+ */
+ public abstract void onPermissionsCleared(PermissionsManager manager);
+
+ /**
+ * Called when the permissions are changed (eg. when new permissions are
+ * received from the server)
+ *
+ * @param manager
+ */
+ public abstract void onPermissionsChanged(PermissionsManager manager);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/PlayerInteractionListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/PlayerInteractionListener.java
new file mode 100644
index 00000000..a63a1b4a
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/PlayerInteractionListener.java
@@ -0,0 +1,58 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.MovingObjectPosition.MovingObjectType;
+
+/**
+ * Interface for mods which want to observe the player's "interaction" status
+ * (player mouse clicks), allows block interaction events to be cancelled.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface PlayerInteractionListener extends LiteMod
+{
+ /**
+ * Mouse buttons
+ */
+ public static enum MouseButton
+ {
+ LEFT,
+ RIGHT
+ }
+
+ /**
+ * Called when the player clicks but does not "hit" a block, the trace
+ * position is raytraced to the player's current view distance and
+ * represents the block which the player is "looking at". This method is
+ * not called when the player right clicks with an empty hand.
+ *
+ * @param player Player
+ * @param button Mouse button the user clicked
+ * @param tracePos Raytraced location of the block which was hit
+ * @param traceSideHit Raytraced side hit
+ * @param traceHitType Type of hit, will be MISS if the trace expired
+ * without hitting anything (eg. the player clicked the sky)
+ */
+ public abstract void onPlayerClickedAir(EntityPlayerMP player, MouseButton button, BlockPos tracePos, EnumFacing traceSideHit,
+ MovingObjectType traceHitType);
+
+ /**
+ * Calls when the player clicks and hits a block, usually indicates that the
+ * player is digging or placing a block, although a block placement does not
+ * necessarily succeed. Return true from this callback to allow the action
+ * to proceed, or false to cancel the action. Cancelling the action does not
+ * prevent further handlers from receiving the event.
+ *
+ * @param player Player
+ * @param button Mouse button that was pressed, left = dig, right = interact
+ * @param hitPos Block which was *hit*. Note that block placement will
+ * normally be at hitPos.offset(sideHit)
+ * @param sideHit Side of the block which was hit
+ * @return true to allow the action to be processed (another listener may
+ * still inhibit the action), return false to cancel the action (other
+ * listeners will still be notified)
+ */
+ public abstract boolean onPlayerClickedBlock(EntityPlayerMP player, MouseButton button, BlockPos hitPos, EnumFacing sideHit);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/PlayerMoveListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/PlayerMoveListener.java
new file mode 100644
index 00000000..2ca8447e
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/PlayerMoveListener.java
@@ -0,0 +1,27 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+
+import com.mumfrey.liteloader.core.LiteLoaderEventBroker.ReturnValue;
+import com.mumfrey.liteloader.util.Position;
+
+/**
+ * Interface for mods which want to monitor or control player movements
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface PlayerMoveListener extends LiteMod
+{
+ /**
+ * Called when a movement/look packet is received from the client.
+ *
+ * @param playerMP Player moving
+ * @param from Player's previous recorded position
+ * @param to Position the player is attempting to move to
+ * @param newPos Set this position to teleport the player to newPos instead
+ * of processing the original move
+ * @return false to cancel the event or true to allow the movement to be
+ * processed as normal or newPos to be applied
+ */
+ public abstract boolean onPlayerMove(EntityPlayerMP playerMP, Position from, Position to, ReturnValue newPos);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/PluginChannelListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/PluginChannelListener.java
new file mode 100644
index 00000000..1ddda3ba
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/PluginChannelListener.java
@@ -0,0 +1,22 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.network.PacketBuffer;
+
+import com.mumfrey.liteloader.core.CommonPluginChannelListener;
+
+/**
+ * Interface for mods which want to use plugin channels
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface PluginChannelListener extends LiteMod, CommonPluginChannelListener
+{
+ /**
+ * Called when a custom payload packet arrives on a channel this mod has
+ * registered.
+ *
+ * @param channel Channel on which the custom payload was received
+ * @param data Custom payload data
+ */
+ public abstract void onCustomPayload(String channel, PacketBuffer data);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/PreJoinGameListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/PreJoinGameListener.java
new file mode 100644
index 00000000..54dec8cb
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/PreJoinGameListener.java
@@ -0,0 +1,24 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.network.INetHandler;
+import net.minecraft.network.play.server.S01PacketJoinGame;
+
+
+/**
+ * Interface for mods which wish to be notified when the player connects to a
+ * server (or local game).
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface PreJoinGameListener extends LiteMod
+{
+ /**
+ * Called before login. NOTICE: as of 1.8 the return value of this method
+ * has a different meaning!
+ *
+ * @param netHandler Net handler
+ * @param joinGamePacket Join game packet
+ * @return true to allow login to continue, false to cancel login
+ */
+ public abstract boolean onPreJoinGame(INetHandler netHandler, S01PacketJoinGame joinGamePacket);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/Priority.java b/liteloader/src/main/java/com/mumfrey/liteloader/Priority.java
new file mode 100644
index 00000000..5a0b24ac
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/Priority.java
@@ -0,0 +1,22 @@
+package com.mumfrey.liteloader;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Priority declaration for LiteMods, used when sorting listener lists. Default
+ * value if no Priority annotation is specified is 1000.
+ *
+ * @author Adam Mummery-Smith
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Priority
+{
+ /**
+ * Priority value, default priority is 1000
+ */
+ public int value();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/ServerChatFilter.java b/liteloader/src/main/java/com/mumfrey/liteloader/ServerChatFilter.java
new file mode 100644
index 00000000..15ea6676
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/ServerChatFilter.java
@@ -0,0 +1,22 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.network.play.client.C01PacketChatMessage;
+
+/**
+ * Interface for mods which can filter inbound chat
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ServerChatFilter extends LiteMod
+{
+ /**
+ * Chat filter function, return false to filter this packet, true to pass
+ * the packet.
+ *
+ * @param chatPacket Chat packet to examine
+ * @param message Chat message
+ * @return True to keep the packet, false to discard
+ */
+ public abstract boolean onChat(EntityPlayerMP player, C01PacketChatMessage chatPacket, String message);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/ServerCommandProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/ServerCommandProvider.java
new file mode 100644
index 00000000..36a3c24e
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/ServerCommandProvider.java
@@ -0,0 +1,21 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.command.ServerCommandManager;
+
+
+/**
+ * Interface for mods which provide commands to the local integrated server
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ServerCommandProvider extends LiteMod
+{
+ /**
+ * Allows the mod to provide commands to the server command manager by
+ * invoking commandManager.registerCommand() to provide new commands for
+ * single player and lan worlds
+ *
+ * @param commandManager
+ */
+ public abstract void provideCommands(ServerCommandManager commandManager);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/ServerPlayerListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/ServerPlayerListener.java
new file mode 100644
index 00000000..3ff7df24
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/ServerPlayerListener.java
@@ -0,0 +1,51 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+
+import com.mojang.authlib.GameProfile;
+
+/**
+ * Interface for mods which want to handle players joining and leaving a LAN
+ * game (or single player game)
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ServerPlayerListener extends LiteMod
+{
+ /**
+ * Called when a player connects to the server and the EntityPlayerMP
+ * instance is created, the player has not logged in at this point and may
+ * be disconnected if login fails.
+ *
+ * @param player Player attempting to connect
+ * @param profile Player's GameProfile from the authentication service
+ */
+ public abstract void onPlayerConnect(EntityPlayerMP player, GameProfile profile);
+
+ /**
+ * Called once the player has successfully logged in and all player
+ * variables are initialised and replicated.
+ *
+ * @param player Player connected
+ */
+ public abstract void onPlayerLoggedIn(EntityPlayerMP player);
+
+ /**
+ * Called when a player respawns. This event is raised when a player
+ * respawns after dying or conquers the end.
+ *
+ * @param player New player instance
+ * @param oldPlayer Old player instance being discarded
+ * @param newDimension Dimension the player is respawning in
+ * @param playerWonTheGame True if the player conquered the end (this
+ * respawn is NOT as the result of a death)
+ */
+ public abstract void onPlayerRespawn(EntityPlayerMP player, EntityPlayerMP oldPlayer, int newDimension, boolean playerWonTheGame);
+
+ /**
+ * Called when a player disconnects from the game
+ *
+ * @param player Player disconnecting
+ */
+ public abstract void onPlayerLogout(EntityPlayerMP player);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/ServerPluginChannelListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/ServerPluginChannelListener.java
new file mode 100644
index 00000000..9ca14d47
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/ServerPluginChannelListener.java
@@ -0,0 +1,25 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.network.PacketBuffer;
+
+import com.mumfrey.liteloader.core.CommonPluginChannelListener;
+
+/**
+ * Interface for mods which want to use plugin channels on the (integrated)
+ * server side.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ServerPluginChannelListener extends CommonPluginChannelListener
+{
+ /**
+ * Called when a custom payload packet arrives on a channel this mod has
+ * registered.
+ *
+ * @param sender Player object which is the source of this message
+ * @param channel Channel on which the custom payload was received
+ * @param data Custom payload data
+ */
+ public abstract void onCustomPayload(EntityPlayerMP sender, String channel, PacketBuffer data);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/ServerTickable.java b/liteloader/src/main/java/com/mumfrey/liteloader/ServerTickable.java
new file mode 100644
index 00000000..61b1eee3
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/ServerTickable.java
@@ -0,0 +1,18 @@
+package com.mumfrey.liteloader;
+
+import net.minecraft.server.MinecraftServer;
+
+/**
+ * Interface for mods which want to be ticked on the server thread
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ServerTickable extends LiteMod
+{
+ /**
+ * Called at the start of every server update tick
+ *
+ * @param server
+ */
+ public abstract void onTick(MinecraftServer server);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/ShutdownListener.java b/liteloader/src/main/java/com/mumfrey/liteloader/ShutdownListener.java
new file mode 100644
index 00000000..12c3efb4
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/ShutdownListener.java
@@ -0,0 +1,13 @@
+package com.mumfrey.liteloader;
+
+/**
+ * Interface for mods that want to receive an event when the game is shutting
+ * down due to a user request. They do not receive the callback when the VM is
+ * terminating for other reasons, use a regular VM shutdownhook for that.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ShutdownListener extends LiteMod
+{
+ public abstract void onShutDown();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/BrandingProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/BrandingProvider.java
new file mode 100644
index 00000000..5f129c64
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/BrandingProvider.java
@@ -0,0 +1,116 @@
+package com.mumfrey.liteloader.api;
+
+import java.net.URI;
+
+import net.minecraft.util.ResourceLocation;
+
+import com.mumfrey.liteloader.util.render.Icon;
+
+/**
+ * LiteLoader Extensible API - Branding Provider
+ *
+ * The Branding Provider manages loader branding alterations for a particular
+ * API. This is an optional API component which allows an API to specify
+ * customisations and additions to the loader environment in order to provide a
+ * more comfortable integration for the API.
+ *
+ * Since some branding options simply stack (like the API copyright notices
+ * for example) all APIs will be allowed to supply this information, however
+ * other options (like the main logo image) can only be set by one API. To
+ * determine which API should be used to set this information, the getPriority()
+ * method will be called and used to sort branding providers by priority, with
+ * highest priority winning.
+ *
+ * All branding options may return a null/not set value, allowing a branding
+ * provider to only override the branding features it wishes. Some options
+ * require a non-null value to be returned from a set of methods in order to
+ * take effect. eg. the logo option requires non-null return values from BOTH
+ * the getLogoResource() and getLogoCoords() methods.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface BrandingProvider extends CustomisationProvider
+{
+ /**
+ * Get the priority of this provider, higher numbers take precedence. Some
+ * brandings can only be set by one provider (eg. the main "about" logo) so
+ * the branding provider with the highest priority will be the one which
+ * gets control of that feature.
+ */
+ public abstract int getPriority();
+
+ /**
+ * Get the primary branding colour for this API, the branding provider
+ * should return 0 if it does not wish to override the branding colour. The
+ * branding colour is used for the mod list entries and hyper-links within
+ * the about GUI panels, the colour returned should be fully opaque.
+ */
+ public abstract int getBrandingColour();
+
+ /**
+ * Get the resource to use for the main logo, the API with the highest
+ * priority gets to define the logo, this method can return null if this API
+ * does not want to override the logo.
+ */
+ public abstract ResourceLocation getLogoResource();
+
+ /**
+ * Gets the coordinates of the logo as an IIcon instance, only called if
+ * getLogoResource() returns a non-null value and the logo will only be used
+ * if BOTH methods return a valid object.
+ */
+ public abstract Icon getLogoCoords();
+
+ /**
+ * Get the resource to use for the icon logo (the chicken in the default
+ * setup), the API with the highest priority gets to define the icon logo,
+ * this method can return null if this API does not want to override the
+ * icon.
+ */
+ public abstract ResourceLocation getIconResource();
+
+ /**
+ * Gets the coordinates of the icon logo as an IIcon instance, only called
+ * if getIconResource() returns a non-null value and the icon will only be
+ * used if BOTH methods return a valid object.
+ */
+ public abstract Icon getIconCoords();
+
+ /**
+ * Get the display name for this API, used on the "about" screen, must not
+ * return null.
+ */
+ public abstract String getDisplayName();
+
+ /**
+ * Get the copyright text for this API, used on the "about" screen, must not
+ * return null.
+ */
+ public abstract String getCopyrightText();
+
+ /**
+ * Get the main home page URL for this API, used on the "about" screen, must
+ * not return null.
+ */
+ public abstract URI getHomepage();
+
+ /**
+ * If you wish to display a clickable twitter icon next to the API
+ * information in the "about" panel then you must return values from this
+ * method as well as getTwitterAvatarResource() and
+ * getTwitterAvatarCoords(). Return the twitter user name here.
+ */
+ public abstract String getTwitterUserName();
+
+ /**
+ * If you wish to display a clickable twitter icon next to the API
+ * information, return the icon resource here.
+ */
+ public abstract ResourceLocation getTwitterAvatarResource();
+
+ /**
+ * If you wish to display a clickable twitter icon next to the API
+ * information, return the icon coordinates here.
+ */
+ public abstract Icon getTwitterAvatarCoords();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/ContainerRegistry.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/ContainerRegistry.java
new file mode 100644
index 00000000..fcd66eec
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/ContainerRegistry.java
@@ -0,0 +1,98 @@
+package com.mumfrey.liteloader.api;
+
+import java.io.File;
+import java.util.Collection;
+
+import com.mumfrey.liteloader.core.ModInfo;
+import com.mumfrey.liteloader.interfaces.Loadable;
+import com.mumfrey.liteloader.interfaces.LoadableMod;
+import com.mumfrey.liteloader.interfaces.TweakContainer;
+
+/**
+ * Registry for enabled, disabled, injected and bad containers
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ContainerRegistry
+{
+ public enum DisabledReason
+ {
+ UNKNOWN("Container %s is could not be loaded for UNKNOWN reason"),
+ USER_DISABLED("Container %s is disabled"),
+ MISSING_DEPENDENCY("Container %s is missing one or more dependencies"),
+ MISSING_API("Container %s is missing one or more required APIs");
+
+ private final String message;
+
+ private DisabledReason(String message)
+ {
+ this.message = message;
+ }
+
+ public String getMessage(LoadableMod> container)
+ {
+ return String.format(this.message, container);
+ }
+ }
+
+ /**
+ * Register an enabled container, removes the container from the disabled
+ * containers list if present.
+ */
+ public abstract void registerEnabledContainer(LoadableMod> container);
+
+ /**
+ * Get all enabled containers
+ */
+ public abstract Collection extends LoadableMod>> getEnabledContainers();
+
+ /**
+ * Get a specific enabled container by id
+ */
+ public abstract LoadableMod> getEnabledContainer(String identifier);
+
+ /**
+ * Register a disabled container
+ */
+ public abstract void registerDisabledContainer(LoadableMod> container, DisabledReason reason);
+
+ /**
+ * Get all disabled containers
+ */
+ public abstract Collection extends ModInfo>> getDisabledContainers();
+
+ /**
+ * Check whether a specific container is registered as disabled
+ */
+ public abstract boolean isDisabledContainer(LoadableMod> container);
+
+ /**
+ * Register a bad container
+ */
+ public abstract void registerBadContainer(Loadable> container, String reason);
+
+ /**
+ * Get all bad containers
+ */
+ public abstract Collection extends ModInfo>> getBadContainers();
+
+ /**
+ * Register a candidate tweak container
+ */
+ public abstract void registerTweakContainer(TweakContainer container);
+
+ /**
+ * Get all registered tweak containers
+ */
+ public abstract Collection> getTweakContainers();
+
+ /**
+ * Register an injected tweak container
+ */
+ public abstract void registerInjectedTweak(TweakContainer container);
+
+ /**
+ * Get all injected tweak containers
+ */
+ public abstract Collection extends ModInfo>> getInjectedTweaks();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/CoreProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/CoreProvider.java
new file mode 100644
index 00000000..f9feefb6
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/CoreProvider.java
@@ -0,0 +1,63 @@
+package com.mumfrey.liteloader.api;
+
+import net.minecraft.network.INetHandler;
+import net.minecraft.network.play.server.S01PacketJoinGame;
+
+import com.mumfrey.liteloader.common.GameEngine;
+import com.mumfrey.liteloader.core.LiteLoaderMods;
+
+/**
+ * LiteLoader Extensible API - API Core Provider
+ *
+ * Core Providers are objects whose lifecycle is equivalent to the run time of
+ * game and thus the entire lifecycle of your API, they are instanced early in
+ * the loader startup process. CoreProviders can implement any Observer
+ * interface as appropriate and are automatically considered when allocating
+ * Observers to callback lists.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface CoreProvider extends TickObserver, WorldObserver, ShutdownObserver, PostRenderObserver
+{
+ public abstract void onInit();
+
+ /**
+ * During the postInit phase, the mods which were discovered during preInit
+ * phase are initialised and the interfaces are allocated. This callback is
+ * invoked at the very start of the postInit phase, before mods are
+ * initialised but after the point at which it is safe to assume it's ok to
+ * access game classes. This is the first point at which the Minecraft game
+ * instance should be referenced. Be aware that certain game classes (such
+ * as the EntityRenderer) are NOT initialised at this point.
+ *
+ * @param engine
+ */
+ public abstract void onPostInit(GameEngine, ?> engine);
+
+ /**
+ * Once the mods are initialised and the interfaces have been allocated,
+ * this callback is invoked to allow the CoreProvider to perform any tasks
+ * which should be performed in the postInit phase but after mods have been
+ * initialised.
+ *
+ * @param mods
+ */
+ public abstract void onPostInitComplete(LiteLoaderMods mods);
+
+ /**
+ * Called once startup is complete and the game loop begins running. This
+ * callback is invoked immediately prior to the first "tick" event and
+ * immediately after the the "late init" phase for mods
+ * (InitCompleteListener).
+ */
+ public abstract void onStartupComplete();
+
+ /**
+ * Called immediately on joining a single or multi-player world when the
+ * JoinGame packet is received. Only called on the client.
+ *
+ * @param netHandler
+ * @param loginPacket
+ */
+ public abstract void onJoinGame(INetHandler netHandler, S01PacketJoinGame loginPacket);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/CustomisationProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/CustomisationProvider.java
new file mode 100644
index 00000000..23ab0437
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/CustomisationProvider.java
@@ -0,0 +1,11 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * Base interface for loader customisation providers, has to be here so that we
+ * don't load branding provider classes too soon.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface CustomisationProvider
+{
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumerationObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumerationObserver.java
new file mode 100644
index 00000000..ebd8b9fa
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumerationObserver.java
@@ -0,0 +1,64 @@
+package com.mumfrey.liteloader.api;
+
+import java.io.File;
+
+import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
+import com.mumfrey.liteloader.core.ModInfo;
+import com.mumfrey.liteloader.interfaces.LoadableMod;
+import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
+import com.mumfrey.liteloader.interfaces.TweakContainer;
+
+/**
+ * LiteLoader Extensible API - Enumeration observer
+ *
+ * EnumerationObserver receive callbacks when mod containers are enumerated.
+ * Instances of this class must be returned from getPreInitObservers in
+ * order to work.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface EnumerationObserver extends Observer
+{
+ /**
+ * Called upon registration for every discovered container which is enabled
+ *
+ * @param enumerator
+ * @param container
+ */
+ public abstract void onRegisterEnabledContainer(LoaderEnumerator enumerator, LoadableMod> container);
+
+ /**
+ * Called upon registration for every discovered container which is
+ * currently disabled, either because
+ *
+ * @param enumerator
+ * @param container
+ * @param reason
+ */
+ public abstract void onRegisterDisabledContainer(LoaderEnumerator enumerator, LoadableMod> container, DisabledReason reason);
+
+ /**
+ * Called AFTER registration of an ENABLED container (eg.
+ * onRegisterEnabledContainer will be called first) if that container also
+ * contains tweaks.
+ *
+ * @param enumerator
+ * @param container
+ */
+ public abstract void onRegisterTweakContainer(LoaderEnumerator enumerator, TweakContainer container);
+
+ /**
+ * Called when a mod container is added to the pending mods list. This does
+ * not mean that the specific mod will actually be instanced since the mod
+ * can still be disabled via the exclusion list (this is to allow entire
+ * containers to be disabled or just individual mods) and so if you wish to
+ * observe actual mod instantiation you should still provide a
+ * {@link com.mumfrey.liteloader.client.ResourceObserver}. However this
+ * event expresses a declaration by the enumerator of an intention to load
+ * the specified mod.
+ *
+ * @param enumerator
+ * @param mod
+ */
+ public abstract void onModAdded(LoaderEnumerator enumerator, ModInfo> mod);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumeratorModule.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumeratorModule.java
new file mode 100644
index 00000000..2fc1cdea
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumeratorModule.java
@@ -0,0 +1,68 @@
+package com.mumfrey.liteloader.api;
+
+import com.mumfrey.liteloader.interfaces.ModularEnumerator;
+import com.mumfrey.liteloader.launch.LoaderEnvironment;
+import com.mumfrey.liteloader.launch.LoaderProperties;
+
+import net.minecraft.launchwrapper.LaunchClassLoader;
+
+/**
+ * LiteLoader Extensible API - Interface for objects which can enumerate mods in
+ * places.
+ *
+ * EnumeratorModules plug into the LoaderEnumerator and are used to discover
+ * mod containers in various locations, for example searching in a specific
+ * folder for particular files.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface EnumeratorModule
+{
+ /**
+ * @param environment Loader environment
+ * @param properties Loader properties
+ */
+ public abstract void init(LoaderEnvironment environment, LoaderProperties properties);
+
+ /**
+ * @param environment Loader environment
+ * @param properties Loader properties
+ */
+ public abstract void writeSettings(LoaderEnvironment environment, LoaderProperties properties);
+
+ /**
+ * Find loadable mods in this enumerator's domain, the enumerator module
+ * should call back against the enumerator itself to register containers it
+ * discovers using the registerModContainer() and registerTweakContainer()
+ * callbacks.
+ *
+ * This method is called during loader PREINIT phase so do not use any
+ * game classes here!
+ *
+ * @param enumerator
+ * @param profile
+ */
+ public abstract void enumerate(ModularEnumerator enumerator, String profile);
+
+ /**
+ * The enumerator module should inject (as required) any discovered
+ * containers into the classpath.
+ *
+ * This method is called during the loader INIT phase.
+ *
+ * @param enumerator
+ * @param classLoader
+ */
+ public abstract void injectIntoClassLoader(ModularEnumerator enumerator, LaunchClassLoader classLoader);
+
+ /**
+ * The enumerator module should callback against the enumerator using the
+ * registerModsFrom() callback to register mods from discovered containers.
+ *
+ * This method is called during the loader INIT phase
+ *
+ * @param enumerator
+ * @param classLoader
+ */
+ public abstract void registerMods(ModularEnumerator enumerator, LaunchClassLoader classLoader);
+}
\ No newline at end of file
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumeratorPlugin.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumeratorPlugin.java
new file mode 100644
index 00000000..e7b113ba
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/EnumeratorPlugin.java
@@ -0,0 +1,37 @@
+package com.mumfrey.liteloader.api;
+
+import java.util.List;
+
+import com.mumfrey.liteloader.interfaces.LoadableMod;
+import com.mumfrey.liteloader.launch.LoaderEnvironment;
+import com.mumfrey.liteloader.launch.LoaderProperties;
+
+/**
+ * LiteLoader Extensible API - Interface for objects which can interact with the
+ * enumeration process, not yet available to APIs.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface EnumeratorPlugin
+{
+ /**
+ * Initialise this plugin
+ */
+ public abstract void init(LoaderEnvironment environment, LoaderProperties properties);
+
+ /**
+ * Get classes in the supplied container
+ *
+ * @param container Container to inspect
+ * @param classloader ClassLoader for this container
+ * @param validator Mod class validator
+ * @return list of classes in the container
+ */
+ public abstract List> getClasses(LoadableMod> container, ClassLoader classloader, ModClassValidator validator);
+
+ public abstract boolean checkEnabled(ContainerRegistry containers, LoadableMod> container);
+
+ public abstract boolean checkDependencies(ContainerRegistry containers, LoadableMod> base);
+
+ public abstract boolean checkAPIRequirements(ContainerRegistry containers, LoadableMod> container);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/GenericObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/GenericObserver.java
new file mode 100644
index 00000000..98389292
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/GenericObserver.java
@@ -0,0 +1,13 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * Generic Observer class, for Intra-API Observer inking
+ *
+ * @author Adam Mummery-Smith
+ *
+ * @param Argument type for observable events
+ */
+public interface GenericObserver extends Observer
+{
+ public abstract void onObservableEvent(String eventName, T... eventArgs) throws ClassCastException;
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/InterfaceObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/InterfaceObserver.java
new file mode 100644
index 00000000..58137627
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/InterfaceObserver.java
@@ -0,0 +1,11 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * Observer for interface binding events
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface InterfaceObserver extends Observer
+{
+ public void onRegisterListener(InterfaceProvider provider, Class extends Listener> interfaceType, Listener listener);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/InterfaceProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/InterfaceProvider.java
new file mode 100644
index 00000000..a6432eea
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/InterfaceProvider.java
@@ -0,0 +1,32 @@
+package com.mumfrey.liteloader.api;
+
+import com.mumfrey.liteloader.core.InterfaceRegistrationDelegate;
+
+/**
+ * LiteLoader Extensible API - Interface Provider
+ *
+ * InterfaceProviders are able to advertise and provide Listener interfaces
+ * which can be implemented by mods or other Listener-derived classes.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface InterfaceProvider
+{
+ /**
+ * Base type of Listeners which can consume events provided by this provider
+ */
+ public abstract Class extends Listener> getListenerBaseType();
+
+ /**
+ * The provider should call back against the supplied delegate in order to
+ * advertise the interfaces it provides.
+ *
+ * @param delegate
+ */
+ public abstract void registerInterfaces(InterfaceRegistrationDelegate delegate);
+
+ /**
+ * Initialise this provider, called AFTER enumeration but before binding
+ */
+ public abstract void initProvider();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/Listener.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/Listener.java
new file mode 100644
index 00000000..65044ae8
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/Listener.java
@@ -0,0 +1,22 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * LiteLoader Extensible API - Listener is the base interface for
+ * (counter-intuitively) consumable Listener interfaces, in that derived
+ * interfaces are consumable (from the point of view of the providers) but
+ * actual implementors consume the events thus advertised by implementing those
+ * interfaces, making them themselves the consumers. Okay so that's probably
+ * pretty confusing but I can't think of any better terminology so it's
+ * staying :)
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface Listener
+{
+ /**
+ * Get the display name
+ *
+ * @return display name
+ */
+ public abstract String getName();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/LiteAPI.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/LiteAPI.java
new file mode 100644
index 00000000..ef5c5d59
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/LiteAPI.java
@@ -0,0 +1,120 @@
+package com.mumfrey.liteloader.api;
+
+import java.util.List;
+
+import com.mumfrey.liteloader.launch.LoaderEnvironment;
+import com.mumfrey.liteloader.launch.LoaderProperties;
+
+/**
+ * LiteLoader Extensible API - main Mod API
+ *
+ * Implementors of this class don't really do anything except provide
+ * instances of other classes which make up the API proper. Where possible,
+ * instance things as late as possible (eg. do not instance your
+ * CoreProviders in the constructor or init()) because it's possible to screw up
+ * the game startup if things get loaded out of order, in general it's best to
+ * instance things only at the earliest point in time at which they are needed.
+ *
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface LiteAPI
+{
+ /**
+ * Initialise this API, the API should do as little processing as possible
+ * here, but should also cache the supplied environment and properties
+ * instances for later use.
+ *
+ * @param environment
+ * @param properties
+ */
+ public abstract void init(LoaderEnvironment environment, LoaderProperties properties);
+
+ /**
+ * Get the identifier for this API, the identifier is used to retrieve the
+ * API and match it against specified mod API dependencies.
+ */
+ public abstract String getIdentifier();
+
+ /**
+ * Get the friendly name of this API
+ */
+ public abstract String getName();
+
+ /**
+ * Get the human-readable version of the API, can be any value
+ */
+ public abstract String getVersion();
+
+ /**
+ * Get the revision number of this API. Unlike the version number, the
+ * revision number should only change when an incompatible change is made to
+ * the APIs interfaces, it is also used when a mod specifies an API
+ * dependency using the api@revision syntax.
+ */
+ public abstract int getRevision();
+
+ /**
+ * Get mixin environment configuration provider for this API, can return
+ * null.
+ */
+ public abstract MixinConfigProvider getMixins();
+
+ /**
+ * Should return an array of required transformer names, these transformers
+ * will be injected UPSTREAM. Can return null.
+ */
+ public abstract String[] getRequiredTransformers();
+
+ /**
+ * Should return an array of required transformer names, these transformers
+ * will be injected DOWNSTREAM. Can return null.
+ */
+ public abstract String[] getRequiredDownstreamTransformers();
+
+ /**
+ * Return a mod class prefix supported by this API, can return null if an
+ * API just wants to use "LiteMod" as a standard class name prefix
+ */
+ public abstract String getModClassPrefix();
+
+ /**
+ * Should return a list of Enumerator modules to be injected, can return
+ * null if the API doesn't want to inject any additonal modules
+ */
+ public abstract List getEnumeratorModules();
+
+ /**
+ * Should return a list of CoreProviders for this API, can return null if
+ * the API doesn't have any CoreProviders, (almost) guaranteed to only be
+ * called once.
+ */
+ public abstract List getCoreProviders();
+
+ /**
+ * Should return a list of InterfaceProviders for this API, can return null
+ * if the API doesn't have any InterfaceProviders, (almost) guaranteed to
+ * only be called once
+ */
+ public abstract List getInterfaceProviders();
+
+ /**
+ * Should return a list of Observers which are safe to instantiate during
+ * pre-init, for example EnumerationObservers. Can return null if the API
+ * doesn't have any Observers.
+ */
+ public abstract List getPreInitObservers();
+
+ /**
+ * Should return a list of Observers for this API, can return null if the
+ * API doesn't have any Observers, (almost) guaranteed to only be called
+ * once. This list may include Observers returned by getPreInitObservers if
+ * the observers are still required.
+ */
+ public abstract List getObservers();
+
+ /**
+ * Get the customisation providers for this API, can return null
+ */
+ public abstract List getCustomisationProviders();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/MixinConfigProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/MixinConfigProvider.java
new file mode 100644
index 00000000..097f34f2
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/MixinConfigProvider.java
@@ -0,0 +1,27 @@
+package com.mumfrey.liteloader.api;
+
+import org.spongepowered.asm.mixin.MixinEnvironment.CompatibilityLevel;
+
+/**
+ * Container for all of an API's mixin environment configuration
+ */
+public interface MixinConfigProvider
+{
+ /**
+ * Get the minimum required mixin operating compatibility level for this
+ * API, can return null.
+ */
+ public abstract CompatibilityLevel getCompatibilityLevel();
+
+ /**
+ * Get mixin configuration files for this API, all returned configs will be
+ * added to the DEFAULT environment. Can return null.
+ */
+ public abstract String[] getMixinConfigs();
+
+ /**
+ * Get mixin error handler classes to register for this API. Can return
+ * null.
+ */
+ public abstract String[] getErrorHandlers();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/ModClassValidator.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/ModClassValidator.java
new file mode 100644
index 00000000..3c3c85eb
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/ModClassValidator.java
@@ -0,0 +1,14 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * Interface for object which validates whether a supplied mod class can be
+ * loaded.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ModClassValidator
+{
+ public abstract boolean validateName(String className);
+
+ public abstract boolean validateClass(ClassLoader classLoader, Class> candidateClass);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/ModInfoDecorator.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/ModInfoDecorator.java
new file mode 100644
index 00000000..d176c491
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/ModInfoDecorator.java
@@ -0,0 +1,53 @@
+package com.mumfrey.liteloader.api;
+
+import java.util.List;
+
+import com.mumfrey.liteloader.core.ModInfo;
+import com.mumfrey.liteloader.util.render.IconTextured;
+
+/**
+ * LiteLoader Extensible API - Branding Provider
+ *
+ * Decorator for ModInfo classes, to alter the appearance of ModInfo entries in
+ * the mod list.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ModInfoDecorator extends CustomisationProvider
+{
+ /**
+ * Add icons to the mod list entry for this mod
+ *
+ * @param mod
+ * @param icons
+ */
+ public abstract void addIcons(ModInfo> mod, List icons);
+
+ /**
+ * Allows this decorator to modify the status text for the specified mod,
+ * return null if no modification required.
+ *
+ * @param statusText
+ * @return new status text or NULL to indicate the text should remain
+ * default
+ */
+ public abstract String modifyStatusText(ModInfo> mod, String statusText);
+
+ /**
+ * Allow decorators to draw custom content on the mod list entries
+ *
+ * @param mouseX Mouse X position
+ * @param mouseY Mouse Y position
+ * @param partialTicks
+ * @param xPosition Panel X position
+ * @param yPosition Panel Y position
+ * @param width Panel width
+ * @param selected Panel height
+ * @param mod ModInfo
+ * @param gradientColour
+ * @param titleColour
+ * @param statusColour
+ */
+ public abstract void onDrawListEntry(int mouseX, int mouseY, float partialTicks, int xPosition, int yPosition, int width, int height,
+ boolean selected, ModInfo> mod, int gradientColour, int titleColour, int statusColour);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/ModLoadObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/ModLoadObserver.java
new file mode 100644
index 00000000..82b9804e
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/ModLoadObserver.java
@@ -0,0 +1,65 @@
+package com.mumfrey.liteloader.api;
+
+import java.io.File;
+
+import com.mumfrey.liteloader.LiteMod;
+import com.mumfrey.liteloader.core.ModInfo;
+import com.mumfrey.liteloader.interfaces.LoadableMod;
+
+/**
+ * LiteLoader Extensible API - Mod Load Observer
+ *
+ * ModLoadObservers receive callbacks when mod loading events are occurring,
+ * prior to init and other loader-managed processes.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ModLoadObserver extends Observer
+{
+ /**
+ * Called immediately after a mod instance is created, throw an exception
+ * from this method in order to prevent further initialisation.
+ */
+ public abstract void onModLoaded(LiteMod mod);
+
+ /**
+ * Called after a mod is instanced and has been successfully added to the
+ * active mods list.
+ *
+ * @param handle Mod handle
+ */
+ public abstract void onPostModLoaded(ModInfo> handle);
+
+ /**
+ * Called if mod loading fails
+ *
+ * @param container
+ * @param identifier
+ * @param reason
+ * @param th
+ */
+ public abstract void onModLoadFailed(LoadableMod> container, String identifier, String reason, Throwable th);
+
+ /**
+ * Called before a mod's init() method is called
+ *
+ * @param mod
+ */
+ public abstract void onPreInitMod(LiteMod mod);
+
+ /**
+ * Called after a mod's init() method is called
+ *
+ * @param mod
+ */
+ public abstract void onPostInitMod(LiteMod mod);
+
+ /**
+ * Called when migrating mod config from version to version
+ *
+ * @param mod
+ * @param newConfigPath
+ * @param oldConfigPath
+ */
+ public abstract void onMigrateModConfig(LiteMod mod, File newConfigPath, File oldConfigPath);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/Observer.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/Observer.java
new file mode 100644
index 00000000..ffbbe86c
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/Observer.java
@@ -0,0 +1,15 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * LiteLoader Extensible API - Observer base interface
+ *
+ * Observers are essentially "core listeners" which are objects which make up
+ * the core a of a particular API implementation and sink events generated by
+ * the Loader or by other observable components. See the derived interfaces for
+ * more detail.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface Observer
+{
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/PostRenderObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/PostRenderObserver.java
new file mode 100644
index 00000000..2d733b2b
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/PostRenderObserver.java
@@ -0,0 +1,14 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * LiteLoader Extensible API - Post-render Observers
+ *
+ * PostRenderObservers receive the onPostRender event every frame, allowing
+ * "draw-on-top" behaviour for API components.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface PostRenderObserver extends Observer
+{
+ public abstract void onPostRender(int mouseX, int mouseY, float partialTicks);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/ShutdownObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/ShutdownObserver.java
new file mode 100644
index 00000000..dced2a89
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/ShutdownObserver.java
@@ -0,0 +1,15 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * LiteLoader Extensible API - ShutDownObserver
+ *
+ * ShutDownObservers receive an event when the game is shutting down due to a
+ * user request. They do NOT receive the callback when the VM is terminating,
+ * use a regular VM shutdownhook for that.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface ShutdownObserver extends Observer
+{
+ public abstract void onShutDown();
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/TickObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/TickObserver.java
new file mode 100644
index 00000000..a2fc4e9d
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/TickObserver.java
@@ -0,0 +1,13 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * LiteLoader Extensible API - TickObserver
+ *
+ * Received a callback every tick (duh) PRIOR to the mod tick event
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface TickObserver extends Observer
+{
+ public abstract void onTick(boolean clock, float partialTicks, boolean inGame);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/TranslationProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/TranslationProvider.java
new file mode 100644
index 00000000..6f945f79
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/TranslationProvider.java
@@ -0,0 +1,21 @@
+package com.mumfrey.liteloader.api;
+
+/**
+ * Interface for providers which can handle translation requests
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface TranslationProvider extends CustomisationProvider
+{
+ /**
+ * Translate the supplied key or return NULL if the provider has no
+ * translation for the specified key
+ */
+ public abstract String translate(String key, Object... args);
+
+ /**
+ * Translate the supplied key to the specified locale, or return NULL if the
+ * provider has no translation for this key
+ */
+ public abstract String translate(String locale, String key, Object... args);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/WorldObserver.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/WorldObserver.java
new file mode 100644
index 00000000..4b662b9f
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/WorldObserver.java
@@ -0,0 +1,16 @@
+package com.mumfrey.liteloader.api;
+
+import net.minecraft.world.World;
+
+/**
+ * LiteLoader Extensible API - WorldObserver
+ *
+ * WorldObservers receive a callback when the Minecraft.theWorld reference
+ * changes, beware the value is allowed to be null.
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface WorldObserver extends Observer
+{
+ public abstract void onWorldChanged(World world);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/APIException.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/APIException.java
new file mode 100644
index 00000000..f2e9d1d7
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/APIException.java
@@ -0,0 +1,27 @@
+package com.mumfrey.liteloader.api.exceptions;
+
+public abstract class APIException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public APIException()
+ {
+ super();
+ }
+
+ public APIException(String message)
+ {
+ super(message);
+ }
+
+ public APIException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ public APIException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+}
\ No newline at end of file
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidAPIException.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidAPIException.java
new file mode 100644
index 00000000..8615f121
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidAPIException.java
@@ -0,0 +1,16 @@
+package com.mumfrey.liteloader.api.exceptions;
+
+public class InvalidAPIException extends APIException
+{
+ private static final long serialVersionUID = 1L;
+
+ public InvalidAPIException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public InvalidAPIException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidAPIStateException.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidAPIStateException.java
new file mode 100644
index 00000000..57de5e7f
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidAPIStateException.java
@@ -0,0 +1,11 @@
+package com.mumfrey.liteloader.api.exceptions;
+
+public class InvalidAPIStateException extends APIException
+{
+ private static final long serialVersionUID = 1L;
+
+ public InvalidAPIStateException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidProviderException.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidProviderException.java
new file mode 100644
index 00000000..a361b9df
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/exceptions/InvalidProviderException.java
@@ -0,0 +1,16 @@
+package com.mumfrey.liteloader.api.exceptions;
+
+public class InvalidProviderException extends APIException
+{
+ private static final long serialVersionUID = 1L;
+
+ public InvalidProviderException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public InvalidProviderException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/manager/APIAdapter.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/manager/APIAdapter.java
new file mode 100644
index 00000000..53583fc1
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/manager/APIAdapter.java
@@ -0,0 +1,86 @@
+package com.mumfrey.liteloader.api.manager;
+
+import java.util.List;
+
+import com.mumfrey.liteloader.api.CoreProvider;
+import com.mumfrey.liteloader.api.LiteAPI;
+import com.mumfrey.liteloader.api.Observer;
+import com.mumfrey.liteloader.interfaces.InterfaceRegistry;
+
+/**
+ * API Adapter provides convenience methods for invoking actions on ALL
+ * registered APIs
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface APIAdapter
+{
+ /**
+ * APIs should register their mixin configs and set up the mixin environment
+ * here.
+ */
+ public abstract void initMixins();
+
+ /**
+ * Aggregate and return required transformers from all registered APIs
+ */
+ public abstract List getRequiredTransformers();
+
+ /**
+ * Aggregate and return required downstream transformers from all registered
+ * APIs
+ */
+ public abstract List getRequiredDownstreamTransformers();
+
+ /**
+ * Register interfaces from all registered APIs with the specified registry
+ */
+ public abstract void registerInterfaces(InterfaceRegistry interfaceManager);
+
+ /**
+ * Get the CoreProviders for the specified API. Consuming classes should
+ * call this method instead of calling API::getCoreProviders() directly
+ * since getCoreProviders() should only be invoked once and the resulting
+ * collection is cached by the API Adapter
+ */
+ public abstract List getCoreProviders();
+
+ /**
+ * Get the observers for the specified API. Consuming classes should call
+ * this method instead of calling API::getObservers() directly since
+ * getObservers() should only be invoked once and the resulting list is
+ * cached by the API Adapter
+ *
+ * @param api API to get observers for
+ */
+ public abstract List extends Observer> getObservers(LiteAPI api);
+
+ /**
+ * Get the observers for the specified API which implement the specified
+ * Observer interface. Always returns a valid list (even if empty) and
+ * doesn't return null.
+ *
+ * @param api API to get observers for
+ * @param observerType type of observer to search for
+ */
+ public abstract List getObservers(LiteAPI api, Class observerType);
+
+ /**
+ * Get the observers for all registered APIs which implement the specified
+ * Observer interface. Always returns a valid list (even if empty) and
+ * doesn't return null. Also includes core providers
+ *
+ * @param observerType type of observer to search for
+ */
+ public abstract List getAllObservers(Class observerType);
+
+ /**
+ * @param api
+ */
+ public abstract List extends Observer> getPreInitObservers(LiteAPI api);
+
+ /**
+ * @param observerType
+ */
+ public abstract List getPreInitObservers(Class observerType);
+}
diff --git a/liteloader/src/main/java/com/mumfrey/liteloader/api/manager/APIProvider.java b/liteloader/src/main/java/com/mumfrey/liteloader/api/manager/APIProvider.java
new file mode 100644
index 00000000..8669b192
--- /dev/null
+++ b/liteloader/src/main/java/com/mumfrey/liteloader/api/manager/APIProvider.java
@@ -0,0 +1,50 @@
+package com.mumfrey.liteloader.api.manager;
+
+import java.util.regex.Pattern;
+
+import com.mumfrey.liteloader.api.LiteAPI;
+
+/**
+ * Interface for the API Provider, which manages API instances and lifecycle
+ *
+ * @author Adam Mummery-Smith
+ */
+public interface APIProvider
+{
+ public static final Pattern idAndRevisionPattern = Pattern.compile("^([^@]+)@([0-9]{1,5})$");
+
+ /**
+ * Get all available API instances in an array
+ */
+ public abstract LiteAPI[] getAPIs();
+
+ /**
+ * Returns true if the specified API is available
+ *
+ * @param identifier API identifier (case sensitive) or API
+ * identifier-plus-minrevision in the form "identifier@minver"
+ */
+ public abstract boolean isAPIAvailable(String identifier);
+
+ /**
+ * Returns true if the specified API is available
+ *
+ * @param identifier API identifier (case sensitive)
+ * @param minRevision minimum required revision
+ */
+ public abstract boolean isAPIAvailable(String identifier, int minRevision);
+
+ /**
+ * Gets a specific API by identifier
+ *
+ * @param identifier API identifier (case sensitive)
+ */
+ public abstract LiteAPI getAPI(String identifier);
+
+ /**
+ * Gets a specific API by class
+ *
+ * @param apiClass
+ */
+ public abstract T getAPI(Class