diff --git a/resources/2char.png b/resources/2char.png
new file mode 100644
index 0000000..56196af
Binary files /dev/null and b/resources/2char.png differ
diff --git a/resources/META-INF/MANIFEST.MF b/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..58630c0
--- /dev/null
+++ b/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+
diff --git a/resources/armor/chain.png b/resources/armor/chain.png
new file mode 100644
index 0000000..5c26ea8
Binary files /dev/null and b/resources/armor/chain.png differ
diff --git a/resources/armor/plate.png b/resources/armor/plate.png
new file mode 100644
index 0000000..5350f3f
Binary files /dev/null and b/resources/armor/plate.png differ
diff --git a/resources/char.png b/resources/char.png
new file mode 100644
index 0000000..7cfa08a
Binary files /dev/null and b/resources/char.png differ
diff --git a/resources/clouds.png b/resources/clouds.png
new file mode 100644
index 0000000..b6c9e13
Binary files /dev/null and b/resources/clouds.png differ
diff --git a/resources/default.gif b/resources/default.gif
new file mode 100644
index 0000000..15e0fc2
Binary files /dev/null and b/resources/default.gif differ
diff --git a/resources/default.png b/resources/default.png
new file mode 100644
index 0000000..13a42f1
Binary files /dev/null and b/resources/default.png differ
diff --git a/resources/dirt.png b/resources/dirt.png
new file mode 100644
index 0000000..b29e009
Binary files /dev/null and b/resources/dirt.png differ
diff --git a/resources/glsl/core.glsl b/resources/glsl/core.glsl
new file mode 100644
index 0000000..0c88351
--- /dev/null
+++ b/resources/glsl/core.glsl
@@ -0,0 +1,144 @@
+
+// eaglercraft opengl 1.3 emulation
+// copyright (c) 2020 calder young
+// creative commons BY-NC 4.0
+
+#line 7
+
+precision highp int;
+precision highp sampler2D;
+precision highp float;
+
+uniform mat4 matrix_m;
+uniform mat4 matrix_p;
+uniform mat4 matrix_t;
+
+#ifdef CC_VERT
+
+in vec3 a_position;
+#ifdef CC_a_texture0
+in vec2 a_texture0;
+#endif
+#ifdef CC_a_color
+in vec4 a_color;
+#endif
+#ifdef CC_a_normal
+in vec4 a_normal;
+#endif
+
+#ifdef CC_fog
+out vec4 v_position;
+#endif
+#ifdef CC_a_color
+out vec4 v_color;
+#endif
+#ifdef CC_a_normal
+out vec4 v_normal;
+#endif
+#ifdef CC_a_texture0
+out vec2 v_texture0;
+#endif
+
+void main(){
+ vec4 pos = matrix_m * vec4(a_position, 1.0);
+#ifdef CC_fog
+ v_position = pos;
+#endif
+#ifdef CC_a_color
+ v_color = a_color;
+#endif
+#ifdef CC_a_normal
+ v_normal = a_normal;
+#endif
+#ifdef CC_a_texture0
+ v_texture0 = a_texture0;
+#endif
+ gl_Position = matrix_p * pos;
+}
+
+#endif
+
+#ifdef CC_FRAG
+
+#ifdef CC_unit0
+uniform sampler2D tex0;
+#ifndef CC_a_texture0
+uniform vec2 texCoordV0;
+#endif
+#endif
+#ifdef CC_lighting
+uniform vec3 light0Pos;
+uniform vec3 light1Pos;
+uniform vec3 normalUniform;
+#endif
+#ifdef CC_fog
+uniform vec4 fogColor;
+uniform int fogMode;
+uniform float fogStart;
+uniform float fogEnd;
+uniform float fogDensity;
+uniform float fogPremultiply;
+#endif
+uniform vec4 colorUniform;
+#ifdef CC_alphatest
+uniform float alphaTestF;
+#endif
+
+#ifdef CC_fog
+in vec4 v_position;
+#endif
+#ifdef CC_a_color
+in vec4 v_color;
+#endif
+#ifdef CC_a_normal
+in vec4 v_normal;
+#endif
+#ifdef CC_a_texture0
+in vec2 v_texture0;
+#endif
+
+out vec4 fragColor;
+
+void main(){
+#ifdef CC_a_color
+ vec4 color = colorUniform * v_color;
+#else
+ vec4 color = colorUniform;
+#endif
+
+#ifdef CC_unit0
+#ifdef CC_a_texture0
+ color *= texture(tex0, (matrix_t * vec4(v_texture0, 0.0, 1.0)).xy).rgba;
+#else
+ color *= texture(tex0, (matrix_t * vec4(texCoordV0, 0.0, 1.0)).xy).rgba;
+#endif
+#endif
+
+#ifdef CC_alphatest
+ if(color.a < alphaTestF){
+ discard;
+ }
+#endif
+
+#ifdef CC_lighting
+#ifdef CC_a_normal
+ vec3 normal = ((v_normal.xyz - 0.5) * 2.0);
+#else
+ vec3 normal = normalUniform;
+#endif
+ normal = normalize(mat3(matrix_m) * normal);
+ float ins = max(dot(normal, -light0Pos), 0.0) + max(dot(normal, -light1Pos), 0.0);
+ color.rgb *= min((0.4 + ins * 0.6), 1.0);
+#endif
+
+#ifdef CC_fog
+ float dist = sqrt(dot(v_position, v_position));
+ float i = (fogMode == 1) ? clamp((dist - fogStart) / (fogEnd - fogStart), 0.0, 1.0) : clamp(1.0 - pow(2.718, -(fogDensity * dist)), 0.0, 1.0);
+ color.rgb = mix(color.rgb, fogColor.xyz, i * fogColor.a);
+#endif
+
+ fragColor = color;
+}
+
+#endif
+
diff --git a/resources/glsl/fxaa.glsl b/resources/glsl/fxaa.glsl
new file mode 100644
index 0000000..8cd01a3
--- /dev/null
+++ b/resources/glsl/fxaa.glsl
@@ -0,0 +1,255 @@
+#line 0
+
+precision lowp int;
+precision lowp sampler2D;
+precision lowp float;
+
+in vec2 pos;
+
+out vec4 fragColor;
+
+#define FXAA_PC 1
+#define FXAA_GLSL_130 1
+#define FXAA_FAST_PIXEL_OFFSET 0
+#define FXAA_GATHER4_ALPHA 0
+
+#ifndef FXAA_GREEN_AS_LUMA
+ // For those using non-linear color,
+ // and either not able to get luma in alpha, or not wanting to,
+ // this enables FXAA to run using green as a proxy for luma.
+ // So with this enabled, no need to pack luma in alpha.
+ //
+ // This will turn off AA on anything which lacks some amount of green.
+ // Pure red and blue or combination of only R and B, will get no AA.
+ //
+ // Might want to lower the settings for both,
+ // fxaaConsoleEdgeThresholdMin
+ // fxaaQualityEdgeThresholdMin
+ // In order to insure AA does not get turned off on colors
+ // which contain a minor amount of green.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_GREEN_AS_LUMA 1
+#endif
+
+#ifndef FXAA_DISCARD
+ // 1 = Use discard on pixels which don't need AA.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ #define FXAA_DISCARD 0
+#endif
+
+/*============================================================================
+ API PORTING
+============================================================================*/
+ #define FxaaBool bool
+ #define FxaaDiscard discard
+ #define FxaaFloat float
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaHalf float
+ #define FxaaHalf2 vec2
+ #define FxaaHalf3 vec3
+ #define FxaaHalf4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaTex sampler2D
+/*--------------------------------------------------------------------------*/
+
+ #define FxaaTexTop(t, p) texture(t, p)
+
+/*============================================================================
+ GREEN AS LUMA OPTION SUPPORT FUNCTION
+============================================================================*/
+#if (FXAA_GREEN_AS_LUMA == 0)
+ // TODO Luma
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return dot(rgba.xyz, vec3(0.299, 0.587, 0.114)); }
+#else
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
+#endif
+
+/*============================================================================
+ FXAA3 CONSOLE - PC VERSION
+============================================================================*/
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+ //
+ // Used only for FXAA Console, and not used on the 360 version.
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ // if (FXAA_GREEN_AS_LUMA == 0)
+ // {___a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ //
+ // Only used on FXAA Console.
+ // This must be from a constant/uniform.
+ // This effects sub-pixel AA quality and inversely sharpness.
+ // Where N ranges between,
+ // N = 0.50 (default)
+ // N = 0.33 (sharper)
+ // {x___} = -N/screenWidthInPixels
+ // {_y__} = -N/screenHeightInPixels
+ // {__z_} = N/screenWidthInPixels
+ // {___w} = N/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ //
+ // Only used on FXAA Console.
+ // Not used on 360, but used on PS3 and PC.
+ // This must be from a constant/uniform.
+ // {x___} = -2.0/screenWidthInPixels
+ // {_y__} = -2.0/screenHeightInPixels
+ // {__z_} = 2.0/screenWidthInPixels
+ // {___w} = 2.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only three safe values here: 2 and 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // For all other platforms can be a non-power of two.
+ // 8.0 is sharper (default!!!)
+ // 4.0 is softer
+ // 2.0 is really soft (good only for vector graphics inputs)
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 1/4 and 1/8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // The console setting has a different mapping than the quality setting.
+ // Other platforms can use other values.
+ // 0.125 leaves less aliasing, but is softer (default!!!)
+ // 0.25 leaves more aliasing, and is sharper
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ // This does not apply to PS3,
+ // PS3 was simplified to avoid more shader instructions.
+ // 0.06 - faster but more aliasing in darks
+ // 0.05 - default
+ // 0.04 - slower and less aliasing in darks
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaConsoleEdgeThresholdMin
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));
+ FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));
+ FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));
+ FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ // TODO Luma
+ FxaaFloat lumaM = FxaaLuma(rgbyM);
+ #else
+ FxaaFloat lumaM = rgbyM.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);
+ lumaNe += 1.0/384.0;
+ FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);
+ FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
+ FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMinM = min(lumaMin, lumaM);
+ FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);
+ FxaaFloat lumaMaxM = max(lumaMax, lumaM);
+ FxaaFloat dirSwMinusNe = lumaSw - lumaNe;
+ FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;
+ FxaaFloat dirSeMinusNw = lumaSe - lumaNw;
+ if(lumaMaxSubMinM < lumaMaxScaledClamped)
+ {
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+ }
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir;
+ dir.x = dirSwMinusNe + dirSeMinusNw;
+ dir.y = dirSwMinusNe - dirSeMinusNw;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir1 = normalize(dir.xy);
+ FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);
+ FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;
+ FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir2x = dir2 * fxaaConsoleRcpFrameOpt2.zw;
+ FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2x);
+ FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2x);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;
+ FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ // TODO Luma
+ float lumaB = FxaaLuma(rgbyB);
+ #else
+ float lumaB = rgbyB.y;
+ #endif
+ if((lumaB < lumaMin) || (lumaB > lumaMax))
+ rgbyB.xyz = rgbyA.xyz * 0.5;
+ //
+ return rgbyB;
+}
+/*==========================================================================*/
+
+uniform sampler2D f_color;
+
+uniform vec2 screenSize;
+
+#define edgeSharpness 7.0
+#define edgeThreshold 0.1
+#define edgeThresholdMin 0.005
+
+void main(){
+ vec4 posPos;
+ posPos.xy = pos - (0.6 / screenSize);
+ posPos.zw = pos + (0.6 / screenSize);
+ vec4 rcpFrameOpt;
+ rcpFrameOpt.xy = vec2(-0.50, -0.50) / screenSize;
+ rcpFrameOpt.zw = vec2( 0.50, 0.50) / screenSize;
+ vec4 rcpFrameOpt2;
+ rcpFrameOpt2.xy = vec2(-2.0, -2.0) / screenSize;
+ rcpFrameOpt2.zw = vec2( 2.0, 2.0) / screenSize;
+
+ fragColor = vec4(FxaaPixelShader(pos, posPos, f_color, rcpFrameOpt, rcpFrameOpt2, edgeSharpness, edgeThreshold, edgeThresholdMin).rgb, 1.0);
+}
diff --git a/resources/glsl/occl.glsl b/resources/glsl/occl.glsl
new file mode 100644
index 0000000..df74763
--- /dev/null
+++ b/resources/glsl/occl.glsl
@@ -0,0 +1,25 @@
+#line 2
+
+precision highp int;
+precision highp sampler2D;
+precision highp float;
+
+#ifdef CC_VERT
+uniform mat4 matrix_m;
+uniform mat4 matrix_p;
+
+in vec3 a_vert;
+
+void main(){
+ gl_Position = (matrix_p * (matrix_m * vec4(a_vert, 1.0)));
+}
+#endif
+
+#ifdef CC_FRAG
+
+out vec4 fragColor;
+
+void main(){
+ fragColor = vec4(1.0);
+}
+#endif
diff --git a/resources/glsl/pvert.glsl b/resources/glsl/pvert.glsl
new file mode 100644
index 0000000..ce17a2c
--- /dev/null
+++ b/resources/glsl/pvert.glsl
@@ -0,0 +1,13 @@
+#line 0
+
+precision lowp int;
+precision lowp sampler2D;
+precision lowp float;
+
+in vec2 a_pos;
+
+out vec2 pos;
+
+void main(){
+ gl_Position = vec4((pos = a_pos) * 2.0 - 1.0, 0.0, 1.0);
+}
diff --git a/resources/grass.png b/resources/grass.png
new file mode 100644
index 0000000..fd7a724
Binary files /dev/null and b/resources/grass.png differ
diff --git a/resources/gui/gui.png b/resources/gui/gui.png
new file mode 100644
index 0000000..81af329
Binary files /dev/null and b/resources/gui/gui.png differ
diff --git a/resources/gui/icons.png b/resources/gui/icons.png
new file mode 100644
index 0000000..93e95aa
Binary files /dev/null and b/resources/gui/icons.png differ
diff --git a/resources/item/arrows.png b/resources/item/arrows.png
new file mode 100644
index 0000000..75c5828
Binary files /dev/null and b/resources/item/arrows.png differ
diff --git a/resources/item/sign.png b/resources/item/sign.png
new file mode 100644
index 0000000..e829472
Binary files /dev/null and b/resources/item/sign.png differ
diff --git a/resources/mob/creeper.png b/resources/mob/creeper.png
new file mode 100644
index 0000000..e0a5e0a
Binary files /dev/null and b/resources/mob/creeper.png differ
diff --git a/resources/mob/pig.png b/resources/mob/pig.png
new file mode 100644
index 0000000..5c1efc2
Binary files /dev/null and b/resources/mob/pig.png differ
diff --git a/resources/mob/sheep.png b/resources/mob/sheep.png
new file mode 100644
index 0000000..98cfa9a
Binary files /dev/null and b/resources/mob/sheep.png differ
diff --git a/resources/mob/sheep_fur.png b/resources/mob/sheep_fur.png
new file mode 100644
index 0000000..f1291a5
Binary files /dev/null and b/resources/mob/sheep_fur.png differ
diff --git a/resources/mob/skeleton.png b/resources/mob/skeleton.png
new file mode 100644
index 0000000..9d22339
Binary files /dev/null and b/resources/mob/skeleton.png differ
diff --git a/resources/mob/spider.png b/resources/mob/spider.png
new file mode 100644
index 0000000..08344a8
Binary files /dev/null and b/resources/mob/spider.png differ
diff --git a/resources/mob/zombie.png b/resources/mob/zombie.png
new file mode 100644
index 0000000..0ab7089
Binary files /dev/null and b/resources/mob/zombie.png differ
diff --git a/resources/null b/resources/null
new file mode 100644
index 0000000..e69de29
diff --git a/resources/particles.png b/resources/particles.png
new file mode 100644
index 0000000..3077c2d
Binary files /dev/null and b/resources/particles.png differ
diff --git a/resources/rain.png b/resources/rain.png
new file mode 100644
index 0000000..e9dc16c
Binary files /dev/null and b/resources/rain.png differ
diff --git a/resources/terrain.png b/resources/terrain.png
new file mode 100644
index 0000000..cbf4e3c
Binary files /dev/null and b/resources/terrain.png differ
diff --git a/resources/water.png b/resources/water.png
new file mode 100644
index 0000000..8b92f9b
Binary files /dev/null and b/resources/water.png differ
diff --git a/src/main/java/com/mojang/minecraft/ChatLine.java b/src/main/java/com/mojang/minecraft/ChatLine.java
new file mode 100644
index 0000000..05ebffe
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/ChatLine.java
@@ -0,0 +1,13 @@
+package com.mojang.minecraft;
+
+public class ChatLine
+{
+ public ChatLine(String message)
+ {
+ this.message = message;
+ this.time = 0;
+ }
+
+ public String message;
+ public int time;
+}
diff --git a/src/main/java/com/mojang/minecraft/Entity.java b/src/main/java/com/mojang/minecraft/Entity.java
new file mode 100644
index 0000000..595cd6d
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/Entity.java
@@ -0,0 +1,477 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.level.BlockMap;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.level.tile.Tile$SoundType;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.net.PositionUpdate;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+public abstract class Entity implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ public Level level;
+ public float xo;
+ public float yo;
+ public float zo;
+ public float x;
+ public float y;
+ public float z;
+ public float xd;
+ public float yd;
+ public float zd;
+ public float yRot;
+ public float xRot;
+ public float yRotO;
+ public float xRotO;
+ public AABB bb;
+ public boolean onGround = false;
+ public boolean horizontalCollision = false;
+ public boolean collision = false;
+ public boolean slide = true;
+ public boolean removed = false;
+ public float heightOffset = 0.0F;
+ public float bbWidth = 0.6F;
+ public float bbHeight = 1.8F;
+ public float walkDistO = 0.0F;
+ public float walkDist = 0.0F;
+ public boolean makeStepSound = true;
+ public float fallDistance = 0.0F;
+ private int nextStep = 1;
+ public BlockMap blockMap;
+ public float xOld;
+ public float yOld;
+ public float zOld;
+ public int textureId = 0;
+ public float ySlideOffset = 0.0F;
+ public float footSize = 0.0F;
+ public boolean noPhysics = false;
+ public float pushthrough = 0.0F;
+ public boolean hovered = false;
+
+
+ public Entity(Level var1) {
+ this.level = var1;
+ this.setPos(0.0F, 0.0F, 0.0F);
+ }
+
+ public void resetPos() {
+ if(this.level != null) {
+ float var1 = (float)this.level.xSpawn + 0.5F;
+ float var2 = (float)this.level.ySpawn;
+
+ for(float var3 = (float)this.level.zSpawn + 0.5F; var2 > 0.0F; ++var2) {
+ this.setPos(var1, var2, var3);
+ if(this.level.getCubes(this.bb).size() == 0) {
+ break;
+ }
+ }
+
+ this.xd = this.yd = this.zd = 0.0F;
+ this.yRot = this.level.rotSpawn;
+ this.xRot = 0.0F;
+ }
+ }
+
+ public void remove() {
+ this.removed = true;
+ }
+
+ public void setSize(float var1, float var2) {
+ this.bbWidth = var1;
+ this.bbHeight = var2;
+ }
+
+ public void setPos(PositionUpdate var1) {
+ if(var1.position) {
+ this.setPos(var1.x, var1.y, var1.z);
+ } else {
+ this.setPos(this.x, this.y, this.z);
+ }
+
+ if(var1.rotation) {
+ this.setRot(var1.yaw, var1.pitch);
+ } else {
+ this.setRot(this.yRot, this.xRot);
+ }
+ }
+
+ protected void setRot(float var1, float var2) {
+ this.yRot = var1;
+ this.xRot = var2;
+ }
+
+ public void setPos(float var1, float var2, float var3) {
+ this.x = var1;
+ this.y = var2;
+ this.z = var3;
+ float var4 = this.bbWidth / 2.0F;
+ float var5 = this.bbHeight / 2.0F;
+ this.bb = new AABB(var1 - var4, var2 - var5, var3 - var4, var1 + var4, var2 + var5, var3 + var4);
+ }
+
+ public void turn(float var1, float var2) {
+ float var3 = this.xRot;
+ float var4 = this.yRot;
+ this.yRot = (float)((double)this.yRot + (double)var1 * 0.15D);
+ this.xRot = (float)((double)this.xRot - (double)var2 * 0.15D);
+ if(this.xRot < -90.0F) {
+ this.xRot = -90.0F;
+ }
+
+ if(this.xRot > 90.0F) {
+ this.xRot = 90.0F;
+ }
+
+ this.xRotO += this.xRot - var3;
+ this.yRotO += this.yRot - var4;
+ }
+
+ public void interpolateTurn(float var1, float var2) {
+ this.yRot = (float)((double)this.yRot + (double)var1 * 0.15D);
+ this.xRot = (float)((double)this.xRot - (double)var2 * 0.15D);
+ if(this.xRot < -90.0F) {
+ this.xRot = -90.0F;
+ }
+
+ if(this.xRot > 90.0F) {
+ this.xRot = 90.0F;
+ }
+
+ }
+
+ public void tick() {
+ this.walkDistO = this.walkDist;
+ this.xo = this.x;
+ this.yo = this.y;
+ this.zo = this.z;
+ this.xRotO = this.xRot;
+ this.yRotO = this.yRot;
+ }
+
+ public boolean isFree(float var1, float var2, float var3, float var4) {
+ AABB var5 = this.bb.grow(var4, var4, var4).cloneMove(var1, var2, var3);
+ return this.level.getCubes(var5).size() > 0?false:!this.level.containsAnyLiquid(var5);
+ }
+
+ public boolean isFree(float var1, float var2, float var3) {
+ AABB var4 = this.bb.cloneMove(var1, var2, var3);
+ return this.level.getCubes(var4).size() > 0?false:!this.level.containsAnyLiquid(var4);
+ }
+
+ public void move(float var1, float var2, float var3) {
+ if(this.noPhysics) {
+ this.bb.move(var1, var2, var3);
+ this.x = (this.bb.x0 + this.bb.x1) / 2.0F;
+ this.y = this.bb.y0 + this.heightOffset - this.ySlideOffset;
+ this.z = (this.bb.z0 + this.bb.z1) / 2.0F;
+ } else {
+ float var4 = this.x;
+ float var5 = this.z;
+ float var6 = var1;
+ float var7 = var2;
+ float var8 = var3;
+ AABB var9 = this.bb.copy();
+ ArrayList var10 = this.level.getCubes(this.bb.expand(var1, var2, var3));
+
+ for(int var11 = 0; var11 < var10.size(); ++var11) {
+ var2 = ((AABB)var10.get(var11)).clipYCollide(this.bb, var2);
+ }
+
+ this.bb.move(0.0F, var2, 0.0F);
+ if(!this.slide && var7 != var2) {
+ var3 = 0.0F;
+ var2 = 0.0F;
+ var1 = 0.0F;
+ }
+
+ boolean var16 = this.onGround || var7 != var2 && var7 < 0.0F;
+
+ int var12;
+ for(var12 = 0; var12 < var10.size(); ++var12) {
+ var1 = ((AABB)var10.get(var12)).clipXCollide(this.bb, var1);
+ }
+
+ this.bb.move(var1, 0.0F, 0.0F);
+ if(!this.slide && var6 != var1) {
+ var3 = 0.0F;
+ var2 = 0.0F;
+ var1 = 0.0F;
+ }
+
+ for(var12 = 0; var12 < var10.size(); ++var12) {
+ var3 = ((AABB)var10.get(var12)).clipZCollide(this.bb, var3);
+ }
+
+ this.bb.move(0.0F, 0.0F, var3);
+ if(!this.slide && var8 != var3) {
+ var3 = 0.0F;
+ var2 = 0.0F;
+ var1 = 0.0F;
+ }
+
+ float var17;
+ float var18;
+ if(this.footSize > 0.0F && var16 && this.ySlideOffset < 0.05F && (var6 != var1 || var8 != var3)) {
+ var18 = var1;
+ var17 = var2;
+ float var13 = var3;
+ var1 = var6;
+ var2 = this.footSize;
+ var3 = var8;
+ AABB var14 = this.bb.copy();
+ this.bb = var9.copy();
+ var10 = this.level.getCubes(this.bb.expand(var6, var2, var8));
+
+ int var15;
+ for(var15 = 0; var15 < var10.size(); ++var15) {
+ var2 = ((AABB)var10.get(var15)).clipYCollide(this.bb, var2);
+ }
+
+ this.bb.move(0.0F, var2, 0.0F);
+ if(!this.slide && var7 != var2) {
+ var3 = 0.0F;
+ var2 = 0.0F;
+ var1 = 0.0F;
+ }
+
+ for(var15 = 0; var15 < var10.size(); ++var15) {
+ var1 = ((AABB)var10.get(var15)).clipXCollide(this.bb, var1);
+ }
+
+ this.bb.move(var1, 0.0F, 0.0F);
+ if(!this.slide && var6 != var1) {
+ var3 = 0.0F;
+ var2 = 0.0F;
+ var1 = 0.0F;
+ }
+
+ for(var15 = 0; var15 < var10.size(); ++var15) {
+ var3 = ((AABB)var10.get(var15)).clipZCollide(this.bb, var3);
+ }
+
+ this.bb.move(0.0F, 0.0F, var3);
+ if(!this.slide && var8 != var3) {
+ var3 = 0.0F;
+ var2 = 0.0F;
+ var1 = 0.0F;
+ }
+
+ if(var18 * var18 + var13 * var13 >= var1 * var1 + var3 * var3) {
+ var1 = var18;
+ var2 = var17;
+ var3 = var13;
+ this.bb = var14.copy();
+ } else {
+ this.ySlideOffset = (float)((double)this.ySlideOffset + 0.5D);
+ }
+ }
+
+ this.horizontalCollision = var6 != var1 || var8 != var3;
+ this.onGround = var7 != var2 && var7 < 0.0F;
+ this.collision = this.horizontalCollision || var7 != var2;
+ if(this.onGround) {
+ if(this.fallDistance > 0.0F) {
+ this.causeFallDamage(this.fallDistance);
+ this.fallDistance = 0.0F;
+ }
+ } else if(var2 < 0.0F) {
+ this.fallDistance -= var2;
+ }
+
+ if(var6 != var1) {
+ this.xd = 0.0F;
+ }
+
+ if(var7 != var2) {
+ this.yd = 0.0F;
+ }
+
+ if(var8 != var3) {
+ this.zd = 0.0F;
+ }
+
+ this.x = (this.bb.x0 + this.bb.x1) / 2.0F;
+ this.y = this.bb.y0 + this.heightOffset - this.ySlideOffset;
+ this.z = (this.bb.z0 + this.bb.z1) / 2.0F;
+ var18 = this.x - var4;
+ var17 = this.z - var5;
+ this.walkDist = (float)((double)this.walkDist + (double)MathHelper.sqrt(var18 * var18 + var17 * var17) * 0.6D);
+ if(this.makeStepSound) {
+ int var19 = this.level.getTile((int)this.x, (int)(this.y - 0.2F - this.heightOffset), (int)this.z);
+ if(this.walkDist > (float)this.nextStep && var19 > 0) {
+ ++this.nextStep;
+ Tile$SoundType var20;
+ if((var20 = Block.blocks[var19].stepsound) != Tile$SoundType.none) {
+ this.playSound("step." + var20.name, var20.getVolume() * 0.75F, var20.getPitch());
+ }
+ }
+ }
+
+ this.ySlideOffset *= 0.4F;
+ }
+ }
+
+ protected void causeFallDamage(float var1) {}
+
+ public boolean isInWater() {
+ return this.level.containsLiquid(this.bb.grow(0.0F, -0.4F, 0.0F), LiquidType.WATER);
+ }
+
+ public boolean isUnderWater() {
+ int var1;
+ return (var1 = this.level.getTile((int)this.x, (int)(this.y + 0.12F), (int)this.z)) != 0?Block.blocks[var1].getLiquidType().equals(LiquidType.WATER):false;
+ }
+
+ public boolean isInLava() {
+ return this.level.containsLiquid(this.bb.grow(0.0F, -0.4F, 0.0F), LiquidType.LAVA);
+ }
+
+ public void moveRelative(float var1, float var2, float var3) {
+ float var4;
+ if((var4 = MathHelper.sqrt(var1 * var1 + var2 * var2)) >= 0.01F) {
+ if(var4 < 1.0F) {
+ var4 = 1.0F;
+ }
+
+ var4 = var3 / var4;
+ var1 *= var4;
+ var2 *= var4;
+ var3 = MathHelper.sin(this.yRot * 3.1415927F / 180.0F);
+ var4 = MathHelper.cos(this.yRot * 3.1415927F / 180.0F);
+ this.xd += var1 * var4 - var2 * var3;
+ this.zd += var2 * var4 + var1 * var3;
+ }
+ }
+
+ public boolean isLit() {
+ int var1 = (int)this.x;
+ int var2 = (int)this.y;
+ int var3 = (int)this.z;
+ return this.level.isLit(var1, var2, var3);
+ }
+
+ public float getBrightness(float var1) {
+ int var4 = (int)this.x;
+ int var2 = (int)(this.y + this.heightOffset / 2.0F - 0.5F);
+ int var3 = (int)this.z;
+ return this.level.getBrightness(var4, var2, var3);
+ }
+
+ public void render(TextureManager var1, float var2) {}
+
+ public void setLevel(Level var1) {
+ this.level = var1;
+ }
+
+ public void playSound(String var1, float var2, float var3) {
+ this.level.playSound(var1, this, var2, var3);
+ }
+
+ public void moveTo(float var1, float var2, float var3, float var4, float var5) {
+ this.xo = this.x = var1;
+ this.yo = this.y = var2;
+ this.zo = this.z = var3;
+ this.yRot = var4;
+ this.xRot = var5;
+ this.setPos(var1, var2, var3);
+ }
+
+ public float distanceTo(Entity var1) {
+ float var2 = this.x - var1.x;
+ float var3 = this.y - var1.y;
+ float var4 = this.z - var1.z;
+ return MathHelper.sqrt(var2 * var2 + var3 * var3 + var4 * var4);
+ }
+
+ public float distanceTo(float var1, float var2, float var3) {
+ var1 = this.x - var1;
+ var2 = this.y - var2;
+ float var4 = this.z - var3;
+ return MathHelper.sqrt(var1 * var1 + var2 * var2 + var4 * var4);
+ }
+
+ public float distanceToSqr(Entity var1) {
+ float var2 = this.x - var1.x;
+ float var3 = this.y - var1.y;
+ float var4 = this.z - var1.z;
+ return var2 * var2 + var3 * var3 + var4 * var4;
+ }
+
+ public void playerTouch(Entity var1) {}
+
+ public void push(Entity var1) {
+ float var2 = var1.x - this.x;
+ float var3 = var1.z - this.z;
+ float var4;
+ if((var4 = var2 * var2 + var3 * var3) >= 0.01F) {
+ var4 = MathHelper.sqrt(var4);
+ var2 /= var4;
+ var3 /= var4;
+ var2 /= var4;
+ var3 /= var4;
+ var2 *= 0.05F;
+ var3 *= 0.05F;
+ var2 *= 1.0F - this.pushthrough;
+ var3 *= 1.0F - this.pushthrough;
+ this.push(-var2, 0.0F, -var3);
+ var1.push(var2, 0.0F, var3);
+ }
+
+ }
+
+ protected void push(float var1, float var2, float var3) {
+ this.xd += var1;
+ this.yd += var2;
+ this.zd += var3;
+ }
+
+ public void hurt(Entity var1, int var2) {}
+
+ public boolean intersects(float var1, float var2, float var3, float var4, float var5, float var6) {
+ return this.bb.intersects(var1, var2, var3, var4, var5, var6);
+ }
+
+ public boolean isPickable() {
+ return false;
+ }
+
+ public boolean isPushable() {
+ return false;
+ }
+
+ public boolean isShootable() {
+ return false;
+ }
+
+ public void awardKillScore(Entity var1, int var2) {}
+
+ public boolean shouldRender(Vec3D var1) {
+ float var2 = this.x - var1.x;
+ float var3 = this.y - var1.y;
+ float var4 = this.z - var1.z;
+ var4 = var2 * var2 + var3 * var3 + var4 * var4;
+ return this.shouldRenderAtSqrDistance(var4);
+ }
+
+ public boolean shouldRenderAtSqrDistance(float var1) {
+ float var2 = this.bb.getSize() * 64.0F;
+ return var1 < var2 * var2;
+ }
+
+ public int getTexture() {
+ return this.textureId;
+ }
+
+ public boolean isCreativeModeAllowed() {
+ return false;
+ }
+
+ public void renderHover(TextureManager var1, float var2) {}
+}
diff --git a/src/main/java/com/mojang/minecraft/GameSettings.java b/src/main/java/com/mojang/minecraft/GameSettings.java
new file mode 100644
index 0000000..06f11af
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/GameSettings.java
@@ -0,0 +1,287 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.render.TextureManager;
+import java.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import org.lwjgl.input.Keyboard;
+
+import com.mojang.minecraft.gamemode.*;
+import com.mojang.minecraft.player.Inventory;
+
+public final class GameSettings
+{
+ public GameSettings(Minecraft minecraft, File minecraftFolder)
+ {
+ bindings = new KeyBinding[] {forwardKey, leftKey, backKey, rightKey, jumpKey, buildKey, chatKey, toggleFogKey, saveLocationKey, loadLocationKey};
+
+ settingCount = 8;
+
+ this.minecraft = minecraft;
+
+ settingsFile = new File(minecraftFolder, "options.txt");
+
+ load();
+ }
+
+ private static final String[] renderDistances = new String[]{"FAR", "NORMAL", "SHORT", "TINY"};
+ public boolean music = true;
+ public boolean sound = true;
+ public boolean invertMouse = false;
+ public boolean showFrameRate = false;
+ public int viewDistance = 0;
+ public boolean viewBobbing = true;
+ public boolean anaglyph = false;
+ public boolean limitFramerate = false;
+ public boolean ofBetterGrass = false;
+ public boolean ofFastMath = true;
+ public boolean ofSmoothFPS = false;
+ public boolean gamemode = false;
+ public boolean randomDrops = false;
+ public KeyBinding forwardKey = new KeyBinding("Forward", 17);
+ public KeyBinding leftKey = new KeyBinding("Left", 30);
+ public KeyBinding backKey = new KeyBinding("Back", 31);
+ public KeyBinding rightKey = new KeyBinding("Right", 32);
+ public KeyBinding jumpKey = new KeyBinding("Jump", 57);
+ public KeyBinding buildKey = new KeyBinding("Build", 48);
+ public KeyBinding chatKey = new KeyBinding("Chat", 20);
+ public KeyBinding toggleFogKey = new KeyBinding("Toggle fog", 33);
+ public KeyBinding saveLocationKey = new KeyBinding("Save location", 28);
+ public KeyBinding loadLocationKey = new KeyBinding("Load location", 19);
+ public KeyBinding[] bindings;
+ private Minecraft minecraft;
+ private File settingsFile;
+ public int settingCount;
+
+ public String getBinding(int key)
+ {
+ return bindings[key].name + ": " + Keyboard.getKeyName(bindings[key].key);
+ }
+
+ public void setBinding(int key, int keyID)
+ {
+ bindings[key].key = keyID;
+
+ save();
+ }
+
+ public void toggleSetting(int setting, int fogValue)
+ {
+ if(setting == 0)
+ {
+ music = !music;
+ }
+
+ if(setting == 1)
+ {
+ sound = !sound;
+ }
+
+ if(setting == 2)
+ {
+ invertMouse = !invertMouse;
+ }
+
+ if(setting == 3)
+ {
+ showFrameRate = !showFrameRate;
+ }
+
+ if(setting == 4)
+ {
+ viewDistance = viewDistance + fogValue & 3;
+ }
+
+ if(setting == 5)
+ {
+ viewBobbing = !viewBobbing;
+ }
+
+ if(setting == 6)
+ {
+ minecraft.levelRenderer.refresh();
+ anaglyph = !anaglyph;
+ minecraft.levelRenderer.refresh();
+ }
+
+ if(setting == 7)
+ {
+ limitFramerate = !limitFramerate;
+ }
+
+ if(setting == 8) {
+ ofBetterGrass = !ofBetterGrass;
+ minecraft.levelRenderer.refresh();
+ }
+
+ if(setting == 9) {
+ ofFastMath = !ofFastMath;
+ minecraft.levelRenderer.refresh();
+ }
+
+ if(setting == 11) {
+ if(gamemode) {
+ GameMode game = new SurvivalGameMode(minecraft);
+ game.apply(minecraft.level);
+ game.apply(minecraft.player);
+ minecraft.gamemode = game;
+ } else {
+ GameMode game = new CreativeGameMode(minecraft);
+ game.apply(minecraft.level);
+ game.apply(minecraft.player);
+ minecraft.gamemode = game;
+ }
+ gamemode = !gamemode;
+ }
+
+ if(setting == 12) {
+ randomDrops = !randomDrops;
+ }
+
+ save();
+ }
+
+ public String getSetting(int id)
+ {
+ return id == 0 ? "Music: " + (music ? "ON" : "OFF")
+ : (id == 1 ? "Sound: " + (sound ? "ON" : "OFF")
+ : (id == 2 ? "Invert mouse: " + (invertMouse ? "ON" : "OFF")
+ : (id == 3 ? "Show FPS: " + (showFrameRate ? "ON" : "OFF")
+ : (id == 4 ? "Render distance: " + renderDistances[viewDistance]
+ : (id == 5 ? "View bobbing: " + (viewBobbing ? "ON" : "OFF")
+ : (id == 6 ? "3d anaglyph: " + (anaglyph ? "ON" : "OFF")
+ : (id == 7 ? "Limit framerate: " + (limitFramerate ? "ON" : "OFF")
+ : (id == 8 ? "Better Grass: " + (ofBetterGrass ? "ON" : "OFF")
+ : (id == 9 ? "Fast Math: " + (ofFastMath ? "ON" : "OFF")
+ : (id == 10 ? "Smooth FPS: " + (ofSmoothFPS ? "ON" : "OFF")
+ : (id == 11 ? "GameMode: " + (gamemode ? "Creative" : "Survival")
+ : (id == 12 ? "Random Drops: " + (randomDrops ? "ON": "OFF")
+ : ""))))))))))));
+ }
+
+ private void load()
+ {
+ try
+ {
+ if(settingsFile.exists())
+ {
+ FileReader fileReader = new FileReader(settingsFile);
+ BufferedReader reader = new BufferedReader(fileReader);
+
+ String line = null;
+
+ while((line = reader.readLine()) != null)
+ {
+ String[] setting = line.split(":");
+
+ if(setting[0].equals("music"))
+ {
+ music = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("sound"))
+ {
+ sound = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("invertYMouse"))
+ {
+ invertMouse = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("showFrameRate"))
+ {
+ showFrameRate = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("viewDistance"))
+ {
+ viewDistance = Integer.parseInt(setting[1]);
+ }
+
+ if(setting[0].equals("bobView"))
+ {
+ viewBobbing = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("anaglyph3d"))
+ {
+ anaglyph = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("limitFramerate"))
+ {
+ limitFramerate = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("ofBetterGrass"))
+ {
+ ofBetterGrass = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("ofFastMath"))
+ {
+ ofFastMath = setting[1].equals("true");
+ }
+
+ if(setting[0].equals("ofSmoothFPS"))
+ {
+ ofSmoothFPS = setting[1].equals("true");
+ }
+
+ for(int index = 0; index < this.bindings.length; index++)
+ {
+ if(setting[0].equals("key_" + bindings[index].name))
+ {
+ bindings[index].key = Integer.parseInt(setting[1]);
+ }
+ }
+ }
+
+ reader.close();
+ }
+ } catch (Exception e) {
+ System.out.println("Failed to load options");
+
+ e.printStackTrace();
+ }
+ }
+
+ private void save()
+ {
+ try {
+ FileWriter fileWriter = new FileWriter(this.settingsFile);
+ PrintWriter writer = new PrintWriter(fileWriter);
+
+ writer.println("music:" + music);
+ writer.println("sound:" + sound);
+ writer.println("invertYMouse:" + invertMouse);
+ writer.println("showFrameRate:" + showFrameRate);
+ writer.println("viewDistance:" + viewDistance);
+ writer.println("bobView:" + viewBobbing);
+ writer.println("anaglyph3d:" + anaglyph);
+ writer.println("limitFramerate:" + limitFramerate);
+ writer.println("ofBetterGrass:" + ofBetterGrass);
+ writer.println("ofFastMath:" + ofFastMath);
+ writer.println("ofSmoothFPS:" + ofSmoothFPS);
+
+ for(int binding = 0; binding < bindings.length; binding++)
+ {
+ writer.println("key_" + bindings[binding].name + ":" + bindings[binding].key);
+ }
+
+ writer.close();
+ } catch (Exception e) {
+ System.out.println("Failed to save options");
+
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/KeyBinding.java b/src/main/java/com/mojang/minecraft/KeyBinding.java
new file mode 100644
index 0000000..b97a0d1
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/KeyBinding.java
@@ -0,0 +1,13 @@
+package com.mojang.minecraft;
+
+public class KeyBinding
+{
+ public KeyBinding(String name, int key)
+ {
+ this.name = name;
+ this.key = key;
+ }
+
+ public String name;
+ public int key;
+}
diff --git a/src/main/java/com/mojang/minecraft/Minecraft$OS.java b/src/main/java/com/mojang/minecraft/Minecraft$OS.java
new file mode 100644
index 0000000..53e2455
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/Minecraft$OS.java
@@ -0,0 +1,16 @@
+package com.mojang.minecraft;
+
+public enum Minecraft$OS
+{
+ linux("linux", 0),
+ solaris("solaris", 1),
+ windows("windows", 2),
+ macos("macos", 3),
+ unknown("unknown", 4);
+
+ private static final Minecraft$OS[] values = new Minecraft$OS[] {linux, solaris, windows, macos, unknown};
+
+ private Minecraft$OS(String name, int id)
+ {
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/Minecraft.java b/src/main/java/com/mojang/minecraft/Minecraft.java
new file mode 100644
index 0000000..6c8dc75
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/Minecraft.java
@@ -0,0 +1,1804 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.gamemode.CreativeGameMode;
+import com.mojang.minecraft.gamemode.GameMode;
+import com.mojang.minecraft.gamemode.SurvivalGameMode;
+import com.mojang.minecraft.gui.*;
+import com.mojang.minecraft.item.Arrow;
+import com.mojang.minecraft.item.Item;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.LevelIO;
+import com.mojang.minecraft.level.generator.LevelGenerator;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.model.HumanoidModel;
+import com.mojang.minecraft.model.ModelManager;
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.net.NetworkManager;
+import com.mojang.minecraft.net.NetworkPlayer;
+import com.mojang.minecraft.net.PacketType;
+import com.mojang.minecraft.particle.Particle;
+import com.mojang.minecraft.particle.ParticleManager;
+import com.mojang.minecraft.particle.WaterDropParticle;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.player.InputHandlerImpl;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.*;
+import com.mojang.minecraft.render.Renderer;
+import com.mojang.minecraft.render.texture.TextureFX;
+import com.mojang.minecraft.render.texture.TextureLavaFX;
+import com.mojang.minecraft.render.texture.TextureWaterFX;
+import com.mojang.minecraft.sound.SoundManager;
+import com.mojang.minecraft.sound.SoundPlayer;
+import com.mojang.net.NetworkHandler;
+import com.mojang.util.MathHelper;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Controllers;
+import org.lwjgl.input.Cursor;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLU;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.swing.*;
+import java.awt.*;
+import java.io.*;
+import java.nio.IntBuffer;
+import java.util.Collections;
+import java.util.List;
+
+public final class Minecraft implements Runnable {
+
+ public GameMode gamemode = new SurvivalGameMode(this);
+ private boolean fullscreen = false;
+ public int width;
+ public int height;
+ private Timer timer = new Timer(20.0F);
+ public Level level;
+ public LevelRenderer levelRenderer;
+ public Player player;
+ public ParticleManager particleManager;
+ public SessionData session = null;
+ public String host;
+ public Canvas canvas;
+ public boolean levelLoaded = false;
+ public volatile boolean waiting = false;
+ private Cursor cursor;
+ public TextureManager textureManager;
+ public FontRenderer fontRenderer;
+ public GuiScreen currentScreen = null;
+ public ProgressBarDisplay progressBar = new ProgressBarDisplay(this);
+ public Renderer renderer = new Renderer(this);
+ public LevelIO levelIo;
+ public SoundManager sound;
+ private ResourceDownloadThread resourceThread;
+ private int ticks;
+ private int blockHitTime;
+ public String levelName;
+ public int levelId;
+ public Robot robot;
+ public HUDScreen hud;
+ public boolean online;
+ public NetworkManager networkManager;
+ public SoundPlayer soundPlayer;
+ public MovingObjectPosition selected;
+ public static GameSettings settings;
+ private MinecraftApplet applet;
+ String server;
+ int port;
+ volatile boolean running;
+ public String debug;
+ public boolean hasMouse;
+ private int lastClick;
+ public boolean raining;
+
+
+ public Minecraft(Canvas var1, MinecraftApplet var2, int var3, int var4, boolean var5) {
+ this.levelIo = new LevelIO(this.progressBar);
+ this.sound = new SoundManager();
+ this.ticks = 0;
+ this.blockHitTime = 0;
+ this.levelName = null;
+ this.levelId = 0;
+ this.online = false;
+ new HumanoidModel(0.0F);
+ this.selected = null;
+ this.server = null;
+ this.port = 0;
+ this.running = false;
+ this.debug = "";
+ this.hasMouse = false;
+ this.lastClick = 0;
+ this.raining = false;
+
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception var7) {
+ var7.printStackTrace();
+ }
+
+ this.applet = var2;
+ new SleepForeverThread(this);
+ this.canvas = var1;
+ this.width = var3;
+ this.height = var4;
+ this.fullscreen = var5;
+ if(var1 != null) {
+ try {
+ this.robot = new Robot();
+ return;
+ } catch (AWTException var8) {
+ var8.printStackTrace();
+ }
+ }
+
+ }
+
+ public final void setCurrentScreen(GuiScreen var1) {
+ if(!(this.currentScreen instanceof ErrorScreen)) {
+ if(this.currentScreen != null) {
+ this.currentScreen.onClose();
+ }
+
+ if(var1 == null && this.player.health <= 0) {
+ var1 = new GameOverScreen();
+ }
+
+ this.currentScreen = (GuiScreen)var1;
+ if(var1 != null) {
+ if(this.hasMouse) {
+ this.player.releaseAllKeys();
+ this.hasMouse = false;
+ if(this.levelLoaded) {
+ try {
+ Mouse.setNativeCursor((Cursor)null);
+ } catch (LWJGLException var4) {
+ var4.printStackTrace();
+ }
+ } else {
+ Mouse.setGrabbed(false);
+ }
+ }
+
+ int var2 = this.width * 240 / this.height;
+ int var3 = this.height * 240 / this.height;
+ ((GuiScreen)var1).open(this, var2, var3);
+ this.online = false;
+ } else {
+ this.grabMouse();
+ }
+ }
+ }
+
+ private static void checkGLError(String var0) {
+ int var1;
+ if((var1 = GL11.glGetError()) != 0) {
+ String var2 = GLU.gluErrorString(var1);
+ System.out.println("########## GL ERROR ##########");
+ System.out.println("@ " + var0);
+ System.out.println(var1 + ": " + var2);
+ System.exit(0);
+ }
+
+ }
+
+ public final void shutdown() {
+ try {
+ if(this.soundPlayer != null) {
+ SoundPlayer var1 = this.soundPlayer;
+ this.soundPlayer.running = false;
+ }
+
+ if(this.resourceThread != null) {
+ ResourceDownloadThread var4 = this.resourceThread;
+ this.resourceThread.running = true;
+ }
+ } catch (Exception var3) {
+ ;
+ }
+
+ Minecraft var5 = this;
+ if(!this.levelLoaded) {
+ try {
+ LevelIO.save(var5.level, (OutputStream)(new FileOutputStream(new File("level.dat"))));
+ } catch (Exception var2) {
+ var2.printStackTrace();
+ }
+ }
+
+ Mouse.destroy();
+ Keyboard.destroy();
+ Display.destroy();
+ }
+
+ public final void run() {
+ this.running = true;
+
+ try {
+ Minecraft var1 = this;
+ if(this.canvas != null) {
+ Display.setParent(this.canvas);
+ } else if(this.fullscreen) {
+ Display.setFullscreen(true);
+ this.width = Display.getDisplayMode().getWidth();
+ this.height = Display.getDisplayMode().getHeight();
+ } else {
+ Display.setDisplayMode(new DisplayMode(this.width, this.height));
+ }
+
+ Display.setTitle("Minecraft 0.30");
+
+ try {
+ Display.create();
+ } catch (LWJGLException var57) {
+ var57.printStackTrace();
+
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException var56) {
+ ;
+ }
+
+ Display.create();
+ }
+
+ Keyboard.create();
+ Mouse.create();
+
+ try {
+ Controllers.create();
+ } catch (Exception var55) {
+ var55.printStackTrace();
+ }
+
+ checkGLError("Pre startup");
+ GL11.glEnable(3553);
+ GL11.glShadeModel(7425);
+ GL11.glClearDepth(1.0D);
+ GL11.glEnable(2929);
+ GL11.glDepthFunc(515);
+ GL11.glEnable(3008);
+ GL11.glAlphaFunc(516, 0.0F);
+ GL11.glCullFace(1029);
+ GL11.glMatrixMode(5889);
+ GL11.glLoadIdentity();
+ GL11.glMatrixMode(5888);
+ checkGLError("Startup");
+ String var3 = "minecraftclassicforever";
+ String var5 = System.getProperty("user.home", ".");
+ String var6;
+ File var7;
+ switch(OperatingSystemLookup.lookup[((var6 = System.getProperty("os.name").toLowerCase()).contains("win")?Minecraft$OS.windows:(var6.contains("mac")?Minecraft$OS.macos:(var6.contains("solaris")?Minecraft$OS.solaris:(var6.contains("sunos")?Minecraft$OS.solaris:(var6.contains("linux")?Minecraft$OS.linux:(var6.contains("unix")?Minecraft$OS.linux:Minecraft$OS.unknown)))))).ordinal()]) {
+ case 1:
+ case 2:
+ var7 = new File(var5, '.' + var3 + '/');
+ break;
+ case 3:
+ String var8;
+ if((var8 = System.getenv("APPDATA")) != null) {
+ var7 = new File(var8, "." + var3 + '/');
+ } else {
+ var7 = new File(var5, '.' + var3 + '/');
+ }
+ break;
+ case 4:
+ var7 = new File(var5, "Library/Application Support/" + var3);
+ break;
+ default:
+ var7 = new File(var5, var3 + '/');
+ }
+
+ if(!var7.exists() && !var7.mkdirs()) {
+ throw new RuntimeException("The working directory could not be created: " + var7);
+ }
+
+ File var2 = var7;
+ this.settings = new GameSettings(this, var7);
+ this.textureManager = new TextureManager(this.settings);
+ this.textureManager.registerAnimation(new TextureLavaFX());
+ this.textureManager.registerAnimation(new TextureWaterFX());
+ this.fontRenderer = new FontRenderer(this.settings, "/default.png", this.textureManager);
+ IntBuffer var9;
+ (var9 = BufferUtils.createIntBuffer(256)).clear().limit(256);
+ this.levelRenderer = new LevelRenderer(this, this.textureManager);
+ Item.initModels();
+ Mob.modelCache = new ModelManager();
+ GL11.glViewport(0, 0, this.width, this.height);
+ if(this.server != null && this.session != null) {
+ Level var85;
+ (var85 = new Level()).setData(8, 8, 8, new byte[512]);
+ this.setLevel(var85);
+ } else {
+ boolean var10 = false;
+
+ try {
+ if(var1.levelName != null) {
+ var1.loadOnlineLevel(var1.levelName, var1.levelId);
+ } else if(!var1.levelLoaded) {
+ Level var11 = null;
+ if((var11 = var1.levelIo.load((InputStream)(new FileInputStream(new File("level.dat"))))) != null) {
+ var1.setLevel(var11);
+ }
+ }
+ } catch (Exception var54) {
+ var54.printStackTrace();
+ }
+
+ if(this.level == null) {
+ this.generateLevel(1);
+ }
+ }
+
+ this.particleManager = new ParticleManager(this.level, this.textureManager);
+ if(this.levelLoaded) {
+ try {
+ var1.cursor = new Cursor(16, 16, 0, 0, 1, var9, (IntBuffer)null);
+ } catch (LWJGLException var53) {
+ var53.printStackTrace();
+ }
+ }
+
+ try {
+ var1.soundPlayer = new SoundPlayer(var1.settings);
+ SoundPlayer var4 = var1.soundPlayer;
+
+ try {
+ AudioFormat var67 = new AudioFormat(44100.0F, 16, 2, true, true);
+ var4.dataLine = AudioSystem.getSourceDataLine(var67);
+ var4.dataLine.open(var67, 4410);
+ var4.dataLine.start();
+ var4.running = true;
+ Thread var72;
+ (var72 = new Thread(var4)).setDaemon(true);
+ var72.setPriority(10);
+ var72.start();
+ } catch (Exception var51) {
+ var51.printStackTrace();
+ var4.running = false;
+ }
+
+ var1.resourceThread = new ResourceDownloadThread(var2, var1);
+ var1.resourceThread.start();
+ } catch (Exception var52) {
+ ;
+ }
+
+ checkGLError("Post startup");
+ this.hud = new HUDScreen(this, this.width, this.height);
+ (new SkinDownloadThread(this)).start();
+ if(this.server != null && this.session != null) {
+ this.networkManager = new NetworkManager(this, this.server, this.port, this.session.username, this.session.mppass);
+ }
+ } catch (Exception var62) {
+ var62.printStackTrace();
+ JOptionPane.showMessageDialog((Component)null, var62.toString(), "Failed to start Minecraft", 0);
+ return;
+ }
+
+ long var13 = System.currentTimeMillis();
+ int var15 = 0;
+
+ try {
+ while(this.running) {
+ if(this.waiting) {
+ Thread.sleep(100L);
+ } else {
+ if(this.canvas == null && Display.isCloseRequested()) {
+ this.running = false;
+ }
+
+ try {
+ Timer var63 = this.timer;
+ long var16;
+ long var18 = (var16 = System.currentTimeMillis()) - var63.lastSysClock;
+ long var20 = System.nanoTime() / 1000000L;
+ double var24;
+ if(var18 > 1000L) {
+ long var22 = var20 - var63.lastHRClock;
+ var24 = (double)var18 / (double)var22;
+ var63.adjustment += (var24 - var63.adjustment) * 0.20000000298023224D;
+ var63.lastSysClock = var16;
+ var63.lastHRClock = var20;
+ }
+
+ if(var18 < 0L) {
+ var63.lastSysClock = var16;
+ var63.lastHRClock = var20;
+ }
+
+ double var95;
+ var24 = ((var95 = (double)var20 / 1000.0D) - var63.lastHR) * var63.adjustment;
+ var63.lastHR = var95;
+ if(var24 < 0.0D) {
+ var24 = 0.0D;
+ }
+
+ if(var24 > 1.0D) {
+ var24 = 1.0D;
+ }
+
+ var63.elapsedDelta = (float)((double)var63.elapsedDelta + var24 * (double)var63.speed * (double)var63.tps);
+ var63.elapsedTicks = (int)var63.elapsedDelta;
+ if(var63.elapsedTicks > 100) {
+ var63.elapsedTicks = 100;
+ }
+
+ var63.elapsedDelta -= (float)var63.elapsedTicks;
+ var63.delta = var63.elapsedDelta;
+
+ for(int var64 = 0; var64 < this.timer.elapsedTicks; ++var64) {
+ ++this.ticks;
+ this.tick();
+ }
+
+ checkGLError("Pre render");
+ GL11.glEnable(3553);
+ if(!this.online) {
+ this.gamemode.applyCracks(this.timer.delta);
+ float var65 = this.timer.delta;
+ Renderer var66 = this.renderer;
+ if(this.renderer.displayActive && !Display.isActive()) {
+ var66.minecraft.pause();
+ }
+
+ var66.displayActive = Display.isActive();
+ int var68;
+ int var70;
+ int var86;
+ int var81;
+ if(var66.minecraft.hasMouse) {
+ var81 = 0;
+ var86 = 0;
+ if(var66.minecraft.levelLoaded) {
+ if(var66.minecraft.canvas != null) {
+ Point var90;
+ var70 = (var90 = var66.minecraft.canvas.getLocationOnScreen()).x + var66.minecraft.width / 2;
+ var68 = var90.y + var66.minecraft.height / 2;
+ Point var75;
+ var81 = (var75 = MouseInfo.getPointerInfo().getLocation()).x - var70;
+ var86 = -(var75.y - var68);
+ var66.minecraft.robot.mouseMove(var70, var68);
+ } else {
+ Mouse.setCursorPosition(var66.minecraft.width / 2, var66.minecraft.height / 2);
+ }
+ } else {
+ var81 = Mouse.getDX();
+ var86 = Mouse.getDY();
+ }
+
+ byte var91 = 1;
+ if(var66.minecraft.settings.invertMouse) {
+ var91 = -1;
+ }
+
+ var66.minecraft.player.turn((float)var81, (float)(var86 * var91));
+ }
+
+ if(!var66.minecraft.online) {
+ var81 = var66.minecraft.width * 240 / var66.minecraft.height;
+ var86 = var66.minecraft.height * 240 / var66.minecraft.height;
+ int var94 = Mouse.getX() * var81 / var66.minecraft.width;
+ var70 = var86 - Mouse.getY() * var86 / var66.minecraft.height - 1;
+ if(var66.minecraft.level != null) {
+ float var80 = var65;
+ Renderer var82 = var66;
+ Renderer var27 = var66;
+ Player var28;
+ float var29 = (var28 = var66.minecraft.player).xRotO + (var28.xRot - var28.xRotO) * var65;
+ float var30 = var28.yRotO + (var28.yRot - var28.yRotO) * var65;
+ Vec3D var31 = var66.getPlayerVector(var65);
+ float var32 = MathHelper.cos(-var30 * 0.017453292F - 3.1415927F);
+ float var69 = MathHelper.sin(-var30 * 0.017453292F - 3.1415927F);
+ float var74 = MathHelper.cos(-var29 * 0.017453292F);
+ float var33 = MathHelper.sin(-var29 * 0.017453292F);
+ float var34 = var69 * var74;
+ float var87 = var32 * var74;
+ float var36 = var66.minecraft.gamemode.getReachDistance();
+ Vec3D var71 = var31.add(var34 * var36, var33 * var36, var87 * var36);
+ var66.minecraft.selected = var66.minecraft.level.clip(var31, var71);
+ var74 = var36;
+ if(var66.minecraft.selected != null) {
+ var74 = var66.minecraft.selected.vec.distance(var66.getPlayerVector(var65));
+ }
+
+ var31 = var66.getPlayerVector(var65);
+ if(var66.minecraft.gamemode instanceof CreativeGameMode) {
+ var36 = 32.0F;
+ } else {
+ var36 = var74;
+ }
+
+ var71 = var31.add(var34 * var36, var33 * var36, var87 * var36);
+ var66.entity = null;
+ List var37 = var66.minecraft.level.blockMap.getEntities(var28, var28.bb.expand(var34 * var36, var33 * var36, var87 * var36));
+ float var35 = 0.0F;
+
+ for(var81 = 0; var81 < var37.size(); ++var81) {
+ Entity var88;
+ if((var88 = (Entity)var37.get(var81)).isPickable()) {
+ var74 = 0.1F;
+ MovingObjectPosition var78;
+ if((var78 = var88.bb.grow(var74, var74, var74).clip(var31, var71)) != null && ((var74 = var31.distance(var78.vec)) < var35 || var35 == 0.0F)) {
+ var27.entity = var88;
+ var35 = var74;
+ }
+ }
+ }
+
+ if(var27.entity != null && !(var27.minecraft.gamemode instanceof CreativeGameMode)) {
+ var27.minecraft.selected = new MovingObjectPosition(var27.entity);
+ }
+
+ int var77 = 0;
+
+ while(true) {
+ if(var77 >= 2) {
+ GL11.glColorMask(true, true, true, false);
+ break;
+ }
+
+ if(var82.minecraft.settings.anaglyph) {
+ if(var77 == 0) {
+ GL11.glColorMask(false, true, true, false);
+ } else {
+ GL11.glColorMask(true, false, false, false);
+ }
+ }
+
+ Player var126 = var82.minecraft.player;
+ Level var119 = var82.minecraft.level;
+ LevelRenderer var89 = var82.minecraft.levelRenderer;
+ ParticleManager var93 = var82.minecraft.particleManager;
+ GL11.glViewport(0, 0, var82.minecraft.width, var82.minecraft.height);
+ Level var26 = var82.minecraft.level;
+ var28 = var82.minecraft.player;
+ var29 = 1.0F / (float)(4 - var82.minecraft.settings.viewDistance);
+ var29 = 1.0F - (float)Math.pow((double)var29, 0.25D);
+ var30 = (float)(var26.skyColor >> 16 & 255) / 255.0F;
+ float var117 = (float)(var26.skyColor >> 8 & 255) / 255.0F;
+ var32 = (float)(var26.skyColor & 255) / 255.0F;
+ var82.fogRed = (float)(var26.fogColor >> 16 & 255) / 255.0F;
+ var82.fogBlue = (float)(var26.fogColor >> 8 & 255) / 255.0F;
+ var82.fogGreen = (float)(var26.fogColor & 255) / 255.0F;
+ var82.fogRed += (var30 - var82.fogRed) * var29;
+ var82.fogBlue += (var117 - var82.fogBlue) * var29;
+ var82.fogGreen += (var32 - var82.fogGreen) * var29;
+ var82.fogRed *= var82.fogColorMultiplier;
+ var82.fogBlue *= var82.fogColorMultiplier;
+ var82.fogGreen *= var82.fogColorMultiplier;
+ Block var73;
+ if((var73 = Block.blocks[var26.getTile((int)var28.x, (int)(var28.y + 0.12F), (int)var28.z)]) != null && var73.getLiquidType() != LiquidType.NOT_LIQUID) {
+ LiquidType var79;
+ if((var79 = var73.getLiquidType()) == LiquidType.WATER) {
+ var82.fogRed = 0.02F;
+ var82.fogBlue = 0.02F;
+ var82.fogGreen = 0.2F;
+ } else if(var79 == LiquidType.LAVA) {
+ var82.fogRed = 0.6F;
+ var82.fogBlue = 0.1F;
+ var82.fogGreen = 0.0F;
+ }
+ }
+
+ if(var82.minecraft.settings.anaglyph) {
+ var74 = (var82.fogRed * 30.0F + var82.fogBlue * 59.0F + var82.fogGreen * 11.0F) / 100.0F;
+ var33 = (var82.fogRed * 30.0F + var82.fogBlue * 70.0F) / 100.0F;
+ var34 = (var82.fogRed * 30.0F + var82.fogGreen * 70.0F) / 100.0F;
+ var82.fogRed = var74;
+ var82.fogBlue = var33;
+ var82.fogGreen = var34;
+ }
+
+ GL11.glClearColor(var82.fogRed, var82.fogBlue, var82.fogGreen, 0.0F);
+ GL11.glClear(16640);
+ var82.fogColorMultiplier = 1.0F;
+ GL11.glEnable(2884);
+ var82.fogEnd = (float)(512 >> (var82.minecraft.settings.viewDistance << 1));
+ GL11.glMatrixMode(5889);
+ GL11.glLoadIdentity();
+ var29 = 0.07F;
+ if(var82.minecraft.settings.anaglyph) {
+ GL11.glTranslatef((float)(-((var77 << 1) - 1)) * var29, 0.0F, 0.0F);
+ }
+
+ Player var116 = var82.minecraft.player;
+ var69 = 70.0F;
+ if(var116.health <= 0) {
+ var74 = (float)var116.deathTime + var80;
+ var69 /= (1.0F - 500.0F / (var74 + 500.0F)) * 2.0F + 1.0F;
+ }
+
+ GLU.gluPerspective(var69, (float)var82.minecraft.width / (float)var82.minecraft.height, 0.05F, var82.fogEnd);
+ GL11.glMatrixMode(5888);
+ GL11.glLoadIdentity();
+ if(var82.minecraft.settings.anaglyph) {
+ GL11.glTranslatef((float)((var77 << 1) - 1) * 0.1F, 0.0F, 0.0F);
+ }
+
+ var82.hurtEffect(var80);
+ if(var82.minecraft.settings.viewBobbing) {
+ var82.applyBobbing(var80);
+ }
+
+ var116 = var82.minecraft.player;
+ GL11.glTranslatef(0.0F, 0.0F, -0.1F);
+ GL11.glRotatef(var116.xRotO + (var116.xRot - var116.xRotO) * var80, 1.0F, 0.0F, 0.0F);
+ GL11.glRotatef(var116.yRotO + (var116.yRot - var116.yRotO) * var80, 0.0F, 1.0F, 0.0F);
+ var69 = var116.xo + (var116.x - var116.xo) * var80;
+ var74 = var116.yo + (var116.y - var116.yo) * var80;
+ var33 = var116.zo + (var116.z - var116.zo) * var80;
+ GL11.glTranslatef(-var69, -var74, -var33);
+ Frustrum var76 = FrustrumImpl.update();
+ Frustrum var100 = var76;
+ LevelRenderer var101 = var82.minecraft.levelRenderer;
+
+ int var98;
+ for(var98 = 0; var98 < var101.chunkCache.length; ++var98) {
+ var101.chunkCache[var98].clip(var100);
+ }
+
+ var101 = var82.minecraft.levelRenderer;
+ Collections.sort(var82.minecraft.levelRenderer.chunks, new ChunkDirtyDistanceComparator(var126));
+ var98 = var101.chunks.size() - 1;
+ int var105;
+ if((var105 = var101.chunks.size()) > 3) {
+ var105 = 3;
+ }
+
+ int var104;
+ for(var104 = 0; var104 < var105; ++var104) {
+ Chunk var118;
+ (var118 = (Chunk)var101.chunks.remove(var98 - var104)).update();
+ var118.loaded = false;
+ }
+
+ var82.updateFog();
+ GL11.glEnable(2912);
+ var89.sortChunks(var126, 0);
+ int var83;
+ int var110;
+ ShapeRenderer var115;
+ int var114;
+ int var125;
+ int var122;
+ int var120;
+ if(var119.isSolid(var126.x, var126.y, var126.z, 0.1F)) {
+ var120 = (int)var126.x;
+ var83 = (int)var126.y;
+ var110 = (int)var126.z;
+
+ for(var122 = var120 - 1; var122 <= var120 + 1; ++var122) {
+ for(var125 = var83 - 1; var125 <= var83 + 1; ++var125) {
+ for(int var38 = var110 - 1; var38 <= var110 + 1; ++var38) {
+ var105 = var38;
+ var98 = var125;
+ int var99 = var122;
+ if((var104 = var89.level.getTile(var122, var125, var38)) != 0 && Block.blocks[var104].isSolid()) {
+ GL11.glColor4f(0.2F, 0.2F, 0.2F, 1.0F);
+ GL11.glDepthFunc(513);
+ var115 = ShapeRenderer.instance;
+ ShapeRenderer.instance.begin();
+
+ for(var114 = 0; var114 < 6; ++var114) {
+ Block.blocks[var104].renderInside(var115, var99, var98, var105, var114);
+ }
+
+ var115.end();
+ GL11.glCullFace(1028);
+ var115.begin();
+
+ for(var114 = 0; var114 < 6; ++var114) {
+ Block.blocks[var104].renderInside(var115, var99, var98, var105, var114);
+ }
+
+ var115.end();
+ GL11.glCullFace(1029);
+ GL11.glDepthFunc(515);
+ }
+ }
+ }
+ }
+ }
+
+ var82.setLighting(true);
+ Vec3D var103 = var82.getPlayerVector(var80);
+ var89.level.blockMap.render(var103, var76, var89.textureManager, var80);
+ var82.setLighting(false);
+ var82.updateFog();
+ float var107 = var80;
+ ParticleManager var96 = var93;
+ var29 = -MathHelper.cos(var126.yRot * 3.1415927F / 180.0F);
+ var117 = -(var30 = -MathHelper.sin(var126.yRot * 3.1415927F / 180.0F)) * MathHelper.sin(var126.xRot * 3.1415927F / 180.0F);
+ var32 = var29 * MathHelper.sin(var126.xRot * 3.1415927F / 180.0F);
+ var69 = MathHelper.cos(var126.xRot * 3.1415927F / 180.0F);
+
+ for(var83 = 0; var83 < 2; ++var83) {
+ if(var96.particles[var83].size() != 0) {
+ var110 = 0;
+ if(var83 == 0) {
+ var110 = var96.textureManager.load("/particles.png");
+ }
+
+ if(var83 == 1) {
+ var110 = var96.textureManager.load("/terrain.png");
+ }
+
+ GL11.glBindTexture(3553, var110);
+ ShapeRenderer var121 = ShapeRenderer.instance;
+ ShapeRenderer.instance.begin();
+
+ for(var120 = 0; var120 < var96.particles[var83].size(); ++var120) {
+ ((Particle)var96.particles[var83].get(var120)).render(var121, var107, var29, var69, var30, var117, var32);
+ }
+
+ var121.end();
+ }
+ }
+
+ GL11.glBindTexture(3553, var89.textureManager.load("/rock.png"));
+ GL11.glEnable(3553);
+ GL11.glCallList(var89.listId);
+ var82.updateFog();
+ var101 = var89;
+ GL11.glBindTexture(3553, var89.textureManager.load("/clouds.png"));
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ var107 = (float)(var89.level.cloudColor >> 16 & 255) / 255.0F;
+ var29 = (float)(var89.level.cloudColor >> 8 & 255) / 255.0F;
+ var30 = (float)(var89.level.cloudColor & 255) / 255.0F;
+ if(var89.minecraft.settings.anaglyph) {
+ var117 = (var107 * 30.0F + var29 * 59.0F + var30 * 11.0F) / 100.0F;
+ var32 = (var107 * 30.0F + var29 * 70.0F) / 100.0F;
+ var69 = (var107 * 30.0F + var30 * 70.0F) / 100.0F;
+ var107 = var117;
+ var29 = var32;
+ var30 = var69;
+ }
+
+ var115 = ShapeRenderer.instance;
+ var74 = 0.0F;
+ var33 = 4.8828125E-4F;
+ var74 = (float)(var89.level.depth + 2);
+ var34 = ((float)var89.ticks + var80) * var33 * 0.03F;
+ var35 = 0.0F;
+ var115.begin();
+ var115.color(var107, var29, var30);
+
+ for(var86 = -2048; var86 < var101.level.width + 2048; var86 += 512) {
+ for(var125 = -2048; var125 < var101.level.height + 2048; var125 += 512) {
+ var115.vertexUV((float)var86, var74, (float)(var125 + 512), (float)var86 * var33 + var34, (float)(var125 + 512) * var33);
+ var115.vertexUV((float)(var86 + 512), var74, (float)(var125 + 512), (float)(var86 + 512) * var33 + var34, (float)(var125 + 512) * var33);
+ var115.vertexUV((float)(var86 + 512), var74, (float)var125, (float)(var86 + 512) * var33 + var34, (float)var125 * var33);
+ var115.vertexUV((float)var86, var74, (float)var125, (float)var86 * var33 + var34, (float)var125 * var33);
+ var115.vertexUV((float)var86, var74, (float)var125, (float)var86 * var33 + var34, (float)var125 * var33);
+ var115.vertexUV((float)(var86 + 512), var74, (float)var125, (float)(var86 + 512) * var33 + var34, (float)var125 * var33);
+ var115.vertexUV((float)(var86 + 512), var74, (float)(var125 + 512), (float)(var86 + 512) * var33 + var34, (float)(var125 + 512) * var33);
+ var115.vertexUV((float)var86, var74, (float)(var125 + 512), (float)var86 * var33 + var34, (float)(var125 + 512) * var33);
+ }
+ }
+
+ var115.end();
+ GL11.glDisable(3553);
+ var115.begin();
+ var34 = (float)(var101.level.skyColor >> 16 & 255) / 255.0F;
+ var35 = (float)(var101.level.skyColor >> 8 & 255) / 255.0F;
+ var87 = (float)(var101.level.skyColor & 255) / 255.0F;
+ if(var101.minecraft.settings.anaglyph) {
+ var36 = (var34 * 30.0F + var35 * 59.0F + var87 * 11.0F) / 100.0F;
+ var69 = (var34 * 30.0F + var35 * 70.0F) / 100.0F;
+ var74 = (var34 * 30.0F + var87 * 70.0F) / 100.0F;
+ var34 = var36;
+ var35 = var69;
+ var87 = var74;
+ }
+
+ var115.color(var34, var35, var87);
+ var74 = (float)(var101.level.depth + 10);
+
+ for(var125 = -2048; var125 < var101.level.width + 2048; var125 += 512) {
+ for(var68 = -2048; var68 < var101.level.height + 2048; var68 += 512) {
+ var115.vertex((float)var125, var74, (float)var68);
+ var115.vertex((float)(var125 + 512), var74, (float)var68);
+ var115.vertex((float)(var125 + 512), var74, (float)(var68 + 512));
+ var115.vertex((float)var125, var74, (float)(var68 + 512));
+ }
+ }
+
+ var115.end();
+ GL11.glEnable(3553);
+ var82.updateFog();
+ int var108;
+ if(var82.minecraft.selected != null) {
+ GL11.glDisable(3008);
+ MovingObjectPosition var10001 = var82.minecraft.selected;
+ var105 = var126.inventory.getSelected();
+ boolean var106 = false;
+ MovingObjectPosition var102 = var10001;
+ var101 = var89;
+ ShapeRenderer var113 = ShapeRenderer.instance;
+ GL11.glEnable(3042);
+ GL11.glEnable(3008);
+ GL11.glBlendFunc(770, 1);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, (MathHelper.sin((float)System.currentTimeMillis() / 100.0F) * 0.2F + 0.4F) * 0.5F);
+ if(var89.cracks > 0.0F) {
+ GL11.glBlendFunc(774, 768);
+ var108 = var89.textureManager.load("/terrain.png");
+ GL11.glBindTexture(3553, var108);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.5F);
+ GL11.glPushMatrix();
+ Block var10000 = (var114 = var89.level.getTile(var102.x, var102.y, var102.z)) > 0?Block.blocks[var114]:null;
+ var73 = var10000;
+ var74 = (var10000.x1 + var73.x2) / 2.0F;
+ var33 = (var73.y1 + var73.y2) / 2.0F;
+ var34 = (var73.z1 + var73.z2) / 2.0F;
+ GL11.glTranslatef((float)var102.x + var74, (float)var102.y + var33, (float)var102.z + var34);
+ var35 = 1.01F;
+ GL11.glScalef(1.01F, var35, var35);
+ GL11.glTranslatef(-((float)var102.x + var74), -((float)var102.y + var33), -((float)var102.z + var34));
+ var113.begin();
+ var113.noColor();
+ GL11.glDepthMask(false);
+ if(var73 == null) {
+ var73 = Block.STONE;
+ }
+
+ for(var86 = 0; var86 < 6; ++var86) {
+ var73.renderSide(var113, var102.x, var102.y, var102.z, var86, 240 + (int)(var101.cracks * 10.0F));
+ }
+
+ var113.end();
+ GL11.glDepthMask(true);
+ GL11.glPopMatrix();
+ }
+
+ GL11.glDisable(3042);
+ GL11.glDisable(3008);
+ var10001 = var82.minecraft.selected;
+ var126.inventory.getSelected();
+ var106 = false;
+ var102 = var10001;
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 771);
+ GL11.glColor4f(0.0F, 0.0F, 0.0F, 0.4F);
+ GL11.glLineWidth(2.0F);
+ GL11.glDisable(3553);
+ GL11.glDepthMask(false);
+ var29 = 0.002F;
+ if((var104 = var89.level.getTile(var102.x, var102.y, var102.z)) > 0) {
+ AABB var111 = Block.blocks[var104].getSelectionBox(var102.x, var102.y, var102.z).grow(var29, var29, var29);
+ GL11.glBegin(3);
+ GL11.glVertex3f(var111.x0, var111.y0, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y0, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y0, var111.z1);
+ GL11.glVertex3f(var111.x0, var111.y0, var111.z1);
+ GL11.glVertex3f(var111.x0, var111.y0, var111.z0);
+ GL11.glEnd();
+ GL11.glBegin(3);
+ GL11.glVertex3f(var111.x0, var111.y1, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y1, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y1, var111.z1);
+ GL11.glVertex3f(var111.x0, var111.y1, var111.z1);
+ GL11.glVertex3f(var111.x0, var111.y1, var111.z0);
+ GL11.glEnd();
+ GL11.glBegin(1);
+ GL11.glVertex3f(var111.x0, var111.y0, var111.z0);
+ GL11.glVertex3f(var111.x0, var111.y1, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y0, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y1, var111.z0);
+ GL11.glVertex3f(var111.x1, var111.y0, var111.z1);
+ GL11.glVertex3f(var111.x1, var111.y1, var111.z1);
+ GL11.glVertex3f(var111.x0, var111.y0, var111.z1);
+ GL11.glVertex3f(var111.x0, var111.y1, var111.z1);
+ GL11.glEnd();
+ }
+
+ GL11.glDepthMask(true);
+ GL11.glEnable(3553);
+ GL11.glDisable(3042);
+ GL11.glEnable(3008);
+ }
+
+ GL11.glBlendFunc(770, 771);
+ var82.updateFog();
+ GL11.glEnable(3553);
+ GL11.glEnable(3042);
+ GL11.glBindTexture(3553, var89.textureManager.load("/water.png"));
+ GL11.glCallList(var89.listId + 1);
+ GL11.glDisable(3042);
+ GL11.glEnable(3042);
+ GL11.glColorMask(false, false, false, false);
+ var120 = var89.sortChunks(var126, 1);
+ GL11.glColorMask(true, true, true, true);
+ if(var82.minecraft.settings.anaglyph) {
+ if(var77 == 0) {
+ GL11.glColorMask(false, true, true, false);
+ } else {
+ GL11.glColorMask(true, false, false, false);
+ }
+ }
+
+ if(var120 > 0) {
+ GL11.glBindTexture(3553, var89.textureManager.load("/terrain.png"));
+ if(settings.ofFastMath) {
+ GL11.glCallLists(var89.buffer_fast);
+ } else {
+ GL11.glCallLists(var89.buffer);
+ }
+ }
+
+ GL11.glDepthMask(true);
+ GL11.glDisable(3042);
+ GL11.glDisable(2912);
+ if(var82.minecraft.raining) {
+ float var97 = var80;
+ var27 = var82;
+ var28 = var82.minecraft.player;
+ Level var109 = var82.minecraft.level;
+ var104 = (int)var28.x;
+ var108 = (int)var28.y;
+ var114 = (int)var28.z;
+ ShapeRenderer var84 = ShapeRenderer.instance;
+ GL11.glDisable(2884);
+ GL11.glNormal3f(0.0F, 1.0F, 0.0F);
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 771);
+ //GL11.glBindTexture(3553, var82.minecraft.textureManager.load("/rain.png"));
+
+ for(var110 = var104 - 5; var110 <= var104 + 5; ++var110) {
+ for(var122 = var114 - 5; var122 <= var114 + 5; ++var122) {
+ var120 = var109.getHighestTile(var110, var122);
+ var86 = var108 - 5;
+ var125 = var108 + 5;
+ if(var86 < var120) {
+ var86 = var120;
+ }
+
+ if(var125 < var120) {
+ var125 = var120;
+ }
+
+ if(var86 != var125) {
+ var74 = ((float)((var27.levelTicks + var110 * 3121 + var122 * 418711) % 32) + var97) / 32.0F;
+ float var124 = (float)var110 + 0.5F - var28.x;
+ var35 = (float)var122 + 0.5F - var28.z;
+ float var92 = MathHelper.sqrt(var124 * var124 + var35 * var35) / (float)5;
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, (1.0F - var92 * var92) * 0.7F);
+ var84.begin();
+ var84.vertexUV((float)var110, (float)var86, (float)var122, 0.0F, (float)var86 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)(var110 + 1), (float)var86, (float)(var122 + 1), 2.0F, (float)var86 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)(var110 + 1), (float)var125, (float)(var122 + 1), 2.0F, (float)var125 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)var110, (float)var125, (float)var122, 0.0F, (float)var125 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)var110, (float)var86, (float)(var122 + 1), 0.0F, (float)var86 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)(var110 + 1), (float)var86, (float)var122, 2.0F, (float)var86 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)(var110 + 1), (float)var125, (float)var122, 2.0F, (float)var125 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.vertexUV((float)var110, (float)var125, (float)(var122 + 1), 0.0F, (float)var125 * 2.0F / 8.0F + var74 * 2.0F);
+ var84.end();
+ }
+ }
+ }
+
+ GL11.glEnable(2884);
+ GL11.glDisable(3042);
+ }
+
+ if(var82.entity != null) {
+ var82.entity.renderHover(var82.minecraft.textureManager, var80);
+ }
+
+ GL11.glClear(256);
+ GL11.glLoadIdentity();
+ if(var82.minecraft.settings.anaglyph) {
+ GL11.glTranslatef((float)((var77 << 1) - 1) * 0.1F, 0.0F, 0.0F);
+ }
+
+ var82.hurtEffect(var80);
+ if(var82.minecraft.settings.viewBobbing) {
+ var82.applyBobbing(var80);
+ }
+
+ HeldBlock var112 = var82.heldBlock;
+ var117 = var82.heldBlock.lastPos + (var112.pos - var112.lastPos) * var80;
+ var116 = var112.minecraft.player;
+ GL11.glPushMatrix();
+ GL11.glRotatef(var116.xRotO + (var116.xRot - var116.xRotO) * var80, 1.0F, 0.0F, 0.0F);
+ GL11.glRotatef(var116.yRotO + (var116.yRot - var116.yRotO) * var80, 0.0F, 1.0F, 0.0F);
+ var112.minecraft.renderer.setLighting(true);
+ GL11.glPopMatrix();
+ GL11.glPushMatrix();
+ var69 = 0.8F;
+ if(var112.moving) {
+ var33 = MathHelper.sin((var74 = ((float)var112.offset + var80) / 7.0F) * 3.1415927F);
+ GL11.glTranslatef(-MathHelper.sin(MathHelper.sqrt(var74) * 3.1415927F) * 0.4F, MathHelper.sin(MathHelper.sqrt(var74) * 3.1415927F * 2.0F) * 0.2F, -var33 * 0.2F);
+ }
+
+ GL11.glTranslatef(0.7F * var69, -0.65F * var69 - (1.0F - var117) * 0.6F, -0.9F * var69);
+ GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
+ GL11.glEnable(2977);
+ if(var112.moving) {
+ var33 = MathHelper.sin((var74 = ((float)var112.offset + var80) / 7.0F) * var74 * 3.1415927F);
+ GL11.glRotatef(MathHelper.sin(MathHelper.sqrt(var74) * 3.1415927F) * 80.0F, 0.0F, 1.0F, 0.0F);
+ GL11.glRotatef(-var33 * 20.0F, 1.0F, 0.0F, 0.0F);
+ }
+
+ GL11.glColor4f(var74 = var112.minecraft.level.getBrightness((int)var116.x, (int)var116.y, (int)var116.z), var74, var74, 1.0F);
+ ShapeRenderer var123 = ShapeRenderer.instance;
+ if(var112.block != null) {
+ var34 = 0.4F;
+ GL11.glScalef(0.4F, var34, var34);
+ GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
+ GL11.glBindTexture(3553, var112.minecraft.textureManager.load("/terrain.png"));
+ var112.block.renderPreview(var123);
+ } else {
+ var116.bindTexture(var112.minecraft.textureManager);
+ GL11.glScalef(1.0F, -1.0F, -1.0F);
+ GL11.glTranslatef(0.0F, 0.2F, 0.0F);
+ GL11.glRotatef(-120.0F, 0.0F, 0.0F, 1.0F);
+ GL11.glScalef(1.0F, 1.0F, 1.0F);
+ var34 = 0.0625F;
+ ModelPart var127;
+ if(!(var127 = var112.minecraft.player.getModel().leftArm).hasList) {
+ var127.generateList(var34);
+ }
+
+ GL11.glCallList(var127.list);
+ }
+
+ GL11.glDisable(2977);
+ GL11.glPopMatrix();
+ var112.minecraft.renderer.setLighting(false);
+ if(!var82.minecraft.settings.anaglyph) {
+ break;
+ }
+
+ ++var77;
+ }
+
+ var66.minecraft.hud.render(var65, var66.minecraft.currentScreen != null, var94, var70);
+ } else {
+ GL11.glViewport(0, 0, var66.minecraft.width, var66.minecraft.height);
+ GL11.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
+ GL11.glClear(16640);
+ GL11.glMatrixMode(5889);
+ GL11.glLoadIdentity();
+ GL11.glMatrixMode(5888);
+ GL11.glLoadIdentity();
+ var66.enableGuiMode();
+ }
+
+ if(var66.minecraft.currentScreen != null) {
+ var66.minecraft.currentScreen.render(var94, var70);
+ }
+
+ Thread.yield();
+ Display.update();
+ }
+ }
+
+ if(this.settings.limitFramerate) {
+ Thread.sleep(5L);
+ }
+
+ checkGLError("Post render");
+ ++var15;
+ } catch (Exception var58) {
+ this.setCurrentScreen(new ErrorScreen("Client error", "The game broke! [" + var58 + "]"));
+ var58.printStackTrace();
+ }
+
+ while(System.currentTimeMillis() >= var13 + 1000L) {
+ this.debug = var15 + " fps, " + Chunk.chunkUpdates + " chunk updates";
+ Chunk.chunkUpdates = 0;
+ var13 += 1000L;
+ var15 = 0;
+ }
+ }
+ }
+
+ return;
+ } catch (StopGameException var59) {
+ ;
+ } catch (Exception var60) {
+ var60.printStackTrace();
+ return;
+ } finally {
+ this.shutdown();
+ }
+
+ }
+
+ public final void grabMouse() {
+ if(!this.hasMouse) {
+ this.hasMouse = true;
+ if(this.levelLoaded) {
+ try {
+ Mouse.setNativeCursor(this.cursor);
+ Mouse.setCursorPosition(this.width / 2, this.height / 2);
+ } catch (LWJGLException var2) {
+ var2.printStackTrace();
+ }
+
+ if(this.canvas == null) {
+ this.canvas.requestFocus();
+ }
+ } else {
+ Mouse.setGrabbed(true);
+ }
+
+ this.setCurrentScreen((GuiScreen)null);
+ this.lastClick = this.ticks + 10000;
+ }
+ }
+
+ public final void pause() {
+ if(this.currentScreen == null) {
+ this.setCurrentScreen(new PauseScreen());
+ }
+ }
+
+ private void onMouseClick(int var1) {
+ if(var1 != 0 || this.blockHitTime <= 0) {
+ HeldBlock var2;
+ if(var1 == 0) {
+ var2 = this.renderer.heldBlock;
+ this.renderer.heldBlock.offset = -1;
+ var2.moving = true;
+ }
+
+ int var3;
+ if(var1 == 1 && (var3 = this.player.inventory.getSelected()) > 0 && this.gamemode.useItem(this.player, var3)) {
+ var2 = this.renderer.heldBlock;
+ this.renderer.heldBlock.pos = 0.0F;
+ } else if(this.selected == null) {
+ if(var1 == 0 && !(this.gamemode instanceof CreativeGameMode)) {
+ this.blockHitTime = 10;
+ }
+
+ } else {
+ if(this.selected.entityPos == 1) {
+ if(var1 == 0) {
+ this.selected.entity.hurt(this.player, 4);
+ return;
+ }
+ } else if(this.selected.entityPos == 0) {
+ var3 = this.selected.x;
+ int var4 = this.selected.y;
+ int var5 = this.selected.z;
+ if(var1 != 0) {
+ if(this.selected.face == 0) {
+ --var4;
+ }
+
+ if(this.selected.face == 1) {
+ ++var4;
+ }
+
+ if(this.selected.face == 2) {
+ --var5;
+ }
+
+ if(this.selected.face == 3) {
+ ++var5;
+ }
+
+ if(this.selected.face == 4) {
+ --var3;
+ }
+
+ if(this.selected.face == 5) {
+ ++var3;
+ }
+ }
+
+ Block var6 = Block.blocks[this.level.getTile(var3, var4, var5)];
+ if(var1 == 0) {
+ if(var6 != Block.BEDROCK || this.player.userType >= 100) {
+ this.gamemode.hitBlock(var3, var4, var5);
+ return;
+ }
+ } else {
+ int var10;
+ if((var10 = this.player.inventory.getSelected()) <= 0) {
+ return;
+ }
+
+ Block var8;
+ AABB var9;
+ if(((var8 = Block.blocks[this.level.getTile(var3, var4, var5)]) == null || var8 == Block.WATER || var8 == Block.STATIONARY_WATER || var8 == Block.LAVA || var8 == Block.STATIONARY_LAVA) && ((var9 = Block.blocks[var10].getCollisionBox(var3, var4, var5)) == null || (this.player.bb.intersects(var9)?false:this.level.isFree(var9)))) {
+ if(!this.gamemode.canPlace(var10)) {
+ return;
+ }
+
+ if(this.isOnline()) {
+ this.networkManager.sendBlockChange(var3, var4, var5, var1, var10);
+ }
+
+ this.level.netSetTile(var3, var4, var5, var10);
+ var2 = this.renderer.heldBlock;
+ this.renderer.heldBlock.pos = 0.0F;
+ Block.blocks[var10].onPlace(this.level, var3, var4, var5);
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ private void tick() {
+ if(this.soundPlayer != null) {
+ SoundPlayer var1 = this.soundPlayer;
+ SoundManager var2 = this.sound;
+ if(System.currentTimeMillis() > var2.lastMusic && var2.playMusic(var1, "calm")) {
+ var2.lastMusic = System.currentTimeMillis() + (long)var2.random.nextInt(900000) + 300000L;
+ }
+ }
+
+ this.gamemode.spawnMob();
+ HUDScreen var17 = this.hud;
+ ++this.hud.ticks;
+
+ int var16;
+ for(var16 = 0; var16 < var17.chat.size(); ++var16) {
+ ++((ChatLine)var17.chat.get(var16)).time;
+ }
+
+ GL11.glBindTexture(3553, this.textureManager.load("/terrain.png"));
+ TextureManager var19 = this.textureManager;
+
+ for(var16 = 0; var16 < var19.animations.size(); ++var16) {
+ TextureFX var3;
+ (var3 = (TextureFX)var19.animations.get(var16)).anaglyph = var19.settings.anaglyph;
+ var3.animate();
+ var19.textureBuffer.clear();
+ var19.textureBuffer.put(var3.textureData);
+ var19.textureBuffer.position(0).limit(var3.textureData.length);
+ GL11.glTexSubImage2D(3553, 0, var3.textureId % 16 << 4, var3.textureId / 16 << 4, 16, 16, 6408, 5121, var19.textureBuffer);
+ }
+
+ int var4;
+ int var8;
+ int var40;
+ int var46;
+ int var45;
+ if(this.networkManager != null && !(this.currentScreen instanceof ErrorScreen)) {
+ if(!this.networkManager.isConnected()) {
+ this.progressBar.setTitle("Connecting..");
+ this.progressBar.setProgress(0);
+ } else {
+ NetworkManager var20 = this.networkManager;
+ if(this.networkManager.successful) {
+ NetworkHandler var18 = var20.netHandler;
+ if(var20.netHandler.connected) {
+ try {
+ NetworkHandler var22 = var20.netHandler;
+ var20.netHandler.channel.read(var22.in);
+ var4 = 0;
+
+ while(var22.in.position() > 0 && var4++ != 100) {
+ var22.in.flip();
+ byte var5 = var22.in.get(0);
+ PacketType var6;
+ if((var6 = PacketType.packets[var5]) == null) {
+ throw new IOException("Bad command: " + var5);
+ }
+
+ if(var22.in.remaining() < var6.length + 1) {
+ var22.in.compact();
+ break;
+ }
+
+ var22.in.get();
+ Object[] var7 = new Object[var6.params.length];
+
+ for(var8 = 0; var8 < var7.length; ++var8) {
+ var7[var8] = var22.readObject(var6.params[var8]);
+ }
+
+ NetworkManager var42 = var22.netManager;
+ if(var22.netManager.successful) {
+ if(var6 == PacketType.IDENTIFICATION) {
+ var42.minecraft.progressBar.setTitle(var7[1].toString());
+ var42.minecraft.progressBar.setText(var7[2].toString());
+ var42.minecraft.player.userType = ((Byte)var7[3]).byteValue();
+ } else if(var6 == PacketType.LEVEL_INIT) {
+ var42.minecraft.setLevel((Level)null);
+ var42.levelData = new ByteArrayOutputStream();
+ } else if(var6 == PacketType.LEVEL_DATA) {
+ short var11 = ((Short)var7[0]).shortValue();
+ byte[] var12 = (byte[])((byte[])var7[1]);
+ byte var13 = ((Byte)var7[2]).byteValue();
+ var42.minecraft.progressBar.setProgress(var13);
+ var42.levelData.write(var12, 0, var11);
+ } else if(var6 == PacketType.LEVEL_FINALIZE) {
+ try {
+ var42.levelData.close();
+ } catch (IOException var14) {
+ var14.printStackTrace();
+ }
+
+ byte[] var51 = LevelIO.decompress(new ByteArrayInputStream(var42.levelData.toByteArray()));
+ var42.levelData = null;
+ short var55 = ((Short)var7[0]).shortValue();
+ short var63 = ((Short)var7[1]).shortValue();
+ short var21 = ((Short)var7[2]).shortValue();
+ Level var30;
+ (var30 = new Level()).setNetworkMode(true);
+ var30.setData(var55, var63, var21, var51);
+ var42.minecraft.setLevel(var30);
+ var42.minecraft.online = false;
+ var42.levelLoaded = true;
+ } else if(var6 == PacketType.BLOCK_CHANGE) {
+ if(var42.minecraft.level != null) {
+ var42.minecraft.level.netSetTile(((Short)var7[0]).shortValue(), ((Short)var7[1]).shortValue(), ((Short)var7[2]).shortValue(), ((Byte)var7[3]).byteValue());
+ }
+ } else {
+ byte var9;
+ String var34;
+ NetworkPlayer var33;
+ short var36;
+ short var10004;
+ byte var10001;
+ short var47;
+ short var10003;
+ if(var6 == PacketType.SPAWN_PLAYER) {
+ var10001 = ((Byte)var7[0]).byteValue();
+ String var10002 = (String)var7[1];
+ var10003 = ((Short)var7[2]).shortValue();
+ var10004 = ((Short)var7[3]).shortValue();
+ short var10005 = ((Short)var7[4]).shortValue();
+ byte var10006 = ((Byte)var7[5]).byteValue();
+ byte var58 = ((Byte)var7[6]).byteValue();
+ var9 = var10006;
+ short var10 = var10005;
+ var47 = var10004;
+ var36 = var10003;
+ var34 = var10002;
+ var5 = var10001;
+ if(var5 >= 0) {
+ var9 = (byte)(var9 + 128);
+ var47 = (short)(var47 - 22);
+ var33 = new NetworkPlayer(var42.minecraft, var5, var34, var36, var47, var10, (float)(var9 * 360) / 256.0F, (float)(var58 * 360) / 256.0F);
+ var42.players.put(Byte.valueOf(var5), var33);
+ var42.minecraft.level.addEntity(var33);
+ } else {
+ var42.minecraft.level.setSpawnPos(var36 / 32, var47 / 32, var10 / 32, (float)(var9 * 320 / 256));
+ var42.minecraft.player.moveTo((float)var36 / 32.0F, (float)var47 / 32.0F, (float)var10 / 32.0F, (float)(var9 * 360) / 256.0F, (float)(var58 * 360) / 256.0F);
+ }
+ } else {
+ byte var53;
+ NetworkPlayer var61;
+ byte var69;
+ if(var6 == PacketType.POSITION_ROTATION) {
+ var10001 = ((Byte)var7[0]).byteValue();
+ short var66 = ((Short)var7[1]).shortValue();
+ var10003 = ((Short)var7[2]).shortValue();
+ var10004 = ((Short)var7[3]).shortValue();
+ var69 = ((Byte)var7[4]).byteValue();
+ var9 = ((Byte)var7[5]).byteValue();
+ var53 = var69;
+ var47 = var10004;
+ var36 = var10003;
+ short var38 = var66;
+ var5 = var10001;
+ if(var5 < 0) {
+ var42.minecraft.player.moveTo((float)var38 / 32.0F, (float)var36 / 32.0F, (float)var47 / 32.0F, (float)(var53 * 360) / 256.0F, (float)(var9 * 360) / 256.0F);
+ } else {
+ var53 = (byte)(var53 + 128);
+ var36 = (short)(var36 - 22);
+ if((var61 = (NetworkPlayer)var42.players.get(Byte.valueOf(var5))) != null) {
+ var61.teleport(var38, var36, var47, (float)(var53 * 360) / 256.0F, (float)(var9 * 360) / 256.0F);
+ }
+ }
+ } else {
+ byte var37;
+ byte var44;
+ byte var49;
+ byte var65;
+ byte var67;
+ if(var6 == PacketType.POSITION_ROTATION_UPDATE) {
+ var10001 = ((Byte)var7[0]).byteValue();
+ var67 = ((Byte)var7[1]).byteValue();
+ var65 = ((Byte)var7[2]).byteValue();
+ byte var64 = ((Byte)var7[3]).byteValue();
+ var69 = ((Byte)var7[4]).byteValue();
+ var9 = ((Byte)var7[5]).byteValue();
+ var53 = var69;
+ var49 = var64;
+ var44 = var65;
+ var37 = var67;
+ var5 = var10001;
+ if(var5 >= 0) {
+ var53 = (byte)(var53 + 128);
+ if((var61 = (NetworkPlayer)var42.players.get(Byte.valueOf(var5))) != null) {
+ var61.queue(var37, var44, var49, (float)(var53 * 360) / 256.0F, (float)(var9 * 360) / 256.0F);
+ }
+ }
+ } else if(var6 == PacketType.ROTATION_UPDATE) {
+ var10001 = ((Byte)var7[0]).byteValue();
+ var67 = ((Byte)var7[1]).byteValue();
+ var44 = ((Byte)var7[2]).byteValue();
+ var37 = var67;
+ var5 = var10001;
+ if(var5 >= 0) {
+ var37 = (byte)(var37 + 128);
+ NetworkPlayer var54;
+ if((var54 = (NetworkPlayer)var42.players.get(Byte.valueOf(var5))) != null) {
+ var54.queue((float)(var37 * 360) / 256.0F, (float)(var44 * 360) / 256.0F);
+ }
+ }
+ } else if(var6 == PacketType.POSITION_UPDATE) {
+ var10001 = ((Byte)var7[0]).byteValue();
+ var67 = ((Byte)var7[1]).byteValue();
+ var65 = ((Byte)var7[2]).byteValue();
+ var49 = ((Byte)var7[3]).byteValue();
+ var44 = var65;
+ var37 = var67;
+ var5 = var10001;
+ NetworkPlayer var59;
+ if(var5 >= 0 && (var59 = (NetworkPlayer)var42.players.get(Byte.valueOf(var5))) != null) {
+ var59.queue(var37, var44, var49);
+ }
+ } else if(var6 == PacketType.DESPAWN_PLAYER) {
+ var5 = ((Byte)var7[0]).byteValue();
+ if(var5 >= 0 && (var33 = (NetworkPlayer)var42.players.remove(Byte.valueOf(var5))) != null) {
+ var33.clear();
+ var42.minecraft.level.removeEntity(var33);
+ }
+ } else if(var6 == PacketType.CHAT_MESSAGE) {
+ var10001 = ((Byte)var7[0]).byteValue();
+ var34 = (String)var7[1];
+ var5 = var10001;
+ if(var5 < 0) {
+ var42.minecraft.hud.addChat("&e" + var34);
+ } else {
+ var42.players.get(Byte.valueOf(var5));
+ var42.minecraft.hud.addChat(var34);
+ }
+ } else if(var6 == PacketType.DISCONNECT) {
+ var42.netHandler.close();
+ var42.minecraft.setCurrentScreen(new ErrorScreen("Connection lost", (String)var7[0]));
+ } else if(var6 == PacketType.UPDATE_PLAYER_TYPE) {
+ var42.minecraft.player.userType = ((Byte)var7[0]).byteValue();
+ }
+ }
+ }
+ }
+ }
+
+ if(!var22.connected) {
+ break;
+ }
+
+ var22.in.compact();
+ }
+
+ if(var22.out.position() > 0) {
+ var22.out.flip();
+ var22.channel.write(var22.out);
+ var22.out.compact();
+ }
+ } catch (Exception var15) {
+ var20.minecraft.setCurrentScreen(new ErrorScreen("Disconnected!", "You\'ve lost connection to the server"));
+ var20.minecraft.online = false;
+ var15.printStackTrace();
+ var20.netHandler.close();
+ var20.minecraft.networkManager = null;
+ }
+ }
+ }
+
+ Player var28 = this.player;
+ var20 = this.networkManager;
+ if(this.networkManager.levelLoaded) {
+ int var24 = (int)(var28.x * 32.0F);
+ var4 = (int)(var28.y * 32.0F);
+ var40 = (int)(var28.z * 32.0F);
+ var46 = (int)(var28.yRot * 256.0F / 360.0F) & 255;
+ var45 = (int)(var28.xRot * 256.0F / 360.0F) & 255;
+ var20.netHandler.send(PacketType.POSITION_ROTATION, new Object[]{Integer.valueOf(-1), Integer.valueOf(var24), Integer.valueOf(var4), Integer.valueOf(var40), Integer.valueOf(var46), Integer.valueOf(var45)});
+ }
+ }
+ }
+
+ if(this.currentScreen == null && this.player != null && this.player.health <= 0) {
+ this.setCurrentScreen((GuiScreen)null);
+ }
+
+ if(this.currentScreen == null || this.currentScreen.grabsMouse) {
+ int var25;
+ while(Mouse.next()) {
+ if((var25 = Mouse.getEventDWheel()) != 0) {
+ this.player.inventory.swapPaint(var25);
+ }
+
+ if(this.currentScreen == null) {
+ if(!this.hasMouse && Mouse.getEventButtonState()) {
+ this.grabMouse();
+ } else {
+ if(Mouse.getEventButton() == 0 && Mouse.getEventButtonState()) {
+ this.onMouseClick(0);
+ this.lastClick = this.ticks;
+ }
+
+ if(Mouse.getEventButton() == 1 && Mouse.getEventButtonState()) {
+ this.onMouseClick(1);
+ this.lastClick = this.ticks;
+ }
+
+ if(Mouse.getEventButton() == 2 && Mouse.getEventButtonState() && this.selected != null) {
+ if((var16 = this.level.getTile(this.selected.x, this.selected.y, this.selected.z)) == Block.GRASS.id) {
+ var16 = Block.DIRT.id;
+ }
+
+ if(var16 == Block.DOUBLE_SLAB.id) {
+ var16 = Block.SLAB.id;
+ }
+
+ if(var16 == Block.BEDROCK.id) {
+ var16 = Block.STONE.id;
+ }
+
+ this.player.inventory.grabTexture(var16, this.gamemode instanceof CreativeGameMode);
+ }
+ }
+ }
+
+ if(this.currentScreen != null) {
+ this.currentScreen.mouseEvent();
+ }
+ }
+
+ if(this.blockHitTime > 0) {
+ --this.blockHitTime;
+ }
+
+ while(Keyboard.next()) {
+ this.player.setKey(Keyboard.getEventKey(), Keyboard.getEventKeyState());
+ if(Keyboard.getEventKeyState()) {
+ if(this.currentScreen != null) {
+ this.currentScreen.keyboardEvent();
+ }
+
+ if(this.currentScreen == null) {
+ if(Keyboard.getEventKey() == 1) {
+ this.pause();
+ }
+
+ if(this.gamemode instanceof CreativeGameMode) {
+ if(Keyboard.getEventKey() == this.settings.loadLocationKey.key) {
+ this.player.resetPos();
+ }
+
+ if(Keyboard.getEventKey() == this.settings.saveLocationKey.key) {
+ this.level.setSpawnPos((int)this.player.x, (int)this.player.y, (int)this.player.z, this.player.yRot);
+ this.player.resetPos();
+ }
+ }
+
+ Keyboard.getEventKey();
+ if(Keyboard.getEventKey() == 63) {
+ this.raining = !this.raining;
+ }
+
+ if(Keyboard.getEventKey() == 15 && this.gamemode instanceof SurvivalGameMode && this.player.arrows > 0) {
+ this.level.addEntity(new Arrow(this.level, this.player, this.player.x, this.player.y, this.player.z, this.player.yRot, this.player.xRot, 1.2F));
+ --this.player.arrows;
+ }
+
+ if(Keyboard.getEventKey() == this.settings.buildKey.key) {
+ this.gamemode.openInventory();
+ }
+
+ if(Keyboard.getEventKey() == this.settings.chatKey.key && this.networkManager != null && this.networkManager.isConnected()) {
+ this.player.releaseAllKeys();
+ this.setCurrentScreen(new ChatInputScreen());
+ }
+ }
+
+ for(var25 = 0; var25 < 9; ++var25) {
+ if(Keyboard.getEventKey() == var25 + 2) {
+ this.player.inventory.selected = var25;
+ }
+ }
+
+ if(Keyboard.getEventKey() == this.settings.toggleFogKey.key) {
+ this.settings.toggleSetting(4, !Keyboard.isKeyDown(42) && !Keyboard.isKeyDown(54)?1:-1);
+ }
+ }
+ }
+
+ if(this.currentScreen == null) {
+ if(Mouse.isButtonDown(0) && (float)(this.ticks - this.lastClick) >= this.timer.tps / 4.0F && this.hasMouse) {
+ this.onMouseClick(0);
+ this.lastClick = this.ticks;
+ }
+
+ if(Mouse.isButtonDown(1) && (float)(this.ticks - this.lastClick) >= this.timer.tps / 4.0F && this.hasMouse) {
+ this.onMouseClick(1);
+ this.lastClick = this.ticks;
+ }
+ }
+
+ boolean var26 = this.currentScreen == null && Mouse.isButtonDown(0) && this.hasMouse;
+ boolean var35 = false;
+ if(!this.gamemode.instantBreak && this.blockHitTime <= 0) {
+ if(var26 && this.selected != null && this.selected.entityPos == 0) {
+ var4 = this.selected.x;
+ var40 = this.selected.y;
+ var46 = this.selected.z;
+ this.gamemode.hitBlock(var4, var40, var46, this.selected.face);
+ } else {
+ this.gamemode.resetHits();
+ }
+ }
+ }
+
+ if(this.currentScreen != null) {
+ this.lastClick = this.ticks + 10000;
+ }
+
+ if(this.currentScreen != null) {
+ this.currentScreen.doInput();
+ if(this.currentScreen != null) {
+ this.currentScreen.tick();
+ }
+ }
+
+ if(this.level != null) {
+ Renderer var29 = this.renderer;
+ ++this.renderer.levelTicks;
+ HeldBlock var41 = var29.heldBlock;
+ var29.heldBlock.lastPos = var41.pos;
+ if(var41.moving) {
+ ++var41.offset;
+ if(var41.offset == 7) {
+ var41.offset = 0;
+ var41.moving = false;
+ }
+ }
+
+ Player var27 = var41.minecraft.player;
+ var4 = var41.minecraft.player.inventory.getSelected();
+ Block var43 = null;
+ if(var4 > 0) {
+ var43 = Block.blocks[var4];
+ }
+
+ float var48 = 0.4F;
+ float var50;
+ if((var50 = (var43 == var41.block?1.0F:0.0F) - var41.pos) < -var48) {
+ var50 = -var48;
+ }
+
+ if(var50 > var48) {
+ var50 = var48;
+ }
+
+ var41.pos += var50;
+ if(var41.pos < 0.1F) {
+ var41.block = var43;
+ }
+
+ if(var29.minecraft.raining) {
+ Renderer var39 = var29;
+ var27 = var29.minecraft.player;
+ Level var32 = var29.minecraft.level;
+ var40 = (int)var27.x;
+ var46 = (int)var27.y;
+ var45 = (int)var27.z;
+
+ for(var8 = 0; var8 < 50; ++var8) {
+ int var60 = var40 + var39.random.nextInt(9) - 4;
+ int var52 = var45 + var39.random.nextInt(9) - 4;
+ int var57;
+ if((var57 = var32.getHighestTile(var60, var52)) <= var46 + 4 && var57 >= var46 - 4) {
+ float var56 = var39.random.nextFloat();
+ float var62 = var39.random.nextFloat();
+ var39.minecraft.particleManager.spawnParticle(new WaterDropParticle(var32, (float)var60 + var56, (float)var57 + 0.1F, (float)var52 + var62));
+ }
+ }
+ }
+
+ LevelRenderer var31 = this.levelRenderer;
+ ++this.levelRenderer.ticks;
+ this.level.tickEntities();
+ if(!this.isOnline()) {
+ this.level.tick();
+ }
+
+ this.particleManager.tick();
+ }
+
+ }
+
+ public final boolean isOnline() {
+ return this.networkManager != null;
+ }
+
+ public final void generateLevel(int var1) {
+ String var2 = this.session != null?this.session.username:"anonymous";
+ Level var4 = (new LevelGenerator(this.progressBar)).generate(var2, 128 << var1, 128 << var1, 64);
+ this.gamemode.prepareLevel(var4);
+ this.setLevel(var4);
+ }
+
+ public final boolean loadOnlineLevel(String var1, int var2) {
+ Level var3;
+ if((var3 = this.levelIo.loadOnline(this.host, var1, var2)) == null) {
+ return false;
+ } else {
+ this.setLevel(var3);
+ return true;
+ }
+ }
+
+ public final void setLevel(Level var1) {
+ if(this.applet == null || !this.applet.getDocumentBase().getHost().equalsIgnoreCase("minecraft.net") && !this.applet.getDocumentBase().getHost().equalsIgnoreCase("www.minecraft.net") || !this.applet.getCodeBase().getHost().equalsIgnoreCase("minecraft.net") && !this.applet.getCodeBase().getHost().equalsIgnoreCase("www.minecraft.net")) {
+ var1 = null;
+ }
+
+ this.level = var1;
+ if(var1 != null) {
+ var1.initTransient();
+ this.gamemode.apply(var1);
+ var1.font = this.fontRenderer;
+ var1.rendererContext$5cd64a7f = this;
+ if(!this.isOnline()) {
+ this.player = (Player)var1.findSubclassOf(Player.class);
+ } else if(this.player != null) {
+ this.player.resetPos();
+ this.gamemode.preparePlayer(this.player);
+ if(var1 != null) {
+ var1.player = this.player;
+ var1.addEntity(this.player);
+ }
+ }
+ }
+
+ if(this.player == null) {
+ this.player = new Player(var1);
+ this.player.resetPos();
+ this.gamemode.preparePlayer(this.player);
+ if(var1 != null) {
+ var1.player = this.player;
+ }
+ }
+
+ if(this.player != null) {
+ this.player.input = new InputHandlerImpl(this.settings);
+ this.gamemode.apply(this.player);
+ }
+
+ if(this.levelRenderer != null) {
+ LevelRenderer var3 = this.levelRenderer;
+ if(this.levelRenderer.level != null) {
+ var3.level.removeListener(var3);
+ }
+
+ var3.level = var1;
+ if(var1 != null) {
+ var1.addListener(var3);
+ var3.refresh();
+ }
+ }
+
+ if(this.particleManager != null) {
+ ParticleManager var5 = this.particleManager;
+ if(var1 != null) {
+ var1.particleEngine = var5;
+ }
+
+ for(int var4 = 0; var4 < 2; ++var4) {
+ var5.particles[var4].clear();
+ }
+ }
+
+ System.gc();
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/MinecraftApplet$1.java b/src/main/java/com/mojang/minecraft/MinecraftApplet$1.java
new file mode 100644
index 0000000..d2ed969
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/MinecraftApplet$1.java
@@ -0,0 +1,32 @@
+package com.mojang.minecraft;
+
+import java.awt.Canvas;
+
+// MinecraftCanvas
+public class MinecraftApplet$1 extends Canvas
+{
+ public MinecraftApplet$1(MinecraftApplet minecraftApplet)
+ {
+ this.applet = minecraftApplet;
+ }
+
+ @Override
+ public synchronized void addNotify()
+ {
+ super.addNotify();
+
+ applet.startGameThread();
+ }
+
+ @Override
+ public synchronized void removeNotify()
+ {
+ applet.stopGameThread();
+
+ super.removeNotify();
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ private MinecraftApplet applet;
+}
diff --git a/src/main/java/com/mojang/minecraft/MinecraftApplet.java b/src/main/java/com/mojang/minecraft/MinecraftApplet.java
new file mode 100644
index 0000000..a835106
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/MinecraftApplet.java
@@ -0,0 +1,115 @@
+package com.mojang.minecraft;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+
+public class MinecraftApplet extends Applet
+{
+ private static final long serialVersionUID = 1L;
+
+ private Canvas canvas;
+ private Minecraft minecraft;
+
+ private Thread thread = null;
+
+ public void init()
+ {
+ canvas = new MinecraftApplet$1(this);
+
+ boolean fullscreen = false;
+
+ if(getParameter("fullscreen") != null)
+ {
+ fullscreen = getParameter("fullscreen").equalsIgnoreCase("true");
+ }
+
+ minecraft = new Minecraft(canvas, this, getWidth(), getHeight(), fullscreen);
+
+ minecraft.host = getDocumentBase().getHost();
+
+ if(getDocumentBase().getPort() > 0)
+ {
+ minecraft.host = minecraft.host + ":" + getDocumentBase().getPort();
+ }
+
+ if(getParameter("username") != null && getParameter("sessionid") != null)
+ {
+ minecraft.session = new SessionData(getParameter("username"), getParameter("sessionid"));
+
+ if(getParameter("mppass") != null)
+ {
+ minecraft.session.mppass = getParameter("mppass");
+ }
+
+ // TODO: Not tested.
+ minecraft.session.haspaid = getParameter("haspaid").equalsIgnoreCase("true");
+ }
+
+ if(getParameter("loadmap_user") != null && getParameter("loadmap_id") != null)
+ {
+ minecraft.levelName = getParameter("loadmap_user");
+ minecraft.levelId = Integer.parseInt(getParameter("loadmap_id"));
+ } else if(getParameter("server") != null && getParameter("port") != null) {
+ String server = getParameter("server");
+ int port = Integer.parseInt(getParameter("port"));
+
+ minecraft.server = server;
+ minecraft.port = port;
+ }
+
+ minecraft.levelLoaded = true;
+
+ setLayout(new BorderLayout());
+
+ add(canvas, "Center");
+
+ canvas.setFocusable(true);
+
+ validate();
+ }
+
+ public void startGameThread()
+ {
+ if(thread == null)
+ {
+ thread = new Thread(minecraft);
+
+ thread.start();
+ }
+ }
+
+ @Override
+ public void start()
+ {
+ minecraft.waiting = false;
+ }
+
+ @Override
+ public void stop()
+ {
+ minecraft.waiting = true;
+ }
+
+ @Override
+ public void destroy()
+ {
+ stopGameThread();
+ }
+
+ public void stopGameThread()
+ {
+ if(thread != null)
+ {
+ minecraft.running = false;
+
+ try {
+ thread.join(1000L);
+ } catch (InterruptedException var3) {
+ minecraft.shutdown();
+ }
+
+ thread = null;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/MovingObjectPosition.java b/src/main/java/com/mojang/minecraft/MovingObjectPosition.java
new file mode 100644
index 0000000..07a3980
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/MovingObjectPosition.java
@@ -0,0 +1,37 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.model.Vec3D;
+
+public class MovingObjectPosition
+{
+ public MovingObjectPosition(int x, int y, int z, int side, Vec3D blockPos)
+ {
+ entityPos = 0;
+
+ this.x = x;
+ this.y = y;
+ this.z = z;
+
+ this.face = side;
+
+ vec = new Vec3D(blockPos.x, blockPos.y, blockPos.z);
+ }
+
+ public MovingObjectPosition(Entity entity)
+ {
+ entityPos = 1;
+ this.entity = entity;
+ }
+
+ public int entityPos;
+
+ public int x;
+ public int y;
+ public int z;
+
+ public int face;
+
+ public Vec3D vec;
+
+ public Entity entity;
+}
diff --git a/src/main/java/com/mojang/minecraft/OperatingSystemLookup.java b/src/main/java/com/mojang/minecraft/OperatingSystemLookup.java
new file mode 100644
index 0000000..fb9071c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/OperatingSystemLookup.java
@@ -0,0 +1,37 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.Minecraft$OS;
+
+// $FF: synthetic class
+final class OperatingSystemLookup {
+
+ // $FF: synthetic field
+ static final int[] lookup = new int[Minecraft$OS.values().length];
+
+
+ static {
+ try {
+ lookup[Minecraft$OS.linux.ordinal()] = 1;
+ } catch (NoSuchFieldError var3) {
+ ;
+ }
+
+ try {
+ lookup[Minecraft$OS.solaris.ordinal()] = 2;
+ } catch (NoSuchFieldError var2) {
+ ;
+ }
+
+ try {
+ lookup[Minecraft$OS.windows.ordinal()] = 3;
+ } catch (NoSuchFieldError var1) {
+ ;
+ }
+
+ try {
+ lookup[Minecraft$OS.macos.ordinal()] = 4;
+ } catch (NoSuchFieldError var0) {
+ ;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/ProgressBarDisplay.java b/src/main/java/com/mojang/minecraft/ProgressBarDisplay.java
new file mode 100644
index 0000000..0d1ca21
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/ProgressBarDisplay.java
@@ -0,0 +1,99 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.StopGameException;
+import com.mojang.minecraft.render.ShapeRenderer;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+
+public final class ProgressBarDisplay {
+
+ private String text = "";
+ private Minecraft minecraft;
+ private String title = "";
+ private long start = System.currentTimeMillis();
+
+
+ public ProgressBarDisplay(Minecraft var1) {
+ this.minecraft = var1;
+ }
+
+ public final void setTitle(String var1) {
+ if(!this.minecraft.running) {
+ throw new StopGameException();
+ } else {
+ this.title = var1;
+ int var3 = this.minecraft.width * 240 / this.minecraft.height;
+ int var2 = this.minecraft.height * 240 / this.minecraft.height;
+ GL11.glClear(256);
+ GL11.glMatrixMode(5889);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0.0D, (double)var3, (double)var2, 0.0D, 100.0D, 300.0D);
+ GL11.glMatrixMode(5888);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0F, 0.0F, -200.0F);
+ }
+ }
+
+ public final void setText(String var1) {
+ if(!this.minecraft.running) {
+ throw new StopGameException();
+ } else {
+ this.text = var1;
+ this.setProgress(-1);
+ }
+ }
+
+ public final void setProgress(int var1) {
+ if(!this.minecraft.running) {
+ throw new StopGameException();
+ } else {
+ long var2;
+ if((var2 = System.currentTimeMillis()) - this.start < 0L || var2 - this.start >= 20L) {
+ this.start = var2;
+ int var4 = this.minecraft.width * 240 / this.minecraft.height;
+ int var5 = this.minecraft.height * 240 / this.minecraft.height;
+ GL11.glClear(16640);
+ ShapeRenderer var6 = ShapeRenderer.instance;
+ int var7 = this.minecraft.textureManager.load("/dirt.png");
+ GL11.glBindTexture(3553, var7);
+ float var10 = 32.0F;
+ var6.begin();
+ var6.color(4210752);
+ var6.vertexUV(0.0F, (float)var5, 0.0F, 0.0F, (float)var5 / var10);
+ var6.vertexUV((float)var4, (float)var5, 0.0F, (float)var4 / var10, (float)var5 / var10);
+ var6.vertexUV((float)var4, 0.0F, 0.0F, (float)var4 / var10, 0.0F);
+ var6.vertexUV(0.0F, 0.0F, 0.0F, 0.0F, 0.0F);
+ var6.end();
+ if(var1 >= 0) {
+ var7 = var4 / 2 - 50;
+ int var8 = var5 / 2 + 16;
+ GL11.glDisable(3553);
+ var6.begin();
+ var6.color(8421504);
+ var6.vertex((float)var7, (float)var8, 0.0F);
+ var6.vertex((float)var7, (float)(var8 + 2), 0.0F);
+ var6.vertex((float)(var7 + 100), (float)(var8 + 2), 0.0F);
+ var6.vertex((float)(var7 + 100), (float)var8, 0.0F);
+ var6.color(8454016);
+ var6.vertex((float)var7, (float)var8, 0.0F);
+ var6.vertex((float)var7, (float)(var8 + 2), 0.0F);
+ var6.vertex((float)(var7 + var1), (float)(var8 + 2), 0.0F);
+ var6.vertex((float)(var7 + var1), (float)var8, 0.0F);
+ var6.end();
+ GL11.glEnable(3553);
+ }
+
+ this.minecraft.fontRenderer.render(this.title, (var4 - this.minecraft.fontRenderer.getWidth(this.title)) / 2, var5 / 2 - 4 - 16, 16777215);
+ this.minecraft.fontRenderer.render(this.text, (var4 - this.minecraft.fontRenderer.getWidth(this.text)) / 2, var5 / 2 - 4 + 8, 16777215);
+ Display.update();
+
+ try {
+ Thread.yield();
+ } catch (Exception var9) {
+ ;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/ResourceDownloadThread.java b/src/main/java/com/mojang/minecraft/ResourceDownloadThread.java
new file mode 100644
index 0000000..f9f18c2
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/ResourceDownloadThread.java
@@ -0,0 +1,244 @@
+package com.mojang.minecraft;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+
+public class ResourceDownloadThread extends Thread
+{
+ public ResourceDownloadThread(File minecraftFolder, Minecraft minecraft)
+ {
+ this.minecraft = minecraft;
+
+ this.setName("Resource download thread");
+ this.setDaemon(true);
+
+ dir = new File(minecraftFolder, "resources/");
+
+ if(!dir.exists() && !dir.mkdirs())
+ {
+ throw new RuntimeException("The working directory could not be created: " + dir);
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ BufferedReader reader = null;
+
+ try {
+ ArrayList list = new ArrayList();
+
+ URL base = new URL("http://dl.dropbox.com/u/40737374/minecraft_resources/");
+ URL url = new URL(base, "resources/");
+
+ URLConnection con = url.openConnection();
+
+ con.setConnectTimeout(20000);
+
+ reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
+
+ String line = null;
+
+ while((line = reader.readLine()) != null)
+ {
+ list.add(line);
+ }
+
+ reader.close();
+
+ /*for(String s : list)
+ {
+ try {
+ String split[] = s.split(",");
+ int size = Integer.parseInt(split[1]);
+ File file = new File(dir, split[0]);
+
+ if(!file.exists() || file.length() != size)
+ {
+ try {
+ file.getParentFile().mkdirs();
+ } catch(SecurityException e) {
+ e.printStackTrace();
+ }
+
+ URL url1 = new URL(base, split[0].replaceAll(" ", "%20"));
+
+ download(url1, file, size);
+ } else {
+ int index = split[0].indexOf("/");
+
+ if(split[0].substring(0, index).equalsIgnoreCase("sound"))
+ {
+ minecraft.sound.registerSound(file, split[0].substring(index + 1, split[0].length() - 4).replaceAll("[1-9]", "").replaceAll("/", "."));
+ //this.mc.audio.registerSound(split[0].substring(index + 1, split[0].length() - 4).replaceAll("[1-9]", "").replaceAll("/", "."), file.toURI().toURL(), true);
+ } else if (split[0].substring(0, index).equalsIgnoreCase("music")) {
+ if(split[0].contains("sweden"))
+ {
+ //this.mc.audio.registerMusic("menu", file.toURI().toURL(), true);
+ }
+
+ //this.mc.audio.registerMusic("bg", file.toURI().toURL(), true);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (!this.running) return;
+ }*/
+
+ for(String s : list)
+ {
+ String split[] = s.split(",");
+ int size = Integer.parseInt(split[1]);
+ File file = new File(dir, split[0]);
+
+ File musicFolder = new File(dir, "music");
+
+ if(!file.exists() || file.length() != size)
+ {
+ try {
+ file.getParentFile().mkdirs();
+ } catch(SecurityException e) {
+ e.printStackTrace();
+ }
+
+ URL url1 = new URL(base, split[0].replaceAll(" ", "%20"));
+
+ if(file.getPath().contains("music"))
+ {
+ if(file.getName().equals("minecraft.ogg") && !new File(musicFolder, "calm1.ogg").exists())
+ {
+ download(url1, file, size);
+ } else if(file.getName().equals("clark.ogg") && !new File(musicFolder, "calm2.ogg").exists()) {
+ download(url1, file, size);
+ } else if(file.getName().equals("sweden.ogg") && !new File(musicFolder, "calm3.ogg").exists()) {
+ download(url1, file, size);
+ }
+ } else {
+ download(url1, file, size);
+ }
+ }
+
+ File minecraftOGG = new File(musicFolder, "minecraft.ogg");
+ File clarkOGG = new File(musicFolder, "clark.ogg");
+ File swedenOGG = new File(musicFolder, "sweden.ogg");
+
+ minecraftOGG.renameTo(new File(musicFolder, "calm1.ogg"));
+ clarkOGG.renameTo(new File(musicFolder, "calm2.ogg"));
+ swedenOGG.renameTo(new File(musicFolder, "calm3.ogg"));
+ }
+
+ File soundsFolder = new File(dir, "sound");
+ File stepsFolder = new File(soundsFolder, "step");
+
+ for(int i = 1; i <= 4; i++)
+ {
+ minecraft.sound.registerSound(new File(stepsFolder, "grass" + i + ".ogg"), "step/grass" + i + ".ogg");
+ minecraft.sound.registerSound(new File(stepsFolder, "gravel" + i + ".ogg"), "step/gravel" + i + ".ogg");
+ minecraft.sound.registerSound(new File(stepsFolder, "stone" + i + ".ogg"), "step/stone" + i + ".ogg");
+ minecraft.sound.registerSound(new File(stepsFolder, "wood" + i + ".ogg"), "step/wood" + i + ".ogg");
+ }
+
+ File musicFolder = new File(dir, "music");
+
+ for(int i = 1; i <= 3; i++)
+ {
+ minecraft.sound.registerMusic("calm" + i + ".ogg", new File(musicFolder, "calm" + i + ".ogg"));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (reader != null)
+ reader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ this.finished = true;
+ }
+
+ private File dir;
+ private Minecraft minecraft;
+ boolean running = false;
+
+ private boolean finished = false;
+ private int progress = 0;
+
+ private void download(URL url, File file, int size)
+ {
+ System.out.println("Downloading: " + file.getName() + "...");
+
+ //minecraft.progressBar.setText(file.getName());
+
+ DataInputStream in = null;
+ DataOutputStream out = null;
+
+ try
+ {
+ byte[] data = new byte[4096];
+
+ in = new DataInputStream(url.openStream());
+ FileOutputStream fos = new FileOutputStream(file);
+ out = new DataOutputStream(fos);
+
+ int done = 0;
+
+ do
+ {
+ int length = in.read(data);
+
+ if(length < 0)
+ {
+ in.close();
+ out.close();
+
+ return;
+ }
+
+ out.write(data, 0, length);
+
+ done += length;
+ progress = (int)(((double)done / (double)size) * 100);
+ } while(!running);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try
+ {
+ if(in != null)
+ {
+ in.close();
+ }
+
+ if(out != null)
+ {
+ out.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ //minecraft.progressBar.setText("");
+ progress = 0;
+
+ System.out.println("Downloaded: " + file.getName());
+ }
+
+ public boolean isFinished()
+ {
+ return finished;
+ }
+
+ public int getProgress()
+ {
+ return progress;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/SessionData.java b/src/main/java/com/mojang/minecraft/SessionData.java
new file mode 100644
index 0000000..fa354c2
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/SessionData.java
@@ -0,0 +1,66 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.level.tile.Block;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class SessionData {
+
+ public static List allowedBlocks;
+ public String username;
+ public String sessionId;
+ public String mppass;
+ public boolean haspaid;
+
+
+ public SessionData(String var1, String var2) {
+ this.username = var1;
+ this.sessionId = var2;
+ }
+
+ static {
+ (allowedBlocks = new ArrayList()).add(Block.STONE);
+ allowedBlocks.add(Block.COBBLESTONE);
+ allowedBlocks.add(Block.BRICK);
+ allowedBlocks.add(Block.DIRT);
+ allowedBlocks.add(Block.WOOD);
+ allowedBlocks.add(Block.LOG);
+ allowedBlocks.add(Block.LEAVES);
+ allowedBlocks.add(Block.GLASS);
+ allowedBlocks.add(Block.SLAB);
+ allowedBlocks.add(Block.MOSSY_COBBLESTONE);
+ allowedBlocks.add(Block.SAPLING);
+ allowedBlocks.add(Block.DANDELION);
+ allowedBlocks.add(Block.ROSE);
+ allowedBlocks.add(Block.BROWN_MUSHROOM);
+ allowedBlocks.add(Block.RED_MUSHROOM);
+ allowedBlocks.add(Block.SAND);
+ allowedBlocks.add(Block.GRAVEL);
+ allowedBlocks.add(Block.SPONGE);
+ allowedBlocks.add(Block.RED_WOOL);
+ allowedBlocks.add(Block.ORANGE_WOOL);
+ allowedBlocks.add(Block.YELLOW_WOOL);
+ allowedBlocks.add(Block.LIME_WOOL);
+ allowedBlocks.add(Block.GREEN_WOOL);
+ allowedBlocks.add(Block.AQUA_GREEN_WOOL);
+ allowedBlocks.add(Block.CYAN_WOOL);
+ allowedBlocks.add(Block.BLUE_WOOL);
+ allowedBlocks.add(Block.PURPLE_WOOL);
+ allowedBlocks.add(Block.INDIGO_WOOL);
+ allowedBlocks.add(Block.VIOLET_WOOL);
+ allowedBlocks.add(Block.MAGENTA_WOOL);
+ allowedBlocks.add(Block.PINK_WOOL);
+ allowedBlocks.add(Block.BLACK_WOOL);
+ allowedBlocks.add(Block.GRAY_WOOL);
+ allowedBlocks.add(Block.WHITE_WOOL);
+ allowedBlocks.add(Block.COAL_ORE);
+ allowedBlocks.add(Block.IRON_ORE);
+ allowedBlocks.add(Block.GOLD_ORE);
+ allowedBlocks.add(Block.IRON_BLOCK);
+ allowedBlocks.add(Block.GOLD_BLOCK);
+ allowedBlocks.add(Block.BOOKSHELF);
+ allowedBlocks.add(Block.TNT);
+ allowedBlocks.add(Block.OBSIDIAN);
+ allowedBlocks.add(Block.BEDROCK);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/SkinDownloadThread.java b/src/main/java/com/mojang/minecraft/SkinDownloadThread.java
new file mode 100644
index 0000000..5e85d64
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/SkinDownloadThread.java
@@ -0,0 +1,51 @@
+package com.mojang.minecraft;
+
+import com.mojang.minecraft.player.Player;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import javax.imageio.ImageIO;
+
+public class SkinDownloadThread extends Thread
+{
+ public SkinDownloadThread(Minecraft minecraft)
+ {
+ super();
+
+ this.minecraft = minecraft;
+ }
+
+ @Override
+ public void run()
+ {
+ if(minecraft.session != null)
+ {
+ HttpURLConnection connection = null;
+
+ try {
+ connection = (HttpURLConnection)new URL("http://www.minecraft.net/skin/" + minecraft.session.username + ".png").openConnection();
+
+ connection.setDoInput(true);
+ connection.setDoOutput(false);
+
+ connection.connect();
+
+ if(connection.getResponseCode() != 404)
+ {
+ Player.newTexture = ImageIO.read(connection.getInputStream());
+
+ return;
+ }
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ } finally {
+ if(connection != null)
+ {
+ connection.disconnect();
+ }
+ }
+
+ }
+ }
+
+ private Minecraft minecraft;
+}
diff --git a/src/main/java/com/mojang/minecraft/SleepForeverThread.java b/src/main/java/com/mojang/minecraft/SleepForeverThread.java
new file mode 100644
index 0000000..d64606b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/SleepForeverThread.java
@@ -0,0 +1,27 @@
+package com.mojang.minecraft;
+
+public class SleepForeverThread extends Thread
+{
+ public SleepForeverThread(Minecraft minecraft)
+ {
+ setDaemon(true);
+
+ start();
+ }
+
+ @Override
+ public void run()
+ {
+ while(true)
+ {
+ try {
+ while(true)
+ {
+ Thread.sleep(2147483647L);
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/StopGameException.java b/src/main/java/com/mojang/minecraft/StopGameException.java
new file mode 100644
index 0000000..19f8a52
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/StopGameException.java
@@ -0,0 +1,6 @@
+package com.mojang.minecraft;
+
+public class StopGameException extends Error
+{
+ private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/com/mojang/minecraft/Timer.java b/src/main/java/com/mojang/minecraft/Timer.java
new file mode 100644
index 0000000..ab2bbe5
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/Timer.java
@@ -0,0 +1,21 @@
+package com.mojang.minecraft;
+
+public class Timer
+{
+ public Timer(float tps)
+ {
+ this.tps = tps;
+ lastSysClock = System.currentTimeMillis();
+ lastHRClock = System.nanoTime() / 1000000L;
+ }
+
+ float tps;
+ double lastHR;
+ public int elapsedTicks;
+ public float delta;
+ public float speed = 1.0F;
+ public float elapsedDelta = 0.0F;
+ long lastSysClock;
+ long lastHRClock;
+ double adjustment = 1.0D;
+}
diff --git a/src/main/java/com/mojang/minecraft/gamemode/CreativeGameMode.java b/src/main/java/com/mojang/minecraft/gamemode/CreativeGameMode.java
new file mode 100644
index 0000000..33361bd
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gamemode/CreativeGameMode.java
@@ -0,0 +1,58 @@
+package com.mojang.minecraft.gamemode;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.SessionData;
+import com.mojang.minecraft.gui.BlockSelectScreen;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.player.Player;
+
+public class CreativeGameMode extends GameMode
+{
+ public CreativeGameMode(Minecraft minecraft)
+ {
+ super(minecraft);
+
+ instantBreak = true;
+ }
+
+ @Override
+ public void apply(Level level)
+ {
+ super.apply(level);
+
+ level.removeAllNonCreativeModeEntities();
+
+ level.creativeMode = true;
+ level.growTrees = false;
+ }
+
+ @Override
+ public void openInventory()
+ {
+ BlockSelectScreen blockSelectScreen = new BlockSelectScreen();
+
+ minecraft.setCurrentScreen(blockSelectScreen);
+ }
+
+ @Override
+ public boolean isSurvival()
+ {
+ return false;
+ }
+
+ @Override
+ public void apply(Player player)
+ {
+ for(int slot = 0; slot < 9; slot++)
+ {
+ player.inventory.count[slot] = 1;
+
+ if(player.inventory.slots[slot] <= 0)
+ {
+ player.inventory.slots[slot] = ((Block)SessionData.allowedBlocks.get(slot)).id;
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gamemode/GameMode.java b/src/main/java/com/mojang/minecraft/gamemode/GameMode.java
new file mode 100644
index 0000000..c823ca4
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gamemode/GameMode.java
@@ -0,0 +1,108 @@
+package com.mojang.minecraft.gamemode;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.level.tile.Tile$SoundType;
+import com.mojang.minecraft.player.Player;
+
+public class GameMode
+{
+ public GameMode(Minecraft minecraft)
+ {
+ this.minecraft = minecraft;
+
+ instantBreak = false;
+ }
+
+ public Minecraft minecraft;
+
+ public boolean instantBreak;
+
+ public void apply(Level level)
+ {
+ level.creativeMode = false;
+ level.growTrees = true;
+ }
+
+ public void openInventory()
+ {
+ }
+
+ public void hitBlock(int x, int y, int z)
+ {
+ this.breakBlock(x, y, z);
+ }
+
+ public boolean canPlace(int block)
+ {
+ return true;
+ }
+
+ public void breakBlock(int x, int y, int z)
+ {
+ Level level = minecraft.level;
+ Block block = Block.blocks[level.getTile(x, y, z)];
+
+ boolean success = level.netSetTile(x, y, z, 0);
+
+ if(block != null && success)
+ {
+ if(minecraft.isOnline())
+ {
+ minecraft.networkManager.sendBlockChange(x, y, z, 0, minecraft.player.inventory.getSelected());
+ }
+
+ if(block.stepsound != Tile$SoundType.none)
+ {
+ level.playSound("step." + block.stepsound.name, (float)x, (float)y, (float)z, (block.stepsound.getVolume() + 1.0F) / 2.0F, block.stepsound.getPitch() * 0.8F);
+ }
+
+ block.spawnBreakParticles(level, x, y, z, minecraft.particleManager);
+ }
+
+ }
+
+ public void hitBlock(int x, int y, int z, int side)
+ {
+ }
+
+ public void resetHits()
+ {
+ }
+
+ public void applyCracks(float time)
+ {
+ }
+
+ public float getReachDistance()
+ {
+ return 5.0F;
+ }
+
+ public boolean useItem(Player player, int type)
+ {
+ return false;
+ }
+
+ public void preparePlayer(Player player)
+ {
+ }
+
+ public void spawnMob()
+ {
+ }
+
+ public void prepareLevel(Level level)
+ {
+ }
+
+ public boolean isSurvival()
+ {
+ return true;
+ }
+
+ public void apply(Player player)
+ {
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gamemode/SurvivalGameMode.java b/src/main/java/com/mojang/minecraft/gamemode/SurvivalGameMode.java
new file mode 100644
index 0000000..6c055f0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gamemode/SurvivalGameMode.java
@@ -0,0 +1,174 @@
+package com.mojang.minecraft.gamemode;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.MobSpawner;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.player.Player;
+
+public final class SurvivalGameMode extends GameMode
+{
+ public SurvivalGameMode(Minecraft minecraft)
+ {
+ super(minecraft);
+ }
+
+ private int hitX;
+ private int hitY;
+ private int hitZ;
+ private int hits;
+ private int hardness;
+ private int hitDelay;
+ private MobSpawner spawner;
+
+ @Override
+ public void apply(Level level)
+ {
+ super.apply(level);
+
+ spawner = new MobSpawner(level);
+ }
+
+ @Override
+ public void hitBlock(int x, int y, int z, int side)
+ {
+ if(hitDelay > 0)
+ {
+ hitDelay--;
+ } else if(x == hitX && y == hitY && z == hitZ) {
+ int type = minecraft.level.getTile(x, y, z);
+
+ if(type != 0)
+ {
+ Block block = Block.blocks[type];
+
+ hardness = block.getHardness();
+
+ block.spawnBlockParticles(minecraft.level, x, y, z, side, minecraft.particleManager);
+
+ hits++;
+
+ if(hits == hardness + 1)
+ {
+ breakBlock(x, y, z);
+
+ hits = 0;
+ hitDelay = 5;
+ }
+
+ }
+ } else {
+ // TODO: I think if I don't set hits to 0 you can continue breaking from where you left off.
+
+ hits = 0;
+ hitX = x;
+ hitY = y;
+ hitZ = z;
+ }
+ }
+
+ @Override
+ public boolean canPlace(int block)
+ {
+ return minecraft.player.inventory.removeResource(block);
+ }
+
+ @Override
+ public void breakBlock(int x, int y, int z)
+ {
+ int block = minecraft.level.getTile(x, y, z);
+ Block.blocks[block].onBreak(minecraft.level, x, y, z);
+
+ super.breakBlock(x, y, z);
+ }
+
+ @Override
+ public void hitBlock(int x, int y, int z)
+ {
+ int block = this.minecraft.level.getTile(x, y, z);
+
+ if(block > 0 && Block.blocks[block].getHardness() == 0)
+ {
+ breakBlock(x, y, z);
+ }
+ }
+
+ @Override
+ public void resetHits()
+ {
+ this.hits = 0;
+ this.hitDelay = 0;
+ }
+
+ @Override
+ public void applyCracks(float time)
+ {
+ if(hits <= 0)
+ {
+ minecraft.levelRenderer.cracks = 0.0F;
+ } else {
+ minecraft.levelRenderer.cracks = ((float)hits + time - 1.0F) / (float)hardness;
+ }
+ }
+
+ @Override
+ public float getReachDistance()
+ {
+ return 4.0F;
+ }
+
+ @Override
+ public boolean useItem(Player player, int type)
+ {
+ Block block = Block.blocks[type];
+ if(block == Block.RED_MUSHROOM && minecraft.player.inventory.removeResource(type))
+ {
+ player.hurt(null, 3);
+
+ return true;
+ } else if(block == Block.BROWN_MUSHROOM && minecraft.player.inventory.removeResource(type)) {
+ player.heal(5);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void preparePlayer(Player player)
+ {
+ player.inventory.slots[8] = Block.TNT.id;
+ player.inventory.count[8] = (int) 1e+5;
+ }
+
+ @Override
+ public void spawnMob()
+ {
+ int area = spawner.level.width * spawner.level.height * spawner.level.depth / 64 / 64 / 64;
+
+ if(spawner.level.random.nextInt(100) < area && spawner.level.countInstanceOf(Mob.class) < area * 20)
+ {
+ spawner.spawn(area, spawner.level.player, null);
+ }
+
+ }
+
+ @Override
+ public void prepareLevel(Level level)
+ {
+ spawner = new MobSpawner(level);
+
+ minecraft.progressBar.setText("Spawning..");
+
+ int area = level.width * level.height * level.depth / 800;
+
+ spawner.spawn(area, null, minecraft.progressBar);
+ }
+
+ @Override
+ public void apply(Player player) {
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/BlockSelectScreen.java b/src/main/java/com/mojang/minecraft/gui/BlockSelectScreen.java
new file mode 100644
index 0000000..34fa93d
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/BlockSelectScreen.java
@@ -0,0 +1,74 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.SessionData;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.minecraft.render.TextureManager;
+import org.lwjgl.opengl.GL11;
+
+public final class BlockSelectScreen extends GuiScreen {
+
+ public BlockSelectScreen() {
+ this.grabsMouse = true;
+ }
+
+ private int getBlockOnScreen(int var1, int var2) {
+ for(int var3 = 0; var3 < SessionData.allowedBlocks.size(); ++var3) {
+ int var4 = this.width / 2 + var3 % 9 * 24 + -108 - 3;
+ int var5 = this.height / 2 + var3 / 9 * 24 + -60 + 3;
+ if(var1 >= var4 && var1 <= var4 + 24 && var2 >= var5 - 12 && var2 <= var5 + 12) {
+ return var3;
+ }
+ }
+
+ return -1;
+ }
+
+ public final void render(int var1, int var2) {
+ var1 = this.getBlockOnScreen(var1, var2);
+ drawFadingBox(this.width / 2 - 120, 30, this.width / 2 + 120, 180, -1878719232, -1070583712);
+ if(var1 >= 0) {
+ var2 = this.width / 2 + var1 % 9 * 24 + -108;
+ int var3 = this.height / 2 + var1 / 9 * 24 + -60;
+ drawFadingBox(var2 - 3, var3 - 8, var2 + 23, var3 + 24 - 6, -1862270977, -1056964609);
+ }
+
+ drawCenteredString(this.fontRenderer, "Select block", this.width / 2, 40, 16777215);
+ TextureManager var7 = this.minecraft.textureManager;
+ ShapeRenderer var8 = ShapeRenderer.instance;
+ var2 = var7.load("/terrain.png");
+ GL11.glBindTexture(3553, var2);
+
+ for(var2 = 0; var2 < SessionData.allowedBlocks.size(); ++var2) {
+ Block var4 = (Block)SessionData.allowedBlocks.get(var2);
+ GL11.glPushMatrix();
+ int var5 = this.width / 2 + var2 % 9 * 24 + -108;
+ int var6 = this.height / 2 + var2 / 9 * 24 + -60;
+ GL11.glTranslatef((float)var5, (float)var6, 0.0F);
+ GL11.glScalef(10.0F, 10.0F, 10.0F);
+ GL11.glTranslatef(1.0F, 0.5F, 8.0F);
+ GL11.glRotatef(-30.0F, 1.0F, 0.0F, 0.0F);
+ GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
+ if(var1 == var2) {
+ GL11.glScalef(1.6F, 1.6F, 1.6F);
+ }
+
+ GL11.glTranslatef(-1.5F, 0.5F, 0.5F);
+ GL11.glScalef(-1.0F, -1.0F, -1.0F);
+ var8.begin();
+ var4.renderFullbright(var8);
+ var8.end();
+ GL11.glPopMatrix();
+ }
+
+ }
+
+ protected final void onMouseClick(int var1, int var2, int var3) {
+ if(var3 == 0) {
+ this.minecraft.player.inventory.replaceSlot(this.getBlockOnScreen(var1, var2));
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/Button.java b/src/main/java/com/mojang/minecraft/gui/Button.java
new file mode 100644
index 0000000..5488333
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/Button.java
@@ -0,0 +1,33 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.Screen;
+
+public class Button extends Screen {
+
+ int width;
+ int height;
+ public int x;
+ public int y;
+ public String text;
+ public int id;
+ public boolean active;
+ public boolean visible;
+
+
+ public Button(int var1, int var2, int var3, String var4) {
+ this(var1, var2, var3, 200, 20, var4);
+ }
+
+ protected Button(int var1, int var2, int var3, int var4, int var5, String var6) {
+ this.width = 200;
+ this.height = 20;
+ this.active = true;
+ this.visible = true;
+ this.id = var1;
+ this.x = var2;
+ this.y = var3;
+ this.width = var4;
+ this.height = 20;
+ this.text = var6;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/ChatInputScreen.java b/src/main/java/com/mojang/minecraft/gui/ChatInputScreen.java
new file mode 100644
index 0000000..b16eeb1
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/ChatInputScreen.java
@@ -0,0 +1,69 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.net.NetworkManager;
+import com.mojang.minecraft.net.PacketType;
+import org.lwjgl.input.Keyboard;
+
+public final class ChatInputScreen extends GuiScreen {
+
+ private String message = "";
+ private int counter = 0;
+
+
+ public final void onOpen() {
+ Keyboard.enableRepeatEvents(true);
+ }
+
+ public final void onClose() {
+ Keyboard.enableRepeatEvents(false);
+ }
+
+ public final void tick() {
+ ++this.counter;
+ }
+
+ protected final void onKeyPress(char var1, int var2) {
+ if(var2 == 1) {
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ } else if(var2 == 28) {
+ NetworkManager var10000 = this.minecraft.networkManager;
+ String var4 = this.message.trim();
+ NetworkManager var3 = var10000;
+ if((var4 = var4.trim()).length() > 0) {
+ var3.netHandler.send(PacketType.CHAT_MESSAGE, new Object[]{Integer.valueOf(-1), var4});
+ }
+
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ } else {
+ if(var2 == 14 && this.message.length() > 0) {
+ this.message = this.message.substring(0, this.message.length() - 1);
+ }
+
+ if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.:-_\'*!\\\"#%/()=+?[]{}<>@|$;".indexOf(var1) >= 0 && this.message.length() < 64 - (this.minecraft.session.username.length() + 2)) {
+ this.message = this.message + var1;
+ }
+
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawBox(2, this.height - 14, this.width - 2, this.height - 2, Integer.MIN_VALUE);
+ drawString(this.fontRenderer, "> " + this.message + (this.counter / 6 % 2 == 0?"_":""), 4, this.height - 12, 14737632);
+ }
+
+ protected final void onMouseClick(int var1, int var2, int var3) {
+ if(var3 == 0 && this.minecraft.hud.hoveredPlayer != null) {
+ if(this.message.length() > 0 && !this.message.endsWith(" ")) {
+ this.message = this.message + " ";
+ }
+
+ this.message = this.message + this.minecraft.hud.hoveredPlayer;
+ var1 = 64 - (this.minecraft.session.username.length() + 2);
+ if(this.message.length() > var1) {
+ this.message = this.message.substring(0, var1);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/ControlsScreen.java b/src/main/java/com/mojang/minecraft/gui/ControlsScreen.java
new file mode 100644
index 0000000..bf7052a
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/ControlsScreen.java
@@ -0,0 +1,57 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.GameSettings;
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.gui.OptionButton;
+
+public final class ControlsScreen extends GuiScreen {
+
+ private GuiScreen parent;
+ private String title = "Controls";
+ private GameSettings settings;
+ private int selected = -1;
+
+
+ public ControlsScreen(GuiScreen var1, GameSettings var2) {
+ this.parent = var1;
+ this.settings = var2;
+ }
+
+ public final void onOpen() {
+ for(int var1 = 0; var1 < this.settings.bindings.length; ++var1) {
+ this.buttons.add(new OptionButton(var1, this.width / 2 - 155 + var1 % 2 * 160, this.height / 6 + 24 * (var1 >> 1), this.settings.getBinding(var1)));
+ }
+
+ this.buttons.add(new Button(200, this.width / 2 - 100, this.height / 6 + 168, "Done"));
+ }
+
+ protected final void onButtonClick(Button var1) {
+ for(int var2 = 0; var2 < this.settings.bindings.length; ++var2) {
+ ((Button)this.buttons.get(var2)).text = this.settings.getBinding(var2);
+ }
+
+ if(var1.id == 200) {
+ this.minecraft.setCurrentScreen(this.parent);
+ } else {
+ this.selected = var1.id;
+ var1.text = "> " + this.settings.getBinding(var1.id) + " <";
+ }
+ }
+
+ protected final void onKeyPress(char var1, int var2) {
+ if(this.selected >= 0) {
+ this.settings.setBinding(this.selected, var2);
+ ((Button)this.buttons.get(this.selected)).text = this.settings.getBinding(this.selected);
+ this.selected = -1;
+ } else {
+ super.onKeyPress(var1, var2);
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 20, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/ErrorScreen.java b/src/main/java/com/mojang/minecraft/gui/ErrorScreen.java
new file mode 100644
index 0000000..6fe51d1
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/ErrorScreen.java
@@ -0,0 +1,26 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.GuiScreen;
+
+public final class ErrorScreen extends GuiScreen {
+
+ private String title;
+ private String text;
+
+
+ public ErrorScreen(String var1, String var2) {
+ this.title = var1;
+ this.text = var2;
+ }
+
+ public final void onOpen() {}
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, -12574688, -11530224);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 90, 16777215);
+ drawCenteredString(this.fontRenderer, this.text, this.width / 2, 110, 16777215);
+ super.render(var1, var2);
+ }
+
+ protected final void onKeyPress(char var1, int var2) {}
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/FontRenderer.java b/src/main/java/com/mojang/minecraft/gui/FontRenderer.java
new file mode 100644
index 0000000..d14cc79
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/FontRenderer.java
@@ -0,0 +1,158 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.GameSettings;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.minecraft.render.TextureManager;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import org.lwjgl.opengl.GL11;
+
+public final class FontRenderer {
+
+ private int[] widthmap = new int[256];
+ private int fontTexture = 0;
+ private GameSettings settings;
+
+
+ public FontRenderer(GameSettings var1, String var2, TextureManager var3) {
+ this.settings = var1;
+
+ BufferedImage var14;
+ try {
+ var14 = ImageIO.read(TextureManager.class.getResourceAsStream(var2));
+ } catch (IOException var13) {
+ throw new RuntimeException(var13);
+ }
+
+ int var4 = var14.getWidth();
+ int var5 = var14.getHeight();
+ int[] var6 = new int[var4 * var5];
+ var14.getRGB(0, 0, var4, var5, var6, 0, var4);
+
+ for(int var15 = 0; var15 < 128; ++var15) {
+ var5 = var15 % 16;
+ int var7 = var15 / 16;
+ int var8 = 0;
+
+ for(boolean var9 = false; var8 < 8 && !var9; ++var8) {
+ int var10 = (var5 << 3) + var8;
+ var9 = true;
+
+ for(int var11 = 0; var11 < 8 && var9; ++var11) {
+ int var12 = ((var7 << 3) + var11) * var4;
+ if((var6[var10 + var12] & 255) > 128) {
+ var9 = false;
+ }
+ }
+ }
+
+ if(var15 == 32) {
+ var8 = 4;
+ }
+
+ this.widthmap[var15] = var8;
+ }
+
+ this.fontTexture = var3.load(var2);
+ }
+
+ public final void render(String var1, int var2, int var3, int var4) {
+ this.render(var1, var2 + 1, var3 + 1, var4, true);
+ this.renderNoShadow(var1, var2, var3, var4);
+ }
+
+ public final void renderNoShadow(String var1, int var2, int var3, int var4) {
+ this.render(var1, var2, var3, var4, false);
+ }
+
+ private void render(String var1, int var2, int var3, int var4, boolean var5) {
+ if(var1 != null) {
+ char[] var12 = var1.toCharArray();
+ if(var5) {
+ var4 = (var4 & 16579836) >> 2;
+ }
+
+ GL11.glBindTexture(3553, this.fontTexture);
+ ShapeRenderer var6 = ShapeRenderer.instance;
+ ShapeRenderer.instance.begin();
+ var6.color(var4);
+ int var7 = 0;
+
+ for(int var8 = 0; var8 < var12.length; ++var8) {
+ int var9;
+ if(var12[var8] == 38 && var12.length > var8 + 1) {
+ if((var4 = "0123456789abcdef".indexOf(var12[var8 + 1])) < 0) {
+ var4 = 15;
+ }
+
+ var9 = (var4 & 8) << 3;
+ int var10 = (var4 & 1) * 191 + var9;
+ int var11 = ((var4 & 2) >> 1) * 191 + var9;
+ var4 = ((var4 & 4) >> 2) * 191 + var9;
+ if(this.settings.anaglyph) {
+ var9 = (var4 * 30 + var11 * 59 + var10 * 11) / 100;
+ var11 = (var4 * 30 + var11 * 70) / 100;
+ var10 = (var4 * 30 + var10 * 70) / 100;
+ var4 = var9;
+ var11 = var11;
+ var10 = var10;
+ }
+
+ var4 = var4 << 16 | var11 << 8 | var10;
+ var8 += 2;
+ if(var5) {
+ var4 = (var4 & 16579836) >> 2;
+ }
+
+ var6.color(var4);
+ }
+
+ var4 = var12[var8] % 16 << 3;
+ var9 = var12[var8] / 16 << 3;
+ float var13 = 7.99F;
+ var6.vertexUV((float)(var2 + var7), (float)var3 + var13, 0.0F, (float)var4 / 128.0F, ((float)var9 + var13) / 128.0F);
+ var6.vertexUV((float)(var2 + var7) + var13, (float)var3 + var13, 0.0F, ((float)var4 + var13) / 128.0F, ((float)var9 + var13) / 128.0F);
+ var6.vertexUV((float)(var2 + var7) + var13, (float)var3, 0.0F, ((float)var4 + var13) / 128.0F, (float)var9 / 128.0F);
+ var6.vertexUV((float)(var2 + var7), (float)var3, 0.0F, (float)var4 / 128.0F, (float)var9 / 128.0F);
+ var7 += this.widthmap[var12[var8]];
+ }
+
+ var6.end();
+ }
+ }
+
+ public final int getWidth(String var1) {
+ if(var1 == null) {
+ return 0;
+ } else {
+ char[] var4 = var1.toCharArray();
+ int var2 = 0;
+
+ for(int var3 = 0; var3 < var4.length; ++var3) {
+ if(var4[var3] == 38) {
+ ++var3;
+ } else {
+ var2 += this.widthmap[var4[var3]];
+ }
+ }
+
+ return var2;
+ }
+ }
+
+ public static String stripColor(String var0) {
+ char[] var3 = var0.toCharArray();
+ String var1 = "";
+
+ for(int var2 = 0; var2 < var3.length; ++var2) {
+ if(var3[var2] == 38) {
+ ++var2;
+ } else {
+ var1 = var1 + var3[var2];
+ }
+ }
+
+ return var1;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/GameOverScreen.java b/src/main/java/com/mojang/minecraft/gui/GameOverScreen.java
new file mode 100644
index 0000000..09a7546
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/GameOverScreen.java
@@ -0,0 +1,46 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GenerateLevelScreen;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.gui.LoadLevelScreen;
+import com.mojang.minecraft.gui.OptionsScreen;
+import org.lwjgl.opengl.GL11;
+
+public final class GameOverScreen extends GuiScreen {
+
+ public final void onOpen() {
+ this.buttons.clear();
+ this.buttons.add(new Button(1, this.width / 2 - 100, this.height / 4 + 72, "Generate new level..."));
+ this.buttons.add(new Button(2, this.width / 2 - 100, this.height / 4 + 96, "Load level.."));
+ if(this.minecraft.session == null) {
+ ((Button)this.buttons.get(1)).active = false;
+ }
+
+ }
+
+ protected final void onButtonClick(Button var1) {
+ if(var1.id == 0) {
+ this.minecraft.setCurrentScreen(new OptionsScreen(this, this.minecraft.settings));
+ }
+
+ if(var1.id == 1) {
+ this.minecraft.setCurrentScreen(new GenerateLevelScreen(this));
+ }
+
+ if(this.minecraft.session != null && var1.id == 2) {
+ this.minecraft.setCurrentScreen(new LoadLevelScreen(this));
+ }
+
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1615855616, -1602211792);
+ GL11.glPushMatrix();
+ GL11.glScalef(2.0F, 2.0F, 2.0F);
+ drawCenteredString(this.fontRenderer, "Game over!", this.width / 2 / 2, 30, 16777215);
+ GL11.glPopMatrix();
+ drawCenteredString(this.fontRenderer, "Score: &e" + this.minecraft.player.getScore(), this.width / 2, 100, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/GenerateLevelScreen.java b/src/main/java/com/mojang/minecraft/gui/GenerateLevelScreen.java
new file mode 100644
index 0000000..2e1b2fe
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/GenerateLevelScreen.java
@@ -0,0 +1,38 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GuiScreen;
+
+public final class GenerateLevelScreen extends GuiScreen {
+
+ private GuiScreen parent;
+
+
+ public GenerateLevelScreen(GuiScreen var1) {
+ this.parent = var1;
+ }
+
+ public final void onOpen() {
+ this.buttons.clear();
+ this.buttons.add(new Button(0, this.width / 2 - 100, this.height / 4, "Small"));
+ this.buttons.add(new Button(1, this.width / 2 - 100, this.height / 4 + 24, "Normal"));
+ this.buttons.add(new Button(2, this.width / 2 - 100, this.height / 4 + 48, "Huge"));
+ this.buttons.add(new Button(3, this.width / 2 - 100, this.height / 4 + 120, "Cancel"));
+ }
+
+ protected final void onButtonClick(Button var1) {
+ if(var1.id == 3) {
+ this.minecraft.setCurrentScreen(this.parent);
+ } else {
+ this.minecraft.generateLevel(var1.id);
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ this.minecraft.grabMouse();
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, "Generate new level", this.width / 2, 40, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/GuiMods.java b/src/main/java/com/mojang/minecraft/gui/GuiMods.java
new file mode 100644
index 0000000..85292ea
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/GuiMods.java
@@ -0,0 +1,40 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+
+public class GuiMods extends GuiScreen {
+ GuiScreen parent = null;
+ String title = "Optifine";
+
+ public GuiMods(GuiScreen parent) {
+ this.parent = parent;
+ }
+
+ public final void onOpen() {
+ this.buttons.add(new OptionButton(1, this.width / 2 - 155 + 0 % 2 * 160, this.height / 6 + 24 * (0 >> 1), minecraft.settings.getSetting(11)));
+ this.buttons.add(new OptionButton(2, this.width / 2 - 155 + 1 % 2 * 160, this.height / 6 + 24 * (1 >> 1), minecraft.settings.getSetting(12)));
+ this.buttons.add(new Button(200, this.width / 2 - 100, this.height / 6 + 168 + 12, "Done"));
+ }
+
+ public final void onButtonClick(Button var1) {
+ if(var1.id == 1) {
+ minecraft.settings.toggleSetting(11, 0);
+ var1.text = minecraft.settings.getSetting(11);
+ }
+
+ if(var1.id == 2) {
+ minecraft.settings.toggleSetting(12, 0);
+ var1.text = minecraft.settings.getSetting(12);
+ }
+
+ if(var1.id == 200) {
+ minecraft.setCurrentScreen(parent);
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 20, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/GuiMore.java b/src/main/java/com/mojang/minecraft/gui/GuiMore.java
new file mode 100644
index 0000000..f216795
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/GuiMore.java
@@ -0,0 +1,40 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+
+public class GuiMore extends GuiScreen {
+ GuiScreen parent = null;
+ String title;
+
+ public GuiMore(GuiScreen parent) {
+ this.parent = parent;
+ this.title = "More Options...";
+ }
+
+ public final void onOpen() {
+ this.buttons.add(new Button(50, this.width / 2 - 100, this.height / 6 + 0 + 12, "Mods"));
+ this.buttons.add(new Button(100, this.width / 2 - 100, this.height / 6 + 25 + 12, "Optifine"));
+ this.buttons.add(new Button(200, this.width / 2 - 100, this.height / 6 + 168 + 12, "Done"));
+ }
+
+ public final void onButtonClick(Button var1) {
+
+ if(var1.id == 50) {
+ minecraft.setCurrentScreen(new GuiMods(this));
+ }
+
+ if(var1.id == 100) {
+ minecraft.setCurrentScreen(new GuiOptifine(this));
+ }
+
+ if(var1.id == 200) {
+ minecraft.setCurrentScreen(parent);
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 20, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/GuiOptifine.java b/src/main/java/com/mojang/minecraft/gui/GuiOptifine.java
new file mode 100644
index 0000000..05bdcff
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/GuiOptifine.java
@@ -0,0 +1,40 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+
+public class GuiOptifine extends GuiScreen {
+ GuiScreen parent = null;
+ String title = "Optifine";
+
+ public GuiOptifine(GuiScreen parent) {
+ this.parent = parent;
+ }
+
+ public final void onOpen() {
+ this.buttons.add(new OptionButton(1, this.width / 2 - 155 + 0 % 2 * 160, this.height / 6 + 24 * (0 >> 1), minecraft.settings.getSetting(8)));
+ this.buttons.add(new OptionButton(2, this.width / 2 - 155 + 1 % 2 * 160, this.height / 6 + 24 * (1 >> 1), minecraft.settings.getSetting(9)));
+ this.buttons.add(new Button(200, this.width / 2 - 100, this.height / 6 + 168 + 12, "Done"));
+ }
+
+ public final void onButtonClick(Button var1) {
+ if(var1.id == 1) {
+ minecraft.settings.toggleSetting(8, 0);
+ var1.text = minecraft.settings.getSetting(8);
+ }
+
+ if(var1.id == 2) {
+ minecraft.settings.toggleSetting(9, 0);
+ var1.text = minecraft.settings.getSetting(9);
+ }
+
+ if(var1.id == 200) {
+ minecraft.setCurrentScreen(parent);
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 20, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/GuiScreen.java b/src/main/java/com/mojang/minecraft/gui/GuiScreen.java
new file mode 100644
index 0000000..b62aa2f
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/GuiScreen.java
@@ -0,0 +1,117 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.FontRenderer;
+import com.mojang.minecraft.gui.Screen;
+import java.util.ArrayList;
+import java.util.List;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+public class GuiScreen extends Screen {
+
+ protected Minecraft minecraft;
+ protected int width;
+ protected int height;
+ protected List buttons = new ArrayList();
+ public boolean grabsMouse = false;
+ protected FontRenderer fontRenderer;
+
+
+ public void render(int var1, int var2) {
+ for(int var3 = 0; var3 < this.buttons.size(); ++var3) {
+ Button var10000 = (Button)this.buttons.get(var3);
+ Minecraft var7 = this.minecraft;
+ Button var4 = var10000;
+ if(var10000.visible) {
+ FontRenderer var8 = var7.fontRenderer;
+ GL11.glBindTexture(3553, var7.textureManager.load("/gui/gui.png"));
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ byte var9 = 1;
+ boolean var6 = var1 >= var4.x && var2 >= var4.y && var1 < var4.x + var4.width && var2 < var4.y + var4.height;
+ if(!var4.active) {
+ var9 = 0;
+ } else if(var6) {
+ var9 = 2;
+ }
+
+ var4.drawImage(var4.x, var4.y, 0, 46 + var9 * 20, var4.width / 2, var4.height);
+ var4.drawImage(var4.x + var4.width / 2, var4.y, 200 - var4.width / 2, 46 + var9 * 20, var4.width / 2, var4.height);
+ if(!var4.active) {
+ Button.drawCenteredString(var8, var4.text, var4.x + var4.width / 2, var4.y + (var4.height - 8) / 2, -6250336);
+ } else if(var6) {
+ Button.drawCenteredString(var8, var4.text, var4.x + var4.width / 2, var4.y + (var4.height - 8) / 2, 16777120);
+ } else {
+ Button.drawCenteredString(var8, var4.text, var4.x + var4.width / 2, var4.y + (var4.height - 8) / 2, 14737632);
+ }
+ }
+ }
+
+ }
+
+ protected void onKeyPress(char var1, int var2) {
+ if(var2 == 1) {
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ this.minecraft.grabMouse();
+ }
+
+ }
+
+ protected void onMouseClick(int var1, int var2, int var3) {
+ if(var3 == 0) {
+ for(var3 = 0; var3 < this.buttons.size(); ++var3) {
+ Button var4;
+ Button var7;
+ if((var7 = var4 = (Button)this.buttons.get(var3)).active && var1 >= var7.x && var2 >= var7.y && var1 < var7.x + var7.width && var2 < var7.y + var7.height) {
+ this.onButtonClick(var4);
+ }
+ }
+ }
+
+ }
+
+ protected void onButtonClick(Button var1) {}
+
+ public final void open(Minecraft var1, int var2, int var3) {
+ this.minecraft = var1;
+ this.fontRenderer = var1.fontRenderer;
+ this.width = var2;
+ this.height = var3;
+ this.onOpen();
+ }
+
+ public void onOpen() {}
+
+ public final void doInput() {
+ while(Mouse.next()) {
+ this.mouseEvent();
+ }
+
+ while(Keyboard.next()) {
+ this.keyboardEvent();
+ }
+
+ }
+
+ public final void mouseEvent() {
+ if(Mouse.getEventButtonState()) {
+ int var1 = Mouse.getEventX() * this.width / this.minecraft.width;
+ int var2 = this.height - Mouse.getEventY() * this.height / this.minecraft.height - 1;
+ this.onMouseClick(var1, var2, Mouse.getEventButton());
+ }
+
+ }
+
+ public final void keyboardEvent() {
+ if(Keyboard.getEventKeyState()) {
+ this.onKeyPress(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ }
+
+ }
+
+ public void tick() {}
+
+ public void onClose() {}
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/HUDScreen.java b/src/main/java/com/mojang/minecraft/gui/HUDScreen.java
new file mode 100644
index 0000000..4558ba2
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/HUDScreen.java
@@ -0,0 +1,215 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.ChatLine;
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gamemode.SurvivalGameMode;
+import com.mojang.minecraft.gui.ChatInputScreen;
+import com.mojang.minecraft.gui.FontRenderer;
+import com.mojang.minecraft.gui.Screen;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.player.Inventory;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+
+public final class HUDScreen extends Screen {
+
+ public List chat = new ArrayList();
+ private Random random = new Random();
+ private Minecraft mc;
+ private int width;
+ private int height;
+ public String hoveredPlayer = null;
+ public int ticks = 0;
+
+
+ public HUDScreen(Minecraft var1, int var2, int var3) {
+ this.mc = var1;
+ this.width = var2 * 240 / var3;
+ this.height = var3 * 240 / var3;
+ }
+
+ public final void render(float var1, boolean var2, int var3, int var4) {
+ FontRenderer var5 = this.mc.fontRenderer;
+ this.mc.renderer.enableGuiMode();
+ TextureManager var6 = this.mc.textureManager;
+ GL11.glBindTexture(3553, this.mc.textureManager.load("/gui/gui.png"));
+ ShapeRenderer var7 = ShapeRenderer.instance;
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ GL11.glEnable(3042);
+ Inventory var8 = this.mc.player.inventory;
+ this.imgZ = -90.0F;
+ this.drawImage(this.width / 2 - 91, this.height - 22, 0, 0, 182, 22);
+ this.drawImage(this.width / 2 - 91 - 1 + var8.selected * 20, this.height - 22 - 1, 0, 22, 24, 22);
+ GL11.glBindTexture(3553, this.mc.textureManager.load("/gui/icons.png"));
+ this.drawImage(this.width / 2 - 7, this.height / 2 - 7, 0, 0, 16, 16);
+ boolean var9 = this.mc.player.invulnerableTime / 3 % 2 == 1;
+ if(this.mc.player.invulnerableTime < 10) {
+ var9 = false;
+ }
+
+ int var10 = this.mc.player.health;
+ int var11 = this.mc.player.lastHealth;
+ this.random.setSeed((long)(this.ticks * 312871));
+ int var12;
+ int var14;
+ int var15;
+ int var26;
+ if(this.mc.gamemode.isSurvival()) {
+ for(var12 = 0; var12 < 10; ++var12) {
+ byte var13 = 0;
+ if(var9) {
+ var13 = 1;
+ }
+
+ var14 = this.width / 2 - 91 + (var12 << 3);
+ var15 = this.height - 32;
+ if(var10 <= 4) {
+ var15 += this.random.nextInt(2);
+ }
+
+ this.drawImage(var14, var15, 16 + var13 * 9, 0, 9, 9);
+ if(var9) {
+ if((var12 << 1) + 1 < var11) {
+ this.drawImage(var14, var15, 70, 0, 9, 9);
+ }
+
+ if((var12 << 1) + 1 == var11) {
+ this.drawImage(var14, var15, 79, 0, 9, 9);
+ }
+ }
+
+ if((var12 << 1) + 1 < var10) {
+ this.drawImage(var14, var15, 52, 0, 9, 9);
+ }
+
+ if((var12 << 1) + 1 == var10) {
+ this.drawImage(var14, var15, 61, 0, 9, 9);
+ }
+ }
+
+ if(this.mc.player.isUnderWater()) {
+ var12 = (int)Math.ceil((double)(this.mc.player.airSupply - 2) * 10.0D / 300.0D);
+ var26 = (int)Math.ceil((double)this.mc.player.airSupply * 10.0D / 300.0D) - var12;
+
+ for(var14 = 0; var14 < var12 + var26; ++var14) {
+ if(var14 < var12) {
+ this.drawImage(this.width / 2 - 91 + (var14 << 3), this.height - 32 - 9, 16, 18, 9, 9);
+ } else {
+ this.drawImage(this.width / 2 - 91 + (var14 << 3), this.height - 32 - 9, 25, 18, 9, 9);
+ }
+ }
+ }
+ }
+
+ GL11.glDisable(3042);
+
+ String var23;
+ for(var12 = 0; var12 < var8.slots.length; ++var12) {
+ var26 = this.width / 2 - 90 + var12 * 20;
+ var14 = this.height - 16;
+ if((var15 = var8.slots[var12]) > 0) {
+ GL11.glPushMatrix();
+ GL11.glTranslatef((float)var26, (float)var14, -50.0F);
+ if(var8.popTime[var12] > 0) {
+ float var18;
+ float var21 = -MathHelper.sin((var18 = ((float)var8.popTime[var12] - var1) / 5.0F) * var18 * 3.1415927F) * 8.0F;
+ float var19 = MathHelper.sin(var18 * var18 * 3.1415927F) + 1.0F;
+ float var16 = MathHelper.sin(var18 * 3.1415927F) + 1.0F;
+ GL11.glTranslatef(10.0F, var21 + 10.0F, 0.0F);
+ GL11.glScalef(var19, var16, 1.0F);
+ GL11.glTranslatef(-10.0F, -10.0F, 0.0F);
+ }
+
+ GL11.glScalef(10.0F, 10.0F, 10.0F);
+ GL11.glTranslatef(1.0F, 0.5F, 0.0F);
+ GL11.glRotatef(-30.0F, 1.0F, 0.0F, 0.0F);
+ GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
+ GL11.glTranslatef(-1.5F, 0.5F, 0.5F);
+ GL11.glScalef(-1.0F, -1.0F, -1.0F);
+ int var20 = var6.load("/terrain.png");
+ GL11.glBindTexture(3553, var20);
+ var7.begin();
+ Block.blocks[var15].renderFullbright(var7);
+ var7.end();
+ GL11.glPopMatrix();
+ if(var8.count[var12] > 1) {
+ var23 = "" + var8.count[var12];
+ var5.render(var23, var26 + 19 - var5.getWidth(var23), var14 + 6, 16777215);
+ }
+ }
+ }
+
+ var5.render("0.30", 2, 2, 16777215);
+ if(this.mc.settings.showFrameRate) {
+ var5.render(this.mc.debug, 2, 12, 16777215);
+ }
+
+ if(this.mc.gamemode instanceof SurvivalGameMode) {
+ String var24 = "Score: &e" + this.mc.player.getScore();
+ var5.render(var24, this.width - var5.getWidth(var24) - 2, 2, 16777215);
+ var5.render("Arrows: " + this.mc.player.arrows, this.width / 2 + 8, this.height - 33, 16777215);
+ }
+
+ byte var25 = 10;
+ boolean var27 = false;
+ if(this.mc.currentScreen instanceof ChatInputScreen) {
+ var25 = 20;
+ var27 = true;
+ }
+
+ for(var14 = 0; var14 < this.chat.size() && var14 < var25; ++var14) {
+ if(((ChatLine)this.chat.get(var14)).time < 200 || var27) {
+ var5.render(((ChatLine)this.chat.get(var14)).message, 2, this.height - 8 - var14 * 9 - 20, 16777215);
+ }
+ }
+
+ var14 = this.width / 2;
+ var15 = this.height / 2;
+ this.hoveredPlayer = null;
+ if(Keyboard.isKeyDown(15) && this.mc.networkManager != null && this.mc.networkManager.isConnected()) {
+ List var22 = this.mc.networkManager.getPlayers();
+ GL11.glEnable(3042);
+ GL11.glDisable(3553);
+ GL11.glBlendFunc(770, 771);
+ GL11.glBegin(7);
+ GL11.glColor4f(0.0F, 0.0F, 0.0F, 0.7F);
+ GL11.glVertex2f((float)(var14 + 128), (float)(var15 - 68 - 12));
+ GL11.glVertex2f((float)(var14 - 128), (float)(var15 - 68 - 12));
+ GL11.glColor4f(0.2F, 0.2F, 0.2F, 0.8F);
+ GL11.glVertex2f((float)(var14 - 128), (float)(var15 + 68));
+ GL11.glVertex2f((float)(var14 + 128), (float)(var15 + 68));
+ GL11.glEnd();
+ GL11.glDisable(3042);
+ GL11.glEnable(3553);
+ var23 = "Connected players:";
+ var5.render(var23, var14 - var5.getWidth(var23) / 2, var15 - 64 - 12, 16777215);
+
+ for(var11 = 0; var11 < var22.size(); ++var11) {
+ int var28 = var14 + var11 % 2 * 120 - 120;
+ int var17 = var15 - 64 + (var11 / 2 << 3);
+ if(var2 && var3 >= var28 && var4 >= var17 && var3 < var28 + 120 && var4 < var17 + 8) {
+ this.hoveredPlayer = (String)var22.get(var11);
+ var5.renderNoShadow((String)var22.get(var11), var28 + 2, var17, 16777215);
+ } else {
+ var5.renderNoShadow((String)var22.get(var11), var28, var17, 15658734);
+ }
+ }
+ }
+
+ }
+
+ public final void addChat(String var1) {
+ this.chat.add(0, new ChatLine(var1));
+
+ while(this.chat.size() > 50) {
+ this.chat.remove(this.chat.size() - 1);
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/LevelDialog.java b/src/main/java/com/mojang/minecraft/gui/LevelDialog.java
new file mode 100644
index 0000000..30d1250
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/LevelDialog.java
@@ -0,0 +1,52 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.LoadLevelScreen;
+import javax.swing.JFileChooser;
+import javax.swing.filechooser.FileNameExtensionFilter;
+
+final class LevelDialog extends Thread {
+
+ // $FF: synthetic field
+ private LoadLevelScreen screen;
+
+
+ LevelDialog(LoadLevelScreen var1) {
+ super();
+ this.screen = var1;
+ }
+
+ public final void run() {
+ JFileChooser var1;
+ LoadLevelScreen var2;
+ try {
+ LoadLevelScreen var10000 = this.screen;
+ var1 = new JFileChooser();
+ var10000.chooser = var1;
+ FileNameExtensionFilter var3 = new FileNameExtensionFilter("Minecraft levels", new String[]{"mine"});
+ var2 = this.screen;
+ this.screen.chooser.setFileFilter(var3);
+ var2 = this.screen;
+ this.screen.chooser.setMultiSelectionEnabled(false);
+ int var7;
+ if(this.screen.saving) {
+ var2 = this.screen;
+ var7 = this.screen.chooser.showSaveDialog(this.screen.minecraft.canvas);
+ } else {
+ var2 = this.screen;
+ var7 = this.screen.chooser.showOpenDialog(this.screen.minecraft.canvas);
+ }
+
+ if(var7 == 0) {
+ (var2 = this.screen).selectedFile = this.screen.chooser.getSelectedFile();
+ }
+ } finally {
+ boolean var6 = false;
+ var2 = this.screen;
+ this.screen.frozen = false;
+ var1 = null;
+ var2 = this.screen;
+ this.screen.chooser = var1;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/LevelNameScreen.java b/src/main/java/com/mojang/minecraft/gui/LevelNameScreen.java
new file mode 100644
index 0000000..3c7ee76
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/LevelNameScreen.java
@@ -0,0 +1,85 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GuiScreen;
+import org.lwjgl.input.Keyboard;
+
+public final class LevelNameScreen extends GuiScreen {
+
+ private GuiScreen parent;
+ private String title = "Enter level name:";
+ private int id;
+ private String name;
+ private int counter = 0;
+
+
+ public LevelNameScreen(GuiScreen var1, String var2, int var3) {
+ this.parent = var1;
+ this.id = var3;
+ this.name = var2;
+ if(this.name.equals("-")) {
+ this.name = "";
+ }
+
+ }
+
+ public final void onOpen() {
+ this.buttons.clear();
+ Keyboard.enableRepeatEvents(true);
+ this.buttons.add(new Button(0, this.width / 2 - 100, this.height / 4 + 120, "Save"));
+ this.buttons.add(new Button(1, this.width / 2 - 100, this.height / 4 + 144, "Cancel"));
+ ((Button)this.buttons.get(0)).active = this.name.trim().length() > 1;
+ }
+
+ public final void onClose() {
+ Keyboard.enableRepeatEvents(false);
+ }
+
+ public final void tick() {
+ ++this.counter;
+ }
+
+ protected final void onButtonClick(Button var1) {
+ if(var1.active) {
+ if(var1.id == 0 && this.name.trim().length() > 1) {
+ Minecraft var10000 = this.minecraft;
+ int var10001 = this.id;
+ String var2 = this.name.trim();
+ int var3 = var10001;
+ Minecraft var4 = var10000;
+ var10000.levelIo.saveOnline(var4.level, var4.host, var4.session.username, var4.session.sessionId, var2, var3);
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ this.minecraft.grabMouse();
+ }
+
+ if(var1.id == 1) {
+ this.minecraft.setCurrentScreen(this.parent);
+ }
+
+ }
+ }
+
+ protected final void onKeyPress(char var1, int var2) {
+ if(var2 == 14 && this.name.length() > 0) {
+ this.name = this.name.substring(0, this.name.length() - 1);
+ }
+
+ if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.:-_\'*!\"#%/()=+?[]{}<>".indexOf(var1) >= 0 && this.name.length() < 64) {
+ this.name = this.name + var1;
+ }
+
+ ((Button)this.buttons.get(0)).active = this.name.trim().length() > 1;
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 40, 16777215);
+ int var3 = this.width / 2 - 100;
+ int var4 = this.height / 2 - 10;
+ drawBox(var3 - 1, var4 - 1, var3 + 200 + 1, var4 + 20 + 1, -6250336);
+ drawBox(var3, var4, var3 + 200, var4 + 20, -16777216);
+ drawString(this.fontRenderer, this.name + (this.counter / 6 % 2 == 0?"_":""), var3 + 4, var4 + 6, 14737632);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/LoadLevelScreen.java b/src/main/java/com/mojang/minecraft/gui/LoadLevelScreen.java
new file mode 100644
index 0000000..468f2e0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/LoadLevelScreen.java
@@ -0,0 +1,164 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.gui.LevelDialog;
+import com.mojang.minecraft.level.Level;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.net.URL;
+import javax.swing.JFileChooser;
+import javax.swing.SwingUtilities;
+
+public class LoadLevelScreen extends GuiScreen implements Runnable {
+
+ protected GuiScreen parent;
+ private boolean finished = false;
+ private boolean loaded = false;
+ private String[] levels = null;
+ private String status = "";
+ protected String title = "Load level";
+ boolean frozen = false;
+ JFileChooser chooser;
+ protected boolean saving = false;
+ protected File selectedFile;
+
+
+ public LoadLevelScreen(GuiScreen var1) {
+ this.parent = var1;
+ }
+
+ public void run() {
+ try {
+ if(this.frozen) {
+ try {
+ Thread.sleep(100L);
+ } catch (InterruptedException var2) {
+ var2.printStackTrace();
+ }
+ }
+
+ this.status = "Getting level list..";
+ URL var1 = new URL("http://" + this.minecraft.host + "/listmaps.jsp?user=" + this.minecraft.session.username);
+ BufferedReader var4 = new BufferedReader(new InputStreamReader(var1.openConnection().getInputStream()));
+ this.levels = var4.readLine().split(";");
+ if(this.levels.length >= 5) {
+ this.setLevels(this.levels);
+ this.loaded = true;
+ return;
+ }
+
+ this.status = this.levels[0];
+ this.finished = true;
+ } catch (Exception var3) {
+ var3.printStackTrace();
+ this.status = "Failed to load levels";
+ this.finished = true;
+ }
+
+ }
+
+ protected void setLevels(String[] var1) {
+ for(int var2 = 0; var2 < 5; ++var2) {
+ ((Button)this.buttons.get(var2)).active = !var1[var2].equals("-");
+ ((Button)this.buttons.get(var2)).text = var1[var2];
+ ((Button)this.buttons.get(var2)).visible = true;
+ }
+
+ }
+
+ public void onOpen() {
+ (new Thread(this)).start();
+
+ for(int var1 = 0; var1 < 5; ++var1) {
+ this.buttons.add(new Button(var1, this.width / 2 - 100, this.height / 6 + var1 * 24, "---"));
+ ((Button)this.buttons.get(var1)).visible = false;
+ ((Button)this.buttons.get(var1)).active = false;
+ }
+
+ this.buttons.add(new Button(5, this.width / 2 - 100, this.height / 6 + 120 + 12, "Load file..."));
+ this.buttons.add(new Button(6, this.width / 2 - 100, this.height / 6 + 168, "Cancel"));
+ }
+
+ protected final void onButtonClick(Button var1) {
+ if(!this.frozen) {
+ if(var1.active) {
+ if(this.loaded && var1.id < 5) {
+ this.openLevel(var1.id);
+ }
+
+ if(this.finished || this.loaded && var1.id == 5) {
+ this.frozen = true;
+ LevelDialog var2;
+ (var2 = new LevelDialog(this)).setDaemon(true);
+ SwingUtilities.invokeLater(var2);
+ }
+
+ if(this.finished || this.loaded && var1.id == 6) {
+ this.minecraft.setCurrentScreen(this.parent);
+ }
+
+ }
+ }
+ }
+
+ protected void openLevel(File var1) {
+ File var2 = var1;
+ Minecraft var4 = this.minecraft;
+ Level var5;
+ boolean var10000;
+ if((var5 = this.minecraft.levelIo.load(var2)) == null) {
+ var10000 = false;
+ } else {
+ var4.setLevel(var5);
+ var10000 = true;
+ }
+
+ this.minecraft.setCurrentScreen(this.parent);
+ }
+
+ protected void openLevel(int var1) {
+ this.minecraft.loadOnlineLevel(this.minecraft.session.username, var1);
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ this.minecraft.grabMouse();
+ }
+
+ public void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 20, 16777215);
+ if(this.frozen) {
+ drawCenteredString(this.fontRenderer, "Selecting file..", this.width / 2, this.height / 2 - 4, 16777215);
+
+ try {
+ Thread.sleep(20L);
+ } catch (InterruptedException var3) {
+ var3.printStackTrace();
+ }
+ } else {
+ if(!this.loaded) {
+ drawCenteredString(this.fontRenderer, this.status, this.width / 2, this.height / 2 - 4, 16777215);
+ }
+
+ super.render(var1, var2);
+ }
+ }
+
+ public final void onClose() {
+ super.onClose();
+ if(this.chooser != null) {
+ this.chooser.cancelSelection();
+ }
+
+ }
+
+ public final void tick() {
+ super.tick();
+ if(this.selectedFile != null) {
+ this.openLevel(this.selectedFile);
+ this.selectedFile = null;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/OptionButton.java b/src/main/java/com/mojang/minecraft/gui/OptionButton.java
new file mode 100644
index 0000000..494f155
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/OptionButton.java
@@ -0,0 +1,10 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.Button;
+
+public final class OptionButton extends Button {
+
+ public OptionButton(int var1, int var2, int var3, String var4) {
+ super(var1, var2, var3, 150, 20, var4);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/OptionsScreen.java b/src/main/java/com/mojang/minecraft/gui/OptionsScreen.java
new file mode 100644
index 0000000..391eda6
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/OptionsScreen.java
@@ -0,0 +1,58 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.GameSettings;
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.ControlsScreen;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.gui.OptionButton;
+
+public final class OptionsScreen extends GuiScreen {
+
+ private GuiScreen parent;
+ private String title = "Options";
+ private GameSettings settings;
+
+
+ public OptionsScreen(GuiScreen var1, GameSettings var2) {
+ this.parent = var1;
+ this.settings = var2;
+ }
+
+ public final void onOpen() {
+ for(int var1 = 0; var1 < this.settings.settingCount; ++var1) {
+ this.buttons.add(new OptionButton(var1, this.width / 2 - 155 + var1 % 2 * 160, this.height / 6 + 24 * (var1 >> 1), this.settings.getSetting(var1)));
+ }
+
+ this.buttons.add(new Button(50, this.width / 2 - 100, this.height / 6 + 95 + 12, "More..."));
+ this.buttons.add(new Button(100, this.width / 2 - 100, this.height / 6 + 120 + 12, "Controls..."));
+ this.buttons.add(new Button(200, this.width / 2 - 100, this.height / 6 + 168, "Done"));
+ }
+
+ protected final void onButtonClick(Button var1) {
+ if(var1.active) {
+ if(var1.id < 100) {
+ this.settings.toggleSetting(var1.id, 1);
+ var1.text = this.settings.getSetting(var1.id);
+ }
+
+ if(var1.id == 50) {
+ this.minecraft.setCurrentScreen(new GuiMore(this));
+ }
+
+ if(var1.id == 100) {
+ this.minecraft.setCurrentScreen(new ControlsScreen(this, this.settings));
+ }
+
+ if(var1.id == 200) {
+ this.minecraft.setCurrentScreen(this.parent);
+ }
+
+ }
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, this.title, this.width / 2, 20, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/PauseScreen.java b/src/main/java/com/mojang/minecraft/gui/PauseScreen.java
new file mode 100644
index 0000000..63894d2
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/PauseScreen.java
@@ -0,0 +1,63 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GenerateLevelScreen;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.gui.LoadLevelScreen;
+import com.mojang.minecraft.gui.OptionsScreen;
+import com.mojang.minecraft.gui.SaveLevelScreen;
+
+public final class PauseScreen extends GuiScreen {
+
+ public final void onOpen() {
+ this.buttons.clear();
+ this.buttons.add(new Button(0, this.width / 2 - 100, this.height / 4, "Options..."));
+ this.buttons.add(new Button(1, this.width / 2 - 100, this.height / 4 + 24, "Generate new level..."));
+ this.buttons.add(new Button(2, this.width / 2 - 100, this.height / 4 + 48, "Save level.."));
+ this.buttons.add(new Button(3, this.width / 2 - 100, this.height / 4 + 72, "Load level.."));
+ this.buttons.add(new Button(4, this.width / 2 - 100, this.height / 4 + 120, "Back to game"));
+ if(this.minecraft.session == null) {
+ ((Button)this.buttons.get(2)).active = false;
+ ((Button)this.buttons.get(3)).active = false;
+ }
+
+ if(this.minecraft.networkManager != null) {
+ ((Button)this.buttons.get(1)).active = false;
+ ((Button)this.buttons.get(2)).active = false;
+ ((Button)this.buttons.get(3)).active = false;
+ }
+
+ }
+
+ protected final void onButtonClick(Button var1) {
+ if(var1.id == 0) {
+ this.minecraft.setCurrentScreen(new OptionsScreen(this, this.minecraft.settings));
+ }
+
+ if(var1.id == 1) {
+ this.minecraft.setCurrentScreen(new GenerateLevelScreen(this));
+ }
+
+ if(this.minecraft.session != null) {
+ if(var1.id == 2) {
+ this.minecraft.setCurrentScreen(new SaveLevelScreen(this));
+ }
+
+ if(var1.id == 3) {
+ this.minecraft.setCurrentScreen(new LoadLevelScreen(this));
+ }
+ }
+
+ if(var1.id == 4) {
+ this.minecraft.setCurrentScreen((GuiScreen)null);
+ this.minecraft.grabMouse();
+ }
+
+ }
+
+ public final void render(int var1, int var2) {
+ drawFadingBox(0, 0, this.width, this.height, 1610941696, -1607454624);
+ drawCenteredString(this.fontRenderer, "Game menu", this.width / 2, 40, 16777215);
+ super.render(var1, var2);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/SaveLevelScreen.java b/src/main/java/com/mojang/minecraft/gui/SaveLevelScreen.java
new file mode 100644
index 0000000..6ad7917
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/SaveLevelScreen.java
@@ -0,0 +1,56 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.Button;
+import com.mojang.minecraft.gui.GuiScreen;
+import com.mojang.minecraft.gui.LevelNameScreen;
+import com.mojang.minecraft.gui.LoadLevelScreen;
+import java.io.File;
+
+public final class SaveLevelScreen extends LoadLevelScreen {
+
+ public SaveLevelScreen(GuiScreen var1) {
+ super(var1);
+ this.title = "Save level";
+ this.saving = true;
+ }
+
+ public final void onOpen() {
+ super.onOpen();
+ ((Button)this.buttons.get(5)).text = "Save file...";
+ }
+
+ protected final void setLevels(String[] var1) {
+ for(int var2 = 0; var2 < 5; ++var2) {
+ ((Button)this.buttons.get(var2)).text = var1[var2];
+ ((Button)this.buttons.get(var2)).visible = true;
+ ((Button)this.buttons.get(var2)).active = this.minecraft.session.haspaid;
+ }
+
+ }
+
+ public final void render(int var1, int var2) {
+ super.render(var1, var2);
+ if(!this.minecraft.session.haspaid) {
+ drawFadingBox(this.width / 2 - 80, 72, this.width / 2 + 80, 120, -536870912, -536870912);
+ drawCenteredString(this.fontRenderer, "Premium only!", this.width / 2, 80, 16748688);
+ drawCenteredString(this.fontRenderer, "Purchase the game to be able", this.width / 2, 96, 14712960);
+ drawCenteredString(this.fontRenderer, "to save your levels online.", this.width / 2, 104, 14712960);
+ }
+ }
+
+ protected final void openLevel(File var1) {
+ if(!var1.getName().endsWith(".mine")) {
+ var1 = new File(var1.getParentFile(), var1.getName() + ".mine");
+ }
+
+ File var2 = var1;
+ Minecraft var3 = this.minecraft;
+ this.minecraft.levelIo.save(var3.level, var2);
+ this.minecraft.setCurrentScreen(this.parent);
+ }
+
+ protected final void openLevel(int var1) {
+ this.minecraft.setCurrentScreen(new LevelNameScreen(this, ((Button)this.buttons.get(var1)).text, var1));
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/gui/Screen.java b/src/main/java/com/mojang/minecraft/gui/Screen.java
new file mode 100644
index 0000000..c44cdae
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/gui/Screen.java
@@ -0,0 +1,75 @@
+package com.mojang.minecraft.gui;
+
+import com.mojang.minecraft.gui.FontRenderer;
+import com.mojang.minecraft.render.ShapeRenderer;
+import org.lwjgl.opengl.GL11;
+
+public class Screen {
+
+ protected float imgZ = 0.0F;
+
+
+ protected static void drawBox(int var0, int var1, int var2, int var3, int var4) {
+ float var5 = (float)(var4 >>> 24) / 255.0F;
+ float var6 = (float)(var4 >> 16 & 255) / 255.0F;
+ float var7 = (float)(var4 >> 8 & 255) / 255.0F;
+ float var9 = (float)(var4 & 255) / 255.0F;
+ ShapeRenderer var8 = ShapeRenderer.instance;
+ GL11.glEnable(3042);
+ GL11.glDisable(3553);
+ GL11.glBlendFunc(770, 771);
+ GL11.glColor4f(var6, var7, var9, var5);
+ var8.begin();
+ var8.vertex((float)var0, (float)var3, 0.0F);
+ var8.vertex((float)var2, (float)var3, 0.0F);
+ var8.vertex((float)var2, (float)var1, 0.0F);
+ var8.vertex((float)var0, (float)var1, 0.0F);
+ var8.end();
+ GL11.glEnable(3553);
+ GL11.glDisable(3042);
+ }
+
+ protected static void drawFadingBox(int var0, int var1, int var2, int var3, int var4, int var5) {
+ float var6 = (float)(var4 >>> 24) / 255.0F;
+ float var7 = (float)(var4 >> 16 & 255) / 255.0F;
+ float var8 = (float)(var4 >> 8 & 255) / 255.0F;
+ float var12 = (float)(var4 & 255) / 255.0F;
+ float var9 = (float)(var5 >>> 24) / 255.0F;
+ float var10 = (float)(var5 >> 16 & 255) / 255.0F;
+ float var11 = (float)(var5 >> 8 & 255) / 255.0F;
+ float var13 = (float)(var5 & 255) / 255.0F;
+ GL11.glDisable(3553);
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 771);
+ GL11.glBegin(7);
+ GL11.glColor4f(var7, var8, var12, var6);
+ GL11.glVertex2f((float)var2, (float)var1);
+ GL11.glVertex2f((float)var0, (float)var1);
+ GL11.glColor4f(var10, var11, var13, var9);
+ GL11.glVertex2f((float)var0, (float)var3);
+ GL11.glVertex2f((float)var2, (float)var3);
+ GL11.glEnd();
+ GL11.glDisable(3042);
+ GL11.glEnable(3553);
+ }
+
+ public static void drawCenteredString(FontRenderer var0, String var1, int var2, int var3, int var4) {
+ var0.render(var1, var2 - var0.getWidth(var1) / 2, var3, var4);
+ }
+
+ public static void drawString(FontRenderer var0, String var1, int var2, int var3, int var4) {
+ var0.render(var1, var2, var3, var4);
+ }
+
+ public final void drawImage(int var1, int var2, int var3, int var4, int var5, int var6) {
+ float var7 = 0.00390625F;
+ float var8 = 0.00390625F;
+ ShapeRenderer var9 = ShapeRenderer.instance;
+ ShapeRenderer.instance.begin();
+ var9.vertexUV((float)var1, (float)(var2 + var6), this.imgZ, (float)var3 * var7, (float)(var4 + var6) * var8);
+ var9.vertexUV((float)(var1 + var5), (float)(var2 + var6), this.imgZ, (float)(var3 + var5) * var7, (float)(var4 + var6) * var8);
+ var9.vertexUV((float)(var1 + var5), (float)var2, this.imgZ, (float)(var3 + var5) * var7, (float)var4 * var8);
+ var9.vertexUV((float)var1, (float)var2, this.imgZ, (float)var3 * var7, (float)var4 * var8);
+ var9.end();
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/item/Arrow.java b/src/main/java/com/mojang/minecraft/item/Arrow.java
new file mode 100644
index 0000000..641ab27
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/item/Arrow.java
@@ -0,0 +1,294 @@
+package com.mojang.minecraft.item;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import java.util.List;
+import org.lwjgl.opengl.GL11;
+
+public class Arrow extends Entity
+{
+ public Arrow(Level level1, Entity owner, float x, float y, float z, float unknown0, float unknown1, float unknown2)
+ {
+ super(level1);
+
+ this.owner = owner;
+
+ setSize(0.3F, 0.5F);
+
+ heightOffset = bbHeight / 2.0F;
+ damage = 3;
+
+ if(!(owner instanceof Player))
+ {
+ type = 1;
+ } else {
+ damage = 7;
+ }
+
+ heightOffset = 0.25F;
+
+ float unknown3 = MathHelper.cos(-unknown0 * 0.017453292F - 3.1415927F);
+ float unknown4 = MathHelper.sin(-unknown0 * 0.017453292F - 3.1415927F);
+
+ unknown0 = MathHelper.cos(-unknown1 * 0.017453292F);
+ unknown1 = MathHelper.sin(-unknown1 * 0.017453292F);
+
+ slide = false;
+
+ gravity = 1.0F / unknown2;
+
+ xo -= unknown3 * 0.2F;
+ zo += unknown4 * 0.2F;
+
+ x -= unknown3 * 0.2F;
+ z += unknown4 * 0.2F;
+
+ xd = unknown4 * unknown0 * unknown2;
+ yd = unknown1 * unknown2;
+ zd = unknown3 * unknown0 * unknown2;
+
+ setPos(x, y, z);
+
+ unknown3 = MathHelper.sqrt(xd * xd + zd * zd);
+
+ yRotO = yRot = (float)(Math.atan2((double)xd, (double)zd) * 180.0D / 3.1415927410125732D);
+ xRotO = xRot = (float)(Math.atan2((double)yd, (double)unknown3) * 180.0D / 3.1415927410125732D);
+
+ makeStepSound = false;
+ }
+
+ @Override
+ public void tick()
+ {
+ time++;
+
+ xRotO = xRot;
+ yRotO = yRot;
+
+ xo = x;
+ yo = y;
+ zo = z;
+
+ if(hasHit)
+ {
+ stickTime++;
+
+ if(type == 0)
+ {
+ if(stickTime >= 300 && Math.random() < 0.009999999776482582D)
+ {
+ remove();
+ }
+ } else if(type == 1 && stickTime >= 20) {
+ remove();
+ }
+ } else {
+ xd *= 0.998F;
+ yd *= 0.998F;
+ zd *= 0.998F;
+
+ yd -= 0.02F * gravity;
+
+ int unknown0 = (int)(MathHelper.sqrt(xd * xd + yd * yd + zd * zd) / 0.2F + 1.0F);
+
+ float x0 = xd / (float)unknown0;
+ float y0 = yd / (float)unknown0;
+ float z0 = zd / (float)unknown0;
+
+ for(int unknown4 = 0; unknown4 < unknown0 && !collision; unknown4++)
+ {
+ AABB unknown5 = bb.expand(x0, y0, z0);
+
+ if(level.getCubes(unknown5).size() > 0)
+ {
+ collision = true;
+ }
+
+ List blockMapEntitiesList = level.blockMap.getEntities(this, unknown5);
+
+ for(int currentEntity = 0; currentEntity < blockMapEntitiesList.size(); currentEntity++)
+ {
+ Entity entity = (Entity)blockMapEntitiesList.get(currentEntity);
+
+ if((entity).isShootable() && (entity != owner || time > 5))
+ {
+ entity.hurt(this, damage);
+
+ collision = true;
+
+ remove();
+
+ return;
+ }
+ }
+
+ if(!collision)
+ {
+ bb.move(x0, y0, z0);
+
+ x += x0;
+ y += y0;
+ z += z0;
+
+ blockMap.moved(this);
+ }
+ }
+
+ if(collision)
+ {
+ hasHit = true;
+
+ xd = yd = zd = 0.0F;
+ }
+
+ if(!hasHit)
+ {
+ float unknown6 = MathHelper.sqrt(xd * xd + zd * zd);
+
+ yRot = (float)(Math.atan2((double)xd, (double)zd) * 180.0D / 3.1415927410125732D);
+
+ for(xRot = (float)(Math.atan2((double)yd, (double)unknown6) * 180.0D / 3.1415927410125732D); xRot - xRotO < -180.0F; xRotO -= 360.0F)
+ {
+ // TODO: ?.
+ }
+
+ while(xRot - xRotO >= 180.0F)
+ {
+ xRotO += 360.0F;
+ }
+
+ while(yRot - yRotO < -180.0F)
+ {
+ yRotO -= 360.0F;
+ }
+
+ while(yRot - yRotO >= 180.0F)
+ {
+ yRotO += 360.0F;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void render(TextureManager textureManager, float unknown0)
+ {
+ textureId = textureManager.load("/item/arrows.png");
+
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
+
+ float brightness = level.getBrightness((int)x, (int)y, (int)z);
+
+ GL11.glPushMatrix();
+ GL11.glColor4f(brightness, brightness, brightness, 1.0F);
+ GL11.glTranslatef(xo + (x - xo) * unknown0, this.yo + (this.y - this.yo) * unknown0 - this.heightOffset / 2.0F, this.zo + (this.z - this.zo) * unknown0);
+ GL11.glRotatef(yRotO + (yRot - yRotO) * unknown0 - 90.0F, 0.0F, 1.0F, 0.0F);
+ GL11.glRotatef(xRotO + (xRot - xRotO) * unknown0, 0.0F, 0.0F, 1.0F);
+ GL11.glRotatef(45.0F, 1.0F, 0.0F, 0.0F);
+
+ ShapeRenderer shapeRenderer = ShapeRenderer.instance;
+
+ unknown0 = 0.5F;
+
+ float unknown1 = (float)(0 + type * 10) / 32.0F;
+ float unknown2 = (float)(5 + type * 10) / 32.0F;
+ float unknown3 = 0.15625F;
+
+ float unknown4 = (float)(5 + type * 10) / 32.0F;
+ float unknown5 = (float)(10 + type * 10) / 32.0F;
+ float unknown6 = 0.05625F;
+
+ GL11.glScalef(0.05625F, unknown6, unknown6);
+
+ GL11.glNormal3f(unknown6, 0.0F, 0.0F);
+
+ shapeRenderer.begin();
+ shapeRenderer.vertexUV(-7.0F, -2.0F, -2.0F, 0.0F, unknown4);
+ shapeRenderer.vertexUV(-7.0F, -2.0F, 2.0F, unknown3, unknown4);
+ shapeRenderer.vertexUV(-7.0F, 2.0F, 2.0F, unknown3, unknown5);
+ shapeRenderer.vertexUV(-7.0F, 2.0F, -2.0F, 0.0F, unknown5);
+ shapeRenderer.end();
+
+ GL11.glNormal3f(-unknown6, 0.0F, 0.0F);
+
+ shapeRenderer.begin();
+ shapeRenderer.vertexUV(-7.0F, 2.0F, -2.0F, 0.0F, unknown4);
+ shapeRenderer.vertexUV(-7.0F, 2.0F, 2.0F, unknown3, unknown4);
+ shapeRenderer.vertexUV(-7.0F, -2.0F, 2.0F, unknown3, unknown5);
+ shapeRenderer.vertexUV(-7.0F, -2.0F, -2.0F, 0.0F, unknown5);
+ shapeRenderer.end();
+
+ for(int unknown7 = 0; unknown7 < 4; unknown7++)
+ {
+ GL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);
+
+ GL11.glNormal3f(0.0F, -unknown6, 0.0F);
+
+ shapeRenderer.vertexUV(-8.0F, -2.0F, 0.0F, 0.0F, unknown1);
+ shapeRenderer.vertexUV(8.0F, -2.0F, 0.0F, unknown0, unknown1);
+ shapeRenderer.vertexUV(8.0F, 2.0F, 0.0F, unknown0, unknown2);
+ shapeRenderer.vertexUV(-8.0F, 2.0F, 0.0F, 0.0F, unknown2);
+ shapeRenderer.end();
+ }
+
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ GL11.glPopMatrix();
+ }
+
+ @Override
+ public void playerTouch(Entity entity)
+ {
+ Player player = (Player)entity;
+
+ if(hasHit && owner == player && player.arrows < 99)
+ {
+ TakeEntityAnim takeEntityAnim = new TakeEntityAnim(level, this, player);
+
+ level.addEntity(takeEntityAnim);
+
+ player.arrows++;
+
+ remove();
+ }
+ }
+
+ @Override
+ public void awardKillScore(Entity entity, int score)
+ {
+ owner.awardKillScore(entity, score);
+ }
+
+ public static final long serialVersionUID = 0L;
+
+ private float xd;
+ private float yd;
+ private float zd;
+
+ private float yRot;
+ private float xRot;
+ private float yRotO;
+ private float xRotO;
+
+ private boolean hasHit = false;
+
+ private int stickTime = 0;
+
+ private Entity owner;
+
+ private int time = 0;
+ private int type = 0;
+
+ private float gravity = 0.0F;
+
+ private int damage;
+
+ public Entity getOwner()
+ {
+ return owner;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/item/Item.java b/src/main/java/com/mojang/minecraft/item/Item.java
new file mode 100644
index 0000000..650cb9f
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/item/Item.java
@@ -0,0 +1,149 @@
+package com.mojang.minecraft.item;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import org.lwjgl.opengl.GL11;
+
+public class Item extends Entity
+{
+ public Item(Level level1, float x, float y, float z, int block)
+ {
+ super(level1);
+
+ setSize(0.25F, 0.25F);
+
+ heightOffset = bbHeight / 2.0F;
+
+ setPos(x, y, z);
+
+ resource = block;
+
+ rot = (float)(Math.random() * 360.0D);
+
+ xd = (float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D);
+ yd = 0.2F;
+ zd = (float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D);
+
+ makeStepSound = false;
+ }
+
+ @Override
+ public void tick()
+ {
+ xo = x;
+ yo = y;
+ zo = z;
+
+ yd -= 0.04F;
+
+ move(xd, yd, zd);
+
+ xd *= 0.98F;
+ yd *= 0.98F;
+ zd *= 0.98F;
+
+ if(onGround)
+ {
+ xd *= 0.7F;
+ zd *= 0.7F;
+ yd *= -0.5F;
+ }
+
+ tickCount++;
+
+ age++;
+
+ if(age >= 6000)
+ {
+ remove();
+ }
+ }
+
+ @Override
+ public void render(TextureManager textureManager, float unknown0)
+ {
+ textureId = textureManager.load("/terrain.png");
+
+ GL11.glBindTexture(3553, this.textureId);
+
+ float brightness = level.getBrightness((int)x, (int)y, (int)z);
+ float unknown1 = rot + ((float)tickCount + unknown0) * 3.0F;
+
+ GL11.glPushMatrix();
+ GL11.glColor4f(brightness, brightness, brightness, 1.0F);
+
+ float unknown2 = (brightness = MathHelper.sin(unknown1 / 10.0F)) * 0.1F + 0.1F;
+
+ GL11.glTranslatef(xo + (x - xo) * unknown0, yo + (y - yo) * unknown0 + unknown2, zo + (z - zo) * unknown0);
+ GL11.glRotatef(unknown1, 0.0F, 1.0F, 0.0F);
+
+ models[resource].generateList();
+
+ brightness = (brightness = (brightness = brightness * 0.5F + 0.5F) * brightness) * brightness;
+
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, brightness * 0.4F);
+ GL11.glDisable(3553);
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 1);
+ GL11.glDisable(3008);
+
+ models[resource].generateList();
+
+ GL11.glEnable(3008);
+ GL11.glDisable(3042);
+ GL11.glBlendFunc(770, 771);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ GL11.glPopMatrix();
+ GL11.glEnable(3553);
+ }
+
+ @Override
+ public void playerTouch(Entity entity)
+ {
+ Player player = (Player)entity;
+
+ if(player.addResource(resource))
+ {
+ TakeEntityAnim takeEntityAnim = new TakeEntityAnim(level, this, player);
+
+ level.addEntity(takeEntityAnim);
+
+ remove();
+ }
+
+ }
+
+ public static final long serialVersionUID = 0L;
+
+ private static ItemModel[] models = new ItemModel[256];
+
+ private float xd;
+ private float yd;
+ private float zd;
+
+ private float rot;
+
+ private int resource;
+
+ private int tickCount;
+
+ private int age = 0;
+
+ public static void initModels()
+ {
+ for(int unknown0 = 0; unknown0 < 256; unknown0++)
+ {
+ Block var1 = Block.blocks[unknown0];
+
+ if(var1 != null)
+ {
+ models[unknown0] = new ItemModel(var1.textureId);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/item/ItemModel.java b/src/main/java/com/mojang/minecraft/item/ItemModel.java
new file mode 100644
index 0000000..d9a3693
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/item/ItemModel.java
@@ -0,0 +1,62 @@
+package com.mojang.minecraft.item;
+
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.minecraft.model.TexturedQuad;
+import com.mojang.minecraft.model.Vertex;
+
+public class ItemModel
+{
+ public ItemModel(int tex)
+ {
+ float var3 = -2.0F;
+ float var4 = -2.0F;
+ float var15 = -2.0F;
+
+ model.vertices = new Vertex[8];
+ model.quads = new TexturedQuad[6];
+
+ Vertex vertex1 = new Vertex(var15, var4, var3, 0.0F, 0.0F);
+ Vertex vertex2 = new Vertex(2.0F, var4, var3, 0.0F, 8.0F);
+ Vertex vertex3 = new Vertex(2.0F, 2.0F, var3, 8.0F, 8.0F);
+ Vertex vertex4 = new Vertex(var15, 2.0F, var3, 8.0F, 0.0F);
+ Vertex vertex5 = new Vertex(var15, var4, 2.0F, 0.0F, 0.0F);
+ Vertex vertex6 = new Vertex(2.0F, var4, 2.0F, 0.0F, 8.0F);
+ Vertex vertex7 = new Vertex(2.0F, 2.0F, 2.0F, 8.0F, 8.0F);
+ Vertex vertex8 = new Vertex(var15, 2.0F, 2.0F, 8.0F, 0.0F);
+
+ model.vertices[0] = vertex1;
+ model.vertices[1] = vertex2;
+ model.vertices[2] = vertex3;
+ model.vertices[3] = vertex4;
+ model.vertices[4] = vertex5;
+ model.vertices[5] = vertex6;
+ model.vertices[6] = vertex7;
+ model.vertices[7] = vertex8;
+
+ float u1 = ((float)(tex % 16) + (1.0F - 0.25F)) / 16.0F;
+ float v1 = ((float)(tex / 16) + (1.0F - 0.25F)) / 16.0F;
+ float u2 = ((float)(tex % 16) + 0.25F) / 16.0F;
+ float v2 = ((float)(tex / 16) + 0.25F) / 16.0F;
+
+ Vertex[] vertexes1 = new Vertex[] {vertex6, vertex2, vertex3, vertex7};
+ Vertex[] vertexes2 = new Vertex[] {vertex1, vertex5, vertex8, vertex4};
+ Vertex[] vertexes3 = new Vertex[] {vertex6, vertex5, vertex1, vertex2};
+ Vertex[] vertexes4 = new Vertex[] {vertex3, vertex4, vertex8, vertex7};
+ Vertex[] vertexes5 = new Vertex[] {vertex2, vertex1, vertex4, vertex3};
+ Vertex[] vertexes6 = new Vertex[] {vertex5, vertex6, vertex7, vertex8};
+
+ model.quads[0] = new TexturedQuad(vertexes1, u1, v1, u2, v2);
+ model.quads[1] = new TexturedQuad(vertexes2, u1, v1, u2, v2);
+ model.quads[2] = new TexturedQuad(vertexes3, u1, v1, u2, v2);
+ model.quads[3] = new TexturedQuad(vertexes4, u1, v1, u2, v2);
+ model.quads[4] = new TexturedQuad(vertexes5, u1, v1, u2, v2);
+ model.quads[5] = new TexturedQuad(vertexes6, u1, v1, u2, v2);
+ }
+
+ private ModelPart model = new ModelPart(0, 0);
+
+ public void generateList()
+ {
+ model.render(0.0625F);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/item/PrimedTnt.java b/src/main/java/com/mojang/minecraft/item/PrimedTnt.java
new file mode 100644
index 0000000..814d511
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/item/PrimedTnt.java
@@ -0,0 +1,192 @@
+package com.mojang.minecraft.item;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.particle.SmokeParticle;
+import com.mojang.minecraft.particle.TerrainParticle;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import java.util.Random;
+import org.lwjgl.opengl.GL11;
+
+public class PrimedTnt extends Entity
+{
+ public PrimedTnt(Level level1, float x, float y, float z)
+ {
+ super(level1);
+
+ setSize(0.98F, 0.98F);
+
+ heightOffset = bbHeight / 2.0F;
+
+ setPos(x, y, z);
+
+ float unknown0 = (float)(Math.random() * 3.1415927410125732D * 2.0D);
+
+ xd = -MathHelper.sin(unknown0 * 3.1415927F / 180.0F) * 0.02F;
+ yd = 0.2F;
+ zd = -MathHelper.cos(unknown0 * 3.1415927F / 180.0F) * 0.02F;
+
+ makeStepSound = false;
+
+ life = 40;
+
+ xo = x;
+ yo = y;
+ zo = z;
+ }
+
+ @Override
+ public void tick()
+ {
+ xo = x;
+ yo = y;
+ zo = z;
+
+ yd -= 0.04F;
+
+ move(xd, yd, zd);
+
+ xd *= 0.98F;
+ yd *= 0.98F;
+ zd *= 0.98F;
+
+ if(onGround)
+ {
+ xd *= 0.7F;
+ zd *= 0.7F;
+ yd *= -0.5F;
+ }
+
+ if(!defused)
+ {
+ if(life-- > 0)
+ {
+ SmokeParticle smokeParticle = new SmokeParticle(level, x, y + 0.6F, z);
+
+ level.particleEngine.spawnParticle(smokeParticle);
+ } else {
+ remove();
+
+ Random random = new Random();
+ float radius = 4.0F;
+
+ level.explode(null, x, y, z, radius);
+
+ for(int i = 0; i < 100; i++)
+ {
+ float unknown0 = (float)random.nextGaussian() * radius / 4.0F;
+ float unknown1 = (float)random.nextGaussian() * radius / 4.0F;
+ float unknown2 = (float)random.nextGaussian() * radius / 4.0F;
+ float unknown3 = MathHelper.sqrt(unknown0 * unknown0 + unknown1 * unknown1 + unknown2 * unknown2);
+ float unknown4 = unknown0 / unknown3 / unknown3;
+ float unknown5 = unknown1 / unknown3 / unknown3;
+
+ unknown3 = unknown2 / unknown3 / unknown3;
+
+ TerrainParticle terrainParticle = new TerrainParticle(level, x + unknown0, y + unknown1, z + unknown2, unknown4, unknown5, unknown3, Block.TNT);
+
+ level.particleEngine.spawnParticle(terrainParticle);
+ }
+
+ }
+ }
+ }
+
+ @Override
+ public void render(TextureManager textureManager, float unknown0)
+ {
+ int textureID = textureManager.load("/terrain.png");
+
+ GL11.glBindTexture(3553, textureID);
+
+ float brightness = level.getBrightness((int)x, (int)y, (int)z);
+
+ GL11.glPushMatrix();
+ GL11.glColor4f(brightness, brightness, brightness, 1.0F);
+ GL11.glTranslatef(xo + (x - xo) * unknown0 - 0.5F, yo + (y - yo) * unknown0 - 0.5F, zo + (z - zo) * unknown0 - 0.5F);
+ GL11.glPushMatrix();
+
+ ShapeRenderer shapeRenderer = ShapeRenderer.instance;
+
+ Block.TNT.renderPreview(shapeRenderer);
+
+ GL11.glDisable(3553);
+ GL11.glDisable(2896);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, (float)((life / 4 + 1) % 2) * 0.4F);
+
+ if(life <= 16)
+ {
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, (float)((life + 1) % 2) * 0.6F);
+ }
+
+ if(life <= 2)
+ {
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.9F);
+ }
+
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 1);
+
+ Block.TNT.renderPreview(shapeRenderer);
+
+ GL11.glDisable(3042);
+ GL11.glEnable(3553);
+ GL11.glEnable(2896);
+ GL11.glPopMatrix();
+ GL11.glPopMatrix();
+ }
+
+ @Override
+ public void playerTouch(Entity entity)
+ {
+ if(defused)
+ {
+ Player player = (Player)entity;
+
+ if(player.addResource(Block.TNT.id))
+ {
+ TakeEntityAnim takeEntityAnim = new TakeEntityAnim(this.level, this, player);
+
+ level.addEntity(takeEntityAnim);
+
+ remove();
+ }
+
+ }
+ }
+
+ @Override
+ public void hurt(Entity entity, int damage)
+ {
+ if(!removed)
+ {
+ super.hurt(entity, damage);
+
+ if(entity instanceof Player)
+ {
+ remove();
+
+ Item item = new Item(level, x, y, z, Block.TNT.id);
+
+ level.addEntity(item);
+ }
+
+ }
+ }
+
+ @Override
+ public boolean isPickable() {
+ return !this.removed;
+ }
+
+ public static final long serialVersionUID = 0L;
+ private float xd;
+ private float yd;
+ private float zd;
+ public int life = 0;
+ private boolean defused;
+}
diff --git a/src/main/java/com/mojang/minecraft/item/TakeEntityAnim.java b/src/main/java/com/mojang/minecraft/item/TakeEntityAnim.java
new file mode 100644
index 0000000..335cb13
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/item/TakeEntityAnim.java
@@ -0,0 +1,63 @@
+package com.mojang.minecraft.item;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.render.TextureManager;
+
+public class TakeEntityAnim extends Entity
+{
+ public TakeEntityAnim(Level level1, Entity item, Entity player)
+ {
+ super(level1);
+
+ this.item = item;
+ this.player = player;
+
+ setSize(1.0F, 1.0F);
+
+ xorg = item.x;
+ yorg = item.y;
+ zorg = item.z;
+ }
+
+ @Override
+ public void tick()
+ {
+ time++;
+
+ if(time >= 3)
+ {
+ remove();
+ }
+
+ // TODO: Is this right?
+ float distance = (distance = (float)time / 3.0F) * distance;
+
+ xo = item.xo = item.x;
+ yo = item.yo = item.y;
+ zo = item.zo = item.z;
+
+ x = item.x = xorg + (player.x - xorg) * distance;
+ y = item.y = yorg + (player.y - 1.0F - yorg) * distance;
+ z = item.z = zorg + (player.z - zorg) * distance;
+
+ setPos(x, y, z);
+ }
+
+ @Override
+ public void render(TextureManager textureManager, float unknown0)
+ {
+ item.render(textureManager, unknown0);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ private int time = 0;
+
+ private Entity item;
+ private Entity player;
+
+ private float xorg;
+ private float yorg;
+ private float zorg;
+}
diff --git a/src/main/java/com/mojang/minecraft/level/BlockMap$Slot.java b/src/main/java/com/mojang/minecraft/level/BlockMap$Slot.java
new file mode 100644
index 0000000..2267ecc
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/BlockMap$Slot.java
@@ -0,0 +1,86 @@
+package com.mojang.minecraft.level;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.BlockMap;
+import com.mojang.minecraft.level.SyntheticClass;
+import java.io.Serializable;
+
+class BlockMap$Slot implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ private int xSlot;
+ private int ySlot;
+ private int zSlot;
+ // $FF: synthetic field
+ final BlockMap blockMap;
+
+
+ private BlockMap$Slot(BlockMap var1) {
+ this.blockMap = var1;
+ }
+
+ public BlockMap$Slot init(float var1, float var2, float var3) {
+ this.xSlot = (int)(var1 / 16.0F);
+ this.ySlot = (int)(var2 / 16.0F);
+ this.zSlot = (int)(var3 / 16.0F);
+ if(this.xSlot < 0) {
+ this.xSlot = 0;
+ }
+
+ if(this.ySlot < 0) {
+ this.ySlot = 0;
+ }
+
+ if(this.zSlot < 0) {
+ this.zSlot = 0;
+ }
+
+ if(this.xSlot >= BlockMap.getWidth(this.blockMap)) {
+ this.xSlot = BlockMap.getWidth(this.blockMap) - 1;
+ }
+
+ if(this.ySlot >= BlockMap.getDepth(this.blockMap)) {
+ this.ySlot = BlockMap.getDepth(this.blockMap) - 1;
+ }
+
+ if(this.zSlot >= BlockMap.getHeight(this.blockMap)) {
+ this.zSlot = BlockMap.getHeight(this.blockMap) - 1;
+ }
+
+ return this;
+ }
+
+ public void add(Entity var1) {
+ if(this.xSlot >= 0 && this.ySlot >= 0 && this.zSlot >= 0) {
+ this.blockMap.entityGrid[(this.zSlot * BlockMap.getDepth(this.blockMap) + this.ySlot) * BlockMap.getWidth(this.blockMap) + this.xSlot].add(var1);
+ }
+
+ }
+
+ public void remove(Entity var1) {
+ if(this.xSlot >= 0 && this.ySlot >= 0 && this.zSlot >= 0) {
+ this.blockMap.entityGrid[(this.zSlot * BlockMap.getDepth(this.blockMap) + this.ySlot) * BlockMap.getWidth(this.blockMap) + this.xSlot].remove(var1);
+ }
+
+ }
+
+ // $FF: synthetic method
+ BlockMap$Slot(BlockMap var1, SyntheticClass var2) {
+ this(var1);
+ }
+
+ // $FF: synthetic method
+ static int getXSlot(BlockMap$Slot var0) {
+ return var0.xSlot;
+ }
+
+ // $FF: synthetic method
+ static int getYSlot(BlockMap$Slot var0) {
+ return var0.ySlot;
+ }
+
+ // $FF: synthetic method
+ static int getZSlot(BlockMap$Slot var0) {
+ return var0.zSlot;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/BlockMap.java b/src/main/java/com/mojang/minecraft/level/BlockMap.java
new file mode 100644
index 0000000..9d9f2ca
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/BlockMap.java
@@ -0,0 +1,280 @@
+package com.mojang.minecraft.level;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.BlockMap$Slot;
+import com.mojang.minecraft.level.SyntheticClass;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.render.Frustrum;
+import com.mojang.minecraft.render.TextureManager;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BlockMap implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ private int width;
+ private int depth;
+ private int height;
+ private BlockMap$Slot slot = new BlockMap$Slot(this, (SyntheticClass)null);
+ private BlockMap$Slot slot2 = new BlockMap$Slot(this, (SyntheticClass)null);
+ public List[] entityGrid;
+ public List all = new ArrayList();
+ private List tmp = new ArrayList();
+
+
+ public BlockMap(int var1, int var2, int var3) {
+ this.width = var1 / 16;
+ this.depth = var2 / 16;
+ this.height = var3 / 16;
+ if(this.width == 0) {
+ this.width = 1;
+ }
+
+ if(this.depth == 0) {
+ this.depth = 1;
+ }
+
+ if(this.height == 0) {
+ this.height = 1;
+ }
+
+ this.entityGrid = new ArrayList[this.width * this.depth * this.height];
+
+ for(var1 = 0; var1 < this.width; ++var1) {
+ for(var2 = 0; var2 < this.depth; ++var2) {
+ for(var3 = 0; var3 < this.height; ++var3) {
+ this.entityGrid[(var3 * this.depth + var2) * this.width + var1] = new ArrayList();
+ }
+ }
+ }
+
+ }
+
+ public void insert(Entity var1) {
+ this.all.add(var1);
+ this.slot.init(var1.x, var1.y, var1.z).add(var1);
+ var1.xOld = var1.x;
+ var1.yOld = var1.y;
+ var1.zOld = var1.z;
+ var1.blockMap = this;
+ }
+
+ public void remove(Entity var1) {
+ this.slot.init(var1.xOld, var1.yOld, var1.zOld).remove(var1);
+ this.all.remove(var1);
+ }
+
+ public void moved(Entity var1) {
+ BlockMap$Slot var2 = this.slot.init(var1.xOld, var1.yOld, var1.zOld);
+ BlockMap$Slot var3 = this.slot2.init(var1.x, var1.y, var1.z);
+ if(!var2.equals(var3)) {
+ var2.remove(var1);
+ var3.add(var1);
+ var1.xOld = var1.x;
+ var1.yOld = var1.y;
+ var1.zOld = var1.z;
+ }
+ }
+
+ public List getEntities(Entity var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ this.tmp.clear();
+ return this.getEntities(var1, var2, var3, var4, var5, var6, var7, this.tmp);
+ }
+
+ public List getEntities(Entity var1, float var2, float var3, float var4, float var5, float var6, float var7, List var8) {
+ BlockMap$Slot var9 = this.slot.init(var2, var3, var4);
+ BlockMap$Slot var10 = this.slot2.init(var5, var6, var7);
+
+ for(int var11 = BlockMap$Slot.getXSlot(var9) - 1; var11 <= BlockMap$Slot.getXSlot(var10) + 1; ++var11) {
+ for(int var12 = BlockMap$Slot.getYSlot(var9) - 1; var12 <= BlockMap$Slot.getYSlot(var10) + 1; ++var12) {
+ for(int var13 = BlockMap$Slot.getZSlot(var9) - 1; var13 <= BlockMap$Slot.getZSlot(var10) + 1; ++var13) {
+ if(var11 >= 0 && var12 >= 0 && var13 >= 0 && var11 < this.width && var12 < this.depth && var13 < this.height) {
+ List var14 = this.entityGrid[(var13 * this.depth + var12) * this.width + var11];
+
+ for(int var15 = 0; var15 < var14.size(); ++var15) {
+ Entity var16;
+ if((var16 = (Entity)var14.get(var15)) != var1 && var16.intersects(var2, var3, var4, var5, var6, var7)) {
+ var8.add(var16);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return var8;
+ }
+
+ public void removeAllNonCreativeModeEntities() {
+ for(int var1 = 0; var1 < this.width; ++var1) {
+ for(int var2 = 0; var2 < this.depth; ++var2) {
+ for(int var3 = 0; var3 < this.height; ++var3) {
+ List var4 = this.entityGrid[(var3 * this.depth + var2) * this.width + var1];
+
+ for(int var5 = 0; var5 < var4.size(); ++var5) {
+ if(!((Entity)var4.get(var5)).isCreativeModeAllowed()) {
+ var4.remove(var5--);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ public void clear() {
+ for(int var1 = 0; var1 < this.width; ++var1) {
+ for(int var2 = 0; var2 < this.depth; ++var2) {
+ for(int var3 = 0; var3 < this.height; ++var3) {
+ this.entityGrid[(var3 * this.depth + var2) * this.width + var1].clear();
+ }
+ }
+ }
+
+ }
+
+ public List getEntities(Entity var1, AABB var2) {
+ this.tmp.clear();
+ return this.getEntities(var1, var2.x0, var2.y0, var2.z0, var2.x1, var2.y1, var2.z1, this.tmp);
+ }
+
+ public List getEntities(Entity var1, AABB var2, List var3) {
+ return this.getEntities(var1, var2.x0, var2.y0, var2.z0, var2.x1, var2.y1, var2.z1, var3);
+ }
+
+ public void tickAll() {
+ for(int var1 = 0; var1 < this.all.size(); ++var1) {
+ Entity var2;
+ (var2 = (Entity)this.all.get(var1)).tick();
+ if(var2.removed) {
+ this.all.remove(var1--);
+ this.slot.init(var2.xOld, var2.yOld, var2.zOld).remove(var2);
+ } else {
+ int var3 = (int)(var2.xOld / 16.0F);
+ int var4 = (int)(var2.yOld / 16.0F);
+ int var5 = (int)(var2.zOld / 16.0F);
+ int var6 = (int)(var2.x / 16.0F);
+ int var7 = (int)(var2.y / 16.0F);
+ int var8 = (int)(var2.z / 16.0F);
+ if(var3 != var6 || var4 != var7 || var5 != var8) {
+ this.moved(var2);
+ }
+ }
+ }
+
+ }
+
+ public void render(Vec3D var1, Frustrum var2, TextureManager var3, float var4) {
+ for(int var5 = 0; var5 < this.width; ++var5) {
+ float var6 = (float)((var5 << 4) - 2);
+ float var7 = (float)((var5 + 1 << 4) + 2);
+
+ for(int var8 = 0; var8 < this.depth; ++var8) {
+ float var9 = (float)((var8 << 4) - 2);
+ float var10 = (float)((var8 + 1 << 4) + 2);
+
+ for(int var11 = 0; var11 < this.height; ++var11) {
+ List var12;
+ if((var12 = this.entityGrid[(var11 * this.depth + var8) * this.width + var5]).size() != 0) {
+ float var13 = (float)((var11 << 4) - 2);
+ float var14 = (float)((var11 + 1 << 4) + 2);
+ if(var2.isBoxInFrustrum(var6, var9, var13, var7, var10, var14)) {
+ float var16 = var14;
+ float var17 = var10;
+ float var15 = var7;
+ var14 = var13;
+ var13 = var9;
+ float var18 = var6;
+ Frustrum var19 = var2;
+ int var20 = 0;
+
+ boolean var10000;
+ while(true) {
+ if(var20 >= 6) {
+ var10000 = true;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var18 + var19.frustrum[var20][1] * var13 + var19.frustrum[var20][2] * var14 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var15 + var19.frustrum[var20][1] * var13 + var19.frustrum[var20][2] * var14 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var18 + var19.frustrum[var20][1] * var17 + var19.frustrum[var20][2] * var14 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var15 + var19.frustrum[var20][1] * var17 + var19.frustrum[var20][2] * var14 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var18 + var19.frustrum[var20][1] * var13 + var19.frustrum[var20][2] * var16 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var15 + var19.frustrum[var20][1] * var13 + var19.frustrum[var20][2] * var16 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var18 + var19.frustrum[var20][1] * var17 + var19.frustrum[var20][2] * var16 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ if(var19.frustrum[var20][0] * var15 + var19.frustrum[var20][1] * var17 + var19.frustrum[var20][2] * var16 + var19.frustrum[var20][3] <= 0.0F) {
+ var10000 = false;
+ break;
+ }
+
+ ++var20;
+ }
+
+ boolean var21 = var10000;
+
+ for(int var23 = 0; var23 < var12.size(); ++var23) {
+ Entity var22;
+ if((var22 = (Entity)var12.get(var23)).shouldRender(var1)) {
+ if(!var21) {
+ AABB var24 = var22.bb;
+ if(!var2.isBoxInFrustrum(var24.x0, var24.y0, var24.z0, var24.x1, var24.y1, var24.z1)) {
+ continue;
+ }
+ }
+
+ var22.render(var3, var4);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ // $FF: synthetic method
+ static int getWidth(BlockMap var0) {
+ return var0.width;
+ }
+
+ // $FF: synthetic method
+ static int getDepth(BlockMap var0) {
+ return var0.depth;
+ }
+
+ // $FF: synthetic method
+ static int getHeight(BlockMap var0) {
+ return var0.height;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/Level.java b/src/main/java/com/mojang/minecraft/level/Level.java
new file mode 100644
index 0000000..52e96cd
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/Level.java
@@ -0,0 +1,1013 @@
+package com.mojang.minecraft.level;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.MovingObjectPosition;
+import com.mojang.minecraft.level.BlockMap;
+import com.mojang.minecraft.level.NextTickListEntry;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.particle.ParticleManager;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.render.LevelRenderer;
+import com.mojang.minecraft.sound.AudioInfo;
+import com.mojang.minecraft.sound.EntitySoundPos;
+import com.mojang.minecraft.sound.LevelSoundPos;
+import com.mojang.util.MathHelper;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+public class Level implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ public int width;
+ public int height;
+ public int depth;
+ public byte[] blocks;
+ public String name;
+ public String creator;
+ public long createTime;
+ public int xSpawn;
+ public int ySpawn;
+ public int zSpawn;
+ public float rotSpawn;
+ private transient ArrayList listeners = new ArrayList();
+ private transient int[] blockers;
+ public transient Random random = new Random();
+ private transient int randId;
+ private transient ArrayList tickList;
+ public BlockMap blockMap;
+ private boolean networkMode;
+ public transient Minecraft rendererContext$5cd64a7f;
+ public boolean creativeMode;
+ public int waterLevel;
+ public int skyColor;
+ public int fogColor;
+ public int cloudColor;
+ int unprocessed;
+ private int tickCount;
+ public Entity player;
+ public transient ParticleManager particleEngine;
+ public transient Object font;
+ public boolean growTrees;
+
+
+ public Level() {
+ this.randId = this.random.nextInt();
+ this.tickList = new ArrayList();
+ this.networkMode = false;
+ this.unprocessed = 0;
+ this.tickCount = 0;
+ this.growTrees = false;
+ }
+
+ public void initTransient() {
+ if(this.blocks == null) {
+ throw new RuntimeException("The level is corrupt!");
+ } else {
+ this.listeners = new ArrayList();
+ this.blockers = new int[this.width * this.height];
+ Arrays.fill(this.blockers, this.depth);
+ this.calcLightDepths(0, 0, this.width, this.height);
+ this.random = new Random();
+ this.randId = this.random.nextInt();
+ this.tickList = new ArrayList();
+ if(this.waterLevel == 0) {
+ this.waterLevel = this.depth / 2;
+ }
+
+ if(this.skyColor == 0) {
+ this.skyColor = 10079487;
+ }
+
+ if(this.fogColor == 0) {
+ this.fogColor = 16777215;
+ }
+
+ if(this.cloudColor == 0) {
+ this.cloudColor = 16777215;
+ }
+
+ if(this.xSpawn == 0 && this.ySpawn == 0 && this.zSpawn == 0) {
+ this.findSpawn();
+ }
+
+ if(this.blockMap == null) {
+ this.blockMap = new BlockMap(this.width, this.depth, this.height);
+ }
+
+ }
+ }
+
+ public void setData(int var1, int var2, int var3, byte[] var4) {
+ this.width = var1;
+ this.height = var3;
+ this.depth = var2;
+ this.blocks = var4;
+ this.blockers = new int[var1 * var3];
+ Arrays.fill(this.blockers, this.depth);
+ this.calcLightDepths(0, 0, var1, var3);
+
+ for(var1 = 0; var1 < this.listeners.size(); ++var1) {
+ ((LevelRenderer)this.listeners.get(var1)).refresh();
+ }
+
+ this.tickList.clear();
+ this.findSpawn();
+ this.initTransient();
+ System.gc();
+ }
+
+ public void findSpawn() {
+ Random var1 = new Random();
+ int var2 = 0;
+
+ int var3;
+ int var4;
+ int var5;
+ do {
+ ++var2;
+ var3 = var1.nextInt(this.width / 2) + this.width / 4;
+ var4 = var1.nextInt(this.height / 2) + this.height / 4;
+ var5 = this.getHighestTile(var3, var4) + 1;
+ if(var2 == 10000) {
+ this.xSpawn = var3;
+ this.ySpawn = -100;
+ this.zSpawn = var4;
+ return;
+ }
+ } while((float)var5 <= this.getWaterLevel());
+
+ this.xSpawn = var3;
+ this.ySpawn = var5;
+ this.zSpawn = var4;
+ }
+
+ public void calcLightDepths(int var1, int var2, int var3, int var4) {
+ for(int var5 = var1; var5 < var1 + var3; ++var5) {
+ for(int var6 = var2; var6 < var2 + var4; ++var6) {
+ int var7 = this.blockers[var5 + var6 * this.width];
+
+ int var8;
+ for(var8 = this.depth - 1; var8 > 0 && !this.isLightBlocker(var5, var8, var6); --var8) {
+ ;
+ }
+
+ this.blockers[var5 + var6 * this.width] = var8;
+ if(var7 != var8) {
+ int var9 = var7 < var8?var7:var8;
+ var7 = var7 > var8?var7:var8;
+
+ for(var8 = 0; var8 < this.listeners.size(); ++var8) {
+ ((LevelRenderer)this.listeners.get(var8)).queueChunks(var5 - 1, var9 - 1, var6 - 1, var5 + 1, var7 + 1, var6 + 1);
+ }
+ }
+ }
+ }
+
+ }
+
+ public void addListener(LevelRenderer var1) {
+ this.listeners.add(var1);
+ }
+
+ public void finalize() {}
+
+ public void removeListener(LevelRenderer var1) {
+ this.listeners.remove(var1);
+ }
+
+ public boolean isLightBlocker(int var1, int var2, int var3) {
+ Block var4;
+ return (var4 = Block.blocks[this.getTile(var1, var2, var3)]) == null?false:var4.isOpaque();
+ }
+
+ public ArrayList getCubes(AABB var1) {
+ ArrayList var2 = new ArrayList();
+ int var3 = (int)var1.x0;
+ int var4 = (int)var1.x1 + 1;
+ int var5 = (int)var1.y0;
+ int var6 = (int)var1.y1 + 1;
+ int var7 = (int)var1.z0;
+ int var8 = (int)var1.z1 + 1;
+ if(var1.x0 < 0.0F) {
+ --var3;
+ }
+
+ if(var1.y0 < 0.0F) {
+ --var5;
+ }
+
+ if(var1.z0 < 0.0F) {
+ --var7;
+ }
+
+ for(var3 = var3; var3 < var4; ++var3) {
+ for(int var9 = var5; var9 < var6; ++var9) {
+ for(int var10 = var7; var10 < var8; ++var10) {
+ AABB var11;
+ if(var3 >= 0 && var9 >= 0 && var10 >= 0 && var3 < this.width && var9 < this.depth && var10 < this.height) {
+ Block var12;
+ if((var12 = Block.blocks[this.getTile(var3, var9, var10)]) != null && (var11 = var12.getCollisionBox(var3, var9, var10)) != null && var1.intersectsInner(var11)) {
+ var2.add(var11);
+ }
+ } else if((var3 < 0 || var9 < 0 || var10 < 0 || var3 >= this.width || var10 >= this.height) && (var11 = Block.BEDROCK.getCollisionBox(var3, var9, var10)) != null && var1.intersectsInner(var11)) {
+ var2.add(var11);
+ }
+ }
+ }
+ }
+
+ return var2;
+ }
+
+ public void swap(int var1, int var2, int var3, int var4, int var5, int var6) {
+ if(!this.networkMode) {
+ int var7 = this.getTile(var1, var2, var3);
+ int var8 = this.getTile(var4, var5, var6);
+ this.setTileNoNeighborChange(var1, var2, var3, var8);
+ this.setTileNoNeighborChange(var4, var5, var6, var7);
+ this.updateNeighborsAt(var1, var2, var3, var8);
+ this.updateNeighborsAt(var4, var5, var6, var7);
+ }
+ }
+
+ public boolean setTileNoNeighborChange(int var1, int var2, int var3, int var4) {
+ return this.networkMode?false:this.netSetTileNoNeighborChange(var1, var2, var3, var4);
+ }
+
+ public boolean netSetTileNoNeighborChange(int var1, int var2, int var3, int var4) {
+ if(var1 >= 0 && var2 >= 0 && var3 >= 0 && var1 < this.width && var2 < this.depth && var3 < this.height) {
+ if(var4 == this.blocks[(var2 * this.height + var3) * this.width + var1]) {
+ return false;
+ } else {
+ if(var4 == 0 && (var1 == 0 || var3 == 0 || var1 == this.width - 1 || var3 == this.height - 1) && (float)var2 >= this.getGroundLevel() && (float)var2 < this.getWaterLevel()) {
+ var4 = Block.WATER.id;
+ }
+
+ byte var5 = this.blocks[(var2 * this.height + var3) * this.width + var1];
+ this.blocks[(var2 * this.height + var3) * this.width + var1] = (byte)var4;
+ if(var5 != 0) {
+ Block.blocks[var5].onRemoved(this, var1, var2, var3);
+ }
+
+ if(var4 != 0) {
+ Block.blocks[var4].onAdded(this, var1, var2, var3);
+ }
+
+ this.calcLightDepths(var1, var3, 1, 1);
+
+ for(var4 = 0; var4 < this.listeners.size(); ++var4) {
+ ((LevelRenderer)this.listeners.get(var4)).queueChunks(var1 - 1, var2 - 1, var3 - 1, var1 + 1, var2 + 1, var3 + 1);
+ }
+
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public boolean setTile(int var1, int var2, int var3, int var4) {
+ if(this.networkMode) {
+ return false;
+ } else if(this.setTileNoNeighborChange(var1, var2, var3, var4)) {
+ this.updateNeighborsAt(var1, var2, var3, var4);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean netSetTile(int var1, int var2, int var3, int var4) {
+ if(this.netSetTileNoNeighborChange(var1, var2, var3, var4)) {
+ this.updateNeighborsAt(var1, var2, var3, var4);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void updateNeighborsAt(int var1, int var2, int var3, int var4) {
+ this.updateTile(var1 - 1, var2, var3, var4);
+ this.updateTile(var1 + 1, var2, var3, var4);
+ this.updateTile(var1, var2 - 1, var3, var4);
+ this.updateTile(var1, var2 + 1, var3, var4);
+ this.updateTile(var1, var2, var3 - 1, var4);
+ this.updateTile(var1, var2, var3 + 1, var4);
+ }
+
+ public boolean setTileNoUpdate(int var1, int var2, int var3, int var4) {
+ if(var1 >= 0 && var2 >= 0 && var3 >= 0 && var1 < this.width && var2 < this.depth && var3 < this.height) {
+ if(var4 == this.blocks[(var2 * this.height + var3) * this.width + var1]) {
+ return false;
+ } else {
+ this.blocks[(var2 * this.height + var3) * this.width + var1] = (byte)var4;
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private void updateTile(int var1, int var2, int var3, int var4) {
+ if(var1 >= 0 && var2 >= 0 && var3 >= 0 && var1 < this.width && var2 < this.depth && var3 < this.height) {
+ Block var5;
+ if((var5 = Block.blocks[this.blocks[(var2 * this.height + var3) * this.width + var1]]) != null) {
+ var5.onNeighborChange(this, var1, var2, var3, var4);
+ }
+
+ }
+ }
+
+ public boolean isLit(int var1, int var2, int var3) {
+ return var1 >= 0 && var2 >= 0 && var3 >= 0 && var1 < this.width && var2 < this.depth && var3 < this.height?var2 >= this.blockers[var1 + var3 * this.width]:true;
+ }
+
+ public int getTile(int var1, int var2, int var3) {
+ return var1 >= 0 && var2 >= 0 && var3 >= 0 && var1 < this.width && var2 < this.depth && var3 < this.height?this.blocks[(var2 * this.height + var3) * this.width + var1] & 255:0;
+ }
+
+ public boolean isSolidTile(int var1, int var2, int var3) {
+ Block var4;
+ return (var4 = Block.blocks[this.getTile(var1, var2, var3)]) == null?false:var4.isSolid();
+ }
+
+ public void tickEntities() {
+ this.blockMap.tickAll();
+ }
+
+ public void tick() {
+ ++this.tickCount;
+ int var1 = 1;
+
+ int var2;
+ for(var2 = 1; 1 << var1 < this.width; ++var1) {
+ ;
+ }
+
+ while(1 << var2 < this.height) {
+ ++var2;
+ }
+
+ int var3 = this.height - 1;
+ int var4 = this.width - 1;
+ int var5 = this.depth - 1;
+ int var6;
+ int var7;
+ if(this.tickCount % 5 == 0) {
+ var6 = this.tickList.size();
+
+ for(var7 = 0; var7 < var6; ++var7) {
+ NextTickListEntry var8;
+ if((var8 = (NextTickListEntry)this.tickList.remove(0)).ticks > 0) {
+ --var8.ticks;
+ this.tickList.add(var8);
+ } else {
+ byte var9;
+ if(this.isInBounds(var8.x, var8.y, var8.z) && (var9 = this.blocks[(var8.y * this.height + var8.z) * this.width + var8.x]) == var8.block && var9 > 0) {
+ Block.blocks[var9].update(this, var8.x, var8.y, var8.z, this.random);
+ }
+ }
+ }
+ }
+
+ this.unprocessed += this.width * this.height * this.depth;
+ var6 = this.unprocessed / 200;
+ this.unprocessed -= var6 * 200;
+
+ for(var7 = 0; var7 < var6; ++var7) {
+ this.randId = this.randId * 3 + 1013904223;
+ int var12;
+ int var13 = (var12 = this.randId >> 2) & var4;
+ int var10 = var12 >> var1 & var3;
+ var12 = var12 >> var1 + var2 & var5;
+ byte var11 = this.blocks[(var12 * this.height + var10) * this.width + var13];
+ if(Block.physics[var11]) {
+ Block.blocks[var11].update(this, var13, var12, var10, this.random);
+ }
+ }
+
+ }
+
+ public int countInstanceOf(Class var1) {
+ int var2 = 0;
+
+ for(int var3 = 0; var3 < this.blockMap.all.size(); ++var3) {
+ Entity var4 = (Entity)this.blockMap.all.get(var3);
+ if(var1.isAssignableFrom(var4.getClass())) {
+ ++var2;
+ }
+ }
+
+ return var2;
+ }
+
+ private boolean isInBounds(int var1, int var2, int var3) {
+ return var1 >= 0 && var2 >= 0 && var3 >= 0 && var1 < this.width && var2 < this.depth && var3 < this.height;
+ }
+
+ public float getGroundLevel() {
+ return this.getWaterLevel() - 2.0F;
+ }
+
+ public float getWaterLevel() {
+ return (float)this.waterLevel;
+ }
+
+ public boolean containsAnyLiquid(AABB var1) {
+ int var2 = (int)var1.x0;
+ int var3 = (int)var1.x1 + 1;
+ int var4 = (int)var1.y0;
+ int var5 = (int)var1.y1 + 1;
+ int var6 = (int)var1.z0;
+ int var7 = (int)var1.z1 + 1;
+ if(var1.x0 < 0.0F) {
+ --var2;
+ }
+
+ if(var1.y0 < 0.0F) {
+ --var4;
+ }
+
+ if(var1.z0 < 0.0F) {
+ --var6;
+ }
+
+ if(var2 < 0) {
+ var2 = 0;
+ }
+
+ if(var4 < 0) {
+ var4 = 0;
+ }
+
+ if(var6 < 0) {
+ var6 = 0;
+ }
+
+ if(var3 > this.width) {
+ var3 = this.width;
+ }
+
+ if(var5 > this.depth) {
+ var5 = this.depth;
+ }
+
+ if(var7 > this.height) {
+ var7 = this.height;
+ }
+
+ for(int var10 = var2; var10 < var3; ++var10) {
+ for(var2 = var4; var2 < var5; ++var2) {
+ for(int var8 = var6; var8 < var7; ++var8) {
+ Block var9;
+ if((var9 = Block.blocks[this.getTile(var10, var2, var8)]) != null && var9.getLiquidType() != LiquidType.NOT_LIQUID) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public boolean containsLiquid(AABB var1, LiquidType var2) {
+ int var3 = (int)var1.x0;
+ int var4 = (int)var1.x1 + 1;
+ int var5 = (int)var1.y0;
+ int var6 = (int)var1.y1 + 1;
+ int var7 = (int)var1.z0;
+ int var8 = (int)var1.z1 + 1;
+ if(var1.x0 < 0.0F) {
+ --var3;
+ }
+
+ if(var1.y0 < 0.0F) {
+ --var5;
+ }
+
+ if(var1.z0 < 0.0F) {
+ --var7;
+ }
+
+ if(var3 < 0) {
+ var3 = 0;
+ }
+
+ if(var5 < 0) {
+ var5 = 0;
+ }
+
+ if(var7 < 0) {
+ var7 = 0;
+ }
+
+ if(var4 > this.width) {
+ var4 = this.width;
+ }
+
+ if(var6 > this.depth) {
+ var6 = this.depth;
+ }
+
+ if(var8 > this.height) {
+ var8 = this.height;
+ }
+
+ for(int var11 = var3; var11 < var4; ++var11) {
+ for(var3 = var5; var3 < var6; ++var3) {
+ for(int var9 = var7; var9 < var8; ++var9) {
+ Block var10;
+ if((var10 = Block.blocks[this.getTile(var11, var3, var9)]) != null && var10.getLiquidType() == var2) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public void addToTickNextTick(int var1, int var2, int var3, int var4) {
+ if(!this.networkMode) {
+ NextTickListEntry var5 = new NextTickListEntry(var1, var2, var3, var4);
+ if(var4 > 0) {
+ var3 = Block.blocks[var4].getTickDelay();
+ var5.ticks = var3;
+ }
+
+ this.tickList.add(var5);
+ }
+ }
+
+ public boolean isFree(AABB var1) {
+ return this.blockMap.getEntities((Entity)null, var1).size() == 0;
+ }
+
+ public List findEntities(Entity var1, AABB var2) {
+ return this.blockMap.getEntities(var1, var2);
+ }
+
+ public boolean isSolid(float var1, float var2, float var3, float var4) {
+ return this.isSolid(var1 - var4, var2 - var4, var3 - var4)?true:(this.isSolid(var1 - var4, var2 - var4, var3 + var4)?true:(this.isSolid(var1 - var4, var2 + var4, var3 - var4)?true:(this.isSolid(var1 - var4, var2 + var4, var3 + var4)?true:(this.isSolid(var1 + var4, var2 - var4, var3 - var4)?true:(this.isSolid(var1 + var4, var2 - var4, var3 + var4)?true:(this.isSolid(var1 + var4, var2 + var4, var3 - var4)?true:this.isSolid(var1 + var4, var2 + var4, var3 + var4)))))));
+ }
+
+ private boolean isSolid(float var1, float var2, float var3) {
+ int var4;
+ return (var4 = this.getTile((int)var1, (int)var2, (int)var3)) > 0 && Block.blocks[var4].isSolid();
+ }
+
+ public int getHighestTile(int var1, int var2) {
+ int var3;
+ for(var3 = this.depth; (this.getTile(var1, var3 - 1, var2) == 0 || Block.blocks[this.getTile(var1, var3 - 1, var2)].getLiquidType() != LiquidType.NOT_LIQUID) && var3 > 0; --var3) {
+ ;
+ }
+
+ return var3;
+ }
+
+ public void setSpawnPos(int var1, int var2, int var3, float var4) {
+ this.xSpawn = var1;
+ this.ySpawn = var2;
+ this.zSpawn = var3;
+ this.rotSpawn = var4;
+ }
+
+ public float getBrightness(int var1, int var2, int var3) {
+ return this.isLit(var1, var2, var3)?1.0F:0.6F;
+ }
+
+ public float getCaveness(float var1, float var2, float var3, float var4) {
+ int var5 = (int)var1;
+ int var14 = (int)var2;
+ int var6 = (int)var3;
+ float var7 = 0.0F;
+ float var8 = 0.0F;
+
+ for(int var9 = var5 - 6; var9 <= var5 + 6; ++var9) {
+ for(int var10 = var6 - 6; var10 <= var6 + 6; ++var10) {
+ if(this.isInBounds(var9, var14, var10) && !this.isSolidTile(var9, var14, var10)) {
+ float var11 = (float)var9 + 0.5F - var1;
+
+ float var12;
+ float var13;
+ for(var13 = (float)(Math.atan2((double)(var12 = (float)var10 + 0.5F - var3), (double)var11) - (double)(var4 * 3.1415927F / 180.0F) + 1.5707963705062866D); var13 < -3.1415927F; var13 += 6.2831855F) {
+ ;
+ }
+
+ while(var13 >= 3.1415927F) {
+ var13 -= 6.2831855F;
+ }
+
+ if(var13 < 0.0F) {
+ var13 = -var13;
+ }
+
+ var11 = MathHelper.sqrt(var11 * var11 + 4.0F + var12 * var12);
+ var11 = 1.0F / var11;
+ if(var13 > 1.0F) {
+ var11 = 0.0F;
+ }
+
+ if(var11 < 0.0F) {
+ var11 = 0.0F;
+ }
+
+ var8 += var11;
+ if(this.isLit(var9, var14, var10)) {
+ var7 += var11;
+ }
+ }
+ }
+ }
+
+ if(var8 == 0.0F) {
+ return 0.0F;
+ } else {
+ return var7 / var8;
+ }
+ }
+
+ public float getCaveness(Entity var1) {
+ float var2 = MathHelper.cos(-var1.yRot * 0.017453292F + 3.1415927F);
+ float var3 = MathHelper.sin(-var1.yRot * 0.017453292F + 3.1415927F);
+ float var4 = MathHelper.cos(-var1.xRot * 0.017453292F);
+ float var5 = MathHelper.sin(-var1.xRot * 0.017453292F);
+ float var6 = var1.x;
+ float var7 = var1.y;
+ float var21 = var1.z;
+ float var8 = 1.6F;
+ float var9 = 0.0F;
+ float var10 = 0.0F;
+
+ for(int var11 = 0; var11 <= 200; ++var11) {
+ float var12 = ((float)var11 / (float)200 - 0.5F) * 2.0F;
+ int var13 = 0;
+
+ while(var13 <= 200) {
+ float var14 = ((float)var13 / (float)200 - 0.5F) * var8;
+ float var16 = var4 * var14 + var5;
+ var14 = var4 - var5 * var14;
+ float var17 = var2 * var12 + var3 * var14;
+ var16 = var16;
+ var14 = var2 * var14 - var3 * var12;
+ int var15 = 0;
+
+ while(true) {
+ if(var15 < 10) {
+ float var18 = var6 + var17 * (float)var15 * 0.8F;
+ float var19 = var7 + var16 * (float)var15 * 0.8F;
+ float var20 = var21 + var14 * (float)var15 * 0.8F;
+ if(!this.isSolid(var18, var19, var20)) {
+ ++var9;
+ if(this.isLit((int)var18, (int)var19, (int)var20)) {
+ ++var10;
+ }
+
+ ++var15;
+ continue;
+ }
+ }
+
+ ++var13;
+ break;
+ }
+ }
+ }
+
+ if(var9 == 0.0F) {
+ return 0.0F;
+ } else {
+ float var22;
+ if((var22 = var10 / var9 / 0.1F) > 1.0F) {
+ var22 = 1.0F;
+ }
+
+ var22 = 1.0F - var22;
+ return 1.0F - var22 * var22 * var22;
+ }
+ }
+
+ public byte[] copyBlocks() {
+ return Arrays.copyOf(this.blocks, this.blocks.length);
+ }
+
+ public LiquidType getLiquid(int var1, int var2, int var3) {
+ int var4;
+ return (var4 = this.getTile(var1, var2, var3)) == 0?LiquidType.NOT_LIQUID:Block.blocks[var4].getLiquidType();
+ }
+
+ public boolean isWater(int var1, int var2, int var3) {
+ int var4;
+ return (var4 = this.getTile(var1, var2, var3)) > 0 && Block.blocks[var4].getLiquidType() == LiquidType.WATER;
+ }
+
+ public void setNetworkMode(boolean var1) {
+ this.networkMode = var1;
+ }
+
+ public MovingObjectPosition clip(Vec3D var1, Vec3D var2) {
+ if(!Float.isNaN(var1.x) && !Float.isNaN(var1.y) && !Float.isNaN(var1.z)) {
+ if(!Float.isNaN(var2.x) && !Float.isNaN(var2.y) && !Float.isNaN(var2.z)) {
+ int var3 = (int)Math.floor((double)var2.x);
+ int var4 = (int)Math.floor((double)var2.y);
+ int var5 = (int)Math.floor((double)var2.z);
+ int var6 = (int)Math.floor((double)var1.x);
+ int var7 = (int)Math.floor((double)var1.y);
+ int var8 = (int)Math.floor((double)var1.z);
+ int var9 = 20;
+
+ while(var9-- >= 0) {
+ if(Float.isNaN(var1.x) || Float.isNaN(var1.y) || Float.isNaN(var1.z)) {
+ return null;
+ }
+
+ if(var6 == var3 && var7 == var4 && var8 == var5) {
+ return null;
+ }
+
+ float var10 = 999.0F;
+ float var11 = 999.0F;
+ float var12 = 999.0F;
+ if(var3 > var6) {
+ var10 = (float)var6 + 1.0F;
+ }
+
+ if(var3 < var6) {
+ var10 = (float)var6;
+ }
+
+ if(var4 > var7) {
+ var11 = (float)var7 + 1.0F;
+ }
+
+ if(var4 < var7) {
+ var11 = (float)var7;
+ }
+
+ if(var5 > var8) {
+ var12 = (float)var8 + 1.0F;
+ }
+
+ if(var5 < var8) {
+ var12 = (float)var8;
+ }
+
+ float var13 = 999.0F;
+ float var14 = 999.0F;
+ float var15 = 999.0F;
+ float var16 = var2.x - var1.x;
+ float var17 = var2.y - var1.y;
+ float var18 = var2.z - var1.z;
+ if(var10 != 999.0F) {
+ var13 = (var10 - var1.x) / var16;
+ }
+
+ if(var11 != 999.0F) {
+ var14 = (var11 - var1.y) / var17;
+ }
+
+ if(var12 != 999.0F) {
+ var15 = (var12 - var1.z) / var18;
+ }
+
+ boolean var19 = false;
+ byte var24;
+ if(var13 < var14 && var13 < var15) {
+ if(var3 > var6) {
+ var24 = 4;
+ } else {
+ var24 = 5;
+ }
+
+ var1.x = var10;
+ var1.y += var17 * var13;
+ var1.z += var18 * var13;
+ } else if(var14 < var15) {
+ if(var4 > var7) {
+ var24 = 0;
+ } else {
+ var24 = 1;
+ }
+
+ var1.x += var16 * var14;
+ var1.y = var11;
+ var1.z += var18 * var14;
+ } else {
+ if(var5 > var8) {
+ var24 = 2;
+ } else {
+ var24 = 3;
+ }
+
+ var1.x += var16 * var15;
+ var1.y += var17 * var15;
+ var1.z = var12;
+ }
+
+ Vec3D var20;
+ var6 = (int)((var20 = new Vec3D(var1.x, var1.y, var1.z)).x = (float)Math.floor((double)var1.x));
+ if(var24 == 5) {
+ --var6;
+ ++var20.x;
+ }
+
+ var7 = (int)(var20.y = (float)Math.floor((double)var1.y));
+ if(var24 == 1) {
+ --var7;
+ ++var20.y;
+ }
+
+ var8 = (int)(var20.z = (float)Math.floor((double)var1.z));
+ if(var24 == 3) {
+ --var8;
+ ++var20.z;
+ }
+
+ int var22 = this.getTile(var6, var7, var8);
+ Block var21 = Block.blocks[var22];
+ if(var22 > 0 && var21.getLiquidType() == LiquidType.NOT_LIQUID) {
+ MovingObjectPosition var23;
+ if(var21.isCube()) {
+ if((var23 = var21.clip(var6, var7, var8, var1, var2)) != null) {
+ return var23;
+ }
+ } else if((var23 = var21.clip(var6, var7, var8, var1, var2)) != null) {
+ return var23;
+ }
+ }
+ }
+
+ return null;
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public void playSound(String var1, Entity var2, float var3, float var4) {
+ if(this.rendererContext$5cd64a7f != null) {
+ Minecraft var5;
+ if((var5 = this.rendererContext$5cd64a7f).soundPlayer == null || !var5.settings.sound) {
+ return;
+ }
+
+ AudioInfo var6;
+ if(var2.distanceToSqr(var5.player) < 1024.0F && (var6 = var5.sound.getAudioInfo(var1, var3, var4)) != null) {
+ var5.soundPlayer.play(var6, new EntitySoundPos(var2, var5.player));
+ }
+ }
+
+ }
+
+ public void playSound(String var1, float var2, float var3, float var4, float var5, float var6) {
+ if(this.rendererContext$5cd64a7f != null) {
+ Minecraft var7;
+ if((var7 = this.rendererContext$5cd64a7f).soundPlayer == null || !var7.settings.sound) {
+ return;
+ }
+
+ AudioInfo var8;
+ if((var8 = var7.sound.getAudioInfo(var1, var5, var6)) != null) {
+ var7.soundPlayer.play(var8, new LevelSoundPos(var2, var3, var4, var7.player));
+ }
+ }
+
+ }
+
+ public boolean maybeGrowTree(int var1, int var2, int var3) {
+ int var4 = this.random.nextInt(3) + 4;
+ boolean var5 = true;
+
+ int var6;
+ int var8;
+ int var9;
+ for(var6 = var2; var6 <= var2 + 1 + var4; ++var6) {
+ byte var7 = 1;
+ if(var6 == var2) {
+ var7 = 0;
+ }
+
+ if(var6 >= var2 + 1 + var4 - 2) {
+ var7 = 2;
+ }
+
+ for(var8 = var1 - var7; var8 <= var1 + var7 && var5; ++var8) {
+ for(var9 = var3 - var7; var9 <= var3 + var7 && var5; ++var9) {
+ if(var8 >= 0 && var6 >= 0 && var9 >= 0 && var8 < this.width && var6 < this.depth && var9 < this.height) {
+ if((this.blocks[(var6 * this.height + var9) * this.width + var8] & 255) != 0) {
+ var5 = false;
+ }
+ } else {
+ var5 = false;
+ }
+ }
+ }
+ }
+
+ if(!var5) {
+ return false;
+ } else if((this.blocks[((var2 - 1) * this.height + var3) * this.width + var1] & 255) == Block.GRASS.id && var2 < this.depth - var4 - 1) {
+ this.setTile(var1, var2 - 1, var3, Block.DIRT.id);
+
+ int var13;
+ for(var13 = var2 - 3 + var4; var13 <= var2 + var4; ++var13) {
+ var8 = var13 - (var2 + var4);
+ var9 = 1 - var8 / 2;
+
+ for(int var10 = var1 - var9; var10 <= var1 + var9; ++var10) {
+ int var12 = var10 - var1;
+
+ for(var6 = var3 - var9; var6 <= var3 + var9; ++var6) {
+ int var11 = var6 - var3;
+ if(Math.abs(var12) != var9 || Math.abs(var11) != var9 || this.random.nextInt(2) != 0 && var8 != 0) {
+ this.setTile(var10, var13, var6, Block.LEAVES.id);
+ }
+ }
+ }
+ }
+
+ for(var13 = 0; var13 < var4; ++var13) {
+ this.setTile(var1, var2 + var13, var3, Block.LOG.id);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public Entity getPlayer() {
+ return this.player;
+ }
+
+ public void addEntity(Entity var1) {
+ this.blockMap.insert(var1);
+ var1.setLevel(this);
+ }
+
+ public void removeEntity(Entity var1) {
+ this.blockMap.remove(var1);
+ }
+
+ public void explode(Entity var1, float var2, float var3, float var4, float var5) {
+ int var6 = (int)(var2 - var5 - 1.0F);
+ int var7 = (int)(var2 + var5 + 1.0F);
+ int var8 = (int)(var3 - var5 - 1.0F);
+ int var9 = (int)(var3 + var5 + 1.0F);
+ int var10 = (int)(var4 - var5 - 1.0F);
+ int var11 = (int)(var4 + var5 + 1.0F);
+
+ int var13;
+ float var15;
+ float var16;
+ for(int var12 = var6; var12 < var7; ++var12) {
+ for(var13 = var9 - 1; var13 >= var8; --var13) {
+ for(int var14 = var10; var14 < var11; ++var14) {
+ var15 = (float)var12 + 0.5F - var2;
+ var16 = (float)var13 + 0.5F - var3;
+ float var17 = (float)var14 + 0.5F - var4;
+ int var19;
+ if(var12 >= 0 && var13 >= 0 && var14 >= 0 && var12 < this.width && var13 < this.depth && var14 < this.height && var15 * var15 + var16 * var16 + var17 * var17 < var5 * var5 && (var19 = this.getTile(var12, var13, var14)) > 0 && Block.blocks[var19].canExplode()) {
+ Block.blocks[var19].dropItems(this, var12, var13, var14, 0.3F);
+ this.setTile(var12, var13, var14, 0);
+ Block.blocks[var19].explode(this, var12, var13, var14);
+ }
+ }
+ }
+ }
+
+ List var18 = this.blockMap.getEntities(var1, (float)var6, (float)var8, (float)var10, (float)var7, (float)var9, (float)var11);
+
+ for(var13 = 0; var13 < var18.size(); ++var13) {
+ Entity var20;
+ if((var15 = (var20 = (Entity)var18.get(var13)).distanceTo(var2, var3, var4) / var5) <= 1.0F) {
+ var16 = 1.0F - var15;
+ var20.hurt(var1, (int)(var16 * 15.0F + 1.0F));
+ }
+ }
+
+ }
+
+ public Entity findSubclassOf(Class var1) {
+ for(int var2 = 0; var2 < this.blockMap.all.size(); ++var2) {
+ Entity var3 = (Entity)this.blockMap.all.get(var2);
+ if(var1.isAssignableFrom(var3.getClass())) {
+ return var3;
+ }
+ }
+
+ return null;
+ }
+
+ public void removeAllNonCreativeModeEntities() {
+ this.blockMap.removeAllNonCreativeModeEntities();
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/LevelIO.java b/src/main/java/com/mojang/minecraft/level/LevelIO.java
new file mode 100644
index 0000000..ba10a5e
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/LevelIO.java
@@ -0,0 +1,258 @@
+package com.mojang.minecraft.level;
+
+import com.mojang.minecraft.ProgressBarDisplay;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.LevelObjectInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public final class LevelIO {
+
+ private ProgressBarDisplay progressBar;
+
+
+ public LevelIO(ProgressBarDisplay var1) {
+ this.progressBar = var1;
+ }
+
+ public final boolean save(Level var1, File var2) {
+ try {
+ FileOutputStream var5 = new FileOutputStream(var2);
+ save(var1, (OutputStream)var5);
+ var5.close();
+ return true;
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ if(this.progressBar != null) {
+ this.progressBar.setText("Failed!");
+ }
+
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException var3) {
+ ;
+ }
+
+ return false;
+ }
+ }
+
+ public final Level load(File var1) {
+ try {
+ FileInputStream var5 = new FileInputStream(var1);
+ Level var2 = this.load((InputStream)var5);
+ var5.close();
+ return var2;
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ if(this.progressBar != null) {
+ this.progressBar.setText("Failed!");
+ }
+
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException var3) {
+ ;
+ }
+
+ return null;
+ }
+ }
+
+ public final boolean saveOnline(Level var1, String var2, String var3, String var4, String var5, int var6) {
+ if(var4 == null) {
+ var4 = "";
+ }
+
+ if(this.progressBar != null && this.progressBar != null) {
+ this.progressBar.setTitle("Saving level");
+ }
+
+ try {
+ if(this.progressBar != null && this.progressBar != null) {
+ this.progressBar.setText("Compressing..");
+ }
+
+ ByteArrayOutputStream var7 = new ByteArrayOutputStream();
+ save(var1, (OutputStream)var7);
+ var7.close();
+ byte[] var10 = var7.toByteArray();
+ if(this.progressBar != null && this.progressBar != null) {
+ this.progressBar.setText("Connecting..");
+ }
+
+ HttpURLConnection var12;
+ (var12 = (HttpURLConnection)(new URL("http://" + var2 + "/level/save.html")).openConnection()).setDoInput(true);
+ var12.setDoOutput(true);
+ var12.setRequestMethod("POST");
+ DataOutputStream var13;
+ (var13 = new DataOutputStream(var12.getOutputStream())).writeUTF(var3);
+ var13.writeUTF(var4);
+ var13.writeUTF(var5);
+ var13.writeByte(var6);
+ var13.writeInt(var10.length);
+ if(this.progressBar != null) {
+ this.progressBar.setText("Saving..");
+ }
+
+ var13.write(var10);
+ var13.close();
+ BufferedReader var11;
+ if(!(var11 = new BufferedReader(new InputStreamReader(var12.getInputStream()))).readLine().equalsIgnoreCase("ok")) {
+ if(this.progressBar != null) {
+ this.progressBar.setText("Failed: " + var11.readLine());
+ }
+
+ var11.close();
+ Thread.sleep(1000L);
+ return false;
+ } else {
+ var11.close();
+ return true;
+ }
+ } catch (Exception var9) {
+ var9.printStackTrace();
+ if(this.progressBar != null) {
+ this.progressBar.setText("Failed!");
+ }
+
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException var8) {
+ ;
+ }
+
+ return false;
+ }
+ }
+
+ public final Level loadOnline(String var1, String var2, int var3) {
+ if(this.progressBar != null) {
+ this.progressBar.setTitle("Loading level");
+ }
+
+ try {
+ if(this.progressBar != null) {
+ this.progressBar.setText("Connecting..");
+ }
+
+ HttpURLConnection var6;
+ (var6 = (HttpURLConnection)(new URL("http://" + var1 + "/level/load.html?id=" + var3 + "&user=" + var2)).openConnection()).setDoInput(true);
+ if(this.progressBar != null) {
+ this.progressBar.setText("Loading..");
+ }
+
+ DataInputStream var7;
+ if((var7 = new DataInputStream(var6.getInputStream())).readUTF().equalsIgnoreCase("ok")) {
+ return this.load((InputStream)var7);
+ } else {
+ if(this.progressBar != null) {
+ this.progressBar.setText("Failed: " + var7.readUTF());
+ }
+
+ var7.close();
+ Thread.sleep(1000L);
+ return null;
+ }
+ } catch (Exception var5) {
+ var5.printStackTrace();
+ if(this.progressBar != null) {
+ this.progressBar.setText("Failed!");
+ }
+
+ try {
+ Thread.sleep(3000L);
+ } catch (InterruptedException var4) {
+ ;
+ }
+
+ return null;
+ }
+ }
+
+ public final Level load(InputStream var1) {
+ if(this.progressBar != null) {
+ this.progressBar.setTitle("Loading level");
+ }
+
+ if(this.progressBar != null) {
+ this.progressBar.setText("Reading..");
+ }
+
+ try {
+ DataInputStream var10;
+ if((var10 = new DataInputStream(new GZIPInputStream(var1))).readInt() != 656127880) {
+ return null;
+ } else {
+ byte var12;
+ if((var12 = var10.readByte()) > 2) {
+ return null;
+ } else if(var12 <= 1) {
+ String var14 = var10.readUTF();
+ String var15 = var10.readUTF();
+ long var3 = var10.readLong();
+ short var5 = var10.readShort();
+ short var6 = var10.readShort();
+ short var7 = var10.readShort();
+ byte[] var8 = new byte[var5 * var6 * var7];
+ var10.readFully(var8);
+ var10.close();
+ Level var11;
+ (var11 = new Level()).setData(var5, var7, var6, var8);
+ var11.name = var14;
+ var11.creator = var15;
+ var11.createTime = var3;
+ return var11;
+ } else {
+ Level var2;
+ LevelObjectInputStream var13;
+ (var2 = (Level)(var13 = new LevelObjectInputStream(var10)).readObject()).initTransient();
+ var13.close();
+ return var2;
+ }
+ }
+ } catch (Exception var9) {
+ var9.printStackTrace();
+ System.out.println("Failed to load level: " + var9.toString());
+ return null;
+ }
+ }
+
+ public static void save(Level var0, OutputStream var1) {
+ try {
+ DataOutputStream var3;
+ (var3 = new DataOutputStream(new GZIPOutputStream(var1))).writeInt(656127880);
+ var3.writeByte(2);
+ ObjectOutputStream var4;
+ (var4 = new ObjectOutputStream(var3)).writeObject(var0);
+ var4.close();
+ } catch (Exception var2) {
+ var2.printStackTrace();
+ }
+ }
+
+ public static byte[] decompress(InputStream var0) {
+ try {
+ DataInputStream var3;
+ byte[] var1 = new byte[(var3 = new DataInputStream(new GZIPInputStream(var0))).readInt()];
+ var3.readFully(var1);
+ var3.close();
+ return var1;
+ } catch (Exception var2) {
+ throw new RuntimeException(var2);
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/LevelObjectInputStream.java b/src/main/java/com/mojang/minecraft/level/LevelObjectInputStream.java
new file mode 100644
index 0000000..85be8d1
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/LevelObjectInputStream.java
@@ -0,0 +1,35 @@
+package com.mojang.minecraft.level;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class LevelObjectInputStream extends ObjectInputStream {
+
+ private Set classes = new HashSet();
+
+
+ public LevelObjectInputStream(InputStream var1) throws IOException {
+ super(var1);
+ this.classes.add("com.mojang.minecraft.player.Player$1");
+ this.classes.add("com.mojang.minecraft.mob.Creeper$1");
+ this.classes.add("com.mojang.minecraft.mob.Skeleton$1");
+ }
+
+ protected final ObjectStreamClass readClassDescriptor() {
+ try
+ {
+ ObjectStreamClass var1 = super.readClassDescriptor();
+ return this.classes.contains(var1.getName())?ObjectStreamClass.lookup(Class.forName(var1.getName())):var1;
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/MobSpawner.java b/src/main/java/com/mojang/minecraft/level/MobSpawner.java
new file mode 100644
index 0000000..dc3cf14
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/MobSpawner.java
@@ -0,0 +1,106 @@
+package com.mojang.minecraft.level;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.ProgressBarDisplay;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.mob.Creeper;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.mob.Pig;
+import com.mojang.minecraft.mob.Sheep;
+import com.mojang.minecraft.mob.Skeleton;
+import com.mojang.minecraft.mob.Spider;
+import com.mojang.minecraft.mob.Zombie;
+
+public final class MobSpawner {
+
+ public Level level;
+
+
+ public MobSpawner(Level var1) {
+ this.level = var1;
+ }
+
+ public final int spawn(int var1, Entity var2, ProgressBarDisplay var3) {
+ int var4 = 0;
+
+ for(int var5 = 0; var5 < var1; ++var5) {
+ if(var3 != null) {
+ var3.setProgress(var5 * 100 / (var1 - 1));
+ }
+
+ int var6 = this.level.random.nextInt(6);
+ int var7 = this.level.random.nextInt(this.level.width);
+ int var8 = (int)(Math.min(this.level.random.nextFloat(), this.level.random.nextFloat()) * (float)this.level.depth);
+ int var9 = this.level.random.nextInt(this.level.height);
+ if(!this.level.isSolidTile(var7, var8, var9) && this.level.getLiquid(var7, var8, var9) == LiquidType.NOT_LIQUID && (!this.level.isLit(var7, var8, var9) || this.level.random.nextInt(5) == 0)) {
+ for(int var10 = 0; var10 < 3; ++var10) {
+ int var11 = var7;
+ int var12 = var8;
+ int var13 = var9;
+
+ for(int var14 = 0; var14 < 3; ++var14) {
+ var11 += this.level.random.nextInt(6) - this.level.random.nextInt(6);
+ var12 += this.level.random.nextInt(1) - this.level.random.nextInt(1);
+ var13 += this.level.random.nextInt(6) - this.level.random.nextInt(6);
+ if(var11 >= 0 && var13 >= 1 && var12 >= 0 && var12 < this.level.depth - 2 && var11 < this.level.width && var13 < this.level.height && this.level.isSolidTile(var11, var12 - 1, var13) && !this.level.isSolidTile(var11, var12, var13) && !this.level.isSolidTile(var11, var12 + 1, var13)) {
+ float var15 = (float)var11 + 0.5F;
+ float var16 = (float)var12 + 1.0F;
+ float var17 = (float)var13 + 0.5F;
+ float var19;
+ float var18;
+ float var20;
+ if(var2 != null) {
+ var18 = var15 - var2.x;
+ var19 = var16 - var2.y;
+ var20 = var17 - var2.z;
+ if(var18 * var18 + var19 * var19 + var20 * var20 < 256.0F) {
+ continue;
+ }
+ } else {
+ var18 = var15 - (float)this.level.xSpawn;
+ var19 = var16 - (float)this.level.ySpawn;
+ var20 = var17 - (float)this.level.zSpawn;
+ if(var18 * var18 + var19 * var19 + var20 * var20 < 256.0F) {
+ continue;
+ }
+ }
+
+ Object var21 = null;
+ if(var6 == 0) {
+ var21 = new Zombie(this.level, var15, var16, var17);
+ }
+
+ if(var6 == 1) {
+ var21 = new Skeleton(this.level, var15, var16, var17);
+ }
+
+ if(var6 == 2) {
+ var21 = new Pig(this.level, var15, var16, var17);
+ }
+
+ if(var6 == 3) {
+ var21 = new Creeper(this.level, var15, var16, var17);
+ }
+
+ if(var6 == 4) {
+ var21 = new Spider(this.level, var15, var16, var17);
+ }
+
+ if(var6 == 5) {
+ var21 = new Sheep(this.level, var15, var16, var17);
+ }
+
+ if(this.level.isFree(((Mob)var21).bb)) {
+ ++var4;
+ this.level.addEntity((Entity)var21);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return var4;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/NextTickListEntry.java b/src/main/java/com/mojang/minecraft/level/NextTickListEntry.java
new file mode 100644
index 0000000..1bb039b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/NextTickListEntry.java
@@ -0,0 +1,19 @@
+package com.mojang.minecraft.level;
+
+
+public final class NextTickListEntry {
+
+ public int x;
+ public int y;
+ public int z;
+ public int block;
+ public int ticks;
+
+
+ public NextTickListEntry(int var1, int var2, int var3, int var4) {
+ this.x = var1;
+ this.y = var2;
+ this.z = var3;
+ this.block = var4;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/SyntheticClass.java b/src/main/java/com/mojang/minecraft/level/SyntheticClass.java
new file mode 100644
index 0000000..fffeda8
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/SyntheticClass.java
@@ -0,0 +1,6 @@
+package com.mojang.minecraft.level;
+
+
+// $FF: synthetic class
+final class SyntheticClass {
+}
diff --git a/src/main/java/com/mojang/minecraft/level/generator/LevelGenerator.java b/src/main/java/com/mojang/minecraft/level/generator/LevelGenerator.java
new file mode 100644
index 0000000..3727a02
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/generator/LevelGenerator.java
@@ -0,0 +1,544 @@
+package com.mojang.minecraft.level.generator;
+
+import com.mojang.minecraft.ProgressBarDisplay;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.generator.noise.CombinedNoise;
+import com.mojang.minecraft.level.generator.noise.OctaveNoise;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.util.MathHelper;
+import java.util.ArrayList;
+import java.util.Random;
+
+public final class LevelGenerator {
+
+ private ProgressBarDisplay progressBar;
+ private int width;
+ private int depth;
+ private int height;
+ private Random random = new Random();
+ private byte[] blocks;
+ private int waterLevel;
+ private int[] h = new int[1048576];
+
+
+ public LevelGenerator(ProgressBarDisplay var1) {
+ this.progressBar = var1;
+ }
+
+ public final Level generate(String var1, int var2, int var3, int var4) {
+ this.progressBar.setTitle("Generating level");
+ this.width = var2;
+ this.depth = var3;
+ this.height = 64;
+ this.waterLevel = 32;
+ this.blocks = new byte[var2 * var3 << 6];
+ this.progressBar.setText("Raising..");
+ LevelGenerator var5 = this;
+ CombinedNoise var6 = new CombinedNoise(new OctaveNoise(this.random, 8), new OctaveNoise(this.random, 8));
+ CombinedNoise var7 = new CombinedNoise(new OctaveNoise(this.random, 8), new OctaveNoise(this.random, 8));
+ OctaveNoise var8 = new OctaveNoise(this.random, 6);
+ int[] var9 = new int[this.width * this.depth];
+ float var10 = 1.3F;
+
+ int var11;
+ int var12;
+ for(var11 = 0; var11 < var5.width; ++var11) {
+ var5.setProgress(var11 * 100 / (var5.width - 1));
+
+ for(var12 = 0; var12 < var5.depth; ++var12) {
+ double var13 = var6.compute((double)((float)var11 * var10), (double)((float)var12 * var10)) / 6.0D + (double)-4;
+ double var15 = var7.compute((double)((float)var11 * var10), (double)((float)var12 * var10)) / 5.0D + 10.0D + (double)-4;
+ if(var8.compute((double)var11, (double)var12) / 8.0D > 0.0D) {
+ var15 = var13;
+ }
+
+ double var19;
+ if((var19 = Math.max(var13, var15) / 2.0D) < 0.0D) {
+ var19 *= 0.8D;
+ }
+
+ var9[var11 + var12 * var5.width] = (int)var19;
+ }
+ }
+
+ this.progressBar.setText("Eroding..");
+ int[] var42 = var9;
+ var5 = this;
+ var7 = new CombinedNoise(new OctaveNoise(this.random, 8), new OctaveNoise(this.random, 8));
+ CombinedNoise var49 = new CombinedNoise(new OctaveNoise(this.random, 8), new OctaveNoise(this.random, 8));
+
+ int var23;
+ int var51;
+ int var54;
+ for(var51 = 0; var51 < var5.width; ++var51) {
+ var5.setProgress(var51 * 100 / (var5.width - 1));
+
+ for(var54 = 0; var54 < var5.depth; ++var54) {
+ double var21 = var7.compute((double)(var51 << 1), (double)(var54 << 1)) / 8.0D;
+ var12 = var49.compute((double)(var51 << 1), (double)(var54 << 1)) > 0.0D?1:0;
+ if(var21 > 2.0D) {
+ var23 = ((var42[var51 + var54 * var5.width] - var12) / 2 << 1) + var12;
+ var42[var51 + var54 * var5.width] = var23;
+ }
+ }
+ }
+
+ this.progressBar.setText("Soiling..");
+ var42 = var9;
+ var5 = this;
+ int var46 = this.width;
+ int var48 = this.depth;
+ var51 = this.height;
+ OctaveNoise var53 = new OctaveNoise(this.random, 8);
+
+ int var25;
+ int var24;
+ int var27;
+ int var26;
+ int var28;
+ for(var24 = 0; var24 < var46; ++var24) {
+ var5.setProgress(var24 * 100 / (var5.width - 1));
+
+ for(var11 = 0; var11 < var48; ++var11) {
+ var12 = (int)(var53.compute((double)var24, (double)var11) / 24.0D) - 4;
+ var25 = (var23 = var42[var24 + var11 * var46] + var5.waterLevel) + var12;
+ var42[var24 + var11 * var46] = Math.max(var23, var25);
+ if(var42[var24 + var11 * var46] > var51 - 2) {
+ var42[var24 + var11 * var46] = var51 - 2;
+ }
+
+ if(var42[var24 + var11 * var46] < 1) {
+ var42[var24 + var11 * var46] = 1;
+ }
+
+ for(var26 = 0; var26 < var51; ++var26) {
+ var27 = (var26 * var5.depth + var11) * var5.width + var24;
+ var28 = 0;
+ if(var26 <= var23) {
+ var28 = Block.DIRT.id;
+ }
+
+ if(var26 <= var25) {
+ var28 = Block.STONE.id;
+ }
+
+ if(var26 == 0) {
+ var28 = Block.LAVA.id;
+ }
+
+ var5.blocks[var27] = (byte)var28;
+ }
+ }
+ }
+
+ this.progressBar.setText("Carving..");
+ boolean var45 = true;
+ boolean var44 = false;
+ var5 = this;
+ var48 = this.width;
+ var51 = this.depth;
+ var54 = this.height;
+ var24 = var48 * var51 * var54 / 256 / 64 << 1;
+
+ for(var11 = 0; var11 < var24; ++var11) {
+ var5.setProgress(var11 * 100 / (var24 - 1) / 4);
+ float var55 = var5.random.nextFloat() * (float)var48;
+ float var59 = var5.random.nextFloat() * (float)var54;
+ float var56 = var5.random.nextFloat() * (float)var51;
+ var26 = (int)((var5.random.nextFloat() + var5.random.nextFloat()) * 200.0F);
+ float var61 = var5.random.nextFloat() * 3.1415927F * 2.0F;
+ float var64 = 0.0F;
+ float var29 = var5.random.nextFloat() * 3.1415927F * 2.0F;
+ float var30 = 0.0F;
+ float var31 = var5.random.nextFloat() * var5.random.nextFloat();
+
+ for(int var32 = 0; var32 < var26; ++var32) {
+ var55 += MathHelper.sin(var61) * MathHelper.cos(var29);
+ var56 += MathHelper.cos(var61) * MathHelper.cos(var29);
+ var59 += MathHelper.sin(var29);
+ var61 += var64 * 0.2F;
+ var64 = (var64 *= 0.9F) + (var5.random.nextFloat() - var5.random.nextFloat());
+ var29 = (var29 + var30 * 0.5F) * 0.5F;
+ var30 = (var30 *= 0.75F) + (var5.random.nextFloat() - var5.random.nextFloat());
+ if(var5.random.nextFloat() >= 0.25F) {
+ float var43 = var55 + (var5.random.nextFloat() * 4.0F - 2.0F) * 0.2F;
+ float var50 = var59 + (var5.random.nextFloat() * 4.0F - 2.0F) * 0.2F;
+ float var33 = var56 + (var5.random.nextFloat() * 4.0F - 2.0F) * 0.2F;
+ float var34 = ((float)var5.height - var50) / (float)var5.height;
+ var34 = 1.2F + (var34 * 3.5F + 1.0F) * var31;
+ var34 = MathHelper.sin((float)var32 * 3.1415927F / (float)var26) * var34;
+
+ for(int var35 = (int)(var43 - var34); var35 <= (int)(var43 + var34); ++var35) {
+ for(int var36 = (int)(var50 - var34); var36 <= (int)(var50 + var34); ++var36) {
+ for(int var37 = (int)(var33 - var34); var37 <= (int)(var33 + var34); ++var37) {
+ float var38 = (float)var35 - var43;
+ float var39 = (float)var36 - var50;
+ float var40 = (float)var37 - var33;
+ if(var38 * var38 + var39 * var39 * 2.0F + var40 * var40 < var34 * var34 && var35 >= 1 && var36 >= 1 && var37 >= 1 && var35 < var5.width - 1 && var36 < var5.height - 1 && var37 < var5.depth - 1) {
+ int var66 = (var36 * var5.depth + var37) * var5.width + var35;
+ if(var5.blocks[var66] == Block.STONE.id) {
+ var5.blocks[var66] = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ this.populateOre(Block.COAL_ORE.id, 90, 1, 4);
+ this.populateOre(Block.IRON_ORE.id, 70, 2, 4);
+ this.populateOre(Block.GOLD_ORE.id, 50, 3, 4);
+ this.progressBar.setText("Watering..");
+ var5 = this;
+ var51 = Block.STATIONARY_WATER.id;
+ this.setProgress(0);
+
+ for(var54 = 0; var54 < var5.width; ++var54) {
+ var5.flood(var54, var5.height / 2 - 1, 0, 0, var51);
+ var5.flood(var54, var5.height / 2 - 1, var5.depth - 1, 0, var51);
+ }
+
+ for(var54 = 0; var54 < var5.depth; ++var54) {
+ var5.flood(0, var5.height / 2 - 1, var54, 0, var51);
+ var5.flood(var5.width - 1, var5.height / 2 - 1, var54, 0, var51);
+ }
+
+ var54 = var5.width * var5.depth / 8000;
+
+ for(var24 = 0; var24 < var54; ++var24) {
+ if(var24 % 100 == 0) {
+ var5.setProgress(var24 * 100 / (var54 - 1));
+ }
+
+ var11 = var5.random.nextInt(var5.width);
+ var12 = var5.waterLevel - 1 - var5.random.nextInt(2);
+ var23 = var5.random.nextInt(var5.depth);
+ if(var5.blocks[(var12 * var5.depth + var23) * var5.width + var11] == 0) {
+ var5.flood(var11, var12, var23, 0, var51);
+ }
+ }
+
+ var5.setProgress(100);
+ this.progressBar.setText("Melting..");
+ var5 = this;
+ var46 = this.width * this.depth * this.height / 20000;
+
+ for(var48 = 0; var48 < var46; ++var48) {
+ if(var48 % 100 == 0) {
+ var5.setProgress(var48 * 100 / (var46 - 1));
+ }
+
+ var51 = var5.random.nextInt(var5.width);
+ var54 = (int)(var5.random.nextFloat() * var5.random.nextFloat() * (float)(var5.waterLevel - 3));
+ var24 = var5.random.nextInt(var5.depth);
+ if(var5.blocks[(var54 * var5.depth + var24) * var5.width + var51] == 0) {
+ var5.flood(var51, var54, var24, 0, Block.STATIONARY_LAVA.id);
+ }
+ }
+
+ var5.setProgress(100);
+ this.progressBar.setText("Growing..");
+ var42 = var9;
+ var5 = this;
+ var46 = this.width;
+ var48 = this.depth;
+ var51 = this.height;
+ var53 = new OctaveNoise(this.random, 8);
+ OctaveNoise var58 = new OctaveNoise(this.random, 8);
+
+ int var63;
+ for(var11 = 0; var11 < var46; ++var11) {
+ var5.setProgress(var11 * 100 / (var5.width - 1));
+
+ for(var12 = 0; var12 < var48; ++var12) {
+ boolean var60 = var53.compute((double)var11, (double)var12) > 8.0D;
+ boolean var57 = var58.compute((double)var11, (double)var12) > 12.0D;
+ var27 = ((var26 = var42[var11 + var12 * var46]) * var5.depth + var12) * var5.width + var11;
+ if(((var28 = var5.blocks[((var26 + 1) * var5.depth + var12) * var5.width + var11] & 255) == Block.WATER.id || var28 == Block.STATIONARY_WATER.id) && var26 <= var51 / 2 - 1 && var57) {
+ var5.blocks[var27] = (byte)Block.GRAVEL.id;
+ }
+
+ if(var28 == 0) {
+ var63 = Block.GRASS.id;
+ if(var26 <= var51 / 2 - 1 && var60) {
+ var63 = Block.SAND.id;
+ }
+
+ var5.blocks[var27] = (byte)var63;
+ }
+ }
+ }
+
+ this.progressBar.setText("Planting..");
+ var42 = var9;
+ var5 = this;
+ var46 = this.width;
+ var48 = this.width * this.depth / 3000;
+
+ for(var51 = 0; var51 < var48; ++var51) {
+ var54 = var5.random.nextInt(2);
+ var5.setProgress(var51 * 50 / (var48 - 1));
+ var24 = var5.random.nextInt(var5.width);
+ var11 = var5.random.nextInt(var5.depth);
+
+ for(var12 = 0; var12 < 10; ++var12) {
+ var23 = var24;
+ var25 = var11;
+
+ for(var26 = 0; var26 < 5; ++var26) {
+ var23 += var5.random.nextInt(6) - var5.random.nextInt(6);
+ var25 += var5.random.nextInt(6) - var5.random.nextInt(6);
+ if((var54 < 2 || var5.random.nextInt(4) == 0) && var23 >= 0 && var25 >= 0 && var23 < var5.width && var25 < var5.depth) {
+ var27 = var42[var23 + var25 * var46] + 1;
+ if((var5.blocks[(var27 * var5.depth + var25) * var5.width + var23] & 255) == 0) {
+ var63 = (var27 * var5.depth + var25) * var5.width + var23;
+ if((var5.blocks[((var27 - 1) * var5.depth + var25) * var5.width + var23] & 255) == Block.GRASS.id) {
+ if(var54 == 0) {
+ var5.blocks[var63] = (byte)Block.DANDELION.id;
+ } else if(var54 == 1) {
+ var5.blocks[var63] = (byte)Block.ROSE.id;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ var42 = var9;
+ var5 = this;
+ var46 = this.width;
+ var51 = this.width * this.depth * this.height / 2000;
+
+ for(var54 = 0; var54 < var51; ++var54) {
+ var24 = var5.random.nextInt(2);
+ var5.setProgress(var54 * 50 / (var51 - 1) + 50);
+ var11 = var5.random.nextInt(var5.width);
+ var12 = var5.random.nextInt(var5.height);
+ var23 = var5.random.nextInt(var5.depth);
+
+ for(var25 = 0; var25 < 20; ++var25) {
+ var26 = var11;
+ var27 = var12;
+ var28 = var23;
+
+ for(var63 = 0; var63 < 5; ++var63) {
+ var26 += var5.random.nextInt(6) - var5.random.nextInt(6);
+ var27 += var5.random.nextInt(2) - var5.random.nextInt(2);
+ var28 += var5.random.nextInt(6) - var5.random.nextInt(6);
+ if((var24 < 2 || var5.random.nextInt(4) == 0) && var26 >= 0 && var28 >= 0 && var27 >= 1 && var26 < var5.width && var28 < var5.depth && var27 < var42[var26 + var28 * var46] - 1 && (var5.blocks[(var27 * var5.depth + var28) * var5.width + var26] & 255) == 0) {
+ int var62 = (var27 * var5.depth + var28) * var5.width + var26;
+ if((var5.blocks[((var27 - 1) * var5.depth + var28) * var5.width + var26] & 255) == Block.STONE.id) {
+ if(var24 == 0) {
+ var5.blocks[var62] = (byte)Block.BROWN_MUSHROOM.id;
+ } else if(var24 == 1) {
+ var5.blocks[var62] = (byte)Block.RED_MUSHROOM.id;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Level var65;
+ (var65 = new Level()).waterLevel = this.waterLevel;
+ var65.setData(var2, 64, var3, this.blocks);
+ var65.createTime = System.currentTimeMillis();
+ var65.creator = var1;
+ var65.name = "A Nice World";
+ int[] var52 = var9;
+ Level var47 = var65;
+ var5 = this;
+ var48 = this.width;
+ var51 = this.width * this.depth / 4000;
+
+ for(var54 = 0; var54 < var51; ++var54) {
+ var5.setProgress(var54 * 50 / (var51 - 1) + 50);
+ var24 = var5.random.nextInt(var5.width);
+ var11 = var5.random.nextInt(var5.depth);
+
+ for(var12 = 0; var12 < 20; ++var12) {
+ var23 = var24;
+ var25 = var11;
+
+ for(var26 = 0; var26 < 20; ++var26) {
+ var23 += var5.random.nextInt(6) - var5.random.nextInt(6);
+ var25 += var5.random.nextInt(6) - var5.random.nextInt(6);
+ if(var23 >= 0 && var25 >= 0 && var23 < var5.width && var25 < var5.depth) {
+ var27 = var52[var23 + var25 * var48] + 1;
+ if(var5.random.nextInt(4) == 0) {
+ var47.maybeGrowTree(var23, var27, var25);
+ }
+ }
+ }
+ }
+ }
+
+ return var65;
+ }
+
+ private void populateOre(int var1, int var2, int var3, int var4) {
+ byte var25 = (byte)var1;
+ var4 = this.width;
+ int var5 = this.depth;
+ int var6 = this.height;
+ int var7 = var4 * var5 * var6 / 256 / 64 * var2 / 100;
+
+ for(int var8 = 0; var8 < var7; ++var8) {
+ this.setProgress(var8 * 100 / (var7 - 1) / 4 + var3 * 100 / 4);
+ float var9 = this.random.nextFloat() * (float)var4;
+ float var10 = this.random.nextFloat() * (float)var6;
+ float var11 = this.random.nextFloat() * (float)var5;
+ int var12 = (int)((this.random.nextFloat() + this.random.nextFloat()) * 75.0F * (float)var2 / 100.0F);
+ float var13 = this.random.nextFloat() * 3.1415927F * 2.0F;
+ float var14 = 0.0F;
+ float var15 = this.random.nextFloat() * 3.1415927F * 2.0F;
+ float var16 = 0.0F;
+
+ for(int var17 = 0; var17 < var12; ++var17) {
+ var9 += MathHelper.sin(var13) * MathHelper.cos(var15);
+ var11 += MathHelper.cos(var13) * MathHelper.cos(var15);
+ var10 += MathHelper.sin(var15);
+ var13 += var14 * 0.2F;
+ var14 = (var14 *= 0.9F) + (this.random.nextFloat() - this.random.nextFloat());
+ var15 = (var15 + var16 * 0.5F) * 0.5F;
+ var16 = (var16 *= 0.9F) + (this.random.nextFloat() - this.random.nextFloat());
+ float var18 = MathHelper.sin((float)var17 * 3.1415927F / (float)var12) * (float)var2 / 100.0F + 1.0F;
+
+ for(int var19 = (int)(var9 - var18); var19 <= (int)(var9 + var18); ++var19) {
+ for(int var20 = (int)(var10 - var18); var20 <= (int)(var10 + var18); ++var20) {
+ for(int var21 = (int)(var11 - var18); var21 <= (int)(var11 + var18); ++var21) {
+ float var22 = (float)var19 - var9;
+ float var23 = (float)var20 - var10;
+ float var24 = (float)var21 - var11;
+ if(var22 * var22 + var23 * var23 * 2.0F + var24 * var24 < var18 * var18 && var19 >= 1 && var20 >= 1 && var21 >= 1 && var19 < this.width - 1 && var20 < this.height - 1 && var21 < this.depth - 1) {
+ int var26 = (var20 * this.depth + var21) * this.width + var19;
+ if(this.blocks[var26] == Block.STONE.id) {
+ this.blocks[var26] = var25;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ private void setProgress(int var1) {
+ this.progressBar.setProgress(var1);
+ }
+
+ private long flood(int var1, int var2, int var3, int var4, int var5) {
+ byte var20 = (byte)var5;
+ ArrayList var21 = new ArrayList();
+ byte var6 = 0;
+ int var7 = 1;
+
+ int var8;
+ for(var8 = 1; 1 << var7 < this.width; ++var7) {
+ ;
+ }
+
+ while(1 << var8 < this.depth) {
+ ++var8;
+ }
+
+ int var9 = this.depth - 1;
+ int var10 = this.width - 1;
+ int var22 = var6 + 1;
+ this.h[0] = ((var2 << var8) + var3 << var7) + var1;
+ long var11 = 0L;
+ var1 = this.width * this.depth;
+
+ while(var22 > 0) {
+ --var22;
+ var2 = this.h[var22];
+ if(var22 == 0 && var21.size() > 0) {
+ this.h = (int[])var21.remove(var21.size() - 1);
+ var22 = this.h.length;
+ }
+
+ var3 = var2 >> var7 & var9;
+ int var13 = var2 >> var7 + var8;
+
+ int var14;
+ int var15;
+ for(var15 = var14 = var2 & var10; var14 > 0 && this.blocks[var2 - 1] == 0; --var2) {
+ --var14;
+ }
+
+ while(var15 < this.width && this.blocks[var2 + var15 - var14] == 0) {
+ ++var15;
+ }
+
+ int var16 = var2 >> var7 & var9;
+ int var17 = var2 >> var7 + var8;
+ if(var16 != var3 || var17 != var13) {
+ System.out.println("Diagonal flood!?");
+ }
+
+ boolean var23 = false;
+ boolean var24 = false;
+ boolean var18 = false;
+ var11 += (long)(var15 - var14);
+
+ for(var14 = var14; var14 < var15; ++var14) {
+ this.blocks[var2] = var20;
+ boolean var19;
+ if(var3 > 0) {
+ if((var19 = this.blocks[var2 - this.width] == 0) && !var23) {
+ if(var22 == this.h.length) {
+ var21.add(this.h);
+ this.h = new int[1048576];
+ var22 = 0;
+ }
+
+ this.h[var22++] = var2 - this.width;
+ }
+
+ var23 = var19;
+ }
+
+ if(var3 < this.depth - 1) {
+ if((var19 = this.blocks[var2 + this.width] == 0) && !var24) {
+ if(var22 == this.h.length) {
+ var21.add(this.h);
+ this.h = new int[1048576];
+ var22 = 0;
+ }
+
+ this.h[var22++] = var2 + this.width;
+ }
+
+ var24 = var19;
+ }
+
+ if(var13 > 0) {
+ byte var25 = this.blocks[var2 - var1];
+ if((var20 == Block.LAVA.id || var20 == Block.STATIONARY_LAVA.id) && (var25 == Block.WATER.id || var25 == Block.STATIONARY_WATER.id)) {
+ this.blocks[var2 - var1] = (byte)Block.STONE.id;
+ }
+
+ if((var19 = var25 == 0) && !var18) {
+ if(var22 == this.h.length) {
+ var21.add(this.h);
+ this.h = new int[1048576];
+ var22 = 0;
+ }
+
+ this.h[var22++] = var2 - var1;
+ }
+
+ var18 = var19;
+ }
+
+ ++var2;
+ }
+ }
+
+ return var11;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/generator/noise/CombinedNoise.java b/src/main/java/com/mojang/minecraft/level/generator/noise/CombinedNoise.java
new file mode 100644
index 0000000..d9fe5f7
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/generator/noise/CombinedNoise.java
@@ -0,0 +1,19 @@
+package com.mojang.minecraft.level.generator.noise;
+
+public final class CombinedNoise extends Noise
+{
+ public CombinedNoise(Noise noise1, Noise noise2)
+ {
+ this.noise1 = noise1;
+ this.noise2 = noise2;
+ }
+
+ @Override
+ public double compute(double x, double z)
+ {
+ return noise1.compute(x + noise2.compute(x, z), z);
+ }
+
+ private Noise noise1;
+ private Noise noise2;
+}
diff --git a/src/main/java/com/mojang/minecraft/level/generator/noise/Noise.java b/src/main/java/com/mojang/minecraft/level/generator/noise/Noise.java
new file mode 100644
index 0000000..a4adfe1
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/generator/noise/Noise.java
@@ -0,0 +1,7 @@
+package com.mojang.minecraft.level.generator.noise;
+
+
+public abstract class Noise
+{
+ public abstract double compute(double x, double z);
+}
diff --git a/src/main/java/com/mojang/minecraft/level/generator/noise/OctaveNoise.java b/src/main/java/com/mojang/minecraft/level/generator/noise/OctaveNoise.java
new file mode 100644
index 0000000..4e2b0fd
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/generator/noise/OctaveNoise.java
@@ -0,0 +1,37 @@
+package com.mojang.minecraft.level.generator.noise;
+
+import java.util.Random;
+
+public class OctaveNoise extends Noise
+{
+ public OctaveNoise(Random random, int octaves)
+ {
+ this.octaves = octaves;
+ perlin = new PerlinNoise[octaves];
+
+ for(int count = 0; count < octaves; count++)
+ {
+ perlin[count] = new PerlinNoise(random);
+ }
+
+ }
+
+ @Override
+ public double compute(double x, double z)
+ {
+ double result = 0.0D;
+ double unknown0 = 1.0D;
+
+ for(int count = 0; count < octaves; count++)
+ {
+ result += perlin[count].compute(x / unknown0, z / unknown0) * unknown0;
+
+ unknown0 *= 2.0D;
+ }
+
+ return result;
+ }
+
+ private PerlinNoise[] perlin;
+ private int octaves;
+}
diff --git a/src/main/java/com/mojang/minecraft/level/generator/noise/PerlinNoise.java b/src/main/java/com/mojang/minecraft/level/generator/noise/PerlinNoise.java
new file mode 100644
index 0000000..8f8d953
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/generator/noise/PerlinNoise.java
@@ -0,0 +1,135 @@
+package com.mojang.minecraft.level.generator.noise;
+
+import java.util.Random;
+
+public class PerlinNoise extends Noise
+{
+ public PerlinNoise()
+ {
+ this(new Random());
+ }
+
+ public PerlinNoise(Random random)
+ {
+ noise = new int[512];
+
+ for(int count = 0; count < 256; noise[count] = count++)
+ {
+ }
+
+ for(int count = 0; count < 256; count++)
+ {
+ int unknown0 = random.nextInt(256 - count) + count;
+ int unknown1 = noise[count];
+
+ noise[count] = noise[unknown0];
+ noise[unknown0] = unknown1;
+ noise[count + 256] = noise[count];
+ }
+
+ }
+
+ @Override
+ public double compute(double x, double z)
+ {
+ double unknown0 = 0.0D;
+ double unknown1 = z;
+ double unknown2 = x;
+
+ int unknown3 = (int)Math.floor(x) & 255;
+ int unknown4 = (int)Math.floor(z) & 255;
+ int unknown5 = (int)Math.floor(0.0D) & 255;
+
+ unknown2 -= Math.floor(unknown2);
+ unknown1 -= Math.floor(unknown1);
+ unknown0 = 0.0D - Math.floor(0.0D);
+
+ double unknown6 = a(unknown2);
+ double unknown7 = a(unknown1);
+ double unknown8 = a(unknown0);
+
+ int unknown9 = noise[unknown3] + unknown4;
+ int unknown10 = noise[unknown9] + unknown5;
+
+ unknown9 = noise[unknown9 + 1] + unknown5;
+ unknown3 = noise[unknown3 + 1] + unknown4;
+ unknown4 = noise[unknown3] + unknown5;
+ unknown3 = noise[unknown3 + 1] + unknown5;
+
+ // TODO: Maybe organize better.
+ return lerp(
+ unknown8,
+ lerp(
+ unknown7,
+ lerp(
+ unknown6,
+ grad(
+ noise[unknown10],
+ unknown2,
+ unknown1,
+ unknown0),
+ grad(
+ noise[unknown4],
+ unknown2 - 1.0D,
+ unknown1,
+ unknown0)),
+ lerp(
+ unknown6,
+ grad(
+ noise[unknown9],
+ unknown2,
+ unknown1 - 1.0D,
+ unknown0),
+ grad(
+ noise[unknown3],
+ unknown2 - 1.0D,
+ unknown1 - 1.0D,
+ unknown0))),
+ lerp(
+ unknown7,
+ lerp(
+ unknown6,
+ grad(
+ noise[unknown10 + 1],
+ unknown2,
+ unknown1,
+ unknown0 - 1.0D),
+ grad(
+ noise[unknown4 + 1],
+ unknown2 - 1.0D,
+ unknown1,
+ unknown0 - 1.0D)),
+ lerp(
+ unknown6,
+ grad(
+ noise[unknown9 + 1],
+ unknown2,
+ unknown1 - 1.0D,
+ unknown0 - 1.0D),
+ grad(
+ noise[unknown3 + 1],
+ unknown2 - 1.0D,
+ unknown1 - 1.0D,
+ unknown0 - 1.0D))));
+ }
+
+ private int[] noise;
+
+ private static double a(double unknown0)
+ {
+ return unknown0 * unknown0 * unknown0 * (unknown0 * (unknown0 * 6.0D - 15.0D) + 10.0D);
+ }
+
+ private static double lerp(double unknown0, double unknown1, double unknown2)
+ {
+ return unknown1 + unknown0 * (unknown2 - unknown1);
+ }
+
+ private static double grad(int unknown0, double unknown1, double unknown2, double unknown3)
+ {
+ double unknown4 = (unknown0 &= 15) < 8 ? unknown1 : unknown2;
+ double unknown5 = unknown0 < 4 ? unknown2 : (unknown0 != 12 && unknown0 != 14 ? unknown3 : unknown1);
+
+ return ((unknown0 & 1) == 0 ? unknown4 : -unknown4) + ((unknown0 & 2) == 0 ? unknown5 : -unknown5);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/liquid/LiquidType.java b/src/main/java/com/mojang/minecraft/level/liquid/LiquidType.java
new file mode 100644
index 0000000..b830b4c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/liquid/LiquidType.java
@@ -0,0 +1,17 @@
+package com.mojang.minecraft.level.liquid;
+
+public class LiquidType
+{
+ private LiquidType(int type)
+ {
+ values = new LiquidType[4];
+
+ values[type] = this;
+ }
+
+ private LiquidType[] values;
+
+ public static final LiquidType NOT_LIQUID = new LiquidType(0);
+ public static final LiquidType WATER = new LiquidType(1);
+ public static final LiquidType LAVA = new LiquidType(2);
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/Block.java b/src/main/java/com/mojang/minecraft/level/tile/Block.java
new file mode 100644
index 0000000..e3219b0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/Block.java
@@ -0,0 +1,742 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.MovingObjectPosition;
+import com.mojang.minecraft.item.Item;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.particle.ParticleManager;
+import com.mojang.minecraft.particle.TerrainParticle;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.render.ShapeRenderer;
+import java.util.Random;
+
+public class Block
+{
+ protected Block(int id)
+ {
+ explodes = true;
+ blocks[id] = this;
+ this.id = id;
+
+ setBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+
+ opaque[id] = isSolid();
+ cube[id] = isCube();
+ liquid[id] = false;
+ }
+
+ protected Block(int id, int textureID)
+ {
+ this(id);
+
+ textureId = textureID;
+ }
+
+ protected static Random random = new Random();
+ public static final Block[] blocks = new Block[256];
+ public static final boolean[] physics = new boolean[256];
+ private static boolean[] opaque = new boolean[256];
+ private static boolean[] cube = new boolean[256];
+ public static final boolean[] liquid = new boolean[256];
+ private static int[] tickDelay = new int[256];
+ public static final Block STONE;
+ public static final Block GRASS;
+ public static final Block DIRT;
+ public static final Block COBBLESTONE;
+ public static final Block WOOD;
+ public static final Block SAPLING;
+ public static final Block BEDROCK;
+ public static final Block WATER;
+ public static final Block STATIONARY_WATER;
+ public static final Block LAVA;
+ public static final Block STATIONARY_LAVA;
+ public static final Block SAND;
+ public static final Block GRAVEL;
+ public static final Block GOLD_ORE;
+ public static final Block IRON_ORE;
+ public static final Block COAL_ORE;
+ public static final Block LOG;
+ public static final Block LEAVES;
+ public static final Block SPONGE;
+ public static final Block GLASS;
+ public static final Block RED_WOOL;
+ public static final Block ORANGE_WOOL;
+ public static final Block YELLOW_WOOL;
+ public static final Block LIME_WOOL;
+ public static final Block GREEN_WOOL;
+ public static final Block AQUA_GREEN_WOOL;
+ public static final Block CYAN_WOOL;
+ public static final Block BLUE_WOOL;
+ public static final Block PURPLE_WOOL;
+ public static final Block INDIGO_WOOL;
+ public static final Block VIOLET_WOOL;
+ public static final Block MAGENTA_WOOL;
+ public static final Block PINK_WOOL;
+ public static final Block BLACK_WOOL;
+ public static final Block GRAY_WOOL;
+ public static final Block WHITE_WOOL;
+ public static final Block DANDELION;
+ public static final Block ROSE;
+ public static final Block BROWN_MUSHROOM;
+ public static final Block RED_MUSHROOM;
+ public static final Block GOLD_BLOCK;
+ public static final Block IRON_BLOCK;
+ public static final Block DOUBLE_SLAB;
+ public static final Block SLAB;
+ public static final Block BRICK;
+ public static final Block TNT;
+ public static final Block BOOKSHELF;
+ public static final Block MOSSY_COBBLESTONE;
+ public static final Block OBSIDIAN;
+ public int textureId;
+ public final int id;
+ public Tile$SoundType stepsound;
+ private int hardness;
+ private boolean explodes;
+ public float x1;
+ public float y1;
+ public float z1;
+ public float x2;
+ public float y2;
+ public float z2;
+ public float particleGravity;
+
+ public boolean isCube()
+ {
+ return true;
+ }
+
+ protected Block setData(Tile$SoundType soundType, float var2, float particleGravity, float hardness)
+ {
+ this.particleGravity = particleGravity;
+ this.stepsound = soundType;
+ this.hardness = (int)(hardness * 20.0F);
+
+ return this;
+ }
+
+ protected void setPhysics(boolean physics)
+ {
+ this.physics[id] = physics;
+ }
+
+ protected void setBounds(float x1, float y1, float z1, float x2, float y2, float z2)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.z1 = z1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.z2 = z2;
+ }
+
+ public void setTickDelay(int tickDelay)
+ {
+ this.tickDelay[id] = tickDelay;
+ }
+
+ public void renderFullbright(ShapeRenderer shapeRenderer)
+ {
+ float red = 0.5F;
+ float green = 0.8F;
+ float blue = 0.6F;
+
+ shapeRenderer.color(red, red, red);
+ renderInside(shapeRenderer, -2, 0, 0, 0);
+
+ shapeRenderer.color(1.0F, 1.0F, 1.0F);
+ renderInside(shapeRenderer, -2, 0, 0, 1);
+
+ shapeRenderer.color(green, green, green);
+ renderInside(shapeRenderer, -2, 0, 0, 2);
+
+ shapeRenderer.color(green, green, green);
+ renderInside(shapeRenderer, -2, 0, 0, 3);
+
+ shapeRenderer.color(blue, blue, blue);
+ renderInside(shapeRenderer, -2, 0, 0, 4);
+
+ shapeRenderer.color(blue, blue, blue);
+ renderInside(shapeRenderer, -2, 0, 0, 5);
+ }
+
+ protected float getBrightness(Level level, int x, int y, int z)
+ {
+ return level.getBrightness(x, y, z);
+ }
+
+ public boolean canRenderSide(Level level, int x, int y, int z, int side)
+ {
+ return !level.isSolidTile(x, y, z);
+ }
+
+ protected int getTextureId(int texture)
+ {
+ return textureId;
+ }
+
+ public void renderInside(ShapeRenderer shapeRenderer, int x, int y, int z, int side)
+ {
+ int textureID1 = getTextureId(side);
+
+ renderSide(shapeRenderer, x, y, z, side, textureID1);
+ }
+
+ // TODO.
+ public void renderSide(ShapeRenderer shapeRenderer, int x, int y, int z, int side, int textureID)
+ {
+ int var7 = textureID % 16 << 4;
+ int var8 = textureID / 16 << 4;
+ float var9 = (float)var7 / 256.0F;
+ float var17 = ((float)var7 + 15.99F) / 256.0F;
+ float var10 = (float)var8 / 256.0F;
+ float var11 = ((float)var8 + 15.99F) / 256.0F;
+ if(side >= 2 && textureID < 240) {
+ if(this.y1 >= 0.0F && this.y2 <= 1.0F) {
+ var10 = ((float)var8 + this.y1 * 15.99F) / 256.0F;
+ var11 = ((float)var8 + this.y2 * 15.99F) / 256.0F;
+ } else {
+ var10 = (float)var8 / 256.0F;
+ var11 = ((float)var8 + 15.99F) / 256.0F;
+ }
+ }
+
+ float var16 = (float)x + this.x1;
+ float var14 = (float)x + this.x2;
+ float var18 = (float)y + this.y1;
+ float var15 = (float)y + this.y2;
+ float var12 = (float)z + this.z1;
+ float var13 = (float)z + this.z2;
+ if(side == 0) {
+ shapeRenderer.vertexUV(var16, var18, var13, var9, var11);
+ shapeRenderer.vertexUV(var16, var18, var12, var9, var10);
+ shapeRenderer.vertexUV(var14, var18, var12, var17, var10);
+ shapeRenderer.vertexUV(var14, var18, var13, var17, var11);
+ } else if(side == 1) {
+ shapeRenderer.vertexUV(var14, var15, var13, var17, var11);
+ shapeRenderer.vertexUV(var14, var15, var12, var17, var10);
+ shapeRenderer.vertexUV(var16, var15, var12, var9, var10);
+ shapeRenderer.vertexUV(var16, var15, var13, var9, var11);
+ } else if(side == 2) {
+ shapeRenderer.vertexUV(var16, var15, var12, var17, var10);
+ shapeRenderer.vertexUV(var14, var15, var12, var9, var10);
+ shapeRenderer.vertexUV(var14, var18, var12, var9, var11);
+ shapeRenderer.vertexUV(var16, var18, var12, var17, var11);
+ } else if(side == 3) {
+ shapeRenderer.vertexUV(var16, var15, var13, var9, var10);
+ shapeRenderer.vertexUV(var16, var18, var13, var9, var11);
+ shapeRenderer.vertexUV(var14, var18, var13, var17, var11);
+ shapeRenderer.vertexUV(var14, var15, var13, var17, var10);
+ } else if(side == 4) {
+ shapeRenderer.vertexUV(var16, var15, var13, var17, var10);
+ shapeRenderer.vertexUV(var16, var15, var12, var9, var10);
+ shapeRenderer.vertexUV(var16, var18, var12, var9, var11);
+ shapeRenderer.vertexUV(var16, var18, var13, var17, var11);
+ } else if(side == 5) {
+ shapeRenderer.vertexUV(var14, var18, var13, var9, var11);
+ shapeRenderer.vertexUV(var14, var18, var12, var17, var11);
+ shapeRenderer.vertexUV(var14, var15, var12, var17, var10);
+ shapeRenderer.vertexUV(var14, var15, var13, var9, var10);
+ }
+ }
+
+ // TODO.
+ public final void renderSide(ShapeRenderer var1, int var2, int var3, int var4, int var5) {
+ int var6;
+ float var7;
+ float var8 = (var7 = (float)((var6 = this.getTextureId(var5)) % 16) / 16.0F) + 0.0624375F;
+ float var16;
+ float var9 = (var16 = (float)(var6 / 16) / 16.0F) + 0.0624375F;
+ float var10 = (float)var2 + this.x1;
+ float var14 = (float)var2 + this.x2;
+ float var11 = (float)var3 + this.y1;
+ float var15 = (float)var3 + this.y2;
+ float var12 = (float)var4 + this.z1;
+ float var13 = (float)var4 + this.z2;
+ if(var5 == 0) {
+ var1.vertexUV(var14, var11, var13, var8, var9);
+ var1.vertexUV(var14, var11, var12, var8, var16);
+ var1.vertexUV(var10, var11, var12, var7, var16);
+ var1.vertexUV(var10, var11, var13, var7, var9);
+ }
+
+ if(var5 == 1) {
+ var1.vertexUV(var10, var15, var13, var7, var9);
+ var1.vertexUV(var10, var15, var12, var7, var16);
+ var1.vertexUV(var14, var15, var12, var8, var16);
+ var1.vertexUV(var14, var15, var13, var8, var9);
+ }
+
+ if(var5 == 2) {
+ var1.vertexUV(var10, var11, var12, var8, var9);
+ var1.vertexUV(var14, var11, var12, var7, var9);
+ var1.vertexUV(var14, var15, var12, var7, var16);
+ var1.vertexUV(var10, var15, var12, var8, var16);
+ }
+
+ if(var5 == 3) {
+ var1.vertexUV(var14, var15, var13, var8, var16);
+ var1.vertexUV(var14, var11, var13, var8, var9);
+ var1.vertexUV(var10, var11, var13, var7, var9);
+ var1.vertexUV(var10, var15, var13, var7, var16);
+ }
+
+ if(var5 == 4) {
+ var1.vertexUV(var10, var11, var13, var8, var9);
+ var1.vertexUV(var10, var11, var12, var7, var9);
+ var1.vertexUV(var10, var15, var12, var7, var16);
+ var1.vertexUV(var10, var15, var13, var8, var16);
+ }
+
+ if(var5 == 5) {
+ var1.vertexUV(var14, var15, var13, var7, var16);
+ var1.vertexUV(var14, var15, var12, var8, var16);
+ var1.vertexUV(var14, var11, var12, var8, var9);
+ var1.vertexUV(var14, var11, var13, var7, var9);
+ }
+
+ }
+
+ public AABB getSelectionBox(int x, int y, int z)
+ {
+ AABB aabb = new AABB((float)x + x1, (float)y + y1, (float)z + z1, (float)x + x2, (float)y + y2, (float)z + z2);;
+
+ return aabb;
+ }
+
+ public AABB getCollisionBox(int x, int y, int z)
+ {
+ AABB aabb = new AABB((float)x + x1, (float)y + y1, (float)z + z1, (float)x + x2, (float)y + y2, (float)z + z2);;
+
+ return aabb;
+ }
+
+ public boolean isOpaque()
+ {
+ return true;
+ }
+
+ public boolean isSolid()
+ {
+ return true;
+ }
+
+ public void update(Level level, int x, int y, int z, Random rand)
+ {
+ }
+
+ // TODO.
+ public void spawnBreakParticles(Level level, int x, int y, int z, ParticleManager particleManager)
+ {
+ for(int var6 = 0; var6 < 4; ++var6)
+ {
+ for(int var7 = 0; var7 < 4; ++var7)
+ {
+ for(int var8 = 0; var8 < 4; ++var8)
+ {
+ float var9 = (float)x + ((float)var6 + 0.5F) / (float)4;
+ float var10 = (float)y + ((float)var7 + 0.5F) / (float)4;
+ float var11 = (float)z + ((float)var8 + 0.5F) / (float)4;
+
+ particleManager.spawnParticle(new TerrainParticle(level, var9, var10, var11, var9 - (float) x - 0.5F, var10 - (float) y - 0.5F, var11 - (float) z - 0.5F, this));
+ }
+ }
+ }
+
+ }
+
+ // TODO.
+ public final void spawnBlockParticles(Level var1, int var2, int var3, int var4, int var5, ParticleManager var6) {
+ float var7 = 0.1F;
+ float var8 = (float)var2 + random.nextFloat() * (this.x2 - this.x1 - var7 * 2.0F) + var7 + this.x1;
+ float var9 = (float)var3 + random.nextFloat() * (this.y2 - this.y1 - var7 * 2.0F) + var7 + this.y1;
+ float var10 = (float)var4 + random.nextFloat() * (this.z2 - this.z1 - var7 * 2.0F) + var7 + this.z1;
+ if(var5 == 0) {
+ var9 = (float)var3 + this.y1 - var7;
+ }
+
+ if(var5 == 1) {
+ var9 = (float)var3 + this.y2 + var7;
+ }
+
+ if(var5 == 2) {
+ var10 = (float)var4 + this.z1 - var7;
+ }
+
+ if(var5 == 3) {
+ var10 = (float)var4 + this.z2 + var7;
+ }
+
+ if(var5 == 4) {
+ var8 = (float)var2 + this.x1 - var7;
+ }
+
+ if(var5 == 5) {
+ var8 = (float)var2 + this.x2 + var7;
+ }
+
+ var6.spawnParticle((new TerrainParticle(var1, var8, var9, var10, 0.0F, 0.0F, 0.0F, this)).setPower(0.2F).scale(0.6F));
+ }
+
+ public LiquidType getLiquidType()
+ {
+ return LiquidType.NOT_LIQUID;
+ }
+
+ // TODO.
+ public void onNeighborChange(Level var1, int var2, int var3, int var4, int var5)
+ {
+ }
+
+ public void onPlace(Level level, int x, int y, int z)
+ {
+ }
+
+ public int getTickDelay()
+ {
+ return 0;
+ }
+
+ public void onAdded(Level level, int x, int y, int z)
+ {
+ }
+
+ // TODO past here.
+
+ public void onRemoved(Level var1, int var2, int var3, int var4) {}
+
+ public int getDropCount() {
+ return 1;
+ }
+
+ public int getDrop() {
+ return this.id;
+ }
+
+ public final int getHardness() {
+ return this.hardness;
+ }
+
+ public void onBreak(Level var1, int var2, int var3, int var4) {
+ this.dropItems(var1, var2, var3, var4, 1.0F);
+ }
+
+ public void dropItems(Level var1, int var2, int var3, int var4, float var5) {
+ if(!var1.creativeMode) {
+ int var6 = this.getDropCount();
+
+ for(int var7 = 0; var7 < var6; ++var7) {
+ if(random.nextFloat() <= var5) {
+ float var8 = 0.7F;
+ float var9 = random.nextFloat() * var8 + (1.0F - var8) * 0.5F;
+ float var10 = random.nextFloat() * var8 + (1.0F - var8) * 0.5F;
+ var8 = random.nextFloat() * var8 + (1.0F - var8) * 0.5F;
+ var1.addEntity(new Item(var1, (float)var2 + var9, (float)var3 + var10, (float)var4 + var8, this.getDrop()));
+ }
+ }
+
+ }
+ }
+
+ public void renderPreview(ShapeRenderer var1) {
+ var1.begin();
+
+ for(int var2 = 0; var2 < 6; ++var2) {
+ if(var2 == 0) {
+ var1.normal(0.0F, 1.0F, 0.0F);
+ }
+
+ if(var2 == 1) {
+ var1.normal(0.0F, -1.0F, 0.0F);
+ }
+
+ if(var2 == 2) {
+ var1.normal(0.0F, 0.0F, 1.0F);
+ }
+
+ if(var2 == 3) {
+ var1.normal(0.0F, 0.0F, -1.0F);
+ }
+
+ if(var2 == 4) {
+ var1.normal(1.0F, 0.0F, 0.0F);
+ }
+
+ if(var2 == 5) {
+ var1.normal(-1.0F, 0.0F, 0.0F);
+ }
+
+ this.renderInside(var1, 0, 0, 0, var2);
+ }
+
+ var1.end();
+ }
+
+ public final boolean canExplode() {
+ return this.explodes;
+ }
+
+ public final MovingObjectPosition clip(int var1, int var2, int var3, Vec3D var4, Vec3D var5) {
+ var4 = var4.add((float)(-var1), (float)(-var2), (float)(-var3));
+ var5 = var5.add((float)(-var1), (float)(-var2), (float)(-var3));
+ Vec3D var6 = var4.getXIntersection(var5, this.x1);
+ Vec3D var7 = var4.getXIntersection(var5, this.x2);
+ Vec3D var8 = var4.getYIntersection(var5, this.y1);
+ Vec3D var9 = var4.getYIntersection(var5, this.y2);
+ Vec3D var10 = var4.getZIntersection(var5, this.z1);
+ var5 = var4.getZIntersection(var5, this.z2);
+ if(!this.xIntersects(var6)) {
+ var6 = null;
+ }
+
+ if(!this.xIntersects(var7)) {
+ var7 = null;
+ }
+
+ if(!this.yIntersects(var8)) {
+ var8 = null;
+ }
+
+ if(!this.yIntersects(var9)) {
+ var9 = null;
+ }
+
+ if(!this.zIntersects(var10)) {
+ var10 = null;
+ }
+
+ if(!this.zIntersects(var5)) {
+ var5 = null;
+ }
+
+ Vec3D var11 = null;
+ if(var6 != null) {
+ var11 = var6;
+ }
+
+ if(var7 != null && (var11 == null || var4.distance(var7) < var4.distance(var11))) {
+ var11 = var7;
+ }
+
+ if(var8 != null && (var11 == null || var4.distance(var8) < var4.distance(var11))) {
+ var11 = var8;
+ }
+
+ if(var9 != null && (var11 == null || var4.distance(var9) < var4.distance(var11))) {
+ var11 = var9;
+ }
+
+ if(var10 != null && (var11 == null || var4.distance(var10) < var4.distance(var11))) {
+ var11 = var10;
+ }
+
+ if(var5 != null && (var11 == null || var4.distance(var5) < var4.distance(var11))) {
+ var11 = var5;
+ }
+
+ if(var11 == null) {
+ return null;
+ } else {
+ byte var12 = -1;
+ if(var11 == var6) {
+ var12 = 4;
+ }
+
+ if(var11 == var7) {
+ var12 = 5;
+ }
+
+ if(var11 == var8) {
+ var12 = 0;
+ }
+
+ if(var11 == var9) {
+ var12 = 1;
+ }
+
+ if(var11 == var10) {
+ var12 = 2;
+ }
+
+ if(var11 == var5) {
+ var12 = 3;
+ }
+
+ return new MovingObjectPosition(var1, var2, var3, var12, var11.add((float)var1, (float)var2, (float)var3));
+ }
+ }
+
+ private boolean xIntersects(Vec3D var1) {
+ return var1 == null?false:var1.y >= this.y1 && var1.y <= this.y2 && var1.z >= this.z1 && var1.z <= this.z2;
+ }
+
+ private boolean yIntersects(Vec3D var1) {
+ return var1 == null?false:var1.x >= this.x1 && var1.x <= this.x2 && var1.z >= this.z1 && var1.z <= this.z2;
+ }
+
+ private boolean zIntersects(Vec3D var1) {
+ return var1 == null?false:var1.x >= this.x1 && var1.x <= this.x2 && var1.y >= this.y1 && var1.y <= this.y2;
+ }
+
+ public void explode(Level var1, int var2, int var3, int var4) {}
+
+ public boolean render(Level var1, int var2, int var3, int var4, ShapeRenderer var5) {
+ boolean var6 = false;
+ float var7 = 0.5F;
+ float var8 = 0.8F;
+ float var9 = 0.6F;
+ float var10;
+ if(this.canRenderSide(var1, var2, var3 - 1, var4, 0)) {
+ var10 = this.getBrightness(var1, var2, var3 - 1, var4);
+ var5.color(var7 * var10, var7 * var10, var7 * var10);
+ this.renderInside(var5, var2, var3, var4, 0);
+ var6 = true;
+ }
+
+ if(this.canRenderSide(var1, var2, var3 + 1, var4, 1)) {
+ var10 = this.getBrightness(var1, var2, var3 + 1, var4);
+ var5.color(var10 * 1.0F, var10 * 1.0F, var10 * 1.0F);
+ this.renderInside(var5, var2, var3, var4, 1);
+ var6 = true;
+ }
+
+ if(this.canRenderSide(var1, var2, var3, var4 - 1, 2)) {
+ var10 = this.getBrightness(var1, var2, var3, var4 - 1);
+ var5.color(var8 * var10, var8 * var10, var8 * var10);
+ this.renderInside(var5, var2, var3, var4, 2);
+ var6 = true;
+ }
+
+ if(this.canRenderSide(var1, var2, var3, var4 + 1, 3)) {
+ var10 = this.getBrightness(var1, var2, var3, var4 + 1);
+ var5.color(var8 * var10, var8 * var10, var8 * var10);
+ this.renderInside(var5, var2, var3, var4, 3);
+ var6 = true;
+ }
+
+ if(this.canRenderSide(var1, var2 - 1, var3, var4, 4)) {
+ var10 = this.getBrightness(var1, var2 - 1, var3, var4);
+ var5.color(var9 * var10, var9 * var10, var9 * var10);
+ this.renderInside(var5, var2, var3, var4, 4);
+ var6 = true;
+ }
+
+ if(this.canRenderSide(var1, var2 + 1, var3, var4, 5)) {
+ var10 = this.getBrightness(var1, var2 + 1, var3, var4);
+ var5.color(var9 * var10, var9 * var10, var9 * var10);
+ this.renderInside(var5, var2, var3, var4, 5);
+ var6 = true;
+ }
+
+ return var6;
+ }
+
+ public int getRenderPass() {
+ return 0;
+ }
+
+ static {
+ Block var10000 = (new StoneBlock(1, 1)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 1.0F);
+ boolean var0 = false;
+ Block var1 = var10000;
+ var10000.explodes = false;
+ STONE = var1;
+ GRASS = (new GrassBlock(2)).setData(Tile$SoundType.grass, 0.9F, 1.0F, 0.6F);
+ DIRT = (new DirtBlock(3, 2)).setData(Tile$SoundType.grass, 0.8F, 1.0F, 0.5F);
+ var10000 = (new Block(4, 16)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 1.5F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ COBBLESTONE = var1;
+ WOOD = (new Block(5, 4)).setData(Tile$SoundType.wood, 1.0F, 1.0F, 1.5F);
+ SAPLING = (new SaplingBlock(6, 15)).setData(Tile$SoundType.none, 0.7F, 1.0F, 0.0F);
+ var10000 = (new Block(7, 17)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 999.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ BEDROCK = var1;
+ WATER = (new LiquidBlock(8, LiquidType.WATER)).setData(Tile$SoundType.none, 1.0F, 1.0F, 100.0F);
+ STATIONARY_WATER = (new StillLiquidBlock(9, LiquidType.WATER)).setData(Tile$SoundType.none, 1.0F, 1.0F, 100.0F);
+ LAVA = (new LiquidBlock(10, LiquidType.LAVA)).setData(Tile$SoundType.none, 1.0F, 1.0F, 100.0F);
+ STATIONARY_LAVA = (new StillLiquidBlock(11, LiquidType.LAVA)).setData(Tile$SoundType.none, 1.0F, 1.0F, 100.0F);
+ SAND = (new SandBlock(12, 18)).setData(Tile$SoundType.gravel, 0.8F, 1.0F, 0.5F);
+ GRAVEL = (new SandBlock(13, 19)).setData(Tile$SoundType.gravel, 0.8F, 1.0F, 0.6F);
+ var10000 = (new OreBlock(14, 32)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 3.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ GOLD_ORE = var1;
+ var10000 = (new OreBlock(15, 33)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 3.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ IRON_ORE = var1;
+ var10000 = (new OreBlock(16, 34)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 3.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ COAL_ORE = var1;
+ LOG = (new WoodBlock(17)).setData(Tile$SoundType.wood, 1.0F, 1.0F, 2.5F);
+ LEAVES = (new LeavesBlock(18, 22)).setData(Tile$SoundType.grass, 1.0F, 0.4F, 0.2F);
+ SPONGE = (new SpongeBlock(19)).setData(Tile$SoundType.cloth, 1.0F, 0.9F, 0.6F);
+ GLASS = (new GlassBlock(20, 49, false)).setData(Tile$SoundType.metal, 1.0F, 1.0F, 0.3F);
+ RED_WOOL = (new Block(21, 64)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ ORANGE_WOOL = (new Block(22, 65)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ YELLOW_WOOL = (new Block(23, 66)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ LIME_WOOL = (new Block(24, 67)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ GREEN_WOOL = (new Block(25, 68)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ AQUA_GREEN_WOOL = (new Block(26, 69)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ CYAN_WOOL = (new Block(27, 70)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ BLUE_WOOL = (new Block(28, 71)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ PURPLE_WOOL = (new Block(29, 72)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ INDIGO_WOOL = (new Block(30, 73)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ VIOLET_WOOL = (new Block(31, 74)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ MAGENTA_WOOL = (new Block(32, 75)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ PINK_WOOL = (new Block(33, 76)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ BLACK_WOOL = (new Block(34, 77)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ GRAY_WOOL = (new Block(35, 78)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ WHITE_WOOL = (new Block(36, 79)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.8F);
+ DANDELION = (new FlowerBlock(37, 13)).setData(Tile$SoundType.none, 0.7F, 1.0F, 0.0F);
+ ROSE = (new FlowerBlock(38, 12)).setData(Tile$SoundType.none, 0.7F, 1.0F, 0.0F);
+ BROWN_MUSHROOM = (new MushroomBlock(39, 29)).setData(Tile$SoundType.none, 0.7F, 1.0F, 0.0F);
+ RED_MUSHROOM = (new MushroomBlock(40, 28)).setData(Tile$SoundType.none, 0.7F, 1.0F, 0.0F);
+ var10000 = (new MetalBlock(41, 40)).setData(Tile$SoundType.metal, 0.7F, 1.0F, 3.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ GOLD_BLOCK = var1;
+ var10000 = (new MetalBlock(42, 39)).setData(Tile$SoundType.metal, 0.7F, 1.0F, 5.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ IRON_BLOCK = var1;
+ var10000 = (new SlabBlock(43, true)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 2.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ DOUBLE_SLAB = var1;
+ var10000 = (new SlabBlock(44, false)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 2.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ SLAB = var1;
+ var10000 = (new Block(45, 7)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 2.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ BRICK = var1;
+ TNT = (new TNTBlock(46, 8)).setData(Tile$SoundType.cloth, 1.0F, 1.0F, 0.0F);
+ BOOKSHELF = (new BookshelfBlock(47, 35)).setData(Tile$SoundType.wood, 1.0F, 1.0F, 1.5F);
+ var10000 = (new Block(48, 36)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 1.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ MOSSY_COBBLESTONE = var1;
+ var10000 = (new StoneBlock(49, 37)).setData(Tile$SoundType.stone, 1.0F, 1.0F, 10.0F);
+ var0 = false;
+ var1 = var10000;
+ var10000.explodes = false;
+ OBSIDIAN = var1;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/BookshelfBlock.java b/src/main/java/com/mojang/minecraft/level/tile/BookshelfBlock.java
new file mode 100644
index 0000000..e9a90ee
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/BookshelfBlock.java
@@ -0,0 +1,28 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class BookshelfBlock extends Block {
+
+ public BookshelfBlock(int var1, int var2) {
+ super(47, 35);
+ }
+
+ protected final int getTextureId(int texture) {
+ return texture <= 1?4:this.textureId;
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.BOOKSHELF.id;
+ }
+
+ public final int getDropCount() {
+ return 0;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/DirtBlock.java b/src/main/java/com/mojang/minecraft/level/tile/DirtBlock.java
new file mode 100644
index 0000000..fa0b366
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/DirtBlock.java
@@ -0,0 +1,20 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class DirtBlock extends Block {
+
+ protected DirtBlock(int var1, int var2) {
+ super(3, 2);
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.DIRT.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/FlowerBlock.java b/src/main/java/com/mojang/minecraft/level/tile/FlowerBlock.java
new file mode 100644
index 0000000..f09d98b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/FlowerBlock.java
@@ -0,0 +1,103 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.util.MathHelper;
+
+import java.util.Random;
+
+public class FlowerBlock extends Block {
+
+ protected FlowerBlock(int var1, int var2) {
+ super(var1);
+ this.textureId = var2;
+ this.setPhysics(true);
+ float var3 = 0.2F;
+ this.setBounds(0.5F - var3, 0.0F, 0.5F - var3, var3 + 0.5F, var3 * 3.0F, var3 + 0.5F);
+ }
+
+ public void update(Level level, int x, int y, int z, Random rand) {
+ if(!level.growTrees) {
+ int var6 = level.getTile(x, y - 1, z);
+ if(!level.isLit(x, y, z) || var6 != Block.DIRT.id && var6 != Block.GRASS.id) {
+ level.setTile(x, y, z, 0);
+ }
+
+ }
+ }
+
+ private void render(ShapeRenderer var1, float var2, float var3, float var4) {
+ int var15;
+ int var5 = (var15 = this.getTextureId(15)) % 16 << 4;
+ int var6 = var15 / 16 << 4;
+ float var16 = (float)var5 / 256.0F;
+ float var17 = ((float)var5 + 15.99F) / 256.0F;
+ float var7 = (float)var6 / 256.0F;
+ float var18 = ((float)var6 + 15.99F) / 256.0F;
+
+ for(int var8 = 0; var8 < 2; ++var8) {
+ float var9 = (float)((double)MathHelper.sin((float)var8 * 3.1415927F / 2.0F + 0.7853982F) * 0.5D);
+ float var10 = (float)((double)MathHelper.cos((float)var8 * 3.1415927F / 2.0F + 0.7853982F) * 0.5D);
+ float var11 = var2 + 0.5F - var9;
+ var9 += var2 + 0.5F;
+ float var13 = var3 + 1.0F;
+ float var14 = var4 + 0.5F - var10;
+ var10 += var4 + 0.5F;
+ var1.vertexUV(var11, var13, var14, var17, var7);
+ var1.vertexUV(var9, var13, var10, var16, var7);
+ var1.vertexUV(var9, var3, var10, var16, var18);
+ var1.vertexUV(var11, var3, var14, var17, var18);
+ var1.vertexUV(var9, var13, var10, var17, var7);
+ var1.vertexUV(var11, var13, var14, var16, var7);
+ var1.vertexUV(var11, var3, var14, var16, var18);
+ var1.vertexUV(var9, var3, var10, var17, var18);
+ }
+
+ }
+
+ public final boolean isOpaque() {
+ return false;
+ }
+
+ public final boolean isSolid() {
+ return false;
+ }
+
+ public final void renderPreview(ShapeRenderer var1) {
+ var1.normal(0.0F, 1.0F, 0.0F);
+ var1.begin();
+ this.render(var1, 0.0F, 0.4F, -0.3F);
+ var1.end();
+ }
+
+ public final boolean isCube() {
+ return false;
+ }
+
+ public final boolean render(Level var1, int var2, int var3, int var4, ShapeRenderer var5) {
+ float var6 = var1.getBrightness(var2, var3, var4);
+ var5.color(var6, var6, var6);
+ this.render(var5, (float)var2, (float)var3, (float)var4);
+ return true;
+ }
+
+ public final void renderFullbright(ShapeRenderer shapeRenderer) {
+ shapeRenderer.color(1.0F, 1.0F, 1.0F);
+ this.render(shapeRenderer, (float)-2, 0.0F, 0.0F);
+ }
+
+ @Override
+ public AABB getCollisionBox(int x, int y, int z)
+ {
+ return null;
+ }
+
+ public int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return this == Block.ROSE ? Block.ROSE.id : Block.DANDELION.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/GlassBlock.java b/src/main/java/com/mojang/minecraft/level/tile/GlassBlock.java
new file mode 100644
index 0000000..8ebbc25
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/GlassBlock.java
@@ -0,0 +1,29 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+
+public final class GlassBlock extends Block {
+
+ private boolean showNeighborSides = false;
+
+
+ protected GlassBlock(int var1, int var2, boolean var3) {
+ super(20, 49);
+ }
+
+ public final boolean isSolid() {
+ return false;
+ }
+
+ public final boolean canRenderSide(Level level, int x, int y, int z, int side) {
+ int var6 = level.getTile(x, y, z);
+ return !this.showNeighborSides && var6 == this.id?false:super.canRenderSide(level, x, y, z, side);
+ }
+
+ public final boolean isOpaque() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/GrassBlock.java b/src/main/java/com/mojang/minecraft/level/tile/GrassBlock.java
new file mode 100644
index 0000000..8599528
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/GrassBlock.java
@@ -0,0 +1,44 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import java.util.Random;
+
+public final class GrassBlock extends Block {
+
+ protected GrassBlock(int var1) {
+ super(2);
+ this.textureId = 3;
+ this.setPhysics(true);
+ }
+
+ protected final int getTextureId(int texture) {
+ return texture == 1 ? 0 : (texture == 0 ? 2 : Minecraft.settings.ofBetterGrass ? 0 : 3);
+ }
+
+ public final void update(Level level, int x, int y, int z, Random rand) {
+ if(rand.nextInt(4) == 0) {
+ if(!level.isLit(x, y, z)) {
+ level.setTile(x, y, z, Block.DIRT.id);
+ } else {
+ for(int var9 = 0; var9 < 4; ++var9) {
+ int var6 = x + rand.nextInt(3) - 1;
+ int var7 = y + rand.nextInt(5) - 3;
+ int var8 = z + rand.nextInt(3) - 1;
+ if(level.getTile(var6, var7, var8) == Block.DIRT.id && level.isLit(var6, var7, var8)) {
+ level.setTile(var6, var7, var8, Block.GRASS.id);
+ }
+ }
+
+ }
+ }
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.DIRT.getDrop();
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/LeavesBaseBlock.java b/src/main/java/com/mojang/minecraft/level/tile/LeavesBaseBlock.java
new file mode 100644
index 0000000..20a9ff6
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/LeavesBaseBlock.java
@@ -0,0 +1,26 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.level.Level;
+
+public class LeavesBaseBlock extends Block {
+
+ private boolean showNeighborSides = true;
+
+
+ protected LeavesBaseBlock(int var1, int var2, boolean var3) {
+ super(var1, var2);
+ }
+
+ public final boolean isSolid() {
+ return false;
+ }
+
+ public final boolean canRenderSide(Level level, int x, int y, int z, int side) {
+ int var6 = level.getTile(x, y, z);
+ return !this.showNeighborSides && var6 == this.id?false:super.canRenderSide(level, x, y, z, side);
+ }
+
+ public final boolean isOpaque() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/LeavesBlock.java b/src/main/java/com/mojang/minecraft/level/tile/LeavesBlock.java
new file mode 100644
index 0000000..0730acb
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/LeavesBlock.java
@@ -0,0 +1,19 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.level.tile.LeavesBaseBlock;
+
+public final class LeavesBlock extends LeavesBaseBlock {
+
+ protected LeavesBlock(int var1, int var2) {
+ super(18, 22, true);
+ }
+
+ public final int getDropCount() {
+ return random.nextInt(10) == 0?1:0;
+ }
+
+ public final int getDrop() {
+ return Block.SAPLING.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/LiquidBlock.java b/src/main/java/com/mojang/minecraft/level/tile/LiquidBlock.java
new file mode 100644
index 0000000..de06907
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/LiquidBlock.java
@@ -0,0 +1,168 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.phys.AABB;
+import com.mojang.minecraft.render.ShapeRenderer;
+
+import java.util.Random;
+
+public class LiquidBlock extends Block {
+
+ protected LiquidType type;
+ protected int stillId;
+ protected int movingId;
+
+
+ protected LiquidBlock(int var1, LiquidType var2) {
+ super(var1);
+ this.type = var2;
+ this.textureId = 14;
+ if(var2 == LiquidType.LAVA) {
+ this.textureId = 30;
+ }
+
+ Block.liquid[var1] = true;
+ this.movingId = var1;
+ this.stillId = var1 + 1;
+ float var4 = 0.01F;
+ float var3 = 0.1F;
+ this.setBounds(var4 + 0.0F, 0.0F - var3 + var4, var4 + 0.0F, var4 + 1.0F, 1.0F - var3 + var4, var4 + 1.0F);
+ this.setPhysics(true);
+ if(var2 == LiquidType.LAVA) {
+ this.setTickDelay(16);
+ }
+
+ }
+
+ public final boolean isCube() {
+ return false;
+ }
+
+ public final void onPlace(Level level, int x, int y, int z) {
+ level.addToTickNextTick(x, y, z, this.movingId);
+ }
+
+ public void update(Level level, int x, int y, int z, Random rand) {
+ boolean var7 = false;
+ z = z;
+ y = y;
+ x = x;
+ level = level;
+ boolean var8 = false;
+
+ boolean var6;
+ do {
+ --y;
+ if(level.getTile(x, y, z) != 0 || !this.canFlow(level, x, y, z)) {
+ break;
+ }
+
+ if(var6 = level.setTile(x, y, z, this.movingId)) {
+ var8 = true;
+ }
+ } while(var6 && this.type != LiquidType.LAVA);
+
+ ++y;
+ if(this.type == LiquidType.WATER || !var8) {
+ var8 = var8 | this.flow(level, x - 1, y, z) | this.flow(level, x + 1, y, z) | this.flow(level, x, y, z - 1) | this.flow(level, x, y, z + 1);
+ }
+
+ if(!var8) {
+ level.setTileNoUpdate(x, y, z, this.stillId);
+ } else {
+ level.addToTickNextTick(x, y, z, this.movingId);
+ }
+
+ }
+
+ private boolean canFlow(Level var1, int var2, int var3, int var4) {
+ if(this.type == LiquidType.WATER) {
+ for(int var7 = var2 - 2; var7 <= var2 + 2; ++var7) {
+ for(int var5 = var3 - 2; var5 <= var3 + 2; ++var5) {
+ for(int var6 = var4 - 2; var6 <= var4 + 2; ++var6) {
+ if(var1.getTile(var7, var5, var6) == Block.SPONGE.id) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean flow(Level var1, int var2, int var3, int var4) {
+ if(var1.getTile(var2, var3, var4) == 0) {
+ if(!this.canFlow(var1, var2, var3, var4)) {
+ return false;
+ }
+
+ if(var1.setTile(var2, var3, var4, this.movingId)) {
+ var1.addToTickNextTick(var2, var3, var4, this.movingId);
+ }
+ }
+
+ return false;
+ }
+
+ protected final float getBrightness(Level level, int x, int y, int z) {
+ return this.type == LiquidType.LAVA?100.0F: level.getBrightness(x, y, z);
+ }
+
+ public final boolean canRenderSide(Level level, int x, int y, int z, int side) {
+ int var6;
+ return x >= 0 && y >= 0 && z >= 0 && x < level.width && z < level.height?((var6 = level.getTile(x, y, z)) != this.movingId && var6 != this.stillId?(side == 1 && (level.getTile(x - 1, y, z) == 0 || level.getTile(x + 1, y, z) == 0 || level.getTile(x, y, z - 1) == 0 || level.getTile(x, y, z + 1) == 0)?true:super.canRenderSide(level, x, y, z, side)):false):false;
+ }
+
+ public final void renderInside(ShapeRenderer shapeRenderer, int x, int y, int z, int side) {
+ super.renderInside(shapeRenderer, x, y, z, side);
+ super.renderSide(shapeRenderer, x, y, z, side);
+ }
+
+ public final boolean isOpaque() {
+ return true;
+ }
+
+ public final boolean isSolid() {
+ return false;
+ }
+
+ public final LiquidType getLiquidType() {
+ return this.type;
+ }
+
+ public void onNeighborChange(Level var1, int var2, int var3, int var4, int var5) {
+ if(var5 != 0) {
+ LiquidType var6 = Block.blocks[var5].getLiquidType();
+ if(this.type == LiquidType.WATER && var6 == LiquidType.LAVA || var6 == LiquidType.WATER && this.type == LiquidType.LAVA) {
+ var1.setTile(var2, var3, var4, Block.STONE.id);
+ return;
+ }
+ }
+
+ var1.addToTickNextTick(var2, var3, var4, var5);
+ }
+
+ public final int getTickDelay() {
+ return this.type == LiquidType.LAVA?5:0;
+ }
+
+ public final void dropItems(Level var1, int var2, int var3, int var4, float var5) {}
+
+ public final void onBreak(Level var1, int var2, int var3, int var4) {}
+
+ public final int getDropCount() {
+ return 0;
+ }
+
+ public final int getRenderPass() {
+ return this.type == LiquidType.WATER?1:0;
+ }
+
+ @Override
+ public AABB getCollisionBox(int x, int y, int z)
+ {
+ return null;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/MetalBlock.java b/src/main/java/com/mojang/minecraft/level/tile/MetalBlock.java
new file mode 100644
index 0000000..e439f89
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/MetalBlock.java
@@ -0,0 +1,25 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class MetalBlock extends Block {
+
+ public MetalBlock(int var1, int var2) {
+ super(var1);
+ this.textureId = var2;
+ }
+
+ protected final int getTextureId(int texture) {
+ return texture == 1?this.textureId - 16:(texture == 0?this.textureId + 16:this.textureId);
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return this == Block.GOLD_BLOCK ? Block.GOLD_BLOCK.id : Block.IRON_BLOCK.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/MushroomBlock.java b/src/main/java/com/mojang/minecraft/level/tile/MushroomBlock.java
new file mode 100644
index 0000000..f63b611
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/MushroomBlock.java
@@ -0,0 +1,32 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.level.tile.FlowerBlock;
+import java.util.Random;
+
+public final class MushroomBlock extends FlowerBlock {
+
+ protected MushroomBlock(int var1, int var2) {
+ super(var1, var2);
+ float var3 = 0.2F;
+ this.setBounds(0.5F - var3, 0.0F, 0.5F - var3, var3 + 0.5F, var3 * 2.0F, var3 + 0.5F);
+ }
+
+ public final void update(Level level, int x, int y, int z, Random rand) {
+ int var6 = level.getTile(x, y - 1, z);
+ if(level.isLit(x, y, z) || var6 != Block.STONE.id && var6 != Block.GRAVEL.id && var6 != Block.COBBLESTONE.id) {
+ level.setTile(x, y, z, 0);
+ }
+
+ }
+
+ @Override
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return this == Block.RED_MUSHROOM ? Block.RED_MUSHROOM.id : Block.BROWN_MUSHROOM.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/OreBlock.java b/src/main/java/com/mojang/minecraft/level/tile/OreBlock.java
new file mode 100644
index 0000000..d1e5c02
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/OreBlock.java
@@ -0,0 +1,24 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class OreBlock extends Block {
+
+ public OreBlock(int var1, int var2) {
+ super(var1, var2);
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return this == Block.COAL_ORE?Block.SLAB.id:(this == Block.GOLD_ORE?Block.GOLD_BLOCK.id:(this == Block.IRON_ORE?Block.IRON_BLOCK.id:this.id));
+ }
+
+ public final int getDropCount() {
+ return random.nextInt(3) + 1;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/SandBlock.java b/src/main/java/com/mojang/minecraft/level/tile/SandBlock.java
new file mode 100644
index 0000000..793db28
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/SandBlock.java
@@ -0,0 +1,55 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class SandBlock extends Block {
+
+ public SandBlock(int var1, int var2) {
+ super(var1, var2);
+ }
+
+ public final void onPlace(Level level, int x, int y, int z) {
+ this.fall(level, x, y, z);
+ }
+
+ public final void onNeighborChange(Level var1, int var2, int var3, int var4, int var5) {
+ this.fall(var1, var2, var3, var4);
+ }
+
+ private void fall(Level var1, int var2, int var3, int var4) {
+ int var11 = var2;
+ int var5 = var3;
+ int var6 = var4;
+
+ while(true) {
+ int var8 = var5 - 1;
+ int var10;
+ LiquidType var12;
+ if(!((var10 = var1.getTile(var11, var8, var6)) == 0?true:((var12 = Block.blocks[var10].getLiquidType()) == LiquidType.WATER?true:var12 == LiquidType.LAVA)) || var5 <= 0) {
+ if(var5 != var3) {
+ if((var10 = var1.getTile(var11, var5, var6)) > 0 && Block.blocks[var10].getLiquidType() != LiquidType.NOT_LIQUID) {
+ var1.setTileNoUpdate(var11, var5, var6, 0);
+ }
+
+ var1.swap(var2, var3, var4, var11, var5, var6);
+ }
+
+ return;
+ }
+
+ --var5;
+ }
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.SAND.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/SaplingBlock.java b/src/main/java/com/mojang/minecraft/level/tile/SaplingBlock.java
new file mode 100644
index 0000000..48cc55a
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/SaplingBlock.java
@@ -0,0 +1,38 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.level.tile.FlowerBlock;
+import java.util.Random;
+
+public final class SaplingBlock extends FlowerBlock {
+
+ protected SaplingBlock(int var1, int var2) {
+ super(6, 15);
+ float var3 = 0.4F;
+ this.setBounds(0.5F - var3, 0.0F, 0.5F - var3, var3 + 0.5F, var3 * 2.0F, var3 + 0.5F);
+ }
+
+ public final void update(Level level, int x, int y, int z, Random rand) {
+ int var6 = level.getTile(x, y - 1, z);
+ if(level.isLit(x, y, z) && (var6 == Block.DIRT.id || var6 == Block.GRASS.id)) {
+ if(rand.nextInt(5) == 0) {
+ level.setTileNoUpdate(x, y, z, 0);
+ if(!level.maybeGrowTree(x, y, z)) {
+ level.setTileNoUpdate(x, y, z, this.id);
+ }
+ }
+
+ } else {
+ level.setTile(x, y, z, 0);
+ }
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.SAPLING.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/SlabBlock.java b/src/main/java/com/mojang/minecraft/level/tile/SlabBlock.java
new file mode 100644
index 0000000..1a155e0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/SlabBlock.java
@@ -0,0 +1,67 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class SlabBlock extends Block {
+
+ private boolean doubleSlab;
+
+
+ public SlabBlock(int var1, boolean var2) {
+ super(var1, 6);
+ this.doubleSlab = var2;
+ if(!var2) {
+ this.setBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
+ }
+
+ }
+
+ protected final int getTextureId(int texture) {
+ return texture <= 1?6:5;
+ }
+
+ public final boolean isSolid() {
+ return this.doubleSlab;
+ }
+
+ public final void onNeighborChange(Level var1, int var2, int var3, int var4, int var5) {
+ if(this == Block.SLAB) {
+ ;
+ }
+ }
+
+ public final void onAdded(Level level, int x, int y, int z) {
+ if(this != Block.SLAB) {
+ super.onAdded(level, x, y, z);
+ }
+
+ if(level.getTile(x, y - 1, z) == SLAB.id) {
+ level.setTile(x, y, z, 0);
+ level.setTile(x, y - 1, z, Block.DOUBLE_SLAB.id);
+ }
+
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.SLAB.id;
+ }
+
+ public final boolean isCube() {
+ return this.doubleSlab;
+ }
+
+ public final boolean canRenderSide(Level level, int x, int y, int z, int side) {
+ if(this != Block.SLAB) {
+ super.canRenderSide(level, x, y, z, side);
+ }
+
+ return side == 1?true:(!super.canRenderSide(level, x, y, z, side)?false:(side == 0?true: level.getTile(x, y, z) != this.id));
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/SpongeBlock.java b/src/main/java/com/mojang/minecraft/level/tile/SpongeBlock.java
new file mode 100644
index 0000000..6e13069
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/SpongeBlock.java
@@ -0,0 +1,46 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class SpongeBlock extends Block {
+
+ protected SpongeBlock(int var1) {
+ super(19);
+ this.textureId = 48;
+ }
+
+ public final void onAdded(Level level, int x, int y, int z) {
+ for(int var7 = x - 2; var7 <= x + 2; ++var7) {
+ for(int var5 = y - 2; var5 <= y + 2; ++var5) {
+ for(int var6 = z - 2; var6 <= z + 2; ++var6) {
+ if(level.isWater(var7, var5, var6)) {
+ level.setTileNoNeighborChange(var7, var5, var6, 0);
+ }
+ }
+ }
+ }
+
+ }
+
+ public final void onRemoved(Level var1, int var2, int var3, int var4) {
+ for(int var7 = var2 - 2; var7 <= var2 + 2; ++var7) {
+ for(int var5 = var3 - 2; var5 <= var3 + 2; ++var5) {
+ for(int var6 = var4 - 2; var6 <= var4 + 2; ++var6) {
+ var1.updateNeighborsAt(var7, var5, var6, var1.getTile(var7, var5, var6));
+ }
+ }
+ }
+
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.SPONGE.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/StillLiquidBlock.java b/src/main/java/com/mojang/minecraft/level/tile/StillLiquidBlock.java
new file mode 100644
index 0000000..0709be0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/StillLiquidBlock.java
@@ -0,0 +1,57 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+
+import java.util.Random;
+
+public final class StillLiquidBlock extends LiquidBlock {
+
+ protected StillLiquidBlock(int var1, LiquidType var2) {
+ super(var1, var2);
+ this.movingId = var1 - 1;
+ this.stillId = var1;
+ this.setPhysics(false);
+ }
+
+ public final void update(Level level, int x, int y, int z, Random rand) {}
+
+ public final void onNeighborChange(Level var1, int var2, int var3, int var4, int var5) {
+ boolean var6 = false;
+ if(var1.getTile(var2 - 1, var3, var4) == 0) {
+ var6 = true;
+ }
+
+ if(var1.getTile(var2 + 1, var3, var4) == 0) {
+ var6 = true;
+ }
+
+ if(var1.getTile(var2, var3, var4 - 1) == 0) {
+ var6 = true;
+ }
+
+ if(var1.getTile(var2, var3, var4 + 1) == 0) {
+ var6 = true;
+ }
+
+ if(var1.getTile(var2, var3 - 1, var4) == 0) {
+ var6 = true;
+ }
+
+ if(var5 != 0) {
+ LiquidType var7 = Block.blocks[var5].getLiquidType();
+ if(this.type == LiquidType.WATER && var7 == LiquidType.LAVA || var7 == LiquidType.WATER && this.type == LiquidType.LAVA) {
+ var1.setTile(var2, var3, var4, Block.STONE.id);
+ return;
+ }
+ }
+
+ if(var6) {
+ var1.setTileNoUpdate(var2, var3, var4, this.movingId);
+ var1.addToTickNextTick(var2, var3, var4, this.movingId);
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/StoneBlock.java b/src/main/java/com/mojang/minecraft/level/tile/StoneBlock.java
new file mode 100644
index 0000000..9518e37
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/StoneBlock.java
@@ -0,0 +1,20 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class StoneBlock extends Block {
+
+ public StoneBlock(int var1, int var2) {
+ super(var1, var2);
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.COBBLESTONE.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/TNTBlock.java b/src/main/java/com/mojang/minecraft/level/tile/TNTBlock.java
new file mode 100644
index 0000000..7db3915
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/TNTBlock.java
@@ -0,0 +1,48 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.item.PrimedTnt;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.particle.ParticleManager;
+
+public final class TNTBlock extends Block {
+
+ public TNTBlock(int var1, int var2) {
+ super(46, 8);
+ }
+
+ protected final int getTextureId(int texture) {
+ return texture == 0?this.textureId + 2:(texture == 1?this.textureId + 1:this.textureId);
+ }
+
+ public final int getDropCount() {
+ return 0;
+ }
+
+ public final void explode(Level var1, int var2, int var3, int var4) {
+ if(!var1.creativeMode) {
+ PrimedTnt var5;
+ (var5 = new PrimedTnt(var1, (float)var2 + 0.5F, (float)var3 + 0.5F, (float)var4 + 0.5F)).life = random.nextInt(var5.life / 4) + var5.life / 8;
+ var1.addEntity(var5);
+ }
+
+ }
+
+ public final void spawnBreakParticles(Level level, int x, int y, int z, ParticleManager particleManager) {
+ if(!level.creativeMode) {
+ level.addEntity(new PrimedTnt(level, (float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F));
+ } else {
+ super.spawnBreakParticles(level, x, y, z, particleManager);
+ }
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.TNT.id;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/Tile$SoundType.java b/src/main/java/com/mojang/minecraft/level/tile/Tile$SoundType.java
new file mode 100644
index 0000000..84fff91
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/Tile$SoundType.java
@@ -0,0 +1,35 @@
+package com.mojang.minecraft.level.tile;
+
+import com.mojang.minecraft.level.tile.Block;
+
+public enum Tile$SoundType {
+
+ none("none", 0, "-", 0.0F, 0.0F),
+ grass("grass", 1, "grass", 0.6F, 1.0F),
+ cloth("cloth", 2, "grass", 0.7F, 1.2F),
+ gravel("gravel", 3, "gravel", 1.0F, 1.0F),
+ stone("stone", 4, "stone", 1.0F, 1.0F),
+ metal("metal", 5, "stone", 1.0F, 2.0F),
+ wood("wood", 6, "wood", 1.0F, 1.0F);
+ public final String name;
+ private final float volume;
+ private final float pitch;
+ // $FF: synthetic field
+ private static final Tile$SoundType[] values = new Tile$SoundType[]{none, grass, cloth, gravel, stone, metal, wood};
+
+
+ private Tile$SoundType(String var1, int var2, String var3, float var4, float var5) {
+ this.name = var3;
+ this.volume = var4;
+ this.pitch = var5;
+ }
+
+ public final float getVolume() {
+ return this.volume / (Block.random.nextFloat() * 0.4F + 1.0F) * 0.5F;
+ }
+
+ public final float getPitch() {
+ return this.pitch / (Block.random.nextFloat() * 0.2F + 0.9F);
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/level/tile/WoodBlock.java b/src/main/java/com/mojang/minecraft/level/tile/WoodBlock.java
new file mode 100644
index 0000000..1805f72
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/level/tile/WoodBlock.java
@@ -0,0 +1,29 @@
+package com.mojang.minecraft.level.tile;
+
+import java.util.Random;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public final class WoodBlock extends Block {
+
+ protected WoodBlock(int var1) {
+ super(17);
+ this.textureId = 20;
+ }
+
+ public final int getDropCount() {
+ return random.nextInt(3) + 3;
+ }
+
+ public final int getDrop() {
+ if(Minecraft.settings.randomDrops) {
+ return new Random().nextInt(49 - 1 + 1) + 1;
+ }
+ return Block.WOOD.id;
+ }
+
+ protected final int getTextureId(int texture) {
+ return texture == 1?21:(texture == 0?21:20);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Creeper$1.java b/src/main/java/com/mojang/minecraft/mob/Creeper$1.java
new file mode 100644
index 0000000..2663cee
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Creeper$1.java
@@ -0,0 +1,46 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.mob.Creeper;
+import com.mojang.minecraft.mob.ai.BasicAttackAI;
+import com.mojang.minecraft.particle.TerrainParticle;
+import com.mojang.util.MathHelper;
+
+final class Creeper$1 extends BasicAttackAI {
+
+ public static final long serialVersionUID = 0L;
+ // $FF: synthetic field
+ final Creeper creeper;
+
+
+ Creeper$1(Creeper var1) {
+ this.creeper = var1;
+ }
+
+ public final boolean attack(Entity var1) {
+ if(!super.attack(var1)) {
+ return false;
+ } else {
+ this.mob.hurt(var1, 6);
+ return true;
+ }
+ }
+
+ public final void beforeRemove() {
+ float var1 = 4.0F;
+ this.level.explode(this.mob, this.mob.x, this.mob.y, this.mob.z, var1);
+
+ for(int var2 = 0; var2 < 500; ++var2) {
+ float var3 = (float)this.random.nextGaussian() * var1 / 4.0F;
+ float var4 = (float)this.random.nextGaussian() * var1 / 4.0F;
+ float var5 = (float)this.random.nextGaussian() * var1 / 4.0F;
+ float var6 = MathHelper.sqrt(var3 * var3 + var4 * var4 + var5 * var5);
+ float var7 = var3 / var6 / var6;
+ float var8 = var4 / var6 / var6;
+ var6 = var5 / var6 / var6;
+ this.level.particleEngine.spawnParticle(new TerrainParticle(this.level, this.mob.x + var3, this.mob.y + var4, this.mob.z + var5, var7, var8, var6, Block.LEAVES));
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Creeper.java b/src/main/java/com/mojang/minecraft/mob/Creeper.java
new file mode 100644
index 0000000..e27ce57
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Creeper.java
@@ -0,0 +1,28 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Creeper$1;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.util.MathHelper;
+
+public class Creeper extends Mob {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public Creeper(Level var1, float var2, float var3, float var4) {
+ super(var1);
+ this.heightOffset = 1.62F;
+ this.modelName = "creeper";
+ this.textureName = "/mob/creeper.png";
+ this.ai = new Creeper$1(this);
+ this.ai.defaultLookAngle = 45;
+ this.deathScore = 200;
+ this.setPos(var2, var3, var4);
+ }
+
+ public float getBrightness(float var1) {
+ float var2 = (float)(20 - this.health) / 20.0F;
+ return ((MathHelper.sin((float)this.tickCount + var1) * 0.5F + 0.5F) * var2 * 0.5F + 0.25F + var2 * 0.25F) * super.getBrightness(var1);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/HumanoidMob.java b/src/main/java/com/mojang/minecraft/mob/HumanoidMob.java
new file mode 100644
index 0000000..bf4175a
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/HumanoidMob.java
@@ -0,0 +1,70 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.model.HumanoidModel;
+import com.mojang.minecraft.model.Model;
+import com.mojang.minecraft.render.TextureManager;
+import org.lwjgl.opengl.GL11;
+
+public class HumanoidMob extends Mob {
+
+ public static final long serialVersionUID = 0L;
+ public boolean helmet = Math.random() < 0.20000000298023224D;
+ public boolean armor = Math.random() < 0.20000000298023224D;
+
+
+ public HumanoidMob(Level var1, float var2, float var3, float var4) {
+ super(var1);
+ this.modelName = "humanoid";
+ this.setPos(var2, var3, var4);
+ }
+
+ public void renderModel(TextureManager var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ super.renderModel(var1, var2, var3, var4, var5, var6, var7);
+ Model var9 = modelCache.getModel(this.modelName);
+ GL11.glEnable(3008);
+ if(this.allowAlpha) {
+ GL11.glEnable(2884);
+ }
+
+ if(this.hasHair) {
+ GL11.glDisable(2884);
+ HumanoidModel var10 = null;
+ (var10 = (HumanoidModel)var9).headwear.yaw = var10.head.yaw;
+ var10.headwear.pitch = var10.head.pitch;
+ var10.headwear.render(var7);
+ GL11.glEnable(2884);
+ }
+
+ if(this.armor || this.helmet) {
+ GL11.glBindTexture(3553, var1.load("/armor/plate.png"));
+ GL11.glDisable(2884);
+ HumanoidModel var8;
+ (var8 = (HumanoidModel)modelCache.getModel("humanoid.armor")).head.render = this.helmet;
+ var8.body.render = this.armor;
+ var8.rightArm.render = this.armor;
+ var8.leftArm.render = this.armor;
+ var8.rightLeg.render = false;
+ var8.leftLeg.render = false;
+ HumanoidModel var11 = (HumanoidModel)var9;
+ var8.head.yaw = var11.head.yaw;
+ var8.head.pitch = var11.head.pitch;
+ var8.rightArm.pitch = var11.rightArm.pitch;
+ var8.rightArm.roll = var11.rightArm.roll;
+ var8.leftArm.pitch = var11.leftArm.pitch;
+ var8.leftArm.roll = var11.leftArm.roll;
+ var8.rightLeg.pitch = var11.rightLeg.pitch;
+ var8.leftLeg.pitch = var11.leftLeg.pitch;
+ var8.head.render(var7);
+ var8.body.render(var7);
+ var8.rightArm.render(var7);
+ var8.leftArm.render(var7);
+ var8.rightLeg.render(var7);
+ var8.leftLeg.render(var7);
+ GL11.glEnable(2884);
+ }
+
+ GL11.glDisable(3008);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Mob.java b/src/main/java/com/mojang/minecraft/mob/Mob.java
new file mode 100644
index 0000000..36a3e29
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Mob.java
@@ -0,0 +1,443 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.ai.AI;
+import com.mojang.minecraft.mob.ai.BasicAI;
+import com.mojang.minecraft.model.ModelManager;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import org.lwjgl.opengl.GL11;
+
+public class Mob extends Entity {
+
+ public static final long serialVersionUID = 0L;
+ public static final int ATTACK_DURATION = 5;
+ public static final int TOTAL_AIR_SUPPLY = 300;
+ public static ModelManager modelCache;
+ public int invulnerableDuration = 20;
+ public float rot;
+ public float timeOffs;
+ public float speed;
+ public float rotA = (float)(Math.random() + 1.0D) * 0.01F;
+ protected float yBodyRot = 0.0F;
+ protected float yBodyRotO = 0.0F;
+ protected float oRun;
+ protected float run;
+ protected float animStep;
+ protected float animStepO;
+ protected int tickCount = 0;
+ public boolean hasHair = true;
+ protected String textureName = "/char.png";
+ public boolean allowAlpha = true;
+ public float rotOffs = 0.0F;
+ public String modelName = null;
+ protected float bobStrength = 1.0F;
+ protected int deathScore = 0;
+ public float renderOffset = 0.0F;
+ public int health = 20;
+ public int lastHealth;
+ public int invulnerableTime = 0;
+ public int airSupply = 300;
+ public int hurtTime;
+ public int hurtDuration;
+ public float hurtDir = 0.0F;
+ public int deathTime = 0;
+ public int attackTime = 0;
+ public float oTilt;
+ public float tilt;
+ protected boolean dead = false;
+ public AI ai;
+
+
+ public Mob(Level var1) {
+ super(var1);
+ this.setPos(this.x, this.y, this.z);
+ this.timeOffs = (float)Math.random() * 12398.0F;
+ this.rot = (float)(Math.random() * 3.1415927410125732D * 2.0D);
+ this.speed = 1.0F;
+ this.ai = new BasicAI();
+ this.footSize = 0.5F;
+ }
+
+ public boolean isPickable() {
+ return !this.removed;
+ }
+
+ public boolean isPushable() {
+ return !this.removed;
+ }
+
+ public final void tick() {
+ super.tick();
+ this.oTilt = this.tilt;
+ if(this.attackTime > 0) {
+ --this.attackTime;
+ }
+
+ if(this.hurtTime > 0) {
+ --this.hurtTime;
+ }
+
+ if(this.invulnerableTime > 0) {
+ --this.invulnerableTime;
+ }
+
+ if(this.health <= 0) {
+ ++this.deathTime;
+ if(this.deathTime > 20) {
+ if(this.ai != null) {
+ this.ai.beforeRemove();
+ }
+
+ this.remove();
+ }
+ }
+
+ if(this.isUnderWater()) {
+ if(this.airSupply > 0) {
+ --this.airSupply;
+ } else {
+ this.hurt((Entity)null, 2);
+ }
+ } else {
+ this.airSupply = 300;
+ }
+
+ if(this.isInWater()) {
+ this.fallDistance = 0.0F;
+ }
+
+ if(this.isInLava()) {
+ this.hurt((Entity)null, 10);
+ }
+
+ this.animStepO = this.animStep;
+ this.yBodyRotO = this.yBodyRot;
+ this.yRotO = this.yRot;
+ this.xRotO = this.xRot;
+ ++this.tickCount;
+ this.aiStep();
+ float var1 = this.x - this.xo;
+ float var2 = this.z - this.zo;
+ float var3 = MathHelper.sqrt(var1 * var1 + var2 * var2);
+ float var4 = this.yBodyRot;
+ float var5 = 0.0F;
+ this.oRun = this.run;
+ float var6 = 0.0F;
+ if(var3 > 0.05F) {
+ var6 = 1.0F;
+ var5 = var3 * 3.0F;
+ var4 = (float)Math.atan2((double)var2, (double)var1) * 180.0F / 3.1415927F - 90.0F;
+ }
+
+ if(!this.onGround) {
+ var6 = 0.0F;
+ }
+
+ this.run += (var6 - this.run) * 0.3F;
+
+ for(var1 = var4 - this.yBodyRot; var1 < -180.0F; var1 += 360.0F) {
+ ;
+ }
+
+ while(var1 >= 180.0F) {
+ var1 -= 360.0F;
+ }
+
+ this.yBodyRot += var1 * 0.1F;
+
+ for(var1 = this.yRot - this.yBodyRot; var1 < -180.0F; var1 += 360.0F) {
+ ;
+ }
+
+ while(var1 >= 180.0F) {
+ var1 -= 360.0F;
+ }
+
+ boolean var7 = var1 < -90.0F || var1 >= 90.0F;
+ if(var1 < -75.0F) {
+ var1 = -75.0F;
+ }
+
+ if(var1 >= 75.0F) {
+ var1 = 75.0F;
+ }
+
+ this.yBodyRot = this.yRot - var1;
+ this.yBodyRot += var1 * 0.1F;
+ if(var7) {
+ var5 = -var5;
+ }
+
+ while(this.yRot - this.yRotO < -180.0F) {
+ this.yRotO -= 360.0F;
+ }
+
+ while(this.yRot - this.yRotO >= 180.0F) {
+ this.yRotO += 360.0F;
+ }
+
+ while(this.yBodyRot - this.yBodyRotO < -180.0F) {
+ this.yBodyRotO -= 360.0F;
+ }
+
+ while(this.yBodyRot - this.yBodyRotO >= 180.0F) {
+ this.yBodyRotO += 360.0F;
+ }
+
+ while(this.xRot - this.xRotO < -180.0F) {
+ this.xRotO -= 360.0F;
+ }
+
+ while(this.xRot - this.xRotO >= 180.0F) {
+ this.xRotO += 360.0F;
+ }
+
+ this.animStep += var5;
+ }
+
+ public void aiStep() {
+ if(this.ai != null) {
+ this.ai.tick(this.level, this);
+ }
+
+ }
+
+ protected void bindTexture(TextureManager var1) {
+ this.textureId = var1.load(this.textureName);
+ GL11.glBindTexture(3553, this.textureId);
+ }
+
+ public void render(TextureManager var1, float var2) {
+ if(this.modelName != null) {
+ float var3;
+ if((var3 = (float)this.attackTime - var2) < 0.0F) {
+ var3 = 0.0F;
+ }
+
+ while(this.yBodyRotO - this.yBodyRot < -180.0F) {
+ this.yBodyRotO += 360.0F;
+ }
+
+ while(this.yBodyRotO - this.yBodyRot >= 180.0F) {
+ this.yBodyRotO -= 360.0F;
+ }
+
+ while(this.xRotO - this.xRot < -180.0F) {
+ this.xRotO += 360.0F;
+ }
+
+ while(this.xRotO - this.xRot >= 180.0F) {
+ this.xRotO -= 360.0F;
+ }
+
+ while(this.yRotO - this.yRot < -180.0F) {
+ this.yRotO += 360.0F;
+ }
+
+ while(this.yRotO - this.yRot >= 180.0F) {
+ this.yRotO -= 360.0F;
+ }
+
+ float var4 = this.yBodyRotO + (this.yBodyRot - this.yBodyRotO) * var2;
+ float var5 = this.oRun + (this.run - this.oRun) * var2;
+ float var6 = this.yRotO + (this.yRot - this.yRotO) * var2;
+ float var7 = this.xRotO + (this.xRot - this.xRotO) * var2;
+ var6 -= var4;
+ GL11.glPushMatrix();
+ float var8 = this.animStepO + (this.animStep - this.animStepO) * var2;
+ float var9;
+ GL11.glColor3f(var9 = this.getBrightness(var2), var9, var9);
+ var9 = 0.0625F;
+ float var10 = -Math.abs(MathHelper.cos(var8 * 0.6662F)) * 5.0F * var5 * this.bobStrength - 23.0F;
+ GL11.glTranslatef(this.xo + (this.x - this.xo) * var2, this.yo + (this.y - this.yo) * var2 - 1.62F + this.renderOffset, this.zo + (this.z - this.zo) * var2);
+ float var11;
+ if((var11 = (float)this.hurtTime - var2) > 0.0F || this.health <= 0) {
+ if(var11 < 0.0F) {
+ var11 = 0.0F;
+ } else {
+ var11 = MathHelper.sin((var11 /= (float)this.hurtDuration) * var11 * var11 * var11 * 3.1415927F) * 14.0F;
+ }
+
+ float var12 = 0.0F;
+ if(this.health <= 0) {
+ var12 = ((float)this.deathTime + var2) / 20.0F;
+ if((var11 += var12 * var12 * 800.0F) > 90.0F) {
+ var11 = 90.0F;
+ }
+ }
+
+ var12 = this.hurtDir;
+ GL11.glRotatef(180.0F - var4 + this.rotOffs, 0.0F, 1.0F, 0.0F);
+ GL11.glScalef(1.0F, 1.0F, 1.0F);
+ GL11.glRotatef(-var12, 0.0F, 1.0F, 0.0F);
+ GL11.glRotatef(-var11, 0.0F, 0.0F, 1.0F);
+ GL11.glRotatef(var12, 0.0F, 1.0F, 0.0F);
+ GL11.glRotatef(-(180.0F - var4 + this.rotOffs), 0.0F, 1.0F, 0.0F);
+ }
+
+ GL11.glTranslatef(0.0F, -var10 * var9, 0.0F);
+ GL11.glScalef(1.0F, -1.0F, 1.0F);
+ GL11.glRotatef(180.0F - var4 + this.rotOffs, 0.0F, 1.0F, 0.0F);
+ if(!this.allowAlpha) {
+ GL11.glDisable(3008);
+ } else {
+ GL11.glDisable(2884);
+ }
+
+ GL11.glScalef(-1.0F, 1.0F, 1.0F);
+ modelCache.getModel(this.modelName).attackOffset = var3 / 5.0F;
+ this.bindTexture(var1);
+ this.renderModel(var1, var8, var2, var5, var6, var7, var9);
+ if(this.invulnerableTime > this.invulnerableDuration - 10) {
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.75F);
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 1);
+ this.bindTexture(var1);
+ this.renderModel(var1, var8, var2, var5, var6, var7, var9);
+ GL11.glDisable(3042);
+ GL11.glBlendFunc(770, 771);
+ }
+
+ GL11.glEnable(3008);
+ if(this.allowAlpha) {
+ GL11.glEnable(2884);
+ }
+
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ GL11.glPopMatrix();
+ }
+ }
+
+ public void renderModel(TextureManager var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ modelCache.getModel(this.modelName).render(var2, var4, (float)this.tickCount + var3, var5, var6, var7);
+ }
+
+ public void heal(int var1) {
+ if(this.health > 0) {
+ this.health += var1;
+ if(this.health > 20) {
+ this.health = 20;
+ }
+
+ this.invulnerableTime = this.invulnerableDuration / 2;
+ }
+ }
+
+ public void hurt(Entity var1, int var2) {
+ if(!this.level.creativeMode) {
+ if(this.health > 0) {
+ this.ai.hurt(var1, var2);
+ if((float)this.invulnerableTime > (float)this.invulnerableDuration / 2.0F) {
+ if(this.lastHealth - var2 >= this.health) {
+ return;
+ }
+
+ this.health = this.lastHealth - var2;
+ } else {
+ this.lastHealth = this.health;
+ this.invulnerableTime = this.invulnerableDuration;
+ this.health -= var2;
+ this.hurtTime = this.hurtDuration = 10;
+ }
+
+ this.hurtDir = 0.0F;
+ if(var1 != null) {
+ float var3 = var1.x - this.x;
+ float var4 = var1.z - this.z;
+ this.hurtDir = (float)(Math.atan2((double)var4, (double)var3) * 180.0D / 3.1415927410125732D) - this.yRot;
+ this.knockback(var1, var2, var3, var4);
+ } else {
+ this.hurtDir = (float)((int)(Math.random() * 2.0D) * 180);
+ }
+
+ if(this.health <= 0) {
+ this.die(var1);
+ }
+
+ }
+ }
+ }
+
+ public void knockback(Entity var1, int var2, float var3, float var4) {
+ float var5 = MathHelper.sqrt(var3 * var3 + var4 * var4);
+ float var6 = 0.4F;
+ this.xd /= 2.0F;
+ this.yd /= 2.0F;
+ this.zd /= 2.0F;
+ this.xd -= var3 / var5 * var6;
+ this.yd += 0.4F;
+ this.zd -= var4 / var5 * var6;
+ if(this.yd > 0.4F) {
+ this.yd = 0.4F;
+ }
+
+ }
+
+ public void die(Entity var1) {
+ if(!this.level.creativeMode) {
+ if(this.deathScore > 0 && var1 != null) {
+ var1.awardKillScore(this, this.deathScore);
+ }
+
+ this.dead = true;
+ }
+ }
+
+ protected void causeFallDamage(float var1) {
+ if(!this.level.creativeMode) {
+ int var2;
+ if((var2 = (int)Math.ceil((double)(var1 - 3.0F))) > 0) {
+ this.hurt((Entity)null, var2);
+ }
+
+ }
+ }
+
+ public void travel(float var1, float var2) {
+ float var3;
+ if(this.isInWater()) {
+ var3 = this.y;
+ this.moveRelative(var1, var2, 0.02F);
+ this.move(this.xd, this.yd, this.zd);
+ this.xd *= 0.8F;
+ this.yd *= 0.8F;
+ this.zd *= 0.8F;
+ this.yd = (float)((double)this.yd - 0.02D);
+ if(this.horizontalCollision && this.isFree(this.xd, this.yd + 0.6F - this.y + var3, this.zd)) {
+ this.yd = 0.3F;
+ }
+
+ } else if(this.isInLava()) {
+ var3 = this.y;
+ this.moveRelative(var1, var2, 0.02F);
+ this.move(this.xd, this.yd, this.zd);
+ this.xd *= 0.5F;
+ this.yd *= 0.5F;
+ this.zd *= 0.5F;
+ this.yd = (float)((double)this.yd - 0.02D);
+ if(this.horizontalCollision && this.isFree(this.xd, this.yd + 0.6F - this.y + var3, this.zd)) {
+ this.yd = 0.3F;
+ }
+
+ } else {
+ this.moveRelative(var1, var2, this.onGround?0.1F:0.02F);
+ this.move(this.xd, this.yd, this.zd);
+ this.xd *= 0.91F;
+ this.yd *= 0.98F;
+ this.zd *= 0.91F;
+ this.yd = (float)((double)this.yd - 0.08D);
+ if(this.onGround) {
+ var3 = 0.6F;
+ this.xd *= var3;
+ this.zd *= var3;
+ }
+
+ }
+ }
+
+ public boolean isShootable() {
+ return true;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Pig.java b/src/main/java/com/mojang/minecraft/mob/Pig.java
new file mode 100644
index 0000000..fb6f286
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Pig.java
@@ -0,0 +1,34 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.item.Item;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.mob.QuadrupedMob;
+
+public class Pig extends QuadrupedMob {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public Pig(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4);
+ this.heightOffset = 1.72F;
+ this.modelName = "pig";
+ this.textureName = "/mob/pig.png";
+ }
+
+ public void die(Entity var1) {
+ if(var1 != null) {
+ var1.awardKillScore(this, 10);
+ }
+
+ int var2 = (int)(Math.random() + Math.random() + 1.0D);
+
+ for(int var3 = 0; var3 < var2; ++var3) {
+ this.level.addEntity(new Item(this.level, this.x, this.y, this.z, Block.BROWN_MUSHROOM.id));
+ }
+
+ super.die(var1);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/QuadrupedMob.java b/src/main/java/com/mojang/minecraft/mob/QuadrupedMob.java
new file mode 100644
index 0000000..385461d
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/QuadrupedMob.java
@@ -0,0 +1,17 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Mob;
+
+public class QuadrupedMob extends Mob {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public QuadrupedMob(Level var1, float var2, float var3, float var4) {
+ super(var1);
+ this.setSize(1.4F, 1.2F);
+ this.setPos(var2, var3, var4);
+ this.modelName = "pig";
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Sheep$1.java b/src/main/java/com/mojang/minecraft/mob/Sheep$1.java
new file mode 100644
index 0000000..25c205e
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Sheep$1.java
@@ -0,0 +1,51 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.mob.Sheep;
+import com.mojang.minecraft.mob.ai.BasicAI;
+import com.mojang.util.MathHelper;
+
+final class Sheep$1 extends BasicAI {
+
+ private static final long serialVersionUID = 1L;
+ // $FF: synthetic field
+ final Sheep sheep;
+
+
+ Sheep$1(Sheep var1) {
+ this.sheep = var1;
+ }
+
+ protected final void update() {
+ float var1 = MathHelper.sin(this.sheep.yRot * 3.1415927F / 180.0F);
+ float var2 = MathHelper.cos(this.sheep.yRot * 3.1415927F / 180.0F);
+ var1 = -0.7F * var1;
+ var2 = 0.7F * var2;
+ int var4 = (int)(this.mob.x + var1);
+ int var3 = (int)(this.mob.y - 2.0F);
+ int var5 = (int)(this.mob.z + var2);
+ if(this.sheep.grazing) {
+ if(this.level.getTile(var4, var3, var5) != Block.GRASS.id) {
+ this.sheep.grazing = false;
+ } else {
+ if(++this.sheep.grazingTime == 60) {
+ this.level.setTile(var4, var3, var5, Block.DIRT.id);
+ if(this.random.nextInt(5) == 0) {
+ this.sheep.hasFur = true;
+ }
+ }
+
+ this.xxa = 0.0F;
+ this.yya = 0.0F;
+ this.mob.xRot = (float)(40 + this.sheep.grazingTime / 2 % 2 * 10);
+ }
+ } else {
+ if(this.level.getTile(var4, var3, var5) == Block.GRASS.id) {
+ this.sheep.grazing = true;
+ this.sheep.grazingTime = 0;
+ }
+
+ super.update();
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Sheep.java b/src/main/java/com/mojang/minecraft/mob/Sheep.java
new file mode 100644
index 0000000..9eb126b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Sheep.java
@@ -0,0 +1,113 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.item.Item;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.mob.QuadrupedMob;
+import com.mojang.minecraft.mob.Sheep$1;
+import com.mojang.minecraft.model.AnimalModel;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.TextureManager;
+import org.lwjgl.opengl.GL11;
+
+public class Sheep extends QuadrupedMob {
+
+ public static final long serialVersionUID = 0L;
+ public boolean hasFur = true;
+ public boolean grazing = false;
+ public int grazingTime = 0;
+ public float graze;
+ public float grazeO;
+
+
+ public Sheep(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4);
+ this.setSize(1.4F, 1.72F);
+ this.setPos(var2, var3, var4);
+ this.heightOffset = 1.72F;
+ this.modelName = "sheep";
+ this.textureName = "/mob/sheep.png";
+ this.ai = new Sheep$1(this);
+ }
+
+ public void aiStep() {
+ super.aiStep();
+ this.grazeO = this.graze;
+ if(this.grazing) {
+ this.graze += 0.2F;
+ } else {
+ this.graze -= 0.2F;
+ }
+
+ if(this.graze < 0.0F) {
+ this.graze = 0.0F;
+ }
+
+ if(this.graze > 1.0F) {
+ this.graze = 1.0F;
+ }
+
+ }
+
+ public void die(Entity var1) {
+ if(var1 != null) {
+ var1.awardKillScore(this, 10);
+ }
+
+ int var2 = (int)(Math.random() + Math.random() + 1.0D);
+
+ for(int var3 = 0; var3 < var2; ++var3) {
+ this.level.addEntity(new Item(this.level, this.x, this.y, this.z, Block.BROWN_MUSHROOM.id));
+ }
+
+ super.die(var1);
+ }
+
+ public void hurt(Entity var1, int var2) {
+ if(this.hasFur && var1 instanceof Player) {
+ this.hasFur = false;
+ int var3 = (int)(Math.random() * 3.0D + 1.0D);
+
+ for(var2 = 0; var2 < var3; ++var2) {
+ this.level.addEntity(new Item(this.level, this.x, this.y, this.z, Block.WHITE_WOOL.id));
+ }
+
+ } else {
+ super.hurt(var1, var2);
+ }
+ }
+
+ public void renderModel(TextureManager var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ AnimalModel var8;
+ float var9 = (var8 = (AnimalModel)modelCache.getModel(this.modelName)).head.y;
+ float var10 = var8.head.z;
+ var8.head.y += (this.grazeO + (this.graze - this.grazeO) * var3) * 8.0F;
+ var8.head.z -= this.grazeO + (this.graze - this.grazeO) * var3;
+ super.renderModel(var1, var2, var3, var4, var5, var6, var7);
+ if(this.hasFur) {
+ GL11.glBindTexture(3553, var1.load("/mob/sheep_fur.png"));
+ GL11.glDisable(2884);
+ AnimalModel var11;
+ (var11 = (AnimalModel)modelCache.getModel("sheep.fur")).head.yaw = var8.head.yaw;
+ var11.head.pitch = var8.head.pitch;
+ var11.head.y = var8.head.y;
+ var11.head.x = var8.head.x;
+ var11.body.yaw = var8.body.yaw;
+ var11.body.pitch = var8.body.pitch;
+ var11.leg1.pitch = var8.leg1.pitch;
+ var11.leg2.pitch = var8.leg2.pitch;
+ var11.leg3.pitch = var8.leg3.pitch;
+ var11.leg4.pitch = var8.leg4.pitch;
+ var11.head.render(var7);
+ var11.body.render(var7);
+ var11.leg1.render(var7);
+ var11.leg2.render(var7);
+ var11.leg3.render(var7);
+ var11.leg4.render(var7);
+ }
+
+ var8.head.y = var9;
+ var8.head.z = var10;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Skeleton$1.java b/src/main/java/com/mojang/minecraft/mob/Skeleton$1.java
new file mode 100644
index 0000000..3ae510b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Skeleton$1.java
@@ -0,0 +1,30 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.mob.Skeleton;
+import com.mojang.minecraft.mob.ai.BasicAttackAI;
+
+final class Skeleton$1 extends BasicAttackAI {
+
+ public static final long serialVersionUID = 0L;
+ // $FF: synthetic field
+ final Skeleton parent;
+
+
+ Skeleton$1(Skeleton var1) {
+ this.parent = var1;
+ }
+
+ public final void tick(Level var1, Mob var2) {
+ super.tick(var1, var2);
+ if(var2.health > 0 && this.random.nextInt(30) == 0 && this.attackTarget != null) {
+ this.parent.shootArrow(var1);
+ }
+
+ }
+
+ public final void beforeRemove() {
+ Skeleton.shootRandomArrow(this.parent);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Skeleton.java b/src/main/java/com/mojang/minecraft/mob/Skeleton.java
new file mode 100644
index 0000000..aa2f050
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Skeleton.java
@@ -0,0 +1,38 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.item.Arrow;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Skeleton$1;
+import com.mojang.minecraft.mob.Zombie;
+
+public class Skeleton extends Zombie {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public Skeleton(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4);
+ this.modelName = "skeleton";
+ this.textureName = "/mob/skeleton.png";
+ Skeleton$1 var5 = new Skeleton$1(this);
+ this.deathScore = 120;
+ var5.runSpeed = 0.3F;
+ var5.damage = 8;
+ this.ai = var5;
+ }
+
+ public void shootArrow(Level var1) {
+ var1.addEntity(new Arrow(var1, this, this.x, this.y, this.z, this.yRot + 180.0F + (float)(Math.random() * 45.0D - 22.5D), this.xRot - (float)(Math.random() * 45.0D - 10.0D), 1.0F));
+ }
+
+ // $FF: synthetic method
+ static void shootRandomArrow(Skeleton var0) {
+ var0 = var0;
+ int var1 = (int)((Math.random() + Math.random()) * 3.0D + 4.0D);
+
+ for(int var2 = 0; var2 < var1; ++var2) {
+ var0.level.addEntity(new Arrow(var0.level, var0.level.getPlayer(), var0.x, var0.y - 0.2F, var0.z, (float)Math.random() * 360.0F, -((float)Math.random()) * 60.0F, 0.4F));
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Spider.java b/src/main/java/com/mojang/minecraft/mob/Spider.java
new file mode 100644
index 0000000..c3104a0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Spider.java
@@ -0,0 +1,23 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.QuadrupedMob;
+import com.mojang.minecraft.mob.ai.JumpAttackAI;
+
+public class Spider extends QuadrupedMob {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public Spider(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4);
+ this.heightOffset = 0.72F;
+ this.modelName = "spider";
+ this.textureName = "/mob/spider.png";
+ this.setSize(1.4F, 0.9F);
+ this.setPos(var2, var3, var4);
+ this.deathScore = 105;
+ this.bobStrength = 0.0F;
+ this.ai = new JumpAttackAI();
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/Zombie.java b/src/main/java/com/mojang/minecraft/mob/Zombie.java
new file mode 100644
index 0000000..5c6c8aa
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/Zombie.java
@@ -0,0 +1,23 @@
+package com.mojang.minecraft.mob;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.HumanoidMob;
+import com.mojang.minecraft.mob.ai.BasicAttackAI;
+
+public class Zombie extends HumanoidMob {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public Zombie(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4);
+ this.modelName = "zombie";
+ this.textureName = "/mob/zombie.png";
+ this.heightOffset = 1.62F;
+ BasicAttackAI var5 = new BasicAttackAI();
+ this.deathScore = 80;
+ var5.defaultLookAngle = 30;
+ var5.runSpeed = 1.0F;
+ this.ai = var5;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/ai/AI.java b/src/main/java/com/mojang/minecraft/mob/ai/AI.java
new file mode 100644
index 0000000..8be0556
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/ai/AI.java
@@ -0,0 +1,19 @@
+package com.mojang.minecraft.mob.ai;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Mob;
+import java.io.Serializable;
+
+public abstract class AI implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ public int defaultLookAngle = 0;
+
+
+ public void tick(Level var1, Mob var2) {}
+
+ public void beforeRemove() {}
+
+ public void hurt(Entity var1, int var2) {}
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/ai/BasicAI.java b/src/main/java/com/mojang/minecraft/mob/ai/BasicAI.java
new file mode 100644
index 0000000..3714b28
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/ai/BasicAI.java
@@ -0,0 +1,119 @@
+package com.mojang.minecraft.mob.ai;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.mob.ai.AI;
+import java.util.List;
+import java.util.Random;
+
+public class BasicAI extends AI {
+
+ public static final long serialVersionUID = 0L;
+ public Random random = new Random();
+ public float xxa;
+ public float yya;
+ protected float yRotA;
+ public Level level;
+ public Mob mob;
+ public boolean jumping = false;
+ protected int attackDelay = 0;
+ public float runSpeed = 0.7F;
+ protected int noActionTime = 0;
+ public Entity attackTarget = null;
+
+
+ public void tick(Level var1, Mob var2) {
+ ++this.noActionTime;
+ Entity var3;
+ if(this.noActionTime > 600 && this.random.nextInt(800) == 0 && (var3 = var1.getPlayer()) != null) {
+ float var4 = var3.x - var2.x;
+ float var5 = var3.y - var2.y;
+ float var6 = var3.z - var2.z;
+ if(var4 * var4 + var5 * var5 + var6 * var6 < 1024.0F) {
+ this.noActionTime = 0;
+ } else {
+ var2.remove();
+ }
+ }
+
+ this.level = var1;
+ this.mob = var2;
+ if(this.attackDelay > 0) {
+ --this.attackDelay;
+ }
+
+ if(var2.health <= 0) {
+ this.jumping = false;
+ this.xxa = 0.0F;
+ this.yya = 0.0F;
+ this.yRotA = 0.0F;
+ } else {
+ this.update();
+ }
+
+ boolean var7 = var2.isInWater();
+ boolean var9 = var2.isInLava();
+ if(this.jumping) {
+ if(var7) {
+ var2.yd += 0.04F;
+ } else if(var9) {
+ var2.yd += 0.04F;
+ } else if(var2.onGround) {
+ this.jumpFromGround();
+ }
+ }
+
+ this.xxa *= 0.98F;
+ this.yya *= 0.98F;
+ this.yRotA *= 0.9F;
+ var2.travel(this.xxa, this.yya);
+ List var11;
+ if((var11 = var1.findEntities(var2, var2.bb.grow(0.2F, 0.0F, 0.2F))) != null && var11.size() > 0) {
+ for(int var8 = 0; var8 < var11.size(); ++var8) {
+ Entity var10;
+ if((var10 = (Entity)var11.get(var8)).isPushable()) {
+ var10.push(var2);
+ }
+ }
+ }
+
+ }
+
+ protected void jumpFromGround() {
+ this.mob.yd = 0.42F;
+ }
+
+ protected void update() {
+ if(this.random.nextFloat() < 0.07F) {
+ this.xxa = (this.random.nextFloat() - 0.5F) * this.runSpeed;
+ this.yya = this.random.nextFloat() * this.runSpeed;
+ }
+
+ this.jumping = this.random.nextFloat() < 0.01F;
+ if(this.random.nextFloat() < 0.04F) {
+ this.yRotA = (this.random.nextFloat() - 0.5F) * 60.0F;
+ }
+
+ this.mob.yRot += this.yRotA;
+ this.mob.xRot = (float)this.defaultLookAngle;
+ if(this.attackTarget != null) {
+ this.yya = this.runSpeed;
+ this.jumping = this.random.nextFloat() < 0.04F;
+ }
+
+ boolean var1 = this.mob.isInWater();
+ boolean var2 = this.mob.isInLava();
+ if(var1 || var2) {
+ this.jumping = this.random.nextFloat() < 0.8F;
+ }
+
+ }
+
+ public void beforeRemove() {}
+
+ public void hurt(Entity var1, int var2) {
+ super.hurt(var1, var2);
+ this.noActionTime = 0;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/ai/BasicAttackAI.java b/src/main/java/com/mojang/minecraft/mob/ai/BasicAttackAI.java
new file mode 100644
index 0000000..a1eefb9
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/ai/BasicAttackAI.java
@@ -0,0 +1,87 @@
+package com.mojang.minecraft.mob.ai;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.item.Arrow;
+import com.mojang.minecraft.mob.ai.BasicAI;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.util.MathHelper;
+
+public class BasicAttackAI extends BasicAI {
+
+ public static final long serialVersionUID = 0L;
+ public int damage = 6;
+
+
+ protected void update() {
+ super.update();
+ if(this.mob.health > 0) {
+ this.doAttack();
+ }
+
+ }
+
+ protected void doAttack() {
+ Entity var1 = this.level.getPlayer();
+ float var2 = 16.0F;
+ if(this.attackTarget != null && this.attackTarget.removed) {
+ this.attackTarget = null;
+ }
+
+ float var3;
+ float var4;
+ float var5;
+ if(var1 != null && this.attackTarget == null) {
+ var3 = var1.x - this.mob.x;
+ var4 = var1.y - this.mob.y;
+ var5 = var1.z - this.mob.z;
+ if(var3 * var3 + var4 * var4 + var5 * var5 < var2 * var2) {
+ this.attackTarget = var1;
+ }
+ }
+
+ if(this.attackTarget != null) {
+ var3 = this.attackTarget.x - this.mob.x;
+ var4 = this.attackTarget.y - this.mob.y;
+ var5 = this.attackTarget.z - this.mob.z;
+ float var6;
+ if((var6 = var3 * var3 + var4 * var4 + var5 * var5) > var2 * var2 * 2.0F * 2.0F && this.random.nextInt(100) == 0) {
+ this.attackTarget = null;
+ }
+
+ if(this.attackTarget != null) {
+ var6 = MathHelper.sqrt(var6);
+ this.mob.yRot = (float)(Math.atan2((double)var5, (double)var3) * 180.0D / 3.1415927410125732D) - 90.0F;
+ this.mob.xRot = -((float)(Math.atan2((double)var4, (double)var6) * 180.0D / 3.1415927410125732D));
+ if(MathHelper.sqrt(var3 * var3 + var4 * var4 + var5 * var5) < 2.0F && this.attackDelay == 0) {
+ this.attack(this.attackTarget);
+ }
+ }
+
+ }
+ }
+
+ public boolean attack(Entity var1) {
+ if(this.level.clip(new Vec3D(this.mob.x, this.mob.y, this.mob.z), new Vec3D(var1.x, var1.y, var1.z)) != null) {
+ return false;
+ } else {
+ this.mob.attackTime = 5;
+ this.attackDelay = this.random.nextInt(20) + 10;
+ int var2 = (int)((this.random.nextFloat() + this.random.nextFloat()) / 2.0F * (float)this.damage + 1.0F);
+ var1.hurt(this.mob, var2);
+ this.noActionTime = 0;
+ return true;
+ }
+ }
+
+ public void hurt(Entity var1, int var2) {
+ super.hurt(var1, var2);
+ if(var1 instanceof Arrow) {
+ var1 = ((Arrow)var1).getOwner();
+ }
+
+ if(var1 != null && !var1.getClass().equals(this.mob.getClass())) {
+ this.attackTarget = var1;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/mob/ai/JumpAttackAI.java b/src/main/java/com/mojang/minecraft/mob/ai/JumpAttackAI.java
new file mode 100644
index 0000000..6eff10b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/mob/ai/JumpAttackAI.java
@@ -0,0 +1,24 @@
+package com.mojang.minecraft.mob.ai;
+
+import com.mojang.minecraft.mob.ai.BasicAttackAI;
+
+public class JumpAttackAI extends BasicAttackAI {
+
+ public static final long serialVersionUID = 0L;
+
+
+ public JumpAttackAI() {
+ this.runSpeed *= 0.8F;
+ }
+
+ protected void jumpFromGround() {
+ if(this.attackTarget == null) {
+ super.jumpFromGround();
+ } else {
+ this.mob.xd = 0.0F;
+ this.mob.zd = 0.0F;
+ this.mob.moveRelative(0.0F, 1.0F, 0.6F);
+ this.mob.yd = 0.5F;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/AnimalModel.java b/src/main/java/com/mojang/minecraft/model/AnimalModel.java
new file mode 100644
index 0000000..d5094e8
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/AnimalModel.java
@@ -0,0 +1,52 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.Model;
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.util.MathHelper;
+
+public class AnimalModel extends Model {
+
+ public ModelPart head = new ModelPart(0, 0);
+ public ModelPart body;
+ public ModelPart leg1;
+ public ModelPart leg2;
+ public ModelPart leg3;
+ public ModelPart leg4;
+
+
+ public AnimalModel(int var1, float var2) {
+ this.head.setBounds(-4.0F, -4.0F, -8.0F, 8, 8, 8, 0.0F);
+ this.head.setPosition(0.0F, (float)(18 - var1), -6.0F);
+ this.body = new ModelPart(28, 8);
+ this.body.setBounds(-5.0F, -10.0F, -7.0F, 10, 16, 8, 0.0F);
+ this.body.setPosition(0.0F, (float)(17 - var1), 2.0F);
+ this.leg1 = new ModelPart(0, 16);
+ this.leg1.setBounds(-2.0F, 0.0F, -2.0F, 4, var1, 4, 0.0F);
+ this.leg1.setPosition(-3.0F, (float)(24 - var1), 7.0F);
+ this.leg2 = new ModelPart(0, 16);
+ this.leg2.setBounds(-2.0F, 0.0F, -2.0F, 4, var1, 4, 0.0F);
+ this.leg2.setPosition(3.0F, (float)(24 - var1), 7.0F);
+ this.leg3 = new ModelPart(0, 16);
+ this.leg3.setBounds(-2.0F, 0.0F, -2.0F, 4, var1, 4, 0.0F);
+ this.leg3.setPosition(-3.0F, (float)(24 - var1), -5.0F);
+ this.leg4 = new ModelPart(0, 16);
+ this.leg4.setBounds(-2.0F, 0.0F, -2.0F, 4, var1, 4, 0.0F);
+ this.leg4.setPosition(3.0F, (float)(24 - var1), -5.0F);
+ }
+
+ public final void render(float var1, float var2, float var3, float var4, float var5, float var6) {
+ this.head.yaw = var4 / 57.295776F;
+ this.head.pitch = var5 / 57.295776F;
+ this.body.pitch = 1.5707964F;
+ this.leg1.pitch = MathHelper.cos(var1 * 0.6662F) * 1.4F * var2;
+ this.leg2.pitch = MathHelper.cos(var1 * 0.6662F + 3.1415927F) * 1.4F * var2;
+ this.leg3.pitch = MathHelper.cos(var1 * 0.6662F + 3.1415927F) * 1.4F * var2;
+ this.leg4.pitch = MathHelper.cos(var1 * 0.6662F) * 1.4F * var2;
+ this.head.render(var6);
+ this.body.render(var6);
+ this.leg1.render(var6);
+ this.leg2.render(var6);
+ this.leg3.render(var6);
+ this.leg4.render(var6);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/CreeperModel.java b/src/main/java/com/mojang/minecraft/model/CreeperModel.java
new file mode 100644
index 0000000..73c1478
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/CreeperModel.java
@@ -0,0 +1,52 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.Model;
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.util.MathHelper;
+
+public final class CreeperModel extends Model {
+
+ private ModelPart head = new ModelPart(0, 0);
+ private ModelPart unused;
+ private ModelPart body;
+ private ModelPart leg1;
+ private ModelPart leg2;
+ private ModelPart leg3;
+ private ModelPart leg4;
+
+
+ public CreeperModel() {
+ this.head.setBounds(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F);
+ this.unused = new ModelPart(32, 0);
+ this.unused.setBounds(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F + 0.5F);
+ this.body = new ModelPart(16, 16);
+ this.body.setBounds(-4.0F, 0.0F, -2.0F, 8, 12, 4, 0.0F);
+ this.leg1 = new ModelPart(0, 16);
+ this.leg1.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, 0.0F);
+ this.leg1.setPosition(-2.0F, 12.0F, 4.0F);
+ this.leg2 = new ModelPart(0, 16);
+ this.leg2.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, 0.0F);
+ this.leg2.setPosition(2.0F, 12.0F, 4.0F);
+ this.leg3 = new ModelPart(0, 16);
+ this.leg3.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, 0.0F);
+ this.leg3.setPosition(-2.0F, 12.0F, -4.0F);
+ this.leg4 = new ModelPart(0, 16);
+ this.leg4.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, 0.0F);
+ this.leg4.setPosition(2.0F, 12.0F, -4.0F);
+ }
+
+ public final void render(float var1, float var2, float var3, float var4, float var5, float var6) {
+ this.head.yaw = var4 / 57.295776F;
+ this.head.pitch = var5 / 57.295776F;
+ this.leg1.pitch = MathHelper.cos(var1 * 0.6662F) * 1.4F * var2;
+ this.leg2.pitch = MathHelper.cos(var1 * 0.6662F + 3.1415927F) * 1.4F * var2;
+ this.leg3.pitch = MathHelper.cos(var1 * 0.6662F + 3.1415927F) * 1.4F * var2;
+ this.leg4.pitch = MathHelper.cos(var1 * 0.6662F) * 1.4F * var2;
+ this.head.render(var6);
+ this.body.render(var6);
+ this.leg1.render(var6);
+ this.leg2.render(var6);
+ this.leg3.render(var6);
+ this.leg4.render(var6);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/HumanoidModel.java b/src/main/java/com/mojang/minecraft/model/HumanoidModel.java
new file mode 100644
index 0000000..dc2bd24
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/HumanoidModel.java
@@ -0,0 +1,69 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.Model;
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.util.MathHelper;
+
+public class HumanoidModel extends Model {
+
+ public ModelPart head;
+ public ModelPart headwear;
+ public ModelPart body;
+ public ModelPart rightArm;
+ public ModelPart leftArm;
+ public ModelPart rightLeg;
+ public ModelPart leftLeg;
+
+
+ public HumanoidModel() {
+ this(0.0F);
+ }
+
+ public HumanoidModel(float var1) {
+ this.head = new ModelPart(0, 0);
+ this.head.setBounds(-4.0F, -8.0F, -4.0F, 8, 8, 8, var1);
+ this.headwear = new ModelPart(32, 0);
+ this.headwear.setBounds(-4.0F, -8.0F, -4.0F, 8, 8, 8, var1 + 0.5F);
+ this.body = new ModelPart(16, 16);
+ this.body.setBounds(-4.0F, 0.0F, -2.0F, 8, 12, 4, var1);
+ this.rightArm = new ModelPart(40, 16);
+ this.rightArm.setBounds(-3.0F, -2.0F, -2.0F, 4, 12, 4, var1);
+ this.rightArm.setPosition(-5.0F, 2.0F, 0.0F);
+ this.leftArm = new ModelPart(40, 16);
+ this.leftArm.mirror = true;
+ this.leftArm.setBounds(-1.0F, -2.0F, -2.0F, 4, 12, 4, var1);
+ this.leftArm.setPosition(5.0F, 2.0F, 0.0F);
+ this.rightLeg = new ModelPart(0, 16);
+ this.rightLeg.setBounds(-2.0F, 0.0F, -2.0F, 4, 12, 4, var1);
+ this.rightLeg.setPosition(-2.0F, 12.0F, 0.0F);
+ this.leftLeg = new ModelPart(0, 16);
+ this.leftLeg.mirror = true;
+ this.leftLeg.setBounds(-2.0F, 0.0F, -2.0F, 4, 12, 4, var1);
+ this.leftLeg.setPosition(2.0F, 12.0F, 0.0F);
+ }
+
+ public final void render(float var1, float var2, float var3, float var4, float var5, float var6) {
+ this.setRotationAngles(var1, var2, var3, var4, var5, var6);
+ this.head.render(var6);
+ this.body.render(var6);
+ this.rightArm.render(var6);
+ this.leftArm.render(var6);
+ this.rightLeg.render(var6);
+ this.leftLeg.render(var6);
+ }
+
+ public void setRotationAngles(float var1, float var2, float var3, float var4, float var5, float var6) {
+ this.head.yaw = var4 / 57.295776F;
+ this.head.pitch = var5 / 57.295776F;
+ this.rightArm.pitch = MathHelper.cos(var1 * 0.6662F + 3.1415927F) * 2.0F * var2;
+ this.rightArm.roll = (MathHelper.cos(var1 * 0.2312F) + 1.0F) * var2;
+ this.leftArm.pitch = MathHelper.cos(var1 * 0.6662F) * 2.0F * var2;
+ this.leftArm.roll = (MathHelper.cos(var1 * 0.2812F) - 1.0F) * var2;
+ this.rightLeg.pitch = MathHelper.cos(var1 * 0.6662F) * 1.4F * var2;
+ this.leftLeg.pitch = MathHelper.cos(var1 * 0.6662F + 3.1415927F) * 1.4F * var2;
+ this.rightArm.roll += MathHelper.cos(var3 * 0.09F) * 0.05F + 0.05F;
+ this.leftArm.roll -= MathHelper.cos(var3 * 0.09F) * 0.05F + 0.05F;
+ this.rightArm.pitch += MathHelper.sin(var3 * 0.067F) * 0.05F;
+ this.leftArm.pitch -= MathHelper.sin(var3 * 0.067F) * 0.05F;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/Model.java b/src/main/java/com/mojang/minecraft/model/Model.java
new file mode 100644
index 0000000..1585634
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/Model.java
@@ -0,0 +1,10 @@
+package com.mojang.minecraft.model;
+
+
+public abstract class Model {
+
+ public float attackOffset;
+
+
+ public void render(float var1, float var2, float var3, float var4, float var5, float var6) {}
+}
diff --git a/src/main/java/com/mojang/minecraft/model/ModelManager.java b/src/main/java/com/mojang/minecraft/model/ModelManager.java
new file mode 100644
index 0000000..790839c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/ModelManager.java
@@ -0,0 +1,30 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.AnimalModel;
+import com.mojang.minecraft.model.CreeperModel;
+import com.mojang.minecraft.model.HumanoidModel;
+import com.mojang.minecraft.model.Model;
+import com.mojang.minecraft.model.PigModel;
+import com.mojang.minecraft.model.SheepFurModel;
+import com.mojang.minecraft.model.SheepModel;
+import com.mojang.minecraft.model.SkeletonModel;
+import com.mojang.minecraft.model.SpiderModel;
+import com.mojang.minecraft.model.ZombieModel;
+
+public final class ModelManager {
+
+ private HumanoidModel human = new HumanoidModel(0.0F);
+ private HumanoidModel armoredHuman = new HumanoidModel(1.0F);
+ private CreeperModel creeper = new CreeperModel();
+ private SkeletonModel skeleton = new SkeletonModel();
+ private ZombieModel zombie = new ZombieModel();
+ private AnimalModel pig = new PigModel();
+ private AnimalModel sheep = new SheepModel();
+ private SpiderModel spider = new SpiderModel();
+ private SheepFurModel sheepFur = new SheepFurModel();
+
+
+ public final Model getModel(String var1) {
+ return (Model)(var1.equals("humanoid")?this.human:(var1.equals("humanoid.armor")?this.armoredHuman:(var1.equals("creeper")?this.creeper:(var1.equals("skeleton")?this.skeleton:(var1.equals("zombie")?this.zombie:(var1.equals("pig")?this.pig:(var1.equals("sheep")?this.sheep:(var1.equals("spider")?this.spider:(var1.equals("sheep.fur")?this.sheepFur:null)))))))));
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/ModelPart.java b/src/main/java/com/mojang/minecraft/model/ModelPart.java
new file mode 100644
index 0000000..2f61d76
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/ModelPart.java
@@ -0,0 +1,152 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.TexturedQuad;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.model.Vertex;
+import org.lwjgl.opengl.GL11;
+
+public final class ModelPart {
+
+ public Vertex[] vertices;
+ public TexturedQuad[] quads;
+ private int u;
+ private int v;
+ public float x;
+ public float y;
+ public float z;
+ public float pitch;
+ public float yaw;
+ public float roll;
+ public boolean hasList = false;
+ public int list = 0;
+ public boolean mirror = false;
+ public boolean render = true;
+ private boolean unused = false;
+
+
+ public ModelPart(int var1, int var2) {
+ this.u = var1;
+ this.v = var2;
+ }
+
+ public final void setBounds(float var1, float var2, float var3, int var4, int var5, int var6, float var7) {
+ this.vertices = new Vertex[8];
+ this.quads = new TexturedQuad[6];
+ float var8 = var1 + (float)var4;
+ float var9 = var2 + (float)var5;
+ float var10 = var3 + (float)var6;
+ var1 -= var7;
+ var2 -= var7;
+ var3 -= var7;
+ var8 += var7;
+ var9 += var7;
+ var10 += var7;
+ if(this.mirror) {
+ var7 = var8;
+ var8 = var1;
+ var1 = var7;
+ }
+
+ Vertex var20 = new Vertex(var1, var2, var3, 0.0F, 0.0F);
+ Vertex var11 = new Vertex(var8, var2, var3, 0.0F, 8.0F);
+ Vertex var12 = new Vertex(var8, var9, var3, 8.0F, 8.0F);
+ Vertex var18 = new Vertex(var1, var9, var3, 8.0F, 0.0F);
+ Vertex var13 = new Vertex(var1, var2, var10, 0.0F, 0.0F);
+ Vertex var15 = new Vertex(var8, var2, var10, 0.0F, 8.0F);
+ Vertex var21 = new Vertex(var8, var9, var10, 8.0F, 8.0F);
+ Vertex var14 = new Vertex(var1, var9, var10, 8.0F, 0.0F);
+ this.vertices[0] = var20;
+ this.vertices[1] = var11;
+ this.vertices[2] = var12;
+ this.vertices[3] = var18;
+ this.vertices[4] = var13;
+ this.vertices[5] = var15;
+ this.vertices[6] = var21;
+ this.vertices[7] = var14;
+ this.quads[0] = new TexturedQuad(new Vertex[]{var15, var11, var12, var21}, this.u + var6 + var4, this.v + var6, this.u + var6 + var4 + var6, this.v + var6 + var5);
+ this.quads[1] = new TexturedQuad(new Vertex[]{var20, var13, var14, var18}, this.u, this.v + var6, this.u + var6, this.v + var6 + var5);
+ this.quads[2] = new TexturedQuad(new Vertex[]{var15, var13, var20, var11}, this.u + var6, this.v, this.u + var6 + var4, this.v + var6);
+ this.quads[3] = new TexturedQuad(new Vertex[]{var12, var18, var14, var21}, this.u + var6 + var4, this.v, this.u + var6 + var4 + var4, this.v + var6);
+ this.quads[4] = new TexturedQuad(new Vertex[]{var11, var20, var18, var12}, this.u + var6, this.v + var6, this.u + var6 + var4, this.v + var6 + var5);
+ this.quads[5] = new TexturedQuad(new Vertex[]{var13, var15, var21, var14}, this.u + var6 + var4 + var6, this.v + var6, this.u + var6 + var4 + var6 + var4, this.v + var6 + var5);
+ if(this.mirror) {
+ for(int var16 = 0; var16 < this.quads.length; ++var16) {
+ TexturedQuad var17;
+ Vertex[] var19 = new Vertex[(var17 = this.quads[var16]).vertices.length];
+
+ for(var4 = 0; var4 < var17.vertices.length; ++var4) {
+ var19[var4] = var17.vertices[var17.vertices.length - var4 - 1];
+ }
+
+ var17.vertices = var19;
+ }
+ }
+
+ }
+
+ public final void setPosition(float var1, float var2, float var3) {
+ this.x = var1;
+ this.y = var2;
+ this.z = var3;
+ }
+
+ public final void render(float var1) {
+ if(this.render) {
+ if(!this.hasList) {
+ this.generateList(var1);
+ }
+
+ if(this.pitch == 0.0F && this.yaw == 0.0F && this.roll == 0.0F) {
+ if(this.x == 0.0F && this.y == 0.0F && this.z == 0.0F) {
+ GL11.glCallList(this.list);
+ } else {
+ GL11.glTranslatef(this.x * var1, this.y * var1, this.z * var1);
+ GL11.glCallList(this.list);
+ GL11.glTranslatef(-this.x * var1, -this.y * var1, -this.z * var1);
+ }
+ } else {
+ GL11.glPushMatrix();
+ GL11.glTranslatef(this.x * var1, this.y * var1, this.z * var1);
+ if(this.roll != 0.0F) {
+ GL11.glRotatef(this.roll * 57.295776F, 0.0F, 0.0F, 1.0F);
+ }
+
+ if(this.yaw != 0.0F) {
+ GL11.glRotatef(this.yaw * 57.295776F, 0.0F, 1.0F, 0.0F);
+ }
+
+ if(this.pitch != 0.0F) {
+ GL11.glRotatef(this.pitch * 57.295776F, 1.0F, 0.0F, 0.0F);
+ }
+
+ GL11.glCallList(this.list);
+ GL11.glPopMatrix();
+ }
+ }
+ }
+
+ public void generateList(float var1) {
+ this.list = GL11.glGenLists(1);
+ GL11.glNewList(this.list, 4864);
+ GL11.glBegin(7);
+
+ for(int var2 = 0; var2 < this.quads.length; ++var2) {
+ TexturedQuad var10000 = this.quads[var2];
+ float var3 = var1;
+ TexturedQuad var4 = var10000;
+ Vec3D var5 = var10000.vertices[1].vector.subtract(var4.vertices[0].vector).normalize();
+ Vec3D var6 = var4.vertices[1].vector.subtract(var4.vertices[2].vector).normalize();
+ GL11.glNormal3f((var5 = (new Vec3D(var5.y * var6.z - var5.z * var6.y, var5.z * var6.x - var5.x * var6.z, var5.x * var6.y - var5.y * var6.x)).normalize()).x, var5.y, var5.z);
+
+ for(int var7 = 0; var7 < 4; ++var7) {
+ Vertex var8;
+ GL11.glTexCoord2f((var8 = var4.vertices[var7]).u, var8.v);
+ GL11.glVertex3f(var8.vector.x * var3, var8.vector.y * var3, var8.vector.z * var3);
+ }
+ }
+
+ GL11.glEnd();
+ GL11.glEndList();
+ this.hasList = true;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/PigModel.java b/src/main/java/com/mojang/minecraft/model/PigModel.java
new file mode 100644
index 0000000..64fe27c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/PigModel.java
@@ -0,0 +1,10 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.AnimalModel;
+
+public final class PigModel extends AnimalModel {
+
+ public PigModel() {
+ super(6, 0.0F);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/SheepFurModel.java b/src/main/java/com/mojang/minecraft/model/SheepFurModel.java
new file mode 100644
index 0000000..9eab032
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/SheepFurModel.java
@@ -0,0 +1,30 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.AnimalModel;
+import com.mojang.minecraft.model.ModelPart;
+
+public final class SheepFurModel extends AnimalModel {
+
+ public SheepFurModel() {
+ super(12, 0.0F);
+ this.head = new ModelPart(0, 0);
+ this.head.setBounds(-3.0F, -4.0F, -4.0F, 6, 6, 6, 0.6F);
+ this.head.setPosition(0.0F, 6.0F, -8.0F);
+ this.body = new ModelPart(28, 8);
+ this.body.setBounds(-4.0F, -10.0F, -7.0F, 8, 16, 6, 1.75F);
+ this.body.setPosition(0.0F, 5.0F, 2.0F);
+ float var1 = 0.5F;
+ this.leg1 = new ModelPart(0, 16);
+ this.leg1.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, var1);
+ this.leg1.setPosition(-3.0F, 12.0F, 7.0F);
+ this.leg2 = new ModelPart(0, 16);
+ this.leg2.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, var1);
+ this.leg2.setPosition(3.0F, 12.0F, 7.0F);
+ this.leg3 = new ModelPart(0, 16);
+ this.leg3.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, var1);
+ this.leg3.setPosition(-3.0F, 12.0F, -5.0F);
+ this.leg4 = new ModelPart(0, 16);
+ this.leg4.setBounds(-2.0F, 0.0F, -2.0F, 4, 6, 4, var1);
+ this.leg4.setPosition(3.0F, 12.0F, -5.0F);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/SheepModel.java b/src/main/java/com/mojang/minecraft/model/SheepModel.java
new file mode 100644
index 0000000..2b3fcba
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/SheepModel.java
@@ -0,0 +1,17 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.AnimalModel;
+import com.mojang.minecraft.model.ModelPart;
+
+public final class SheepModel extends AnimalModel {
+
+ public SheepModel() {
+ super(12, 0.0F);
+ this.head = new ModelPart(0, 0);
+ this.head.setBounds(-3.0F, -4.0F, -6.0F, 6, 6, 8, 0.0F);
+ this.head.setPosition(0.0F, 6.0F, -8.0F);
+ this.body = new ModelPart(28, 8);
+ this.body.setBounds(-4.0F, -10.0F, -7.0F, 8, 16, 6, 0.0F);
+ this.body.setPosition(0.0F, 5.0F, 2.0F);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/SkeletonModel.java b/src/main/java/com/mojang/minecraft/model/SkeletonModel.java
new file mode 100644
index 0000000..c084563
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/SkeletonModel.java
@@ -0,0 +1,24 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.minecraft.model.ZombieModel;
+
+public final class SkeletonModel extends ZombieModel {
+
+ public SkeletonModel() {
+ this.rightArm = new ModelPart(40, 16);
+ this.rightArm.setBounds(-1.0F, -2.0F, -1.0F, 2, 12, 2, 0.0F);
+ this.rightArm.setPosition(-5.0F, 2.0F, 0.0F);
+ this.leftArm = new ModelPart(40, 16);
+ this.leftArm.mirror = true;
+ this.leftArm.setBounds(-1.0F, -2.0F, -1.0F, 2, 12, 2, 0.0F);
+ this.leftArm.setPosition(5.0F, 2.0F, 0.0F);
+ this.rightLeg = new ModelPart(0, 16);
+ this.rightLeg.setBounds(-1.0F, 0.0F, -1.0F, 2, 12, 2, 0.0F);
+ this.rightLeg.setPosition(-2.0F, 12.0F, 0.0F);
+ this.leftLeg = new ModelPart(0, 16);
+ this.leftLeg.mirror = true;
+ this.leftLeg.setBounds(-1.0F, 0.0F, -1.0F, 2, 12, 2, 0.0F);
+ this.leftLeg.setPosition(2.0F, 12.0F, 0.0F);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/SpiderModel.java b/src/main/java/com/mojang/minecraft/model/SpiderModel.java
new file mode 100644
index 0000000..0c065b0
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/SpiderModel.java
@@ -0,0 +1,113 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.Model;
+import com.mojang.minecraft.model.ModelPart;
+import com.mojang.util.MathHelper;
+
+public final class SpiderModel extends Model {
+
+ private ModelPart head = new ModelPart(32, 4);
+ private ModelPart neck;
+ private ModelPart body;
+ private ModelPart leg1;
+ private ModelPart leg2;
+ private ModelPart leg3;
+ private ModelPart leg4;
+ private ModelPart leg5;
+ private ModelPart leg6;
+ private ModelPart leg7;
+ private ModelPart leg8;
+
+
+ public SpiderModel() {
+ this.head.setBounds(-4.0F, -4.0F, -8.0F, 8, 8, 8, 0.0F);
+ this.head.setPosition(0.0F, 0.0F, -3.0F);
+ this.neck = new ModelPart(0, 0);
+ this.neck.setBounds(-3.0F, -3.0F, -3.0F, 6, 6, 6, 0.0F);
+ this.body = new ModelPart(0, 12);
+ this.body.setBounds(-5.0F, -4.0F, -6.0F, 10, 8, 12, 0.0F);
+ this.body.setPosition(0.0F, 0.0F, 9.0F);
+ this.leg1 = new ModelPart(18, 0);
+ this.leg1.setBounds(-15.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg1.setPosition(-4.0F, 0.0F, 2.0F);
+ this.leg2 = new ModelPart(18, 0);
+ this.leg2.setBounds(-1.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg2.setPosition(4.0F, 0.0F, 2.0F);
+ this.leg3 = new ModelPart(18, 0);
+ this.leg3.setBounds(-15.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg3.setPosition(-4.0F, 0.0F, 1.0F);
+ this.leg4 = new ModelPart(18, 0);
+ this.leg4.setBounds(-1.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg4.setPosition(4.0F, 0.0F, 1.0F);
+ this.leg5 = new ModelPart(18, 0);
+ this.leg5.setBounds(-15.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg5.setPosition(-4.0F, 0.0F, 0.0F);
+ this.leg6 = new ModelPart(18, 0);
+ this.leg6.setBounds(-1.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg6.setPosition(4.0F, 0.0F, 0.0F);
+ this.leg7 = new ModelPart(18, 0);
+ this.leg7.setBounds(-15.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg7.setPosition(-4.0F, 0.0F, -1.0F);
+ this.leg8 = new ModelPart(18, 0);
+ this.leg8.setBounds(-1.0F, -1.0F, -1.0F, 16, 2, 2, 0.0F);
+ this.leg8.setPosition(4.0F, 0.0F, -1.0F);
+ }
+
+ public final void render(float var1, float var2, float var3, float var4, float var5, float var6) {
+ this.head.yaw = var4 / 57.295776F;
+ this.head.pitch = var5 / 57.295776F;
+ var4 = 0.7853982F;
+ this.leg1.roll = -var4;
+ this.leg2.roll = var4;
+ this.leg3.roll = -var4 * 0.74F;
+ this.leg4.roll = var4 * 0.74F;
+ this.leg5.roll = -var4 * 0.74F;
+ this.leg6.roll = var4 * 0.74F;
+ this.leg7.roll = -var4;
+ this.leg8.roll = var4;
+ var4 = 0.3926991F;
+ this.leg1.yaw = var4 * 2.0F;
+ this.leg2.yaw = -var4 * 2.0F;
+ this.leg3.yaw = var4;
+ this.leg4.yaw = -var4;
+ this.leg5.yaw = -var4;
+ this.leg6.yaw = var4;
+ this.leg7.yaw = -var4 * 2.0F;
+ this.leg8.yaw = var4 * 2.0F;
+ var4 = -(MathHelper.cos(var1 * 0.6662F * 2.0F) * 0.4F) * var2;
+ var5 = -(MathHelper.cos(var1 * 0.6662F * 2.0F + 3.1415927F) * 0.4F) * var2;
+ float var7 = -(MathHelper.cos(var1 * 0.6662F * 2.0F + 1.5707964F) * 0.4F) * var2;
+ float var8 = -(MathHelper.cos(var1 * 0.6662F * 2.0F + 4.712389F) * 0.4F) * var2;
+ float var9 = Math.abs(MathHelper.sin(var1 * 0.6662F) * 0.4F) * var2;
+ float var10 = Math.abs(MathHelper.sin(var1 * 0.6662F + 3.1415927F) * 0.4F) * var2;
+ float var11 = Math.abs(MathHelper.sin(var1 * 0.6662F + 1.5707964F) * 0.4F) * var2;
+ var2 = Math.abs(MathHelper.sin(var1 * 0.6662F + 4.712389F) * 0.4F) * var2;
+ this.leg1.yaw += var4;
+ this.leg2.yaw -= var4;
+ this.leg3.yaw += var5;
+ this.leg4.yaw -= var5;
+ this.leg5.yaw += var7;
+ this.leg6.yaw -= var7;
+ this.leg7.yaw += var8;
+ this.leg8.yaw -= var8;
+ this.leg1.roll += var9;
+ this.leg2.roll -= var9;
+ this.leg3.roll += var10;
+ this.leg4.roll -= var10;
+ this.leg5.roll += var11;
+ this.leg6.roll -= var11;
+ this.leg7.roll += var2;
+ this.leg8.roll -= var2;
+ this.head.render(var6);
+ this.neck.render(var6);
+ this.body.render(var6);
+ this.leg1.render(var6);
+ this.leg2.render(var6);
+ this.leg3.render(var6);
+ this.leg4.render(var6);
+ this.leg5.render(var6);
+ this.leg6.render(var6);
+ this.leg7.render(var6);
+ this.leg8.render(var6);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/TexturedQuad.java b/src/main/java/com/mojang/minecraft/model/TexturedQuad.java
new file mode 100644
index 0000000..3a680a7
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/TexturedQuad.java
@@ -0,0 +1,31 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.Vertex;
+
+public final class TexturedQuad {
+
+ public Vertex[] vertices;
+
+
+ private TexturedQuad(Vertex[] var1) {
+ this.vertices = var1;
+ }
+
+ public TexturedQuad(Vertex[] var1, int var2, int var3, int var4, int var5) {
+ this(var1);
+ float var7 = 0.0015625F;
+ float var6 = 0.003125F;
+ var1[0] = var1[0].create((float)var4 / 64.0F - var7, (float)var3 / 32.0F + var6);
+ var1[1] = var1[1].create((float)var2 / 64.0F + var7, (float)var3 / 32.0F + var6);
+ var1[2] = var1[2].create((float)var2 / 64.0F + var7, (float)var5 / 32.0F - var6);
+ var1[3] = var1[3].create((float)var4 / 64.0F - var7, (float)var5 / 32.0F - var6);
+ }
+
+ public TexturedQuad(Vertex[] var1, float var2, float var3, float var4, float var5) {
+ this(var1);
+ var1[0] = var1[0].create(var4, var3);
+ var1[1] = var1[1].create(var2, var3);
+ var1[2] = var1[2].create(var2, var5);
+ var1[3] = var1[3].create(var4, var5);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/Vec3D.java b/src/main/java/com/mojang/minecraft/model/Vec3D.java
new file mode 100644
index 0000000..cff068c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/Vec3D.java
@@ -0,0 +1,69 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.util.MathHelper;
+
+public final class Vec3D {
+
+ public float x;
+ public float y;
+ public float z;
+
+
+ public Vec3D(float var1, float var2, float var3) {
+ this.x = var1;
+ this.y = var2;
+ this.z = var3;
+ }
+
+ public final Vec3D subtract(Vec3D var1) {
+ return new Vec3D(this.x - var1.x, this.y - var1.y, this.z - var1.z);
+ }
+
+ public final Vec3D normalize() {
+ float var1 = MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
+ return new Vec3D(this.x / var1, this.y / var1, this.z / var1);
+ }
+
+ public final Vec3D add(float var1, float var2, float var3) {
+ return new Vec3D(this.x + var1, this.y + var2, this.z + var3);
+ }
+
+ public final float distance(Vec3D var1) {
+ float var2 = var1.x - this.x;
+ float var3 = var1.y - this.y;
+ float var4 = var1.z - this.z;
+ return MathHelper.sqrt(var2 * var2 + var3 * var3 + var4 * var4);
+ }
+
+ public final float distanceSquared(Vec3D var1) {
+ float var2 = var1.x - this.x;
+ float var3 = var1.y - this.y;
+ float var4 = var1.z - this.z;
+ return var2 * var2 + var3 * var3 + var4 * var4;
+ }
+
+ public final Vec3D getXIntersection(Vec3D var1, float var2) {
+ float var3 = var1.x - this.x;
+ float var4 = var1.y - this.y;
+ float var5 = var1.z - this.z;
+ return var3 * var3 < 1.0E-7F?null:((var2 = (var2 - this.x) / var3) >= 0.0F && var2 <= 1.0F?new Vec3D(this.x + var3 * var2, this.y + var4 * var2, this.z + var5 * var2):null);
+ }
+
+ public final Vec3D getYIntersection(Vec3D var1, float var2) {
+ float var3 = var1.x - this.x;
+ float var4 = var1.y - this.y;
+ float var5 = var1.z - this.z;
+ return var4 * var4 < 1.0E-7F?null:((var2 = (var2 - this.y) / var4) >= 0.0F && var2 <= 1.0F?new Vec3D(this.x + var3 * var2, this.y + var4 * var2, this.z + var5 * var2):null);
+ }
+
+ public final Vec3D getZIntersection(Vec3D var1, float var2) {
+ float var3 = var1.x - this.x;
+ float var4 = var1.y - this.y;
+ float var5;
+ return (var5 = var1.z - this.z) * var5 < 1.0E-7F?null:((var2 = (var2 - this.z) / var5) >= 0.0F && var2 <= 1.0F?new Vec3D(this.x + var3 * var2, this.y + var4 * var2, this.z + var5 * var2):null);
+ }
+
+ public final String toString() {
+ return "(" + this.x + ", " + this.y + ", " + this.z + ")";
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/Vertex.java b/src/main/java/com/mojang/minecraft/model/Vertex.java
new file mode 100644
index 0000000..1e62351
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/Vertex.java
@@ -0,0 +1,31 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.Vec3D;
+
+public final class Vertex {
+
+ public Vec3D vector;
+ public float u;
+ public float v;
+
+
+ public Vertex(float var1, float var2, float var3, float var4, float var5) {
+ this(new Vec3D(var1, var2, var3), var4, var5);
+ }
+
+ public final Vertex create(float var1, float var2) {
+ return new Vertex(this, var1, var2);
+ }
+
+ private Vertex(Vertex var1, float var2, float var3) {
+ this.vector = var1.vector;
+ this.u = var2;
+ this.v = var3;
+ }
+
+ private Vertex(Vec3D var1, float var2, float var3) {
+ this.vector = var1;
+ this.u = var2;
+ this.v = var3;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/model/ZombieModel.java b/src/main/java/com/mojang/minecraft/model/ZombieModel.java
new file mode 100644
index 0000000..c5e6f23
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/model/ZombieModel.java
@@ -0,0 +1,25 @@
+package com.mojang.minecraft.model;
+
+import com.mojang.minecraft.model.HumanoidModel;
+import com.mojang.util.MathHelper;
+
+public class ZombieModel extends HumanoidModel {
+
+ public final void setRotationAngles(float var1, float var2, float var3, float var4, float var5, float var6) {
+ super.setRotationAngles(var1, var2, var3, var4, var5, var6);
+ var1 = MathHelper.sin(this.attackOffset * 3.1415927F);
+ var2 = MathHelper.sin((1.0F - (1.0F - this.attackOffset) * (1.0F - this.attackOffset)) * 3.1415927F);
+ this.rightArm.roll = 0.0F;
+ this.leftArm.roll = 0.0F;
+ this.rightArm.yaw = -(0.1F - var1 * 0.6F);
+ this.leftArm.yaw = 0.1F - var1 * 0.6F;
+ this.rightArm.pitch = -1.5707964F;
+ this.leftArm.pitch = -1.5707964F;
+ this.rightArm.pitch -= var1 * 1.2F - var2 * 0.4F;
+ this.leftArm.pitch -= var1 * 1.2F - var2 * 0.4F;
+ this.rightArm.roll += MathHelper.cos(var3 * 0.09F) * 0.05F + 0.05F;
+ this.leftArm.roll -= MathHelper.cos(var3 * 0.09F) * 0.05F + 0.05F;
+ this.rightArm.pitch += MathHelper.sin(var3 * 0.067F) * 0.05F;
+ this.leftArm.pitch -= MathHelper.sin(var3 * 0.067F) * 0.05F;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/net/NetworkManager.java b/src/main/java/com/mojang/minecraft/net/NetworkManager.java
new file mode 100644
index 0000000..866878b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/net/NetworkManager.java
@@ -0,0 +1,74 @@
+package com.mojang.minecraft.net;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.ErrorScreen;
+import com.mojang.net.NetworkHandler;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+public class NetworkManager
+{
+ public NetworkManager(Minecraft minecraft, String server, int port, String username, String key)
+ {
+ minecraft.online = true;
+
+ this.minecraft = minecraft;
+
+ players = new HashMap();
+
+ new ServerConnectThread(this, server, port, username, key, minecraft).start();
+ }
+
+ public ByteArrayOutputStream levelData;
+
+ public NetworkHandler netHandler;
+
+ public Minecraft minecraft;
+
+ public boolean successful = false;
+ public boolean levelLoaded = false;
+
+ public HashMap players;
+
+ public void sendBlockChange(int x, int y, int z, int mode, int block)
+ {
+ netHandler.send(PacketType.PLAYER_SET_BLOCK, new Object[] {x, y, z, mode, block});
+ }
+
+ public void error(Exception e)
+ {
+ netHandler.close();
+
+ ErrorScreen errorScreen = new ErrorScreen("Disconnected!", e.getMessage());
+
+ minecraft.setCurrentScreen(errorScreen);
+
+ e.printStackTrace();
+ }
+
+ public boolean isConnected()
+ {
+ return netHandler != null && netHandler.connected;
+ }
+
+ public List getPlayers()
+ {
+ ArrayList list = new ArrayList();
+
+ list.add(minecraft.session.username);
+
+ Iterator playerIterator = this.players.values().iterator();
+
+ while(playerIterator.hasNext())
+ {
+ NetworkPlayer networkPlayer = (NetworkPlayer)playerIterator.next();
+
+ list.add(networkPlayer.name);
+ }
+
+ return list;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/net/NetworkPlayer.java b/src/main/java/com/mojang/minecraft/net/NetworkPlayer.java
new file mode 100644
index 0000000..b8c0045
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/net/NetworkPlayer.java
@@ -0,0 +1,235 @@
+package com.mojang.minecraft.net;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.FontRenderer;
+import com.mojang.minecraft.mob.HumanoidMob;
+import com.mojang.minecraft.net.PositionUpdate;
+import com.mojang.minecraft.net.SkinDownloadThread;
+import com.mojang.minecraft.render.TextureManager;
+import java.awt.image.BufferedImage;
+import java.util.LinkedList;
+import java.util.List;
+import org.lwjgl.opengl.GL11;
+
+public class NetworkPlayer extends HumanoidMob {
+
+ public static final long serialVersionUID = 77479605454997290L;
+ private List moveQueue = new LinkedList();
+ private Minecraft minecraft;
+ private int xp;
+ private int yp;
+ private int zp;
+ private transient int a = -1;
+ public transient BufferedImage newTexture = null;
+ public String name;
+ public String displayName;
+ int tickCount = 0;
+ private TextureManager textures;
+
+
+ public NetworkPlayer(Minecraft var1, int var2, String var3, int var4, int var5, int var6, float var7, float var8) {
+ super(var1.level, (float)var4, (float)var5, (float)var6);
+ this.minecraft = var1;
+ this.displayName = var3;
+ var3 = FontRenderer.stripColor(var3);
+ this.name = var3;
+ this.xp = var4;
+ this.yp = var5;
+ this.zp = var6;
+ this.heightOffset = 0.0F;
+ this.pushthrough = 0.8F;
+ this.setPos((float)var4 / 32.0F, (float)var5 / 32.0F, (float)var6 / 32.0F);
+ this.xRot = var8;
+ this.yRot = var7;
+ this.armor = this.helmet = false;
+ this.renderOffset = 0.6875F;
+ (new SkinDownloadThread(this)).start();
+ this.allowAlpha = false;
+ }
+
+ public void aiStep() {
+ int var1 = 5;
+
+ do {
+ if(this.moveQueue.size() > 0) {
+ this.setPos((PositionUpdate)this.moveQueue.remove(0));
+ }
+ } while(var1-- > 0 && this.moveQueue.size() > 10);
+
+ this.onGround = true;
+ }
+
+ public void bindTexture(TextureManager var1) {
+ this.textures = var1;
+ if(this.newTexture != null) {
+ BufferedImage var2 = this.newTexture;
+ int[] var3 = new int[512];
+ var2.getRGB(32, 0, 32, 16, var3, 0, 32);
+ int var5 = 0;
+
+ boolean var10001;
+ while(true) {
+ if(var5 >= var3.length) {
+ var10001 = false;
+ break;
+ }
+
+ if(var3[var5] >>> 24 < 128) {
+ var10001 = true;
+ break;
+ }
+
+ ++var5;
+ }
+
+ this.hasHair = var10001;
+ this.a = var1.load(this.newTexture);
+ this.newTexture = null;
+ }
+
+ if(this.a < 0) {
+ GL11.glBindTexture(3553, var1.load("/char.png"));
+ } else {
+ GL11.glBindTexture(3553, this.a);
+ }
+ }
+
+ public void renderHover(TextureManager var1, float var2) {
+ FontRenderer var3 = this.minecraft.fontRenderer;
+ GL11.glPushMatrix();
+ GL11.glTranslatef(this.xo + (this.x - this.xo) * var2, this.yo + (this.y - this.yo) * var2 + 0.8F + this.renderOffset, this.zo + (this.z - this.zo) * var2);
+ GL11.glRotatef(-this.minecraft.player.yRot, 0.0F, 1.0F, 0.0F);
+ var2 = 0.05F;
+ GL11.glScalef(0.05F, -var2, var2);
+ GL11.glTranslatef((float)(-var3.getWidth(this.displayName)) / 2.0F, 0.0F, 0.0F);
+ GL11.glNormal3f(1.0F, -1.0F, 1.0F);
+ GL11.glDisable(2896);
+ GL11.glDisable(16384);
+ if(this.name.equalsIgnoreCase("Notch")) {
+ var3.renderNoShadow(this.displayName, 0, 0, 16776960);
+ } else {
+ var3.renderNoShadow(this.displayName, 0, 0, 16777215);
+ }
+
+ GL11.glDepthFunc(516);
+ GL11.glDepthMask(false);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.8F);
+ GL11.glEnable(3042);
+ GL11.glBlendFunc(770, 771);
+ var3.renderNoShadow(this.displayName, 0, 0, 16777215);
+ GL11.glDisable(3042);
+ GL11.glDepthMask(true);
+ GL11.glDepthFunc(515);
+ GL11.glTranslatef(1.0F, 1.0F, -0.05F);
+ var3.renderNoShadow(this.name, 0, 0, 5263440);
+ GL11.glEnable(16384);
+ GL11.glEnable(2896);
+ GL11.glPopMatrix();
+ }
+
+ public void queue(byte var1, byte var2, byte var3, float var4, float var5) {
+ float var6 = var4 - this.yRot;
+
+ float var7;
+ for(var7 = var5 - this.xRot; var6 >= 180.0F; var6 -= 360.0F) {
+ ;
+ }
+
+ while(var6 < -180.0F) {
+ var6 += 360.0F;
+ }
+
+ while(var7 >= 180.0F) {
+ var7 -= 360.0F;
+ }
+
+ while(var7 < -180.0F) {
+ var7 += 360.0F;
+ }
+
+ var6 = this.yRot + var6 * 0.5F;
+ var7 = this.xRot + var7 * 0.5F;
+ this.moveQueue.add(new PositionUpdate(((float)this.xp + (float)var1 / 2.0F) / 32.0F, ((float)this.yp + (float)var2 / 2.0F) / 32.0F, ((float)this.zp + (float)var3 / 2.0F) / 32.0F, var6, var7));
+ this.xp += var1;
+ this.yp += var2;
+ this.zp += var3;
+ this.moveQueue.add(new PositionUpdate((float)this.xp / 32.0F, (float)this.yp / 32.0F, (float)this.zp / 32.0F, var4, var5));
+ }
+
+ public void teleport(short var1, short var2, short var3, float var4, float var5) {
+ float var6 = var4 - this.yRot;
+
+ float var7;
+ for(var7 = var5 - this.xRot; var6 >= 180.0F; var6 -= 360.0F) {
+ ;
+ }
+
+ while(var6 < -180.0F) {
+ var6 += 360.0F;
+ }
+
+ while(var7 >= 180.0F) {
+ var7 -= 360.0F;
+ }
+
+ while(var7 < -180.0F) {
+ var7 += 360.0F;
+ }
+
+ var6 = this.yRot + var6 * 0.5F;
+ var7 = this.xRot + var7 * 0.5F;
+ this.moveQueue.add(new PositionUpdate((float)(this.xp + var1) / 64.0F, (float)(this.yp + var2) / 64.0F, (float)(this.zp + var3) / 64.0F, var6, var7));
+ this.xp = var1;
+ this.yp = var2;
+ this.zp = var3;
+ this.moveQueue.add(new PositionUpdate((float)this.xp / 32.0F, (float)this.yp / 32.0F, (float)this.zp / 32.0F, var4, var5));
+ }
+
+ public void queue(byte var1, byte var2, byte var3) {
+ this.moveQueue.add(new PositionUpdate(((float)this.xp + (float)var1 / 2.0F) / 32.0F, ((float)this.yp + (float)var2 / 2.0F) / 32.0F, ((float)this.zp + (float)var3 / 2.0F) / 32.0F));
+ this.xp += var1;
+ this.yp += var2;
+ this.zp += var3;
+ this.moveQueue.add(new PositionUpdate((float)this.xp / 32.0F, (float)this.yp / 32.0F, (float)this.zp / 32.0F));
+ }
+
+ public void queue(float var1, float var2) {
+ float var3 = var1 - this.yRot;
+
+ float var4;
+ for(var4 = var2 - this.xRot; var3 >= 180.0F; var3 -= 360.0F) {
+ ;
+ }
+
+ while(var3 < -180.0F) {
+ var3 += 360.0F;
+ }
+
+ while(var4 >= 180.0F) {
+ var4 -= 360.0F;
+ }
+
+ while(var4 < -180.0F) {
+ var4 += 360.0F;
+ }
+
+ var3 = this.yRot + var3 * 0.5F;
+ var4 = this.xRot + var4 * 0.5F;
+ this.moveQueue.add(new PositionUpdate(var3, var4));
+ this.moveQueue.add(new PositionUpdate(var1, var2));
+ }
+
+ public void clear() {
+ if(this.a >= 0 && this.textures != null) {
+ TextureManager var10000 = this.textures;
+ int var1 = this.a;
+ TextureManager var2 = this.textures;
+ var10000.textureImages.remove(Integer.valueOf(var1));
+ var2.idBuffer.clear();
+ var2.idBuffer.put(var1);
+ var2.idBuffer.flip();
+ GL11.glDeleteTextures(var2.idBuffer.get());
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/net/PacketType.java b/src/main/java/com/mojang/minecraft/net/PacketType.java
new file mode 100644
index 0000000..9d3ca6f
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/net/PacketType.java
@@ -0,0 +1,86 @@
+package com.mojang.minecraft.net;
+
+public class PacketType
+{
+ private PacketType(Class ... classes)
+ {
+ opcode = (byte)(nextOpcode++);
+ packets[opcode] = this;
+ params = new Class[classes.length];
+
+ int length = 0;
+
+ for(int classNumber = 0; classNumber < classes.length; classNumber++)
+ {
+ Class class_ = classes[classNumber];
+
+ params[classNumber] = class_;
+
+ if(class_ == Long.TYPE)
+ {
+ length += 8;
+ } else if(class_ == Integer.TYPE) {
+ length += 4;
+ } else if(class_ == Short.TYPE) {
+ length += 2;
+ } else if(class_ == Byte.TYPE) {
+ ++length;
+ } else if(class_ == Float.TYPE) {
+ length += 4;
+ } else if(class_ == Double.TYPE) {
+ length += 8;
+ } else if(class_ == byte[].class) {
+ length += 1024;
+ } else if(class_ == String.class) {
+ length += 64;
+ }
+ }
+
+ this.length = length;
+ }
+
+ public static final PacketType[] packets = new PacketType[256];
+
+ public static final PacketType IDENTIFICATION = new PacketType(new Class[] {Byte.TYPE, String.class, String.class, Byte.TYPE});
+ public static final PacketType LEVEL_INIT;
+ public static final PacketType LEVEL_DATA;
+ public static final PacketType LEVEL_FINALIZE;
+ public static final PacketType PLAYER_SET_BLOCK;
+ public static final PacketType BLOCK_CHANGE;
+ public static final PacketType SPAWN_PLAYER;
+ public static final PacketType POSITION_ROTATION;
+ public static final PacketType POSITION_ROTATION_UPDATE;
+ public static final PacketType POSITION_UPDATE;
+ public static final PacketType ROTATION_UPDATE;
+ public static final PacketType DESPAWN_PLAYER;
+ public static final PacketType CHAT_MESSAGE;
+ public static final PacketType DISCONNECT;
+ public static final PacketType UPDATE_PLAYER_TYPE;
+
+ public int length;
+ private static int nextOpcode;
+ public byte opcode;
+ public Class[] params;
+
+ static
+ {
+ new PacketType(new Class[0]);
+
+ LEVEL_INIT = new PacketType(new Class[0]);
+ LEVEL_DATA = new PacketType(new Class[] {Short.TYPE, byte[].class, Byte.TYPE});
+ LEVEL_FINALIZE = new PacketType(new Class[] {Short.TYPE, Short.TYPE, Short.TYPE});
+ PLAYER_SET_BLOCK = new PacketType(new Class[] {Short.TYPE, Short.TYPE, Short.TYPE, Byte.TYPE, Byte.TYPE});
+ BLOCK_CHANGE = new PacketType(new Class[] {Short.TYPE, Short.TYPE, Short.TYPE, Byte.TYPE});
+ SPAWN_PLAYER = new PacketType(new Class[] {Byte.TYPE, String.class, Short.TYPE, Short.TYPE, Short.TYPE, Byte.TYPE, Byte.TYPE});
+ POSITION_ROTATION = new PacketType(new Class[] {Byte.TYPE, Short.TYPE, Short.TYPE, Short.TYPE, Byte.TYPE, Byte.TYPE});
+ POSITION_ROTATION_UPDATE = new PacketType(new Class[] {Byte.TYPE, Byte.TYPE, Byte.TYPE, Byte.TYPE, Byte.TYPE, Byte.TYPE});
+ POSITION_UPDATE = new PacketType(new Class[] {Byte.TYPE, Byte.TYPE, Byte.TYPE, Byte.TYPE});
+ ROTATION_UPDATE = new PacketType(new Class[] {Byte.TYPE, Byte.TYPE, Byte.TYPE});
+ DESPAWN_PLAYER = new PacketType(new Class[] {Byte.TYPE});
+ CHAT_MESSAGE = new PacketType(new Class[] {Byte.TYPE, String.class});
+ DISCONNECT = new PacketType(new Class[] {String.class});
+ UPDATE_PLAYER_TYPE = new PacketType(new Class[] {Byte.TYPE});
+
+ nextOpcode = 0;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/net/PositionUpdate.java b/src/main/java/com/mojang/minecraft/net/PositionUpdate.java
new file mode 100644
index 0000000..f6dd543
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/net/PositionUpdate.java
@@ -0,0 +1,45 @@
+package com.mojang.minecraft.net;
+
+public class PositionUpdate
+{
+ public PositionUpdate(float x, float y, float z, float yaw, float pitch)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.yaw = yaw;
+ this.pitch = pitch;
+
+ rotation = true;
+ position = true;
+ }
+
+ public PositionUpdate(float x, float y, float z)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+
+ position = true;
+ rotation = false;
+ }
+
+ public PositionUpdate(float yaw, float pitch)
+ {
+ this.yaw = yaw;
+ this.pitch = pitch;
+
+ rotation = true;
+ position = false;
+ }
+
+ public float x;
+ public float y;
+ public float z;
+
+ public float yaw;
+ public float pitch;
+
+ public boolean rotation = false;
+ public boolean position = false;
+}
diff --git a/src/main/java/com/mojang/minecraft/net/ServerConnectThread.java b/src/main/java/com/mojang/minecraft/net/ServerConnectThread.java
new file mode 100644
index 0000000..e102efb
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/net/ServerConnectThread.java
@@ -0,0 +1,53 @@
+package com.mojang.minecraft.net;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.gui.ErrorScreen;
+import com.mojang.net.NetworkHandler;
+
+public class ServerConnectThread extends Thread
+{
+ public ServerConnectThread(NetworkManager networkManager, String server, int port, String username, String key, Minecraft minecraft) {
+ super();
+
+ netManager = networkManager;
+
+ this.server = server;
+ this.port = port;
+
+ this.username = username;
+ this.key = key;
+
+ this.minecraft = minecraft;
+ }
+
+ @Override
+ public void run()
+ {
+ try {
+ netManager.netHandler = new NetworkHandler(server, port);
+ netManager.netHandler.netManager = netManager;
+
+ netManager.netHandler.send(PacketType.IDENTIFICATION, new Object[]{Byte.valueOf((byte)7), this.username, this.key, Integer.valueOf(0)});
+
+ netManager.successful = true;
+ } catch (Exception var3) {
+ minecraft.online = false;
+
+ minecraft.networkManager = null;
+
+ minecraft.setCurrentScreen(new ErrorScreen("Failed to connect", "You failed to connect to the server. It\'s probably down!"));
+
+ netManager.successful = false;
+ }
+ }
+
+ private String server;
+ private int port;
+
+ private String username;
+ private String key;
+
+ private Minecraft minecraft;
+
+ private NetworkManager netManager;
+}
diff --git a/src/main/java/com/mojang/minecraft/net/SkinDownloadThread.java b/src/main/java/com/mojang/minecraft/net/SkinDownloadThread.java
new file mode 100644
index 0000000..e8a4098
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/net/SkinDownloadThread.java
@@ -0,0 +1,46 @@
+package com.mojang.minecraft.net;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import javax.imageio.ImageIO;
+
+public class SkinDownloadThread extends Thread
+{
+ public SkinDownloadThread(NetworkPlayer networkPlayer)
+ {
+ super();
+
+ this.player = networkPlayer;
+ }
+
+ @Override
+ public void run()
+ {
+ HttpURLConnection connection = null;
+
+ try {
+ connection = (HttpURLConnection)new URL("http://www.minecraft.net/skin/" + player.name + ".png").openConnection();
+
+ connection.setDoInput(true);
+ connection.setDoOutput(false);
+
+ connection.connect();
+
+ if(connection.getResponseCode() == 404)
+ {
+ return;
+ }
+
+ player.newTexture = ImageIO.read(connection.getInputStream());
+ } catch(Exception e) {
+ e.printStackTrace();
+ } finally {
+ if(connection != null)
+ {
+ connection.disconnect();
+ }
+ }
+ }
+
+ private NetworkPlayer player;
+}
diff --git a/src/main/java/com/mojang/minecraft/particle/Particle.java b/src/main/java/com/mojang/minecraft/particle/Particle.java
new file mode 100644
index 0000000..d24916c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/particle/Particle.java
@@ -0,0 +1,101 @@
+package com.mojang.minecraft.particle;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.util.MathHelper;
+
+public class Particle extends Entity {
+
+ private static final long serialVersionUID = 1L;
+ protected float xd;
+ protected float yd;
+ protected float zd;
+ protected int tex;
+ protected float uo;
+ protected float vo;
+ protected int age = 0;
+ protected int lifetime = 0;
+ protected float size;
+ protected float gravity;
+ protected float rCol;
+ protected float gCol;
+ protected float bCol;
+
+
+ public Particle(Level var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ super(var1);
+ this.setSize(0.2F, 0.2F);
+ this.heightOffset = this.bbHeight / 2.0F;
+ this.setPos(var2, var3, var4);
+ this.rCol = this.gCol = this.bCol = 1.0F;
+ this.xd = var5 + (float)(Math.random() * 2.0D - 1.0D) * 0.4F;
+ this.yd = var6 + (float)(Math.random() * 2.0D - 1.0D) * 0.4F;
+ this.zd = var7 + (float)(Math.random() * 2.0D - 1.0D) * 0.4F;
+ float var8 = (float)(Math.random() + Math.random() + 1.0D) * 0.15F;
+ var2 = MathHelper.sqrt(this.xd * this.xd + this.yd * this.yd + this.zd * this.zd);
+ this.xd = this.xd / var2 * var8 * 0.4F;
+ this.yd = this.yd / var2 * var8 * 0.4F + 0.1F;
+ this.zd = this.zd / var2 * var8 * 0.4F;
+ this.uo = (float)Math.random() * 3.0F;
+ this.vo = (float)Math.random() * 3.0F;
+ this.size = (float)(Math.random() * 0.5D + 0.5D);
+ this.lifetime = (int)(4.0D / (Math.random() * 0.9D + 0.1D));
+ this.age = 0;
+ this.makeStepSound = false;
+ }
+
+ public Particle setPower(float var1) {
+ this.xd *= var1;
+ this.yd = (this.yd - 0.1F) * var1 + 0.1F;
+ this.zd *= var1;
+ return this;
+ }
+
+ public Particle scale(float var1) {
+ this.setSize(0.2F * var1, 0.2F * var1);
+ this.size *= var1;
+ return this;
+ }
+
+ public void tick() {
+ this.xo = this.x;
+ this.yo = this.y;
+ this.zo = this.z;
+ if(this.age++ >= this.lifetime) {
+ this.remove();
+ }
+
+ this.yd = (float)((double)this.yd - 0.04D * (double)this.gravity);
+ this.move(this.xd, this.yd, this.zd);
+ this.xd *= 0.98F;
+ this.yd *= 0.98F;
+ this.zd *= 0.98F;
+ if(this.onGround) {
+ this.xd *= 0.7F;
+ this.zd *= 0.7F;
+ }
+
+ }
+
+ public void render(ShapeRenderer var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ float var8;
+ float var9 = (var8 = (float)(this.tex % 16) / 16.0F) + 0.0624375F;
+ float var10;
+ float var11 = (var10 = (float)(this.tex / 16) / 16.0F) + 0.0624375F;
+ float var12 = 0.1F * this.size;
+ float var13 = this.xo + (this.x - this.xo) * var2;
+ float var14 = this.yo + (this.y - this.yo) * var2;
+ float var15 = this.zo + (this.z - this.zo) * var2;
+ var2 = this.getBrightness(var2);
+ var1.color(this.rCol * var2, this.gCol * var2, this.bCol * var2);
+ var1.vertexUV(var13 - var3 * var12 - var6 * var12, var14 - var4 * var12, var15 - var5 * var12 - var7 * var12, var8, var11);
+ var1.vertexUV(var13 - var3 * var12 + var6 * var12, var14 + var4 * var12, var15 - var5 * var12 + var7 * var12, var8, var10);
+ var1.vertexUV(var13 + var3 * var12 + var6 * var12, var14 + var4 * var12, var15 + var5 * var12 + var7 * var12, var9, var10);
+ var1.vertexUV(var13 + var3 * var12 - var6 * var12, var14 - var4 * var12, var15 + var5 * var12 - var7 * var12, var9, var11);
+ }
+
+ public int getParticleTexture() {
+ return 0;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/particle/ParticleManager.java b/src/main/java/com/mojang/minecraft/particle/ParticleManager.java
new file mode 100644
index 0000000..8dbeef6
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/particle/ParticleManager.java
@@ -0,0 +1,47 @@
+package com.mojang.minecraft.particle;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.particle.Particle;
+import com.mojang.minecraft.render.TextureManager;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class ParticleManager {
+
+ public List[] particles = new List[2];
+ public TextureManager textureManager;
+
+
+ public ParticleManager(Level var1, TextureManager var2) {
+ if(var1 != null) {
+ var1.particleEngine = this;
+ }
+
+ this.textureManager = var2;
+
+ for(int var3 = 0; var3 < 2; ++var3) {
+ this.particles[var3] = new ArrayList();
+ }
+
+ }
+
+ public final void spawnParticle(Entity var1) {
+ Particle var3;
+ int var2 = (var3 = (Particle)var1).getParticleTexture();
+ this.particles[var2].add(var3);
+ }
+
+ public final void tick() {
+ for(int var1 = 0; var1 < 2; ++var1) {
+ for(int var2 = 0; var2 < this.particles[var1].size(); ++var2) {
+ Particle var3;
+ (var3 = (Particle)this.particles[var1].get(var2)).tick();
+ if(var3.removed) {
+ this.particles[var1].remove(var2--);
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/particle/SmokeParticle.java b/src/main/java/com/mojang/minecraft/particle/SmokeParticle.java
new file mode 100644
index 0000000..b2ced7c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/particle/SmokeParticle.java
@@ -0,0 +1,46 @@
+package com.mojang.minecraft.particle;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.particle.Particle;
+import com.mojang.minecraft.render.ShapeRenderer;
+
+public class SmokeParticle extends Particle {
+
+ private static final long serialVersionUID = 1L;
+
+
+ public SmokeParticle(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4, 0.0F, 0.0F, 0.0F);
+ this.xd *= 0.1F;
+ this.yd *= 0.1F;
+ this.zd *= 0.1F;
+ this.rCol = this.gCol = this.bCol = (float)(Math.random() * 0.30000001192092896D);
+ this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
+ this.noPhysics = true;
+ }
+
+ public void render(ShapeRenderer var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ super.render(var1, var2, var3, var4, var5, var6, var7);
+ }
+
+ public void tick() {
+ this.xo = this.x;
+ this.yo = this.y;
+ this.zo = this.z;
+ if(this.age++ >= this.lifetime) {
+ this.remove();
+ }
+
+ this.tex = 7 - (this.age << 3) / this.lifetime;
+ this.yd = (float)((double)this.yd + 0.004D);
+ this.move(this.xd, this.yd, this.zd);
+ this.xd *= 0.96F;
+ this.yd *= 0.96F;
+ this.zd *= 0.96F;
+ if(this.onGround) {
+ this.xd *= 0.7F;
+ this.zd *= 0.7F;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/particle/TerrainParticle.java b/src/main/java/com/mojang/minecraft/particle/TerrainParticle.java
new file mode 100644
index 0000000..22f8617
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/particle/TerrainParticle.java
@@ -0,0 +1,40 @@
+package com.mojang.minecraft.particle;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.particle.Particle;
+import com.mojang.minecraft.render.ShapeRenderer;
+
+public class TerrainParticle extends Particle {
+
+ private static final long serialVersionUID = 1L;
+
+
+ public TerrainParticle(Level var1, float var2, float var3, float var4, float var5, float var6, float var7, Block var8) {
+ super(var1, var2, var3, var4, var5, var6, var7);
+ this.tex = var8.textureId;
+ this.gravity = var8.particleGravity;
+ this.rCol = this.gCol = this.bCol = 0.6F;
+ }
+
+ public int getParticleTexture() {
+ return 1;
+ }
+
+ public void render(ShapeRenderer var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ float var8;
+ float var9 = (var8 = ((float)(this.tex % 16) + this.uo / 4.0F) / 16.0F) + 0.015609375F;
+ float var10;
+ float var11 = (var10 = ((float)(this.tex / 16) + this.vo / 4.0F) / 16.0F) + 0.015609375F;
+ float var12 = 0.1F * this.size;
+ float var13 = this.xo + (this.x - this.xo) * var2;
+ float var14 = this.yo + (this.y - this.yo) * var2;
+ float var15 = this.zo + (this.z - this.zo) * var2;
+ var2 = this.getBrightness(var2);
+ var1.color(var2 * this.rCol, var2 * this.gCol, var2 * this.bCol);
+ var1.vertexUV(var13 - var3 * var12 - var6 * var12, var14 - var4 * var12, var15 - var5 * var12 - var7 * var12, var8, var11);
+ var1.vertexUV(var13 - var3 * var12 + var6 * var12, var14 + var4 * var12, var15 - var5 * var12 + var7 * var12, var8, var10);
+ var1.vertexUV(var13 + var3 * var12 + var6 * var12, var14 + var4 * var12, var15 + var5 * var12 + var7 * var12, var9, var10);
+ var1.vertexUV(var13 + var3 * var12 - var6 * var12, var14 - var4 * var12, var15 + var5 * var12 - var7 * var12, var9, var11);
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/particle/WaterDropParticle.java b/src/main/java/com/mojang/minecraft/particle/WaterDropParticle.java
new file mode 100644
index 0000000..0479a50
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/particle/WaterDropParticle.java
@@ -0,0 +1,52 @@
+package com.mojang.minecraft.particle;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.particle.Particle;
+import com.mojang.minecraft.render.ShapeRenderer;
+
+public class WaterDropParticle extends Particle {
+
+ private static final long serialVersionUID = 1L;
+
+
+ public WaterDropParticle(Level var1, float var2, float var3, float var4) {
+ super(var1, var2, var3, var4, 0.0F, 0.0F, 0.0F);
+ this.xd *= 0.3F;
+ this.yd = (float)Math.random() * 0.2F + 0.1F;
+ this.zd *= 0.3F;
+ this.rCol = 1.0F;
+ this.gCol = 1.0F;
+ this.bCol = 1.0F;
+ this.tex = 16;
+ this.setSize(0.01F, 0.01F);
+ this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
+ }
+
+ public void render(ShapeRenderer var1, float var2, float var3, float var4, float var5, float var6, float var7) {
+ super.render(var1, var2, var3, var4, var5, var6, var7);
+ }
+
+ public void tick() {
+ this.xo = this.x;
+ this.yo = this.y;
+ this.zo = this.z;
+ this.yd = (float)((double)this.yd - 0.06D);
+ this.move(this.xd, this.yd, this.zd);
+ this.xd *= 0.98F;
+ this.yd *= 0.98F;
+ this.zd *= 0.98F;
+ if(this.lifetime-- <= 0) {
+ this.remove();
+ }
+
+ if(this.onGround) {
+ if(Math.random() < 0.5D) {
+ this.remove();
+ }
+
+ this.xd *= 0.7F;
+ this.zd *= 0.7F;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/phys/AABB.java b/src/main/java/com/mojang/minecraft/phys/AABB.java
new file mode 100644
index 0000000..6c6ffdf
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/phys/AABB.java
@@ -0,0 +1,308 @@
+package com.mojang.minecraft.phys;
+
+import com.mojang.minecraft.MovingObjectPosition;
+import com.mojang.minecraft.model.Vec3D;
+import java.io.Serializable;
+
+public class AABB implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ private float epsilon = 0.0F;
+ public float x0;
+ public float y0;
+ public float z0;
+ public float x1;
+ public float y1;
+ public float z1;
+
+
+ public AABB(float var1, float var2, float var3, float var4, float var5, float var6) {
+ this.x0 = var1;
+ this.y0 = var2;
+ this.z0 = var3;
+ this.x1 = var4;
+ this.y1 = var5;
+ this.z1 = var6;
+ }
+
+ public AABB expand(float var1, float var2, float var3) {
+ float var4 = this.x0;
+ float var5 = this.y0;
+ float var6 = this.z0;
+ float var7 = this.x1;
+ float var8 = this.y1;
+ float var9 = this.z1;
+ if(var1 < 0.0F) {
+ var4 += var1;
+ }
+
+ if(var1 > 0.0F) {
+ var7 += var1;
+ }
+
+ if(var2 < 0.0F) {
+ var5 += var2;
+ }
+
+ if(var2 > 0.0F) {
+ var8 += var2;
+ }
+
+ if(var3 < 0.0F) {
+ var6 += var3;
+ }
+
+ if(var3 > 0.0F) {
+ var9 += var3;
+ }
+
+ return new AABB(var4, var5, var6, var7, var8, var9);
+ }
+
+ public AABB grow(float var1, float var2, float var3) {
+ float var4 = this.x0 - var1;
+ float var5 = this.y0 - var2;
+ float var6 = this.z0 - var3;
+ var1 += this.x1;
+ var2 += this.y1;
+ float var7 = this.z1 + var3;
+ return new AABB(var4, var5, var6, var1, var2, var7);
+ }
+
+ public AABB cloneMove(float var1, float var2, float var3) {
+ return new AABB(this.x0 + var3, this.y0 + var2, this.z0 + var3, this.x1 + var1, this.y1 + var2, this.z1 + var3);
+ }
+
+ public float clipXCollide(AABB var1, float var2) {
+ if(var1.y1 > this.y0 && var1.y0 < this.y1) {
+ if(var1.z1 > this.z0 && var1.z0 < this.z1) {
+ float var3;
+ if(var2 > 0.0F && var1.x1 <= this.x0 && (var3 = this.x0 - var1.x1 - this.epsilon) < var2) {
+ var2 = var3;
+ }
+
+ if(var2 < 0.0F && var1.x0 >= this.x1 && (var3 = this.x1 - var1.x0 + this.epsilon) > var2) {
+ var2 = var3;
+ }
+
+ return var2;
+ } else {
+ return var2;
+ }
+ } else {
+ return var2;
+ }
+ }
+
+ public float clipYCollide(AABB var1, float var2) {
+ if(var1.x1 > this.x0 && var1.x0 < this.x1) {
+ if(var1.z1 > this.z0 && var1.z0 < this.z1) {
+ float var3;
+ if(var2 > 0.0F && var1.y1 <= this.y0 && (var3 = this.y0 - var1.y1 - this.epsilon) < var2) {
+ var2 = var3;
+ }
+
+ if(var2 < 0.0F && var1.y0 >= this.y1 && (var3 = this.y1 - var1.y0 + this.epsilon) > var2) {
+ var2 = var3;
+ }
+
+ return var2;
+ } else {
+ return var2;
+ }
+ } else {
+ return var2;
+ }
+ }
+
+ public float clipZCollide(AABB var1, float var2) {
+ if(var1.x1 > this.x0 && var1.x0 < this.x1) {
+ if(var1.y1 > this.y0 && var1.y0 < this.y1) {
+ float var3;
+ if(var2 > 0.0F && var1.z1 <= this.z0 && (var3 = this.z0 - var1.z1 - this.epsilon) < var2) {
+ var2 = var3;
+ }
+
+ if(var2 < 0.0F && var1.z0 >= this.z1 && (var3 = this.z1 - var1.z0 + this.epsilon) > var2) {
+ var2 = var3;
+ }
+
+ return var2;
+ } else {
+ return var2;
+ }
+ } else {
+ return var2;
+ }
+ }
+
+ public boolean intersects(AABB var1) {
+ return var1.x1 > this.x0 && var1.x0 < this.x1?(var1.y1 > this.y0 && var1.y0 < this.y1?var1.z1 > this.z0 && var1.z0 < this.z1:false):false;
+ }
+
+ public boolean intersectsInner(AABB var1) {
+ return var1.x1 >= this.x0 && var1.x0 <= this.x1?(var1.y1 >= this.y0 && var1.y0 <= this.y1?var1.z1 >= this.z0 && var1.z0 <= this.z1:false):false;
+ }
+
+ public void move(float var1, float var2, float var3) {
+ this.x0 += var1;
+ this.y0 += var2;
+ this.z0 += var3;
+ this.x1 += var1;
+ this.y1 += var2;
+ this.z1 += var3;
+ }
+
+ public boolean intersects(float var1, float var2, float var3, float var4, float var5, float var6) {
+ return var4 > this.x0 && var1 < this.x1?(var5 > this.y0 && var2 < this.y1?var6 > this.z0 && var3 < this.z1:false):false;
+ }
+
+ public boolean contains(Vec3D var1) {
+ return var1.x > this.x0 && var1.x < this.x1?(var1.y > this.y0 && var1.y < this.y1?var1.z > this.z0 && var1.z < this.z1:false):false;
+ }
+
+ public float getSize() {
+ float var1 = this.x1 - this.x0;
+ float var2 = this.y1 - this.y0;
+ float var3 = this.z1 - this.z0;
+ return (var1 + var2 + var3) / 3.0F;
+ }
+
+ public AABB shrink(float var1, float var2, float var3) {
+ float var4 = this.x0;
+ float var5 = this.y0;
+ float var6 = this.z0;
+ float var7 = this.x1;
+ float var8 = this.y1;
+ float var9 = this.z1;
+ if(var1 < 0.0F) {
+ var4 -= var1;
+ }
+
+ if(var1 > 0.0F) {
+ var7 -= var1;
+ }
+
+ if(var2 < 0.0F) {
+ var5 -= var2;
+ }
+
+ if(var2 > 0.0F) {
+ var8 -= var2;
+ }
+
+ if(var3 < 0.0F) {
+ var6 -= var3;
+ }
+
+ if(var3 > 0.0F) {
+ var9 -= var3;
+ }
+
+ return new AABB(var4, var5, var6, var7, var8, var9);
+ }
+
+ public AABB copy() {
+ return new AABB(this.x0, this.y0, this.z0, this.x1, this.y1, this.z1);
+ }
+
+ public MovingObjectPosition clip(Vec3D var1, Vec3D var2) {
+ Vec3D var3 = var1.getXIntersection(var2, this.x0);
+ Vec3D var4 = var1.getXIntersection(var2, this.x1);
+ Vec3D var5 = var1.getYIntersection(var2, this.y0);
+ Vec3D var6 = var1.getYIntersection(var2, this.y1);
+ Vec3D var7 = var1.getZIntersection(var2, this.z0);
+ var2 = var1.getZIntersection(var2, this.z1);
+ if(!this.xIntersects(var3)) {
+ var3 = null;
+ }
+
+ if(!this.xIntersects(var4)) {
+ var4 = null;
+ }
+
+ if(!this.yIntersects(var5)) {
+ var5 = null;
+ }
+
+ if(!this.yIntersects(var6)) {
+ var6 = null;
+ }
+
+ if(!this.zIntersects(var7)) {
+ var7 = null;
+ }
+
+ if(!this.zIntersects(var2)) {
+ var2 = null;
+ }
+
+ Vec3D var8 = null;
+ if(var3 != null) {
+ var8 = var3;
+ }
+
+ if(var4 != null && (var8 == null || var1.distanceSquared(var4) < var1.distanceSquared(var8))) {
+ var8 = var4;
+ }
+
+ if(var5 != null && (var8 == null || var1.distanceSquared(var5) < var1.distanceSquared(var8))) {
+ var8 = var5;
+ }
+
+ if(var6 != null && (var8 == null || var1.distanceSquared(var6) < var1.distanceSquared(var8))) {
+ var8 = var6;
+ }
+
+ if(var7 != null && (var8 == null || var1.distanceSquared(var7) < var1.distanceSquared(var8))) {
+ var8 = var7;
+ }
+
+ if(var2 != null && (var8 == null || var1.distanceSquared(var2) < var1.distanceSquared(var8))) {
+ var8 = var2;
+ }
+
+ if(var8 == null) {
+ return null;
+ } else {
+ byte var9 = -1;
+ if(var8 == var3) {
+ var9 = 4;
+ }
+
+ if(var8 == var4) {
+ var9 = 5;
+ }
+
+ if(var8 == var5) {
+ var9 = 0;
+ }
+
+ if(var8 == var6) {
+ var9 = 1;
+ }
+
+ if(var8 == var7) {
+ var9 = 2;
+ }
+
+ if(var8 == var2) {
+ var9 = 3;
+ }
+
+ return new MovingObjectPosition(0, 0, 0, var9, var8);
+ }
+ }
+
+ private boolean xIntersects(Vec3D var1) {
+ return var1 == null?false:var1.y >= this.y0 && var1.y <= this.y1 && var1.z >= this.z0 && var1.z <= this.z1;
+ }
+
+ private boolean yIntersects(Vec3D var1) {
+ return var1 == null?false:var1.x >= this.x0 && var1.x <= this.x1 && var1.z >= this.z0 && var1.z <= this.z1;
+ }
+
+ private boolean zIntersects(Vec3D var1) {
+ return var1 == null?false:var1.x >= this.x0 && var1.x <= this.x1 && var1.y >= this.y0 && var1.y <= this.y1;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/player/InputHandler.java b/src/main/java/com/mojang/minecraft/player/InputHandler.java
new file mode 100644
index 0000000..53827bb
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/player/InputHandler.java
@@ -0,0 +1,20 @@
+package com.mojang.minecraft.player;
+
+public class InputHandler
+{
+ public float xxa = 0.0F;
+ public float jumping = 0.0F;
+ public boolean yya = false;
+
+ public void updateMovement()
+ {
+ }
+
+ public void resetKeys()
+ {
+ }
+
+ public void setKeyState(int key, boolean state)
+ {
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/player/InputHandlerImpl.java b/src/main/java/com/mojang/minecraft/player/InputHandlerImpl.java
new file mode 100644
index 0000000..267697c
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/player/InputHandlerImpl.java
@@ -0,0 +1,90 @@
+package com.mojang.minecraft.player;
+
+import com.mojang.minecraft.GameSettings;
+
+public class InputHandlerImpl extends InputHandler
+{
+ public InputHandlerImpl(GameSettings gameSettings)
+ {
+ settings = gameSettings;
+ }
+
+ @Override
+ public void updateMovement()
+ {
+ xxa = 0.0F;
+ jumping = 0.0F;
+
+ if(keyStates[0])
+ {
+ jumping--;
+ }
+
+ if(keyStates[1])
+ {
+ jumping++;
+ }
+
+ if(keyStates[2])
+ {
+ xxa--;
+ }
+
+ if(keyStates[3])
+ {
+ xxa++;
+ }
+
+ yya = keyStates[4];
+ }
+
+ @Override
+ public void resetKeys()
+ {
+ for(int i = 0; i < keyStates.length; ++i)
+ {
+ keyStates[i] = false;
+ }
+
+ }
+
+ @Override
+ public void setKeyState(int key, boolean state)
+ {
+ byte index = -1;
+
+ if(key == settings.forwardKey.key)
+ {
+ index = 0;
+ }
+
+ if(key == settings.backKey.key)
+ {
+ index = 1;
+ }
+
+ if(key == settings.leftKey.key)
+ {
+ index = 2;
+ }
+
+ if(key == settings.rightKey.key)
+ {
+ index = 3;
+ }
+
+ if(key == settings.jumpKey.key)
+ {
+ index = 4;
+ }
+
+ if(index >= 0)
+ {
+ keyStates[index] = state;
+ }
+
+ }
+
+ private boolean[] keyStates = new boolean[10];
+ private GameSettings settings;
+}
diff --git a/src/main/java/com/mojang/minecraft/player/Inventory.java b/src/main/java/com/mojang/minecraft/player/Inventory.java
new file mode 100644
index 0000000..ad4da94
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/player/Inventory.java
@@ -0,0 +1,127 @@
+package com.mojang.minecraft.player;
+
+import com.mojang.minecraft.SessionData;
+import com.mojang.minecraft.level.tile.Block;
+import java.io.Serializable;
+
+public class Inventory implements Serializable {
+
+ public static final long serialVersionUID = 0L;
+ public static final int POP_TIME_DURATION = 5;
+ public int[] slots = new int[9];
+ public int[] count = new int[9];
+ public int[] popTime = new int[9];
+ public int selected = 0;
+
+
+ public Inventory() {
+ for(int var1 = 0; var1 < 9; ++var1) {
+ this.slots[var1] = -1;
+ this.count[var1] = 0;
+ }
+
+ }
+
+ public int getSelected() {
+ return this.slots[this.selected];
+ }
+
+ private int getSlot(int var1) {
+ for(int var2 = 0; var2 < this.slots.length; ++var2) {
+ if(var1 == this.slots[var2]) {
+ return var2;
+ }
+ }
+
+ return -1;
+ }
+
+ public void grabTexture(int var1, boolean var2) {
+ int var3;
+ if((var3 = this.getSlot(var1)) >= 0) {
+ this.selected = var3;
+ } else {
+ if(var2 && var1 > 0 && SessionData.allowedBlocks.contains(Block.blocks[var1])) {
+ this.replaceSlot(Block.blocks[var1]);
+ }
+
+ }
+ }
+
+ public void swapPaint(int var1) {
+ if(var1 > 0) {
+ var1 = 1;
+ }
+
+ if(var1 < 0) {
+ var1 = -1;
+ }
+
+ for(this.selected -= var1; this.selected < 0; this.selected += this.slots.length) {
+ ;
+ }
+
+ while(this.selected >= this.slots.length) {
+ this.selected -= this.slots.length;
+ }
+
+ }
+
+ public void replaceSlot(int var1) {
+ if(var1 >= 0) {
+ this.replaceSlot((Block)SessionData.allowedBlocks.get(var1));
+ }
+
+ }
+
+ public void replaceSlot(Block var1) {
+ if(var1 != null) {
+ int var2;
+ if((var2 = this.getSlot(var1.id)) >= 0) {
+ this.slots[var2] = this.slots[this.selected];
+ }
+
+ this.slots[this.selected] = var1.id;
+ }
+
+ }
+
+ public boolean addResource(int var1) {
+ int var2;
+ if((var2 = this.getSlot(var1)) < 0) {
+ var2 = this.getSlot(-1);
+ }
+
+ if(var2 < 0) {
+ return false;
+ } else if(this.count[var2] >= 99) {
+ return false;
+ } else {
+ this.slots[var2] = var1;
+ ++this.count[var2];
+ this.popTime[var2] = 5;
+ return true;
+ }
+ }
+
+ public void tick() {
+ for(int var1 = 0; var1 < this.popTime.length; ++var1) {
+ if(this.popTime[var1] > 0) {
+ --this.popTime[var1];
+ }
+ }
+
+ }
+
+ public boolean removeResource(int var1) {
+ if((var1 = this.getSlot(var1)) < 0) {
+ return false;
+ } else {
+ if(--this.count[var1] <= 0) {
+ this.slots[var1] = -1;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/player/Player$1.java b/src/main/java/com/mojang/minecraft/player/Player$1.java
new file mode 100644
index 0000000..e755802
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/player/Player$1.java
@@ -0,0 +1,26 @@
+package com.mojang.minecraft.player;
+
+import com.mojang.minecraft.mob.ai.BasicAI;
+import com.mojang.minecraft.player.Player;
+
+// PlayerAI
+public class Player$1 extends BasicAI
+{
+ public Player$1(Player player)
+ {
+ this.player = player;
+ }
+
+ @Override
+ protected void update()
+ {
+ this.jumping = player.input.yya;
+
+ this.xxa = player.input.xxa;
+ this.yya = player.input.jumping;
+ }
+
+ public static final long serialVersionUID = 0L;
+
+ private Player player;
+}
diff --git a/src/main/java/com/mojang/minecraft/player/Player.java b/src/main/java/com/mojang/minecraft/player/Player.java
new file mode 100644
index 0000000..8009833
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/player/Player.java
@@ -0,0 +1,162 @@
+package com.mojang.minecraft.player;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.mob.Mob;
+import com.mojang.minecraft.model.HumanoidModel;
+import com.mojang.minecraft.player.InputHandler;
+import com.mojang.minecraft.player.Inventory;
+import com.mojang.minecraft.player.Player$1;
+import com.mojang.minecraft.render.TextureManager;
+import com.mojang.util.MathHelper;
+import java.awt.image.BufferedImage;
+import java.util.List;
+import org.lwjgl.opengl.GL11;
+
+public class Player extends Mob {
+
+ public static final long serialVersionUID = 0L;
+ public static final int MAX_HEALTH = 20;
+ public static final int MAX_ARROWS = 99;
+ public transient InputHandler input;
+ public Inventory inventory = new Inventory();
+ public byte userType = 0;
+ public float oBob;
+ public float bob;
+ public int score = 0;
+ public int arrows = 20;
+ private static int newTextureId = -1;
+ public static BufferedImage newTexture;
+
+
+ public Player(Level var1) {
+ super(var1);
+ if(var1 != null) {
+ var1.player = this;
+ var1.removeEntity(this);
+ var1.addEntity(this);
+ }
+
+ this.heightOffset = 1.62F;
+ this.health = 20;
+ this.modelName = "humanoid";
+ this.rotOffs = 180.0F;
+ this.ai = new Player$1(this);
+ }
+
+ public void resetPos() {
+ this.heightOffset = 1.62F;
+ this.setSize(0.6F, 1.8F);
+ super.resetPos();
+ if(this.level != null) {
+ this.level.player = this;
+ }
+
+ this.health = 20;
+ this.deathTime = 0;
+ }
+
+ public void aiStep() {
+ this.inventory.tick();
+ this.oBob = this.bob;
+ this.input.updateMovement();
+ super.aiStep();
+ float var1 = MathHelper.sqrt(this.xd * this.xd + this.zd * this.zd);
+ float var2 = (float)Math.atan((double)(-this.yd * 0.2F)) * 15.0F;
+ if(var1 > 0.1F) {
+ var1 = 0.1F;
+ }
+
+ if(!this.onGround || this.health <= 0) {
+ var1 = 0.0F;
+ }
+
+ if(this.onGround || this.health <= 0) {
+ var2 = 0.0F;
+ }
+
+ this.bob += (var1 - this.bob) * 0.4F;
+ this.tilt += (var2 - this.tilt) * 0.8F;
+ List var3;
+ if(this.health > 0 && (var3 = this.level.findEntities(this, this.bb.grow(1.0F, 0.0F, 1.0F))) != null) {
+ for(int var4 = 0; var4 < var3.size(); ++var4) {
+ ((Entity)var3.get(var4)).playerTouch(this);
+ }
+ }
+
+ }
+
+ public void render(TextureManager var1, float var2) {}
+
+ public void releaseAllKeys() {
+ this.input.resetKeys();
+ }
+
+ public void setKey(int var1, boolean var2) {
+ this.input.setKeyState(var1, var2);
+ }
+
+ public boolean addResource(int var1) {
+ return this.inventory.addResource(var1);
+ }
+
+ public int getScore() {
+ return this.score;
+ }
+
+ public HumanoidModel getModel() {
+ return (HumanoidModel)modelCache.getModel(this.modelName);
+ }
+
+ public void die(Entity var1) {
+ this.setSize(0.2F, 0.2F);
+ this.setPos(this.x, this.y, this.z);
+ this.yd = 0.1F;
+ if(var1 != null) {
+ this.xd = -MathHelper.cos((this.hurtDir + this.yRot) * 3.1415927F / 180.0F) * 0.1F;
+ this.zd = -MathHelper.sin((this.hurtDir + this.yRot) * 3.1415927F / 180.0F) * 0.1F;
+ } else {
+ this.xd = this.zd = 0.0F;
+ }
+
+ this.heightOffset = 0.1F;
+ }
+
+ public void remove() {}
+
+ public void awardKillScore(Entity var1, int var2) {
+ this.score += var2;
+ }
+
+ public boolean isShootable() {
+ return true;
+ }
+
+ public void bindTexture(TextureManager var1) {
+ if(newTexture != null) {
+ newTextureId = var1.load(newTexture);
+ newTexture = null;
+ }
+
+ int var2;
+ if(newTextureId < 0) {
+ var2 = var1.load("/char.png");
+ GL11.glBindTexture(3553, var2);
+ } else {
+ var2 = newTextureId;
+ GL11.glBindTexture(3553, var2);
+ }
+ }
+
+ public void hurt(Entity var1, int var2) {
+ if(!this.level.creativeMode) {
+ super.hurt(var1, var2);
+ }
+
+ }
+
+ public boolean isCreativeModeAllowed() {
+ return true;
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/render/Chunk.java b/src/main/java/com/mojang/minecraft/render/Chunk.java
new file mode 100644
index 0000000..10d95cd
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/Chunk.java
@@ -0,0 +1,123 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.Frustrum;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.util.MathHelper;
+import org.lwjgl.opengl.GL11;
+
+public final class Chunk {
+
+ private Level level;
+ private int baseListId = -1;
+ private static ShapeRenderer renderer = ShapeRenderer.instance;
+ public static int chunkUpdates = 0;
+ private int x;
+ private int y;
+ private int z;
+ private int width;
+ private int height;
+ private int depth;
+ public boolean visible = false;
+ private boolean[] dirty = new boolean[2];
+ public boolean loaded;
+
+
+ public Chunk(Level var1, int var2, int var3, int var4, int var5, int var6) {
+ this.level = var1;
+ this.x = var2;
+ this.y = var3;
+ this.z = var4;
+ this.width = this.height = this.depth = 16;
+ MathHelper.sqrt((float)(this.width * this.width + this.height * this.height + this.depth * this.depth));
+ this.baseListId = var6;
+ this.setAllDirty();
+ }
+
+ public final void update() {
+ ++chunkUpdates;
+ int var1 = this.x;
+ int var2 = this.y;
+ int var3 = this.z;
+ int var4 = this.x + this.width;
+ int var5 = this.y + this.height;
+ int var6 = this.z + this.depth;
+
+ int var7;
+ for(var7 = 0; var7 < 2; ++var7) {
+ this.dirty[var7] = true;
+ }
+
+ for(var7 = 0; var7 < 2; ++var7) {
+ boolean var8 = false;
+ boolean var9 = false;
+ GL11.glNewList(this.baseListId + var7, 4864);
+ renderer.begin();
+
+ for(int var10 = var1; var10 < var4; ++var10) {
+ for(int var11 = var2; var11 < var5; ++var11) {
+ for(int var12 = var3; var12 < var6; ++var12) {
+ int var13;
+ if((var13 = this.level.getTile(var10, var11, var12)) > 0) {
+ Block var14;
+ if((var14 = Block.blocks[var13]).getRenderPass() != var7) {
+ var8 = true;
+ } else {
+ var9 |= var14.render(this.level, var10, var11, var12, renderer);
+ }
+ }
+ }
+ }
+ }
+
+ renderer.end();
+ GL11.glEndList();
+ if(var9) {
+ this.dirty[var7] = false;
+ }
+
+ if(!var8) {
+ break;
+ }
+ }
+
+ }
+
+ public final float distanceSquared(Player var1) {
+ float var2 = var1.x - (float)this.x;
+ float var3 = var1.y - (float)this.y;
+ float var4 = var1.z - (float)this.z;
+ return var2 * var2 + var3 * var3 + var4 * var4;
+ }
+
+ private void setAllDirty() {
+ for(int var1 = 0; var1 < 2; ++var1) {
+ this.dirty[var1] = true;
+ }
+
+ }
+
+ public final void dispose() {
+ this.setAllDirty();
+ this.level = null;
+ }
+
+ public final int appendLists(int[] var1, int var2, int var3) {
+ if(!this.visible) {
+ return var2;
+ } else {
+ if(!this.dirty[var3]) {
+ var1[var2++] = this.baseListId + var3;
+ }
+
+ return var2;
+ }
+ }
+
+ public final void clip(Frustrum var1) {
+ this.visible = var1.isBoxInFrustrum((float)this.x, (float)this.y, (float)this.z, (float)(this.x + this.width), (float)(this.y + this.height), (float)(this.z + this.depth));
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/render/ChunkDirtyDistanceComparator.java b/src/main/java/com/mojang/minecraft/render/ChunkDirtyDistanceComparator.java
new file mode 100644
index 0000000..9454f0b
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/ChunkDirtyDistanceComparator.java
@@ -0,0 +1,43 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.player.Player;
+import java.util.Comparator;
+
+public class ChunkDirtyDistanceComparator implements Comparator
+{
+ public ChunkDirtyDistanceComparator(Player player)
+ {
+ this.player = player;
+ }
+
+ @Override
+ public int compare(Object o1, Object o2)
+ {
+ Chunk chunk = (Chunk)o1;
+ Chunk other = (Chunk)o2;
+
+ if(chunk.visible || !other.visible)
+ {
+ if(other.visible)
+ {
+ float sqDist = chunk.distanceSquared(player);
+ float otherSqDist = other.distanceSquared(player);
+
+ if(sqDist == otherSqDist)
+ {
+ return 0;
+ } else if(sqDist > otherSqDist) {
+ return -1;
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+
+ private Player player;
+}
diff --git a/src/main/java/com/mojang/minecraft/render/ChunkDistanceComparator.java b/src/main/java/com/mojang/minecraft/render/ChunkDistanceComparator.java
new file mode 100644
index 0000000..99cd287
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/ChunkDistanceComparator.java
@@ -0,0 +1,33 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.player.Player;
+import java.util.Comparator;
+
+public class ChunkDistanceComparator implements Comparator
+{
+ public ChunkDistanceComparator(Player player)
+ {
+ this.player = player;
+ }
+
+ @Override
+ public int compare(Object o1, Object o2)
+ {
+ Chunk chunk = (Chunk)o1;
+ Chunk other = (Chunk)o2;
+
+ float sqDist = chunk.distanceSquared(player);
+ float otherSqDist = other.distanceSquared(player);
+
+ if(sqDist == otherSqDist)
+ {
+ return 0;
+ } else if(sqDist > otherSqDist) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ private Player player;
+}
diff --git a/src/main/java/com/mojang/minecraft/render/Frustrum.java b/src/main/java/com/mojang/minecraft/render/Frustrum.java
new file mode 100644
index 0000000..a3823d4
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/Frustrum.java
@@ -0,0 +1,21 @@
+package com.mojang.minecraft.render;
+
+
+public class Frustrum {
+
+ public float[][] frustrum = new float[16][16];
+ public float[] projection = new float[16];
+ public float[] modelview = new float[16];
+ public float[] clipping = new float[16];
+
+
+ public final boolean isBoxInFrustrum(float var1, float var2, float var3, float var4, float var5, float var6) {
+ for(int var7 = 0; var7 < 6; ++var7) {
+ if(this.frustrum[var7][0] * var1 + this.frustrum[var7][1] * var2 + this.frustrum[var7][2] * var3 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var4 + this.frustrum[var7][1] * var2 + this.frustrum[var7][2] * var3 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var1 + this.frustrum[var7][1] * var5 + this.frustrum[var7][2] * var3 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var4 + this.frustrum[var7][1] * var5 + this.frustrum[var7][2] * var3 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var1 + this.frustrum[var7][1] * var2 + this.frustrum[var7][2] * var6 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var4 + this.frustrum[var7][1] * var2 + this.frustrum[var7][2] * var6 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var1 + this.frustrum[var7][1] * var5 + this.frustrum[var7][2] * var6 + this.frustrum[var7][3] <= 0.0F && this.frustrum[var7][0] * var4 + this.frustrum[var7][1] * var5 + this.frustrum[var7][2] * var6 + this.frustrum[var7][3] <= 0.0F) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/render/FrustrumImpl.java b/src/main/java/com/mojang/minecraft/render/FrustrumImpl.java
new file mode 100644
index 0000000..05d18e9
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/FrustrumImpl.java
@@ -0,0 +1,85 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.render.Frustrum;
+import com.mojang.util.MathHelper;
+import java.nio.FloatBuffer;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+public final class FrustrumImpl extends Frustrum {
+
+ private static FrustrumImpl instance = new FrustrumImpl();
+ private FloatBuffer projectionBuff = BufferUtils.createFloatBuffer(16);
+ private FloatBuffer modelviewBuff = BufferUtils.createFloatBuffer(16);
+ private FloatBuffer unused = BufferUtils.createFloatBuffer(16);
+
+
+ public static Frustrum update() {
+ FrustrumImpl var0 = instance;
+ instance.projectionBuff.clear();
+ var0.modelviewBuff.clear();
+ var0.unused.clear();
+ GL11.glGetFloat(2983, var0.projectionBuff);
+ GL11.glGetFloat(2982, var0.modelviewBuff);
+ var0.projectionBuff.flip().limit(16);
+ var0.projectionBuff.get(var0.projection);
+ var0.modelviewBuff.flip().limit(16);
+ var0.modelviewBuff.get(var0.modelview);
+ var0.clipping[0] = var0.modelview[0] * var0.projection[0] + var0.modelview[1] * var0.projection[4] + var0.modelview[2] * var0.projection[8] + var0.modelview[3] * var0.projection[12];
+ var0.clipping[1] = var0.modelview[0] * var0.projection[1] + var0.modelview[1] * var0.projection[5] + var0.modelview[2] * var0.projection[9] + var0.modelview[3] * var0.projection[13];
+ var0.clipping[2] = var0.modelview[0] * var0.projection[2] + var0.modelview[1] * var0.projection[6] + var0.modelview[2] * var0.projection[10] + var0.modelview[3] * var0.projection[14];
+ var0.clipping[3] = var0.modelview[0] * var0.projection[3] + var0.modelview[1] * var0.projection[7] + var0.modelview[2] * var0.projection[11] + var0.modelview[3] * var0.projection[15];
+ var0.clipping[4] = var0.modelview[4] * var0.projection[0] + var0.modelview[5] * var0.projection[4] + var0.modelview[6] * var0.projection[8] + var0.modelview[7] * var0.projection[12];
+ var0.clipping[5] = var0.modelview[4] * var0.projection[1] + var0.modelview[5] * var0.projection[5] + var0.modelview[6] * var0.projection[9] + var0.modelview[7] * var0.projection[13];
+ var0.clipping[6] = var0.modelview[4] * var0.projection[2] + var0.modelview[5] * var0.projection[6] + var0.modelview[6] * var0.projection[10] + var0.modelview[7] * var0.projection[14];
+ var0.clipping[7] = var0.modelview[4] * var0.projection[3] + var0.modelview[5] * var0.projection[7] + var0.modelview[6] * var0.projection[11] + var0.modelview[7] * var0.projection[15];
+ var0.clipping[8] = var0.modelview[8] * var0.projection[0] + var0.modelview[9] * var0.projection[4] + var0.modelview[10] * var0.projection[8] + var0.modelview[11] * var0.projection[12];
+ var0.clipping[9] = var0.modelview[8] * var0.projection[1] + var0.modelview[9] * var0.projection[5] + var0.modelview[10] * var0.projection[9] + var0.modelview[11] * var0.projection[13];
+ var0.clipping[10] = var0.modelview[8] * var0.projection[2] + var0.modelview[9] * var0.projection[6] + var0.modelview[10] * var0.projection[10] + var0.modelview[11] * var0.projection[14];
+ var0.clipping[11] = var0.modelview[8] * var0.projection[3] + var0.modelview[9] * var0.projection[7] + var0.modelview[10] * var0.projection[11] + var0.modelview[11] * var0.projection[15];
+ var0.clipping[12] = var0.modelview[12] * var0.projection[0] + var0.modelview[13] * var0.projection[4] + var0.modelview[14] * var0.projection[8] + var0.modelview[15] * var0.projection[12];
+ var0.clipping[13] = var0.modelview[12] * var0.projection[1] + var0.modelview[13] * var0.projection[5] + var0.modelview[14] * var0.projection[9] + var0.modelview[15] * var0.projection[13];
+ var0.clipping[14] = var0.modelview[12] * var0.projection[2] + var0.modelview[13] * var0.projection[6] + var0.modelview[14] * var0.projection[10] + var0.modelview[15] * var0.projection[14];
+ var0.clipping[15] = var0.modelview[12] * var0.projection[3] + var0.modelview[13] * var0.projection[7] + var0.modelview[14] * var0.projection[11] + var0.modelview[15] * var0.projection[15];
+ var0.frustrum[0][0] = var0.clipping[3] - var0.clipping[0];
+ var0.frustrum[0][1] = var0.clipping[7] - var0.clipping[4];
+ var0.frustrum[0][2] = var0.clipping[11] - var0.clipping[8];
+ var0.frustrum[0][3] = var0.clipping[15] - var0.clipping[12];
+ normalize(var0.frustrum, 0);
+ var0.frustrum[1][0] = var0.clipping[3] + var0.clipping[0];
+ var0.frustrum[1][1] = var0.clipping[7] + var0.clipping[4];
+ var0.frustrum[1][2] = var0.clipping[11] + var0.clipping[8];
+ var0.frustrum[1][3] = var0.clipping[15] + var0.clipping[12];
+ normalize(var0.frustrum, 1);
+ var0.frustrum[2][0] = var0.clipping[3] + var0.clipping[1];
+ var0.frustrum[2][1] = var0.clipping[7] + var0.clipping[5];
+ var0.frustrum[2][2] = var0.clipping[11] + var0.clipping[9];
+ var0.frustrum[2][3] = var0.clipping[15] + var0.clipping[13];
+ normalize(var0.frustrum, 2);
+ var0.frustrum[3][0] = var0.clipping[3] - var0.clipping[1];
+ var0.frustrum[3][1] = var0.clipping[7] - var0.clipping[5];
+ var0.frustrum[3][2] = var0.clipping[11] - var0.clipping[9];
+ var0.frustrum[3][3] = var0.clipping[15] - var0.clipping[13];
+ normalize(var0.frustrum, 3);
+ var0.frustrum[4][0] = var0.clipping[3] - var0.clipping[2];
+ var0.frustrum[4][1] = var0.clipping[7] - var0.clipping[6];
+ var0.frustrum[4][2] = var0.clipping[11] - var0.clipping[10];
+ var0.frustrum[4][3] = var0.clipping[15] - var0.clipping[14];
+ normalize(var0.frustrum, 4);
+ var0.frustrum[5][0] = var0.clipping[3] + var0.clipping[2];
+ var0.frustrum[5][1] = var0.clipping[7] + var0.clipping[6];
+ var0.frustrum[5][2] = var0.clipping[11] + var0.clipping[10];
+ var0.frustrum[5][3] = var0.clipping[15] + var0.clipping[14];
+ normalize(var0.frustrum, 5);
+ return instance;
+ }
+
+ private static void normalize(float[][] var0, int var1) {
+ float var2 = MathHelper.sqrt(var0[var1][0] * var0[var1][0] + var0[var1][1] * var0[var1][1] + var0[var1][2] * var0[var1][2]);
+ var0[var1][0] /= var2;
+ var0[var1][1] /= var2;
+ var0[var1][2] /= var2;
+ var0[var1][3] /= var2;
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/render/HeldBlock.java b/src/main/java/com/mojang/minecraft/render/HeldBlock.java
new file mode 100644
index 0000000..541cd46
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/HeldBlock.java
@@ -0,0 +1,23 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.tile.Block;
+
+public class HeldBlock
+{
+ public HeldBlock(Minecraft minecraft)
+ {
+ this.minecraft = minecraft;
+ }
+
+ public Minecraft minecraft;
+
+ public Block block = null;
+
+ public float pos = 0.0F;
+ public float lastPos = 0.0F;
+
+ public int offset = 0;
+
+ public boolean moving = false;
+}
diff --git a/src/main/java/com/mojang/minecraft/render/LevelRenderer.java b/src/main/java/com/mojang/minecraft/render/LevelRenderer.java
new file mode 100644
index 0000000..cd62d11
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/LevelRenderer.java
@@ -0,0 +1,266 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.Chunk;
+import com.mojang.minecraft.render.ChunkDistanceComparator;
+import com.mojang.minecraft.render.ShapeRenderer;
+import com.mojang.minecraft.render.TextureManager;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+public final class LevelRenderer {
+
+ public Level level;
+ public TextureManager textureManager;
+ public int listId;
+ public IntBuffer buffer = BufferUtils.createIntBuffer(65536);
+ public IntBuffer buffer_fast = BufferUtils.createIntBuffer(4096);
+ public List chunks = new ArrayList();
+ private Chunk[] loadQueue;
+ public Chunk[] chunkCache;
+ private int xChunks;
+ private int yChunks;
+ private int zChunks;
+ private int baseListId;
+ public Minecraft minecraft;
+ private int[] chunkDataCache = new int['\uc350'];
+ public int ticks = 0;
+ private float lastLoadX = -9999.0F;
+ private float lastLoadY = -9999.0F;
+ private float lastLoadZ = -9999.0F;
+ public float cracks;
+
+
+ public LevelRenderer(Minecraft var1, TextureManager var2) {
+ this.minecraft = var1;
+ this.textureManager = var2;
+ this.listId = GL11.glGenLists(2);
+ this.baseListId = GL11.glGenLists(4096 << 6 << 1);
+ }
+
+ public final void refresh() {
+ int var1;
+ if(this.chunkCache != null) {
+ for(var1 = 0; var1 < this.chunkCache.length; ++var1) {
+ this.chunkCache[var1].dispose();
+ }
+ }
+
+ this.xChunks = this.level.width / 16;
+ this.yChunks = this.level.depth / 16;
+ this.zChunks = this.level.height / 16;
+ this.chunkCache = new Chunk[this.xChunks * this.yChunks * this.zChunks];
+ this.loadQueue = new Chunk[this.xChunks * this.yChunks * this.zChunks];
+ var1 = 0;
+
+ int var2;
+ int var4;
+ for(var2 = 0; var2 < this.xChunks; ++var2) {
+ for(int var3 = 0; var3 < this.yChunks; ++var3) {
+ for(var4 = 0; var4 < this.zChunks; ++var4) {
+ this.chunkCache[(var4 * this.yChunks + var3) * this.xChunks + var2] = new Chunk(this.level, var2 << 4, var3 << 4, var4 << 4, 16, this.baseListId + var1);
+ this.loadQueue[(var4 * this.yChunks + var3) * this.xChunks + var2] = this.chunkCache[(var4 * this.yChunks + var3) * this.xChunks + var2];
+ var1 += 2;
+ }
+ }
+ }
+
+ for(var2 = 0; var2 < this.chunks.size(); ++var2) {
+ ((Chunk)this.chunks.get(var2)).loaded = false;
+ }
+
+ this.chunks.clear();
+ GL11.glNewList(this.listId, 4864);
+ LevelRenderer var9 = this;
+ float var10 = 0.5F;
+ GL11.glColor4f(0.5F, var10, var10, 1.0F);
+ ShapeRenderer var11 = ShapeRenderer.instance;
+ float var12 = this.level.getGroundLevel();
+ int var5 = 128;
+ if(128 > this.level.width) {
+ var5 = this.level.width;
+ }
+
+ if(var5 > this.level.height) {
+ var5 = this.level.height;
+ }
+
+ int var6 = 2048 / var5;
+ var11.begin();
+
+ int var7;
+ for(var7 = -var5 * var6; var7 < var9.level.width + var5 * var6; var7 += var5) {
+ for(int var8 = -var5 * var6; var8 < var9.level.height + var5 * var6; var8 += var5) {
+ var10 = var12;
+ if(var7 >= 0 && var8 >= 0 && var7 < var9.level.width && var8 < var9.level.height) {
+ var10 = 0.0F;
+ }
+
+ var11.vertexUV((float)var7, var10, (float)(var8 + var5), 0.0F, (float)var5);
+ var11.vertexUV((float)(var7 + var5), var10, (float)(var8 + var5), (float)var5, (float)var5);
+ var11.vertexUV((float)(var7 + var5), var10, (float)var8, (float)var5, 0.0F);
+ var11.vertexUV((float)var7, var10, (float)var8, 0.0F, 0.0F);
+ }
+ }
+
+ var11.end();
+ GL11.glColor3f(0.8F, 0.8F, 0.8F);
+ var11.begin();
+
+ for(var7 = 0; var7 < var9.level.width; var7 += var5) {
+ var11.vertexUV((float)var7, 0.0F, 0.0F, 0.0F, 0.0F);
+ var11.vertexUV((float)(var7 + var5), 0.0F, 0.0F, (float)var5, 0.0F);
+ var11.vertexUV((float)(var7 + var5), var12, 0.0F, (float)var5, var12);
+ var11.vertexUV((float)var7, var12, 0.0F, 0.0F, var12);
+ var11.vertexUV((float)var7, var12, (float)var9.level.height, 0.0F, var12);
+ var11.vertexUV((float)(var7 + var5), var12, (float)var9.level.height, (float)var5, var12);
+ var11.vertexUV((float)(var7 + var5), 0.0F, (float)var9.level.height, (float)var5, 0.0F);
+ var11.vertexUV((float)var7, 0.0F, (float)var9.level.height, 0.0F, 0.0F);
+ }
+
+ GL11.glColor3f(0.6F, 0.6F, 0.6F);
+
+ for(var7 = 0; var7 < var9.level.height; var7 += var5) {
+ var11.vertexUV(0.0F, var12, (float)var7, 0.0F, 0.0F);
+ var11.vertexUV(0.0F, var12, (float)(var7 + var5), (float)var5, 0.0F);
+ var11.vertexUV(0.0F, 0.0F, (float)(var7 + var5), (float)var5, var12);
+ var11.vertexUV(0.0F, 0.0F, (float)var7, 0.0F, var12);
+ var11.vertexUV((float)var9.level.width, 0.0F, (float)var7, 0.0F, var12);
+ var11.vertexUV((float)var9.level.width, 0.0F, (float)(var7 + var5), (float)var5, var12);
+ var11.vertexUV((float)var9.level.width, var12, (float)(var7 + var5), (float)var5, 0.0F);
+ var11.vertexUV((float)var9.level.width, var12, (float)var7, 0.0F, 0.0F);
+ }
+
+ var11.end();
+ GL11.glEndList();
+ GL11.glNewList(this.listId + 1, 4864);
+ var9 = this;
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+ var10 = this.level.getWaterLevel();
+ GL11.glBlendFunc(770, 771);
+ var11 = ShapeRenderer.instance;
+ var4 = 128;
+ if(128 > this.level.width) {
+ var4 = this.level.width;
+ }
+
+ if(var4 > this.level.height) {
+ var4 = this.level.height;
+ }
+
+ var5 = 2048 / var4;
+ var11.begin();
+
+ for(var6 = -var4 * var5; var6 < var9.level.width + var4 * var5; var6 += var4) {
+ for(var7 = -var4 * var5; var7 < var9.level.height + var4 * var5; var7 += var4) {
+ float var13 = var10 - 0.1F;
+ if(var6 < 0 || var7 < 0 || var6 >= var9.level.width || var7 >= var9.level.height) {
+ var11.vertexUV((float)var6, var13, (float)(var7 + var4), 0.0F, (float)var4);
+ var11.vertexUV((float)(var6 + var4), var13, (float)(var7 + var4), (float)var4, (float)var4);
+ var11.vertexUV((float)(var6 + var4), var13, (float)var7, (float)var4, 0.0F);
+ var11.vertexUV((float)var6, var13, (float)var7, 0.0F, 0.0F);
+ var11.vertexUV((float)var6, var13, (float)var7, 0.0F, 0.0F);
+ var11.vertexUV((float)(var6 + var4), var13, (float)var7, (float)var4, 0.0F);
+ var11.vertexUV((float)(var6 + var4), var13, (float)(var7 + var4), (float)var4, (float)var4);
+ var11.vertexUV((float)var6, var13, (float)(var7 + var4), 0.0F, (float)var4);
+ }
+ }
+ }
+
+ var11.end();
+ GL11.glDisable(3042);
+ GL11.glEndList();
+ this.queueChunks(0, 0, 0, this.level.width, this.level.depth, this.level.height);
+ }
+
+ public final int sortChunks(Player var1, int var2) {
+ float var3 = var1.x - this.lastLoadX;
+ float var4 = var1.y - this.lastLoadY;
+ float var5 = var1.z - this.lastLoadZ;
+ if(var3 * var3 + var4 * var4 + var5 * var5 > 64.0F) {
+ this.lastLoadX = var1.x;
+ this.lastLoadY = var1.y;
+ this.lastLoadZ = var1.z;
+ Arrays.sort(this.loadQueue, new ChunkDistanceComparator(var1));
+ }
+
+ int var6 = 0;
+
+ for(int var7 = 0; var7 < this.loadQueue.length; ++var7) {
+ var6 = this.loadQueue[var7].appendLists(this.chunkDataCache, var6, var2);
+ }
+
+ if(!Minecraft.settings.ofFastMath) {
+ this.buffer.clear();
+ this.buffer.put(this.chunkDataCache, 0, var6);
+ this.buffer.flip();
+ if(this.buffer.remaining() > 0) {
+ GL11.glBindTexture(3553, this.textureManager.load("/terrain.png"));
+ GL11.glCallLists(this.buffer);
+ }
+
+ return this.buffer.remaining();
+ } else {
+ this.buffer_fast.clear();
+ this.buffer_fast.put(this.chunkDataCache, 0, var6);
+ this.buffer_fast.flip();
+ if(this.buffer_fast.remaining() > 0) {
+ GL11.glBindTexture(3553, this.textureManager.load("/terrain.png"));
+ GL11.glCallLists(this.buffer_fast);
+ }
+
+ return this.buffer_fast.remaining();
+ }
+ }
+
+ public final void queueChunks(int var1, int var2, int var3, int var4, int var5, int var6) {
+ var1 /= 16;
+ var2 /= 16;
+ var3 /= 16;
+ var4 /= 16;
+ var5 /= 16;
+ var6 /= 16;
+ if(var1 < 0) {
+ var1 = 0;
+ }
+
+ if(var2 < 0) {
+ var2 = 0;
+ }
+
+ if(var3 < 0) {
+ var3 = 0;
+ }
+
+ if(var4 > this.xChunks - 1) {
+ var4 = this.xChunks - 1;
+ }
+
+ if(var5 > this.yChunks - 1) {
+ var5 = this.yChunks - 1;
+ }
+
+ if(var6 > this.zChunks - 1) {
+ var6 = this.zChunks - 1;
+ }
+
+ for(var1 = var1; var1 <= var4; ++var1) {
+ for(int var7 = var2; var7 <= var5; ++var7) {
+ for(int var8 = var3; var8 <= var6; ++var8) {
+ Chunk var9;
+ if(!(var9 = this.chunkCache[(var8 * this.yChunks + var7) * this.xChunks + var1]).loaded) {
+ var9.loaded = true;
+ this.chunks.add(this.chunkCache[(var8 * this.yChunks + var7) * this.xChunks + var1]);
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/render/Renderer.java b/src/main/java/com/mojang/minecraft/render/Renderer.java
new file mode 100644
index 0000000..023070a
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/Renderer.java
@@ -0,0 +1,170 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.minecraft.Minecraft;
+import com.mojang.minecraft.level.Level;
+import com.mojang.minecraft.level.liquid.LiquidType;
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.model.Vec3D;
+import com.mojang.minecraft.player.Player;
+import com.mojang.minecraft.render.HeldBlock;
+import com.mojang.util.MathHelper;
+import java.nio.FloatBuffer;
+import java.util.Random;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+public final class Renderer {
+
+ public Minecraft minecraft;
+ public float fogColorMultiplier = 1.0F;
+ public boolean displayActive = false;
+ public float fogEnd = 0.0F;
+ public HeldBlock heldBlock;
+ public int levelTicks;
+ public Entity entity = null;
+ public Random random = new Random();
+ private volatile int unused1 = 0;
+ private volatile int unused2 = 0;
+ private FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
+ public float fogRed;
+ public float fogBlue;
+ public float fogGreen;
+
+
+ public Renderer(Minecraft var1) {
+ this.minecraft = var1;
+ this.heldBlock = new HeldBlock(var1);
+ }
+
+ public Vec3D getPlayerVector(float var1) {
+ Player var4;
+ float var2 = (var4 = this.minecraft.player).xo + (var4.x - var4.xo) * var1;
+ float var3 = var4.yo + (var4.y - var4.yo) * var1;
+ float var5 = var4.zo + (var4.z - var4.zo) * var1;
+ return new Vec3D(var2, var3, var5);
+ }
+
+ public void hurtEffect(float var1) {
+ Player var3;
+ float var2 = (float)(var3 = this.minecraft.player).hurtTime - var1;
+ if(var3.health <= 0) {
+ var1 += (float)var3.deathTime;
+ GL11.glRotatef(40.0F - 8000.0F / (var1 + 200.0F), 0.0F, 0.0F, 1.0F);
+ }
+
+ if(var2 >= 0.0F) {
+ var2 = MathHelper.sin((var2 /= (float)var3.hurtDuration) * var2 * var2 * var2 * 3.1415927F);
+ var1 = var3.hurtDir;
+ GL11.glRotatef(-var3.hurtDir, 0.0F, 1.0F, 0.0F);
+ GL11.glRotatef(-var2 * 14.0F, 0.0F, 0.0F, 1.0F);
+ GL11.glRotatef(var1, 0.0F, 1.0F, 0.0F);
+ }
+ }
+
+ public void applyBobbing(float var1) {
+ Player var4;
+ float var2 = (var4 = this.minecraft.player).walkDist - var4.walkDistO;
+ var2 = var4.walkDist + var2 * var1;
+ float var3 = var4.oBob + (var4.bob - var4.oBob) * var1;
+ float var5 = var4.oTilt + (var4.tilt - var4.oTilt) * var1;
+ GL11.glTranslatef(MathHelper.sin(var2 * 3.1415927F) * var3 * 0.5F, -Math.abs(MathHelper.cos(var2 * 3.1415927F) * var3), 0.0F);
+ GL11.glRotatef(MathHelper.sin(var2 * 3.1415927F) * var3 * 3.0F, 0.0F, 0.0F, 1.0F);
+ GL11.glRotatef(Math.abs(MathHelper.cos(var2 * 3.1415927F + 0.2F) * var3) * 5.0F, 1.0F, 0.0F, 0.0F);
+ GL11.glRotatef(var5, 1.0F, 0.0F, 0.0F);
+ }
+
+ public final void setLighting(boolean var1) {
+ if(!var1) {
+ GL11.glDisable(2896);
+ GL11.glDisable(16384);
+ } else {
+ GL11.glEnable(2896);
+ GL11.glEnable(16384);
+ GL11.glEnable(2903);
+ GL11.glColorMaterial(1032, 5634);
+ float var4 = 0.7F;
+ float var2 = 0.3F;
+ Vec3D var3 = (new Vec3D(0.0F, -1.0F, 0.5F)).normalize();
+ GL11.glLight(16384, 4611, this.createBuffer(var3.x, var3.y, var3.z, 0.0F));
+ GL11.glLight(16384, 4609, this.createBuffer(var2, var2, var2, 1.0F));
+ GL11.glLight(16384, 4608, this.createBuffer(0.0F, 0.0F, 0.0F, 1.0F));
+ GL11.glLightModel(2899, this.createBuffer(var4, var4, var4, 1.0F));
+ }
+ }
+
+ public final void enableGuiMode() {
+ int var1 = this.minecraft.width * 240 / this.minecraft.height;
+ int var2 = this.minecraft.height * 240 / this.minecraft.height;
+ GL11.glClear(256);
+ GL11.glMatrixMode(5889);
+ GL11.glLoadIdentity();
+ GL11.glOrtho(0.0D, (double)var1, (double)var2, 0.0D, 100.0D, 300.0D);
+ GL11.glMatrixMode(5888);
+ GL11.glLoadIdentity();
+ GL11.glTranslatef(0.0F, 0.0F, -200.0F);
+ }
+
+ public void updateFog() {
+ Level var1 = this.minecraft.level;
+ Player var2 = this.minecraft.player;
+ GL11.glFog(2918, this.createBuffer(this.fogRed, this.fogBlue, this.fogGreen, 1.0F));
+ GL11.glNormal3f(0.0F, -1.0F, 0.0F);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ Block var5;
+ if((var5 = Block.blocks[var1.getTile((int)var2.x, (int)(var2.y + 0.12F), (int)var2.z)]) != null && var5.getLiquidType() != LiquidType.NOT_LIQUID) {
+ LiquidType var6 = var5.getLiquidType();
+ GL11.glFogi(2917, 2048);
+ float var3;
+ float var4;
+ float var7;
+ float var8;
+ if(var6 == LiquidType.WATER) {
+ GL11.glFogf(2914, 0.1F);
+ var7 = 0.4F;
+ var8 = 0.4F;
+ var3 = 0.9F;
+ if(this.minecraft.settings.anaglyph) {
+ var4 = (var7 * 30.0F + var8 * 59.0F + var3 * 11.0F) / 100.0F;
+ var8 = (var7 * 30.0F + var8 * 70.0F) / 100.0F;
+ var3 = (var7 * 30.0F + var3 * 70.0F) / 100.0F;
+ var7 = var4;
+ var8 = var8;
+ var3 = var3;
+ }
+
+ GL11.glLightModel(2899, this.createBuffer(var7, var8, var3, 1.0F));
+ } else if(var6 == LiquidType.LAVA) {
+ GL11.glFogf(2914, 2.0F);
+ var7 = 0.4F;
+ var8 = 0.3F;
+ var3 = 0.3F;
+ if(this.minecraft.settings.anaglyph) {
+ var4 = (var7 * 30.0F + var8 * 59.0F + var3 * 11.0F) / 100.0F;
+ var8 = (var7 * 30.0F + var8 * 70.0F) / 100.0F;
+ var3 = (var7 * 30.0F + var3 * 70.0F) / 100.0F;
+ var7 = var4;
+ var8 = var8;
+ var3 = var3;
+ }
+
+ GL11.glLightModel(2899, this.createBuffer(var7, var8, var3, 1.0F));
+ }
+ } else {
+ GL11.glFogi(2917, 9729);
+ GL11.glFogf(2915, 0.0F);
+ GL11.glFogf(2916, this.fogEnd);
+ GL11.glLightModel(2899, this.createBuffer(1.0F, 1.0F, 1.0F, 1.0F));
+ }
+
+ GL11.glEnable(2903);
+ GL11.glColorMaterial(1028, 4608);
+ }
+
+ private FloatBuffer createBuffer(float var1, float var2, float var3, float var4) {
+ this.buffer.clear();
+ this.buffer.put(var1).put(var2).put(var3).put(var4);
+ this.buffer.flip();
+ return this.buffer;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/render/ShapeRenderer.java b/src/main/java/com/mojang/minecraft/render/ShapeRenderer.java
new file mode 100644
index 0000000..1a484dc
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/ShapeRenderer.java
@@ -0,0 +1,157 @@
+package com.mojang.minecraft.render;
+
+import java.nio.FloatBuffer;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+public final class ShapeRenderer {
+
+ private FloatBuffer buffer = BufferUtils.createFloatBuffer(524288);
+ private float[] data = new float[524288];
+ private int vertices = 0;
+ private float u;
+ private float v;
+ private float r;
+ private float g;
+ private float b;
+ private boolean color = false;
+ private boolean texture = false;
+ private int vertexLength = 3;
+ private int length = 0;
+ private boolean noColor = false;
+ public static ShapeRenderer instance = new ShapeRenderer();
+
+
+ public final void end() {
+ if(this.vertices > 0) {
+ this.buffer.clear();
+ this.buffer.put(this.data, 0, this.length);
+ this.buffer.flip();
+ if(this.texture && this.color) {
+ GL11.glInterleavedArrays(10794, 0, this.buffer);
+ } else if(this.texture) {
+ GL11.glInterleavedArrays(10791, 0, this.buffer);
+ } else if(this.color) {
+ GL11.glInterleavedArrays(10788, 0, this.buffer);
+ } else {
+ GL11.glInterleavedArrays(10785, 0, this.buffer);
+ }
+
+ GL11.glEnableClientState('\u8074');
+ if(this.texture) {
+ GL11.glEnableClientState('\u8078');
+ }
+
+ if(this.color) {
+ GL11.glEnableClientState('\u8076');
+ }
+
+ GL11.glDrawArrays(7, 0, this.vertices);
+ GL11.glDisableClientState('\u8074');
+ if(this.texture) {
+ GL11.glDisableClientState('\u8078');
+ }
+
+ if(this.color) {
+ GL11.glDisableClientState('\u8076');
+ }
+ }
+
+ this.clear();
+ }
+
+ private void clear() {
+ this.vertices = 0;
+ this.buffer.clear();
+ this.length = 0;
+ }
+
+ public final void begin() {
+ this.clear();
+ this.color = false;
+ this.texture = false;
+ this.noColor = false;
+ }
+
+ public final void color(float var1, float var2, float var3) {
+ if(!this.noColor) {
+ if(!this.color) {
+ this.vertexLength += 3;
+ }
+
+ this.color = true;
+ this.r = var1;
+ this.g = var2;
+ this.b = var3;
+ }
+ }
+
+ public final void vertexUV(float var1, float var2, float var3, float var4, float var5) {
+ if(!this.texture) {
+ this.vertexLength += 2;
+ }
+
+ this.texture = true;
+ this.u = var4;
+ this.v = var5;
+ this.vertex(var1, var2, var3);
+ }
+
+ public final void vertex(float var1, float var2, float var3) {
+ if(this.texture) {
+ this.data[this.length++] = this.u;
+ this.data[this.length++] = this.v;
+ }
+
+ if(this.color) {
+ this.data[this.length++] = this.r;
+ this.data[this.length++] = this.g;
+ this.data[this.length++] = this.b;
+ }
+
+ this.data[this.length++] = var1;
+ this.data[this.length++] = var2;
+ this.data[this.length++] = var3;
+ ++this.vertices;
+ if(this.vertices % 4 == 0 && this.length >= 524288 - (this.vertexLength << 2)) {
+ this.end();
+ }
+
+ }
+
+ public final void color(int var1) {
+ int var2 = var1 >> 16 & 255;
+ int var3 = var1 >> 8 & 255;
+ var1 &= 255;
+ int var10001 = var2;
+ int var10002 = var3;
+ var3 = var1;
+ var2 = var10002;
+ var1 = var10001;
+ byte var7 = (byte)var1;
+ byte var4 = (byte)var2;
+ byte var8 = (byte)var3;
+ byte var6 = var4;
+ byte var5 = var7;
+ if(!this.noColor) {
+ if(!this.color) {
+ this.vertexLength += 3;
+ }
+
+ this.color = true;
+ this.r = (float)(var5 & 255) / 255.0F;
+ this.g = (float)(var6 & 255) / 255.0F;
+ this.b = (float)(var8 & 255) / 255.0F;
+ }
+
+ }
+
+ public final void noColor() {
+ this.noColor = true;
+ }
+
+ public final void normal(float var1, float var2, float var3) {
+ GL11.glNormal3f(var1, var2, var3);
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/render/TextureManager.java b/src/main/java/com/mojang/minecraft/render/TextureManager.java
new file mode 100644
index 0000000..f53e204
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/TextureManager.java
@@ -0,0 +1,99 @@
+package com.mojang.minecraft.render;
+
+import com.mojang.minecraft.GameSettings;
+import com.mojang.minecraft.render.texture.TextureFX;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import javax.imageio.ImageIO;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+
+public class TextureManager {
+
+ public HashMap textures = new HashMap();
+ public HashMap textureImages = new HashMap();
+ public IntBuffer idBuffer = BufferUtils.createIntBuffer(1);
+ public ByteBuffer textureBuffer = BufferUtils.createByteBuffer(262144);
+ public List animations = new ArrayList();
+ public GameSettings settings;
+
+
+ public TextureManager(GameSettings var1) {
+ this.settings = var1;
+ }
+
+ public final int load(String var1) {
+ Integer var2;
+ if((var2 = (Integer)this.textures.get(var1)) != null) {
+ return var2.intValue();
+ } else {
+ try {
+ this.idBuffer.clear();
+ GL11.glGenTextures(this.idBuffer);
+ int var4 = this.idBuffer.get(0);
+ this.load(ImageIO.read(TextureManager.class.getResourceAsStream(var1)), var4);
+ this.textures.put(var1, Integer.valueOf(var4));
+ return var4;
+ } catch (IOException var3) {
+ throw new RuntimeException("!!");
+ }
+ }
+ }
+
+ public final int load(BufferedImage var1) {
+ this.idBuffer.clear();
+ GL11.glGenTextures(this.idBuffer);
+ int var2 = this.idBuffer.get(0);
+ this.load(var1, var2);
+ this.textureImages.put(Integer.valueOf(var2), var1);
+ return var2;
+ }
+
+ public void load(BufferedImage var1, int var2) {
+ GL11.glBindTexture(3553, var2);
+ GL11.glTexParameteri(3553, 10241, 9728);
+ GL11.glTexParameteri(3553, 10240, 9728);
+ var2 = var1.getWidth();
+ int var3 = var1.getHeight();
+ int[] var4 = new int[var2 * var3];
+ byte[] var5 = new byte[var2 * var3 << 2];
+ var1.getRGB(0, 0, var2, var3, var4, 0, var2);
+
+ for(int var11 = 0; var11 < var4.length; ++var11) {
+ int var6 = var4[var11] >>> 24;
+ int var7 = var4[var11] >> 16 & 255;
+ int var8 = var4[var11] >> 8 & 255;
+ int var9 = var4[var11] & 255;
+ if(this.settings.anaglyph) {
+ int var10 = (var7 * 30 + var8 * 59 + var9 * 11) / 100;
+ var8 = (var7 * 30 + var8 * 70) / 100;
+ var9 = (var7 * 30 + var9 * 70) / 100;
+ var7 = var10;
+ var8 = var8;
+ var9 = var9;
+ }
+
+ var5[var11 << 2] = (byte)var7;
+ var5[(var11 << 2) + 1] = (byte)var8;
+ var5[(var11 << 2) + 2] = (byte)var9;
+ var5[(var11 << 2) + 3] = (byte)var6;
+ }
+
+ this.textureBuffer.clear();
+ this.textureBuffer.put(var5);
+ this.textureBuffer.position(0).limit(var5.length);
+ GL11.glTexImage2D(3553, 0, 6408, var2, var3, 0, 6408, 5121, this.textureBuffer);
+ }
+
+ public final void registerAnimation(TextureFX var1) {
+ this.animations.add(var1);
+ var1.animate();
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/render/texture/TextureFX.java b/src/main/java/com/mojang/minecraft/render/texture/TextureFX.java
new file mode 100644
index 0000000..f9179bc
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/texture/TextureFX.java
@@ -0,0 +1,17 @@
+package com.mojang.minecraft.render.texture;
+
+public class TextureFX
+{
+ public TextureFX(int textureID)
+ {
+ this.textureId = textureID;
+ }
+
+ public byte[] textureData = new byte[1024];
+ public int textureId;
+ public boolean anaglyph = false;
+
+ public void animate()
+ {
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/render/texture/TextureLavaFX.java b/src/main/java/com/mojang/minecraft/render/texture/TextureLavaFX.java
new file mode 100644
index 0000000..8ba098f
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/texture/TextureLavaFX.java
@@ -0,0 +1,87 @@
+package com.mojang.minecraft.render.texture;
+
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.render.texture.TextureFX;
+import com.mojang.util.MathHelper;
+
+public final class TextureLavaFX extends TextureFX {
+
+ private float[] red = new float[256];
+ private float[] green = new float[256];
+ private float[] blue = new float[256];
+ private float[] alpha = new float[256];
+
+
+ public TextureLavaFX() {
+ super(Block.LAVA.textureId);
+ }
+
+ public final void animate() {
+ int var1;
+ int var2;
+ float var3;
+ int var5;
+ int var6;
+ int var7;
+ int var8;
+ int var9;
+ for(var1 = 0; var1 < 16; ++var1) {
+ for(var2 = 0; var2 < 16; ++var2) {
+ var3 = 0.0F;
+ int var4 = (int)(MathHelper.sin((float)var2 * 3.1415927F * 2.0F / 16.0F) * 1.2F);
+ var5 = (int)(MathHelper.sin((float)var1 * 3.1415927F * 2.0F / 16.0F) * 1.2F);
+
+ for(var6 = var1 - 1; var6 <= var1 + 1; ++var6) {
+ for(var7 = var2 - 1; var7 <= var2 + 1; ++var7) {
+ var8 = var6 + var4 & 15;
+ var9 = var7 + var5 & 15;
+ var3 += this.red[var8 + (var9 << 4)];
+ }
+ }
+
+ this.green[var1 + (var2 << 4)] = var3 / 10.0F + (this.blue[(var1 & 15) + ((var2 & 15) << 4)] + this.blue[(var1 + 1 & 15) + ((var2 & 15) << 4)] + this.blue[(var1 + 1 & 15) + ((var2 + 1 & 15) << 4)] + this.blue[(var1 & 15) + ((var2 + 1 & 15) << 4)]) / 4.0F * 0.8F;
+ this.blue[var1 + (var2 << 4)] += this.alpha[var1 + (var2 << 4)] * 0.01F;
+ if(this.blue[var1 + (var2 << 4)] < 0.0F) {
+ this.blue[var1 + (var2 << 4)] = 0.0F;
+ }
+
+ this.alpha[var1 + (var2 << 4)] -= 0.06F;
+ if(Math.random() < 0.005D) {
+ this.alpha[var1 + (var2 << 4)] = 1.5F;
+ }
+ }
+ }
+
+ float[] var10 = this.green;
+ this.green = this.red;
+ this.red = var10;
+
+ for(var2 = 0; var2 < 256; ++var2) {
+ if((var3 = this.red[var2] * 2.0F) > 1.0F) {
+ var3 = 1.0F;
+ }
+
+ if(var3 < 0.0F) {
+ var3 = 0.0F;
+ }
+
+ var5 = (int)(var3 * 100.0F + 155.0F);
+ var6 = (int)(var3 * var3 * 255.0F);
+ var7 = (int)(var3 * var3 * var3 * var3 * 128.0F);
+ if(this.anaglyph) {
+ var8 = (var5 * 30 + var6 * 59 + var7 * 11) / 100;
+ var9 = (var5 * 30 + var6 * 70) / 100;
+ var1 = (var5 * 30 + var7 * 70) / 100;
+ var5 = var8;
+ var6 = var9;
+ var7 = var1;
+ }
+
+ this.textureData[var2 << 2] = (byte)var5;
+ this.textureData[(var2 << 2) + 1] = (byte)var6;
+ this.textureData[(var2 << 2) + 2] = (byte)var7;
+ this.textureData[(var2 << 2) + 3] = -1;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/render/texture/TextureWaterFX.java b/src/main/java/com/mojang/minecraft/render/texture/TextureWaterFX.java
new file mode 100644
index 0000000..777cd82
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/render/texture/TextureWaterFX.java
@@ -0,0 +1,90 @@
+package com.mojang.minecraft.render.texture;
+
+import com.mojang.minecraft.level.tile.Block;
+import com.mojang.minecraft.render.texture.TextureFX;
+
+public final class TextureWaterFX extends TextureFX {
+
+ private float[] red = new float[256];
+ private float[] blue = new float[256];
+ private float[] green = new float[256];
+ private float[] alpha = new float[256];
+ private int updates = 0;
+
+
+ public TextureWaterFX() {
+ super(Block.WATER.textureId);
+ }
+
+ public final void animate() {
+ ++this.updates;
+
+ int var1;
+ int var2;
+ float var3;
+ int var4;
+ int var5;
+ int var6;
+ for(var1 = 0; var1 < 16; ++var1) {
+ for(var2 = 0; var2 < 16; ++var2) {
+ var3 = 0.0F;
+
+ for(var4 = var1 - 1; var4 <= var1 + 1; ++var4) {
+ var5 = var4 & 15;
+ var6 = var2 & 15;
+ var3 += this.red[var5 + (var6 << 4)];
+ }
+
+ this.blue[var1 + (var2 << 4)] = var3 / 3.3F + this.green[var1 + (var2 << 4)] * 0.8F;
+ }
+ }
+
+ for(var1 = 0; var1 < 16; ++var1) {
+ for(var2 = 0; var2 < 16; ++var2) {
+ this.green[var1 + (var2 << 4)] += this.alpha[var1 + (var2 << 4)] * 0.05F;
+ if(this.green[var1 + (var2 << 4)] < 0.0F) {
+ this.green[var1 + (var2 << 4)] = 0.0F;
+ }
+
+ this.alpha[var1 + (var2 << 4)] -= 0.1F;
+ if(Math.random() < 0.05D) {
+ this.alpha[var1 + (var2 << 4)] = 0.5F;
+ }
+ }
+ }
+
+ float[] var8 = this.blue;
+ this.blue = this.red;
+ this.red = var8;
+
+ for(var2 = 0; var2 < 256; ++var2) {
+ if((var3 = this.red[var2]) > 1.0F) {
+ var3 = 1.0F;
+ }
+
+ if(var3 < 0.0F) {
+ var3 = 0.0F;
+ }
+
+ float var9 = var3 * var3;
+ var5 = (int)(32.0F + var9 * 32.0F);
+ var6 = (int)(50.0F + var9 * 64.0F);
+ var1 = 255;
+ int var10 = (int)(146.0F + var9 * 50.0F);
+ if(this.anaglyph) {
+ var1 = (var5 * 30 + var6 * 59 + 2805) / 100;
+ var4 = (var5 * 30 + var6 * 70) / 100;
+ int var7 = (var5 * 30 + 17850) / 100;
+ var5 = var1;
+ var6 = var4;
+ var1 = var7;
+ }
+
+ this.textureData[var2 << 2] = (byte)var5;
+ this.textureData[(var2 << 2) + 1] = (byte)var6;
+ this.textureData[(var2 << 2) + 2] = (byte)var1;
+ this.textureData[(var2 << 2) + 3] = (byte)var10;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/Audio.java b/src/main/java/com/mojang/minecraft/sound/Audio.java
new file mode 100644
index 0000000..dcd4e50
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/Audio.java
@@ -0,0 +1,6 @@
+package com.mojang.minecraft.sound;
+
+public interface Audio
+{
+ boolean play(int[] var1, int[] var2, int var3);
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/AudioInfo.java b/src/main/java/com/mojang/minecraft/sound/AudioInfo.java
new file mode 100644
index 0000000..a827f21
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/AudioInfo.java
@@ -0,0 +1,11 @@
+package com.mojang.minecraft.sound;
+
+public class AudioInfo
+{
+ public float volume = 1.0F;
+
+ public int update(short[] var1, int var2)
+ {
+ return 0;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/BaseSoundPos.java b/src/main/java/com/mojang/minecraft/sound/BaseSoundPos.java
new file mode 100644
index 0000000..eb16cd9
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/BaseSoundPos.java
@@ -0,0 +1,50 @@
+package com.mojang.minecraft.sound;
+
+import com.mojang.minecraft.Entity;
+import com.mojang.util.MathHelper;
+
+public abstract class BaseSoundPos implements SoundPos
+{
+ public BaseSoundPos(Entity listener)
+ {
+ this.listener = listener;
+ }
+
+ private Entity listener;
+
+ public float getRotationDiff(float x, float y)
+ {
+ x -= listener.x;
+ y -= listener.z;
+
+ float var3 = MathHelper.sqrt(x * x + y * y);
+
+ x /= var3;
+ y /= var3;
+
+ if((var3 /= 2.0F) > 1.0F)
+ {
+ var3 = 1.0F;
+ }
+
+ float var4 = MathHelper.cos(-listener.yRot * 0.017453292F + 3.1415927F);
+
+ return (MathHelper.sin(-listener.yRot * 0.017453292F + 3.1415927F) * y - var4 * x) * var3;
+ }
+
+ public float getDistanceSq(float x, float y, float z)
+ {
+ x -= listener.x;
+ y -= listener.y;
+ float var4 = z - listener.z;
+
+ var4 = MathHelper.sqrt(x * x + y * y + var4 * var4);
+
+ if((var4 = 1.0F - var4 / 32.0F) < 0.0F)
+ {
+ var4 = 0.0F;
+ }
+
+ return var4;
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/EntitySoundPos.java b/src/main/java/com/mojang/minecraft/sound/EntitySoundPos.java
new file mode 100644
index 0000000..56a2767
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/EntitySoundPos.java
@@ -0,0 +1,27 @@
+package com.mojang.minecraft.sound;
+
+import com.mojang.minecraft.Entity;
+
+public class EntitySoundPos extends BaseSoundPos
+{
+ public EntitySoundPos(Entity source, Entity listener)
+ {
+ super(listener);
+
+ this.source = source;
+ }
+
+ @Override
+ public float getRotationDiff()
+ {
+ return super.getRotationDiff(source.x, source.z);
+ }
+
+ @Override
+ public float getDistanceSq()
+ {
+ return super.getDistanceSq(source.x, source.y, source.z);
+ }
+
+ private Entity source;
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/LevelSoundPos.java b/src/main/java/com/mojang/minecraft/sound/LevelSoundPos.java
new file mode 100644
index 0000000..4afa5bc
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/LevelSoundPos.java
@@ -0,0 +1,31 @@
+package com.mojang.minecraft.sound;
+
+import com.mojang.minecraft.Entity;
+
+public final class LevelSoundPos extends BaseSoundPos
+{
+ public LevelSoundPos(float x, float y, float z, Entity listener)
+ {
+ super(listener);
+
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ @Override
+ public float getRotationDiff()
+ {
+ return super.getRotationDiff(x, z);
+ }
+
+ @Override
+ public float getDistanceSq()
+ {
+ return super.getDistanceSq(x, y, z);
+ }
+
+ private float x;
+ private float y;
+ private float z;
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/Music.java b/src/main/java/com/mojang/minecraft/sound/Music.java
new file mode 100644
index 0000000..a6bb799
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/Music.java
@@ -0,0 +1,80 @@
+package com.mojang.minecraft.sound;
+
+import de.jarnbjo.ogg.LogicalOggStreamImpl;
+import de.jarnbjo.ogg.OggFormatException;
+import de.jarnbjo.ogg.OnDemandUrlStream;
+import de.jarnbjo.vorbis.VorbisFormatException;
+import de.jarnbjo.vorbis.VorbisStream;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+
+// TODO.
+public final class Music implements Audio {
+
+ ByteBuffer playing = ByteBuffer.allocate(176400);
+ ByteBuffer current = ByteBuffer.allocate(176400);
+ private ByteBuffer processing = null;
+ ByteBuffer previous = null;
+ VorbisStream stream;
+ SoundPlayer player;
+ boolean finished = false;
+ boolean stopped = false;
+
+
+ public Music(SoundPlayer var1, URL var2) {
+ this.player = var1;
+ try
+ {
+ LogicalOggStreamImpl var3 = (LogicalOggStreamImpl)(new OnDemandUrlStream(var2)).getLogicalStreams().iterator().next();
+ this.stream = new VorbisStream(var3);
+ } catch (VorbisFormatException e) {
+ e.printStackTrace();
+ } catch (OggFormatException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ (new MusicPlayThread(this)).start();
+ }
+
+ public final boolean play(int[] var1, int[] var2, int var3) {
+ if(!this.player.settings.music) {
+ this.stopped = true;
+ return false;
+ } else {
+ var3 = var3;
+ int var4 = 0;
+
+ while(var3 > 0 && (this.processing != null || this.previous != null)) {
+ if(this.processing == null && this.previous != null) {
+ this.processing = this.previous;
+ this.previous = null;
+ }
+
+ if(this.processing != null && this.processing.remaining() > 0) {
+ int var5;
+ if((var5 = this.processing.remaining() / 4) > var3) {
+ var5 = var3;
+ }
+
+ for(int var6 = 0; var6 < var5; ++var6) {
+ var1[var4 + var6] += this.processing.getShort();
+ var2[var4 + var6] += this.processing.getShort();
+ }
+
+ var4 += var5;
+ var3 -= var5;
+ }
+
+ if(this.current == null && this.processing != null && this.processing.remaining() == 0) {
+ this.current = this.processing;
+ this.processing = null;
+ }
+ }
+
+ return this.processing != null || this.previous != null || !this.finished;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/MusicPlayThread.java b/src/main/java/com/mojang/minecraft/sound/MusicPlayThread.java
new file mode 100644
index 0000000..e187931
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/MusicPlayThread.java
@@ -0,0 +1,101 @@
+package com.mojang.minecraft.sound;
+
+import de.jarnbjo.vorbis.VorbisStream;
+
+import java.nio.ByteBuffer;
+
+// TODO.
+final class MusicPlayThread extends Thread {
+
+ // $FF: synthetic field
+ private Music music;
+
+
+ public MusicPlayThread(Music var1) {
+ super();
+ this.music = var1;
+ this.setPriority(10);
+ this.setDaemon(true);
+ }
+
+ public final void run() {
+ try {
+ do {
+ if(this.music.stopped) {
+ return;
+ }
+
+ Music var1 = this.music;
+ ByteBuffer var2;
+ Music var10001;
+ if(this.music.playing == null) {
+ var1 = this.music;
+ if(this.music.current != null) {
+ var1 = this.music;
+ var2 = this.music.current;
+ var10001 = this.music;
+ this.music.playing = var2;
+ var2 = null;
+ var1 = this.music;
+ this.music.current = null;
+ var1 = this.music;
+ this.music.playing.clear();
+ }
+ }
+
+ var1 = this.music;
+ if(this.music.playing != null) {
+ var1 = this.music;
+ if(this.music.playing.remaining() != 0) {
+ while(true) {
+ var1 = this.music;
+ if(this.music.playing.remaining() == 0) {
+ break;
+ }
+
+ var1 = this.music;
+ var1 = this.music;
+ var2 = this.music.playing;
+ VorbisStream var9 = this.music.stream;
+ int var10 = this.music.stream.readPcm(var2.array(), var2.position(), var2.remaining());
+ var2.position(var2.position() + var10);
+ boolean var11;
+ if(var11 = var10 <= 0) {
+ this.music.finished = true;
+ this.music.stopped = true;
+ break;
+ }
+ }
+ }
+ }
+
+ var1 = this.music;
+ if(this.music.playing != null) {
+ var1 = this.music;
+ if(this.music.previous == null) {
+ var1 = this.music;
+ this.music.playing.flip();
+ var1 = this.music;
+ var2 = this.music.playing;
+ var10001 = this.music;
+ this.music.previous = var2;
+ var2 = null;
+ var1 = this.music;
+ this.music.playing = var2;
+ }
+ }
+
+ Thread.sleep(10L);
+ var1 = this.music;
+ } while(this.music.player.running);
+
+ return;
+ } catch (Exception var7) {
+ var7.printStackTrace();
+ return;
+ } finally {
+ this.music.finished = true;
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/Sound.java b/src/main/java/com/mojang/minecraft/sound/Sound.java
new file mode 100644
index 0000000..43a9433
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/Sound.java
@@ -0,0 +1,62 @@
+package com.mojang.minecraft.sound;
+
+// TODO.
+public final class Sound implements Audio {
+
+ private AudioInfo info;
+ private SoundPos pos;
+ private float pitch = 0.0F;
+ private float volume = 1.0F;
+ private static short[] data = new short[1];
+
+
+ public Sound(AudioInfo var1, SoundPos var2) {
+ this.info = var1;
+ this.pos = var2;
+ this.pitch = var2.getRotationDiff();
+ this.volume = var2.getDistanceSq() * var1.volume;
+ }
+
+ public final boolean play(int[] var1, int[] var2, int var3) {
+ if(data.length < var3) {
+ data = new short[var3];
+ }
+
+ int var4;
+ boolean var5 = (var4 = this.info.update(data, var3)) > 0;
+ float var6 = this.pos.getRotationDiff();
+ float var7 = this.pos.getDistanceSq() * this.info.volume;
+ int var8 = (int)((this.pitch > 0.0F?1.0F - this.pitch:1.0F) * this.volume * 65536.0F);
+ int var9 = (int)((this.pitch < 0.0F?1.0F + this.pitch:1.0F) * this.volume * 65536.0F);
+ int var10 = (int)((var6 > 0.0F?1.0F - var6:1.0F) * var7 * 65536.0F);
+ int var11 = (int)((var6 < 0.0F?var6 + 1.0F:1.0F) * var7 * 65536.0F);
+ var10 -= var8;
+ var11 -= var9;
+ int var12;
+ int var13;
+ int var14;
+ if(var10 == 0 && var11 == 0) {
+ if(var8 >= 0 || var9 != 0) {
+ var12 = var8;
+ var13 = var9;
+
+ for(var14 = 0; var14 < var4; ++var14) {
+ var1[var14] += data[var14] * var12 >> 16;
+ var2[var14] += data[var14] * var13 >> 16;
+ }
+ }
+ } else {
+ for(var12 = 0; var12 < var4; ++var12) {
+ var13 = var8 + var10 * var12 / var3;
+ var14 = var9 + var11 * var12 / var3;
+ var1[var12] += data[var12] * var13 >> 16;
+ var2[var12] += data[var12] * var14 >> 16;
+ }
+ }
+
+ this.pitch = var6;
+ this.volume = var7;
+ return var5;
+ }
+
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/SoundData.java b/src/main/java/com/mojang/minecraft/sound/SoundData.java
new file mode 100644
index 0000000..700b960
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/SoundData.java
@@ -0,0 +1,13 @@
+package com.mojang.minecraft.sound;
+
+public class SoundData
+{
+ public SoundData(short[] data, float length)
+ {
+ this.data = data;
+ this.length = length;
+ }
+
+ public short[] data;
+ public float length;
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/SoundInfo.java b/src/main/java/com/mojang/minecraft/sound/SoundInfo.java
new file mode 100644
index 0000000..e98720f
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/SoundInfo.java
@@ -0,0 +1,35 @@
+package com.mojang.minecraft.sound;
+
+// TODO.
+public final class SoundInfo extends AudioInfo {
+
+ private SoundData data;
+ private float seek = 0.0F;
+ private float pitch;
+
+
+ public SoundInfo(SoundData var1, float var2, float var3) {
+ this.data = var1;
+ this.pitch = var2 * 44100.0F / var1.length;
+ this.volume = var3;
+ }
+
+ public final int update(short[] var1, int var2) {
+ if(this.seek >= (float)this.data.data.length) {
+ return 0;
+ } else {
+ for(int var3 = 0; var3 < var2; ++var3) {
+ int var4 = (int)this.seek;
+ short var5 = this.data.data[var4];
+ short var6 = var4 < this.data.data.length - 1?this.data.data[var4 + 1]:0;
+ var1[var3] = (short)((int)((float)var5 + (float)(var6 - var5) * (this.seek - (float)var4)));
+ this.seek += this.pitch;
+ if(this.seek >= (float)this.data.data.length) {
+ return var3;
+ }
+ }
+
+ return var2;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/SoundManager.java b/src/main/java/com/mojang/minecraft/sound/SoundManager.java
new file mode 100644
index 0000000..f794e8f
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/SoundManager.java
@@ -0,0 +1,96 @@
+package com.mojang.minecraft.sound;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.*;
+
+// TODO.
+public final class SoundManager {
+
+ private SoundReader reader = new SoundReader();
+ public Map sounds = new HashMap();
+ private Map music = new HashMap();
+ public Random random = new Random();
+ public long lastMusic = System.currentTimeMillis() + 60000L;
+
+
+ public final AudioInfo getAudioInfo(String var1, float var2, float var3) {
+ List var4 = null;
+ Map var5 = this.sounds;
+ synchronized(this.sounds) {
+ var4 = (List)this.sounds.get(var1);
+ }
+
+ if(var4 == null) {
+ return null;
+ } else {
+ SoundData var7 = (SoundData)var4.get(this.random.nextInt(var4.size()));
+ return new SoundInfo(var7, var3, var2);
+ }
+ }
+
+ public void registerSound(File var1, String var2) {
+ try {
+ for(var2 = var2.substring(0, var2.length() - 4).replaceAll("/", "."); Character.isDigit(var2.charAt(var2.length() - 1)); var2 = var2.substring(0, var2.length() - 1)) {
+ ;
+ }
+
+ SoundData var7 = SoundReader.read(var1.toURI().toURL());
+ Map var3 = this.sounds;
+ synchronized(this.sounds) {
+ Object var4;
+ if((var4 = (List)this.sounds.get(var2)) == null) {
+ var4 = new ArrayList();
+ this.sounds.put(var2, var4);
+ }
+
+ ((List)var4).add(var7);
+ }
+ } catch (Exception var6) {
+ var6.printStackTrace();
+ }
+
+ }
+
+ public final void registerMusic(String var1, File var2) {
+ Map var3 = this.music;
+ synchronized(this.music) {
+ for(var1 = var1.substring(0, var1.length() - 4).replaceAll("/", "."); Character.isDigit(var1.charAt(var1.length() - 1)); var1 = var1.substring(0, var1.length() - 1)) {
+ ;
+ }
+
+ Object var4;
+ if((var4 = (List)this.music.get(var1)) == null) {
+ var4 = new ArrayList();
+ this.music.put(var1, var4);
+ }
+
+ ((List)var4).add(var2);
+ }
+ }
+
+ public boolean playMusic(SoundPlayer var1, String var2) {
+ List var3 = null;
+ Map var4 = this.music;
+ synchronized(this.music) {
+ var3 = (List)this.music.get(var2);
+ }
+
+ if(var3 == null) {
+ return false;
+ } else {
+ File var8 = (File)var3.get(this.random.nextInt(var3.size()));
+
+ try {
+ var1.play(new Music(var1, var8.toURI().toURL()));
+ } catch (MalformedURLException var5) {
+ var5.printStackTrace();
+ } catch (IOException var6) {
+ var6.printStackTrace();
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/SoundPlayer.java b/src/main/java/com/mojang/minecraft/sound/SoundPlayer.java
new file mode 100644
index 0000000..7a73138
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/SoundPlayer.java
@@ -0,0 +1,107 @@
+package com.mojang.minecraft.sound;
+
+import com.mojang.minecraft.GameSettings;
+
+import javax.sound.sampled.SourceDataLine;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+// TODO.
+public final class SoundPlayer implements Runnable {
+
+ public boolean running = false;
+ public SourceDataLine dataLine;
+ private List audioQueue = new ArrayList();
+ public GameSettings settings;
+
+
+ public SoundPlayer(GameSettings var1) {
+ this.settings = var1;
+ }
+
+ public final void play(Audio var1) {
+ if(this.running) {
+ List var2 = this.audioQueue;
+ synchronized(this.audioQueue) {
+ this.audioQueue.add(var1);
+ }
+ }
+ }
+
+ public final void play(AudioInfo var1, SoundPos var2) {
+ this.play(new Sound(var1, var2));
+ }
+
+ public final void run() {
+ int[] var1 = new int[4410];
+ int[] var2 = new int[4410];
+
+ for(byte[] var3 = new byte[17640]; this.running; this.dataLine.write(var3, 0, 17640)) {
+ try {
+ Thread.sleep(1L);
+ } catch (InterruptedException var10) {
+ var10.printStackTrace();
+ }
+
+ Arrays.fill(var1, 0, 4410, 0);
+ Arrays.fill(var2, 0, 4410, 0);
+ boolean var4 = true;
+ int[] var5 = var2;
+ int[] var6 = var1;
+ List var12 = this.audioQueue;
+ List var7 = this.audioQueue;
+ synchronized(this.audioQueue) {
+ int var8 = 0;
+
+ while(true) {
+ if(var8 >= var12.size()) {
+ break;
+ }
+
+ if(!((Audio)var12.get(var8)).play(var6, var5, 4410)) {
+ var12.remove(var8--);
+ }
+
+ ++var8;
+ }
+ }
+
+ int var13;
+ if(!this.settings.music && !this.settings.sound) {
+ for(var13 = 0; var13 < 4410; ++var13) {
+ var3[var13 << 2] = 0;
+ var3[(var13 << 2) + 1] = 0;
+ var3[(var13 << 2) + 2] = 0;
+ var3[(var13 << 2) + 3] = 0;
+ }
+ } else {
+ for(var13 = 0; var13 < 4410; ++var13) {
+ int var15 = var1[var13];
+ int var14 = var2[var13];
+ if(var15 < -32000) {
+ var15 = -32000;
+ }
+
+ if(var14 < -32000) {
+ var14 = -32000;
+ }
+
+ if(var15 >= 32000) {
+ var15 = 32000;
+ }
+
+ if(var14 >= 32000) {
+ var14 = 32000;
+ }
+
+ var3[var13 << 2] = (byte)(var15 >> 8);
+ var3[(var13 << 2) + 1] = (byte)var15;
+ var3[(var13 << 2) + 2] = (byte)(var14 >> 8);
+ var3[(var13 << 2) + 3] = (byte)var14;
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/SoundPos.java b/src/main/java/com/mojang/minecraft/sound/SoundPos.java
new file mode 100644
index 0000000..f425b88
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/SoundPos.java
@@ -0,0 +1,8 @@
+package com.mojang.minecraft.sound;
+
+public interface SoundPos
+{
+ float getRotationDiff();
+
+ float getDistanceSq();
+}
diff --git a/src/main/java/com/mojang/minecraft/sound/SoundReader.java b/src/main/java/com/mojang/minecraft/sound/SoundReader.java
new file mode 100644
index 0000000..ec57429
--- /dev/null
+++ b/src/main/java/com/mojang/minecraft/sound/SoundReader.java
@@ -0,0 +1,89 @@
+package com.mojang.minecraft.sound;
+
+import de.jarnbjo.ogg.LogicalOggStreamImpl;
+import de.jarnbjo.ogg.OggFormatException;
+import de.jarnbjo.ogg.OnDemandUrlStream;
+import de.jarnbjo.vorbis.IdentificationHeader;
+import de.jarnbjo.vorbis.VorbisFormatException;
+import de.jarnbjo.vorbis.VorbisStream;
+
+import java.io.IOException;
+import java.net.URL;
+
+// TODO.
+public final class SoundReader {
+
+ public static SoundData read(URL var0) {
+ VorbisStream var12 = null;
+ try
+ {
+ LogicalOggStreamImpl var11 = (LogicalOggStreamImpl)(new OnDemandUrlStream(var0)).getLogicalStreams().iterator().next();
+ var12 = new VorbisStream(var11);
+ } catch (VorbisFormatException e) {
+ e.printStackTrace();
+ } catch (OggFormatException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ byte[] var2 = new byte[4096];
+ int var3 = 0;
+ boolean var1 = false;
+ IdentificationHeader var14 = var12.getIdentificationHeader();
+ int var4 = var12.getIdentificationHeader().getChannels();
+ short[] var5 = new short[4096];
+ int var6 = 0;
+
+ label51:
+ while(var3 >= 0) {
+ int var15 = 0;
+
+ while(true) {
+ try {
+ if(var15 < var2.length && (var3 = var12.readPcm(var2, var15, var2.length - var15)) > 0) {
+ var15 += var3;
+ continue;
+ }
+ } catch (Exception var10) {
+ var3 = -1;
+ }
+
+ if(var15 <= 0) {
+ break;
+ }
+
+ boolean var7 = false;
+ int var16 = 0;
+
+ while(true) {
+ if(var16 >= var15) {
+ continue label51;
+ }
+
+ int var8 = 0;
+
+ for(int var9 = 0; var9 < var4; ++var9) {
+ var8 += var2[var16++] << 8 | var2[var16++] & 255;
+ }
+
+ if(var6 == var5.length) {
+ short[] var18 = var5;
+ var5 = new short[var5.length << 1];
+ System.arraycopy(var18, 0, var5, 0, var6);
+ }
+
+ var5[var6++] = (short)(var8 / var4);
+ }
+ }
+ }
+
+ if(var6 != var5.length) {
+ short[] var17 = var5;
+ var5 = new short[var6];
+ System.arraycopy(var17, 0, var5, 0, var6);
+ }
+
+ IdentificationHeader var13;
+ return new SoundData(var5, (float)(var13 = var12.getIdentificationHeader()).getSampleRate());
+ }
+}
diff --git a/src/main/java/com/mojang/net/NetworkHandler.java b/src/main/java/com/mojang/net/NetworkHandler.java
new file mode 100644
index 0000000..cb6a88b
--- /dev/null
+++ b/src/main/java/com/mojang/net/NetworkHandler.java
@@ -0,0 +1,164 @@
+package com.mojang.net;
+
+import com.mojang.minecraft.net.NetworkManager;
+import com.mojang.minecraft.net.PacketType;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.Arrays;
+
+public final class NetworkHandler {
+
+ public volatile boolean connected;
+ public SocketChannel channel;
+ public ByteBuffer in = ByteBuffer.allocate(1048576);
+ public ByteBuffer out = ByteBuffer.allocate(1048576);
+ public NetworkManager netManager;
+ private Socket sock;
+ private boolean unused = false;
+ private byte[] stringBytes = new byte[64];
+
+
+ public NetworkHandler(String var1, int var2) {
+ try
+ {
+ channel = SocketChannel.open();
+ this.channel.connect(new InetSocketAddress(var1, var2));
+ this.channel.configureBlocking(false);
+ System.currentTimeMillis();
+ this.sock = this.channel.socket();
+ this.connected = true;
+ this.in.clear();
+ this.out.clear();
+ this.sock.setTcpNoDelay(true);
+ this.sock.setTrafficClass(24);
+ this.sock.setKeepAlive(false);
+ this.sock.setReuseAddress(false);
+ this.sock.setSoTimeout(100);
+ this.sock.getInetAddress().toString();
+ } catch (SocketException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public final void close() {
+ try {
+ if(this.out.position() > 0) {
+ this.out.flip();
+ this.channel.write(this.out);
+ this.out.compact();
+ }
+ } catch (Exception var2) {
+ ;
+ }
+
+ this.connected = false;
+
+ try {
+ this.channel.close();
+ } catch (Exception var1) {
+ ;
+ }
+
+ this.sock = null;
+ this.channel = null;
+ }
+
+ public final void send(PacketType var1, Object ... var2) {
+ if(this.connected) {
+ this.out.put(var1.opcode);
+
+ for(int var3 = 0; var3 < var2.length; ++var3) {
+ Class var10001 = var1.params[var3];
+ Object var4 = var2[var3];
+ Class var5 = var10001;
+ NetworkHandler var6 = this;
+ if(this.connected) {
+ try {
+ if(var5 == Long.TYPE) {
+ var6.out.putLong(((Long)var4).longValue());
+ } else if(var5 == Integer.TYPE) {
+ var6.out.putInt(((Number)var4).intValue());
+ } else if(var5 == Short.TYPE) {
+ var6.out.putShort(((Number)var4).shortValue());
+ } else if(var5 == Byte.TYPE) {
+ var6.out.put(((Number)var4).byteValue());
+ } else if(var5 == Double.TYPE) {
+ var6.out.putDouble(((Double)var4).doubleValue());
+ } else if(var5 == Float.TYPE) {
+ var6.out.putFloat(((Float)var4).floatValue());
+ } else {
+ byte[] var9;
+ if(var5 != String.class) {
+ if(var5 == byte[].class) {
+ if((var9 = (byte[])((byte[])var4)).length < 1024) {
+ var9 = Arrays.copyOf(var9, 1024);
+ }
+
+ var6.out.put(var9);
+ }
+ } else {
+ var9 = ((String)var4).getBytes("UTF-8");
+ Arrays.fill(var6.stringBytes, (byte)32);
+
+ int var8;
+ for(var8 = 0; var8 < 64 && var8 < var9.length; ++var8) {
+ var6.stringBytes[var8] = var9[var8];
+ }
+
+ for(var8 = var9.length; var8 < 64; ++var8) {
+ var6.stringBytes[var8] = 32;
+ }
+
+ var6.out.put(var6.stringBytes);
+ }
+ }
+ } catch (Exception var7) {
+ this.netManager.error(var7);
+ }
+ }
+ }
+
+ }
+ }
+
+ public Object readObject(Class var1) {
+ if(!this.connected) {
+ return null;
+ } else {
+ try {
+ if(var1 == Long.TYPE) {
+ return Long.valueOf(this.in.getLong());
+ } else if(var1 == Integer.TYPE) {
+ return Integer.valueOf(this.in.getInt());
+ } else if(var1 == Short.TYPE) {
+ return Short.valueOf(this.in.getShort());
+ } else if(var1 == Byte.TYPE) {
+ return Byte.valueOf(this.in.get());
+ } else if(var1 == Double.TYPE) {
+ return Double.valueOf(this.in.getDouble());
+ } else if(var1 == Float.TYPE) {
+ return Float.valueOf(this.in.getFloat());
+ } else if(var1 == String.class) {
+ this.in.get(this.stringBytes);
+ return (new String(this.stringBytes, "UTF-8")).trim();
+ } else if(var1 == byte[].class) {
+ byte[] var3 = new byte[1024];
+ this.in.get(var3);
+ return var3;
+ } else {
+ return null;
+ }
+ } catch (Exception var2) {
+ this.netManager.error(var2);
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/mojang/util/MathHelper.java b/src/main/java/com/mojang/util/MathHelper.java
new file mode 100644
index 0000000..ede92ea
--- /dev/null
+++ b/src/main/java/com/mojang/util/MathHelper.java
@@ -0,0 +1,43 @@
+package com.mojang.util;
+
+import com.mojang.minecraft.Minecraft;
+
+public final class MathHelper {
+
+ private static float[] SIN_TABLE = new float[65536];
+ private static float[] SIN_TABLE_FAST = new float[4096];
+
+ public static final float sin(float var0) {
+ if(Minecraft.settings.ofFastMath) {
+ return SIN_TABLE_FAST[(int)(var0 * 651.8986F) & 4095];
+ } else {
+ return SIN_TABLE[(int)(var0 * 10430.378F) & '\uffff'];
+ }
+ }
+
+ public static final float cos(float var0) {
+ if(Minecraft.settings.ofFastMath) {
+ return SIN_TABLE_FAST[(int)((var0 + ((float)Math.PI / 2F)) * 651.8986F) & 4095];
+ } else {
+ return SIN_TABLE[(int)(var0 * 10430.378F + 16384.0F) & '\uffff'];
+ }
+ }
+
+ public static final float sqrt(float var0) {
+ return (float)Math.sqrt((double)var0);
+ }
+
+ static {
+ for(int var0 = 0; var0 < 65536; ++var0) {
+ SIN_TABLE[var0] = (float)Math.sin((double)var0 * 3.141592653589793D * 2.0D / 65536.0D);
+ }
+
+ for (int j = 0; j < 4096; ++j) {
+ SIN_TABLE_FAST[j] = (float)Math.sin((double)(((float)j + 0.5F) / 4096.0F * ((float)Math.PI * 2F)));
+ }
+
+ for (int l = 0; l < 360; l += 90) {
+ SIN_TABLE_FAST[(int)((float)l * 11.377778F) & 4095] = (float)Math.sin((double)((float)l * 0.017453292F));
+ }
+ }
+}
diff --git a/src/main/java/de/jarnbjo/ogg/BasicStream.java b/src/main/java/de/jarnbjo/ogg/BasicStream.java
new file mode 100644
index 0000000..8f35e15
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/BasicStream.java
@@ -0,0 +1,107 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: BasicStream.java,v 1.1 2003/08/08 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: BasicStream.java,v $
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * Implementation of the PhysicalOggStream
interface for reading
+ * an Ogg stream from a URL. This class performs
+ * no internal caching, and will not read data from the network before
+ * requested to do so. It is intended to be used in non-realtime applications
+ * like file download managers or similar.
+ */
+
+public class BasicStream implements PhysicalOggStream {
+
+ private boolean closed=false;
+ private InputStream sourceStream;
+ private Object drainLock=new Object();
+ private LinkedList pageCache=new LinkedList();
+ private long numberOfSamples=-1;
+ private int position=0;
+
+ private HashMap logicalStreams=new HashMap();
+ private OggPage firstPage;
+
+ public BasicStream(InputStream sourceStream) throws OggFormatException, IOException {
+ firstPage=OggPage.create(sourceStream);
+ position+=firstPage.getTotalLength();
+ LogicalOggStreamImpl los=new LogicalOggStreamImpl(this, firstPage.getStreamSerialNumber());
+ logicalStreams.put(new Integer(firstPage.getStreamSerialNumber()), los);
+ los.checkFormat(firstPage);
+ }
+
+ public Collection getLogicalStreams() {
+ return logicalStreams.values();
+ }
+
+ public boolean isOpen() {
+ return !closed;
+ }
+
+ public void close() throws IOException {
+ closed=true;
+ sourceStream.close();
+ }
+
+ public int getContentLength() {
+ return -1;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ int pageNumber=2;
+
+ public OggPage getOggPage(int index) throws IOException {
+ if(firstPage!=null) {
+ OggPage tmp=firstPage;
+ firstPage=null;
+ return tmp;
+ }
+ else {
+ OggPage page=OggPage.create(sourceStream);
+ position+=page.getTotalLength();
+ return page;
+ }
+ }
+
+ private LogicalOggStream getLogicalStream(int serialNumber) {
+ return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
+ }
+
+ public void setTime(long granulePosition) throws IOException {
+ throw new UnsupportedOperationException("Method not supported by this class");
+ }
+
+ /**
+ * @return always false
+ */
+
+ public boolean isSeekable() {
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/CachedUrlStream.java b/src/main/java/de/jarnbjo/ogg/CachedUrlStream.java
new file mode 100644
index 0000000..db126bd
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/CachedUrlStream.java
@@ -0,0 +1,246 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: CachedUrlStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: CachedUrlStream.java,v $
+ * Revision 1.1 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * Implementation of the PhysicalOggStream
interface for reading
+ * and caching an Ogg stream from a URL. This class reads the data as fast as
+ * possible from the URL, caches it locally either in memory or on disk, and
+ * supports seeking within the available data.
+ */
+
+public class CachedUrlStream implements PhysicalOggStream {
+
+ private boolean closed=false;
+ private URLConnection source;
+ private InputStream sourceStream;
+ private Object drainLock=new Object();
+ private RandomAccessFile drain;
+ private byte[] memoryCache;
+ private ArrayList pageOffsets=new ArrayList();
+ private ArrayList pageLengths=new ArrayList();
+ private long numberOfSamples=-1;
+ private long cacheLength;
+
+ private HashMap logicalStreams=new HashMap();
+
+ private LoaderThread loaderThread;
+
+ /**
+ * Creates an instance of this class, using a memory cache.
+ */
+
+ public CachedUrlStream(URL source) throws OggFormatException, IOException {
+ this(source, null);
+ }
+
+ /**
+ * Creates an instance of this class, using the specified file as cache. The
+ * file is not automatically deleted when this class is disposed.
+ */
+
+ public CachedUrlStream(URL source, RandomAccessFile drain) throws OggFormatException, IOException {
+
+ this.source=source.openConnection();
+
+ if(drain==null) {
+ int contentLength=this.source.getContentLength();
+ if(contentLength==-1) {
+ throw new IOException("The URLConncetion's content length must be set when operating with a in-memory cache.");
+ }
+ memoryCache=new byte[contentLength];
+ }
+
+ this.drain=drain;
+ this.sourceStream=this.source.getInputStream();
+
+ loaderThread=new LoaderThread(sourceStream, drain, memoryCache);
+ new Thread(loaderThread).start();
+
+ while(!loaderThread.isBosDone() || pageOffsets.size()<20) {
+ System.out.print("pageOffsets.size(): "+pageOffsets.size()+"\r");
+ try {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException ex) {
+ }
+ }
+ System.out.println();
+ System.out.println("caching "+pageOffsets.size()+"/20 pages\r");
+ }
+
+ public Collection getLogicalStreams() {
+ return logicalStreams.values();
+ }
+
+ public boolean isOpen() {
+ return !closed;
+ }
+
+ public void close() throws IOException {
+ closed=true;
+ sourceStream.close();
+ }
+
+ public long getCacheLength() {
+ return cacheLength;
+ }
+
+ /*
+ private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
+ return getNextPage(false);
+ }
+
+ private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
+ return OggPage.create(sourceStream, skipData);
+ }
+ */
+
+ public OggPage getOggPage(int index) throws IOException {
+ synchronized(drainLock) {
+ Long offset=(Long)pageOffsets.get(index);
+ Long length=(Long)pageLengths.get(index);
+ if(offset!=null) {
+ if(drain!=null) {
+ drain.seek(offset.longValue());
+ return OggPage.create(drain);
+ }
+ else {
+ byte[] tmpArray=new byte[length.intValue()];
+ System.arraycopy(memoryCache, offset.intValue(), tmpArray, 0, length.intValue());
+ return OggPage.create(tmpArray);
+ }
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
+ private LogicalOggStream getLogicalStream(int serialNumber) {
+ return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
+ }
+
+ public void setTime(long granulePosition) throws IOException {
+ for(Iterator iter=logicalStreams.values().iterator(); iter.hasNext(); ) {
+ LogicalOggStream los=(LogicalOggStream)iter.next();
+ los.setTime(granulePosition);
+ }
+ }
+
+ public class LoaderThread implements Runnable {
+
+ private InputStream source;
+ private RandomAccessFile drain;
+ private byte[] memoryCache;
+
+ private boolean bosDone=false;
+
+ private int pageNumber;
+
+ public LoaderThread(InputStream source, RandomAccessFile drain, byte[] memoryCache) {
+ this.source=source;
+ this.drain=drain;
+ this.memoryCache=memoryCache;
+ }
+
+ public void run() {
+ try {
+ boolean eos=false;
+ byte[] buffer=new byte[8192];
+ while(!eos) {
+ OggPage op=OggPage.create(source);
+ synchronized (drainLock) {
+ int listSize=pageOffsets.size();
+
+ long pos=
+ listSize>0?
+ ((Long)pageOffsets.get(listSize-1)).longValue()+
+ ((Long)pageLengths.get(listSize-1)).longValue():
+ 0;
+
+ byte[] arr1=op.getHeader();
+ byte[] arr2=op.getSegmentTable();
+ byte[] arr3=op.getData();
+
+ if(drain!=null) {
+ drain.seek(pos);
+ drain.write(arr1);
+ drain.write(arr2);
+ drain.write(arr3);
+ }
+ else {
+ System.arraycopy(arr1, 0, memoryCache, (int)pos, arr1.length);
+ System.arraycopy(arr2, 0, memoryCache, (int)pos+arr1.length, arr2.length);
+ System.arraycopy(arr3, 0, memoryCache, (int)pos+arr1.length+arr2.length, arr3.length);
+ }
+
+ pageOffsets.add(new Long(pos));
+ pageLengths.add(new Long(arr1.length+arr2.length+arr3.length));
+ }
+
+ if(!op.isBos()) {
+ bosDone=true;
+ //System.out.println("bosDone=true;");
+ }
+ if(op.isEos()) {
+ eos=true;
+ }
+
+ LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
+ if(los==null) {
+ los=new LogicalOggStreamImpl(CachedUrlStream.this, op.getStreamSerialNumber());
+ logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
+ los.checkFormat(op);
+ }
+
+ los.addPageNumberMapping(pageNumber);
+ los.addGranulePosition(op.getAbsoluteGranulePosition());
+
+ pageNumber++;
+ cacheLength=op.getAbsoluteGranulePosition();
+ //System.out.println("read page: "+pageNumber);
+ }
+ }
+ catch(EndOfOggStreamException e) {
+ // ok
+ }
+ catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isBosDone() {
+ return bosDone;
+ }
+ }
+
+ public boolean isSeekable() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/EndOfOggStreamException.java b/src/main/java/de/jarnbjo/ogg/EndOfOggStreamException.java
new file mode 100644
index 0000000..19e67de
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/EndOfOggStreamException.java
@@ -0,0 +1,35 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: EndOfOggStreamException.java,v 1.1 2003/03/03 21:02:20 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: EndOfOggStreamException.java,v $
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+ package de.jarnbjo.ogg;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when reaching the end of an Ogg stream
+ */
+
+public class EndOfOggStreamException extends IOException {
+
+ public EndOfOggStreamException() {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/FileStream.java b/src/main/java/de/jarnbjo/ogg/FileStream.java
new file mode 100644
index 0000000..7d21c1e
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/FileStream.java
@@ -0,0 +1,148 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: FileStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: FileStream.java,v $
+ * Revision 1.1 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Implementation of the PhysicalOggStream
interface for accessing
+ * normal disk files.
+ */
+
+public class FileStream implements PhysicalOggStream {
+
+ private boolean closed=false;
+ private RandomAccessFile source;
+ private long[] pageOffsets;
+ private long numberOfSamples=-1;
+
+ private HashMap logicalStreams=new HashMap();
+
+ /**
+ * Creates access to the specified file through the PhysicalOggStream
interface.
+ * The specified source file must have been opened for reading.
+ *
+ * @param source the file to read from
+ *
+ * @throws OggFormatException if the stream format is incorrect
+ * @throws IOException if some other IO error occurs when reading the file
+ */
+
+ public FileStream(RandomAccessFile source) throws OggFormatException, IOException {
+ this.source=source;
+
+ ArrayList po=new ArrayList();
+ int pageNumber=0;
+ try {
+ while(true) {
+ po.add(new Long(this.source.getFilePointer()));
+
+ // skip data if pageNumber>0
+ OggPage op=getNextPage(pageNumber>0);
+ if(op==null) {
+ break;
+ }
+
+ LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
+ if(los==null) {
+ los=new LogicalOggStreamImpl(this, op.getStreamSerialNumber());
+ logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
+ }
+
+ if(pageNumber==0) {
+ los.checkFormat(op);
+ }
+
+ los.addPageNumberMapping(pageNumber);
+ los.addGranulePosition(op.getAbsoluteGranulePosition());
+
+ if(pageNumber>0) {
+ this.source.seek(this.source.getFilePointer()+op.getTotalLength());
+ }
+
+ pageNumber++;
+ }
+ }
+ catch(EndOfOggStreamException e) {
+ // ok
+ }
+ catch(IOException e) {
+ throw e;
+ }
+ //System.out.println("pageNumber: "+pageNumber);
+ this.source.seek(0L);
+ pageOffsets=new long[po.size()];
+ int i=0;
+ Iterator iter=po.iterator();
+ while(iter.hasNext()) {
+ pageOffsets[i++]=((Long)iter.next()).longValue();
+ }
+ }
+
+ public Collection getLogicalStreams() {
+ return logicalStreams.values();
+ }
+
+ public boolean isOpen() {
+ return !closed;
+ }
+
+ public void close() throws IOException {
+ closed=true;
+ source.close();
+ }
+
+ private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
+ return getNextPage(false);
+ }
+
+ private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
+ return OggPage.create(source, skipData);
+ }
+
+ public OggPage getOggPage(int index) throws IOException {
+ source.seek(pageOffsets[index]);
+ return OggPage.create(source);
+ }
+
+ private LogicalOggStream getLogicalStream(int serialNumber) {
+ return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
+ }
+
+ public void setTime(long granulePosition) throws IOException {
+ for(Iterator iter=logicalStreams.values().iterator(); iter.hasNext(); ) {
+ LogicalOggStream los=(LogicalOggStream)iter.next();
+ los.setTime(granulePosition);
+ }
+ }
+
+ /**
+ * @return always true
+ */
+
+ public boolean isSeekable() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/LogicalOggStream.java b/src/main/java/de/jarnbjo/ogg/LogicalOggStream.java
new file mode 100644
index 0000000..98f1f6d
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/LogicalOggStream.java
@@ -0,0 +1,145 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: LogicalOggStream.java,v 1.2 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: LogicalOggStream.java,v $
+ * Revision 1.2 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.IOException;
+
+/**
+ * Interface providing access to a logical Ogg stream as part of a
+ * physical Ogg stream.
+ */
+
+
+public interface LogicalOggStream {
+
+ public static final String FORMAT_UNKNOWN = "application/octet-stream";
+
+ public static final String FORMAT_VORBIS = "audio/x-vorbis";
+ public static final String FORMAT_FLAC = "audio/x-flac";
+ public static final String FORMAT_THEORA = "video/x-theora";
+
+ /**
+ * Note: To read from the stream, you must use either
+ * this method or the method getNextOggPacket
.
+ * Mixing calls to the two methods will cause data corruption.
+ *
+ * @return the next Ogg page
+ *
+ * @see #getNextOggPacket()
+ *
+ * @throws OggFormatException if the ogg stream is corrupted
+ * @throws IOException if some other IO error occurs
+ */
+
+ public OggPage getNextOggPage() throws OggFormatException, IOException;
+
+ /**
+ * Note: To read from the stream, you must use either
+ * this method or the method getNextOggPage
.
+ * Mixing calls to the two methods will cause data corruption.
+ *
+ * @return the next packet as a byte array
+ *
+ * @see #getNextOggPage()
+ *
+ * @throws OggFormatException if the ogg stream is corrupted
+ * @throws IOException if some other IO error occurs
+ */
+
+ public byte[] getNextOggPacket() throws OggFormatException, IOException;
+
+ /**
+ * Checks if this stream is open for reading.
+ *
+ * @return true
if this stream is open for reading,
+ * false
otherwise
+ */
+
+ public boolean isOpen();
+
+ /**
+ * Closes this stream. After invoking this method, no further access
+ * to the streams data is possible.
+ *
+ * @throws IOException if an IO error occurs
+ */
+
+ public void close() throws IOException;
+
+ /**
+ * Sets the stream's position to the beginning of the stream.
+ * This method does not work if the physical Ogg stream is not
+ * seekable.
+ *
+ * @throws OggFormatException if the ogg stream is corrupted
+ * @throws IOException if some other IO error occurs
+ */
+
+ public void reset() throws OggFormatException, IOException;
+
+ /**
+ * This method does not work if the physical Ogg stream is not
+ * seekable.
+ *
+ * @return the granule position of the last page within
+ * this stream
+ */
+
+ public long getMaximumGranulePosition();
+
+ /**
+ * This method is invoked on all logical streams when
+ * calling the same method on the physical stream. The
+ * same restrictions as mentioned there apply.
+ * This method does not work if the physical Ogg stream is not
+ * seekable.
+ *
+ * @param granulePosition
+ *
+ * @see PhysicalOggStream#setTime(long)
+ *
+ * @throws IOException if an IO error occurs
+ */
+
+ public void setTime(long granulePosition) throws IOException;
+
+ /**
+ * @return the last parsed granule position of this stream
+ */
+
+ public long getTime();
+
+ /**
+ * @return the content type of this stream
+ *
+ * @see #FORMAT_UNKNOWN
+ * @see #FORMAT_VORBIS
+ * @see #FORMAT_FLAC
+ * @see #FORMAT_THEORA
+ */
+
+ public String getFormat();
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/LogicalOggStreamImpl.java b/src/main/java/de/jarnbjo/ogg/LogicalOggStreamImpl.java
new file mode 100644
index 0000000..f898f48
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/LogicalOggStreamImpl.java
@@ -0,0 +1,207 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: LogicalOggStreamImpl.java,v 1.3 2003/03/31 00:23:04 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: LogicalOggStreamImpl.java,v $
+ * Revision 1.3 2003/03/31 00:23:04 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:26 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+import java.util.*;
+
+public class LogicalOggStreamImpl implements LogicalOggStream {
+
+ private PhysicalOggStream source;
+ private int serialNumber;
+
+ private ArrayList pageNumberMapping=new ArrayList();
+ private ArrayList granulePositions=new ArrayList();
+
+ private int pageIndex=0;
+ private OggPage currentPage;
+ private int currentSegmentIndex;
+
+ private boolean open=true;
+
+ private String format=FORMAT_UNKNOWN;
+
+ public LogicalOggStreamImpl(PhysicalOggStream source, int serialNumber) {
+ this.source=source;
+ this.serialNumber=serialNumber;
+ }
+
+ public void addPageNumberMapping(int physicalPageNumber) {
+ pageNumberMapping.add(new Integer(physicalPageNumber));
+ }
+
+ public void addGranulePosition(long granulePosition) {
+ granulePositions.add(new Long(granulePosition));
+ }
+
+ public synchronized void reset() throws OggFormatException, IOException {
+ currentPage=null;
+ currentSegmentIndex=0;
+ pageIndex=0;
+ }
+
+ public synchronized OggPage getNextOggPage() throws EndOfOggStreamException, OggFormatException, IOException {
+ if(source.isSeekable()) {
+ currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
+ }
+ else {
+ currentPage=source.getOggPage(-1);
+ }
+ return currentPage;
+ }
+
+ public synchronized byte[] getNextOggPacket() throws EndOfOggStreamException, OggFormatException, IOException {
+ ByteArrayOutputStream res=new ByteArrayOutputStream();
+ int segmentLength=0;
+
+ if(currentPage==null) {
+ currentPage=getNextOggPage();
+ }
+
+ do {
+ if(currentSegmentIndex>=currentPage.getSegmentOffsets().length) {
+ currentSegmentIndex=0;
+
+ if(!currentPage.isEos()) {
+ if(source.isSeekable() && pageNumberMapping.size()<=pageIndex) {
+ while(pageNumberMapping.size()<=pageIndex+10) {
+ try {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException ex) {
+ }
+ }
+ }
+ currentPage=getNextOggPage();
+
+ if(res.size()==0 && currentPage.isContinued()) {
+ boolean done=false;
+ while(!done) {
+ if(currentPage.getSegmentLengths()[currentSegmentIndex++]!=255) {
+ done=true;
+ }
+ if(currentSegmentIndex>currentPage.getSegmentTable().length) {
+ currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
+ }
+ }
+ }
+ }
+ else {
+ throw new EndOfOggStreamException();
+ }
+ }
+ segmentLength=currentPage.getSegmentLengths()[currentSegmentIndex];
+ res.write(currentPage.getData(), currentPage.getSegmentOffsets()[currentSegmentIndex], segmentLength);
+ currentSegmentIndex++;
+ } while(segmentLength==255);
+
+ return res.toByteArray();
+ }
+
+ public boolean isOpen() {
+ return open;
+ }
+
+ public void close() throws IOException {
+ open=false;
+ }
+
+ public long getMaximumGranulePosition() {
+ Long mgp=(Long)granulePositions.get(granulePositions.size()-1);
+ return mgp.longValue();
+ }
+
+ public synchronized long getTime() {
+ return currentPage!=null?currentPage.getAbsoluteGranulePosition():-1;
+ }
+
+ public synchronized void setTime(long granulePosition) throws IOException {
+
+ int page=0;
+ for(page=0; pagegranulePosition) {
+ break;
+ }
+ }
+
+ pageIndex=page;
+ currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
+ currentSegmentIndex=0;
+ int segmentLength=0;
+ do {
+ if(currentSegmentIndex>=currentPage.getSegmentOffsets().length) {
+ currentSegmentIndex=0;
+ if(pageIndex>=pageNumberMapping.size()) {
+ throw new EndOfOggStreamException();
+ }
+ currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
+ }
+ segmentLength=currentPage.getSegmentLengths()[currentSegmentIndex];
+ currentSegmentIndex++;
+ } while(segmentLength==255);
+ }
+
+ public void checkFormat(OggPage page) {
+ byte[] data=page.getData();
+
+ if(data.length>=7 &&
+ data[1]==0x76 &&
+ data[2]==0x6f &&
+ data[3]==0x72 &&
+ data[4]==0x62 &&
+ data[5]==0x69 &&
+ data[6]==0x73) {
+
+ format=FORMAT_VORBIS;
+ }
+ else if(data.length>=7 &&
+ data[1]==0x74 &&
+ data[2]==0x68 &&
+ data[3]==0x65 &&
+ data[4]==0x6f &&
+ data[5]==0x72 &&
+ data[6]==0x61) {
+
+ format=FORMAT_THEORA;
+ }
+ else if (data.length==4 &&
+ data[0]==0x66 &&
+ data[1]==0x4c &&
+ data[2]==0x61 &&
+ data[3]==0x43) {
+
+ format=FORMAT_FLAC;
+ }
+ }
+
+ public String getFormat() {
+ return format;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/OggFormatException.java b/src/main/java/de/jarnbjo/ogg/OggFormatException.java
new file mode 100644
index 0000000..055f146
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/OggFormatException.java
@@ -0,0 +1,40 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: OggFormatException.java,v 1.1 2003/03/03 21:02:20 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: OggFormatException.java,v $
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when trying to read a corrupted Ogg stream.
+ */
+
+public class OggFormatException extends IOException {
+
+ public OggFormatException() {
+ super();
+ }
+
+ public OggFormatException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/OggPage.java b/src/main/java/de/jarnbjo/ogg/OggPage.java
new file mode 100644
index 0000000..af9a32f
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/OggPage.java
@@ -0,0 +1,425 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: OggPage.java,v 1.3 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: OggPage.java,v $
+ * Revision 1.3 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/31 00:23:04 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+
+import de.jarnbjo.util.io.*;
+
+/**
+ * An instance of this class represents an ogg page read from an ogg file
+ * or network stream. It has no public constructor, but instances can be
+ * created by the create
methods, supplying a JMF stream or
+ * a RandomAccessFile
+ * which is positioned at the beginning of an Ogg page.
+ *
+ * Furtheron, the class provides methods for accessing the raw page data,
+ * as well as data attributes like segmenting information, sequence number,
+ * stream serial number, chechsum and wether this page is the beginning or
+ * end of a logical bitstream (BOS, EOS) and if the page data starts with a
+ * continued packet or a fresh data packet.
+ */
+
+public class OggPage {
+
+ private int version;
+ private boolean continued, bos, eos;
+ private long absoluteGranulePosition;
+ private int streamSerialNumber, pageSequenceNumber, pageCheckSum;
+ private int[] segmentOffsets;
+ private int[] segmentLengths;
+ private int totalLength;
+ private byte[] header, segmentTable, data;
+
+ protected OggPage() {
+ }
+
+ private OggPage(
+ int version,
+ boolean continued,
+ boolean bos,
+ boolean eos,
+ long absoluteGranulePosition,
+ int streamSerialNumber,
+ int pageSequenceNumber,
+ int pageCheckSum,
+ int[] segmentOffsets,
+ int[] segmentLengths,
+ int totalLength,
+ byte[] header,
+ byte[] segmentTable,
+ byte[] data) {
+
+ this.version=version;
+ this.continued=continued;
+ this.bos=bos;
+ this.eos=eos;
+ this.absoluteGranulePosition=absoluteGranulePosition;
+ this.streamSerialNumber=streamSerialNumber;
+ this.pageSequenceNumber=pageSequenceNumber;
+ this.pageCheckSum=pageCheckSum;
+ this.segmentOffsets=segmentOffsets;
+ this.segmentLengths=segmentLengths;
+ this.totalLength=totalLength;
+ this.header=header;
+ this.segmentTable=segmentTable;
+ this.data=data;
+ }
+
+ /**
+ * this method equals to create(RandomAccessFile source, false)
+ *
+ * @see #create(RandomAccessFile, boolean)
+ */
+
+ public static OggPage create(RandomAccessFile source) throws IOException, EndOfOggStreamException, OggFormatException {
+ return create(source, false);
+ }
+
+ /**
+ * This method is called to read data from the current position in the
+ * specified RandomAccessFile and create a new OggPage instance based on the data
+ * read. If the parameter skipData
is set to true
,
+ * the actual page segments (page data) is skipped and not read into
+ * memory. This mode is useful when scanning through an ogg file to build
+ * a seek table.
+ *
+ * @param source the source from which the ogg page is generated
+ * @param skipData if set to true
, the actual page data is not read into memory
+ * @return an ogg page created by reading data from the specified source, starting at the current position
+ * @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
+ * @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
+ * @throws IOException if some other I/O error is detected when reading from the source
+ *
+ * @see #create(RandomAccessFile)
+ */
+
+ public static OggPage create(RandomAccessFile source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
+ return create((Object)source, skipData);
+ }
+
+ /**
+ * this method equals to create(InputStream source, false)
+ *
+ * @see #create(InputStream, boolean)
+ */
+
+ public static OggPage create(InputStream source) throws IOException, EndOfOggStreamException, OggFormatException {
+ return create(source, false);
+ }
+
+ /**
+ * This method is called to read data from the current position in the
+ * specified InpuStream and create a new OggPage instance based on the data
+ * read. If the parameter skipData
is set to true
,
+ * the actual page segments (page data) is skipped and not read into
+ * memory. This mode is useful when scanning through an ogg file to build
+ * a seek table.
+ *
+ * @param source the source from which the ogg page is generated
+ * @param skipData if set to true
, the actual page data is not read into memory
+ * @return an ogg page created by reading data from the specified source, starting at the current position
+ * @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
+ * @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
+ * @throws IOException if some other I/O error is detected when reading from the source
+ *
+ * @see #create(InputStream)
+ */
+
+ public static OggPage create(InputStream source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
+ return create((Object)source, skipData);
+ }
+
+ /**
+ * this method equals to create(byte[] source, false)
+ *
+ * @see #create(byte[], boolean)
+ */
+
+ public static OggPage create(byte[] source) throws IOException, EndOfOggStreamException, OggFormatException {
+ return create(source, false);
+ }
+
+ /**
+ * This method is called to
+ * create a new OggPage instance based on the specified byte array.
+ *
+ * @param source the source from which the ogg page is generated
+ * @param skipData if set to true
, the actual page data is not read into memory
+ * @return an ogg page created by reading data from the specified source, starting at the current position
+ * @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
+ * @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
+ * @throws IOException if some other I/O error is detected when reading from the source
+ *
+ * @see #create(byte[])
+ */
+
+ public static OggPage create(byte[] source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
+ return create((Object)source, skipData);
+ }
+
+ private static OggPage create(Object source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
+
+ try {
+ int sourceOffset=27;
+
+ byte[] header=new byte[27];
+ if(source instanceof RandomAccessFile) {
+ RandomAccessFile raf=(RandomAccessFile)source;
+ if(raf.getFilePointer()==raf.length()) {
+ return null;
+ }
+ raf.readFully(header);
+ }
+ else if(source instanceof InputStream) {
+ readFully((InputStream)source, header);
+ }
+ else if(source instanceof byte[]) {
+ System.arraycopy((byte[])source, 0, header, 0, 27);
+ }
+
+ BitInputStream bdSource=new ByteArrayBitInputStream(header);
+
+ int capture=bdSource.getInt(32);
+
+ if(capture!=0x5367674f) {
+ //throw new FormatException("Ogg page does not start with 'OggS' (0x4f676753)");
+
+ /*
+ ** This condition is IMHO an error, but older Ogg files often contain
+ ** pages with a different capture than OggS. I am not sure how to
+ ** manage these pages, but the decoder seems to work properly, if
+ ** the incorrect capture is simply ignored.
+ */
+
+ String cs=Integer.toHexString(capture);
+ while(cs.length()<8) {
+ cs="0"+cs;
+ }
+ cs=cs.substring(6, 8)+cs.substring(4, 6)+cs.substring(2, 4)+cs.substring(0, 2);
+ char c1=(char)(Integer.valueOf(cs.substring(0, 2), 16).intValue());
+ char c2=(char)(Integer.valueOf(cs.substring(2, 4), 16).intValue());
+ char c3=(char)(Integer.valueOf(cs.substring(4, 6), 16).intValue());
+ char c4=(char)(Integer.valueOf(cs.substring(6, 8), 16).intValue());
+ System.out.println("Ogg packet header is 0x"+cs+" ("+c1+c2+c3+c4+"), should be 0x4f676753 (OggS)");
+ }
+
+ int version=bdSource.getInt(8);
+ byte tmp=(byte)bdSource.getInt(8);
+ boolean bf1=(tmp&1)!=0;
+ boolean bos=(tmp&2)!=0;
+ boolean eos=(tmp&4)!=0;
+ long absoluteGranulePosition=bdSource.getLong(64);
+ int streamSerialNumber=bdSource.getInt(32);
+ int pageSequenceNumber=bdSource.getInt(32);
+ int pageCheckSum=bdSource.getInt(32);
+ int pageSegments=bdSource.getInt(8);
+
+ //System.out.println("OggPage: "+streamSerialNumber+" / "+absoluteGranulePosition+" / "+pageSequenceNumber);
+
+ int[] segmentOffsets=new int[pageSegments];
+ int[] segmentLengths=new int[pageSegments];
+ int totalLength=0;
+
+ byte[] segmentTable=new byte[pageSegments];
+ byte[] tmpBuf=new byte[1];
+
+ for(int i=0; itrue if this page begins with a continued packet
+ */
+
+ public boolean isContinued() {
+ return continued;
+ }
+
+ /**
+ * @return true
if this page begins with a fresh packet
+ */
+
+ public boolean isFresh() {
+ return !continued;
+ }
+
+ /**
+ * @return true
if this page is the beginning of a logical stream
+ */
+
+ public boolean isBos() {
+ return bos;
+ }
+
+ /**
+ * @return true
if this page is the end of a logical stream
+ */
+
+ public boolean isEos() {
+ return eos;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/OnDemandUrlStream.java b/src/main/java/de/jarnbjo/ogg/OnDemandUrlStream.java
new file mode 100644
index 0000000..c57ddf2
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/OnDemandUrlStream.java
@@ -0,0 +1,121 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: OnDemandUrlStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: OnDemandUrlStream.java,v $
+ * Revision 1.1 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/31 00:23:04 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * Implementation of the PhysicalOggStream
interface for reading
+ * an Ogg stream from a URL. This class performs
+ * no internal caching, and will not read data from the network before
+ * requested to do so. It is intended to be used in non-realtime applications
+ * like file download managers or similar.
+ */
+
+public class OnDemandUrlStream implements PhysicalOggStream {
+
+ private boolean closed=false;
+ private URLConnection source;
+ private InputStream sourceStream;
+ private Object drainLock=new Object();
+ private LinkedList pageCache=new LinkedList();
+ private long numberOfSamples=-1;
+ private int contentLength=0;
+ private int position=0;
+
+ private HashMap logicalStreams=new HashMap();
+ private OggPage firstPage;
+
+ private static final int PAGECACHE_SIZE = 20;
+
+ public OnDemandUrlStream(URL source) throws OggFormatException, IOException {
+ this.source=source.openConnection();
+ this.sourceStream=this.source.getInputStream();
+
+ contentLength=this.source.getContentLength();
+
+ firstPage=OggPage.create(sourceStream);
+ position+=firstPage.getTotalLength();
+ LogicalOggStreamImpl los=new LogicalOggStreamImpl(this, firstPage.getStreamSerialNumber());
+ logicalStreams.put(new Integer(firstPage.getStreamSerialNumber()), los);
+ los.checkFormat(firstPage);
+ }
+
+ public Collection getLogicalStreams() {
+ return logicalStreams.values();
+ }
+
+ public boolean isOpen() {
+ return !closed;
+ }
+
+ public void close() throws IOException {
+ closed=true;
+ sourceStream.close();
+ }
+
+ public int getContentLength() {
+ return contentLength;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ int pageNumber=2;
+
+ public OggPage getOggPage(int index) throws IOException {
+ if(firstPage!=null) {
+ OggPage tmp=firstPage;
+ firstPage=null;
+ return tmp;
+ }
+ else {
+ OggPage page=OggPage.create(sourceStream);
+ position+=page.getTotalLength();
+ return page;
+ }
+ }
+
+ private LogicalOggStream getLogicalStream(int serialNumber) {
+ return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
+ }
+
+ public void setTime(long granulePosition) throws IOException {
+ throw new UnsupportedOperationException("Method not supported by this class");
+ }
+
+ /**
+ * @return always false
+ */
+
+ public boolean isSeekable() {
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/PhysicalOggStream.java b/src/main/java/de/jarnbjo/ogg/PhysicalOggStream.java
new file mode 100644
index 0000000..698d09a
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/PhysicalOggStream.java
@@ -0,0 +1,118 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: PhysicalOggStream.java,v 1.3 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: PhysicalOggStream.java,v $
+ * Revision 1.3 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/31 00:23:04 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Interface providing access to a physical Ogg stream. Typically this is
+ * a file.
+ */
+
+public interface PhysicalOggStream {
+
+ /**
+ * Returns a collection of objects implementing LogicalOggStream
+ * for accessing the separate logical streams within this physical Ogg stream.
+ *
+ * @return a collection of objects implementing LogicalOggStream
+ * which are representing the logical streams contained within this
+ * physical stream
+ *
+ * @see LogicalOggStream
+ */
+
+ public Collection getLogicalStreams();
+
+ /**
+ * Return the Ogg page with the absolute index index
,
+ * independent from the logical structure of this stream or if the
+ * index parameter is -1, the next Ogg page is returned.
+ * This method should only be used by implementations of LogicalOggStream
+ * to access the raw pages.
+ *
+ * @param index the absolute index starting from 0 at the beginning of
+ * the file or stream or -1 to get the next page in a non-seekable
+ * stream
+ *
+ * @return the Ogg page with the physical absolute index index
+ *
+ * @throws OggFormatException if the ogg stream is corrupted
+ * @throws IOException if some other IO error occurs
+ */
+
+ public OggPage getOggPage(int index) throws OggFormatException, IOException;
+
+ /**
+ * Checks if this stream is open for reading.
+ *
+ * @return true
if this stream is open for reading,
+ * false
otherwise
+ */
+
+ public boolean isOpen();
+
+ /**
+ * Closes this stream. After invoking this method, no further access
+ * to the streams data is possible.
+ *
+ * @throws IOException
+ */
+
+ public void close() throws IOException;
+
+ /**
+ * Sets this stream's (and its logical stream's) position to the granule
+ * position. The next packet read from any logical stream will be the
+ * first packet beginning on the first page with a granule position higher
+ * than the argument.
+ *
+ * At the moment, this method only works correctly for Ogg files with
+ * a single logical Vorbis stream, and due to the different interpretations
+ * of the granule position, depending on mixed content, this method will
+ * never be able to work for mixed streams. Chained and interleaved streams are
+ * also not yet supported. Actually, this method is only a hack to support
+ * seeking from JMF, but may of course be abused otherwise too :)
+ *
+ * @param granulePosition
+ *
+ * @throws OggFormatException if the ogg stream is corrupted
+ * @throws IOException if some other IO error occurs
+ */
+
+ public void setTime(long granulePosition) throws OggFormatException, IOException;
+
+ /**
+ * @return true
if the stream is seekable, false
+ * otherwise
+ */
+
+ public boolean isSeekable();
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/ogg/UncachedUrlStream.java b/src/main/java/de/jarnbjo/ogg/UncachedUrlStream.java
new file mode 100644
index 0000000..6ecffa6
--- /dev/null
+++ b/src/main/java/de/jarnbjo/ogg/UncachedUrlStream.java
@@ -0,0 +1,201 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: UncachedUrlStream.java,v 1.1 2003/04/10 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: UncachedUrlStream.java,v $
+ * Revision 1.1 2003/04/10 19:48:22 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.ogg;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * Implementation of the PhysicalOggStream
interface for reading
+ * an Ogg stream from a URL. This class performs only the necessary caching
+ * to provide continous playback. Seeking within the stream is not supported.
+ */
+
+public class UncachedUrlStream implements PhysicalOggStream {
+
+ private boolean closed=false;
+ private URLConnection source;
+ private InputStream sourceStream;
+ private Object drainLock=new Object();
+ private LinkedList pageCache=new LinkedList();
+ private long numberOfSamples=-1;
+
+ private HashMap logicalStreams=new HashMap();
+
+ private LoaderThread loaderThread;
+
+ private static final int PAGECACHE_SIZE = 10;
+
+ /** Creates an instance of the PhysicalOggStream
interface
+ * suitable for reading an Ogg stream from a URL.
+ */
+
+ public UncachedUrlStream(URL source) throws OggFormatException, IOException {
+
+ this.source=source.openConnection();
+ this.sourceStream=this.source.getInputStream();
+
+ loaderThread=new LoaderThread(sourceStream, pageCache);
+ new Thread(loaderThread).start();
+
+ while(!loaderThread.isBosDone() || pageCache.size()PAGECACHE_SIZE) {
+ try {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+ catch(EndOfOggStreamException e) {
+ // ok
+ }
+ catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isBosDone() {
+ return bosDone;
+ }
+ }
+
+ /**
+ * @return always false
+ */
+
+ public boolean isSeekable() {
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/util/audio/FadeableAudioInputStream.java b/src/main/java/de/jarnbjo/util/audio/FadeableAudioInputStream.java
new file mode 100644
index 0000000..4916102
--- /dev/null
+++ b/src/main/java/de/jarnbjo/util/audio/FadeableAudioInputStream.java
@@ -0,0 +1,62 @@
+package de.jarnbjo.util.audio;
+
+import java.io.*;
+import javax.sound.sampled.*;
+
+public class FadeableAudioInputStream extends AudioInputStream {
+
+ private AudioInputStream stream;
+ private boolean fading=false;
+ private double phi=0.0;
+
+ public FadeableAudioInputStream(AudioInputStream stream) throws IOException {
+ super(stream, stream.getFormat(), -1L);
+ }
+
+ public void fadeOut() {
+ fading=true;
+ phi=0.0;
+ }
+
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ public int read(byte[] b, int offset, int length) throws IOException {
+ int read=super.read(b, offset, length);
+
+ //System.out.println("read "+read);
+
+ if(fading) {
+ int j=0, l=0, r=0;
+ double gain=0.0;
+
+ for(int i=offset; i>8)&0xff);
+ b[j++]=(byte)(r&0xff);
+ b[j++]=(byte)((r>>8)&0xff);
+ }
+ }
+
+ return read;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/util/io/BitInputStream.java b/src/main/java/de/jarnbjo/util/io/BitInputStream.java
new file mode 100644
index 0000000..1f31092
--- /dev/null
+++ b/src/main/java/de/jarnbjo/util/io/BitInputStream.java
@@ -0,0 +1,179 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: BitInputStream.java,v 1.5 2003/04/10 19:48:31 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: BitInputStream.java,v $
+ * Revision 1.5 2003/04/10 19:48:31 jarnbjo
+ * no message
+ *
+ * Revision 1.4 2003/03/16 20:57:06 jarnbjo
+ * no message
+ *
+ * Revision 1.3 2003/03/16 20:56:56 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:39 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.util.io;
+
+import java.io.IOException;
+
+/**
+ * An interface with methods allowing bit-wise reading from
+ * an input stream. All methods in this interface are optional
+ * and an implementation not support a method or a specific state
+ * (e.g. endian) will throw an UnspportedOperationException if
+ * such a method is being called. This should be speicified in
+ * the implementation documentation.
+ */
+
+public interface BitInputStream {
+
+ /**
+ * constant for setting this stream's mode to little endian
+ *
+ * @see #setEndian(int)
+ */
+
+ public static final int LITTLE_ENDIAN = 0;
+
+ /**
+ * constant for setting this stream's mode to big endian
+ *
+ * @see #setEndian(int)
+ */
+
+ public static final int BIG_ENDIAN = 1;
+
+ /**
+ * reads one bit (as a boolean) from the input stream
+ *
+ * @return true
if the next bit is 1,
+ * false
otherwise
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public boolean getBit() throws IOException;
+
+ /**
+ * reads bits
number of bits from the input
+ * stream
+ *
+ * @return the unsigned integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public int getInt(int bits) throws IOException;
+
+ /**
+ * reads bits
number of bits from the input
+ * stream
+ *
+ * @return the signed integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public int getSignedInt(int bits) throws IOException;
+
+ /**
+ * reads a huffman codeword based on the root
+ * parameter and returns the decoded value
+ *
+ * @param root the root of the Huffman tree used to decode the codeword
+ * @return the decoded unsigned integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public int getInt(HuffmanNode root) throws IOException;
+
+ /**
+ * reads an integer encoded as "signed rice" as described in
+ * the FLAC audio format specification
+ *
+ * @param order
+ * @return the decoded integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public int readSignedRice(int order) throws IOException;
+
+ /**
+ * fills the array from offset
with len
+ * integers encoded as "signed rice" as described in
+ * the FLAC audio format specification
+ *
+ * @param order
+ * @param buffer
+ * @param offset
+ * @param len
+ * @return the decoded integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public void readSignedRice(int order, int[] buffer, int offset, int len) throws IOException;
+
+ /**
+ * reads bits
number of bits from the input
+ * stream
+ *
+ * @return the unsigned long value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public long getLong(int bits) throws IOException;
+
+ /**
+ * causes the read pointer to be moved to the beginning
+ * of the next byte, remaining bits in the current byte
+ * are discarded
+ *
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public void align();
+
+ /**
+ * changes the endian mode used when reading bit-wise from
+ * the stream, changing the mode mid-stream will cause the
+ * read cursor to move to the beginning of the next byte
+ * (as if calling the allign
method
+ *
+ * @see #align()
+ *
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public void setEndian(int endian);
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/util/io/ByteArrayBitInputStream.java b/src/main/java/de/jarnbjo/util/io/ByteArrayBitInputStream.java
new file mode 100644
index 0000000..c62483f
--- /dev/null
+++ b/src/main/java/de/jarnbjo/util/io/ByteArrayBitInputStream.java
@@ -0,0 +1,346 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: ByteArrayBitInputStream.java,v 1.3 2003/04/10 19:48:31 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: ByteArrayBitInputStream.java,v $
+ * Revision 1.3 2003/04/10 19:48:31 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:39 jarnbjo
+ * no message
+ *
+ * Revision 1.1 2003/03/03 21:02:20 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.util.io;
+
+import java.io.IOException;
+
+/**
+ * Implementation of the BitInputStream
interface,
+ * using a byte array as data source.
+*/
+
+public class ByteArrayBitInputStream implements BitInputStream {
+
+ private byte[] source;
+ private byte currentByte;
+
+ private int endian;
+
+ private int byteIndex=0;
+ private int bitIndex=0;
+
+ public ByteArrayBitInputStream(byte[] source) {
+ this(source, LITTLE_ENDIAN);
+ }
+
+ public ByteArrayBitInputStream(byte[] source, int endian) {
+ this.endian=endian;
+ this.source=source;
+ currentByte=source[0];
+ bitIndex=(endian==LITTLE_ENDIAN)?0:7;
+ }
+
+ public boolean getBit() throws IOException {
+ if(endian==LITTLE_ENDIAN) {
+ if(bitIndex>7) {
+ bitIndex=0;
+ currentByte=source[++byteIndex];
+ }
+ return (currentByte&(1<<(bitIndex++)))!=0;
+ }
+ else {
+ if(bitIndex<0) {
+ bitIndex=7;
+ currentByte=source[++byteIndex];
+ }
+ return (currentByte&(1<<(bitIndex--)))!=0;
+ }
+ }
+
+ public int getInt(int bits) throws IOException {
+ if(bits>32) {
+ throw new IllegalArgumentException("Argument \"bits\" must be <= 32");
+ }
+ int res=0;
+ if(endian==LITTLE_ENDIAN) {
+ for(int i=0; i>offset;
+ bitIndex-=bits;
+ }
+ else {
+ res=(((int)currentByte)&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
+ bits-=bitIndex+1;
+ currentByte=source[++byteIndex];
+ while(bits>=8) {
+ bits-=8;
+ res|=(((int)source[byteIndex])&0xff)<0) {
+ int ci=((int)source[byteIndex])&0xff;
+ res|=(ci>>(8-bits))&((1<=1<<(bits-1)) {
+ raw-=1<7) {
+ bitIndex=0;
+ currentByte=source[++byteIndex];
+ }
+ root=(currentByte&(1<<(bitIndex++)))!=0?root.o1:root.o0;
+ }
+ return root.value.intValue();
+ }
+
+ public long getLong(int bits) throws IOException {
+ if(bits>64) {
+ throw new IllegalArgumentException("Argument \"bits\" must be <= 64");
+ }
+ long res=0;
+ if(endian==LITTLE_ENDIAN) {
+ for(int i=0; i=0; i--) {
+ if(getBit()) {
+ res|=(1L<reads an integer encoded as "signed rice" as described in
+ * the FLAC audio format specification
+ *
+ * not supported for little endian
+ *
+ * @param order
+ * @return the decoded integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public int readSignedRice(int order) throws IOException {
+
+ int msbs=-1, lsbs=0, res=0;
+
+ if(endian==LITTLE_ENDIAN) {
+ // little endian
+ throw new UnsupportedOperationException("ByteArrayBitInputStream.readSignedRice() is only supported in big endian mode");
+ }
+ else {
+ // big endian
+
+ byte cb=source[byteIndex];
+ do {
+ msbs++;
+ if(bitIndex<0) {
+ bitIndex=7;
+ byteIndex++;
+ cb=source[byteIndex];
+ }
+ } while((cb&(1<>offset;
+ bitIndex-=bits;
+ }
+ else {
+ lsbs=(((int)source[byteIndex])&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
+ bits-=bitIndex+1;
+ byteIndex++;
+ while(bits>=8) {
+ bits-=8;
+ lsbs|=(((int)source[byteIndex])&0xff)<0) {
+ int ci=((int)source[byteIndex])&0xff;
+ lsbs|=(ci>>(8-bits))&((1<>1)-1:(res>>1);
+ }
+
+ /**
+ * fills the array from offset
with len
+ * integers encoded as "signed rice" as described in
+ * the FLAC audio format specification
+ *
+ * not supported for little endian
+ *
+ * @param order
+ * @param buffer
+ * @param offset
+ * @param len
+ * @return the decoded integer value read from the stream
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnsupportedOperationException if the method is not supported by the implementation
+ */
+
+ public void readSignedRice(int order, int[] buffer, int off, int len) throws IOException {
+
+ if(endian==LITTLE_ENDIAN) {
+ // little endian
+ throw new UnsupportedOperationException("ByteArrayBitInputStream.readSignedRice() is only supported in big endian mode");
+ }
+ else {
+ // big endian
+ for(int i=off; i>offset;
+ bitIndex-=bits;
+ }
+ else {
+ lsbs=(((int)source[byteIndex])&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
+ bits-=bitIndex+1;
+ byteIndex++;
+ while(bits>=8) {
+ bits-=8;
+ lsbs|=(((int)source[byteIndex])&0xff)<0) {
+ int ci=((int)source[byteIndex])&0xff;
+ lsbs|=(ci>>(8-bits))&((1<>1)-1:(res>>1);
+ }
+ }
+ }
+
+ public void align() {
+ if(endian==BIG_ENDIAN && bitIndex>=0) {
+ bitIndex=7;
+ byteIndex++;
+ }
+ else if(endian==LITTLE_ENDIAN && bitIndex<=7) {
+ bitIndex=0;
+ byteIndex++;
+ }
+ }
+
+ public void setEndian(int endian) {
+ if(this.endian==BIG_ENDIAN && endian==LITTLE_ENDIAN) {
+ bitIndex=0;
+ byteIndex++;
+ }
+ else if(this.endian==LITTLE_ENDIAN && endian==BIG_ENDIAN) {
+ bitIndex=7;
+ byteIndex++;
+ }
+ this.endian=endian;
+ }
+
+ /**
+ * @return the byte array used as a source for this instance
+ */
+
+ public byte[] getSource() {
+ return source;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/util/io/HuffmanNode.java b/src/main/java/de/jarnbjo/util/io/HuffmanNode.java
new file mode 100644
index 0000000..9528a62
--- /dev/null
+++ b/src/main/java/de/jarnbjo/util/io/HuffmanNode.java
@@ -0,0 +1,138 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: HuffmanNode.java,v 1.2 2003/04/10 19:48:31 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: HuffmanNode.java,v $
+ * Revision 1.2 2003/04/10 19:48:31 jarnbjo
+ * no message
+ *
+ */
+
+package de.jarnbjo.util.io;
+
+import java.io.IOException;
+import de.jarnbjo.util.io.BitInputStream;
+
+/**
+ * Representation of a node in a Huffman tree, used to read
+ * Huffman compressed codewords from e.g. a Vorbis stream.
+ */
+
+final public class HuffmanNode {
+
+ private HuffmanNode parent;
+ private int depth=0;
+ protected HuffmanNode o0, o1;
+ protected Integer value;
+ private boolean full=false;
+
+ /**
+ * creates a new Huffman tree root node
+ */
+
+ public HuffmanNode() {
+ this(null);
+ }
+
+ protected HuffmanNode(HuffmanNode parent) {
+ this.parent=parent;
+ if(parent!=null) {
+ depth=parent.getDepth()+1;
+ }
+ }
+
+ protected HuffmanNode(HuffmanNode parent, int value) {
+ this(parent);
+ this.value=new Integer(value);
+ full=true;
+ }
+
+ protected int read(BitInputStream bis) throws IOException {
+ HuffmanNode iter=this;
+ while(iter.value==null) {
+ iter=bis.getBit()?iter.o1:iter.o0;
+ }
+ return iter.value.intValue();
+ }
+
+ protected HuffmanNode get0() {
+ return o0==null?set0(new HuffmanNode(this)):o0;
+ }
+
+ protected HuffmanNode get1() {
+ return o1==null?set1(new HuffmanNode(this)):o1;
+ }
+
+ protected Integer getValue() {
+ return value;
+ }
+
+ private HuffmanNode getParent() {
+ return parent;
+ }
+
+ protected int getDepth() {
+ return depth;
+ }
+
+ private boolean isFull() {
+ return full?true:(full=o0!=null&&o0.isFull()&&o1!=null&&o1.isFull());
+ }
+
+ private HuffmanNode set0(HuffmanNode value) {
+ return o0=value;
+ }
+
+ private HuffmanNode set1(HuffmanNode value) {
+ return o1=value;
+ }
+
+ private void setValue(Integer value) {
+ full=true;
+ this.value=value;
+ }
+
+ /**
+ * creates a new tree node at the first free location at the given
+ * depth, and assigns the value to it
+ *
+ * @param depth the tree depth of the new node (codeword length in bits)
+ * @param value the node's new value
+ */
+
+ public boolean setNewValue(int depth, int value) {
+ if(isFull()) {
+ return false;
+ }
+ if(depth==1) {
+ if(o0==null) {
+ set0(new HuffmanNode(this, value));
+ return true;
+ }
+ else if(o1==null) {
+ set1(new HuffmanNode(this, value));
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ return get0().setNewValue(depth-1, value)?
+ true:
+ get1().setNewValue(depth-1, value);
+ }
+ }
+}
diff --git a/src/main/java/de/jarnbjo/vorbis/AudioPacket.java b/src/main/java/de/jarnbjo/vorbis/AudioPacket.java
new file mode 100644
index 0000000..88e0c4d
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/AudioPacket.java
@@ -0,0 +1,320 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: AudioPacket.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: AudioPacket.java,v $
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+import java.util.*;
+
+import de.jarnbjo.util.io.*;
+
+class AudioPacket {
+
+ private int modeNumber;
+ private Mode mode;
+ private Mapping mapping;
+ private int n; // block size
+ private boolean blockFlag, previousWindowFlag, nextWindowFlag;
+
+ private int windowCenter, leftWindowStart, leftWindowEnd, leftN, rightWindowStart, rightWindowEnd, rightN;
+ private float[] window;
+ private float[][] pcm;
+ private int[][] pcmInt;
+
+ private Floor[] channelFloors;
+ private boolean[] noResidues;
+
+ private final static float[][] windows=new float[8][];
+
+ protected AudioPacket(final VorbisStream vorbis, final BitInputStream source) throws VorbisFormatException, IOException {
+
+ final SetupHeader sHeader=vorbis.getSetupHeader();
+ final IdentificationHeader iHeader=vorbis.getIdentificationHeader();
+ final Mode[] modes=sHeader.getModes();
+ final Mapping[] mappings=sHeader.getMappings();
+ final Residue[] residues=sHeader.getResidues();
+ final int channels=iHeader.getChannels();
+
+ if(source.getInt(1)!=0) {
+ throw new VorbisFormatException("Packet type mismatch when trying to create an audio packet.");
+ }
+
+ modeNumber=source.getInt(Util.ilog(modes.length-1));
+
+ try {
+ mode=modes[modeNumber];
+ }
+ catch(ArrayIndexOutOfBoundsException e) {
+ throw new VorbisFormatException("Reference to invalid mode in audio packet.");
+ }
+
+ mapping=mappings[mode.getMapping()];
+
+ final int[] magnitudes=mapping.getMagnitudes();
+ final int[] angles=mapping.getAngles();
+
+ blockFlag=mode.getBlockFlag();
+
+ final int blockSize0=iHeader.getBlockSize0();
+ final int blockSize1=iHeader.getBlockSize1();
+
+ n=blockFlag?blockSize1:blockSize0;
+
+ if(blockFlag) {
+ previousWindowFlag=source.getBit();
+ nextWindowFlag=source.getBit();
+ }
+
+ windowCenter=n/2;
+
+ if(blockFlag && !previousWindowFlag) {
+ leftWindowStart=n/4-blockSize0/4;
+ leftWindowEnd=n/4+blockSize0/4;
+ leftN=blockSize0/2;
+ }
+ else {
+ leftWindowStart=0;
+ leftWindowEnd=n/2;
+ leftN=windowCenter;
+ }
+
+ if(blockFlag && !nextWindowFlag) {
+ rightWindowStart=n*3/4-blockSize0/4;
+ rightWindowEnd=n*3/4+blockSize0/4;
+ rightN=blockSize0/2;
+ }
+ else {
+ rightWindowStart=windowCenter;
+ rightWindowEnd=n;
+ rightN=n/2;
+ }
+
+ window=getComputedWindow();//new double[n];
+
+ channelFloors=new Floor[channels];
+ noResidues=new boolean[channels];
+
+ pcm=new float[channels][n];
+ pcmInt=new int[channels][n];
+
+ boolean allFloorsEmpty=true;
+
+ for(int i=0; i=0; i--) {
+ double newA=0, newM=0;
+ final float[] magnitudeVector=pcm[magnitudes[i]];
+ final float[] angleVector=pcm[angles[i]];
+ for(int j=0; j0) {
+ //magnitudeVector[j]=m;
+ angleVector[j]=m>0?m-a:m+a;
+ }
+ else {
+ magnitudeVector[j]=m>0?m+a:m-a;
+ angleVector[j]=m;
+ }
+ }
+ }
+
+ for(int i=0; i32767) val=32767;
+ if(val<-32768) val=-32768;
+ target[j1++]=val;
+ }
+ }
+
+ // use System.arraycopy to copy the middle part (if any)
+ // of the window
+ if(leftWindowEnd+132767) val=32767;
+ if(val<-32768) val=-32768;
+ buffer[ix+(i*2)+1]=(byte)(val&0xff);
+ buffer[ix+(i*2)]=(byte)((val>>8)&0xff);
+ ix+=channels*2;
+ }
+
+ ix=(leftWindowEnd-leftWindowStart)*channels*2;
+ for(int j=leftWindowEnd; j32767) val=32767;
+ if(val<-32768) val=-32768;
+ buffer[ix+(i*2)+1]=(byte)(val&0xff);
+ buffer[ix+(i*2)]=(byte)((val>>8)&0xff);
+ ix+=channels*2;
+ }
+ }
+ }
+
+ protected float[] getWindow() {
+ return window;
+ }
+
+ protected int getLeftWindowStart() {
+ return leftWindowStart;
+ }
+
+ protected int getLeftWindowEnd() {
+ return leftWindowEnd;
+ }
+
+ protected int getRightWindowStart() {
+ return rightWindowStart;
+ }
+
+ protected int getRightWindowEnd() {
+ return rightWindowEnd;
+ }
+
+ public int[][] getPcm() {
+ return pcmInt;
+ }
+
+ public float[][] getFreqencyDomain() {
+ return pcm;
+ }
+}
diff --git a/src/main/java/de/jarnbjo/vorbis/CodeBook.java b/src/main/java/de/jarnbjo/vorbis/CodeBook.java
new file mode 100644
index 0000000..46133f4
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/CodeBook.java
@@ -0,0 +1,267 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: CodeBook.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: CodeBook.java,v $
+ * Revision 1.3 2003/04/10 19:49:04 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.*;
+
+import java.text.*;
+import java.util.*;
+
+import de.jarnbjo.util.io.*;
+
+class CodeBook {
+
+ private HuffmanNode huffmanRoot;
+ private int dimensions, entries;
+
+ private int[] entryLengths;
+ private float[][] valueVector;
+
+ protected CodeBook(BitInputStream source) throws VorbisFormatException, IOException {
+
+ // check sync
+ if(source.getInt(24)!=0x564342) {
+ throw new VorbisFormatException("The code book sync pattern is not correct.");
+ }
+
+ dimensions=source.getInt(16);
+ entries=source.getInt(24);
+
+ entryLengths=new int[entries];
+
+ boolean ordered=source.getBit();
+
+ if(ordered) {
+ int cl=source.getInt(5)+1;
+ for(int i=0; ientryLengths.length) {
+ throw new VorbisFormatException("The codebook entry length list is longer than the actual number of entry lengths.");
+ }
+ Arrays.fill(entryLengths, i, i+num, cl);
+ cl++;
+ i+=num;
+ }
+ }
+ else {
+ // !ordered
+ boolean sparse=source.getBit();
+
+ if(sparse) {
+ for(int i=0; i0) {
+ if(!huffmanRoot.setNewValue(el, i)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ protected int getDimensions() {
+ return dimensions;
+ }
+
+ protected int getEntries() {
+ return entries;
+ }
+
+ protected HuffmanNode getHuffmanRoot() {
+ return huffmanRoot;
+ }
+
+ //public float[] readVQ(ReadableBitChannel source) throws IOException {
+ // return valueVector[readInt(source)];
+ //}
+
+ protected int readInt(final BitInputStream source) throws IOException {
+ return source.getInt(huffmanRoot);
+ /*
+ HuffmanNode node;
+ for(node=huffmanRoot; node.value==null; node=source.getBit()?node.o1:node.o0);
+ return node.value.intValue();
+ */
+ }
+
+ protected void readVvAdd(float[][] a, BitInputStream source, int offset, int length)
+ throws VorbisFormatException, IOException {
+
+ int i,j;//k;//entry;
+ int chptr=0;
+ int ch=a.length;
+
+ if(ch==0) {
+ return;
+ }
+
+ int lim=(offset+length)/ch;
+
+ for(i=offset/ch;i8){
+ for(i=0;iheader.getCodeBooks().length) {
+ throw new VorbisFormatException("A floor0_book_list entry is higher than the code book count.");
+ }
+ }
+ }
+
+ protected int getType() {
+ return 0;
+ }
+
+ protected Floor decodeFloor(VorbisStream vorbis, BitInputStream source) throws VorbisFormatException, IOException {
+ /** @todo implement */
+ throw new UnsupportedOperationException();
+ }
+
+ protected void computeFloor(float[] vector) {
+ /** @todo implement */
+ throw new UnsupportedOperationException();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/Floor1.java b/src/main/java/de/jarnbjo/vorbis/Floor1.java
new file mode 100644
index 0000000..b95f6d9
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/Floor1.java
@@ -0,0 +1,318 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: Floor1.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $multip
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: Floor1.java,v $
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+import java.util.*;
+
+import de.jarnbjo.util.io.BitInputStream;
+
+
+class Floor1 extends Floor implements Cloneable {
+
+ private int[] partitionClassList;
+ private int maximumClass, multiplier, rangeBits;
+ private int[] classDimensions;
+ private int[] classSubclasses;
+ private int[] classMasterbooks;
+ private int[][] subclassBooks;
+ private int[] xList;
+ private int[] yList;
+ private int[] lowNeighbours, highNeighbours;
+ //private boolean[] step2Flags;
+
+ private static final int[] RANGES = {256, 128, 86, 64};
+
+ private Floor1() {
+ }
+
+ protected Floor1(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
+
+ maximumClass=-1;
+ int partitions=source.getInt(5);
+ partitionClassList=new int[partitions];
+
+ for(int i=0; imaximumClass) {
+ maximumClass=partitionClassList[i];
+ }
+ }
+
+
+ classDimensions=new int[maximumClass+1];
+ classSubclasses=new int[maximumClass+1];
+ classMasterbooks=new int[maximumClass+1];
+ subclassBooks=new int[maximumClass+1][];
+
+ int xListLength=2;
+
+ for(int i=0; i<=maximumClass; i++) {
+ classDimensions[i]=source.getInt(3)+1;
+ xListLength+=classDimensions[i];
+ classSubclasses[i]=source.getInt(2);
+
+ if(classDimensions[i] > header.getCodeBooks().length ||
+ classSubclasses[i] > header.getCodeBooks().length) {
+ throw new VorbisFormatException("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");
+ }
+ if(classSubclasses[i]!=0) {
+ classMasterbooks[i]=source.getInt(8);
+ }
+ subclassBooks[i]=new int[1<0) {
+ cval=source.getInt(vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].getHuffmanRoot());
+ //cval=vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].readInt(source);
+ //System.out.println("cval: "+cval);
+ }
+ //System.out.println("0: "+cls+" "+cdim+" "+cbits+" "+csub+" "+cval);
+ for(int j=0; j>>=cbits;
+ if(book>=0) {
+ clone.yList[j+offset]=source.getInt(vorbis.getSetupHeader().getCodeBooks()[book].getHuffmanRoot());
+ //clone.yList[j+offset]=vorbis.getSetupHeader().getCodeBooks()[book].readInt(source);
+ //System.out.println("b: "+(j+offset)+" "+book+" "+clone.yList[j+offset]);
+ //System.out.println("");
+ }
+ else {
+ clone.yList[j+offset]=0;
+ }
+ }
+ offset+=cdim;
+ }
+
+ //System.out.println("");
+ //for(int i=0; i=room) {
+ yList[i]=highRoom>lowRoom?
+ val-lowRoom+predicted:
+ -val+highRoom+predicted-1;
+ }
+ else {
+ yList[i]=(val&1)==1?
+ predicted-((val+1)>>1):
+ predicted+(val>>1);
+ }
+ }
+ else {
+ step2Flags[i]=false;
+ yList[i]=predicted;
+ }
+ }
+
+ final int[] xList2=new int[values];
+
+ System.arraycopy(xList, 0, xList2, 0, values);
+ sort(xList2, yList, step2Flags);
+
+ int hx=0, hy=0, lx=0, ly=yList[0]*multiplier;
+
+ float[] vector2=new float[vector.length];
+ float[] vector3=new float[vector.length];
+ Arrays.fill(vector2, 1.0f);
+ System.arraycopy(vector, 0, vector3, 0, vector.length);
+
+ for(int i=1; ioff && x[j-1]>x[j]; j--) {
+ itmp=x[j];
+ x[j]=x[j-1];
+ x[j-1]=itmp;
+ itmp=y[j];
+ y[j]=y[j-1];
+ y[j-1]=itmp;
+ btmp=b[j];
+ b[j]=b[j-1];
+ b[j-1]=btmp;
+ //swap(x, j, j-1);
+ //swap(y, j, j-1);
+ //swap(b, j, j-1);
+ }
+ }
+ }
+
+ private final static void swap(int x[], int a, int b) {
+ int t = x[a];
+ x[a] = x[b];
+ x[b] = t;
+ }
+
+ private final static void swap(boolean x[], int a, int b) {
+ boolean t = x[a];
+ x[a] = x[b];
+ x[b] = t;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/Floor1.java~1~ b/src/main/java/de/jarnbjo/vorbis/Floor1.java~1~
new file mode 100644
index 0000000..bd6d21a
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/Floor1.java~1~
@@ -0,0 +1,318 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: Floor1.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: Floor1.java,v $
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+import java.util.*;
+
+import de.jarnbjo.util.io.BitInputStream;
+
+
+class Floor1 extends Floor implements Cloneable {
+
+ private int[] partitionClassList;
+ private int maximumClass, multiplier, rangeBits;
+ private int[] classDimensions;
+ private int[] classSubclasses;
+ private int[] classMasterbooks;
+ private int[][] subclassBooks;
+ private int[] xList;
+ private int[] yList;
+ private int[] lowNeighbours, highNeighbours;
+ //private boolean[] step2Flags;
+
+ private static final int[] RANGES = {256, 128, 86, 64};
+
+ private Floor1() {
+ }
+
+ protected Floor1(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
+
+ maximumClass=-1;
+ int partitions=source.getInt(5);
+ partitionClassList=new int[partitions];
+
+ for(int i=0; imaximumClass) {
+ maximumClass=partitionClassList[i];
+ }
+ }
+
+
+ classDimensions=new int[maximumClass+1];
+ classSubclasses=new int[maximumClass+1];
+ classMasterbooks=new int[maximumClass+1];
+ subclassBooks=new int[maximumClass+1][];
+
+ int xListLength=2;
+
+ for(int i=0; i<=maximumClass; i++) {
+ classDimensions[i]=source.getInt(3)+1;
+ xListLength+=classDimensions[i];
+ classSubclasses[i]=source.getInt(2);
+
+ if(classDimensions[i] > header.getCodeBooks().length ||
+ classSubclasses[i] > header.getCodeBooks().length) {
+ throw new VorbisFormatException("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");
+ }
+ if(classSubclasses[i]!=0) {
+ classMasterbooks[i]=source.getInt(8);
+ }
+ subclassBooks[i]=new int[1<0) {
+ cval=source.getInt(vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].getHuffmanRoot());
+ //cval=vorbis.getSetupHeader().getCodeBooks()[classMasterbooks[cls]].readInt(source);
+ //System.out.println("cval: "+cval);
+ }
+ //System.out.println("0: "+cls+" "+cdim+" "+cbits+" "+csub+" "+cval);
+ for(int j=0; j>>=cbits;
+ if(book>=0) {
+ clone.yList[j+offset]=source.getInt(vorbis.getSetupHeader().getCodeBooks()[book].getHuffmanRoot());
+ //clone.yList[j+offset]=vorbis.getSetupHeader().getCodeBooks()[book].readInt(source);
+ //System.out.println("b: "+(j+offset)+" "+book+" "+clone.yList[j+offset]);
+ //System.out.println("");
+ }
+ else {
+ clone.yList[j+offset]=0;
+ }
+ }
+ offset+=cdim;
+ }
+
+ //System.out.println("");
+ //for(int i=0; i=room) {
+ yList[i]=highRoom>lowRoom?
+ val-lowRoom+predicted:
+ -val+highRoom+predicted-1;
+ }
+ else {
+ yList[i]=(val&1)==1?
+ predicted-((val+1)>>1):
+ predicted+(val>>1);
+ }
+ }
+ else {
+ step2Flags[i]=false;
+ yList[i]=predicted;
+ }
+ }
+
+ final int[] xList2=new int[values];
+
+ System.arraycopy(xList, 0, xList2, 0, values);
+ sort(xList2, yList, step2Flags);
+
+ int hx=0, hy=0, lx=0, ly=yList[0]*multiplier;
+
+ float[] vector2=new float[vector.length];
+ float[] vector3=new float[vector.length];
+ Arrays.fill(vector2, 1.0f);
+ System.arraycopy(vector, 0, vector3, 0, vector.length);
+
+ for(int i=1; ioff && x[j-1]>x[j]; j--) {
+ itmp=x[j];
+ x[j]=x[j-1];
+ x[j-1]=itmp;
+ itmp=y[j];
+ y[j]=y[j-1];
+ y[j-1]=itmp;
+ btmp=b[j];
+ b[j]=b[j-1];
+ b[j-1]=btmp;
+ //swap(x, j, j-1);
+ //swap(y, j, j-1);
+ //swap(b, j, j-1);
+ }
+ }
+ }
+
+ private final static void swap(int x[], int a, int b) {
+ int t = x[a];
+ x[a] = x[b];
+ x[b] = t;
+ }
+
+ private final static void swap(boolean x[], int a, int b) {
+ boolean t = x[a];
+ x[a] = x[b];
+ x[b] = t;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/IdentificationHeader.java b/src/main/java/de/jarnbjo/vorbis/IdentificationHeader.java
new file mode 100644
index 0000000..c0a4568
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/IdentificationHeader.java
@@ -0,0 +1,116 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: IdentificationHeader.java,v 1.3 2003/03/31 00:20:16 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: IdentificationHeader.java,v $
+ * Revision 1.3 2003/03/31 00:20:16 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.*;
+
+import de.jarnbjo.util.io.BitInputStream;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+/**
+ */
+
+public class IdentificationHeader {
+
+ private int version, channels, sampleRate, bitrateMaximum, bitrateNominal, bitrateMinimum, blockSize0, blockSize1;
+ private boolean framingFlag;
+ private MdctFloat[] mdct=new MdctFloat[2];
+ //private MdctLong[] mdctInt=new MdctLong[2];
+
+ private static final long HEADER = 0x736962726f76L; // 'vorbis'
+
+ public IdentificationHeader(BitInputStream source) throws VorbisFormatException, IOException {
+ //equalizer=new Equalizer();
+ //equalizer.pack();
+ //equalizer.show();
+
+ long leading=source.getLong(48);
+ if(leading!=HEADER) {
+ throw new VorbisFormatException("The identification header has an illegal leading.");
+ }
+ version=source.getInt(32);
+ channels=source.getInt(8);
+ sampleRate=source.getInt(32);
+ bitrateMaximum=source.getInt(32);
+ bitrateNominal=source.getInt(32);
+ bitrateMinimum=source.getInt(32);
+ int bs=source.getInt(8);
+ blockSize0=1<<(bs&0xf);
+ blockSize1=1<<(bs>>4);
+
+ mdct[0]=new MdctFloat(blockSize0);
+ mdct[1]=new MdctFloat(blockSize1);
+ //mdctInt[0]=new MdctLong(blockSize0);
+ //mdctInt[1]=new MdctLong(blockSize1);
+
+ framingFlag=source.getInt(8)!=0;
+ }
+
+ public int getSampleRate() {
+ return sampleRate;
+ }
+
+ public int getMaximumBitrate() {
+ return bitrateMaximum;
+ }
+
+ public int getNominalBitrate() {
+ return bitrateNominal;
+ }
+
+ public int getMinimumBitrate() {
+ return bitrateMinimum;
+ }
+
+ public int getChannels() {
+ return channels;
+ }
+
+ public int getBlockSize0() {
+ return blockSize0;
+ }
+
+ public int getBlockSize1() {
+ return blockSize1;
+ }
+
+ protected MdctFloat getMdct0() {
+ return mdct[0];
+ }
+
+ protected MdctFloat getMdct1() {
+ return mdct[1];
+ }
+
+ public int getVersion() {
+ return version;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/Mapping.java b/src/main/java/de/jarnbjo/vorbis/Mapping.java
new file mode 100644
index 0000000..964be87
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/Mapping.java
@@ -0,0 +1,53 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: Mapping.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: Mapping.java,v $
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+
+import de.jarnbjo.util.io.BitInputStream;
+
+abstract class Mapping {
+
+ protected static Mapping createInstance(VorbisStream vorbis, BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
+
+ int type=source.getInt(16);
+ switch(type) {
+ case 0:
+ //System.out.println("mapping type 0");
+ return new Mapping0(vorbis, source, header);
+ default:
+ throw new VorbisFormatException("Mapping type "+type+" is not supported.");
+ }
+ }
+
+ protected abstract int getType();
+ protected abstract int[] getAngles();
+ protected abstract int[] getMagnitudes() ;
+ protected abstract int[] getMux();
+ protected abstract int[] getSubmapFloors();
+ protected abstract int[] getSubmapResidues();
+ protected abstract int getCouplingSteps();
+ protected abstract int getSubmaps();
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/Mapping0.java b/src/main/java/de/jarnbjo/vorbis/Mapping0.java
new file mode 100644
index 0000000..a24dc51
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/Mapping0.java
@@ -0,0 +1,140 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: Mapping0.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: Mapping0.java,v $
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+
+import de.jarnbjo.util.io.BitInputStream;
+
+class Mapping0 extends Mapping {
+
+ private int[] magnitudes, angles, mux, submapFloors, submapResidues;
+
+ protected Mapping0(VorbisStream vorbis, BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
+
+ int submaps=1;
+
+ if(source.getBit()) {
+ submaps=source.getInt(4)+1;
+ }
+
+ //System.out.println("submaps: "+submaps);
+
+ int channels=vorbis.getIdentificationHeader().getChannels();
+ int ilogChannels=Util.ilog(channels-1);
+
+ //System.out.println("ilogChannels: "+ilogChannels);
+
+ if(source.getBit()) {
+ int couplingSteps=source.getInt(8)+1;
+ magnitudes=new int[couplingSteps];
+ angles=new int[couplingSteps];
+
+ for(int i=0; i=channels || angles[i]>=channels) {
+ System.err.println(magnitudes[i]);
+ System.err.println(angles[i]);
+ throw new VorbisFormatException("The channel magnitude and/or angle mismatch.");
+ }
+ }
+ }
+ else {
+ magnitudes=new int[0];
+ angles=new int[0];
+ }
+
+ if(source.getInt(2)!=0) {
+ throw new VorbisFormatException("A reserved mapping field has an invalid value.");
+ }
+
+ mux=new int[channels];
+ if(submaps>1) {
+ for(int i=0; isubmaps) {
+ throw new VorbisFormatException("A mapping mux value is higher than the number of submaps");
+ }
+ }
+ }
+ else {
+ for(int i=0; ifloorCount) {
+ throw new VorbisFormatException("A mapping floor value is higher than the number of floors.");
+ }
+
+ if(submapResidues[i]>residueCount) {
+ throw new VorbisFormatException("A mapping residue value is higher than the number of residues.");
+ }
+ }
+ }
+
+ protected int getType() {
+ return 0;
+ }
+
+ protected int[] getAngles() {
+ return angles;
+ }
+
+ protected int[] getMagnitudes() {
+ return magnitudes;
+ }
+
+ protected int[] getMux() {
+ return mux;
+ }
+
+ protected int[] getSubmapFloors() {
+ return submapFloors;
+ }
+
+ protected int[] getSubmapResidues() {
+ return submapResidues;
+ }
+
+ protected int getCouplingSteps() {
+ return angles.length;
+ }
+
+ protected int getSubmaps() {
+ return submapFloors.length;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/MdctFloat.java b/src/main/java/de/jarnbjo/vorbis/MdctFloat.java
new file mode 100644
index 0000000..0c4836f
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/MdctFloat.java
@@ -0,0 +1,312 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: MdctFloat.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: MdctFloat.java,v $
+ * Revision 1.3 2003/04/10 19:49:04 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+class MdctFloat {
+ static private final float cPI3_8=0.38268343236508977175f;
+ static private final float cPI2_8=0.70710678118654752441f;
+ static private final float cPI1_8=0.92387953251128675613f;
+
+ private int n;
+ private int log2n;
+
+ private float[] trig;
+ private int[] bitrev;
+
+ private float[] equalizer;
+
+ private float scale;
+
+ private int itmp1, itmp2, itmp3, itmp4, itmp5, itmp6, itmp7, itmp8, itmp9;
+ private float dtmp1, dtmp2, dtmp3, dtmp4, dtmp5, dtmp6, dtmp7, dtmp8, dtmp9;
+
+ protected MdctFloat(int n) {
+ bitrev=new int[n/4];
+ trig=new float[n+n/4];
+
+ int n2=n>>>1;
+ log2n=(int)Math.rint(Math.log(n)/Math.log(2));
+ this.n=n;
+
+ int AE=0;
+ int AO=1;
+ int BE=AE+n/2;
+ int BO=BE+1;
+ int CE=BE+n/2;
+ int CO=CE+1;
+ // trig lookups...
+ for(int i=0;i>>j!=0;j++)
+ if(((msb>>>j)&i)!=0)acc|=1<>1;
+ int n4=n>>2;
+ int n8=n>>3;
+
+ if(equalizer!=null) {
+ for(int i=0; i32767.0f) temp1=32767.0f;
+ //if(temp1<-32768.0f) temp1=-32768.0f;
+ //if(temp2>32767.0f) temp2=32767.0f;
+ //if(temp2<-32768.0f) temp2=-32768.0f;
+
+ pcm[o1]=(int)(-temp1*window[o1]);
+ pcm[o2]=(int)( temp1*window[o2]);
+ pcm[o3]=(int)( temp2*window[o3]);
+ pcm[o4]=(int)( temp2*window[o4]);
+
+ o1++;
+ o2--;
+ o3++;
+ o4--;
+ //xx+=2;
+ //B+=2;
+ }
+ }
+ }
+
+ private float[] kernel(float[] x, float[] w,
+ int n, int n2, int n4, int n8){
+ // step 2
+
+ int xA=n4;
+ int xB=0;
+ int w2=n4;
+ int A=n2;
+
+ for(int i=0;i>>(i+2);
+ int k1=1<<(i+3);
+ int wbase=n2-2;
+
+ A=0;
+ float[] temp;
+
+ for(int r=0;r<(k0>>>2);r++){
+ int w1=wbase;
+ w2=w1-(k0>>1);
+ float AEv= trig[A],wA;
+ float AOv= trig[A+1],wB;
+ wbase-=2;
+
+ k0++;
+ for(int s=0;s<(2<header.getMappings().length) {
+ throw new VorbisFormatException("Mode mapping number is higher than total number of mappings.");
+ }
+ }
+
+ protected boolean getBlockFlag() {
+ return blockFlag;
+ }
+
+ protected int getWindowType() {
+ return windowType;
+ }
+
+ protected int getTransformType() {
+ return transformType;
+ }
+
+ protected int getMapping() {
+ return mapping;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/Residue.java b/src/main/java/de/jarnbjo/vorbis/Residue.java
new file mode 100644
index 0000000..e79fc75
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/Residue.java
@@ -0,0 +1,254 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: Residue.java,v 1.3 2003/04/04 08:33:02 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: Residue.java,v $
+ * Revision 1.3 2003/04/04 08:33:02 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import de.jarnbjo.util.io.*;
+
+
+abstract class Residue {
+
+ protected int begin, end;
+ protected int partitionSize; // grouping
+ protected int classifications; // partitions
+ protected int classBook; // groupbook
+ protected int[] cascade; // secondstages
+ protected int[][] books;
+ protected HashMap looks=new HashMap();
+
+ protected Residue() {
+ }
+
+ protected Residue(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
+ begin=source.getInt(24);
+ end=source.getInt(24);
+ partitionSize=source.getInt(24)+1;
+ classifications=source.getInt(6)+1;
+ classBook=source.getInt(8);
+
+ cascade=new int[classifications];
+
+ int acc=0;
+
+ for(int i=0; iheader.getCodeBooks().length) {
+ throw new VorbisFormatException("Reference to invalid codebook entry in residue header.");
+ }
+ }
+ }
+ }
+ }
+
+
+ protected static Residue createInstance(BitInputStream source, SetupHeader header) throws VorbisFormatException, IOException {
+
+ int type=source.getInt(16);
+ switch(type) {
+ case 0:
+ //System.out.println("residue type 0");
+ return new Residue0(source, header);
+ case 1:
+ //System.out.println("residue type 1");
+ return new Residue2(source, header);
+ case 2:
+ //System.out.println("residue type 2");
+ return new Residue2(source, header);
+ default:
+ throw new VorbisFormatException("Residue type "+type+" is not supported.");
+ }
+ }
+
+ protected abstract int getType();
+ protected abstract void decodeResidue(VorbisStream vorbis, BitInputStream source, Mode mode, int ch, boolean[] doNotDecodeFlags, float[][] vectors) throws VorbisFormatException, IOException;
+ //public abstract double[][] getDecodedVectors();
+
+ protected int getBegin() {
+ return begin;
+ }
+
+ protected int getEnd() {
+ return end;
+ }
+
+ protected int getPartitionSize() {
+ return partitionSize;
+ }
+
+ protected int getClassifications() {
+ return classifications;
+ }
+
+ protected int getClassBook() {
+ return classBook;
+ }
+
+ protected int[] getCascade() {
+ return cascade;
+ }
+
+ protected int[][] getBooks() {
+ return books;
+ }
+
+ protected final void fill(Residue clone) {
+ clone.begin=begin;
+ clone.books=books;
+ clone.cascade=cascade;
+ clone.classBook=classBook;
+ clone.classifications=classifications;
+ clone.end=end;
+ clone.partitionSize=partitionSize;
+ }
+
+ protected Look getLook(VorbisStream source, Mode key) {
+ //return new Look(source, key);
+ Look look=(Look)looks.get(key);
+ if(look==null) {
+ look=new Look(source, key);
+ looks.put(key, look);
+ }
+ return look;
+ }
+
+
+ class Look {
+ int map;
+ int parts;
+ int stages;
+ CodeBook[] fullbooks;
+ CodeBook phrasebook;
+ int[][] partbooks;
+ int partvals;
+ int[][] decodemap;
+ int postbits;
+ int phrasebits;
+ int frames;
+
+ protected Look (VorbisStream source, Mode mode) {
+ int dim=0, acc=0, maxstage=0;
+
+ map=mode.getMapping();
+ parts=Residue.this.getClassifications();
+ fullbooks=source.getSetupHeader().getCodeBooks();
+ phrasebook=fullbooks[Residue.this.getClassBook()];
+ dim=phrasebook.getDimensions();
+
+ partbooks=new int[parts][];
+
+ for(int j=0;jmaxstage) {
+ maxstage=stages;
+ }
+ partbooks[j]=new int[stages];
+ for(int k=0; k0; x>>=1, res++);
+ return res;
+ }
+
+ public static final float float32unpack(int x) {
+ float mantissa=x&0x1fffff;
+ float e=(x&0x7fe00000)>>21;
+ if((x&0x80000000)!=0) {
+ mantissa=-mantissa;
+ }
+ return mantissa*(float)Math.pow(2.0, e-788.0);
+ }
+
+ public static final int lookup1Values(int a, int b) {
+ int res=(int)Math.pow(Math.E, Math.log(a)/b);
+ return intPow(res+1, b)<=a?res+1:res;
+ }
+
+ public static final int intPow(int base, int e) {
+ int res=1;
+ for(; e>0; e--, res*=base);
+ return res;
+ }
+
+ public static final boolean isBitSet(int value, int bit) {
+ return (value&(1<0) {
+ res+=value&1;
+ value>>=1;
+ }
+ return res;
+ }
+
+ public static final int lowNeighbour(int[] v, int x) {
+ int max=-1, n=0;
+ for(int i=0; imax && v[i]v[x]) {
+ min=v[i];
+ n=i;
+ }
+ }
+ return n;
+ }
+
+ public static final int renderPoint(int x0, int x1, int y0, int y1, int x) {
+ int dy=y1-y0;
+ int ady=dy<0?-dy:dy;
+ int off=(ady*(x-x0))/(x1-x0);
+ return dy<0?y0-off:y0+off;
+ }
+
+ public static final void renderLine(final int x0, final int y0, final int x1, final int y1, final float[] v) {
+ final int dy=y1-y0;
+ final int adx=x1-x0;
+ final int base=dy/adx;
+ final int sy=dy<0?base-1:base+1;
+ int x=x0;
+ int y=y0;
+ int err=0;
+ final int ady=(dy<0?-dy:dy)-(base>0?base*adx:-base*adx);
+
+ v[x]*=Floor.DB_STATIC_TABLE[y];
+ for(x=x0+1; x=adx) {
+ err-=adx;
+ v[x]*=Floor.DB_STATIC_TABLE[y+=sy];
+ }
+ else {
+ v[x]*=Floor.DB_STATIC_TABLE[y+=base];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/VorbisAudioFileReader.java b/src/main/java/de/jarnbjo/vorbis/VorbisAudioFileReader.java
new file mode 100644
index 0000000..9bafefd
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/VorbisAudioFileReader.java
@@ -0,0 +1,196 @@
+package de.jarnbjo.vorbis;
+
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: VorbisAudioFileReader.java,v 1.1 2003/08/08 19:48:22 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: VorbisAudioFileReader.java,v $
+ *
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import de.jarnbjo.ogg.*;
+import de.jarnbjo.vorbis.*;
+
+import javax.sound.sampled.*;
+import javax.sound.sampled.spi.AudioFileReader;
+
+public class VorbisAudioFileReader extends AudioFileReader {
+
+ public VorbisAudioFileReader() {
+ }
+
+ public AudioFileFormat getAudioFileFormat(File file) throws IOException, UnsupportedAudioFileException {
+ try {
+ return getAudioFileFormat(new FileStream(new RandomAccessFile(file, "r")));
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+ public AudioFileFormat getAudioFileFormat(InputStream stream) throws IOException, UnsupportedAudioFileException {
+ try {
+ return getAudioFileFormat(new BasicStream(stream));
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+ public AudioFileFormat getAudioFileFormat(URL url) throws IOException, UnsupportedAudioFileException {
+ try {
+ return getAudioFileFormat(new UncachedUrlStream(url));
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+ private AudioFileFormat getAudioFileFormat(PhysicalOggStream oggStream) throws IOException, UnsupportedAudioFileException {
+ try {
+ Collection streams=oggStream.getLogicalStreams();
+ if(streams.size()!=1) {
+ throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
+ }
+
+ LogicalOggStream los=(LogicalOggStream)streams.iterator().next();
+ if(los.getFormat()!=LogicalOggStream.FORMAT_VORBIS) {
+ throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
+ }
+
+ VorbisStream vs=new VorbisStream(los);
+
+ AudioFormat audioFormat=new AudioFormat(
+ (float)vs.getIdentificationHeader().getSampleRate(),
+ 16,
+ vs.getIdentificationHeader().getChannels(),
+ true, true);
+
+ return new AudioFileFormat(VorbisFormatType.getInstance(), audioFormat, AudioSystem.NOT_SPECIFIED);
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ catch(VorbisFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+
+
+ public AudioInputStream getAudioInputStream(File file) throws IOException, UnsupportedAudioFileException {
+ try {
+ return getAudioInputStream(new FileStream(new RandomAccessFile(file, "r")));
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+ public AudioInputStream getAudioInputStream(InputStream stream) throws IOException, UnsupportedAudioFileException {
+ try {
+ return getAudioInputStream(new BasicStream(stream));
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+ public AudioInputStream getAudioInputStream(URL url) throws IOException, UnsupportedAudioFileException {
+ try {
+ return getAudioInputStream(new UncachedUrlStream(url));
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+ private AudioInputStream getAudioInputStream(PhysicalOggStream oggStream) throws IOException, UnsupportedAudioFileException {
+ try {
+ Collection streams=oggStream.getLogicalStreams();
+ if(streams.size()!=1) {
+ throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
+ }
+
+ LogicalOggStream los=(LogicalOggStream)streams.iterator().next();
+ if(los.getFormat()!=LogicalOggStream.FORMAT_VORBIS) {
+ throw new UnsupportedAudioFileException("Only Ogg files with one logical Vorbis stream are supported.");
+ }
+
+ VorbisStream vs=new VorbisStream(los);
+
+ AudioFormat audioFormat=new AudioFormat(
+ (float)vs.getIdentificationHeader().getSampleRate(),
+ 16,
+ vs.getIdentificationHeader().getChannels(),
+ true, true);
+
+ return new AudioInputStream(new VorbisInputStream(vs), audioFormat, -1);
+ }
+ catch(OggFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ catch(VorbisFormatException e) {
+ throw new UnsupportedAudioFileException(e.getMessage());
+ }
+ }
+
+
+ public static class VorbisFormatType extends AudioFileFormat.Type {
+
+ private static final VorbisFormatType instance=new VorbisFormatType();
+
+ private VorbisFormatType() {
+ super("VORBIS", "ogg");
+ }
+
+ public static AudioFileFormat.Type getInstance() {
+ return instance;
+ }
+ }
+
+ public static class VorbisInputStream extends InputStream {
+
+ private VorbisStream source;
+ private byte[] buffer=new byte[8192];
+
+ public VorbisInputStream(VorbisStream source) {
+ this.source=source;
+ }
+
+ public int read() throws IOException {
+ return 0;
+ }
+
+ public int read(byte[] buffer) throws IOException {
+ return read(buffer, 0, buffer.length);
+ }
+
+ public int read(byte[] buffer, int offset, int length) throws IOException {
+ try {
+ return source.readPcm(buffer, offset, length);
+ }
+ catch(EndOfOggStreamException e) {
+ return -1;
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/VorbisFormatException.java b/src/main/java/de/jarnbjo/vorbis/VorbisFormatException.java
new file mode 100644
index 0000000..fc2a5d5
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/VorbisFormatException.java
@@ -0,0 +1,41 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: VorbisFormatException.java,v 1.2 2003/03/16 01:11:12 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: VorbisFormatException.java,v $
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when trying to read a corrupted Vorbis stream.
+ */
+
+public class VorbisFormatException extends IOException {
+
+ public VorbisFormatException() {
+ super();
+ }
+
+ public VorbisFormatException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jarnbjo/vorbis/VorbisStream.java b/src/main/java/de/jarnbjo/vorbis/VorbisStream.java
new file mode 100644
index 0000000..16d285b
--- /dev/null
+++ b/src/main/java/de/jarnbjo/vorbis/VorbisStream.java
@@ -0,0 +1,241 @@
+/*
+ * $ProjectName$
+ * $ProjectRevision$
+ * -----------------------------------------------------------
+ * $Id: VorbisStream.java,v 1.4 2003/04/10 19:49:04 jarnbjo Exp $
+ * -----------------------------------------------------------
+ *
+ * $Author: jarnbjo $
+ *
+ * Description:
+ *
+ * Copyright 2002-2003 Tor-Einar Jarnbjo
+ * -----------------------------------------------------------
+ *
+ * Change History
+ * -----------------------------------------------------------
+ * $Log: VorbisStream.java,v $
+ * Revision 1.4 2003/04/10 19:49:04 jarnbjo
+ * no message
+ *
+ * Revision 1.3 2003/03/31 00:20:16 jarnbjo
+ * no message
+ *
+ * Revision 1.2 2003/03/16 01:11:12 jarnbjo
+ * no message
+ *
+ *
+ */
+
+package de.jarnbjo.vorbis;
+
+import java.io.*;
+import java.util.*;
+
+import de.jarnbjo.ogg.*;
+import de.jarnbjo.util.io.*;
+
+/**
+ */
+
+public class VorbisStream {
+
+ private LogicalOggStream oggStream;
+ private IdentificationHeader identificationHeader;
+ private CommentHeader commentHeader;
+ private SetupHeader setupHeader;
+
+ private AudioPacket lastAudioPacket, nextAudioPacket;
+ private LinkedList audioPackets=new LinkedList();
+ private byte[] currentPcm;
+ private int currentPcmIndex;
+ private int currentPcmLimit;
+
+ private static final int IDENTIFICATION_HEADER = 1;
+ private static final int COMMENT_HEADER = 3;
+ private static final int SETUP_HEADER = 5;
+
+ private int bitIndex=0;
+ private byte lastByte=(byte)0;
+ private boolean initialized=false;
+
+ private Object streamLock=new Object();
+ private int pageCounter=0;
+
+ private int currentBitRate=0;
+
+ private long currentGranulePosition;
+
+ public static final int BIG_ENDIAN = 0;
+ public static final int LITTLE_ENDIAN = 1;
+
+ public VorbisStream() {
+ }
+
+ public VorbisStream(LogicalOggStream oggStream) throws VorbisFormatException, IOException {
+ this.oggStream=oggStream;
+
+ for(int i=0; i<3; i++) {
+ BitInputStream source=new ByteArrayBitInputStream(oggStream.getNextOggPacket());
+ int headerType=source.getInt(8);
+ switch(headerType) {
+ case IDENTIFICATION_HEADER:
+ identificationHeader=new IdentificationHeader(source);
+ break;
+ case COMMENT_HEADER:
+ commentHeader=new CommentHeader(source);
+ break;
+ case SETUP_HEADER:
+ setupHeader=new SetupHeader(this, source);
+ break;
+ }
+ }
+
+ if(identificationHeader==null) {
+ throw new VorbisFormatException("The file has no identification header.");
+ }
+
+ if(commentHeader==null) {
+ throw new VorbisFormatException("The file has no commentHeader.");
+ }
+
+ if(setupHeader==null) {
+ throw new VorbisFormatException("The file has no setup header.");
+ }
+
+ //currentPcm=new int[identificationHeader.getChannels()][16384];
+ currentPcm=new byte[identificationHeader.getChannels()*identificationHeader.getBlockSize1()*2];
+ //new BufferThread().start();
+ }
+
+ public IdentificationHeader getIdentificationHeader() {
+ return identificationHeader;
+ }
+
+ public CommentHeader getCommentHeader() {
+ return commentHeader;
+ }
+
+ protected SetupHeader getSetupHeader() {
+ return setupHeader;
+ }
+
+ public boolean isOpen() {
+ return oggStream.isOpen();
+ }
+
+ public void close() throws IOException {
+ oggStream.close();
+ }
+
+
+ public int readPcm(byte[] buffer, int offset, int length) throws IOException {
+ synchronized (streamLock) {
+ final int channels=identificationHeader.getChannels();
+
+ if(lastAudioPacket==null) {
+ lastAudioPacket=getNextAudioPacket();
+ }
+ if(currentPcm==null || currentPcmIndex>=currentPcmLimit) {
+ AudioPacket ap=getNextAudioPacket();
+ try {
+ ap.getPcm(lastAudioPacket, currentPcm);
+ currentPcmLimit=ap.getNumberOfSamples()*identificationHeader.getChannels()*2;
+ }
+ catch(ArrayIndexOutOfBoundsException e) {
+ return 0;
+ }
+ currentPcmIndex=0;
+ lastAudioPacket=ap;
+ }
+ int written=0;
+ int i=0;
+ int arrIx=0;
+ for(i=currentPcmIndex; i