diff --git a/.gradle/8.0/executionHistory/executionHistory.lock b/.gradle/8.0/executionHistory/executionHistory.lock
index b6eecc8..72d231a 100644
Binary files a/.gradle/8.0/executionHistory/executionHistory.lock and b/.gradle/8.0/executionHistory/executionHistory.lock differ
diff --git a/.gradle/8.0/fileHashes/fileHashes.bin b/.gradle/8.0/fileHashes/fileHashes.bin
index e611bd7..5bee1dd 100644
Binary files a/.gradle/8.0/fileHashes/fileHashes.bin and b/.gradle/8.0/fileHashes/fileHashes.bin differ
diff --git a/.gradle/8.0/fileHashes/fileHashes.lock b/.gradle/8.0/fileHashes/fileHashes.lock
index 9c61704..cd2cff1 100644
Binary files a/.gradle/8.0/fileHashes/fileHashes.lock and b/.gradle/8.0/fileHashes/fileHashes.lock differ
diff --git a/.gradle/8.0/fileHashes/resourceHashesCache.bin b/.gradle/8.0/fileHashes/resourceHashesCache.bin
index 173d71f..ec481a5 100644
Binary files a/.gradle/8.0/fileHashes/resourceHashesCache.bin and b/.gradle/8.0/fileHashes/resourceHashesCache.bin differ
diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock
index 2d161e5..a69d276 100644
Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..dbb5ddd
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+eaglercraft
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..fcb19bf
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..f9163b4
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..fdc9bf7
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lwjgl-rundir/java-websocket.jar b/lwjgl-rundir/java-websocket.jar
new file mode 100644
index 0000000..8fb33ad
Binary files /dev/null and b/lwjgl-rundir/java-websocket.jar differ
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java
new file mode 100644
index 0000000..d123192
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java
@@ -0,0 +1,69 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class IPCInputStream extends InputStream {
+
+ private byte[] currentBuffer = null;
+ private int idx = 0;
+ private int markIDX = 0;
+ private String errorName = null;
+
+ public void feedBuffer(byte[] b) {
+ currentBuffer = b;
+ idx = 0;
+ errorName = null;
+ markIDX = 0;
+ }
+
+ public void nameBuffer(String str) {
+ errorName = str;
+ }
+
+ @Override
+ public int read() throws IOException {
+ try {
+ return ((int)currentBuffer[idx++]) & 0xFF;
+ }catch(ArrayIndexOutOfBoundsException a) {
+ throw new IOException("IPCInputStream buffer underflow" + (errorName == null ? "," : (" (while deserializing '" + errorName + "')")) + " no bytes remaining", a);
+ }
+ }
+
+ @Override
+ public int read(byte b[], int off, int len) throws IOException {
+ if(idx + len > currentBuffer.length) {
+ throw new IOException("IPCInputStream buffer underflow" + (errorName == null ? "," : (" (while deserializing '" + errorName + "')")) + " tried to read " + len + " when there are only " + (currentBuffer.length - idx) + " bytes remaining", new ArrayIndexOutOfBoundsException(idx + len - 1));
+ }
+ if(off + len > b.length) {
+ throw new ArrayIndexOutOfBoundsException(off + len - 1);
+ }
+ System.arraycopy(currentBuffer, idx, b, off, len);
+ idx += len;
+ return len;
+ }
+
+ public void markIndex() {
+ markIDX = idx;
+ }
+
+ public void rewindIndex() {
+ idx = markIDX;
+ }
+
+ public byte[] getLeftover() {
+ if(currentBuffer.length - idx <= 0) {
+ return null;
+ }
+
+ byte[] buf = new byte[currentBuffer.length - idx];
+ System.arraycopy(currentBuffer, idx, buf, 0, currentBuffer.length - idx);
+
+ return buf;
+ }
+
+ public int getLeftoverCount() {
+ return currentBuffer.length - idx;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java
new file mode 100644
index 0000000..dc019d5
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java
@@ -0,0 +1,54 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class IPCOutputStream extends OutputStream {
+
+ private String className = null;
+ private byte[] currentBuffer = null;
+ private int idx = 0;
+ private int originalSize = 0;
+
+ public void feedBuffer(byte[] buf, String clazzName) {
+ currentBuffer = buf;
+ idx = 0;
+ originalSize = buf.length;
+ className = clazzName;
+ }
+
+ public byte[] returnBuffer() {
+ if(className != null && currentBuffer.length != originalSize) {
+ System.err.println("WARNING: Packet '" + className + "' was supposed to be " + originalSize + " bytes but buffer has grown by " + (currentBuffer.length - originalSize) + " to " + currentBuffer.length + " bytes");
+ }
+ return currentBuffer;
+ }
+
+ void growBuffer(int i) {
+ int ii = currentBuffer.length;
+ int iii = i - ii;
+ if(iii > 0) {
+ byte[] n = new byte[i];
+ System.arraycopy(currentBuffer, 0, n, 0, ii);
+ currentBuffer = n;
+ }
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ if(idx >= currentBuffer.length) {
+ growBuffer(idx + 1);
+ }
+ currentBuffer[idx++] = (byte) b;
+ }
+
+ @Override
+ public void write(byte b[], int off, int len) throws IOException {
+ if(idx + len > currentBuffer.length) {
+ growBuffer(idx + len);
+ }
+ System.arraycopy(b, off, currentBuffer, idx, len);
+ idx += len;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java
new file mode 100644
index 0000000..597551f
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java
@@ -0,0 +1,48 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket00StartServer implements IPCPacketBase {
+
+ public static final int ID = 0x00;
+
+ public String worldName;
+ public String ownerName;
+ public int initialDifficulty;
+
+ public IPCPacket00StartServer() {
+ }
+
+ public IPCPacket00StartServer(String worldName, String ownerName, int initialDifficulty) {
+ this.worldName = worldName;
+ this.ownerName = ownerName;
+ this.initialDifficulty = initialDifficulty;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldName = bin.readUTF();
+ ownerName = bin.readUTF();
+ initialDifficulty = bin.readByte();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ bin.writeUTF(ownerName);
+ bin.writeByte(initialDifficulty);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName) + IPCPacketBase.strLen(ownerName) + 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java
new file mode 100644
index 0000000..08494d6
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java
@@ -0,0 +1,32 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket01StopServer implements IPCPacketBase {
+
+ public static final int ID = 0x01;
+
+ public IPCPacket01StopServer() {
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java
new file mode 100644
index 0000000..d688ce6
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java
@@ -0,0 +1,68 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket02InitWorld implements IPCPacketBase {
+
+ public static final int ID = 0x02;
+
+ public String worldName;
+ public byte gamemode;
+ public byte worldType;
+ public String worldArgs;
+ public long seed;
+ public boolean cheats;
+ public boolean structures;
+ public boolean bonusChest;
+
+ public IPCPacket02InitWorld() {
+ }
+
+ public IPCPacket02InitWorld(String worldName, int gamemode, int worldType, String worldArgs, long seed, boolean cheats, boolean structures, boolean bonusChest) {
+ this.worldName = worldName;
+ this.gamemode = (byte)gamemode;
+ this.worldType = (byte)worldType;
+ this.worldArgs = worldArgs;
+ this.seed = seed;
+ this.cheats = cheats;
+ this.structures = structures;
+ this.bonusChest = bonusChest;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldName = bin.readUTF();
+ gamemode = bin.readByte();
+ worldType = bin.readByte();
+ worldArgs = bin.readUTF();
+ seed = bin.readLong();
+ cheats = bin.readBoolean();
+ structures = bin.readBoolean();
+ bonusChest = bin.readBoolean();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ bin.writeByte(gamemode);
+ bin.writeByte(worldType);
+ bin.writeUTF(worldArgs);
+ bin.writeLong(seed);
+ bin.writeBoolean(cheats);
+ bin.writeBoolean(structures);
+ bin.writeBoolean(bonusChest);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName) + 1 + 1 + IPCPacketBase.strLen(worldArgs) + 8 + 1 + 1 + 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java
new file mode 100644
index 0000000..d3f2a0b
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket03DeleteWorld implements IPCPacketBase {
+
+ public static final int ID = 0x03;
+
+ public String worldName;
+
+ public IPCPacket03DeleteWorld() {
+ }
+
+ public IPCPacket03DeleteWorld(String worldName) {
+ this.worldName = worldName;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldName = bin.readUTF();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName);
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java
new file mode 100644
index 0000000..751c075
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java
@@ -0,0 +1,52 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket04RenameWorld implements IPCPacketBase {
+
+ public static final int ID = 0x04;
+
+ public String worldOldName;
+ public String worldNewName;
+ public String displayName;
+ public boolean copy;
+
+ public IPCPacket04RenameWorld() {
+ }
+
+ public IPCPacket04RenameWorld(String worldOldName, String worldNewName, String displayName, boolean copy) {
+ this.worldOldName = worldOldName;
+ this.worldNewName = worldNewName;
+ this.displayName = displayName;
+ this.copy = copy;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldOldName = bin.readUTF();
+ worldNewName = bin.readUTF();
+ displayName = bin.readUTF();
+ copy = bin.readBoolean();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldOldName);
+ bin.writeUTF(worldNewName);
+ bin.writeUTF(displayName);
+ bin.writeBoolean(copy);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldOldName) + IPCPacketBase.strLen(worldNewName) + IPCPacketBase.strLen(displayName) + 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java
new file mode 100644
index 0000000..00355aa
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java
@@ -0,0 +1,48 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket05RequestData implements IPCPacketBase {
+
+ public static final int ID = 0x05;
+
+ public static final byte REQUEST_LEVEL_DAT = 0x00;
+ public static final byte REQUEST_LEVEL_EAG = 0x01;
+ public static final byte REQUEST_LEVEL_MCA = 0x02;
+
+ public String worldName;
+ public byte request;
+
+ public IPCPacket05RequestData() {
+ }
+
+ public IPCPacket05RequestData(String worldName, byte request) {
+ this.worldName = worldName;
+ this.request = request;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldName = bin.readUTF();
+ request = bin.readByte();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ bin.writeByte(request);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName) + 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java
new file mode 100644
index 0000000..27fb9d1
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java
@@ -0,0 +1,44 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket06RenameWorldNBT implements IPCPacketBase {
+
+ public static final int ID = 0x06;
+
+ public String worldName;
+ public String displayName;
+
+ public IPCPacket06RenameWorldNBT() {
+ }
+
+ public IPCPacket06RenameWorldNBT(String worldName, String displayName) {
+ this.worldName = worldName;
+ this.displayName = displayName;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ this.worldName = bin.readUTF();
+ this.displayName = bin.readUTF();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ bin.writeUTF(displayName);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName) + IPCPacketBase.strLen(displayName);
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java
new file mode 100644
index 0000000..c702b3d
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java
@@ -0,0 +1,53 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket07ImportWorld implements IPCPacketBase {
+
+ public static final int ID = 0x07;
+
+ public String worldName;
+ public byte[] worldData;
+ public byte worldFormat;
+
+ public static final byte WORLD_FORMAT_EAG = 0x00;
+ public static final byte WORLD_FORMAT_MCA = 0x01;
+
+ public IPCPacket07ImportWorld() {
+ }
+
+ public IPCPacket07ImportWorld(String worldName, byte[] worldData, byte worldFormat) {
+ this.worldName = worldName;
+ this.worldData = worldData;
+ this.worldFormat = worldFormat;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldName = bin.readUTF();
+ worldData = new byte[bin.readInt()];
+ worldFormat = bin.readByte();
+ bin.readFully(worldData);
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ bin.writeInt(worldData.length);
+ bin.writeByte(worldFormat);
+ bin.write(worldData);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName) + worldData.length + 5;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java
new file mode 100644
index 0000000..e8e47db
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java
@@ -0,0 +1,42 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket09RequestResponse implements IPCPacketBase {
+
+ public static final int ID = 0x09;
+
+ public byte[] response;
+
+ public IPCPacket09RequestResponse() {
+ }
+
+ public IPCPacket09RequestResponse(byte[] dat) {
+ this.response = dat;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ response = new byte[bin.readInt()];
+ bin.readFully(response);
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeInt(response.length);
+ bin.write(response);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return 4 + response.length;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java
new file mode 100644
index 0000000..6a549fe
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket0ASetWorldDifficulty implements IPCPacketBase {
+
+ public static final int ID = 0x0A;
+
+ public byte difficulty;
+
+ public IPCPacket0ASetWorldDifficulty() {
+ }
+
+ public IPCPacket0ASetWorldDifficulty(byte difficulty) {
+ this.difficulty = difficulty;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ difficulty = bin.readByte();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeByte(difficulty);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java
new file mode 100644
index 0000000..5bf0028
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket0BPause implements IPCPacketBase {
+
+ public static final int ID = 0x0B;
+
+ public boolean pause;
+
+ public IPCPacket0BPause() {
+ }
+
+ public IPCPacket0BPause(boolean pause) {
+ this.pause = pause;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ pause = bin.readBoolean();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeBoolean(pause);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java
new file mode 100644
index 0000000..ad9d681
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java
@@ -0,0 +1,44 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket0CPlayerChannel implements IPCPacketBase {
+
+ public static final int ID = 0x0C;
+
+ public String channel;
+ public boolean open;
+
+ public IPCPacket0CPlayerChannel() {
+ }
+
+ public IPCPacket0CPlayerChannel(String channel, boolean open) {
+ this.channel = channel;
+ this.open = open;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ channel = bin.readUTF();
+ open = bin.readBoolean();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(channel);
+ bin.writeBoolean(open);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(channel) + 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java
new file mode 100644
index 0000000..98f30f7
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java
@@ -0,0 +1,44 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket0DProgressUpdate implements IPCPacketBase {
+
+ public static final int ID = 0x0D;
+
+ public String updateMessage;
+ public float updateProgress;
+
+ public IPCPacket0DProgressUpdate() {
+ }
+
+ public IPCPacket0DProgressUpdate(String updateMessage, float updateProgress) {
+ this.updateMessage = updateMessage == null ? "" : updateMessage;
+ this.updateProgress = updateProgress;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ updateMessage = bin.readUTF();
+ updateProgress = bin.readFloat();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(updateMessage);
+ bin.writeFloat(updateProgress);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(updateMessage) + 4;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java
new file mode 100644
index 0000000..8a81c70
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java
@@ -0,0 +1,32 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket0EListWorlds implements IPCPacketBase {
+
+ public static final int ID = 0x0E;
+
+ public IPCPacket0EListWorlds() {
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java
new file mode 100644
index 0000000..fb00b24
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket0FListFiles implements IPCPacketBase {
+
+ public static final int ID = 0x0F;
+
+ public String path;
+
+ public IPCPacket0FListFiles() {
+ }
+
+ public IPCPacket0FListFiles(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ this.path = bin.readUTF();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(path);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(path);
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java
new file mode 100644
index 0000000..75d8f3b
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket10FileRead implements IPCPacketBase {
+
+ public static final int ID = 0x10;
+
+ public String file;
+
+ public IPCPacket10FileRead() {
+ }
+
+ public IPCPacket10FileRead(String file) {
+ this.file = file;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ file = bin.readUTF();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(file);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(file);
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java
new file mode 100644
index 0000000..3bc5f5c
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java
@@ -0,0 +1,44 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket12FileWrite implements IPCPacketBase {
+
+ public static final int ID = 0x12;
+
+ public String path;
+ public byte[] data;
+
+ public IPCPacket12FileWrite() {
+ }
+
+ public IPCPacket12FileWrite(String path, byte[] data) {
+ this.path = path;
+ this.data = data;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ path = bin.readUTF();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(path);
+ bin.writeInt(data.length);
+ bin.write(data);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(path) + 4 + data.length;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java
new file mode 100644
index 0000000..c239968
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java
@@ -0,0 +1,48 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket13FileCopyMove implements IPCPacketBase {
+
+ public static final int ID = 0x13;
+
+ public String fileOldName;
+ public String fileNewName;
+ public boolean copy;
+
+ public IPCPacket13FileCopyMove() {
+ }
+
+ public IPCPacket13FileCopyMove(String fileOldName, String fileNewName, boolean copy) {
+ this.fileOldName = fileOldName;
+ this.fileNewName = fileNewName;
+ this.copy = copy;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ fileOldName = bin.readUTF();
+ fileNewName = bin.readUTF();
+ copy = bin.readBoolean();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(fileOldName);
+ bin.writeUTF(fileNewName);
+ bin.writeBoolean(copy);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(fileOldName) + IPCPacketBase.strLen(fileNewName) + 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java
new file mode 100644
index 0000000..f8992fe
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java
@@ -0,0 +1,80 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class IPCPacket14StringList implements IPCPacketBase {
+
+ public static final int ID = 0x14;
+
+ public static final int FILE_LIST = 0x0;
+ public static final int LOCALE = 0x1;
+ public static final int STAT_GUID = 0x2;
+ public static final int SERVER_TPS = 0x3;
+
+ public int opCode;
+ public final List stringList;
+
+ public IPCPacket14StringList() {
+ stringList = new ArrayList<>();
+ }
+
+ public IPCPacket14StringList(int opcode, String[] list) {
+ stringList = new ArrayList<>();
+ for(String s : list) {
+ s = s.trim();
+ if(s.length() > 0) {
+ stringList.add(s);
+ }
+ }
+ this.opCode = opcode;
+ }
+
+ public IPCPacket14StringList(int opcode, List list) {
+ stringList = new ArrayList<>();
+ for(String s : list) {
+ s = s.trim();
+ if(s.length() > 0) {
+ stringList.add(s);
+ }
+ }
+ this.opCode = opcode;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ stringList.clear();
+ opCode = bin.readByte();
+ int len = bin.readInt();
+ for(int i = 0; i < len; ++i) {
+ stringList.add(bin.readUTF());
+ }
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeByte(opCode);
+ bin.writeInt(stringList.size());
+ for(String str : stringList) {
+ bin.writeUTF(str);
+ }
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ int len = 5;
+ for(String str : stringList) {
+ len += IPCPacketBase.strLen(str);
+ }
+ return len;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java
new file mode 100644
index 0000000..ff4dad3
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java
@@ -0,0 +1,71 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class IPCPacket15ThrowException implements IPCPacketBase {
+
+ public static final int ID = 0x15;
+
+ public String errorMessage;
+ public final List stackTrace;
+
+ public IPCPacket15ThrowException() {
+ stackTrace = new ArrayList<>();
+ }
+
+ public IPCPacket15ThrowException(String errorMessage, String[] list) {
+ stackTrace = new ArrayList<>(Arrays.asList(list));
+ this.errorMessage = errorMessage;
+ }
+
+ public IPCPacket15ThrowException(String errorMessage, List list) {
+ stackTrace = list;
+ this.errorMessage = errorMessage;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ stackTrace.clear();
+ errorMessage = bin.readUTF();
+ int len = bin.readInt();
+ for(int i = 0; i < len; ++i) {
+ stackTrace.add(bin.readUTF());
+ }
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(errorMessage);
+ bin.writeInt(stackTrace.size());
+ for(String str : stackTrace) {
+ bin.writeUTF(str);
+ }
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ int len = 4 + IPCPacketBase.strLen(errorMessage);
+ for(String str : stackTrace) {
+ len += IPCPacketBase.strLen(str);
+ }
+ return len;
+ }
+
+ public void log() {
+ System.err.println("Integrated server exception: " + errorMessage);
+ for(String s : stackTrace) {
+ System.err.println(" at " + s);
+ }
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java
new file mode 100644
index 0000000..b248479
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java
@@ -0,0 +1,95 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.minecraft.src.CompressedStreamTools;
+import net.minecraft.src.NBTTagCompound;
+
+public class IPCPacket16NBTList implements IPCPacketBase {
+
+ public static final int ID = 0x16;
+
+ public static final int WORLD_LIST = 0x0;
+
+ public int opCode;
+ public final List tagList;
+ public final List nbtTagList;
+
+ public IPCPacket16NBTList() {
+ tagList = new LinkedList<>();
+ nbtTagList = new LinkedList<>();
+ }
+
+ public IPCPacket16NBTList(int opcode, NBTTagCompound[] list) {
+ this(opcode, Arrays.asList(list));
+ }
+
+ public IPCPacket16NBTList(int opcode, List list) {
+ tagList = new LinkedList<>();
+ nbtTagList = list;
+ for(int i = 0, size = list.size(); i < size; ++i) {
+ NBTTagCompound tag = list.get(i);
+ try {
+ ByteArrayOutputStream bao = new ByteArrayOutputStream();
+ CompressedStreamTools.write(tag, new DataOutputStream(bao));
+ tagList.add(bao.toByteArray());
+ }catch(IOException e) {
+ System.err.println("Failed to write tag '" + tag.getName() + "' (#" + i + ") in IPCPacket16NBTList");
+ }
+ }
+ opCode = opcode;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ tagList.clear();
+ nbtTagList.clear();
+ opCode = bin.readInt();
+ int count = bin.readInt();
+ for(int i = 0; i < count; ++i) {
+ byte[] toRead = new byte[bin.readInt()];
+ bin.readFully(toRead);
+ tagList.add(toRead);
+ try {
+ nbtTagList.add(CompressedStreamTools.read(new DataInputStream(new ByteArrayInputStream(toRead))));
+ }catch(IOException e) {
+ System.err.println("Failed to read tag #" + i + " in IPCPacket16NBTList");
+ }
+ }
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeInt(opCode);
+ bin.writeInt(tagList.size());
+ for(byte[] str : tagList) {
+ bin.writeInt(str.length);
+ bin.write(str);
+ }
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ int len = 8;
+ for(byte[] str : tagList) {
+ len += 4;
+ len += str.length;
+ }
+ return len;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java
new file mode 100644
index 0000000..1d3f1bd
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java
@@ -0,0 +1,63 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class IPCPacket17ConfigureLAN implements IPCPacketBase {
+
+ public static final int ID = 0x17;
+
+ public int gamemode;
+ public boolean cheats;
+ public final List iceServers;
+
+ public IPCPacket17ConfigureLAN() {
+ iceServers = new ArrayList<>();
+ }
+
+ public IPCPacket17ConfigureLAN(int gamemode, boolean cheats, List iceServers) {
+ this.gamemode = gamemode;
+ this.cheats = cheats;
+ this.iceServers = iceServers;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ gamemode = bin.readUnsignedByte();
+ cheats = bin.readBoolean();
+ iceServers.clear();
+ int iceCount = bin.readUnsignedByte();
+ for(int i = 0; i < iceCount; ++i) {
+ iceServers.add(bin.readUTF());
+ }
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeByte(gamemode);
+ bin.writeBoolean(cheats);
+ bin.writeByte(iceServers.size());
+ for(int i = 0, l = iceServers.size(); i < l; ++i) {
+ bin.writeUTF(iceServers.get(i));
+ }
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ int s = 0;
+ for(int i = 0, l = iceServers.size(); i < l; ++i) {
+ s += 2;
+ s += iceServers.get(i).length();
+ }
+ return 2 + 1 + s;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java
new file mode 100644
index 0000000..f6651c4
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacket18ClearPlayers implements IPCPacketBase {
+
+ public static final int ID = 0x18;
+
+ public String worldName = null;
+
+ public IPCPacket18ClearPlayers(String worldName) {
+ this.worldName = worldName;
+ }
+
+ public IPCPacket18ClearPlayers() {
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ worldName = bin.readUTF();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeUTF(worldName);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return IPCPacketBase.strLen(worldName);
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java
new file mode 100644
index 0000000..f85a0bb
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java
@@ -0,0 +1,33 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public interface IPCPacketBase {
+
+ public void deserialize(DataInput bin) throws IOException;
+ public void serialize(DataOutput bin) throws IOException;
+ public int id();
+ public int size();
+
+ public static int strLen(String s) {
+ int strlen = s.length();
+ int utflen = 2;
+ int c;
+
+ for (int i = 0; i < strlen; ++i) {
+ c = s.charAt(i);
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ ++utflen;
+ } else if (c > 0x07FF) {
+ utflen += 3;
+ } else {
+ utflen += 2;
+ }
+ }
+
+ return utflen;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java
new file mode 100644
index 0000000..c5d6197
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java
@@ -0,0 +1,43 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class IPCPacketFFProcessKeepAlive implements IPCPacketBase {
+
+ public static final int ID = 0xFF;
+
+ public static final int KEEPALIVE = 0;
+ public static final int FAILURE = 0xFE;
+
+ public int ack;
+
+ public IPCPacketFFProcessKeepAlive() {
+ }
+
+ public IPCPacketFFProcessKeepAlive(int ack) {
+ this.ack = ack;
+ }
+
+ @Override
+ public void deserialize(DataInput bin) throws IOException {
+ ack = bin.readUnsignedByte();
+ }
+
+ @Override
+ public void serialize(DataOutput bin) throws IOException {
+ bin.writeByte(ack);
+ }
+
+ @Override
+ public int id() {
+ return ID;
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+
+}
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java
new file mode 100644
index 0000000..5e8f3d2
--- /dev/null
+++ b/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java
@@ -0,0 +1,79 @@
+package net.lax1dude.eaglercraft.sp.ipc;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.function.Supplier;
+
+public class IPCPacketManager {
+
+ public static final HashMap> mappings = new HashMap<>();
+
+ public static final IPCInputStream IPC_INPUT_STREAM = new IPCInputStream();
+ public static final IPCOutputStream IPC_OUTPUT_STREAM = new IPCOutputStream();
+
+ public static final DataInputStream IPC_DATA_INPUT_STREAM = new DataInputStream(IPC_INPUT_STREAM);
+ public static final DataOutputStream IPC_DATA_OUTPUT_STREAM = new DataOutputStream(IPC_OUTPUT_STREAM);
+
+ static {
+ mappings.put(IPCPacket00StartServer.ID, () -> new IPCPacket00StartServer());
+ mappings.put(IPCPacket01StopServer.ID, () -> new IPCPacket01StopServer());
+ mappings.put(IPCPacket02InitWorld.ID, () -> new IPCPacket02InitWorld());
+ mappings.put(IPCPacket03DeleteWorld.ID, () -> new IPCPacket03DeleteWorld());
+ mappings.put(IPCPacket04RenameWorld.ID, () -> new IPCPacket04RenameWorld());
+ mappings.put(IPCPacket05RequestData.ID, () -> new IPCPacket05RequestData());
+ mappings.put(IPCPacket06RenameWorldNBT.ID, () -> new IPCPacket06RenameWorldNBT());
+ mappings.put(IPCPacket07ImportWorld.ID, () -> new IPCPacket07ImportWorld());
+ mappings.put(IPCPacket09RequestResponse.ID, () -> new IPCPacket09RequestResponse());
+ mappings.put(IPCPacket0ASetWorldDifficulty.ID, () -> new IPCPacket0ASetWorldDifficulty());
+ mappings.put(IPCPacket0BPause.ID, () -> new IPCPacket0BPause());
+ mappings.put(IPCPacket0CPlayerChannel.ID, () -> new IPCPacket0CPlayerChannel());
+ mappings.put(IPCPacket0DProgressUpdate.ID, () -> new IPCPacket0DProgressUpdate());
+ mappings.put(IPCPacket0EListWorlds.ID, () -> new IPCPacket0EListWorlds());
+ mappings.put(IPCPacket0FListFiles.ID, () -> new IPCPacket0FListFiles());
+ mappings.put(IPCPacket10FileRead.ID, () -> new IPCPacket10FileRead());
+ mappings.put(IPCPacket12FileWrite.ID, () -> new IPCPacket12FileWrite());
+ mappings.put(IPCPacket13FileCopyMove.ID, () -> new IPCPacket13FileCopyMove());
+ mappings.put(IPCPacket14StringList.ID, () -> new IPCPacket14StringList());
+ mappings.put(IPCPacket15ThrowException.ID, () -> new IPCPacket15ThrowException());
+ mappings.put(IPCPacket16NBTList.ID, () -> new IPCPacket16NBTList());
+ mappings.put(IPCPacket17ConfigureLAN.ID, () -> new IPCPacket17ConfigureLAN());
+ mappings.put(IPCPacket18ClearPlayers.ID, () -> new IPCPacket18ClearPlayers());
+ mappings.put(IPCPacketFFProcessKeepAlive.ID, () -> new IPCPacketFFProcessKeepAlive());
+ }
+
+ public static byte[] IPCSerialize(IPCPacketBase pkt) throws IOException {
+
+ IPC_OUTPUT_STREAM.feedBuffer(new byte[pkt.size() + 1], pkt.getClass().getSimpleName());
+ IPC_OUTPUT_STREAM.write(pkt.id());
+ pkt.serialize(IPC_DATA_OUTPUT_STREAM);
+
+ return IPC_OUTPUT_STREAM.returnBuffer();
+ }
+
+ public static IPCPacketBase IPCDeserialize(byte[] pkt) throws IOException {
+
+ IPC_INPUT_STREAM.feedBuffer(pkt);
+ int i = IPC_INPUT_STREAM.read();
+
+ Supplier pk = mappings.get(Integer.valueOf(i));
+ if(pk == null) {
+ throw new IOException("Packet type 0x" + Integer.toHexString(i) + " doesn't exist");
+ }
+
+ IPCPacketBase p = pk.get();
+
+ IPC_INPUT_STREAM.nameBuffer(p.getClass().getSimpleName());
+
+ p.deserialize(IPC_DATA_INPUT_STREAM);
+
+ int lo = IPC_INPUT_STREAM.getLeftoverCount();
+ if(lo > 0) {
+ System.err.println("Packet type 0x" + Integer.toHexString(i) + " class '" + p.getClass().getSimpleName() + "' was size " + (pkt.length - 1) + " but only " + (pkt.length - 1 - lo) + " bytes were read");
+ }
+
+ return p;
+ }
+
+}
diff --git a/src/main/java/net/minecraft/src/GuiScreenDirectConnect.java b/src/main/java/net/minecraft/src/GuiScreenDirectConnect.java
new file mode 100644
index 0000000..09be543
--- /dev/null
+++ b/src/main/java/net/minecraft/src/GuiScreenDirectConnect.java
@@ -0,0 +1,100 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+
+public class GuiScreenDirectConnect extends GuiScreen {
+ /** Needed a change as a local variable was conflicting on construct */
+ private final GuiScreen guiScreen;
+
+ /** Instance of ServerData. */
+ private final ServerData theServerData;
+ private GuiTextField serverTextField;
+
+ public GuiScreenDirectConnect(GuiScreen par1GuiScreen, ServerData par2ServerData) {
+ this.guiScreen = par1GuiScreen;
+ this.theServerData = par2ServerData;
+ }
+
+ /**
+ * Called from the main game loop to update the screen.
+ */
+ public void updateScreen() {
+ this.serverTextField.updateCursorCounter();
+ }
+
+ /**
+ * Adds the buttons (and other controls) to the screen in question.
+ */
+ public void initGui() {
+ StringTranslate var1 = StringTranslate.getInstance();
+ EaglerAdapter.enableRepeatEvents(true);
+ this.buttonList.clear();
+ this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12, var1.translateKey("selectServer.select")));
+ this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12, var1.translateKey("gui.cancel")));
+ this.serverTextField = new GuiTextField(this.fontRenderer, this.width / 2 - 100, this.height / 4 + 27, 200, 20);
+ this.serverTextField.setMaxStringLength(128);
+ this.serverTextField.setFocused(true);
+ this.serverTextField.setText(this.mc.gameSettings.lastServer);
+ ((GuiButton) this.buttonList.get(0)).enabled = this.serverTextField.getText().length() > 0 && this.serverTextField.getText().split(":").length > 0;
+ }
+
+ /**
+ * Called when the screen is unloaded. Used to disable keyboard repeat events
+ */
+ public void onGuiClosed() {
+ EaglerAdapter.enableRepeatEvents(false);
+ this.mc.gameSettings.lastServer = this.serverTextField.getText();
+ this.mc.gameSettings.saveOptions();
+ }
+
+ /**
+ * Fired when a control is clicked. This is the equivalent of
+ * ActionListener.actionPerformed(ActionEvent e).
+ */
+ protected void actionPerformed(GuiButton par1GuiButton) {
+ if (par1GuiButton.enabled) {
+ if (par1GuiButton.id == 1) {
+ this.guiScreen.confirmClicked(false, 0);
+ } else if (par1GuiButton.id == 0) {
+ this.theServerData.serverIP = this.serverTextField.getText();
+ this.guiScreen.confirmClicked(true, 0);
+ }
+ }
+ }
+
+ /**
+ * Fired when a key is typed. This is the equivalent of
+ * KeyListener.keyTyped(KeyEvent e).
+ */
+ protected void keyTyped(char par1, int par2) {
+ if (this.serverTextField.textboxKeyTyped(par1, par2)) {
+ ((GuiButton) this.buttonList.get(0)).enabled = this.serverTextField.getText().length() > 0 && this.serverTextField.getText().split(":").length > 0;
+ } else if (par2 == 28) {
+ this.actionPerformed((GuiButton) this.buttonList.get(0));
+ }
+ }
+
+ /**
+ * Called when the mouse is clicked.
+ */
+ protected void mouseClicked(int par1, int par2, int par3) {
+ super.mouseClicked(par1, par2, par3);
+ this.serverTextField.mouseClicked(par1, par2, par3);
+ }
+
+ /**
+ * Draws the screen and all the components in it.
+ */
+ public void drawScreen(int par1, int par2, float par3) {
+ StringTranslate var4 = StringTranslate.getInstance();
+ this.drawDefaultBackground();
+ this.drawCenteredString(this.fontRenderer, var4.translateKey("selectServer.direct"), this.width / 2, this.height / 4 - 60 + 20, 16777215);
+ this.drawString(this.fontRenderer, var4.translateKey("addServer.enterIp"), this.width / 2 - 100, this.height / 4 + 12, 10526880);
+ if(EaglerAdapter.isSSLPage()) {
+ this.drawCenteredString(this.fontRenderer, var4.translateKey("addServer.SSLWarn1"), this.width / 2, this.height / 4 + 30 + 28, 0xccccff);
+ this.drawCenteredString(this.fontRenderer, var4.translateKey("addServer.SSLWarn2"), this.width / 2, this.height / 4 + 30 + 40, 0xccccff);
+ }
+ this.serverTextField.drawTextBox();
+ super.drawScreen(par1, par2, par3);
+ }
+}
diff --git a/src/main/java/net/minecraft/src/GuiSlider2.java b/src/main/java/net/minecraft/src/GuiSlider2.java
new file mode 100644
index 0000000..fb55d03
--- /dev/null
+++ b/src/main/java/net/minecraft/src/GuiSlider2.java
@@ -0,0 +1,87 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.minecraft.src.Minecraft;
+
+public class GuiSlider2 extends GuiButton {
+ /** The value of this slider control. */
+ public float sliderValue = 1.0F;
+ public float sliderMax = 1.0F;
+
+ /** Is this slider control being dragged. */
+ public boolean dragging = false;
+
+ public GuiSlider2(int par1, int par2, int par3, int par4, int par5, float par6, float par7) {
+ super(par1, par2, par3, par4, par5, (int)(par6 * par7 * 100.0F) + "%");
+ this.sliderValue = par6;
+ this.sliderMax = par7;
+ }
+
+ /**
+ * Returns 0 if the button is disabled, 1 if the mouse is NOT hovering over this
+ * button and 2 if it IS hovering over this button.
+ */
+ protected int getHoverState(boolean par1) {
+ return 0;
+ }
+
+ /**
+ * Fired when the mouse button is dragged. Equivalent of
+ * MouseListener.mouseDragged(MouseEvent e).
+ */
+ protected void mouseDragged(Minecraft par1Minecraft, int par2, int par3) {
+ if (this.drawButton) {
+ if (this.dragging) {
+ this.sliderValue = (float) (par2 - (this.xPosition + 4)) / (float) (this.width - 8);
+
+ if (this.sliderValue < 0.0F) {
+ this.sliderValue = 0.0F;
+ }
+
+ if (this.sliderValue > 1.0F) {
+ this.sliderValue = 1.0F;
+ }
+
+ this.displayString = (int)(this.sliderValue * this.sliderMax * 100.0F) + "%";
+ }
+
+ if(this.enabled) {
+ EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ this.drawTexturedModalRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 8)), this.yPosition, 0, 66, 4, 20);
+ this.drawTexturedModalRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the mouse has been pressed on this control. Equivalent of
+ * MouseListener.mousePressed(MouseEvent e).
+ */
+ public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) {
+ if (super.mousePressed(par1Minecraft, par2, par3)) {
+ this.sliderValue = (float) (par2 - (this.xPosition + 4)) / (float) (this.width - 8);
+
+ if (this.sliderValue < 0.0F) {
+ this.sliderValue = 0.0F;
+ }
+
+ if (this.sliderValue > 1.0F) {
+ this.sliderValue = 1.0F;
+ }
+
+ this.displayString = (int)(this.sliderValue * this.sliderMax * 100.0F) + "%";
+ this.dragging = true;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Fired when the mouse button is released. Equivalent of
+ * MouseListener.mouseReleased(MouseEvent e).
+ */
+ public void mouseReleased(int par1, int par2) {
+ this.dragging = false;
+ }
+}
diff --git a/src/main/java/net/minecraft/src/GuiSlot.java b/src/main/java/net/minecraft/src/GuiSlot.java
index df2efe6..83d5976 100644
--- a/src/main/java/net/minecraft/src/GuiSlot.java
+++ b/src/main/java/net/minecraft/src/GuiSlot.java
@@ -2,10 +2,11 @@ package net.minecraft.src;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
+import net.lax1dude.eaglercraft.adapter.Tessellator;
public abstract class GuiSlot
{
- private final Minecraft mc;
+ public final Minecraft mc;
/**
* The width of the GuiScreen. Affects the container rendering, but not the overlays.
diff --git a/src/main/java/net/minecraft/src/GuiSlotStatsBlock.java b/src/main/java/net/minecraft/src/GuiSlotStatsBlock.java
index 10c3cd3..a2fd863 100644
--- a/src/main/java/net/minecraft/src/GuiSlotStatsBlock.java
+++ b/src/main/java/net/minecraft/src/GuiSlotStatsBlock.java
@@ -2,6 +2,7 @@ package net.minecraft.src;
import java.util.ArrayList;
import java.util.Iterator;
+import net.lax1dude.eaglercraft.adapter.Tessellator;
class GuiSlotStatsBlock extends GuiSlotStats
{
diff --git a/src/main/java/net/minecraft/src/GuiSlotStatsGeneral.java b/src/main/java/net/minecraft/src/GuiSlotStatsGeneral.java
index 12eef33..658c352 100644
--- a/src/main/java/net/minecraft/src/GuiSlotStatsGeneral.java
+++ b/src/main/java/net/minecraft/src/GuiSlotStatsGeneral.java
@@ -1,5 +1,7 @@
package net.minecraft.src;
+import net.lax1dude.eaglercraft.adapter.Tessellator;
+
class GuiSlotStatsGeneral extends GuiSlot
{
final GuiStats statsGui;
diff --git a/src/main/java/net/minecraft/src/GuiSnooper.java b/src/main/java/net/minecraft/src/GuiSnooper.java
deleted file mode 100644
index 9b57280..0000000
--- a/src/main/java/net/minecraft/src/GuiSnooper.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package net.minecraft.src;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.TreeMap;
-import java.util.Map.Entry;
-
-public class GuiSnooper extends GuiScreen
-{
- /** Instance of GuiScreen. */
- private final GuiScreen snooperGuiScreen;
-
- /** Instance of GameSettings. */
- private final GameSettings snooperGameSettings;
- private final List field_74098_c = new ArrayList();
- private final List field_74096_d = new ArrayList();
-
- /** The Snooper title. */
- private String snooperTitle;
- private String[] field_74101_n;
- private GuiSnooperList snooperList;
- private GuiButton buttonAllowSnooping;
-
- public GuiSnooper(GuiScreen par1GuiScreen, GameSettings par2GameSettings)
- {
- this.snooperGuiScreen = par1GuiScreen;
- this.snooperGameSettings = par2GameSettings;
- }
-
- /**
- * Adds the buttons (and other controls) to the screen in question.
- */
- public void initGui()
- {
- this.snooperTitle = I18n.getString("options.snooper.title");
- String var1 = I18n.getString("options.snooper.desc");
- ArrayList var2 = new ArrayList();
- Iterator var3 = this.fontRenderer.listFormattedStringToWidth(var1, this.width - 30).iterator();
-
- while (var3.hasNext())
- {
- String var4 = (String)var3.next();
- var2.add(var4);
- }
-
- this.field_74101_n = (String[])var2.toArray(new String[0]);
- this.field_74098_c.clear();
- this.field_74096_d.clear();
- this.buttonList.add(this.buttonAllowSnooping = new GuiButton(1, this.width / 2 - 152, this.height - 30, 150, 20, this.snooperGameSettings.getKeyBinding(EnumOptions.SNOOPER_ENABLED)));
- this.buttonList.add(new GuiButton(2, this.width / 2 + 2, this.height - 30, 150, 20, I18n.getString("gui.done")));
- boolean var6 = this.mc.getIntegratedServer() != null && this.mc.getIntegratedServer().getPlayerUsageSnooper() != null;
- Iterator var7 = (new TreeMap(this.mc.getPlayerUsageSnooper().getCurrentStats())).entrySet().iterator();
- Entry var5;
-
- while (var7.hasNext())
- {
- var5 = (Entry)var7.next();
- this.field_74098_c.add((var6 ? "C " : "") + (String)var5.getKey());
- this.field_74096_d.add(this.fontRenderer.trimStringToWidth((String)var5.getValue(), this.width - 220));
- }
-
- if (var6)
- {
- var7 = (new TreeMap(this.mc.getIntegratedServer().getPlayerUsageSnooper().getCurrentStats())).entrySet().iterator();
-
- while (var7.hasNext())
- {
- var5 = (Entry)var7.next();
- this.field_74098_c.add("S " + (String)var5.getKey());
- this.field_74096_d.add(this.fontRenderer.trimStringToWidth((String)var5.getValue(), this.width - 220));
- }
- }
-
- this.snooperList = new GuiSnooperList(this);
- }
-
- /**
- * Fired when a control is clicked. This is the equivalent of ActionListener.actionPerformed(ActionEvent e).
- */
- protected void actionPerformed(GuiButton par1GuiButton)
- {
- if (par1GuiButton.enabled)
- {
- if (par1GuiButton.id == 2)
- {
- this.snooperGameSettings.saveOptions();
- this.snooperGameSettings.saveOptions();
- this.mc.displayGuiScreen(this.snooperGuiScreen);
- }
-
- if (par1GuiButton.id == 1)
- {
- this.snooperGameSettings.setOptionValue(EnumOptions.SNOOPER_ENABLED, 1);
- this.buttonAllowSnooping.displayString = this.snooperGameSettings.getKeyBinding(EnumOptions.SNOOPER_ENABLED);
- }
- }
- }
-
- /**
- * Draws the screen and all the components in it.
- */
- public void drawScreen(int par1, int par2, float par3)
- {
- this.drawDefaultBackground();
- this.snooperList.drawScreen(par1, par2, par3);
- this.drawCenteredString(this.fontRenderer, this.snooperTitle, this.width / 2, 8, 16777215);
- int var4 = 22;
- String[] var5 = this.field_74101_n;
- int var6 = var5.length;
-
- for (int var7 = 0; var7 < var6; ++var7)
- {
- String var8 = var5[var7];
- this.drawCenteredString(this.fontRenderer, var8, this.width / 2, var4, 8421504);
- var4 += this.fontRenderer.FONT_HEIGHT;
- }
-
- super.drawScreen(par1, par2, par3);
- }
-
- static List func_74095_a(GuiSnooper par0GuiSnooper)
- {
- return par0GuiSnooper.field_74098_c;
- }
-
- static List func_74094_b(GuiSnooper par0GuiSnooper)
- {
- return par0GuiSnooper.field_74096_d;
- }
-}
diff --git a/src/main/java/net/minecraft/src/GuiSnooperList.java b/src/main/java/net/minecraft/src/GuiSnooperList.java
deleted file mode 100644
index 1e56472..0000000
--- a/src/main/java/net/minecraft/src/GuiSnooperList.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package net.minecraft.src;
-
-class GuiSnooperList extends GuiSlot
-{
- final GuiSnooper snooperGui;
-
- public GuiSnooperList(GuiSnooper par1GuiSnooper)
- {
- super(par1GuiSnooper.mc, par1GuiSnooper.width, par1GuiSnooper.height, 80, par1GuiSnooper.height - 40, par1GuiSnooper.fontRenderer.FONT_HEIGHT + 1);
- this.snooperGui = par1GuiSnooper;
- }
-
- /**
- * Gets the size of the current slot list.
- */
- protected int getSize()
- {
- return GuiSnooper.func_74095_a(this.snooperGui).size();
- }
-
- /**
- * the element in the slot that was clicked, boolean for wether it was double clicked or not
- */
- protected void elementClicked(int par1, boolean par2) {}
-
- /**
- * returns true if the element passed in is currently selected
- */
- protected boolean isSelected(int par1)
- {
- return false;
- }
-
- protected void drawBackground() {}
-
- protected void drawSlot(int par1, int par2, int par3, int par4, Tessellator par5Tessellator)
- {
- this.snooperGui.fontRenderer.drawString((String)GuiSnooper.func_74095_a(this.snooperGui).get(par1), 10, par3, 16777215);
- this.snooperGui.fontRenderer.drawString((String)GuiSnooper.func_74094_b(this.snooperGui).get(par1), 230, par3, 16777215);
- }
-
- protected int getScrollBarX()
- {
- return this.snooperGui.width - 10;
- }
-}
diff --git a/src/main/java/net/minecraft/src/GuiTexturePackSlot.java b/src/main/java/net/minecraft/src/GuiTexturePackSlot.java
new file mode 100644
index 0000000..5294b71
--- /dev/null
+++ b/src/main/java/net/minecraft/src/GuiTexturePackSlot.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.lax1dude.eaglercraft.adapter.Tessellator;
+
+class GuiTexturePackSlot extends GuiSlot {
+ final GuiTexturePacks parentTexturePackGui;
+
+ public GuiTexturePackSlot(GuiTexturePacks par1GuiTexturePacks) {
+ super(par1GuiTexturePacks.mc, par1GuiTexturePacks.width, par1GuiTexturePacks.height, 32, par1GuiTexturePacks.height - 55 + 4, 36);
+ this.parentTexturePackGui = par1GuiTexturePacks;
+ }
+
+ /**
+ * Gets the size of the current slot list.
+ */
+ protected int getSize() {
+ return this.mc.texturePackList.availableTexturePacks().size();
+ }
+
+ /**
+ * the element in the slot that was clicked, boolean for wether it was double
+ * clicked or not
+ */
+ protected void elementClicked(int par1, boolean par2) {
+ if (par1 == 0 || !this.isSelected(par1)) {
+ this.parentTexturePackGui.confirmClicked(false, par1);
+ } else {
+ this.mc.displayGuiScreen(new GuiYesNo(this.parentTexturePackGui, StatCollector.translateToLocal("texturePack.wannaDelete"), ((ITexturePack) this.mc.texturePackList.availableTexturePacks().get(par1)).getTexturePackFileName(), par1));
+ }
+ }
+
+ /**
+ * returns true if the element passed in is currently selected
+ */
+ protected boolean isSelected(int par1) {
+ List var2 = this.mc.texturePackList.availableTexturePacks();
+ return this.mc.texturePackList.getSelectedTexturePack() == var2.get(par1);
+ }
+
+ /**
+ * return the height of the content being scrolled
+ */
+ protected int getContentHeight() {
+ return this.getSize() * 36;
+ }
+
+ protected void drawBackground() {
+ this.parentTexturePackGui.drawDefaultBackground();
+ }
+
+ protected void drawSlot(int par1, int par2, int par3, int par4, Tessellator par5Tessellator) {
+ ITexturePack var6 = (ITexturePack) this.mc.texturePackList.availableTexturePacks().get(par1);
+ var6.bindThumbnailTexture(this.mc.renderEngine);
+ EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+ par5Tessellator.startDrawingQuads();
+ par5Tessellator.setColorOpaque_I(16777215);
+ par5Tessellator.addVertexWithUV((double) par2, (double) (par3 + par4), 0.0D, 0.0D, 1.0D);
+ par5Tessellator.addVertexWithUV((double) (par2 + 32), (double) (par3 + par4), 0.0D, 1.0D, 1.0D);
+ par5Tessellator.addVertexWithUV((double) (par2 + 32), (double) par3, 0.0D, 1.0D, 0.0D);
+ par5Tessellator.addVertexWithUV((double) par2, (double) par3, 0.0D, 0.0D, 0.0D);
+ par5Tessellator.draw();
+ String var7 = var6.getTexturePackFileName();
+
+ if (!var6.isCompatible()) {
+ var7 = EnumChatFormatting.DARK_RED + StatCollector.translateToLocal("texturePack.incompatible") + " - " + var7;
+ }
+
+ if (var7.length() > 32) {
+ var7 = var7.substring(0, 32).trim() + "...";
+ }
+
+ this.parentTexturePackGui.drawString(this.mc.fontRenderer, var7, par2 + 32 + 2, par3 + 1, 16777215);
+ this.parentTexturePackGui.drawString(this.mc.fontRenderer, var6.getFirstDescriptionLine(), par2 + 32 + 2, par3 + 12, 8421504);
+ this.parentTexturePackGui.drawString(this.mc.fontRenderer, var6.getSecondDescriptionLine(), par2 + 32 + 2, par3 + 12 + 10, 8421504);
+ }
+}
diff --git a/src/main/java/net/minecraft/src/GuiTexturePacks.java b/src/main/java/net/minecraft/src/GuiTexturePacks.java
new file mode 100644
index 0000000..e483c1a
--- /dev/null
+++ b/src/main/java/net/minecraft/src/GuiTexturePacks.java
@@ -0,0 +1,183 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.EPKDecompiler;
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.lax1dude.eaglercraft.EaglerInputStream;
+import net.lax1dude.eaglercraft.adapter.vfs.VFile;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class GuiTexturePacks extends GuiScreen {
+ protected GuiScreen guiScreen;
+ private int refreshTimer = -1;
+
+ /** the absolute location of this texture pack */
+ private String fileLocation = "";
+
+ private boolean isSelectingPack = false;
+
+ /**
+ * the GuiTexturePackSlot that contains all the texture packs and their
+ * descriptions
+ */
+ private GuiTexturePackSlot guiTexturePackSlot;
+ private GameSettings field_96146_n;
+
+ protected static final VFile texturePackListFile = new VFile("__LIST__");
+
+ public GuiTexturePacks(GuiScreen par1, GameSettings par2) {
+ this.guiScreen = par1;
+ this.field_96146_n = par2;
+ }
+
+ /**
+ * Adds the buttons (and other controls) to the screen in question.
+ */
+ public void initGui() {
+ StringTranslate var1 = StringTranslate.getInstance();
+ this.buttonList.add(new GuiSmallButton(5, this.width / 2 - 154, this.height - 48, var1.translateKey("texturePack.openFolder")));
+ this.buttonList.add(new GuiSmallButton(6, this.width / 2 + 4, this.height - 48, var1.translateKey("gui.done")));
+ this.mc.texturePackList.updateAvaliableTexturePacks();
+ this.fileLocation = "texturepacks";
+ this.guiTexturePackSlot = new GuiTexturePackSlot(this);
+ this.guiTexturePackSlot.registerScrollButtons(this.buttonList, 7, 8);
+ }
+
+ /**
+ * Fired when a control is clicked. This is the equivalent of
+ * ActionListener.actionPerformed(ActionEvent e).
+ */
+ protected void actionPerformed(GuiButton par1GuiButton) {
+ if (par1GuiButton.enabled) {
+ if (par1GuiButton.id == 5) {
+ isSelectingPack = true;
+ EaglerAdapter.openFileChooser("epk,.zip", null);
+ } else if (par1GuiButton.id == 6) {
+ // this.mc.renderEngine.refreshTextures();
+ this.mc.displayGuiScreen(guiScreen);
+ } else {
+ this.guiTexturePackSlot.actionPerformed(par1GuiButton);
+ }
+ }
+ }
+
+ /**
+ * Called when the mouse is clicked.
+ */
+ protected void mouseClicked(int par1, int par2, int par3) {
+ super.mouseClicked(par1, par2, par3);
+ }
+
+ /**
+ * Called when the mouse is moved or a mouse button is released. Signature:
+ * (mouseX, mouseY, which) which==-1 is mouseMove, which==0 or which==1 is
+ * mouseUp
+ */
+ protected void mouseMovedOrUp(int par1, int par2, int par3) {
+ super.mouseMovedOrUp(par1, par2, par3);
+ }
+
+ /**
+ * Draws the screen and all the components in it.
+ */
+ public void drawScreen(int par1, int par2, float par3) {
+ this.guiTexturePackSlot.drawScreen(par1, par2, par3);
+
+ if (this.refreshTimer <= 0) {
+ this.mc.texturePackList.updateAvaliableTexturePacks();
+ this.refreshTimer += 20;
+ }
+
+ StringTranslate var4 = StringTranslate.getInstance();
+ this.drawCenteredString(this.fontRenderer, var4.translateKey("texturePack.title"), this.width / 2, 16, 16777215);
+ this.drawCenteredString(this.fontRenderer, var4.translateKey("texturePack.folderInfo"), this.width / 2 - 77, this.height - 26, 8421504);
+ super.drawScreen(par1, par2, par3);
+ }
+
+ /**
+ * Called from the main game loop to update the screen.
+ */
+ public void updateScreen() {
+ super.updateScreen();
+ --this.refreshTimer;
+ if (isSelectingPack && EaglerAdapter.getFileChooserResultAvailable()) {
+ isSelectingPack = false;
+ String name = EaglerAdapter.getFileChooserResultName();
+ String safeName = name.replaceAll("[^A-Za-z0-9_]", "_");
+ if (texturePackListFile.exists()) {
+ texturePackListFile.setAllChars(texturePackListFile.getAllChars() + "\n" + safeName);
+ } else {
+ texturePackListFile.setAllChars(safeName);
+ }
+ try {
+ if (name.toLowerCase().endsWith(".zip")) {
+ try(ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(EaglerAdapter.getFileChooserResult()))) {
+ ZipEntry entry;
+ while ((entry = zipInputStream.getNextEntry()) != null) {
+ if (entry.isDirectory()) continue;
+ new VFile(fileLocation, safeName, entry.getName()).setAllBytes(EaglerInputStream.inputStreamToBytesNoClose(zipInputStream));
+ }
+ }
+ } else {
+ EPKDecompiler epkDecompiler = new EPKDecompiler(EaglerAdapter.getFileChooserResult());
+ EPKDecompiler.FileEntry file;
+ while ((file = epkDecompiler.readFile()) != null) {
+ new VFile(fileLocation, safeName, file.name).setAllBytes(file.data);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ EaglerAdapter.clearFileChooserResult();
+ this.mc.displayGuiScreen(this);
+ }
+ }
+
+ @Override
+ public void confirmClicked(boolean par1, int par2) {
+ this.mc.displayGuiScreen(this);
+
+ List var3 = this.mc.texturePackList.availableTexturePacks();
+
+ if (par1) {
+ this.mc.texturePackList.setTexturePack((ITexturePack) var3.get(0));
+ this.mc.renderEngine.refreshTextures();
+ this.mc.renderGlobal.loadRenderers();
+ String safeName = ((ITexturePack) var3.get(par2)).getTexturePackFileName();
+ new VFile(fileLocation, safeName).deleteAll();
+ if (texturePackListFile.exists()) {
+ String res = texturePackListFile.getAllChars().replaceFirst(safeName, "").replace("\n\n", "\n");
+ if (res.isEmpty()) {
+ texturePackListFile.delete();
+ } else {
+ texturePackListFile.setAllChars(res);
+ }
+ }
+ } else {
+ try {
+ this.mc.texturePackList.setTexturePack((ITexturePack) var3.get(par2));
+ this.mc.renderEngine.refreshTextures();
+ this.mc.renderGlobal.loadRenderers();
+ } catch (Exception var5) {
+ var5.printStackTrace();
+ this.mc.texturePackList.setTexturePack((ITexturePack) var3.get(0));
+ this.mc.renderEngine.refreshTextures();
+ this.mc.renderGlobal.loadRenderers();
+ String safeName = ((ITexturePack) var3.get(par2)).getTexturePackFileName();
+ new VFile(fileLocation, safeName).deleteAll();
+ if (texturePackListFile.exists()) {
+ String res = texturePackListFile.getAllChars().replaceFirst(safeName, "").replace("\n\n", "\n");
+ if (res.isEmpty()) {
+ texturePackListFile.delete();
+ } else {
+ texturePackListFile.setAllChars(res);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/src/GuiWorldSlot.java b/src/main/java/net/minecraft/src/GuiWorldSlot.java
index 38828cf..3f1217c 100644
--- a/src/main/java/net/minecraft/src/GuiWorldSlot.java
+++ b/src/main/java/net/minecraft/src/GuiWorldSlot.java
@@ -1,6 +1,7 @@
package net.minecraft.src;
import java.util.Date;
+import net.lax1dude.eaglercraft.adapter.Tessellator;
class GuiWorldSlot extends GuiSlot
{
diff --git a/src/main/java/net/minecraft/src/ITexturePack.java b/src/main/java/net/minecraft/src/ITexturePack.java
new file mode 100644
index 0000000..2d5920d
--- /dev/null
+++ b/src/main/java/net/minecraft/src/ITexturePack.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface ITexturePack
+{
+ /**
+ * Delete the OpenGL texture id of the pack's thumbnail image, and close the zip file in case of TexturePackCustom.
+ */
+ void deleteTexturePack(RenderEngine var1);
+
+ /**
+ * Bind the texture id of the pack's thumbnail image, loading it if necessary.
+ */
+ void bindThumbnailTexture(RenderEngine var1);
+
+ InputStream func_98137_a(String var1, boolean var2) throws IOException;
+
+ /**
+ * Gives a texture resource as InputStream.
+ */
+ byte[] getResourceAsBytes(String var1);
+
+ /**
+ * Get the texture pack ID
+ */
+ String getTexturePackID();
+
+ /**
+ * Get the file name of the texture pack, or Default if not from a custom texture pack
+ */
+ String getTexturePackFileName();
+
+ /**
+ * Get the first line of the texture pack description (read from the pack.txt file)
+ */
+ String getFirstDescriptionLine();
+
+ /**
+ * Get the second line of the texture pack description (read from the pack.txt file)
+ */
+ String getSecondDescriptionLine();
+
+ boolean func_98138_b(String var1, boolean var2);
+
+ boolean isCompatible();
+}
diff --git a/src/main/java/net/minecraft/src/Minecraft.java b/src/main/java/net/minecraft/src/Minecraft.java
index c5b7f11..c919c24 100644
--- a/src/main/java/net/minecraft/src/Minecraft.java
+++ b/src/main/java/net/minecraft/src/Minecraft.java
@@ -7,10 +7,8 @@ import net.lax1dude.eaglercraft.GuiScreenEditProfile;
import net.lax1dude.eaglercraft.GuiScreenSingleplayerConnecting;
import net.lax1dude.eaglercraft.GuiScreenSingleplayerLoading;
import net.lax1dude.eaglercraft.GuiScreenVSyncWarning;
-import net.lax1dude.eaglercraft.GuiVoiceOverlay;
import net.lax1dude.eaglercraft.IntegratedServer;
import net.lax1dude.eaglercraft.IntegratedServerLAN;
-import net.lax1dude.eaglercraft.Voice;
import net.lax1dude.eaglercraft.WorkerNetworkManager;
import net.lax1dude.eaglercraft.adapter.Tessellator;
import net.lax1dude.eaglercraft.glemu.FixedFunctionShader;
@@ -131,7 +129,6 @@ public class Minecraft implements IPlayerUsage
public final File mcDataDir;
private final File fileAssets;
private final String launchedVersion;
- private final Proxy proxy;
private ISaveFormat saveLoader;
/**
@@ -168,7 +165,6 @@ public class Minecraft implements IPlayerUsage
/** Join player counter */
private int joinPlayerCounter;
- private final boolean isDemo;
private INetworkManager myNetworkManager;
private boolean integratedServerIsRunning;
@@ -2368,11 +2364,6 @@ public class Minecraft implements IPlayerUsage
return this.session;
}
- public Proxy getProxy()
- {
- return this.proxy;
- }
-
public TextureManager getTextureManager()
{
return this.renderEngine;
diff --git a/src/main/java/net/minecraft/src/Packet3Chat.java b/src/main/java/net/minecraft/src/Packet3Chat.java
index 50abf80..237d1c5 100644
--- a/src/main/java/net/minecraft/src/Packet3Chat.java
+++ b/src/main/java/net/minecraft/src/Packet3Chat.java
@@ -6,6 +6,7 @@ import java.io.IOException;
public class Packet3Chat extends Packet
{
+ public static int maxChatLength = 119;
/** The message being sent. */
public String message;
private boolean isServer;
diff --git a/src/main/java/net/minecraft/src/Rect2i.java b/src/main/java/net/minecraft/src/Rect2i.java
new file mode 100644
index 0000000..b8598c0
--- /dev/null
+++ b/src/main/java/net/minecraft/src/Rect2i.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+
+
+public class Rect2i {
+ private int rectX;
+ private int rectY;
+ private int rectWidth;
+ private int rectHeight;
+
+ public Rect2i(int par1, int par2, int par3, int par4) {
+ this.rectX = par1;
+ this.rectY = par2;
+ this.rectWidth = par3;
+ this.rectHeight = par4;
+ }
+
+ public Rect2i intersection(Rect2i par1Rect2i) {
+ int var2 = this.rectX;
+ int var3 = this.rectY;
+ int var4 = this.rectX + this.rectWidth;
+ int var5 = this.rectY + this.rectHeight;
+ int var6 = par1Rect2i.getRectX();
+ int var7 = par1Rect2i.getRectY();
+ int var8 = var6 + par1Rect2i.getRectWidth();
+ int var9 = var7 + par1Rect2i.getRectHeight();
+ this.rectX = Math.max(var2, var6);
+ this.rectY = Math.max(var3, var7);
+ this.rectWidth = Math.max(0, Math.min(var4, var8) - this.rectX);
+ this.rectHeight = Math.max(0, Math.min(var5, var9) - this.rectY);
+ return this;
+ }
+
+ public int getRectX() {
+ return this.rectX;
+ }
+
+ public int getRectY() {
+ return this.rectY;
+ }
+
+ public int getRectWidth() {
+ return this.rectWidth;
+ }
+
+ public int getRectHeight() {
+ return this.rectHeight;
+ }
+}
diff --git a/src/main/java/net/minecraft/src/RenderEngine.java b/src/main/java/net/minecraft/src/RenderEngine.java
new file mode 100644
index 0000000..615f1fa
--- /dev/null
+++ b/src/main/java/net/minecraft/src/RenderEngine.java
@@ -0,0 +1,359 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.lax1dude.eaglercraft.EaglerImage;
+import net.lax1dude.eaglercraft.TextureLocation;
+import net.lax1dude.eaglercraft.TextureTerrainMap;
+import net.minecraft.src.Minecraft;
+
+public class RenderEngine {
+ private HashMap textureMap = new HashMap();
+
+ /** Texture contents map (key: texture name, value: int[] contents) */
+ private HashMap textureContentsMap = new HashMap();
+
+ /** A mapping from GL texture names (integers) to BufferedImage instances */
+ private IntHashMap textureNameToImageMap = new IntHashMap();
+
+ /** Stores the image data for the texture. */
+ private IntBuffer imageData;
+
+ /** A mapping from image URLs to ThreadDownloadImageData instances */
+ private Map urlToImageDataMap = new HashMap();
+
+ /** Reference to the GameSettings object */
+ private GameSettings options;
+
+ /** Texture pack */
+ private TexturePackList texturePack;
+
+ /** Missing texture image */
+ private EaglerImage missingTextureImage;
+ private final TextureTerrainMap textureMapBlocks;
+ private final TextureMap textureMapItems;
+ private int boundTexture;
+
+ public RenderEngine(TexturePackList par1TexturePackList, GameSettings par2GameSettings) {
+ this.imageData = GLAllocation.createDirectIntBuffer(16777216 >> 2);
+ this.texturePack = par1TexturePackList;
+ this.options = par2GameSettings;
+ int[] missingTex = new int[256];
+ for(int i = 0; i < 256; ++i) {
+ missingTex[i] = ((i / 16 + (i % 16)) % 2 == 0) ? 0xffff00ff : 0xff000000;
+ }
+ this.missingTextureImage = new EaglerImage(missingTex, 16, 16, true);
+ this.textureMapBlocks = new TextureTerrainMap(1024, "terrain", "textures/blocks/", this.missingTextureImage);
+ this.textureMapItems = new TextureMap(1, "items", "textures/items/", this.missingTextureImage);
+ }
+
+ public int[] getTextureContents(String par1Str) {
+ ITexturePack var2 = this.texturePack.getSelectedTexturePack();
+ int[] var3 = (int[]) this.textureContentsMap.get(par1Str);
+
+ if (var3 != null) {
+ return var3;
+ } else {
+ byte[] var7 = var2.getResourceAsBytes(par1Str);
+ int[] var4;
+
+ if (var7 == null) {
+ var4 = this.missingTextureImage.data;
+ } else {
+ //var4 = EaglerImage.loadImage(var7).data;
+ var4 = EaglerAdapter.loadPNG(var7).data;
+ }
+
+ this.textureContentsMap.put(par1Str, var4);
+ return var4;
+ }
+ }
+
+
+ public void bindTexture(String par1Str) {
+ this.bindTexture(this.getTexture(par1Str));
+ }
+
+ public void bindTexture(int par1) {
+ if (par1 != this.boundTexture) {
+ EaglerAdapter.glBindTexture(EaglerAdapter.GL_TEXTURE_2D, par1);
+ this.boundTexture = par1;
+ }
+ }
+
+ public void resetBoundTexture() {
+ this.boundTexture = -1;
+ }
+
+ public int getTexture(String par1Str) {
+ if (par1Str.equals("/terrain.png")) {
+ return this.textureMapBlocks.texture;
+ } else if (par1Str.equals("/gui/items.png")) {
+ this.textureMapItems.getTexture().bindTexture(0);
+ return this.textureMapItems.getTexture().getGlTextureId();
+ } else {
+ Integer var2 = (Integer) this.textureMap.get(par1Str);
+
+ if (var2 != null) {
+ return var2.intValue();
+ } else {
+ String var8 = par1Str;
+
+ try {
+ int var3 = GLAllocation.generateTextureNames();
+ boolean var9 = par1Str.startsWith("%blur%");
+
+ if (var9) {
+ par1Str = par1Str.substring(6);
+ }
+
+ boolean var5 = par1Str.startsWith("%clamp%");
+
+ if (var5) {
+ par1Str = par1Str.substring(7);
+ }
+
+ byte[] var6 = this.texturePack.getSelectedTexturePack().getResourceAsBytes(par1Str);
+
+ if (var6 == null) {
+ this.setupTextureExt(this.missingTextureImage, var3, var9, var5);
+ } else {
+ this.setupTextureExt(EaglerImage.loadImage(var6), var3, var9, var5);
+ }
+
+ this.textureMap.put(var8, Integer.valueOf(var3));
+ return var3;
+ } catch (Exception var7) {
+ var7.printStackTrace();
+ int var4 = GLAllocation.generateTextureNames();
+ this.setupTexture(this.missingTextureImage, var4);
+ this.textureMap.put(par1Str, Integer.valueOf(var4));
+ return var4;
+ }
+ }
+ }
+ }
+
+ /**
+ * Copy the supplied image onto a newly-allocated OpenGL texture, returning the
+ * allocated texture name
+ */
+ public int allocateAndSetupTexture(EaglerImage par1BufferedImage) {
+ int var2 = GLAllocation.generateTextureNames();
+ this.setupTexture(par1BufferedImage, var2);
+ this.textureNameToImageMap.addKey(var2, par1BufferedImage);
+ return var2;
+ }
+
+ /**
+ * Copy the supplied image onto the specified OpenGL texture
+ */
+ public void setupTexture(EaglerImage par1BufferedImage, int par2) {
+ this.setupTextureExt(par1BufferedImage, par2, false, false);
+ }
+
+ public int makeViewportTexture(int w, int h) {
+ int t = EaglerAdapter.glGenTextures();
+ this.bindTexture(t);
+ this.imageData.position(0).limit(w * h);
+ EaglerAdapter.glTexImage2D_2(EaglerAdapter.GL_TEXTURE_2D, 0, EaglerAdapter.GL_RGBA, w, h, 0, EaglerAdapter.GL_BGRA, EaglerAdapter.GL_UNSIGNED_INT_8_8_8_8_REV, this.imageData);
+ return t;
+ }
+
+ public void setupTextureExt(EaglerImage par1BufferedImage, int par2, boolean par3, boolean par4) {
+ this.bindTexture(par2);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MIN_FILTER, EaglerAdapter.GL_NEAREST);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MAG_FILTER, EaglerAdapter.GL_NEAREST);
+
+ if (par3) {
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MIN_FILTER, EaglerAdapter.GL_LINEAR);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MAG_FILTER, EaglerAdapter.GL_LINEAR);
+ }
+
+ if (par4) {
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_S, EaglerAdapter.GL_CLAMP);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_T, EaglerAdapter.GL_CLAMP);
+ } else {
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_S, EaglerAdapter.GL_REPEAT);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_T, EaglerAdapter.GL_REPEAT);
+ }
+
+ int var5 = par1BufferedImage.w;
+ int var6 = par1BufferedImage.h;
+ int[] var7 = par1BufferedImage.data;
+
+ if (this.options != null && this.options.anaglyph) {
+ var7 = this.colorToAnaglyph(var7);
+ }
+
+ this.imageData.clear();
+ this.imageData.put(var7);
+ this.imageData.position(0).limit(var7.length);
+ EaglerAdapter.glTexImage2D(EaglerAdapter.GL_TEXTURE_2D, 0, EaglerAdapter.GL_RGBA, var5, var6, 0, EaglerAdapter.GL_BGRA, EaglerAdapter.GL_UNSIGNED_INT_8_8_8_8_REV, this.imageData);
+ }
+
+ public int setupTextureRaw(byte[] data, int w, int h) {
+ int e = GLAllocation.generateTextureNames();
+ this.bindTexture(e);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MIN_FILTER, EaglerAdapter.GL_NEAREST);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MAG_FILTER, EaglerAdapter.GL_NEAREST);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_S, EaglerAdapter.GL_CLAMP);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_T, EaglerAdapter.GL_CLAMP);
+ this.imageData.clear();
+ int[] upload = new int[data.length / 4];
+ for(int i = 0; i < upload.length; ++i) {
+ upload[i] = ((data[i*4+3] & 255) << 24) | ((data[i*4+2] & 255) << 16) | ((data[i*4+1] & 255) << 8) | (data[i*4] & 255);
+ }
+ this.imageData.put(upload).flip();
+ EaglerAdapter.glTexImage2D(EaglerAdapter.GL_TEXTURE_2D, 0, EaglerAdapter.GL_RGBA, w, h, 0, EaglerAdapter.GL_BGRA, EaglerAdapter.GL_UNSIGNED_INT_8_8_8_8_REV, this.imageData);
+ return e;
+ }
+
+ private int[] colorToAnaglyph(int[] par1ArrayOfInteger) {
+ int[] var2 = new int[par1ArrayOfInteger.length];
+
+ for (int var3 = 0; var3 < par1ArrayOfInteger.length; ++var3) {
+ int var4 = par1ArrayOfInteger[var3] >> 24 & 255;
+ int var5 = par1ArrayOfInteger[var3] >> 16 & 255;
+ int var6 = par1ArrayOfInteger[var3] >> 8 & 255;
+ int var7 = par1ArrayOfInteger[var3] & 255;
+ int var8 = (var5 * 30 + var6 * 59 + var7 * 11) / 100;
+ int var9 = (var5 * 30 + var6 * 70) / 100;
+ int var10 = (var5 * 30 + var7 * 70) / 100;
+ var2[var3] = var4 << 24 | var8 << 16 | var9 << 8 | var10;
+ }
+
+ return var2;
+ }
+
+ public void createTextureFromBytes(int[] par1ArrayOfInteger, int par2, int par3, int par4) {
+ this.bindTexture(par4);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MIN_FILTER, EaglerAdapter.GL_NEAREST);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_MAG_FILTER, EaglerAdapter.GL_NEAREST);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_S, EaglerAdapter.GL_REPEAT);
+ EaglerAdapter.glTexParameteri(EaglerAdapter.GL_TEXTURE_2D, EaglerAdapter.GL_TEXTURE_WRAP_T, EaglerAdapter.GL_REPEAT);
+
+ if (this.options != null && this.options.anaglyph) {
+ par1ArrayOfInteger = this.colorToAnaglyph(par1ArrayOfInteger);
+ }
+
+ this.imageData.clear();
+ this.imageData.put(par1ArrayOfInteger);
+ this.imageData.position(0).limit(par1ArrayOfInteger.length);
+ EaglerAdapter.glTexSubImage2D(EaglerAdapter.GL_TEXTURE_2D, 0, 0, 0, par2, par3, EaglerAdapter.GL_BGRA, EaglerAdapter.GL_UNSIGNED_INT_8_8_8_8_REV, this.imageData);
+ }
+
+ /**
+ * Deletes a single GL texture
+ */
+ public void deleteTexture(int par1) {
+ this.textureNameToImageMap.removeObject(par1);
+ EaglerAdapter.glDeleteTextures(par1);
+ }
+
+ public void updateDynamicTextures() {
+ this.textureMapBlocks.updateAnimations();
+ this.textureMapItems.updateAnimations();
+ }
+
+ /**
+ * Call setupTexture on all currently-loaded textures again to account for
+ * changes in rendering options
+ */
+ public void refreshTextures() {
+ TextureLocation.freeTextures();
+ ITexturePack var1 = this.texturePack.getSelectedTexturePack();
+ this.refreshTextureMaps();
+ Iterator var2 = this.textureNameToImageMap.getKeySet().iterator();
+ EaglerImage var4;
+
+ while (var2.hasNext()) {
+ int var3 = ((Integer) var2.next()).intValue();
+ var4 = (EaglerImage) this.textureNameToImageMap.lookup(var3);
+ this.setupTexture(var4, var3);
+ }
+
+ var2 = this.textureMap.keySet().iterator();
+ String var11;
+
+ while (var2.hasNext()) {
+ var11 = (String) var2.next();
+
+ try {
+ int var12 = ((Integer) this.textureMap.get(var11)).intValue();
+ boolean var6 = var11.startsWith("%blur%");
+
+ if (var6) {
+ var11 = var11.substring(6);
+ }
+
+ boolean var7 = var11.startsWith("%clamp%");
+
+ if (var7) {
+ var11 = var11.substring(7);
+ }
+
+ //byte[] b = var1.getResourceAsBytes(var11); //what the fuck
+ //if(b != null) {
+ EaglerImage var5 = EaglerAdapter.loadPNG(var1.getResourceAsBytes(var11));
+ if(var5 == null) {
+ throw new IOException("Could not load PNG");
+ }
+ this.setupTextureExt(var5, var12, var6, var7);
+ //}else {
+ // System.err.println("could not reload: "+var11);
+ //}
+ } catch (IOException var9) {
+ var9.printStackTrace();
+ }
+ }
+
+ var2 = this.textureContentsMap.keySet().iterator();
+
+ while (var2.hasNext()) {
+ var11 = (String) var2.next();
+
+ try {
+ var4 = EaglerAdapter.loadPNG(var1.getResourceAsBytes(var11));
+ if(var4 == null) {
+ throw new IOException("Could not load PNG");
+ }
+ System.arraycopy(var4.data, 0, (int[]) this.textureContentsMap.get(var11), 0, var4.data.length);
+ } catch (IOException var8) {
+ var8.printStackTrace();
+ }
+ }
+
+ Minecraft.getMinecraft().fontRenderer.readFontData();
+ Minecraft.getMinecraft().standardGalacticFontRenderer.readFontData();
+ }
+
+ /**
+ * Returns a BufferedImage read off the provided input stream. Args: inputStream
+ */
+ private EaglerImage readTextureImage(byte[] par1InputStream) throws IOException {
+ return null;//EaglerImage.loadImage(par1InputStream);
+ //return EaglerAdapter.loadPNG(par1InputStream);
+ }
+
+ public void refreshTextureMaps() {
+ this.textureMapBlocks.refreshTextures();
+ this.textureMapItems.refreshTextures();
+ }
+
+ public Icon getMissingIcon(int par1) {
+ switch (par1) {
+ case 0:
+ return this.textureMapBlocks.getMissingIcon();
+
+ case 1:
+ default:
+ return this.textureMapItems.getMissingIcon();
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/src/Texture.java b/src/main/java/net/minecraft/src/Texture.java
new file mode 100644
index 0000000..03d761d
--- /dev/null
+++ b/src/main/java/net/minecraft/src/Texture.java
@@ -0,0 +1,304 @@
+package net.minecraft.src;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.lax1dude.eaglercraft.EaglerImage;
+
+public class Texture {
+ private int glTextureId;
+ private int textureId;
+ private int textureType;
+
+ /** Width of this texture in pixels. */
+ private final int width;
+
+ /** Height of this texture in pixels. */
+ private final int height;
+ private final int textureDepth;
+ private final int textureFormat;
+ private final int textureTarget;
+ private final int textureMinFilter;
+ private final int textureMagFilter;
+ private final int textureWrap;
+ private final boolean mipmapActive;
+ private final String textureName;
+ private Rect2i textureRect;
+ private boolean transferred;
+
+ /**
+ * Uninitialized boolean. If true, the texture is re-uploaded every time it's
+ * modified. If false, every tick after it's been modified at least once in that
+ * tick.
+ */
+ private boolean autoCreate;
+
+ /**
+ * False if the texture has been modified since it was last uploaded to the GPU.
+ */
+ private boolean textureNotModified;
+ private ByteBuffer textureData;
+
+ private Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, int par9) {
+ this.textureName = par1Str;
+ this.textureType = par2;
+ this.width = par3;
+ this.height = par4;
+ this.textureDepth = par5;
+ this.textureFormat = par7;
+ this.textureMinFilter = par8;
+ this.textureMagFilter = par9;
+ this.textureWrap = par6;
+ this.textureRect = new Rect2i(0, 0, par3, par4);
+ this.textureTarget = EaglerAdapter.GL_TEXTURE_2D;
+ this.mipmapActive = false; //par8 != 9728 && par8 != 9729 || par9 != 9728 && par9 != 9729;
+
+ if (par2 != 2) {
+ this.glTextureId = EaglerAdapter.glGenTextures();
+ EaglerAdapter.glBindTexture(this.textureTarget, this.glTextureId);
+ EaglerAdapter.glTexParameteri(this.textureTarget, EaglerAdapter.GL_TEXTURE_MIN_FILTER, par8);
+ EaglerAdapter.glTexParameteri(this.textureTarget, EaglerAdapter.GL_TEXTURE_MAG_FILTER, par9);
+ EaglerAdapter.glTexParameteri(this.textureTarget, EaglerAdapter.GL_TEXTURE_WRAP_S, par6);
+ EaglerAdapter.glTexParameteri(this.textureTarget, EaglerAdapter.GL_TEXTURE_WRAP_T, par6);
+ } else {
+ this.glTextureId = -1;
+ }
+
+ this.textureId = TextureManager.instance().getNextTextureId();
+ }
+
+ public Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, EaglerImage par9BufferedImage) {
+ this(par1Str, par2, par3, par4, 1, par5, par6, par7, par8, par9BufferedImage);
+ }
+
+ public Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, int par9, EaglerImage par10BufferedImage) {
+ this(par1Str, par2, par3, par4, par5, par6, par7, par8, par9);
+
+ if (par10BufferedImage == null) {
+ if (par3 != -1 && par4 != -1) {
+ byte[] var11 = new byte[par3 * par4 * par5 * 4];
+
+ for (int var12 = 0; var12 < var11.length; ++var12) {
+ var11[var12] = 0;
+ }
+
+ this.textureData = GLAllocation.createDirectByteBuffer(var11.length);
+ this.textureData.clear();
+ this.textureData.put(var11);
+ this.textureData.position(0).limit(var11.length);
+
+ if (this.autoCreate) {
+ this.uploadTexture();
+ } else {
+ this.textureNotModified = false;
+ }
+ } else {
+ this.transferred = false;
+ }
+ } else {
+ this.transferred = true;
+ this.transferFromImage(par10BufferedImage);
+
+ if (par2 != 2) {
+ this.uploadTexture();
+ this.autoCreate = false;
+ }
+ }
+ }
+
+ public final Rect2i getTextureRect() {
+ return this.textureRect;
+ }
+
+ public void fillRect(Rect2i par1Rect2i, int par2) {
+ if (this.textureTarget != 32879) {
+ Rect2i var3 = new Rect2i(0, 0, this.width, this.height);
+ var3.intersection(par1Rect2i);
+ this.textureData.position(0);
+
+ for (int var4 = var3.getRectY(); var4 < var3.getRectY() + var3.getRectHeight(); ++var4) {
+ int var5 = var4 * this.width * 4;
+
+ for (int var6 = var3.getRectX(); var6 < var3.getRectX() + var3.getRectWidth(); ++var6) {
+ this.textureData.put(var5 + var6 * 4 + 0, (byte) (par2 >> 24 & 255));
+ this.textureData.put(var5 + var6 * 4 + 1, (byte) (par2 >> 16 & 255));
+ this.textureData.put(var5 + var6 * 4 + 2, (byte) (par2 >> 8 & 255));
+ this.textureData.put(var5 + var6 * 4 + 3, (byte) (par2 >> 0 & 255));
+ }
+ }
+
+ if (this.autoCreate) {
+ this.uploadTexture();
+ } else {
+ this.textureNotModified = false;
+ }
+ }
+ }
+
+ public void writeImage(String par1Str) {
+ /*
+ BufferedImage var2 = new BufferedImage(this.width, this.height, 2);
+ ByteBuffer var3 = this.getTextureData();
+ byte[] var4 = new byte[this.width * this.height * 4];
+ var3.position(0);
+ var3.get(var4);
+
+ for (int var5 = 0; var5 < this.width; ++var5) {
+ for (int var6 = 0; var6 < this.height; ++var6) {
+ int var7 = var6 * this.width * 4 + var5 * 4;
+ byte var8 = 0;
+ int var10 = var8 | (var4[var7 + 2] & 255) << 0;
+ var10 |= (var4[var7 + 1] & 255) << 8;
+ var10 |= (var4[var7 + 0] & 255) << 16;
+ var10 |= (var4[var7 + 3] & 255) << 24;
+ var2.setRGB(var5, var6, var10);
+ }
+ }
+
+ this.textureData.position(this.width * this.height * 4);
+
+ try {
+ ImageIO.write(var2, "png", new File(Minecraft.getMinecraftDir(), par1Str));
+ } catch (IOException var9) {
+ var9.printStackTrace();
+ }
+ */
+ }
+
+ public void copyFrom(int par1, int par2, Texture par3Texture, boolean par4) {
+ if (this.textureTarget != 32879) {
+ EaglerAdapter.glBindTexture(this.textureTarget, this.glTextureId);
+ ByteBuffer var5 = par3Texture.getTextureData();
+ this.textureData.position(0);
+ var5.position(0);
+
+ for (int var6 = 0; var6 < par3Texture.getHeight(); ++var6) {
+ int var7 = par2 + var6;
+ int var8 = var6 * par3Texture.getWidth() * 4;
+ int var9 = var7 * this.width * 4;
+
+ if (par4) {
+ var7 = par2 + (par3Texture.getHeight() - var6);
+ }
+
+ for (int var10 = 0; var10 < par3Texture.getWidth(); ++var10) {
+ int var11 = var9 + (var10 + par1) * 4;
+ int var12 = var8 + var10 * 4;
+
+ if (par4) {
+ var11 = par1 + var10 * this.width * 4 + var7 * 4;
+ }
+
+ this.textureData.put(var11 + 0, var5.get(var12 + 0));
+ this.textureData.put(var11 + 1, var5.get(var12 + 1));
+ this.textureData.put(var11 + 2, var5.get(var12 + 2));
+ this.textureData.put(var11 + 3, var5.get(var12 + 3));
+ }
+ }
+
+ this.textureData.position(this.width * this.height * 4);
+
+ if (this.autoCreate) {
+ this.uploadTexture();
+ } else {
+ this.textureNotModified = false;
+ }
+ }
+ }
+
+ public void func_104062_b(int par1, int par2, Texture par3Texture) {
+ EaglerAdapter.glBindTexture(this.textureTarget, this.glTextureId);
+ EaglerAdapter.glTexSubImage2D(this.textureTarget, 0, par1, par2, par3Texture.getWidth(), par3Texture.getHeight(), 0, EaglerAdapter.GL_UNSIGNED_BYTE, (ByteBuffer) par3Texture.getTextureData().position(0));
+ this.textureNotModified = true;
+ }
+
+ public void transferFromImage(EaglerImage par1BufferedImage) {
+ //if (this.textureTarget != 32879) {
+ int var2 = par1BufferedImage.w;
+ int var3 = par1BufferedImage.h;
+
+ if (var2 <= this.width && var3 <= this.height) {
+ int[] var4 = new int[] { 3, 0, 1, 2 };
+ int[] var5 = new int[] { 3, 2, 1, 0 };
+ int[] var6 = var5;
+ byte[] var9 = new byte[this.width * this.height * 4];
+
+ for (int var10 = 0; var10 < this.height; ++var10) {
+ for (int var11 = 0; var11 < this.width; ++var11) {
+ int var12 = var10 * this.width + var11;
+ int var13 = var12 * 4;
+ var9[var13 + var6[0]] = (byte) (par1BufferedImage.data[var12] >> 24 & 255);
+ var9[var13 + var6[1]] = (byte) (par1BufferedImage.data[var12] >> 16 & 255);
+ var9[var13 + var6[2]] = (byte) (par1BufferedImage.data[var12] >> 8 & 255);
+ var9[var13 + var6[3]] = (byte) (par1BufferedImage.data[var12] >> 0 & 255);
+ }
+ }
+
+ this.textureData = GLAllocation.createDirectByteBuffer(var9.length).order(ByteOrder.nativeOrder());
+ this.textureData.clear();
+ this.textureData.put(var9);
+ this.textureData.limit(var9.length);
+
+ if (this.autoCreate) {
+ this.uploadTexture();
+ } else {
+ this.textureNotModified = false;
+ }
+ } else {
+ System.err.println("transferFromImage called with a BufferedImage with dimensions (" + var2 + ", " + var3 + ") larger than the Texture dimensions (" + this.width + ", " + this.height + "). Ignoring.");
+ }
+ //}
+ }
+
+ public int getTextureId() {
+ return this.textureId;
+ }
+
+ public int getGlTextureId() {
+ return this.glTextureId;
+ }
+
+ public int getWidth() {
+ return this.width;
+ }
+
+ public int getHeight() {
+ return this.height;
+ }
+
+ public String getTextureName() {
+ return this.textureName;
+ }
+
+ public void bindTexture(int par1) {
+ if (this.textureDepth == 1) {
+ EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_2D);
+ } else {
+ //EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_3D);
+ }
+
+ OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit + par1);
+ EaglerAdapter.glBindTexture(this.textureTarget, this.glTextureId);
+
+ if (!this.textureNotModified) {
+ this.uploadTexture();
+ }
+ }
+
+ public void uploadTexture() {
+ this.textureData.flip();
+
+ if (this.height != 1 && this.textureDepth != 1) {
+ //EaglerAdapter.glTexImage3D(this.textureTarget, 0, this.textureFormat, this.width, this.height, this.textureDepth, 0, this.textureFormat, EaglerAdapter.GL_UNSIGNED_BYTE, this.textureData);
+ } else {
+ EaglerAdapter.glTexImage2D(this.textureTarget, 0, this.textureFormat, this.width, this.height, 0, this.textureFormat, EaglerAdapter.GL_UNSIGNED_BYTE, this.textureData);
+ }
+
+ this.textureNotModified = true;
+ }
+
+ public ByteBuffer getTextureData() {
+ return this.textureData;
+ }
+}
diff --git a/src/main/java/net/minecraft/src/TexturePackDefault.java b/src/main/java/net/minecraft/src/TexturePackDefault.java
new file mode 100644
index 0000000..a867a2b
--- /dev/null
+++ b/src/main/java/net/minecraft/src/TexturePackDefault.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+
+public class TexturePackDefault extends TexturePackImplementation {
+ public TexturePackDefault() {
+ super("default", null, "Default", (ITexturePack) null);
+ }
+
+ /**
+ * Load texture pack description from /pack.txt file in the texture pack
+ */
+ protected void loadDescription() {
+ this.firstDescriptionLine = "The default look of Minecraft";
+ }
+
+ public boolean func_98140_c(String par1Str) {
+ return EaglerAdapter.loadResource(par1Str) != null;
+ }
+
+ public boolean isCompatible() {
+ return true;
+ }
+
+ protected InputStream func_98139_b(String par1Str) {
+ return EaglerAdapter.loadResource(par1Str);
+ }
+
+ @Override
+ public byte[] getResourceAsBytes(String par1Str) {
+ return EaglerAdapter.loadResourceBytes(par1Str);
+ }
+}
diff --git a/src/main/java/net/minecraft/src/TexturePackFolder.java b/src/main/java/net/minecraft/src/TexturePackFolder.java
new file mode 100644
index 0000000..e59c756
--- /dev/null
+++ b/src/main/java/net/minecraft/src/TexturePackFolder.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.adapter.vfs.VFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class TexturePackFolder extends TexturePackImplementation {
+ public TexturePackFolder(String par1, VFile par2, ITexturePack par3ITexturePack) {
+ super(par1, par2, par2.getName(), par3ITexturePack);
+ }
+
+ protected InputStream func_98139_b(String par1Str) throws IOException {
+ VFile var2 = new VFile(this.texturePackFile, par1Str.substring(1));
+
+ if (!var2.exists()) {
+ throw new IOException(par1Str);
+ } else {
+ return var2.getInputStream();
+ }
+ }
+
+ public boolean func_98140_c(String par1Str) {
+ VFile var2 = new VFile(this.texturePackFile, par1Str);
+ return var2.exists();
+ }
+
+ public boolean isCompatible() {
+ return true;
+ }
+}
diff --git a/src/main/java/net/minecraft/src/TexturePackImplementation.java b/src/main/java/net/minecraft/src/TexturePackImplementation.java
new file mode 100644
index 0000000..f3e896d
--- /dev/null
+++ b/src/main/java/net/minecraft/src/TexturePackImplementation.java
@@ -0,0 +1,261 @@
+package net.minecraft.src;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.lax1dude.eaglercraft.EaglerImage;
+import net.lax1dude.eaglercraft.EaglerInputStream;
+import net.lax1dude.eaglercraft.adapter.vfs.VFile;
+
+public abstract class TexturePackImplementation implements ITexturePack
+{
+ /**
+ * Texture pack ID as returnd by generateTexturePackID(). Used only internally and not visible to the user.
+ */
+ private final String texturePackID;
+
+ /**
+ * The name of the texture pack's zip file/directory or "Default" for the builtin texture pack. Shown in the GUI.
+ */
+ private final String texturePackFileName;
+
+ /**
+ * File object for the texture pack's zip file in TexturePackCustom or the directory in TexturePackFolder.
+ */
+ protected final VFile texturePackFile;
+
+ /**
+ * First line of texture pack description (from /pack.txt) displayed in the GUI
+ */
+ protected String firstDescriptionLine;
+
+ /**
+ * Second line of texture pack description (from /pack.txt) displayed in the GUI
+ */
+ protected String secondDescriptionLine;
+ private final ITexturePack field_98141_g;
+
+ /** The texture pack's thumbnail image loaded from the /pack.png file. */
+ protected EaglerImage thumbnailImage;
+
+ /** The texture id for this pcak's thumbnail image. */
+ private int thumbnailTextureName = -1;
+
+ protected TexturePackImplementation(String par1, VFile par2File, String par3Str, ITexturePack par4ITexturePack)
+ {
+ this.texturePackID = par1;
+ this.texturePackFileName = par3Str;
+ this.texturePackFile = par2File;
+ this.field_98141_g = par4ITexturePack;
+ this.loadThumbnailImage();
+ this.loadDescription();
+ }
+
+ /**
+ * Truncate strings to at most 34 characters. Truncates description lines
+ */
+ private static String trimStringToGUIWidth(String par0Str)
+ {
+ if (par0Str != null && par0Str.length() > 34)
+ {
+ par0Str = par0Str.substring(0, 34);
+ }
+
+ return par0Str;
+ }
+
+ /**
+ * Load and initialize thumbnailImage from the the /pack.png file.
+ */
+ private void loadThumbnailImage()
+ {
+ InputStream var1 = null;
+
+ try
+ {
+ var1 = this.func_98137_a("/pack.png", false);
+ if (var1 != null) {
+ this.thumbnailImage = EaglerImage.loadImage(EaglerInputStream.inputStreamToBytes(var1));
+ }
+ }
+ catch (IOException var11)
+ {
+ ;
+ }
+ finally
+ {
+ try
+ {
+ if (var1 != null)
+ {
+ var1.close();
+ }
+ }
+ catch (IOException var10)
+ {
+ ;
+ }
+ }
+ }
+
+ /**
+ * Load texture pack description from /pack.txt file in the texture pack
+ */
+ protected void loadDescription()
+ {
+ InputStream var1 = null;
+ BufferedReader var2 = null;
+
+ try
+ {
+ var1 = this.func_98139_b("/pack.txt");
+ var2 = new BufferedReader(new InputStreamReader(var1));
+ this.firstDescriptionLine = trimStringToGUIWidth(var2.readLine());
+ this.secondDescriptionLine = trimStringToGUIWidth(var2.readLine());
+ }
+ catch (IOException var12)
+ {
+ ;
+ }
+ finally
+ {
+ try
+ {
+ if (var2 != null)
+ {
+ var2.close();
+ }
+
+ if (var1 != null)
+ {
+ var1.close();
+ }
+ }
+ catch (IOException var11)
+ {
+ ;
+ }
+ }
+ }
+
+ public InputStream func_98137_a(String par1Str, boolean par2) throws IOException
+ {
+ try
+ {
+ return this.func_98139_b(par1Str);
+ }
+ catch (IOException var4)
+ {
+ if (this.field_98141_g != null && par2)
+ {
+ return this.field_98141_g.func_98137_a(par1Str, true);
+ }
+ else
+ {
+ throw var4;
+ }
+ }
+ }
+
+ /**
+ * Gives a texture resource as InputStream.
+ */
+ public byte[] getResourceAsBytes(String par1Str)
+ {
+ InputStream is = null;
+ byte[] res = null;
+ try {
+ is = this.func_98137_a(par1Str, true);
+ if (is == null) return null;
+ res = EaglerInputStream.inputStreamToBytes(is);
+ } catch (IOException e) {
+ return null;
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ignored) {
+ //
+ }
+ }
+ }
+ return res;
+ }
+
+ protected abstract InputStream func_98139_b(String var1) throws IOException;
+
+ /**
+ * Delete the OpenGL texture id of the pack's thumbnail image, and close the zip file in case of TexturePackCustom.
+ */
+ public void deleteTexturePack(RenderEngine par1RenderEngine)
+ {
+ if (this.thumbnailImage != null && this.thumbnailTextureName != -1)
+ {
+ par1RenderEngine.deleteTexture(this.thumbnailTextureName);
+ }
+ }
+
+ /**
+ * Bind the texture id of the pack's thumbnail image, loading it if necessary.
+ */
+ public void bindThumbnailTexture(RenderEngine par1RenderEngine)
+ {
+ if (this.thumbnailImage != null)
+ {
+ if (this.thumbnailTextureName == -1)
+ {
+ this.thumbnailTextureName = par1RenderEngine.allocateAndSetupTexture(this.thumbnailImage);
+ }
+
+ EaglerAdapter.glBindTexture(EaglerAdapter.GL_TEXTURE_2D, this.thumbnailTextureName);
+ par1RenderEngine.resetBoundTexture();
+ }
+ else
+ {
+ par1RenderEngine.bindTexture("/gui/unknown_pack.png");
+ }
+ }
+
+ public boolean func_98138_b(String par1Str, boolean par2)
+ {
+ boolean var3 = this.func_98140_c(par1Str);
+ return !var3 && par2 && this.field_98141_g != null ? this.field_98141_g.func_98138_b(par1Str, par2) : var3;
+ }
+
+ public abstract boolean func_98140_c(String var1);
+
+ /**
+ * Get the texture pack ID
+ */
+ public String getTexturePackID()
+ {
+ return this.texturePackID;
+ }
+
+ /**
+ * Get the file name of the texture pack, or Default if not from a custom texture pack
+ */
+ public String getTexturePackFileName()
+ {
+ return this.texturePackFileName;
+ }
+
+ /**
+ * Get the first line of the texture pack description (read from the pack.txt file)
+ */
+ public String getFirstDescriptionLine()
+ {
+ return this.firstDescriptionLine;
+ }
+
+ /**
+ * Get the second line of the texture pack description (read from the pack.txt file)
+ */
+ public String getSecondDescriptionLine()
+ {
+ return this.secondDescriptionLine;
+ }
+}
diff --git a/src/main/java/net/minecraft/src/TexturePackList.java b/src/main/java/net/minecraft/src/TexturePackList.java
new file mode 100644
index 0000000..57ba6c1
--- /dev/null
+++ b/src/main/java/net/minecraft/src/TexturePackList.java
@@ -0,0 +1,287 @@
+package net.minecraft.src;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import net.lax1dude.eaglercraft.EPKDecompiler;
+import net.lax1dude.eaglercraft.EaglerAdapter;
+import net.lax1dude.eaglercraft.EaglerInputStream;
+import net.lax1dude.eaglercraft.adapter.vfs.VFile;
+import net.minecraft.src.Minecraft;
+
+public class TexturePackList
+{
+ /**
+ * An instance of TexturePackDefault for the always available builtin texture pack.
+ */
+ private static final ITexturePack defaultTexturePack = new TexturePackDefault();
+
+ /** The Minecraft instance. */
+ private final Minecraft mc;
+
+ /** The directory the texture packs will be loaded from. */
+ private final VFile texturePackDir;
+
+ /** Folder for the multi-player texturepacks. Returns File. */
+ private final VFile mpTexturePackFolder;
+
+ /** The list of the available texture packs. */
+ private List availableTexturePacks = new ArrayList();
+
+ /**
+ * A mapping of texture IDs to TexturePackBase objects used by updateAvaliableTexturePacks() to avoid reloading
+ * texture packs that haven't changed on disk.
+ */
+ private Map texturePackCache = new HashMap();
+
+ /** The TexturePack that will be used. */
+ private ITexturePack selectedTexturePack;
+
+ /** True if a texture pack is downloading in the background. */
+ private boolean isDownloading;
+
+ public TexturePackList(Minecraft par2Minecraft)
+ {
+ this.mc = par2Minecraft;
+ this.texturePackDir = new VFile("texturepacks");
+ this.mpTexturePackFolder = new VFile("texturepacks-mp-cache");
+ this.mpTexturePackFolder.deleteAll();
+ this.updateAvaliableTexturePacks();
+ }
+
+ /**
+ * Sets the new TexturePack to be used, returning true if it has actually changed, false if nothing changed.
+ */
+ public boolean setTexturePack(ITexturePack par1ITexturePack)
+ {
+ if (par1ITexturePack == this.selectedTexturePack)
+ {
+ return false;
+ }
+ else
+ {
+ this.isDownloading = false;
+ this.selectedTexturePack = par1ITexturePack;
+ this.mc.gameSettings.skin = par1ITexturePack.getTexturePackFileName();
+ this.mc.gameSettings.saveOptions();
+ return true;
+ }
+ }
+
+ /**
+ * filename must end in .zip
+ */
+ public void requestDownloadOfTexture(String par1Str)
+ {
+ String var2 = par1Str.substring(par1Str.lastIndexOf("/") + 1);
+
+ if (var2.contains("?"))
+ {
+ var2 = var2.substring(0, var2.indexOf("?"));
+ }
+
+ if (var2.toLowerCase().endsWith(".zip") || var2.toLowerCase().endsWith(".epk"))
+ {
+ VFile var3 = new VFile(this.mpTexturePackFolder, var2.replaceAll("[^A-Za-z0-9_]", "_"));
+ this.downloadTexture(par1Str, var3);
+ }
+ }
+
+ private void downloadTexture(String par1Str, VFile par2File)
+ {
+ this.isDownloading = true;
+ try {
+ byte[] data = EaglerAdapter.downloadURL(par1Str);
+ if (data == null) throw new IOException("Unable to download texture pack!");
+ if (par2File.getName().toLowerCase().endsWith(".epk")) {
+ EPKDecompiler epkDecompiler = new EPKDecompiler(data);
+ EPKDecompiler.FileEntry file;
+ while ((file = epkDecompiler.readFile()) != null) {
+ new VFile(par2File, file.name).setAllBytes(file.data);
+ }
+ } else {
+ try(ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(data))) {
+ ZipEntry entry;
+ while ((entry = zipInputStream.getNextEntry()) != null) {
+ if (entry.isDirectory()) continue;
+ new VFile(par2File, entry.getName()).setAllBytes(EaglerInputStream.inputStreamToBytesNoClose(zipInputStream));
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if (this.isDownloading) {
+ setSelectedTexturePack(this, new TexturePackFolder(TexturePackList.generateTexturePackID(this, par2File), par2File, defaultTexturePack));
+ this.mc.scheduleTexturePackRefresh();
+ }
+ }
+
+ /**
+ * Return true if a texture pack is downloading in the background.
+ */
+ public boolean getIsDownloading()
+ {
+ return this.isDownloading;
+ }
+
+ /**
+ * Called from Minecraft.loadWorld() if getIsDownloading() returned true to prepare the downloaded texture for
+ * usage.
+ */
+ public void onDownloadFinished()
+ {
+ this.isDownloading = false;
+ this.updateAvaliableTexturePacks();
+ this.mc.scheduleTexturePackRefresh();
+ }
+
+ /**
+ * check the texture packs the client has installed
+ */
+ public void updateAvaliableTexturePacks()
+ {
+ ArrayList var1 = new ArrayList();
+ this.selectedTexturePack = defaultTexturePack;
+ var1.add(defaultTexturePack);
+ Iterator var2 = this.getTexturePackDirContents().iterator();
+
+ while (var2.hasNext())
+ {
+ VFile var3 = (VFile)var2.next();
+ String var4 = this.generateTexturePackID(var3);
+
+ if (var4 != null)
+ {
+ Object var5 = (ITexturePack)this.texturePackCache.get(var4);
+
+ if (var5 == null)
+ {
+ var5 = new TexturePackFolder(var4, var3, defaultTexturePack);
+ this.texturePackCache.put(var4, var5);
+ }
+
+ if (((ITexturePack)var5).getTexturePackFileName().equals(this.mc.gameSettings.skin))
+ {
+ this.selectedTexturePack = (ITexturePack)var5;
+ }
+
+ var1.add(var5);
+ }
+ }
+
+ this.availableTexturePacks.removeAll(var1);
+ var2 = this.availableTexturePacks.iterator();
+
+ while (var2.hasNext())
+ {
+ ITexturePack var6 = (ITexturePack)var2.next();
+ var6.deleteTexturePack(this.mc.renderEngine);
+ this.texturePackCache.remove(var6.getTexturePackID());
+ }
+
+ this.availableTexturePacks = var1;
+ }
+
+ /**
+ * Generate an internal texture pack ID from the file/directory name, last modification time, and file size. Returns
+ * null if the file/directory is not a texture pack.
+ */
+ private String generateTexturePackID(VFile par1File)
+ {
+ return (new VFile(par1File, "pack.txt")).exists() ? par1File.getName() + ":folder" : null;
+ }
+
+ /**
+ * Return a List of file/directories in the texture pack directory.
+ */
+ private List getTexturePackDirContents()
+ {
+ if (!GuiTexturePacks.texturePackListFile.exists()) return Collections.emptyList();
+ String[] lines = GuiTexturePacks.texturePackListFile.getAllLines();
+ List files = new ArrayList<>();
+ for (String line : lines) {
+ files.add(new VFile(this.texturePackDir, line));
+ }
+ return files;
+ }
+
+ /**
+ * Returns a list of the available texture packs.
+ */
+ public List availableTexturePacks()
+ {
+ return Collections.unmodifiableList(this.availableTexturePacks);
+ }
+
+ public ITexturePack getSelectedTexturePack()
+ {
+ return this.selectedTexturePack;
+ }
+
+ public boolean func_77300_f()
+ {
+ if (!this.mc.gameSettings.serverTextures)
+ {
+ return false;
+ }
+ else
+ {
+ ServerData var1 = this.mc.getServerData();
+ return var1 == null ? true : var1.func_78840_c();
+ }
+ }
+
+ public boolean getAcceptsTextures()
+ {
+ if (!this.mc.gameSettings.serverTextures)
+ {
+ return false;
+ }
+ else
+ {
+ ServerData var1 = this.mc.getServerData();
+ return var1 == null ? false : var1.getAcceptsTextures();
+ }
+ }
+
+ static boolean isDownloading(TexturePackList par0TexturePackList)
+ {
+ return par0TexturePackList.isDownloading;
+ }
+
+ /**
+ * Set the selectedTexturePack field (Inner class static accessor method).
+ */
+ static ITexturePack setSelectedTexturePack(TexturePackList par0TexturePackList, ITexturePack par1ITexturePack)
+ {
+ return par0TexturePackList.selectedTexturePack = par1ITexturePack;
+ }
+
+ /**
+ * Generate an internal texture pack ID from the file/directory name, last modification time, and file size. Returns
+ * null if the file/directory is not a texture pack. (Inner class static accessor method).
+ */
+ static String generateTexturePackID(TexturePackList par0TexturePackList, VFile par1File)
+ {
+ return par0TexturePackList.generateTexturePackID(par1File);
+ }
+
+ static ITexturePack func_98143_h()
+ {
+ return defaultTexturePack;
+ }
+
+ static Minecraft getMinecraft(TexturePackList par0TexturePackList)
+ {
+ return par0TexturePackList.mc;
+ }
+}
diff --git a/src/main/java/net/minecraft/src/TextureStitched.java b/src/main/java/net/minecraft/src/TextureStitched.java
new file mode 100644
index 0000000..3866291
--- /dev/null
+++ b/src/main/java/net/minecraft/src/TextureStitched.java
@@ -0,0 +1,213 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.EaglerMisc;
+import net.minecraft.client.Minecraft;
+
+public class TextureStitched implements Icon {
+ private final String textureName;
+
+ /** texture sheet containing this texture */
+ protected Texture textureSheet;
+ protected List textureList;
+ private List listAnimationTuples;
+ protected boolean rotated;
+
+ /** x position of this icon on the texture sheet in pixels */
+ protected int originX;
+
+ /** y position of this icon on the texture sheet in pixels */
+ protected int originY;
+
+ /** width of this icon in pixels */
+ private int width;
+
+ /** height of this icon in pixels */
+ private int height;
+ private float minU;
+ private float maxU;
+ private float minV;
+ private float maxV;
+ private float widthNorm;
+ private float heightNorm;
+ protected int frameCounter = 0;
+ protected int tickCounter = 0;
+
+ public static TextureStitched makeTextureStitched(String par0Str) {
+ return (TextureStitched) ("clock".equals(par0Str) ? new TextureClock() : ("compass".equals(par0Str) ? new TextureCompass() : new TextureStitched(par0Str)));
+ }
+
+ protected TextureStitched(String par1) {
+ this.textureName = par1;
+ }
+
+ public void init(Texture par1Texture, List par2List, int par3, int par4, int par5, int par6, boolean par7) {
+ this.textureSheet = par1Texture;
+ this.textureList = par2List;
+ this.originX = par3;
+ this.originY = par4;
+ this.width = par5;
+ this.height = par6;
+ this.rotated = par7;
+ float var8 = 0.01F / (float) par1Texture.getWidth();
+ float var9 = 0.01F / (float) par1Texture.getHeight();
+ this.minU = (float) par3 / (float) par1Texture.getWidth() + var8;
+ this.maxU = (float) (par3 + par5) / (float) par1Texture.getWidth() - var8;
+ this.minV = (float) par4 / (float) par1Texture.getHeight() + var9;
+ this.maxV = (float) (par4 + par6) / (float) par1Texture.getHeight() - var9;
+ this.widthNorm = (float) par5 / 16.0F;
+ this.heightNorm = (float) par6 / 16.0F;
+ }
+
+ public void copyFrom(TextureStitched par1TextureStitched) {
+ this.init(par1TextureStitched.textureSheet, par1TextureStitched.textureList, par1TextureStitched.originX, par1TextureStitched.originY, par1TextureStitched.width, par1TextureStitched.height, par1TextureStitched.rotated);
+ }
+
+ /**
+ * Returns the X position of this icon on its texture sheet, in pixels.
+ */
+ public int getOriginX() {
+ return this.originX;
+ }
+
+ /**
+ * Returns the Y position of this icon on its texture sheet, in pixels.
+ */
+ public int getOriginY() {
+ return this.originY;
+ }
+
+ @Override
+ public int getIconWidth() {
+ return this.originX;
+ }
+
+ @Override
+ public int getIconHeight() {
+ return this.originY;
+ }
+
+ /**
+ * Returns the minimum U coordinate to use when rendering with this icon.
+ */
+ public float getMinU() {
+ return this.minU;
+ }
+
+ /**
+ * Returns the maximum U coordinate to use when rendering with this icon.
+ */
+ public float getMaxU() {
+ return this.maxU;
+ }
+
+ /**
+ * Gets a U coordinate on the icon. 0 returns uMin and 16 returns uMax. Other
+ * arguments return in-between values.
+ */
+ public float getInterpolatedU(double par1) {
+ float var3 = this.maxU - this.minU;
+ return this.minU + var3 * ((float) par1 / 16.0F);
+ }
+
+ /**
+ * Returns the minimum V coordinate to use when rendering with this icon.
+ */
+ public float getMinV() {
+ return this.minV;
+ }
+
+ /**
+ * Returns the maximum V coordinate to use when rendering with this icon.
+ */
+ public float getMaxV() {
+ return this.maxV;
+ }
+
+ /**
+ * Gets a V coordinate on the icon. 0 returns vMin and 16 returns vMax. Other
+ * arguments return in-between values.
+ */
+ public float getInterpolatedV(double par1) {
+ float var3 = this.maxV - this.minV;
+ return this.minV + var3 * ((float) par1 / 16.0F);
+ }
+
+ public String getIconName() {
+ return this.textureName;
+ }
+
+ /**
+ * Returns the width of the texture sheet this icon is on, in pixels.
+ */
+ public int getSheetWidth() {
+ return this.textureSheet.getWidth();
+ }
+
+ /**
+ * Returns the height of the texture sheet this icon is on, in pixels.
+ */
+ public int getSheetHeight() {
+ return this.textureSheet.getHeight();
+ }
+
+ public void updateAnimation() {
+ if (this.listAnimationTuples != null) {
+ Tuple var1 = (Tuple) this.listAnimationTuples.get(this.frameCounter);
+ ++this.tickCounter;
+
+ if (this.tickCounter >= ((Integer) var1.getSecond()).intValue()) {
+ int var2 = ((Integer) var1.getFirst()).intValue();
+ this.frameCounter = (this.frameCounter + 1) % this.listAnimationTuples.size();
+ this.tickCounter = 0;
+ var1 = (Tuple) this.listAnimationTuples.get(this.frameCounter);
+ int var3 = ((Integer) var1.getFirst()).intValue();
+
+ if (var2 != var3 && var3 >= 0 && var3 < this.textureList.size()) {
+ this.textureSheet.func_104062_b(this.originX, this.originY, (Texture) this.textureList.get(var3));
+ }
+ }
+ } else {
+ int var4 = this.frameCounter;
+ this.frameCounter = (this.frameCounter + 1) % this.textureList.size();
+
+ if (var4 != this.frameCounter) {
+ this.textureSheet.func_104062_b(this.originX, this.originY, (Texture) this.textureList.get(this.frameCounter));
+ }
+ }
+ }
+
+ public void readAnimationInfo(String path) {
+ ArrayList var2 = new ArrayList();
+ try {
+ String var3 = EaglerMisc.bytesToString(Minecraft.getMinecraft().texturePackList.getSelectedTexturePack().getResourceAsBytes(path)).trim();
+
+ if (var3.length() > 0) {
+ String[] var4 = var3.split(",");
+ String[] var5 = var4;
+ int var6 = var4.length;
+
+ for (int var7 = 0; var7 < var6; ++var7) {
+ String var8 = var5[var7];
+ int var9 = var8.indexOf(42);
+
+ if (var9 > 0) {
+ Integer var10 = Integer.valueOf(var8.substring(0, var9));
+ Integer var11 = Integer.valueOf(var8.substring(var9 + 1));
+ var2.add(new Tuple(var10, var11));
+ } else {
+ var2.add(new Tuple(Integer.valueOf(var8), Integer.valueOf(1)));
+ }
+ }
+ }
+ } catch (Exception var12) {
+ System.err.println("Failed to read animation info for " + this.textureName + ": " + var12.getMessage());
+ }
+
+ if (!var2.isEmpty() && var2.size() < 600) {
+ this.listAnimationTuples = var2;
+ }
+ }
+}