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; + } + } +}