Use reflection to improve Spout custom block support - fixes StainedGlass

This commit is contained in:
Mike Primm 2012-02-03 22:36:58 -06:00
parent 5a35f132ac
commit f5b428cbbe

View file

@ -5,14 +5,20 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.dynmap.Log; import org.dynmap.Log;
import org.getspout.spoutapi.block.design.BlockDesign; import org.getspout.spoutapi.block.design.BlockDesign;
import org.getspout.spoutapi.block.design.GenericBlockDesign;
import org.getspout.spoutapi.block.design.GenericCuboidBlockDesign;
import org.getspout.spoutapi.block.design.Texture;
import org.getspout.spoutapi.material.CustomBlock; import org.getspout.spoutapi.material.CustomBlock;
import org.getspout.spoutapi.material.MaterialData; import org.getspout.spoutapi.material.MaterialData;
@ -23,9 +29,38 @@ import org.getspout.spoutapi.material.MaterialData;
* directory of downloaded image files (texturepacks/standard/spout/plugin.blockid.png) * directory of downloaded image files (texturepacks/standard/spout/plugin.blockid.png)
*/ */
public class SpoutPluginBlocks { public class SpoutPluginBlocks {
private Field textXPosField; /* float[][] textXPos */
private Field textYPosField; /* float[][] textYPos */
private boolean initSpoutAccess() {
boolean success = false;
try {
textXPosField = GenericBlockDesign.class.getDeclaredField("textXPos");
textXPosField.setAccessible(true);
textYPosField = GenericBlockDesign.class.getDeclaredField("textYPos");
textYPosField.setAccessible(true);
success = true;
} catch (NoSuchFieldException nsfx) {
Log.severe("Cannot access needed Spout custom block fields!");
Log.severe(nsfx);
}
return success;
}
private void addDefaultBlock(StringBuilder sb, CustomBlock blk) {
if(blk.isOpaque())
sb.append("block:id=" + blk.getCustomId() + ",data=*,allfaces=1\n");
else
sb.append("block:id=" + blk.getCustomId() + ",allfaces=12049,transparency=TRANSPARENT\n");
}
/* Process spout blocks - return true if something changed */ /* Process spout blocks - return true if something changed */
public boolean processSpoutBlocks(File datadir) { public boolean processSpoutBlocks(File datadir) {
if(textYPosField == null) {
if(initSpoutAccess() == false)
return false;
}
HashMap<String, String> texturelist = new HashMap<String, String>();
int cnt = 0; int cnt = 0;
File f = new File(datadir, "texturepacks/standard/spout"); File f = new File(datadir, "texturepacks/standard/spout");
if(f.exists() == false) if(f.exists() == false)
@ -38,10 +73,44 @@ public class SpoutPluginBlocks {
for(CustomBlock b : cb) { for(CustomBlock b : cb) {
BlockDesign bd = b.getBlockDesign(); BlockDesign bd = b.getBlockDesign();
String blkid = bd.getTexturePlugin() + "." + b.getName(); String blkid = bd.getTexturePlugin() + "." + b.getName();
/* If not GenericCubiodBlockDesign, we don't handle it */
if((bd instanceof GenericCuboidBlockDesign) == false) {
Log.info("Block " + blkid + " not suppored - only cubiod blocks");
addDefaultBlock(sb, b);
continue;
}
/* Get texture info */
Texture txt = bd.getTexture();
int w = txt.getWidth();
int h = txt.getHeight();
int sz = txt.getSpriteSize();
GenericCuboidBlockDesign gbd = (GenericCuboidBlockDesign)bd;
int[] txtidx = new int[6];
/* Fetch quad fields - figure out which texture for which side */
try {
float[][] textXPos = (float[][])textXPosField.get(gbd);
float[][] textYPos = (float[][])textYPosField.get(gbd);
/* Quads on cuboid are bottom, west, south, east, north, top */
for(int i = 0; i < 6; i++) {
float minx = 1.0F;
float miny = 1.0F;
for(int j = 0; j < 4; j++) {
minx = Math.min(minx, textXPos[i][j]);
miny = Math.min(miny, textYPos[i][j]);
}
txtidx[i] = (int)((minx * w)/sz) + (w/sz)*(int)((miny * h)/sz);
}
} catch (Exception iax) {
addDefaultBlock(sb, b);
continue;
}
String txname = bd.getTexureURL();
String txtid = texturelist.get(txname); /* Get texture */
if(txtid == null) { /* Not found yet */
File imgfile = new File(f, blkid + ".png"); File imgfile = new File(f, blkid + ".png");
BufferedImage img = null; BufferedImage img = null;
boolean urlloaded = false; boolean urlloaded = false;
String txname = bd.getTexureURL();
try { try {
URL url = new URL(txname); URL url = new URL(txname);
img = ImageIO.read(url); /* Load skin for player */ img = ImageIO.read(url); /* Load skin for player */
@ -63,12 +132,11 @@ public class SpoutPluginBlocks {
img = ImageIO.read(tf); img = ImageIO.read(tf);
urlloaded = true; urlloaded = true;
} catch (IOException iox3) { } catch (IOException iox3) {
} }
} }
} }
if(img == null) { if(img == null) {
Log.severe("Error loading texture for custom block '" + blkid + "' (" + b.getCustomId() + ") from " + bd.getTexureURL() + "(" + iox.getMessage() + ")"); Log.severe("Error loading texture for custom block '" + blkid + "' (" + b.getCustomId() + ") from " + txname + "(" + iox.getMessage() + ")");
if(imgfile.exists()) { if(imgfile.exists()) {
try { try {
img = ImageIO.read(imgfile); /* Load existing */ img = ImageIO.read(imgfile); /* Load existing */
@ -83,23 +151,25 @@ public class SpoutPluginBlocks {
try { try {
if(urlloaded) if(urlloaded)
ImageIO.write(img, "png", imgfile); ImageIO.write(img, "png", imgfile);
blks.add(b);
int w = img.getWidth();
int h = img.getHeight();
/* If width >= 6 times height, we're using custom for each side */
sb.append("texturefile:id=" + blkid + ",filename=spout/" + blkid + ".png,xcount=" + w/h + ",ycount=1\n");
if(w >= (6*h)) {
sb.append("block:id=" + b.getCustomId() + ",data=*,bottom=0,north=1,south=2,east=3,west=4,top=5,txtid=" + blkid + "\n");
}
else {
sb.append("block:id=" + b.getCustomId() + ",data=*,allfaces=0,txtid=" + blkid + "\n");
}
cnt++;
} catch (IOException iox) { } catch (IOException iox) {
Log.severe("Error writing " + blkid + ".png"); Log.severe("Error writing " + blkid + ".png");
} finally { } finally {
img.flush(); img.flush();
} }
String tfid = "txtid" + texturelist.size();
sb.append("texturefile:id=" + tfid + ",filename=spout/" + blkid + ".png,xcount=" + w/h + ",ycount=1\n");
texturelist.put(txname, tfid);
}
}
String txfileid = texturelist.get(txname);
if(txfileid != null) {
blks.add(b);
sb.append("block:id=" + b.getCustomId() + ",data=*,bottom=" + txtidx[0] + ",west=" +txtidx[1] + ",south=" + txtidx[2] + ",east=" + txtidx[3] + ",north="+txtidx[4]+",top="+txtidx[5]);
if(b.isOpaque() == false)
sb.append(",transparency=TRANSPARENT");
sb.append(",txtid=" + txfileid + "\n");
cnt++;
} }
} }
String rslt = sb.toString(); String rslt = sb.toString();