diff --git a/src/main/java/org/dynmap/bukkit/SpoutPluginBlocks.java b/src/main/java/org/dynmap/bukkit/SpoutPluginBlocks.java index b6e140f8..7a6a8467 100644 --- a/src/main/java/org/dynmap/bukkit/SpoutPluginBlocks.java +++ b/src/main/java/org/dynmap/bukkit/SpoutPluginBlocks.java @@ -5,14 +5,20 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.lang.reflect.Field; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import javax.imageio.ImageIO; import org.dynmap.Log; 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.MaterialData; @@ -23,9 +29,38 @@ import org.getspout.spoutapi.material.MaterialData; * directory of downloaded image files (texturepacks/standard/spout/plugin.blockid.png) */ 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 */ public boolean processSpoutBlocks(File datadir) { + if(textYPosField == null) { + if(initSpoutAccess() == false) + return false; + } + HashMap texturelist = new HashMap(); + int cnt = 0; File f = new File(datadir, "texturepacks/standard/spout"); if(f.exists() == false) @@ -38,68 +73,103 @@ public class SpoutPluginBlocks { for(CustomBlock b : cb) { BlockDesign bd = b.getBlockDesign(); String blkid = bd.getTexturePlugin() + "." + b.getName(); - File imgfile = new File(f, blkid + ".png"); - BufferedImage img = null; - boolean urlloaded = false; - String txname = bd.getTexureURL(); + /* 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 { - URL url = new URL(txname); - img = ImageIO.read(url); /* Load skin for player */ - urlloaded = true; - } catch (IOException iox) { - if(txname.startsWith("http") == false) { /* Not URL - try file */ - File tf = new File(txname); - if(tf.exists() == false) { - /* Horrible hack - try to find temp file (some SpoutMaterials versions) */ - try { - File tmpf = File.createTempFile("dynmap", "test"); - - tf = new File(tmpf.getParent(), txname); - tmpf.delete(); - } catch (IOException iox2) {} + 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]); } - if(tf.exists()) { - try { - img = ImageIO.read(tf); - urlloaded = true; - } catch (IOException iox3) { - + 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"); + BufferedImage img = null; + boolean urlloaded = false; + try { + URL url = new URL(txname); + img = ImageIO.read(url); /* Load skin for player */ + urlloaded = true; + } catch (IOException iox) { + if(txname.startsWith("http") == false) { /* Not URL - try file */ + File tf = new File(txname); + if(tf.exists() == false) { + /* Horrible hack - try to find temp file (some SpoutMaterials versions) */ + try { + File tmpf = File.createTempFile("dynmap", "test"); + + tf = new File(tmpf.getParent(), txname); + tmpf.delete(); + } catch (IOException iox2) {} + } + if(tf.exists()) { + try { + img = ImageIO.read(tf); + urlloaded = true; + } catch (IOException iox3) { + } + } + } + if(img == null) { + Log.severe("Error loading texture for custom block '" + blkid + "' (" + b.getCustomId() + ") from " + txname + "(" + iox.getMessage() + ")"); + if(imgfile.exists()) { + try { + img = ImageIO.read(imgfile); /* Load existing */ + Log.info("Loaded cached texture file for " + blkid); + } catch (IOException iox2) { + Log.severe("Error loading cached texture file for " + blkid + " - " + iox2.getMessage()); + } } } } - if(img == null) { - Log.severe("Error loading texture for custom block '" + blkid + "' (" + b.getCustomId() + ") from " + bd.getTexureURL() + "(" + iox.getMessage() + ")"); - if(imgfile.exists()) { - try { - img = ImageIO.read(imgfile); /* Load existing */ - Log.info("Loaded cached texture file for " + blkid); - } catch (IOException iox2) { - Log.severe("Error loading cached texture file for " + blkid + " - " + iox2.getMessage()); - } + if(img != null) { + try { + if(urlloaded) + ImageIO.write(img, "png", imgfile); + } catch (IOException iox) { + Log.severe("Error writing " + blkid + ".png"); + } finally { + 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); } } - if(img != null) { - try { - if(urlloaded) - 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) { - Log.severe("Error writing " + blkid + ".png"); - } finally { - img.flush(); - } + 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();