blob: 930f0d772961ba9df6cd6f89fef1c25fb7f92ed6 [file] [log] [blame] [raw]
package com.plusminus.craft;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Graphics2D;
import java.awt.AlphaComposite;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import sun.security.action.GetBooleanAction;
/***
* Utility class which has convenience methods to access the
* files of the current minecraft installation
* @author Vincent Vollers
*/
public class MineCraftEnvironment {
public static enum OS {XP, Vista, MacOS, Linux, NotSupported};
public static OS os;
public static File baseDir;
static {
String os = System.getProperty( "os.name" );
HashMap<String,OS> osData = new HashMap<String,OS>();
/* Full list of os.name strings
AIX
Digital Unix
FreeBSD
HP UX
Irix
Linux
Mac OS
Mac OS X
MPE/iX
Netware 4.11
OS/2
Solaris
Windows 2000
Windows 7
Windows 95
Windows 98
Windows NT
Windows Vista
Windows XP
*/
osData.put("FreeBSD", OS.Linux);
osData.put("HP UX", OS.Linux);
osData.put("Linux", OS.Linux);
osData.put("Mac OS", OS.MacOS);
osData.put("Mac OS X", OS.MacOS);
osData.put("Windows", OS.XP);
osData.put("Windows 7", OS.Vista);
osData.put("Windows XP", OS.XP);
osData.put("Windows 2003", OS.XP);
osData.put("Windows 2000", OS.XP);
osData.put("Windows Vista", OS.Vista);
if(!osData.containsKey(os)) {
MineCraftEnvironment.os = OS.NotSupported;
} else {
MineCraftEnvironment.os = osData.get(os);
}
switch(MineCraftEnvironment.os) {
case Vista:
MineCraftEnvironment.baseDir = new File(System.getenv("APPDATA"), ".minecraft");
break;
case Linux:
MineCraftEnvironment.baseDir = new File(System.getProperty("user.home"), ".minecraft"); // untested
break;
case XP:
MineCraftEnvironment.baseDir = new File(System.getenv("APPDATA"), ".minecraft"); // untested
break;
case MacOS:
// damn macs ;p
File dotMinecraftEnv = new File(System.getProperty("user.home"), "Library/Application Support/.minecraft");
if(dotMinecraftEnv.exists()) {
MineCraftEnvironment.baseDir = dotMinecraftEnv;
} else {
MineCraftEnvironment.baseDir = new File(System.getProperty("user.home"), "Library/Application Support/minecraft"); // untested
}
break;
default:
MineCraftEnvironment.baseDir = null;
}
System.out.println(MineCraftEnvironment.baseDir.getAbsolutePath());
}
/***
* Returns a list of integers corresponding to available worlds
* @return
*/
public static ArrayList<Integer> getAvailableWorlds() {
return getAvailableWorlds(false);
}
/***
* Returns a list of integers corresponding to available worlds
* @param nether
* @return
*/
public static ArrayList<Integer> getAvailableWorlds(boolean nether) {
ArrayList<Integer> worlds = new ArrayList<Integer>();
for(int i=0;i<10;i++) {
File worldDir = getWorldDirectory(i, nether);
if(worldDir.exists() && worldDir.canRead()) {
worlds.add(i);
}
}
return worlds;
}
/***
* Returns a file handle to a chunk file in a world
* @param world
* @param x
* @param z
* @return
*/
public static File getChunkFile(int world, int x, int z) {
return getChunkFile(world, x, z, false);
}
/***
* Returns a file handle to a chunk file in a world
* @param world
* @param x
* @param z
* @param nether
* @return
*/
public static File getChunkFile(int world, int x, int z, boolean nether) {
int xx = x % 64;
if(xx<0) xx = 64+xx;
int zz = z % 64;
if(zz<0) zz = 64+zz;
String firstFolder = Integer.toString(xx, 36);
String secondFolder = Integer.toString(zz, 36);
String filename = "c." + Integer.toString(x, 36) + "." + Integer.toString(z, 36) + ".dat";
return new File(getWorldDirectory(world, nether), firstFolder + "/" + secondFolder + "/" + filename);
}
/***
* Returns a file handle to a base world directory
* @param world
* @return
*/
public static File getWorldDirectory(int world) {
return getWorldDirectory(world, false);
}
/***
* Returns a file handle to a base world directory
* @param world
* @param nether
* @return
*/
public static File getWorldDirectory(int world, boolean nether) {
if (nether)
{
return new File(baseDir, "saves/World" + world + "/DIM-1");
}
else
{
return new File(baseDir, "saves/World" + world);
}
}
/***
* Returns a file handle to the base minecraft directory
* @return
*/
public static File getMinecraftDirectory() {
return MineCraftEnvironment.baseDir;
}
/***
* Returns a stream to the texture data (overrides in the directory are handled)
* @return
*/
public static InputStream getMinecraftTextureData() {
return getMinecraftFile("terrain.png");
}
/***
* Returns a stream to the font data (overrides in the directory are handled)
* @return
*/
public static InputStream getMinecraftFontData() {
return getMinecraftFile("default.png");
}
/***
* Attempts to create a bufferedImage for a stream
* @param i
* @return
*/
private static BufferedImage buildImageFromInput(InputStream i) {
try {
return ImageIO.read(i);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/***
* Attempts to create a bufferedImage containing the texture sprite sheet
* @return
*/
public static BufferedImage getMinecraftTexture() {
BufferedImage bi = buildImageFromInput(getMinecraftTextureData());
// TODO: It doesn't look like Minecraft actually supports biome grass/leaf coloring for higher-res
// texture packs, so right now we're not going to greenify anything but 16x16 packs. When/if
// Minecraft supports that, we should update this. Also it would be nice to get proper Biome
// coloring in here, though from the looks of it, it's more trouble than I'm willing to spend.
int square_width = bi.getWidth()/16;
if (square_width == 16)
{
Graphics2D g2d = bi.createGraphics();
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.4f);
// First greenify grass
Rectangle rect = new Rectangle(0, 0, square_width, square_width);
g2d.setComposite(ac);
g2d.setColor(Color.green);
g2d.fill(rect);
g2d.drawImage(bi, null, 0, 0);
// Now greenify leaves
rect = new Rectangle(4*square_width, 3*square_width, 2*square_width, square_width);
g2d.setComposite(ac);
g2d.setColor(Color.green);
g2d.fill(rect);
g2d.drawImage(bi, null, 0, 0);
}
return bi;
}
/***
* Attempts to create a bufferedImage containing the font
* @return
*/
public static BufferedImage getMinecraftFont() {
return buildImageFromInput(getMinecraftFontData());
}
/***
* Creates an Inputstream to a file in the bin/ directory in the minecraft directory.
* This handles overrides. If a file exists in the bin/ directory it will load that.
* Otherwise it will look in the .jar file of minecraft
* @param fileName
* @return
*/
public static InputStream getMinecraftFile(String fileName){
File overrideFile = new File(baseDir, "bin/" + fileName);
if(overrideFile.exists()) {
try {
return new FileInputStream(overrideFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
File minecraftDataFile = new File(baseDir, "bin/minecraft.jar");
if(!minecraftDataFile.exists()) {
return null;
}
try {
JarFile jf = new JarFile(minecraftDataFile);
ZipEntry zipEntry = jf.getEntry(fileName);
if(zipEntry == null) {
return null;
}
return jf.getInputStream(zipEntry);
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
}