From 66082093decf6e2c3a600264add6a85840dc07b0 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Tue, 1 Feb 2022 23:50:58 -0600 Subject: [PATCH] Add state= mapping for replacing data= in models and textures (eventually) --- .../java/org/dynmap/hdmap/HDBlockModels.java | 495 +++++++----------- .../dynmap/hdmap/HDBlockStateTextureMap.java | 40 +- .../java/org/dynmap/hdmap/TexturePack.java | 262 ++++----- .../org/dynmap/utils/BlockStateParser.java | 236 +++++++++ DynmapCore/src/main/resources/models_1.txt | 34 +- DynmapCore/src/main/resources/texture_1.txt | 76 +-- .../org/dynmap/renderer/DynmapBlockState.java | 11 + 7 files changed, 582 insertions(+), 572 deletions(-) create mode 100644 DynmapCore/src/main/java/org/dynmap/utils/BlockStateParser.java diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java index deb96185..68f9053d 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java @@ -28,6 +28,7 @@ import org.dynmap.renderer.CustomRenderer; import org.dynmap.renderer.DynmapBlockState; import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatchFactory.SideVisible; +import org.dynmap.utils.BlockStateParser; import org.dynmap.utils.ForgeConfigFile; import org.dynmap.utils.PatchDefinition; import org.dynmap.utils.PatchDefinitionFactory; @@ -295,26 +296,6 @@ public class HDBlockModels { } } - private static String getBlockName(String modid, String val) throws NumberFormatException { - char c = val.charAt(0); - if(Character.isLetter(c) || (c == '%') || (c == '&')) { - if ((c == '%') || (c == '&')) { - val = val.substring(1); - } - int off = val.indexOf('+'); - if (off > 0) { - val = val.substring(0, off); - } - if (val.indexOf(':') < 0) { - val = modid + ":" + val; - } - return val; - } - else { - throw new NumberFormatException("invalid ID - " + val); - } - } - // Patch index ordering, corresponding to BlockStep ordinal order public static final int boxPatchList[] = { 1, 4, 0, 3, 2, 5 }; @@ -358,10 +339,11 @@ public class HDBlockModels { int cnt = 0; boolean need_mod_cfg = false; boolean mod_cfg_loaded = false; - BitSet databits = new BitSet(); String modname = "minecraft"; String modversion = null; final String mcver = core.getDynmapPluginPlatformVersion(); + BlockStateParser bsp = new BlockStateParser(); + Map bsprslt; try { String line; ArrayList modlist = new ArrayList(); @@ -373,12 +355,13 @@ public class HDBlockModels { int rownum = 0; int scale = 0; rdr = new LineNumberReader(new InputStreamReader(in)); - while((line = rdr.readLine()) != null) { + while ((line = rdr.readLine()) != null) { boolean skip = false; + int lineNum = rdr.getLineNumber(); if ((line.length() > 0) && (line.charAt(0) == '[')) { // If version constrained like int end = line.indexOf(']'); // Find end if (end < 0) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname + ": bad version limit"); + Log.severe("Format error - line " + lineNum + " of " + fname + ": bad version limit"); return; } String vertst = line.substring(1, end); @@ -392,62 +375,52 @@ public class HDBlockModels { } line = line.substring(end+1); } - // If we're skipping due to version restriction - if (skip) { - + // Comment line + if(line.startsWith("#") || line.startsWith(";")) { + skip = true; } - else if(line.startsWith("block:")) { - ArrayList blknames = new ArrayList(); - databits.clear(); + // If we're skipping due to version restriction + if (skip) continue; + // Split off : + int typeend = line.indexOf(':'); + String typeid = ""; + if (typeend >= 0) { + typeid = line.substring(0, typeend); + line = line.substring(typeend+1).trim(); + } + if (typeid.equals("block")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + scale = 0; - line = line.substring(6); String[] args = line.split(","); for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname,av[1])); - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - else if(av[0].equals("scale")) { + if(av[0].equals("scale")) { scale = Integer.parseInt(av[1]); } } + bsprslt = bsp.getMatchingStates(); /* If we have everything, build block */ - if((blknames.size() > 0) && (scale > 0)) { + if ((bsprslt.size() > 0) && (scale > 0)) { modlist.clear(); - for(String bname : blknames) { - DynmapBlockState bblk = DynmapBlockState.getBaseStateByName(bname); + for (DynmapBlockState bblk : bsprslt.keySet()) { if (bblk.isNotAir()) { - modlist.add(new HDBlockVolumetricModel(bblk, databits, scale, new long[0], blockset)); + modlist.add(new HDBlockVolumetricModel(bblk, bsprslt.get(bblk), scale, new long[0], blockset)); cnt++; } else { - Log.severe("Invalid model block name " + bname + " at line " + rdr.getLineNumber()); + Log.severe("Invalid model block name " + bblk.blockName + " at line " + lineNum); } } } else { - Log.severe("Block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Block model missing required parameters = line " + lineNum + " of " + fname); } layerbits = 0; } - else if(line.startsWith("layer:")) { - line = line.substring(6); + else if (typeid.equals("layer")) { String args[] = line.split(","); layerbits = 0; rownum = 0; @@ -455,28 +428,31 @@ public class HDBlockModels { layerbits |= (1 << Integer.parseInt(a)); } } - else if(line.startsWith("rotate:")) { - line = line.substring(7); + else if (typeid.equals("rotate")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String args[] = line.split(","); - String id = null; - int data = -1; int rot = -1; for(String a : args) { String[] av = a.split("="); - if(av.length < 2) continue; - if(av[0].equals("id")) { - id = getBlockName(modname,av[1]); - } - if(av[0].equals("data")) { data = getIntValue(varvals,av[1]); } - if(av[0].equals("rot")) { rot = Integer.parseInt(av[1]); } + if (av.length < 2) continue; + if (av[0].equals("rot")) { rot = Integer.parseInt(av[1]); } } - /* get old model to be rotated */ - DynmapBlockState bs = DynmapBlockState.getStateByNameAndIndex(id, (data > 0)?data:0); - if (bs.isAir()) { - Log.severe("Invalid rotate ID: " + id + " on line " + rdr.getLineNumber()); - return; + bsprslt = bsp.getMatchingStates(); + if (bsprslt.size() != 1) { + Log.severe("Missing rotate source on line " + lineNum); + continue; } - HDBlockModel mod = models_by_id_data.get(bs.globalStateIndex); + DynmapBlockState basebs = bsprslt.keySet().iterator().next(); + BitSet bits = bsprslt.get(basebs); + /* get old model to be rotated */ + DynmapBlockState bs = basebs.getState(bits.nextSetBit(0)); + if (bs.isAir()) { + Log.severe("Invalid rotate ID: " + bs + " on line " + lineNum); + continue; + } + HDBlockModel mod = models_by_id_data.get(bs.globalStateIndex); if (modlist.isEmpty()) { } else if ((mod != null) && ((rot%90) == 0) && (mod instanceof HDBlockVolumetricModel)) { @@ -512,124 +488,100 @@ public class HDBlockModels { } } else { - Log.severe("Invalid rotate error - line " + rdr.getLineNumber() + " of " + fname); - return; + Log.severe("Invalid rotate error - line " + lineNum + " of " + fname); + continue; } } - else if(line.startsWith("patchrotate:")) { - line = line.substring(12); + else if (typeid.equals("patchrotate")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String args[] = line.split(","); - String id = null; - int data = -1; int rotx = 0; int roty = 0; int rotz = 0; for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - id = getBlockName(modname, av[1]); - } - if(av[0].equals("data")) { data = getIntValue(varvals,av[1]); } if(av[0].equals("rot")) { roty = Integer.parseInt(av[1]); } if(av[0].equals("roty")) { roty = Integer.parseInt(av[1]); } if(av[0].equals("rotx")) { rotx = Integer.parseInt(av[1]); } if(av[0].equals("rotz")) { rotz = Integer.parseInt(av[1]); } } - /* get old model to be rotated */ - DynmapBlockState bs = DynmapBlockState.getStateByNameAndIndex(id, (data > 0)?data:0); - if (bs.isAir()) { - Log.severe("Invalid patchrotate id: " + id + " on line " + rdr.getLineNumber()); - return; + bsprslt = bsp.getMatchingStates(); + if (bsprslt.size() != 1) { + Log.severe("Missing rotate source on line " + lineNum); + continue; } + DynmapBlockState basebs = bsprslt.keySet().iterator().next(); + BitSet bits = bsprslt.get(basebs); + /* get old model to be rotated */ + DynmapBlockState bs = basebs.getState(bits.nextSetBit(0)); + if (bs.isAir()) { + Log.severe("Invalid patchrotate ID: " + bs + " on line " + lineNum); + continue; + } HDBlockModel mod = models_by_id_data.get(bs.globalStateIndex); - if(pmodlist.isEmpty()) { + if (pmodlist.isEmpty()) { } - else if((mod != null) && (mod instanceof HDBlockPatchModel)) { + else if ((mod != null) && (mod instanceof HDBlockPatchModel)) { HDBlockPatchModel pmod = (HDBlockPatchModel)mod; PatchDefinition patches[] = pmod.getPatches(); PatchDefinition newpatches[] = new PatchDefinition[patches.length]; - for(int i = 0; i < patches.length; i++) { + for (int i = 0; i < patches.length; i++) { newpatches[i] = (PatchDefinition)pdf.getRotatedPatch(patches[i], rotx, roty, rotz, patches[i].textureindex); } - if(patches.length > max_patches) + if (patches.length > max_patches) max_patches = patches.length; - for(HDBlockPatchModel patchmod : pmodlist) { + for (HDBlockPatchModel patchmod : pmodlist) { patchmod.setPatches(newpatches); } } else { - Log.severe("Invalid rotate error - line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Invalid rotate error - line " + lineNum + " of " + fname); return; } } - else if(line.startsWith("ignore-updates:")) { - ArrayList blknames = new ArrayList(); - databits.clear(); - line = line.substring(line.indexOf(':')+1); - String[] args = line.split(","); - for(String a : args) { - String[] av = a.split("="); - if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname,av[1])); - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - } - for (String nm : blknames) { - DynmapBlockState bbs = DynmapBlockState.getBaseStateByName(nm); + else if (typeid.equals("ignore-updates")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + + bsprslt = bsp.getMatchingStates(); + + for (DynmapBlockState bbs : bsprslt.keySet()) { if (bbs.isNotAir()) { - for (int i = 0; i < bbs.getStateCount(); i++) { + BitSet bits = bsprslt.get(bbs); + for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) { DynmapBlockState bs = bbs.getState(i); - if (databits.isEmpty() || databits.get(i)) { - changeIgnoredBlocks.set(bs.globalStateIndex); - } + changeIgnoredBlocks.set(bs.globalStateIndex); } } else { - Log.severe("Invalid update ignore block name " + nm + " at line " + rdr.getLineNumber()); + Log.severe("Invalid update ignore block name " + bbs + " at line " + lineNum); } } } - else if(line.startsWith("#") || line.startsWith(";")) { - } - else if(line.startsWith("enabled:")) { /* Test if texture file is enabled */ - line = line.substring(8).trim(); - if(line.startsWith("true")) { /* We're enabled? */ + else if (typeid.equals("enabled")) { /* Test if texture file is enabled */ + if (line.startsWith("true")) { /* We're enabled? */ /* Nothing to do - keep processing */ } - else if(line.startsWith("false")) { /* Disabled */ + else if (line.startsWith("false")) { /* Disabled */ return; /* Quit */ } /* If setting is not defined or false, quit */ - else if(config.getBoolean(line, false) == false) { + else if (config.getBoolean(line, false) == false) { return; } else { Log.info(line + " models enabled"); } } - else if(line.startsWith("var:")) { /* Test if variable declaration */ - line = line.substring(4).trim(); + else if (typeid.equals("var")) { /* Test if variable declaration */ String args[] = line.split(","); for(int i = 0; i < args.length; i++) { String[] v = args[i].split("="); if(v.length < 2) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Format error - line " + lineNum + " of " + fname); return; } try { @@ -637,13 +589,13 @@ public class HDBlockModels { int parmval = config.getInteger(v[0], val); /* Read value, with applied default */ varvals.put(v[0], parmval); /* And save value */ } catch (NumberFormatException nfx) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Format error - line " + lineNum + " of " + fname); return; } } } - else if(line.startsWith("cfgfile:")) { /* If config file */ - File cfgfile = new File(line.substring(8).trim()); + else if (typeid.equals("cfgfile")) { /* If config file */ + File cfgfile = new File(line); ForgeConfigFile cfg = new ForgeConfigFile(cfgfile); if (!mod_cfg_loaded) { need_mod_cfg = true; @@ -654,9 +606,8 @@ public class HDBlockModels { mod_cfg_loaded = true; } } - else if(line.startsWith("patch:")) { + else if (typeid.equals("patch")) { String patchid = null; - line = line.substring(6); String[] args = line.split(","); double p_x0 = 0.0, p_y0 = 0.0, p_z0 = 0.0; double p_xu = 0.0, p_yu = 1.0, p_zu = 0.0; @@ -714,7 +665,7 @@ public class HDBlockModels { p_vmax = Double.parseDouble(av[1]); } else if(av[0].equals("UplusVmax")) { - Log.warning("UplusVmax deprecated - use VmaxAtUMax - line " + rdr.getLineNumber() + " of " + fname); + Log.warning("UplusVmax deprecated - use VmaxAtUMax - line " + lineNum + " of " + fname); p_uplusvmax = Double.parseDouble(av[1]); } else if(av[0].equals("VmaxAtUMax")) { @@ -756,58 +707,40 @@ public class HDBlockModels { } } } - else if(line.startsWith("patchblock:")) { - ArrayList blknames = new ArrayList(); - databits.clear(); - line = line.substring(11); + else if (typeid.equals("patchblock")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String[] args = line.split(","); ArrayList patches = new ArrayList(); for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname,av[1])); - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - else if(av[0].startsWith("patch")) { + if(av[0].startsWith("patch")) { int patchnum0, patchnum1; String ids = av[0].substring(5); String[] ids2 = ids.split("-"); - if(ids2.length == 1) { + if (ids2.length == 1) { patchnum0 = patchnum1 = Integer.parseInt(ids2[0]); } else { patchnum0 = Integer.parseInt(ids2[0]); patchnum1 = Integer.parseInt(ids2[1]); } - if(patchnum0 < 0) { - Log.severe("Invalid patch index " + patchnum0 + " - line " + rdr.getLineNumber() + " of " + fname); + if (patchnum0 < 0) { + Log.severe("Invalid patch index " + patchnum0 + " - line " + lineNum + " of " + fname); return; } - if(patchnum1 < patchnum0) { - Log.severe("Invalid patch index " + patchnum1 + " - line " + rdr.getLineNumber() + " of " + fname); + if (patchnum1 < patchnum0) { + Log.severe("Invalid patch index " + patchnum1 + " - line " + lineNum + " of " + fname); return; } String patchid = av[1]; /* Look up patch by name */ - for(int i = patchnum0; i <= patchnum1; i++) { + for (int i = patchnum0; i <= patchnum1; i++) { PatchDefinition pd = pdf.getPatchByName(patchid, i); - if(pd == null) { - Log.severe("Invalid patch ID " + patchid + " - line " + rdr.getLineNumber() + " of " + fname); + if (pd == null) { + Log.severe("Invalid patch ID " + patchid + " - line " + lineNum + " of " + fname); return; } patches.add(i, pd); @@ -815,57 +748,38 @@ public class HDBlockModels { } } /* If we have everything, build block */ + bsprslt = bsp.getMatchingStates(); pmodlist.clear(); - if (blknames.size() > 0) { + if (bsprslt.size() > 0) { PatchDefinition[] patcharray = patches.toArray(new PatchDefinition[patches.size()]); if(patcharray.length > max_patches) max_patches = patcharray.length; - - for(String nm : blknames) { - DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); + for (DynmapBlockState bs : bsprslt.keySet()) { if (bs.isNotAir()) { - pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset)); + pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset)); cnt++; } else { - Log.severe("Invalid patchmodel block name " + nm + " at line " + rdr.getLineNumber()); + Log.severe("Invalid patchmodel block name " + bs + " at line " + lineNum); } } } else { - Log.severe("Patch block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Patch block model missing required parameters = line " + lineNum + " of " + fname); } } // Shortcut for defining a patchblock that is a simple rectangular prism, with sidex corresponding to full block sides - else if(line.startsWith("boxblock:")) { - ArrayList blknames = new ArrayList(); - databits.clear(); - line = line.substring(9); - String[] args = line.split(","); + else if (typeid.equals("boxblock")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + + String[] args = line.split(","); double xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0, zmin = 0.0, zmax = 1.0; int[] patchlist = boxPatchList; for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname,av[1])); - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - else if(av[0].equals("xmin")) { + if(av[0].equals("xmin")) { xmin = Double.parseDouble(av[1]); } else if(av[0].equals("xmax")) { @@ -893,59 +807,41 @@ public class HDBlockModels { } /* If we have everything, build block */ pmodlist.clear(); - if (blknames.size() > 0) { + bsprslt = bsp.getMatchingStates(); + if (bsprslt.size() > 0) { ArrayList pd = new ArrayList(); CustomRenderer.addBox(pdf, pd, xmin, xmax, ymin, ymax, zmin, zmax, patchlist); PatchDefinition[] patcharray = new PatchDefinition[pd.size()]; for (int i = 0; i < patcharray.length; i++) { patcharray[i] = (PatchDefinition) pd.get(i); } - if(patcharray.length > max_patches) + if (patcharray.length > max_patches) max_patches = patcharray.length; - for(String nm : blknames) { - DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); + for (DynmapBlockState bs : bsprslt.keySet()) { if (bs.isNotAir()) { - pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset)); + pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset)); cnt++; } else { - Log.severe("Invalid boxmodel block name " + nm + " at line " + rdr.getLineNumber()); + Log.severe("Invalid boxmodel block name " + bs + " at line " + lineNum); } } } else { - Log.severe("Box block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Box block model missing required parameters = line " + lineNum + " of " + fname); } } // Shortcut for defining a patchblock that is a simple rectangular prism, with sidex corresponding to full block sides - else if(line.startsWith("boxlist:")) { - ArrayList blknames = new ArrayList(); - databits.clear(); - line = line.substring(8); + else if (typeid.equals("boxlist")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String[] args = line.split(","); ArrayList boxes = new ArrayList(); - for(String a : args) { + for (String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname,av[1])); - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - else if(av[0].equals("box")) { + if (av[0].equals("box")) { String[] prms = av[1].split(":"); BoxLimits box = new BoxLimits(); if (prms.length > 0) @@ -973,8 +869,9 @@ public class HDBlockModels { } } /* If we have everything, build block */ + bsprslt = bsp.getMatchingStates(); pmodlist.clear(); - if (blknames.size() > 0) { + if (bsprslt.size() > 0) { ArrayList pd = new ArrayList(); for (BoxLimits bl : boxes) { @@ -984,52 +881,33 @@ public class HDBlockModels { for (int i = 0; i < patcharray.length; i++) { patcharray[i] = (PatchDefinition) pd.get(i); } - if(patcharray.length > max_patches) + if (patcharray.length > max_patches) max_patches = patcharray.length; - for(String nm : blknames) { - DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); + for (DynmapBlockState bs : bsprslt.keySet()) { if (bs.isNotAir()) { - pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset)); + pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset)); cnt++; } else { - Log.severe("Invalid boxlist block name " + nm + " at line " + rdr.getLineNumber()); + Log.severe("Invalid boxlist block name " + bs + " at line " + lineNum); } } } else { - Log.severe("Box list block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Box list block model missing required parameters = line " + lineNum + " of " + fname); } } // Shortcur for building JSON model style - else if(line.startsWith("modellist:")) { - ArrayList blknames = new ArrayList(); - databits.clear(); - line = line.substring(10); + else if (typeid.equals("modellist")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String[] args = line.split(","); ArrayList boxes = new ArrayList(); - for(String a : args) { + for (String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname,av[1])); - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - else if(av[0].equals("box")) { + if (av[0].equals("box")) { // box=from-x/y/z:to-x/y/z/rotx/roty/rotz://umin/vmin/umax/vmax>:... String[] prms = av[1].split(":"); @@ -1042,7 +920,7 @@ public class HDBlockModels { box.from[2] = Double.parseDouble(xyz[2]); } else { - Log.severe("Invalid modellist FROM value (" + prms[0] + " at line " + rdr.getLineNumber()); + Log.severe("Invalid modellist FROM value (" + prms[0] + " at line " + lineNum); } } if (prms.length > 1) { // Handle to (to-x/y/z or to-x/y/z/rotx/roty/rotz) or to-x/y/z/rotx/roty/rotz/rorigx/rorigy/rorigz @@ -1063,7 +941,7 @@ public class HDBlockModels { } } else { - Log.severe("Invalid modellist TO value (" + prms[1] + " at line " + rdr.getLineNumber()); + Log.severe("Invalid modellist TO value (" + prms[1] + " at line " + lineNum); } } // Rest are faces (//umin/vmin/umax/vmax> or </) @@ -1073,14 +951,14 @@ public class HDBlockModels { ModelBoxSide side = new ModelBoxSide(); side.rot = null; if ((flds.length != 2) && (flds.length != 6)) { - Log.severe("Invalid modellist face '" + v + "' at line " + rdr.getLineNumber()); + Log.severe("Invalid modellist face '" + v + "' at line " + lineNum); continue; } if (flds.length > 0) { String face = flds[0]; side.side = toBlockSide.get(face.substring(0, 1)); if (side.side == null) { - Log.severe("Invalid modellist side value (" + face + ") in '" + v + "' at line " + rdr.getLineNumber()); + Log.severe("Invalid modellist side value (" + face + ") in '" + v + "' at line " + lineNum); continue; } if (flds[0].length() > 1) { @@ -1114,8 +992,9 @@ public class HDBlockModels { } } /* If we have everything, build block */ + bsprslt = bsp.getMatchingStates(); pmodlist.clear(); - if (blknames.size() > 0) { + if (bsprslt.size() > 0) { ArrayList pd = new ArrayList(); for (ModelBox bl : boxes) { @@ -1132,7 +1011,7 @@ public class HDBlockModels { pd.add(patch); } else { - Log.severe(String.format("Invalid modellist patch for box %f/%f/%f:%f/%f/%f side %s at line %d", bl.from[0], bl.from[1], bl.from[2], bl.to[0], bl.to[1], bl.to[2], side.side, rdr.getLineNumber())); + Log.severe(String.format("Invalid modellist patch for box %f/%f/%f:%f/%f/%f side %s at line %d", bl.from[0], bl.from[1], bl.from[2], bl.to[0], bl.to[1], bl.to[2], side.side, lineNum)); } } } @@ -1142,50 +1021,34 @@ public class HDBlockModels { } if (patcharray.length > max_patches) max_patches = patcharray.length; - for(String nm : blknames) { - DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); + for (DynmapBlockState bs : bsprslt.keySet()) { if (bs.isNotAir()) { - pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset)); + pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset)); cnt++; } else { - Log.severe("Invalid modellist block name " + nm + " at line " + rdr.getLineNumber()); + Log.severe("Invalid modellist block name " + bs + " at line " + lineNum); } } } else { - Log.severe("Model list block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Model list block model missing required parameters = line " + lineNum + " of " + fname); } } - else if(line.startsWith("customblock:")) { - ArrayList blknames = new ArrayList(); - HashMap custargs = new HashMap(); - databits.clear(); - line = line.substring(12); + else if (typeid.equals("customblock")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + + HashMap custargs = new HashMap(); String[] args = line.split(","); String cls = null; - for(String a : args) { + for (String a : args) { String[] av = a.split("="); - if(av.length < 2) continue; - if(av[0].equals("id")) { - blknames.add(getBlockName(modname, av[1])); + if (av.length < 2) continue; + if (av[0].equals("id") || av[0].equals("data") || av[0].equals("state")) { + // Skip block state args - should not be bassed to custom block handler } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - databits.clear(); - } - else if (av[1].indexOf('-') > 0) { - String[] sp = av[1].split("-"); - int m0 = getIntValue(varvals, sp[0]); - int m1 = getIntValue(varvals, sp[1]); - for (int m = m0; m <= m1; m++) { - databits.set(m); - } - } - else - databits.set(getIntValue(varvals,av[1])); - } - else if(av[0].equals("class")) { + else if (av[0].equals("class")) { cls = av[1]; } else { @@ -1198,13 +1061,13 @@ public class HDBlockModels { } } /* If we have everything, build block */ - if ((blknames.size() > 0) && (cls != null)) { - for (String nm : blknames) { - DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); + bsprslt = bsp.getMatchingStates(); + if ((bsprslt.size() > 0) && (cls != null)) { + for (DynmapBlockState bs : bsprslt.keySet()) { if (bs.isNotAir()) { - CustomBlockModel cbm = new CustomBlockModel(bs, databits, cls, custargs, blockset); + CustomBlockModel cbm = new CustomBlockModel(bs, bsprslt.get(bs), cls, custargs, blockset); if(cbm.render == null) { - Log.severe("Custom block model failed to initialize = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Custom block model failed to initialize = line " + lineNum + " of " + fname); } else { /* Update maximum texture count */ @@ -1216,16 +1079,16 @@ public class HDBlockModels { cnt++; } else { - Log.severe("Invalid custommodel block name " + nm + " at line " + rdr.getLineNumber()); + Log.severe("Invalid custommodel block name " + bs + " at line " + lineNum); } } } else { - Log.severe("Custom block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + Log.severe("Custom block model missing required parameters = line " + lineNum + " of " + fname); } } - else if(line.startsWith("modname:")) { - String[] names = line.substring(8).split(","); + else if (typeid.equals("modname")) { + String[] names = line.split(","); boolean found = false; for(String n : names) { String[] ntok = n.split("[\\[\\]]"); @@ -1254,8 +1117,7 @@ public class HDBlockModels { return; } } - else if(line.startsWith("version:")) { - line = line.substring(line.indexOf(':')+1); + else if (typeid.equals("version")) { if (!checkVersionRange(mcver, line)) { return; } @@ -1281,10 +1143,9 @@ public class HDBlockModels { } } } - if(need_mod_cfg) { + if (need_mod_cfg) { Log.severe("Error loading configuration file for " + modname); } - Log.verboseinfo("Loaded " + cnt + " block models from " + fname); } catch (IOException iox) { Log.severe("Error reading models.txt - " + iox.toString()); diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockStateTextureMap.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockStateTextureMap.java index 9617de69..dcf227e0 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockStateTextureMap.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockStateTextureMap.java @@ -3,6 +3,7 @@ package org.dynmap.hdmap; import java.util.Arrays; import java.util.BitSet; import java.util.List; +import java.util.Map; import org.dynmap.hdmap.TexturePack; import org.dynmap.Log; @@ -82,40 +83,25 @@ public class HDBlockStateTextureMap { } // Add block state to table, with given block IDs and state indexes - public void addToTable(List blocknames, BitSet stateidx) { + public void addToTable(Map states) { /* Add entries to lookup table */ - for (String blkname : blocknames) { - DynmapBlockState baseblk = DynmapBlockState.getBaseStateByName(blkname); + for (DynmapBlockState baseblk : states.keySet()) { if (baseblk.isNotAir()) { - if (stateidx != null) { - for (int stateid = stateidx.nextSetBit(0); stateid >= 0; stateid = stateidx.nextSetBit(stateid+1)) { - DynmapBlockState bs = baseblk.getState(stateid); - if (bs.isAir()) { - Log.warning("Invalid texture block state: " + blkname + ":" + stateid); - continue; - } - if ((this.blockset != null) && (this.blockset.equals("core") == false)) { - HDBlockModels.resetIfNotBlockSet(bs, this.blockset); - } - copyToStateIndex(bs, this, null); + BitSet stateidx = states.get(baseblk); + for (int stateid = stateidx.nextSetBit(0); stateid >= 0; stateid = stateidx.nextSetBit(stateid+1)) { + DynmapBlockState bs = baseblk.getState(stateid); + if (bs.isAir()) { + Log.warning("Invalid texture block state: " + baseblk.blockName + ":" + stateid); + continue; } - } - else { // Else, loop over all state IDs for given block - for (int stateid = 0; stateid < baseblk.getStateCount(); stateid++) { - DynmapBlockState bs = baseblk.getState(stateid); - if (bs.isAir()) { - Log.warning("Invalid texture block state: " + blkname + ":" + stateid); - continue; - } - if ((this.blockset != null) && (this.blockset.equals("core") == false)) { - HDBlockModels.resetIfNotBlockSet(bs, this.blockset); - } - copyToStateIndex(bs, this, null); + if ((this.blockset != null) && (this.blockset.equals("core") == false)) { + HDBlockModels.resetIfNotBlockSet(bs, this.blockset); } + copyToStateIndex(bs, this, null); } } else { - Log.warning("Invalid texture block name: " + blkname); + Log.warning("Invalid texture block name: " + baseblk.blockName); } } } diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/TexturePack.java b/DynmapCore/src/main/java/org/dynmap/hdmap/TexturePack.java index 2eafb690..dc59fa18 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/TexturePack.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/TexturePack.java @@ -36,6 +36,7 @@ import org.dynmap.common.DynmapCommandSender; import org.dynmap.exporter.OBJExport; import org.dynmap.renderer.CustomColorMultiplier; import org.dynmap.renderer.DynmapBlockState; +import org.dynmap.utils.BlockStateParser; import org.dynmap.utils.BlockStep; import org.dynmap.utils.BufferOutputStream; import org.dynmap.utils.DynIntHashMap; @@ -481,8 +482,7 @@ public class TexturePack { public static class TextureMap { private Map key_to_index = new HashMap(); private List texture_ids = new ArrayList(); - private List blocknames = new ArrayList(); - private BitSet stateids = new BitSet(); + private Map states; private BlockTransparency trans = BlockTransparency.OPAQUE; private int colorMult = 0; private CustomColorMultiplier custColorMult = null; @@ -546,14 +546,13 @@ public class TexturePack { /** * Add settings for texture map */ - private static void addTextureIndex(String id, List blocknames, BitSet stateids, BlockTransparency trans, int colorMult, CustomColorMultiplier custColorMult, String blockset) { + private static void addTextureIndex(String id, Map states, BlockTransparency trans, int colorMult, CustomColorMultiplier custColorMult, String blockset) { TextureMap idx = textmap_by_id.get(id); if(idx == null) { /* Add empty one, if not found */ idx = new TextureMap(); textmap_by_id.put(id, idx); } - idx.blocknames = blocknames; - idx.stateids = stateids; + idx.states = states; idx.trans = trans; idx.colorMult = colorMult; idx.custColorMult = custColorMult; @@ -563,13 +562,13 @@ public class TexturePack { */ private static void processTextureMaps() { for(TextureMap ti : textmap_by_id.values()) { - if(ti.blocknames.isEmpty()) continue; + if(ti.states.isEmpty()) continue; int[] txtids = new int[ti.texture_ids.size()]; for(int i = 0; i < txtids.length; i++) { txtids[i] = ti.texture_ids.get(i).intValue(); } HDBlockStateTextureMap map = new HDBlockStateTextureMap(txtids, null, ti.colorMult, ti.custColorMult, ti.blockset, true, null, ti.trans); - map.addToTable(ti.blocknames, ti.stateids); + map.addToTable(ti.states); } } /** @@ -1914,15 +1913,18 @@ public class TexturePack { String texturemod = null; String texturepath = null; boolean terrain_ok = true; + BlockStateParser bsp = new BlockStateParser(); + Map bsprslt; try { String line; rdr = new LineNumberReader(new InputStreamReader(txtfile)); while((line = rdr.readLine()) != null) { boolean skip = false; + int lineNum = rdr.getLineNumber(); if ((line.length() > 0) && (line.charAt(0) == '[')) { // If version constrained like int end = line.indexOf(']'); // Find end if (end < 0) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": bad version limit"); + Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad version limit"); return; } String vertst = line.substring(1, end); @@ -1936,19 +1938,28 @@ public class TexturePack { } line = line.substring(end+1); } - // If we're skipping due to version restriction - if (skip) { + if (line.startsWith("#") || line.startsWith(";")) { + skip = true; } - else if(line.startsWith("block:")) { - List blknames = new ArrayList(); - BitSet stateids = null; + // If we're skipping due to version restriction + if (skip) continue; + // Split off : + int typeend = line.indexOf(':'); + String typeid = ""; + if (typeend >= 0) { + typeid = line.substring(0, typeend); + line = line.substring(typeend+1).trim(); + } + if (typeid.equals("block")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + int srctxtid = TXTID_TERRAINPNG; if (!terrain_ok) srctxtid = TXTID_INVALID; // Mark as not usable int faces[] = new int[] { TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK, TILEINDEX_BLANK }; int txtidx[] = new int[] { -1, -1, -1, -1, -1, -1 }; byte layers[] = null; - line = line.substring(6); BlockTransparency trans = BlockTransparency.OPAQUE; int colorMult = 0; int blockColorIdx = -1; @@ -1962,45 +1973,16 @@ public class TexturePack { if(filetoidx.containsKey(av[1])) srctxtid = filetoidx.get(av[1]); else - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": bad texture " + av[1]); + Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad texture " + av[1]); } } - // Build ID list : abort rest of processing if no valid values - for(String a : args) { - String[] av = a.split("="); - if(av.length < 2) continue; - if(av[0].equals("id")) { - String id = getBlockName(modname, av[1]); - if (id != null) { - blknames.add(id); - } - } - } - if (blknames.size() > 0) { + bsprslt = bsp.getMatchingStates(); + + if (bsprslt.size() > 0) { for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("data")) { - if(av[1].equals("*")) { - stateids = null; - } - else { - if (stateids == null) { stateids = new BitSet(); } - // See if range - if (av[1].indexOf('-') >= 0) { - String[] tok = av[1].split("-"); - int v1 = getIntValue(varvals, tok[0]); - int v2 = getIntValue(varvals, tok[1]); - for (int v = v1; v <= v2; v++) { - stateids.set(v); - } - } - else { - stateids.set(getIntValue(varvals,av[1])); - } - } - } - else if(av[0].equals("top") || av[0].equals("y-") || av[0].equals("face1")) { + if(av[0].equals("top") || av[0].equals("y-") || av[0].equals("face1")) { faces[BlockStep.Y_MINUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]); } else if(av[0].equals("bottom") || av[0].equals("y+") || av[0].equals("face0")) { @@ -2030,7 +2012,7 @@ public class TexturePack { fid0 = fid1 = Integer.parseInt(ids[0]); } if((fid0 < 0) || (fid1 < fid0)) { - Log.severe("Texture mapping has invalid face index - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping has invalid face index - " + av[1] + " - line " + lineNum + " of " + txtname); return; } int faceToOrd[] = { BlockStep.Y_PLUS.ordinal(), BlockStep.Y_MINUS.ordinal(), @@ -2063,7 +2045,7 @@ public class TexturePack { if(filetoidx.containsKey(av[1])) blockColorIdx = filetoidx.get(av[1]); else - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": bad texture " + av[1]); + Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad texture " + av[1]); } else if(av[0].startsWith("patch")) { int patchid0, patchid1; @@ -2077,7 +2059,7 @@ public class TexturePack { patchid0 = patchid1 = Integer.parseInt(ids[0]); } if((patchid0 < 0) || (patchid1 < patchid0)) { - Log.severe("Texture mapping has invalid patch index - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping has invalid patch index - " + av[1] + " - line " + lineNum + " of " + txtname); return; } if(faces.length <= patchid1) { @@ -2099,7 +2081,7 @@ public class TexturePack { trans = BlockTransparency.valueOf(av[1]); if(trans == null) { trans = BlockTransparency.OPAQUE; - Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + lineNum + " of " + txtname); } /* For leaves, base on leaf transparency setting */ if(trans == BlockTransparency.LEAVES) { @@ -2127,7 +2109,7 @@ public class TexturePack { for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].startsWith("layer")) { + if (av[0].startsWith("layer")) { if(layers == null) { layers = new byte[faces.length]; Arrays.fill(layers, (byte)-1); @@ -2145,21 +2127,21 @@ public class TexturePack { } } /* If we have everything, build block */ - if(blknames.size() > 0) { + if (bsprslt.size() > 0) { Integer colorIndex = (blockColorIdx >= 0)?(blockColorIdx + IMG_CNT):null; HDBlockStateTextureMap map = new HDBlockStateTextureMap(faces, layers, colorMult, custColorMult, blockset, stdrot, colorIndex, trans); - map.addToTable(blknames, stateids); + map.addToTable(bsprslt); cnt++; } else { - Log.severe("Texture mapping missing required parameters = line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping missing required parameters = line " + lineNum + " of " + txtname); } } } - else if(line.startsWith("copyblock:")) { - List blknames = new ArrayList(); - BitSet stateids = null; - line = line.substring(line.indexOf(':')+1); + else if (typeid.equals("copyblock")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String[] args = line.split(","); String srcname = null; int srcmeta = 0; @@ -2167,33 +2149,7 @@ public class TexturePack { for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - String id = getBlockName(modname, av[1]); - if (id != null) { - blknames.add(id); - } - } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - stateids = null; // Set all - } - else { - if (stateids == null) { stateids = new BitSet(); } - // See if range - if (av[1].indexOf('-') >= 0) { - String[] tok = av[1].split("-"); - int v1 = getIntValue(varvals, tok[0]); - int v2 = getIntValue(varvals, tok[1]); - for (int v = v1; v <= v2; v++) { - stateids.set(v); - } - } - else { - stateids.set(getIntValue(varvals,av[1])); - } - } - } - else if(av[0].equals("srcid")) { + if(av[0].equals("srcid")) { srcname = getBlockName(modname, av[1]); } else if(av[0].equals("srcmeta")) { @@ -2203,7 +2159,7 @@ public class TexturePack { trans = BlockTransparency.valueOf(av[1]); if(trans == null) { trans = BlockTransparency.OPAQUE; - Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + lineNum + " of " + txtname); } /* For leaves, base on leaf transparency setting */ if(trans == BlockTransparency.LEAVES) { @@ -2215,49 +2171,42 @@ public class TexturePack { } } /* If we have everything, build block */ - if((blknames.size() > 0) && (srcname != null)) { + bsprslt = bsp.getMatchingStates(); + + if ((bsprslt.size() > 0) && (srcname != null)) { DynmapBlockState srcblk = DynmapBlockState.getStateByNameAndIndex(srcname, srcmeta); HDBlockStateTextureMap map = null; if (srcblk != null) map = HDBlockStateTextureMap.getByBlockState(srcblk); if (map == null) { - Log.severe("Copy of texture mapping failed = line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Copy of texture mapping failed = line " + lineNum + " of " + txtname); } else { - for (String blkname : blknames) { - DynmapBlockState dblk = DynmapBlockState.getBaseStateByName(blkname); - if (stateids == null) { - for (int sid = 0; sid < dblk.getStateCount(); sid++) { - DynmapBlockState dblk2 = dblk.getState(sid); - HDBlockStateTextureMap.copyToStateIndex(dblk2, map, trans); - } - } - else { - for (int stateid = stateids.nextSetBit(0); stateid >= 0; stateid = stateids.nextSetBit(stateid+1)) { - DynmapBlockState dblk2 = dblk.getState(stateid); - HDBlockStateTextureMap.copyToStateIndex(dblk2, map, trans); - } + for (DynmapBlockState bblk : bsprslt.keySet()) { + BitSet stateids = bsprslt.get(bblk); + for (int stateid = stateids.nextSetBit(0); stateid >= 0; stateid = stateids.nextSetBit(stateid+1)) { + DynmapBlockState dblk2 = bblk.getState(stateid); + HDBlockStateTextureMap.copyToStateIndex(dblk2, map, trans); } } cnt++; } } else { - Log.severe("Texture mapping copy missing required parameters = line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping copy missing required parameters = line " + lineNum + " of " + txtname); } } - else if(line.startsWith("addtotexturemap:")) { + else if (typeid.equals("addtotexturemap")) { int srctxtid = -1; String mapid = null; - line = line.substring(line.indexOf(':') + 1); String[] args = line.split(","); - for(String a : args) { + for (String a : args) { String[] av = a.split("="); if(av.length < 2) continue; else if(av[0].equals("txtid")) { if(filetoidx.containsKey(av[1])) srctxtid = filetoidx.get(av[1]); else - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Format error - line " + lineNum + " of " + txtname); } else if(av[0].equals("mapid")) { mapid = av[1]; @@ -2276,14 +2225,14 @@ public class TexturePack { } } else { - Log.severe("Missing mapid - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Missing mapid - line " + lineNum + " of " + txtname); } } - else if(line.startsWith("texturemap:")) { - List blknames = new ArrayList(); - BitSet stateids = null; + else if (typeid.equals("texturemap")) { + // Parse block states + bsp.processLine(modname, line, lineNum, varvals); + String mapid = null; - line = line.substring(line.indexOf(':') + 1); BlockTransparency trans = BlockTransparency.OPAQUE; int colorMult = 0; CustomColorMultiplier custColorMult = null; @@ -2291,40 +2240,14 @@ public class TexturePack { for(String a : args) { String[] av = a.split("="); if(av.length < 2) continue; - if(av[0].equals("id")) { - String id = getBlockName(modname, av[1]); - if (id != null) { - blknames.add(id); - } - } - else if(av[0].equals("mapid")) { + if(av[0].equals("mapid")) { mapid = av[1]; } - else if(av[0].equals("data")) { - if(av[1].equals("*")) { - stateids = null; - } - else { - if (stateids == null) { stateids = new BitSet(); } - // See if range - if (av[1].indexOf('-') >= 0) { - String[] tok = av[1].split("-"); - int v1 = getIntValue(varvals, tok[0]); - int v2 = getIntValue(varvals, tok[1]); - for (int v = v1; v <= v2; v++) { - stateids.set(v); - } - } - else { - stateids.set(getIntValue(varvals,av[1])); - } - } - } else if(av[0].equals("transparency")) { trans = BlockTransparency.valueOf(av[1]); if(trans == null) { trans = BlockTransparency.OPAQUE; - Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture mapping has invalid transparency setting - " + av[1] + " - line " + lineNum + " of " + txtname); } /* For leaves, base on leaf transparency setting */ if(trans == BlockTransparency.LEAVES) { @@ -2347,16 +2270,16 @@ public class TexturePack { } } /* If we have everything, build texture map */ - if((blknames.size() > 0) && (mapid != null)) { - addTextureIndex(mapid, blknames, stateids, trans, colorMult, custColorMult, blockset); + bsprslt = bsp.getMatchingStates(); + if ((bsprslt.size() > 0) && (mapid != null)) { + addTextureIndex(mapid, bsprslt, trans, colorMult, custColorMult, blockset); } else { - Log.severe("Texture map missing required parameters = line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Texture map missing required parameters = line " + lineNum + " of " + txtname); } } - else if(line.startsWith("texturefile:") || line.startsWith("texture:")) { - boolean istxt = line.startsWith("texture:"); - line = line.substring(line.indexOf(':')+1); + else if (typeid.equals("texturefile") || typeid.equals("texture")) { + boolean istxt = typeid.equals("texture"); String[] args = line.split(","); int xdim = 16, ydim = 16; String fname = null; @@ -2391,7 +2314,7 @@ public class TexturePack { else if(aval[0].equals("format")) { fmt = TileFileFormat.valueOf(aval[1].toUpperCase()); if(fmt == null) { - Log.severe("Invalid format type " + aval[1] + " - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Invalid format type " + aval[1] + " - line " + lineNum + " of " + txtname); return; } } @@ -2411,14 +2334,11 @@ public class TexturePack { } } else { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Format error - line " + lineNum + " of " + txtname); return; } } - else if(line.startsWith("#") || line.startsWith(";")) { - } - else if(line.startsWith("enabled:")) { /* Test if texture file is enabled */ - line = line.substring(8).trim(); + else if (typeid.equals("enabled")) { /* Test if texture file is enabled */ if(line.startsWith("true")) { /* We're enabled? */ /* Nothing to do - keep processing */ } @@ -2433,13 +2353,12 @@ public class TexturePack { Log.info(line + " textures enabled"); } } - else if(line.startsWith("var:")) { /* Test if variable declaration */ - line = line.substring(4).trim(); + else if (typeid.equals("var")) { /* Test if variable declaration */ String args[] = line.split(","); for(int i = 0; i < args.length; i++) { String[] v = args[i].split("="); if(v.length < 2) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Format error - line " + lineNum + " of " + txtname); return; } try { @@ -2447,16 +2366,16 @@ public class TexturePack { int parmval = config.getInteger(v[0], val); /* Read value, with applied default */ varvals.put(v[0], parmval); /* And save value */ } catch (NumberFormatException nfx) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": " + nfx.getMessage()); + Log.severe("Format error - line " + lineNum + " of " + txtname + ": " + nfx.getMessage()); return; } } } - else if(line.startsWith("cfgfile:")) { /* If config file */ + else if (typeid.equals("cfgfile")) { /* If config file */ if (!mod_cfg_loaded) { mod_cfg_needed = true; } - File cfgfile = new File(line.substring(8).trim()); + File cfgfile = new File(line); ForgeConfigFile cfg = new ForgeConfigFile(cfgfile); if(cfg.load()) { cfg.addBlockIDs(varvals); @@ -2464,8 +2383,8 @@ public class TexturePack { mod_cfg_loaded = true; } } - else if(line.startsWith("modname:")) { - String[] names = line.substring(8).split(","); + else if (typeid.equals("modname")) { + String[] names = line.split(","); boolean found = false; for(String n : names) { String[] ntok = n.split("[\\[\\]]"); @@ -2494,17 +2413,16 @@ public class TexturePack { } if(!found) return; } - else if(line.startsWith("texturemod:")) { - texturemod = line.substring(line.indexOf(':')+1).trim(); + else if (typeid.equals("texturemod")) { + texturemod = line; } - else if(line.startsWith("texturepath:")) { - texturepath = line.substring(line.indexOf(':')+1).trim(); + else if (typeid.equals("texturepath")) { + texturepath = line.trim(); if (texturepath.charAt(texturepath.length()-1) != '/') { texturepath += "/"; } } - else if(line.startsWith("biome:")) { - line = line.substring(6).trim(); + else if (typeid.equals("biome")) { String args[] = line.split(","); int id = 0; int grasscolormult = -1; @@ -2515,7 +2433,7 @@ public class TexturePack { for(int i = 0; i < args.length; i++) { String[] v = args[i].split("="); if(v.length < 2) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname); + Log.severe("Format error - line " + lineNum + " of " + txtname); return; } if(v[0].equals("id")) { @@ -2540,7 +2458,7 @@ public class TexturePack { if(id > 0) { BiomeMap b = BiomeMap.byBiomeID(id); /* Find biome */ if(b == null) { - Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": " + id); + Log.severe("Format error - line " + lineNum + " of " + txtname + ": " + id); } else { if(foliagecolormult != -1) @@ -2556,14 +2474,12 @@ public class TexturePack { } } } - else if(line.startsWith("version:")) { - line = line.substring(line.indexOf(':')+1); + else if (typeid.equals("version")) { if (!HDBlockModels.checkVersionRange(mcver, line)) { return; } } - else if(line.startsWith("noterrainpng:")) { - line = line.substring(line.indexOf(':')+1); + else if (typeid.equals("noterrainpng")) { if (line.startsWith("true")) { terrain_ok = false; } diff --git a/DynmapCore/src/main/java/org/dynmap/utils/BlockStateParser.java b/DynmapCore/src/main/java/org/dynmap/utils/BlockStateParser.java new file mode 100644 index 00000000..7e9369a0 --- /dev/null +++ b/DynmapCore/src/main/java/org/dynmap/utils/BlockStateParser.java @@ -0,0 +1,236 @@ +package org.dynmap.utils; + +import org.dynmap.Log; +import org.dynmap.renderer.DynmapBlockState; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +// Utility class used for parsing block name and block state identity from lines in model and texture files +public class BlockStateParser { + private HashMap basestates; + private ArrayList badtokens; + private String modid; + private int linenum; + private boolean filtered; + + public BlockStateParser() { + } + + /** + * Process new line into list of matching states Produce list of block states + * matching the fields in the provided line (specifically the portion after the + * ':" prefix) at the stsrt of the line. Processes id= or + * id= or id=: as block identifier data= or + * data=- as selecting matching states of identified blocks by ordered + * index of their block states (analog to metadata> + * state=//... as selecting matching states (based on all + * states where given id=val values match) + * + * @return success or no + */ + public boolean processLine(String modid, String line, int linenum, Map varMap) { + boolean success = true; + String tokens[] = line.split(","); // Split on the commas + this.basestates = new HashMap(); + this.badtokens = new ArrayList(); + this.modid = modid; + this.linenum = linenum; + this.filtered = false; + // Loop through and process id= tokens + for (String token : tokens) { + int idx = token.indexOf("="); // Find equals + if (idx < 0) + continue; // Skip token without equals + String fieldid = token.substring(0, idx); // Split off left of equals + String args = token.substring(idx + 1); // And rest of token after equals + // Just do IDs first (need block names to get to states + if (fieldid.equals("id")) { + if (!handleBlockName(args)) { + badtokens.add(token); + success = false; + } + } + } + // Loop through and process data= and state= tokens + for (String token : tokens) { + int idx = token.indexOf("="); // Find equals + if (idx < 0) + continue; // Skip token without equals + String fieldid = token.substring(0, idx); // Split off left of equals + String args = token.substring(idx + 1); // And rest of token after equals + // Check for data= + if (fieldid.equals("data")) { + if (!handleBlockData(args, varMap)) { + badtokens.add(token); + success = false; + } + } + // If state= + else if (fieldid.equals("state")) { + if (!handleBlockState(args)) { + badtokens.add(token); + success = false; + } + } + } + // If unfiltered, add all states for all blocks + if (!filtered) { + // Now loop through base states and add matching indexes + for (DynmapBlockState bs : basestates.keySet()) { + int cnt = bs.getStateCount(); + BitSet bits = basestates.get(bs); + for (int idx = 0; idx < cnt; idx++) { + bits.set(bs.getState(idx).stateIndex); + } + } + } + // Log.info(String.format("processLine(%s)=%b, basestates=%s", line, success, + // basestates)); + return success; + } + + // Return matching results from last processLine call + public Map getMatchingStates() { + return basestates; + } + + // Return bad tokens from last processLine call + public List getBadTokens() { + return badtokens; + } + + private boolean handleBlockName(String blockname) { + char c = blockname.charAt(0); + if (Character.isLetter(c) || (c == '%') || (c == '&')) { + String orig = blockname; + if ((c == '%') || (c == '&')) { + blockname = blockname.substring(1); + } + if (blockname.indexOf(':') < 0) { + blockname = modid + ":" + blockname; + } + // Now find the base block state + DynmapBlockState bs = DynmapBlockState.getBaseStateByName(blockname); + // Bad if we failed + if (bs == null) { + Log.warning(String.format("id=%s on line %d does not match valid blockName", orig, linenum)); + return false; + } + basestates.put(bs, new BitSet()); + return true; + } else { // Numbers not support anymore + Log.warning(String.format("id=%s on line %d invalid format (numbers not supported anymore)", blockname, + linenum)); + return false; + } + } + + private boolean handleBlockData(String data, Map varMap) { + try { + if (data.equals("*")) { + filtered = false; + } else { + int split = data.indexOf('-'); // See if range of data + int m0, m1; + if (split > 0) { + String start = data.substring(0, split); + String end = data.substring(split + 1); + m0 = getIntValue(varMap, start); + m1 = getIntValue(varMap, end); + } else { + m0 = m1 = getIntValue(varMap, data); + } + filtered = true; + // Now loop through base states and add matching indexes + for (DynmapBlockState bs : basestates.keySet()) { + int cnt = bs.getStateCount(); + BitSet bits = basestates.get(bs); + for (int idx = m0; (idx <= m1) && (idx < cnt); idx++) { + bits.set(bs.getState(idx).stateIndex); + } + if ((m1 >= cnt) || (m0 >= cnt)) { + Log.warning(String.format("data=%s on line %d exceeds state count for %s", data, linenum, + bs.blockName)); + } + } + } + return true; + } catch (NumberFormatException x) { + return false; + } + } + + private boolean handleBlockState(String data) { + boolean success = true; + if (data.equals("*")) { + filtered = false; + } else { + String[] split = data.split("/"); // Split on pairs + String[] attribs = new String[split.length]; + String[] vals = new String[split.length]; + for (int i = 0; i < split.length; i++) { + String[] av = split[i].split(":"); + if (av.length == 2) { + attribs[i] = av[0]; + vals[i] = av[1]; + } else { + success = false; + } + } + filtered = true; + // Now loop through base states and add matching indexes + if (success) { + for (DynmapBlockState bs : basestates.keySet()) { + int cnt = bs.getStateCount(); + BitSet bits = basestates.get(bs); + for (int idx = 0; idx < cnt; idx++) { + DynmapBlockState s = bs.getState(idx); + boolean match = true; + for (int i = 0; match && (i < attribs.length); i++) { + if (!s.isStateMatch(attribs[i], vals[i])) { + match = false; + } + } + if (match) { + bits.set(idx); // Set matching state + } + } + } + } + } + if (!success) { + Log.warning(String.format("Bad block state %s for line %s", data, linenum)); + } + return success; + } + + private static Integer getIntValue(Map vars, String val) throws NumberFormatException { + char c = val.charAt(0); + if (Character.isLetter(c) || (c == '%') || (c == '&')) { + int off = val.indexOf('+'); + int offset = 0; + if (off > 0) { + offset = Integer.valueOf(val.substring(off + 1)); + val = val.substring(0, off); + } + Integer v = vars.get(val); + if (v == null) { + if ((c == '%') || (c == '&')) { // block/item unique IDs + vars.put(val, 0); + v = 0; + } else { + throw new NumberFormatException("invalid ID - " + val); + } + } + if ((offset != 0) && (v.intValue() > 0)) + v = v.intValue() + offset; + return v; + } else { + return Integer.valueOf(val); + } + } +} diff --git a/DynmapCore/src/main/resources/models_1.txt b/DynmapCore/src/main/resources/models_1.txt index 0ad9e449..fc617502 100644 --- a/DynmapCore/src/main/resources/models_1.txt +++ b/DynmapCore/src/main/resources/models_1.txt @@ -187,8 +187,8 @@ customblock:id=oak_stairs,id=cobblestone_stairs,id=brick_stairs,id=stone_brick_s # Jungle slab # Acacia slab # Dark oak slab -boxblock:id=oak_slab,id=spruce_slab,id=birch_slab,id=jungle_slab,id=acacia_slab,id=dark_oak_slab,data=0,data=1,ymin=0.5 -boxblock:id=oak_slab,id=spruce_slab,id=birch_slab,id=jungle_slab,id=acacia_slab,id=dark_oak_slab,data=2,data=3,ymax=0.5 +boxblock:id=oak_slab,id=spruce_slab,id=birch_slab,id=jungle_slab,id=acacia_slab,id=dark_oak_slab,state=type:top,ymin=0.5 +boxblock:id=oak_slab,id=spruce_slab,id=birch_slab,id=jungle_slab,id=acacia_slab,id=dark_oak_slab,state=type:bottom,ymax=0.5 # Stone slab # Sandstone slab # Petified oak slab @@ -202,8 +202,8 @@ boxblock:id=oak_slab,id=spruce_slab,id=birch_slab,id=jungle_slab,id=acacia_slab, # Prismarine slab # Prismarine brick slab # Dark prismarine slab -boxblock:id=stone_slab,id=sandstone_slab,id=petrified_oak_slab,id=cobblestone_slab,id=brick_slab,id=stone_brick_slab,id=nether_brick_slab,id=quartz_slab,id=red_sandstone_slab,id=purpur_slab,id=prismarine_slab,id=prismarine_brick_slab,id=dark_prismarine_slab,data=0,data=1,ymin=0.5 -boxblock:id=stone_slab,id=sandstone_slab,id=petrified_oak_slab,id=cobblestone_slab,id=brick_slab,id=stone_brick_slab,id=nether_brick_slab,id=quartz_slab,id=red_sandstone_slab,id=purpur_slab,id=prismarine_slab,id=prismarine_brick_slab,id=dark_prismarine_slab,data=2,data=3,ymax=0.5 +boxblock:id=stone_slab,id=sandstone_slab,id=petrified_oak_slab,id=cobblestone_slab,id=brick_slab,id=stone_brick_slab,id=nether_brick_slab,id=quartz_slab,id=red_sandstone_slab,id=purpur_slab,id=prismarine_slab,id=prismarine_brick_slab,id=dark_prismarine_slab,state=type:top,ymin=0.5 +boxblock:id=stone_slab,id=sandstone_slab,id=petrified_oak_slab,id=cobblestone_slab,id=brick_slab,id=stone_brick_slab,id=nether_brick_slab,id=quartz_slab,id=red_sandstone_slab,id=purpur_slab,id=prismarine_slab,id=prismarine_brick_slab,id=dark_prismarine_slab,state=type:bottom,ymax=0.5 # Snow boxblock:id=snow,data=0,ymax=0.125 @@ -559,7 +559,7 @@ patchblock:id=lever,data=18 patchrotate:id=lever,data=0,rotx=180,roty=180 patchblock:id=lever,data=20 patchrotate:id=lever,data=0,rotx=180,roty=270 -patchblock:id=lever,data=24 +patchblock:id=lever,data=22 patchrotate:id=lever,data=0,rotx=180,roty=90 # Lever (off) (base, lever) modellist:id=lever,data=1,box=5/0/4:11/3/12:d/0/5/4/11/12:u/0/5/4/11/12:n/0/5/0/11/3:s/0/5/0/11/3:w/0/4/0/12/3:e/0/4/0/12/3,box=7/1/7:9/11/9/-45/0/0/8/1/8:u/1/7/6/9/8:n/1/7/6/9/16:s/1/7/6/9/16:w/1/7/6/9/16:e/1/7/6/9/16 @@ -1024,12 +1024,12 @@ patch:id=AnvilTopSide1,Ox=0.0,Oy=0.0,Oz=0.1825,Ux=1.0,Uy=0.0,Uz=0.1825,Vx=0.0,Vy patch:id=AnvilTopSide2,Ox=0.0,Oy=0.0,Oz=0.0,Ux=1.0,Uy=0.0,Uz=0.0,Vx=0.0,Vy=1.0,Vz=0.0,Umin=0.1825,Umax=0.8175,Vmin=0.625,Vmax=1.0,visibility=both patch:id=AnvilTopTop,Ox=0.0,Oy=1.0,Oz=0.0,Ux=1.0,Uy=1.0,Uz=0.0,Vx=0.0,Vy=1.0,Vz=1.0,Umin=0.0,Umax=1.0,Vmin=0.1825,Vmax=0.8175,visibility=bottom patch:id=AnvilTopBottom,Ox=0.0,Oy=0.625,Oz=0.0,Ux=1.0,Uy=0.625,Uz=0.0,Vx=0.0,Vy=0.625,Vz=1.0,Umin=0.0,Umax=1.0,Vmin=0.1825,Vmax=0.8175,visibility=top -patchblock:id=anvil,data=1,data=5,data=9,data=13,patch0=AnvilBaseTop,patch1=AnvilBaseBottom,patch2=AnvilBaseSide,patch3=AnvilBaseSide@90,patch4=AnvilBaseSide@180,patch5=AnvilBaseSide@270,patch6=AnvilStepTop,patch7=AnvilStepSide1,patch8=AnvilStepSide2@90,patch9=AnvilStepSide1@180,patch10=AnvilStepSide2@270,patch11=AnvilStandSide1,patch12=AnvilStandSide2@90,patch13=AnvilStandSide1@180,patch14=AnvilStandSide2@270,patch15=AnvilTopBottom,patch16=AnvilTopSide1,patch17=AnvilTopSide2@90,patch18=AnvilTopSide1@180,patch19=AnvilTopSide2@270,patch20=AnvilTopTop -patchblock:id=anvil,data=0,data=4,data=8,data=12 +patchblock:id=anvil,data=1,patch0=AnvilBaseTop,patch1=AnvilBaseBottom,patch2=AnvilBaseSide,patch3=AnvilBaseSide@90,patch4=AnvilBaseSide@180,patch5=AnvilBaseSide@270,patch6=AnvilStepTop,patch7=AnvilStepSide1,patch8=AnvilStepSide2@90,patch9=AnvilStepSide1@180,patch10=AnvilStepSide2@270,patch11=AnvilStandSide1,patch12=AnvilStandSide2@90,patch13=AnvilStandSide1@180,patch14=AnvilStandSide2@270,patch15=AnvilTopBottom,patch16=AnvilTopSide1,patch17=AnvilTopSide2@90,patch18=AnvilTopSide1@180,patch19=AnvilTopSide2@270,patch20=AnvilTopTop +patchblock:id=anvil,data=0 patchrotate:id=anvil,data=1,rot=270 -patchblock:id=anvil,data=2,data=6,data=10,data=14 +patchblock:id=anvil,data=2 patchrotate:id=anvil,data=1,rot=90 -patchblock:id=anvil,data=3,data=7,data=11,data=15 +patchblock:id=anvil,data=3 patchrotate:id=anvil,data=1,rot=180 # Daylight Sensor @@ -1354,8 +1354,8 @@ patchblock:id=bubble_column [1.14-]patchblock:id=potted_lily_of_the_valley,patch0=FlowerPotTop,patch1=FlowerPotBottom,patch2=FlowerPotSide,patch3=FlowerPotSide@90,patch4=FlowerPotSide@180,patch5=FlowerPotSide@270,patch6=FlowerPotDirt,patch7=FlowerPotFlower,patch8=FlowerPotFlower@90 # Smooth stone slab # Cut sandstone slab -[1.14-]boxblock:id=smooth_stone_slab,id=cut_sandstone_slab,id=cut_red_sandstone_slab,data=0,data=1,ymin=0.5 -[1.14-]boxblock:id=smooth_stone_slab,id=cut_sandstone_slab,id=cut_red_sandstone_slab,data=2,data=3,ymax=0.5 +[1.14-]boxblock:id=smooth_stone_slab,id=cut_sandstone_slab,id=cut_red_sandstone_slab,state=type:top,ymin=0.5 +[1.14-]boxblock:id=smooth_stone_slab,id=cut_sandstone_slab,id=cut_red_sandstone_slab,state=type:bottom,ymax=0.5 # Bamboo [1.14-]boxblock:id=bamboo,data=0-5,xmin=0.4275,xmax=0.5625,zmin=0.4275,zmax=0.5625 [1.14-]boxblock:id=bamboo,data=6-11,xmin=0.38,xmax=0.62,zmin=0.38,zmax=0.62 @@ -1389,8 +1389,8 @@ patchblock:id=bubble_column # Red nether brick slab # Polished andesite slab # Diorite slab -[1.14-]boxblock:id=polished_granite_slab,id=smooth_red_sandstone_slab,id=mossy_stone_brick_slab,id=polished_diorite_slab,id=mossy_cobblestone_slab,id=end_stone_brick_slab,id=smooth_sandstone_slab,id=smooth_quartz_slab,id=granite_slab,id=andesite_slab,id=red_nether_brick_slab,id=polished_andesite_slab,id=diorite_slab,data=0,data=1,ymin=0.5 -[1.14-]boxblock:id=polished_granite_slab,id=smooth_red_sandstone_slab,id=mossy_stone_brick_slab,id=polished_diorite_slab,id=mossy_cobblestone_slab,id=end_stone_brick_slab,id=smooth_sandstone_slab,id=smooth_quartz_slab,id=granite_slab,id=andesite_slab,id=red_nether_brick_slab,id=polished_andesite_slab,id=diorite_slab,data=2,data=3,ymax=0.5 +[1.14-]boxblock:id=polished_granite_slab,id=smooth_red_sandstone_slab,id=mossy_stone_brick_slab,id=polished_diorite_slab,id=mossy_cobblestone_slab,id=end_stone_brick_slab,id=smooth_sandstone_slab,id=smooth_quartz_slab,id=granite_slab,id=andesite_slab,id=red_nether_brick_slab,id=polished_andesite_slab,id=diorite_slab,state=type:top,ymin=0.5 +[1.14-]boxblock:id=polished_granite_slab,id=smooth_red_sandstone_slab,id=mossy_stone_brick_slab,id=polished_diorite_slab,id=mossy_cobblestone_slab,id=end_stone_brick_slab,id=smooth_sandstone_slab,id=smooth_quartz_slab,id=granite_slab,id=andesite_slab,id=red_nether_brick_slab,id=polished_andesite_slab,id=diorite_slab,state=type:bottom,ymax=0.5 # Brick wall # Prismarine wall # Red sandstone wall @@ -1641,8 +1641,8 @@ patchblock:id=bubble_column # Blackstone Slab # Polished Blackstone slab # Polished Blackstone Brick slab -[1.16-]boxblock:id=crimson_slab,id=warped_slab,id=blackstone_slab,id=polished_blackstone_brick_slab,id=polished_blackstone_slab,data=0,data=1,ymin=0.5 -[1.16-]boxblock:id=crimson_slab,id=warped_slab,id=blackstone_slab,id=polished_blackstone_brick_slab,id=polished_blackstone_slab,data=2,data=3,ymax=0.5 +[1.16-]boxblock:id=crimson_slab,id=warped_slab,id=blackstone_slab,id=polished_blackstone_brick_slab,id=polished_blackstone_slab,state=type:top,ymin=0.5 +[1.16-]boxblock:id=crimson_slab,id=warped_slab,id=blackstone_slab,id=polished_blackstone_brick_slab,id=polished_blackstone_slab,state=type:bottom,ymax=0.5 # Warped pressure plate # Crimson pressure plate # Polished Blackstone pressure plate @@ -1743,8 +1743,8 @@ patchblock:id=bubble_column # Waxed exposed cut copper slab # Waxed weathered cut copper slab # Waxed oxidized cut copper slab -[1.17-]boxblock:id=cobbled_deepslate_slab,id=deepslate_brick_slab,id=deepslate_tile_slab,id=polished_deepslate_slab,id=cut_copper_slab,id=exposed_cut_copper_slab,id=weathered_cut_copper_slab,id=oxidized_cut_copper_slab,id=waxed_cut_copper_slab,id=waxed_exposed_cut_copper_slab,id=waxed_weathered_cut_copper_slab,id=waxed_oxidized_cut_copper_slab,data=0,data=1,ymin=0.5 -[1.17-]boxblock:id=cobbled_deepslate_slab,id=deepslate_brick_slab,id=deepslate_tile_slab,id=polished_deepslate_slab,id=cut_copper_slab,id=exposed_cut_copper_slab,id=weathered_cut_copper_slab,id=oxidized_cut_copper_slab,id=waxed_cut_copper_slab,id=waxed_exposed_cut_copper_slab,id=waxed_weathered_cut_copper_slab,id=waxed_oxidized_cut_copper_slab,data=2,data=3,ymax=0.5 +[1.17-]boxblock:id=cobbled_deepslate_slab,id=deepslate_brick_slab,id=deepslate_tile_slab,id=polished_deepslate_slab,id=cut_copper_slab,id=exposed_cut_copper_slab,id=weathered_cut_copper_slab,id=oxidized_cut_copper_slab,id=waxed_cut_copper_slab,id=waxed_exposed_cut_copper_slab,id=waxed_weathered_cut_copper_slab,id=waxed_oxidized_cut_copper_slab,state=type:top,ymin=0.5 +[1.17-]boxblock:id=cobbled_deepslate_slab,id=deepslate_brick_slab,id=deepslate_tile_slab,id=polished_deepslate_slab,id=cut_copper_slab,id=exposed_cut_copper_slab,id=weathered_cut_copper_slab,id=oxidized_cut_copper_slab,id=waxed_cut_copper_slab,id=waxed_exposed_cut_copper_slab,id=waxed_weathered_cut_copper_slab,id=waxed_oxidized_cut_copper_slab,state=type:bottom,ymax=0.5 # Cobbled deepslate wall # Deepslate brick wall # Deepslate tile wall diff --git a/DynmapCore/src/main/resources/texture_1.txt b/DynmapCore/src/main/resources/texture_1.txt index 7da4817f..e757b8e7 100644 --- a/DynmapCore/src/main/resources/texture_1.txt +++ b/DynmapCore/src/main/resources/texture_1.txt @@ -1287,62 +1287,62 @@ block:id=trapped_chest,patch0=0:trapchest,patch1=1:trapchest,patch2=2:trapchest, ############ # Oak slab -block:id=oak_slab,data=0,data=1,data=2,data=3,allfaces=0:oak_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=oak_slab,data=4,data=5,allfaces=0:oak_planks,stdrot=true +block:id=oak_slab,state=type:top,state=type:bottom,allfaces=0:oak_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=oak_slab,state=type:double,allfaces=0:oak_planks,stdrot=true # Spruce slab -block:id=spruce_slab,data=0,data=1,data=2,data=3,allfaces=0:spruce_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=spruce_slab,data=4,data=5,allfaces=0:spruce_planks,stdrot=true +block:id=spruce_slab,state=type:top,state=type:bottom,allfaces=0:spruce_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=spruce_slab,state=type:double,allfaces=0:spruce_planks,stdrot=true # Birch slab -block:id=birch_slab,data=0,data=1,data=2,data=3,allfaces=0:birch_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=birch_slab,data=4,data=5,allfaces=0:birch_planks,stdrot=true +block:id=birch_slab,state=type:top,state=type:bottom,allfaces=0:birch_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=birch_slab,state=type:double,allfaces=0:birch_planks,stdrot=true # Jungle slab -block:id=jungle_slab,data=0,data=1,data=2,data=3,allfaces=0:jungle_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=jungle_slab,data=4,data=5,allfaces=0:jungle_planks,stdrot=true +block:id=jungle_slab,state=type:top,state=type:bottom,allfaces=0:jungle_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=jungle_slab,state=type:double,allfaces=0:jungle_planks,stdrot=true # Acacia slab -block:id=acacia_slab,data=0,data=1,data=2,data=3,allfaces=0:acacia_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=acacia_slab,data=4,data=5,allfaces=0:acacia_planks,stdrot=true +block:id=acacia_slab,state=type:top,state=type:bottom,allfaces=0:acacia_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=acacia_slab,state=type:double,allfaces=0:acacia_planks,stdrot=true # Dark oak slab -block:id=dark_oak_slab,data=0,data=1,data=2,data=3,allfaces=0:dark_oak_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=dark_oak_slab,data=4,data=5,allfaces=0:dark_oak_planks,stdrot=true +block:id=dark_oak_slab,state=type:top,state=type:bottom,allfaces=0:dark_oak_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=dark_oak_slab,state=type:double,allfaces=0:dark_oak_planks,stdrot=true # Stone slab -block:id=stone_slab,data=0,data=1,data=2,data=3,allsides=0:stone,topbottom=0:stone,stdrot=true,transparency=SEMITRANSPARENT -block:id=stone_slab,data=4,data=5,allsides=0:stone,topbottom=0:stone,stdrot=true +block:id=stone_slab,state=type:top,state=type:bottom,allsides=0:stone,topbottom=0:stone,stdrot=true,transparency=SEMITRANSPARENT +block:id=stone_slab,state=type:double,allsides=0:stone,topbottom=0:stone,stdrot=true # Sandstone slab -block:id=sandstone_slab,data=0,data=1,data=2,data=3,bottom=0:sandstone_bottom,top=0:sandstone_top,allsides=0:sandstone,stdrot=true,transparency=SEMITRANSPARENT -block:id=sandstone_slab,data=4,data=5,bottom=0:sandstone_bottom,top=0:sandstone_top,allsides=0:sandstone,stdrot=true +block:id=sandstone_slab,state=type:top,state=type:bottom,bottom=0:sandstone_bottom,top=0:sandstone_top,allsides=0:sandstone,stdrot=true,transparency=SEMITRANSPARENT +block:id=sandstone_slab,state=type:double,bottom=0:sandstone_bottom,top=0:sandstone_top,allsides=0:sandstone,stdrot=true # Petified oak slab -block:id=petrified_oak_slab,data=0,data=1,data=2,data=3,allfaces=0:oak_planks,stdrot=true,transparency=SEMITRANSPARENT -block:id=petrified_oak_slab,data=4,data=5,allfaces=0:oak_planks,stdrot=true +block:id=petrified_oak_slab,state=type:top,state=type:bottom,allfaces=0:oak_planks,stdrot=true,transparency=SEMITRANSPARENT +block:id=petrified_oak_slab,state=type:double,allfaces=0:oak_planks,stdrot=true # Cobblestone slab -block:id=cobblestone_slab,data=0,data=1,data=2,data=3,allfaces=0:cobblestone,stdrot=true,transparency=SEMITRANSPARENT -block:id=cobblestone_slab,data=4,data=5,allfaces=0:cobblestone,stdrot=true +block:id=cobblestone_slab,state=type:top,state=type:bottom,allfaces=0:cobblestone,stdrot=true,transparency=SEMITRANSPARENT +block:id=cobblestone_slab,state=type:double,allfaces=0:cobblestone,stdrot=true # Brick slab -block:id=brick_slab,data=0,data=1,data=2,data=3,allfaces=0:bricks,stdrot=true,transparency=SEMITRANSPARENT -block:id=brick_slab,data=4,data=5,allfaces=0:bricks,stdrot=true +block:id=brick_slab,state=type:top,state=type:bottom,allfaces=0:bricks,stdrot=true,transparency=SEMITRANSPARENT +block:id=brick_slab,state=type:double,allfaces=0:bricks,stdrot=true # Stone brick slab -block:id=stone_brick_slab,data=0,data=1,data=2,data=3,allfaces=0:stone_bricks,stdrot=true,transparency=SEMITRANSPARENT -block:id=stone_brick_slab,data=4,data=5,allfaces=0:stone_bricks,stdrot=true +block:id=stone_brick_slab,state=type:top,state=type:bottom,allfaces=0:stone_bricks,stdrot=true,transparency=SEMITRANSPARENT +block:id=stone_brick_slab,state=type:double,allfaces=0:stone_bricks,stdrot=true # Nether brick slab -block:id=nether_brick_slab,data=0,data=1,data=2,data=3,allfaces=0:nether_bricks,stdrot=true,transparency=SEMITRANSPARENT -block:id=nether_brick_slab,data=4,data=5,allfaces=0:nether_bricks,stdrot=true +block:id=nether_brick_slab,state=type:top,state=type:bottom,allfaces=0:nether_bricks,stdrot=true,transparency=SEMITRANSPARENT +block:id=nether_brick_slab,state=type:double,allfaces=0:nether_bricks,stdrot=true # Quartz slab -block:id=quartz_slab,data=0,data=1,data=2,data=3,top=0:quartz_block_top,bottom=0:quartz_block_bottom,allsides=0:quartz_block_side,stdrot=true,transparency=SEMITRANSPARENT -block:id=quartz_slab,data=4,data=5,top=0:quartz_block_top,bottom=0:quartz_block_bottom,allsides=0:quartz_block_side +block:id=quartz_slab,state=type:top,state=type:bottom,top=0:quartz_block_top,bottom=0:quartz_block_bottom,allsides=0:quartz_block_side,stdrot=true,transparency=SEMITRANSPARENT +block:id=quartz_slab,state=type:double,top=0:quartz_block_top,bottom=0:quartz_block_bottom,allsides=0:quartz_block_side # Red sandstone slab -block:id=red_sandstone_slab,data=0,data=1,data=2,data=3,bottom=0:red_sandstone_bottom,top=0:red_sandstone_top,allsides=0:red_sandstone,stdrot=true,transparency=SEMITRANSPARENT -block:id=red_sandstone_slab,data=4,data=5,bottom=0:red_sandstone_bottom,top=0:red_sandstone_top,allsides=0:red_sandstone,stdrot=true +block:id=red_sandstone_slab,state=type:top,state=type:bottom,bottom=0:red_sandstone_bottom,top=0:red_sandstone_top,allsides=0:red_sandstone,stdrot=true,transparency=SEMITRANSPARENT +block:id=red_sandstone_slab,state=type:double,bottom=0:red_sandstone_bottom,top=0:red_sandstone_top,allsides=0:red_sandstone,stdrot=true # Purpur slab -block:id=purpur_slab,data=0,data=1,data=2,data=3,allfaces=0:purpur_block,stdrot=true,transparency=SEMITRANSPARENT -block:id=purpur_slab,data=4,data=5,allfaces=0:purpur_block,stdrot=true +block:id=purpur_slab,state=type:top,state=type:bottom,allfaces=0:purpur_block,stdrot=true,transparency=SEMITRANSPARENT +block:id=purpur_slab,state=type:double,allfaces=0:purpur_block,stdrot=true # Prismarine slab -block:id=prismarine_slab,data=0,data=1,data=2,data=3,allfaces=0:prismarine,stdrot=true,transparency=SEMITRANSPARENT -block:id=prismarine_slab,data=4,data=5,allfaces=0:prismarine,stdrot=true +block:id=prismarine_slab,state=type:top,state=type:bottom,allfaces=0:prismarine,stdrot=true,transparency=SEMITRANSPARENT +block:id=prismarine_slab,state=type:double,allfaces=0:prismarine,stdrot=true # Prismarine brick slab -block:id=prismarine_brick_slab,data=0,data=1,data=2,data=3,allfaces=0:prismarine_bricks,stdrot=true,transparency=SEMITRANSPARENT -block:id=prismarine_brick_slab,data=4,data=5,allfaces=0:prismarine_bricks,stdrot=true +block:id=prismarine_brick_slab,state=type:top,state=type:bottom,allfaces=0:prismarine_bricks,stdrot=true,transparency=SEMITRANSPARENT +block:id=prismarine_brick_slab,state=type:double,allfaces=0:prismarine_bricks,stdrot=true # Dsrk prismarine slab -block:id=dark_prismarine_slab,data=0,data=1,data=2,data=3,allfaces=0:dark_prismarine,stdrot=true,transparency=SEMITRANSPARENT -block:id=dark_prismarine_slab,data=4,data=5,allfaces=0:dark_prismarine,stdrot=true +block:id=dark_prismarine_slab,state=type:top,state=type:bottom,allfaces=0:dark_prismarine,stdrot=true,transparency=SEMITRANSPARENT +block:id=dark_prismarine_slab,state=type:double,allfaces=0:dark_prismarine,stdrot=true # Light weighted pressure plate diff --git a/DynmapCoreAPI/src/main/java/org/dynmap/renderer/DynmapBlockState.java b/DynmapCoreAPI/src/main/java/org/dynmap/renderer/DynmapBlockState.java index b4c2af51..151567f2 100644 --- a/DynmapCoreAPI/src/main/java/org/dynmap/renderer/DynmapBlockState.java +++ b/DynmapCoreAPI/src/main/java/org/dynmap/renderer/DynmapBlockState.java @@ -542,6 +542,17 @@ public class DynmapBlockState { } return lightAttenuation; } + /* + * Test if matches attrib=value pair + */ + public final boolean isStateMatch(String attrib, String value) { + String v = attrib + "=" + value; + v = v.toLowerCase(); + for (String state : stateList) { + if (state.equals(v)) return true; + } + return false; + } /** * To printable string */