package org.dynmap.hdmap.renderer; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; import org.dynmap.renderer.CustomRenderer; import org.dynmap.renderer.MapDataContext; import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatchFactory; public class RPMicroRenderer extends CustomRenderer { private static final String[] tileFields = { "cvs", "cvm" }; /* Defined texture indexes * 0 = Cobblestone (cobblestone:0) * 1 = Stone (stone:0) * 2 = Wood planks (Oak) (planks:0) * 3 = Sandstone (sandStone:0) * 4 = Mossy Stone (cobblestoneMossy:0) * 5 = Brick (brick:0) * 6 = Obsidian (obsidian:0) * 7 = Glass (glass:0) * 8 = Dirt (dirt:0) * 9 = Clay (blockClay:0) * 10 = Bookshelf (bookShelf:0) * 11 = Netherrack (87:0) * 12 = Wood (Oak) (wood:0) * 13 = Wood (Spruce) (wood:1) * 14 = Wood (Birch) (wood:2) * 15 = Soul Sand (slowSand:0) * 16 = Polished Stone (stairSingle:0) * 17 = Iron (blockSteel:0) * 18 = Gold (blockGold:0) * 19 = Diamond (blockDiamond:0) * 20 = Lapis Lazuli (blockLapis:0) * 21 = Snow (blockSnow:0) * 22 = Pumpkin (pumpkin:0) * 23 = Stone Brick (stoneBrick:0) * 24 = Stone Brick (stoneBrick:1) * 25 = Stone Brick (stoneBrick:2) * 26 = Nether Brick (netherBrick:0) * 27 = Stone Brick (stoneBrick:3) * 28 = Wooden Planks (planks:1) * 29 = Wooden Planks (planks:2) * 30 = Wooden Planks (planks:3) * 31 = Sandstone (sandStone:1) * 32 = Wool (cloth:0) * 33 = Wool (cloth:1) * 34 = Wool (cloth:2) * 35 = Wool (cloth:3) * 36 = Wool (cloth:4) * 37 = Wool (cloth:5) * 38 = Wool (cloth:6) * 39 = Wool (cloth:7) * 40 = Wool (cloth:8) * 41 = Wool (cloth:9) * 42 = Wool (cloth:10) * 43 = Wool (cloth:11) * 44 = Wool (cloth:12) * 45 = Wool (cloth:13) * 46 = Wool (cloth:14) * 47 = Wool (cloth:15) * 48 = Marble (blockStone:0) * 49 = Basalt (blockStone:1) * 50 = Marble Brick (blockStone:2) * 51 = Basalt Cobblestone (blockStone:3) * 52 = Basalt Brick (blockStone:4) * 53 = Rubberwood (blockLogs:0) * 54 = Ruby Block (blockStorage:0) * 55 = Emerald Block (blockStorage:1) * 56 = Sapphire Block (blockStorage:2) * 57 = Sandstone (sandStone:2) * 58 = Wood (wood:3) * 59 = Sandstone bottom * 60 = Sandstone top * 61 = Log top/bottom * 62 = Stone step top * 63 = Pumpkin top/bottom * 64 = Rubberwood log top/bottom * 65 =Chiseled Basalt Brick (blockStone:5) * 66 = Basalt Paver (blockStone:6) * 67 = Silver Block (blockStorage:3) * 68 = Tin Block (blockStorage:4) * 69 = Copper Block (blockStorage:5) */ private static final int NUM_TEXTURES = 70; /* Texture index = material index in RP */ private static final int materialTextureMap[][] = { { 0 }, // 0 = Cobblestone (cobblestone:0) { 1 }, // 1 = Stone (stone:0) { 2 }, // 2 = Wood planks (Oak) (planks:0) { 59, 60, 3, 3, 3, 3 }, // 3 = Sandstone (sandStone:0) { 4 }, // 4 = Mossy Stone (cobblestoneMossy:0) { 5 }, // 5 = Brick (brick:0) { 6 }, // 6 = Obsidian (obsidian:0) { 7 }, // 7 = Glass (glass:0) { 8 }, // 8 = Dirt (dirt:0) { 9 }, // 9 = Clay (blockClay:0) { 2, 2, 10, 10, 10, 10 }, // 10 = Bookshelf (bookShelf:0) { 11 }, // 11 = Netherrack (87:0) { 61, 61, 12, 12, 12, 12 }, // 12 = Wood (Oak) (wood:0) { 61, 61, 13, 13, 13, 13 }, // 13 = Wood (Spruce) (wood:1) { 61, 61, 14, 14, 14, 14 }, // 14 = Wood (Birch) (wood:2) { 15 }, // 15 = Soul Sand (slowSand:0) { 62, 62, 16, 16, 16, 16 }, // 16 = Polished Stone (stairSingle:0) { 17 }, // 17 = Iron (blockSteel:0) { 18 }, // 18 = Gold (blockGold:0) { 19 }, // 19 = Diamond (blockDiamond:0) { 20 }, // 20 = Lapis Lazuli (blockLapis:0) { 21 }, // 21 = Snow (blockSnow:0) { 63, 63, 22, 22, 22, 22 }, // 22 = Pumpkin (pumpkin:0) { 23 }, // 23 = Stone Brick (stoneBrick:0) { 24 }, // 24 = Stone Brick (stoneBrick:1) { 25 }, // 25 = Stone Brick (stoneBrick:2) { 26 }, // 26 = Nether Brick (netherBrick:0) { 27 }, // 27 = Stone Brick (stoneBrick:3) { 28 }, // 28 = Wooden Planks (planks:1) { 29 }, // 29 = Wooden Planks (planks:2) { 30 }, // 30 = Wooden Planks (planks:3) { 60, 60, 31, 31, 31, 31 }, // 31 = Sandstone (sandStone:1) { 32 }, // 32 = Wool (cloth:0) { 33 }, // 33 = Wool (cloth:1) { 34 }, // 34 = Wool (cloth:2) { 35 }, // 35 = Wool (cloth:3) { 36 }, // 36 = Wool (cloth:4) { 37 }, // 37 = Wool (cloth:5) { 38 }, // 38 = Wool (cloth:6) { 39 }, // 39 = Wool (cloth:7) { 40 }, // 40 = Wool (cloth:8) { 41 }, // 41 = Wool (cloth:9) { 42 }, // 42 = Wool (cloth:10) { 43 }, // 43 = Wool (cloth:11) { 44 }, // 44 = Wool (cloth:12) { 45 }, // 45 = Wool (cloth:13) { 46 }, // 46 = Wool (cloth:14) { 47 }, // 47 = Wool (cloth:15) { 48 }, // 48 = Marble (blockStone:0) { 49 }, // 49 = Basalt (blockStone:1) { 50 }, // 50 = Marble Brick (blockStone:2) { 51 }, // 51 = Basalt Cobblestone (blockStone:3) { 52 }, // 52 = Basalt Brick (blockStone:4) { 64, 64, 53, 53, 53, 53 }, // 53 = Rubberwood (blockLogs:0) { 54 }, // 54 = Ruby Block (blockStorage:0) { 55 }, // 55 = Emerald Block (blockStorage:1) { 56 }, // 56 = Sapphire Block (blockStorage:2) { 65 }, // 57 = Chiseled Basalt Brick (blockStone:5) { 66 }, // 58 = Basalt Paver (blockStone:6) { 0 }, // 59 { 0 }, // 60 { 0 }, // 61 { 0 }, // 62 { 0 }, // 63 { 60, 60, 57, 57, 57, 57 }, // 64 = Sandstone (sandStone:2) { 61, 61, 58, 58, 58, 58 }, // 65 = Wood (wood:3) { 67 }, // 66 = Silver Block (blockStorage:3) { 68 }, // 67 = Tin Block (blockStorage:4) { 69 } // 68 = Copper Block (blockStorage:5) }; @Override public boolean initializeRenderer(RenderPatchFactory rpf, int blkid, int blockdatamask, Map<String,String> custparm) { if(!super.initializeRenderer(rpf, blkid, blockdatamask, custparm)) return false; /* Flesh out sides map */ for(int i = 0; i < materialTextureMap.length; i++) { if(materialTextureMap[i].length < 6) { int[] sides = new int[6]; Arrays.fill(sides, materialTextureMap[i][0]); materialTextureMap[i] = sides; } } return true; } @Override public int getMaximumTextureCount() { return NUM_TEXTURES; } @Override public RenderPatch[] getRenderPatchList(MapDataContext ctx) { int covermask = 0; byte[] covervals = new byte[2*29]; Object v = ctx.getBlockTileEntityField("cvm"); if(v instanceof Integer) { covermask = ((Integer)v).intValue(); } v = ctx.getBlockTileEntityField("cvs"); if(v instanceof byte[]) { covervals = (byte[])v; } // String s = String.format("[%d,%d,%d]:cvm=%08x,cvs=", ctx.getX(), ctx.getY(), ctx.getZ(), covermask); // for(int i = 0; i < covervals.length; i+=2) { // s += String.format("%02x%02x:", covervals[i], covervals[i+1]); // } // Log.info(s); /* Build patch list */ ArrayList<RenderPatch> list = new ArrayList<RenderPatch>(); for(int i = 0, off = 0; i < 29; i++) { if ((covermask & (1 << i)) != 0) { addPatchesFor(ctx.getPatchFactory(), list, i, covervals[off], covervals[off+1]); off += 2; } } return list.toArray(new RenderPatch[list.size()]); } private static final double[] thick_0_5 = { 0.125, 0.25, 0.5, 0.125, 0.25, 0.5, 0.375, 0.625, 0.75, 0.875, 0.375, 0.625, 0.75, 0.875 }; private static final double[] thick_6_25 = { 0.125, 0.25, 0.5, 0.375, 0.625, 0.75, 0.875 }; private static final double[] thick_26_28 = { 0.125, 0.25, 0.375 }; private boolean isHollow(int shape, int thickness) { if(shape < 6) { switch(thickness) { case 3: case 4: case 5: case 10: case 11: case 12: case 13: return true; } } return false; } private double getThickness(int shape, int thickness) { double[] v; if(shape < 6) { v = thick_0_5; if(thickness < v.length) return v[thickness]; else return 1.0; } else if((shape >= 26) && (shape < 29)) { v = thick_26_28; if(thickness < v.length) return v[thickness]; else return v[0]; } else { v = thick_6_25; if(thickness < v.length) return v[thickness]; else return 1.0; } } private void addPatchesFor(RenderPatchFactory rpf, ArrayList<RenderPatch> list, int shape, int material, int thickness) { int[] sides; if((material < 0) || (material >= materialTextureMap.length)) { material = 0; } sides = materialTextureMap[material]; /* Get sides map for texture */ double thick = getThickness(shape, thickness); /* If a hollow block, handle specially */ if(isHollow(shape, thickness)) { switch(shape) { case 0: /* Bottom cover */ CustomRenderer.addBox(rpf, list, 0, 0.75, 0, thick, 0, 0.25, sides); CustomRenderer.addBox(rpf, list, 0.75, 1, 0, thick, 0, 0.75, sides); CustomRenderer.addBox(rpf, list, 0.25, 1, 0, thick, 0.75, 1, sides); CustomRenderer.addBox(rpf, list, 0, 0.25, 0, thick, 0.25, 1, sides); break; case 1: /* Top cover */ CustomRenderer.addBox(rpf, list, 0, 0.75, 1-thick, 1, 0, 0.25, sides); CustomRenderer.addBox(rpf, list, 0.75, 1, 1-thick, 1, 0, 0.75, sides); CustomRenderer.addBox(rpf, list, 0.25, 1, 1-thick, 1, 0.75, 1, sides); CustomRenderer.addBox(rpf, list, 0, 0.25, 1-thick, 1, 0.25, 1, sides); break; case 2: /* Z min cover */ CustomRenderer.addBox(rpf, list, 0, 0.75, 0, 0.25, 0, thick, sides); CustomRenderer.addBox(rpf, list, 0.75, 1, 0, 0.75, 0, thick, sides); CustomRenderer.addBox(rpf, list, 0.25, 1, 0.75, 1, 0, thick, sides); CustomRenderer.addBox(rpf, list, 0, 0.25, 0.25, 1, 0, thick, sides); break; case 3: /* Z max cover */ CustomRenderer.addBox(rpf, list, 0, 0.75, 0, 0.25, 1-thick, 1, sides); CustomRenderer.addBox(rpf, list, 0.75, 1, 0, 0.75, 1-thick, 1, sides); CustomRenderer.addBox(rpf, list, 0.25, 1, 0.75, 1, 1-thick, 1, sides); CustomRenderer.addBox(rpf, list, 0, 0.25, 0.25, 1, 1-thick, 1, sides); break; case 4: /* X min cover */ CustomRenderer.addBox(rpf, list, 0, thick, 0, 0.75, 0, 0.25, sides); CustomRenderer.addBox(rpf, list, 0, thick, 0.75, 1, 0, 0.75, sides); CustomRenderer.addBox(rpf, list, 0, thick, 0.25, 1, 0.75, 1, sides); CustomRenderer.addBox(rpf, list, 0, thick, 0, 0.25, 0.25, 1, sides); break; case 5: /* X max cover */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, 0.75, 0, 0.25, sides); CustomRenderer.addBox(rpf, list, 1-thick, 1, 0.75, 1, 0, 0.75, sides); CustomRenderer.addBox(rpf, list, 1-thick, 1, 0.25, 1, 0.75, 1, sides); CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, 0.25, 0.25, 1, sides); break; } } else { switch(shape) { case 0: /* Bottom cover */ CustomRenderer.addBox(rpf, list, 0, 1, 0, thick, 0, 1, sides); break; case 1: /* Top cover */ CustomRenderer.addBox(rpf, list, 0, 1, 1-thick, 1.0, 0, 1, sides); break; case 2: /* Z min cover */ CustomRenderer.addBox(rpf, list, 0, 1, 0, 1, 0, thick, sides); break; case 3: /* Z max cover */ CustomRenderer.addBox(rpf, list, 0, 1, 0, 1, 1.0-thick, 1, sides); break; case 4: /* X min cover */ CustomRenderer.addBox(rpf, list, 0, thick, 0, 1, 0, 1, sides); break; case 5: /* X max cover */ CustomRenderer.addBox(rpf, list, 1.0-thick, 1, 0, 1, 0, 1, sides); break; case 6: /* Xmin, Ymin, Zmin corner */ CustomRenderer.addBox(rpf, list, 0, thick, 0, thick, 0, thick, sides); break; case 7: /* Xmin, Ymin, Zmax corner */ CustomRenderer.addBox(rpf, list, 0, thick, 0, thick, 1-thick, 1, sides); break; case 8: /* Xmax, Ymin, Zmin corner */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, thick, 0, thick, sides); break; case 9: /* Xmax, Ymin, Zmax corner */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, thick, 1-thick, 1, sides); break; case 10: /* Xmin, Ymax, Zmin corner */ CustomRenderer.addBox(rpf, list, 0, thick, 1-thick, 1, 0, thick, sides); break; case 11: /* Xmin, Ymax, Zmax corner */ CustomRenderer.addBox(rpf, list, 0, thick, 1-thick, 1, 1-thick, 1, sides); break; case 12: /* Xmax, Ymax, Zmin corner */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 1-thick, 1, 0, thick, sides); break; case 13: /* Xmax, Ymax, Zmax corner */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 1-thick, 1, 1-thick, 1, sides); break; case 14: /* Zmin, Ymin Strip */ CustomRenderer.addBox(rpf, list, 0, 1, 0, thick, 0, thick, sides); break; case 15: /* Zmax, Ymin Strip */ CustomRenderer.addBox(rpf, list, 0, 1, 0, thick, 1-thick, 1, sides); break; case 16: /* Xmin, Ymin Strip */ CustomRenderer.addBox(rpf, list, 0, thick, 0, thick, 0, 1, sides); break; case 17: /* Xmax, Ymin Strip */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, thick, 0, 1, sides); break; case 18: /* Xmin, Zmin Strip */ CustomRenderer.addBox(rpf, list, 0, thick, 0, 1, 0, thick, sides); break; case 19: /* Xmin, Zmax Strip */ CustomRenderer.addBox(rpf, list, 0, thick, 0, 1, 1-thick, 1, sides); break; case 20: /* Xmax, Zmin Strip */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, 1, 0, thick, sides); break; case 21: /* Xmax, Zmax Strip */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 0, 1, 1-thick, 1, sides); break; case 22: /* Zmin, Ymax Strip */ CustomRenderer.addBox(rpf, list, 0, 1, 1-thick, 1, 0, thick, sides); break; case 23: /* Zmax, Ymax Strip */ CustomRenderer.addBox(rpf, list, 0, 1, 1-thick, 1, 1-thick, 1, sides); break; case 24: /* Xmin, Ymax Strip */ CustomRenderer.addBox(rpf, list, 0, thick, 1-thick, 1, 0, 1, sides); break; case 25: /* Xmax, Ymax Strip */ CustomRenderer.addBox(rpf, list, 1-thick, 1, 1-thick, 1, 0, 1, sides); break; case 26: /* Pillar Y */ CustomRenderer.addBox(rpf, list, 0.5-thick, 0.5+thick, 0, 1, 0.5-thick, 0.5+thick, sides); break; case 27: /* Pillar Z */ CustomRenderer.addBox(rpf, list, 0.5-thick, 0.5+thick, 0.5-thick, 0.5+thick, 0, 1, sides); break; case 28: /* Pillar X */ CustomRenderer.addBox(rpf, list, 0, 1, 0.5-thick, 0.5+thick, 0.5-thick, 0.5+thick, sides); break; default: CustomRenderer.addBox(rpf, list, 0, 1, 0, 1, 0, 1, sides); break; } } } @Override public String[] getTileEntityFieldsNeeded() { return tileFields; } }