Search in sources :

Example 1 with ForgeConfigFile

use of org.dynmap.utils.ForgeConfigFile in project dynmap by webbukkit.

the class TexturePack method loadTextureFile.

/**
 * Load texture pack mappings from texture.txt file
 */
private static void loadTextureFile(InputStream txtfile, String txtname, ConfigurationNode config, DynmapCore core, String blockset) {
    LineNumberReader rdr = null;
    int cnt = 0;
    HashMap<String, Integer> filetoidx = new HashMap<String, Integer>();
    HashMap<String, Integer> varvals = new HashMap<String, Integer>();
    final String mcver = core.getDynmapPluginPlatformVersion();
    boolean mod_cfg_needed = false;
    boolean mod_cfg_loaded = false;
    // Default to minecraft base
    String modname = "minecraft";
    String modversion = null;
    String texturemod = null;
    String texturepath = null;
    boolean terrain_ok = true;
    BlockStateParser bsp = new BlockStateParser();
    Map<DynmapBlockState, BitSet> 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
                // Find end
                int end = line.indexOf(']');
                if (end < 0) {
                    Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad version limit");
                    return;
                }
                String vertst = line.substring(1, end);
                String tver = mcver;
                if (vertst.startsWith("mod:")) {
                    // If mod version ranged
                    tver = modversion;
                    vertst = vertst.substring(4);
                }
                if (!HDBlockModels.checkVersionRange(tver, vertst)) {
                    skip = true;
                }
                line = line.substring(end + 1);
            }
            if (line.startsWith("#") || line.startsWith(";")) {
                skip = true;
            }
            // If we're skipping due to version restriction
            if (skip)
                continue;
            // Split off <type>:
            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)
                    // Mark as not usable
                    srctxtid = TXTID_INVALID;
                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;
                BlockTransparency trans = BlockTransparency.OPAQUE;
                int colorMult = 0;
                int blockColorIdx = -1;
                // Legacy top/bottom rotation
                boolean stdrot = false;
                CustomColorMultiplier custColorMult = null;
                String[] args = line.split(",");
                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 " + lineNum + " of " + txtname + ": bad texture " + av[1]);
                    }
                }
                bsprslt = bsp.getMatchingStates();
                if (bsprslt.size() > 0) {
                    for (String a : args) {
                        String[] av = a.split("=");
                        if (av.length < 2)
                            continue;
                        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")) {
                            faces[BlockStep.Y_PLUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
                        } else if (av[0].equals("north") || av[0].equals("x+") || av[0].equals("face4")) {
                            faces[BlockStep.X_PLUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
                        } else if (av[0].equals("south") || av[0].equals("x-") || av[0].equals("face5")) {
                            faces[BlockStep.X_MINUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
                        } else if (av[0].equals("west") || av[0].equals("z-") || av[0].equals("face3")) {
                            faces[BlockStep.Z_MINUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
                        } else if (av[0].equals("east") || av[0].equals("z+") || av[0].equals("face2")) {
                            faces[BlockStep.Z_PLUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
                        } else if (av[0].startsWith("face")) {
                            int fid0, fid1;
                            String idrange = av[0].substring(4);
                            String[] ids = idrange.split("-");
                            if (ids.length > 1) {
                                fid0 = Integer.parseInt(ids[0]);
                                fid1 = Integer.parseInt(ids[1]);
                            } else {
                                fid0 = fid1 = Integer.parseInt(ids[0]);
                            }
                            if ((fid0 < 0) || (fid1 < fid0)) {
                                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(), BlockStep.Z_PLUS.ordinal(), BlockStep.Z_MINUS.ordinal(), BlockStep.X_PLUS.ordinal(), BlockStep.X_MINUS.ordinal() };
                            int txtid = parseTextureIndex(filetoidx, srctxtid, av[1]);
                            for (int i = fid0; (i <= fid1) && (i < 6); i++) {
                                faces[faceToOrd[i]] = txtid;
                            }
                        } else if (av[0].equals("allfaces")) {
                            int id = parseTextureIndex(filetoidx, srctxtid, av[1]);
                            for (int i = 0; i < 6; i++) {
                                faces[i] = id;
                            }
                        } else if (av[0].equals("allsides")) {
                            int id = parseTextureIndex(filetoidx, srctxtid, av[1]);
                            faces[BlockStep.X_PLUS.ordinal()] = id;
                            faces[BlockStep.X_MINUS.ordinal()] = id;
                            faces[BlockStep.Z_PLUS.ordinal()] = id;
                            faces[BlockStep.Z_MINUS.ordinal()] = id;
                        } else if (av[0].equals("topbottom")) {
                            faces[BlockStep.Y_MINUS.ordinal()] = faces[BlockStep.Y_PLUS.ordinal()] = parseTextureIndex(filetoidx, srctxtid, av[1]);
                        } else if (av[0].equals("blockcolor")) {
                            if (filetoidx.containsKey(av[1]))
                                blockColorIdx = filetoidx.get(av[1]);
                            else
                                Log.severe("Format error - line " + lineNum + " of " + txtname + ": bad texture " + av[1]);
                        } else if (av[0].startsWith("patch")) {
                            int patchid0, patchid1;
                            String idrange = av[0].substring(5);
                            String[] ids = idrange.split("-");
                            if (ids.length > 1) {
                                patchid0 = Integer.parseInt(ids[0]);
                                patchid1 = Integer.parseInt(ids[1]);
                            } else {
                                patchid0 = patchid1 = Integer.parseInt(ids[0]);
                            }
                            if ((patchid0 < 0) || (patchid1 < patchid0)) {
                                Log.severe("Texture mapping has invalid patch index - " + av[1] + " - line " + lineNum + " of " + txtname);
                                return;
                            }
                            if (faces.length <= patchid1) {
                                int[] newfaces = new int[patchid1 + 1];
                                Arrays.fill(newfaces, TILEINDEX_BLANK);
                                System.arraycopy(faces, 0, newfaces, 0, faces.length);
                                faces = newfaces;
                                int[] newtxtidx = new int[patchid1 + 1];
                                Arrays.fill(newtxtidx, -1);
                                System.arraycopy(txtidx, 0, newtxtidx, 0, txtidx.length);
                                txtidx = newtxtidx;
                            }
                            int txtid = parseTextureIndex(filetoidx, srctxtid, av[1]);
                            for (int i = patchid0; i <= patchid1; i++) {
                                faces[i] = txtid;
                            }
                        } 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 " + lineNum + " of " + txtname);
                            }
                            /* For leaves, base on leaf transparency setting */
                            if (trans == BlockTransparency.LEAVES) {
                                if (core.getLeafTransparency())
                                    trans = BlockTransparency.TRANSPARENT;
                                else
                                    trans = BlockTransparency.OPAQUE;
                            }
                        } else if (av[0].equals("colorMult")) {
                            colorMult = (int) Long.parseLong(av[1], 16);
                        } else if (av[0].equals("custColorMult")) {
                            try {
                                Class<?> cls = Class.forName(av[1]);
                                custColorMult = (CustomColorMultiplier) cls.newInstance();
                            } catch (Exception x) {
                                Log.severe("Error loading custom color multiplier - " + av[1] + ": " + x.getMessage());
                            }
                        } else if (av[0].equals("stdrot")) {
                            stdrot = av[1].equals("true");
                        }
                    }
                    for (String a : args) {
                        String[] av = a.split("=");
                        if (av.length < 2)
                            continue;
                        if (av[0].startsWith("layer")) {
                            if (layers == null) {
                                layers = new byte[faces.length];
                                Arrays.fill(layers, (byte) -1);
                            }
                            String[] v = av[0].substring(5).split("-");
                            int id1, id2;
                            id1 = id2 = Integer.parseInt(v[0]);
                            if (v.length > 1) {
                                id2 = Integer.parseInt(v[1]);
                            }
                            byte val = (byte) Integer.parseInt(av[1]);
                            for (; id1 <= id2; id1++) {
                                layers[id1] = val;
                            }
                        }
                    }
                    /* If we have everything, build block */
                    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(bsprslt);
                        cnt++;
                    } else {
                        Log.severe("Texture mapping missing required parameters = line " + lineNum + " of " + txtname);
                    }
                }
            } else if (typeid.equals("copyblock")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String[] args = line.split(",");
                String srcname = null;
                int srcmeta = 0;
                BlockTransparency trans = null;
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("srcid")) {
                        srcname = getBlockName(modname, av[1]);
                    } else if (av[0].equals("srcmeta")) {
                        srcmeta = 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 " + lineNum + " of " + txtname);
                        }
                        /* For leaves, base on leaf transparency setting */
                        if (trans == BlockTransparency.LEAVES) {
                            if (core.getLeafTransparency())
                                trans = BlockTransparency.TRANSPARENT;
                            else
                                trans = BlockTransparency.OPAQUE;
                        }
                    }
                }
                /* If we have everything, build block */
                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 " + lineNum + " of " + txtname);
                    } else {
                        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 " + lineNum + " of " + txtname);
                }
            } else if (typeid.equals("addtotexturemap")) {
                int srctxtid = -1;
                String mapid = null;
                String[] args = line.split(",");
                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 " + lineNum + " of " + txtname);
                    } else if (av[0].equals("mapid")) {
                        mapid = av[1];
                    }
                }
                if (mapid != null) {
                    for (String a : args) {
                        String[] av = a.split("=");
                        if (av.length < 2)
                            continue;
                        if (av[0].startsWith("key:")) {
                            Integer key = getIntValue(varvals, av[0].substring(4));
                            if ((key != null) && (key > 0)) {
                                addTextureByKey(mapid, key, parseTextureIndex(filetoidx, srctxtid, av[1]));
                            }
                        }
                    }
                } else {
                    Log.severe("Missing mapid  - line " + lineNum + " of " + txtname);
                }
            } else if (typeid.equals("texturemap")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String mapid = null;
                BlockTransparency trans = BlockTransparency.OPAQUE;
                int colorMult = 0;
                CustomColorMultiplier custColorMult = null;
                String[] args = line.split(",");
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("mapid")) {
                        mapid = 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 " + lineNum + " of " + txtname);
                        }
                        /* For leaves, base on leaf transparency setting */
                        if (trans == BlockTransparency.LEAVES) {
                            if (core.getLeafTransparency())
                                trans = BlockTransparency.TRANSPARENT;
                            else
                                trans = BlockTransparency.OPAQUE;
                        }
                    } else if (av[0].equals("colorMult")) {
                        colorMult = Integer.valueOf(av[1], 16);
                    } else if (av[0].equals("custColorMult")) {
                        try {
                            Class<?> cls = Class.forName(av[1]);
                            custColorMult = (CustomColorMultiplier) cls.newInstance();
                        } catch (Exception x) {
                            Log.severe("Error loading custom color multiplier - " + av[1] + ": " + x.getMessage());
                        }
                    }
                }
                /* If we have everything, build texture map */
                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 " + lineNum + " of " + txtname);
                }
            } 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;
                String id = null;
                TileFileFormat fmt = TileFileFormat.GRID;
                MaterialType mt = null;
                if (istxt) {
                    xdim = ydim = 1;
                    fmt = TileFileFormat.GRID;
                }
                for (String arg : args) {
                    String[] aval = arg.split("=");
                    if (aval.length < 2)
                        continue;
                    if (aval[0].equals("id")) {
                        id = aval[1];
                        if (fname == null) {
                            if (texturepath != null) {
                                fname = texturepath + id + ".png";
                            } else if (texturemod != null) {
                                fname = "mods/" + texturemod + "/textures/blocks/" + id + ".png";
                            }
                        }
                    } else if (aval[0].equals("filename"))
                        fname = aval[1];
                    else if (aval[0].equals("xcount"))
                        xdim = Integer.parseInt(aval[1]);
                    else if (aval[0].equals("ycount"))
                        ydim = Integer.parseInt(aval[1]);
                    else if (aval[0].equals("format")) {
                        fmt = TileFileFormat.valueOf(aval[1].toUpperCase());
                        if (fmt == null) {
                            Log.severe("Invalid format type " + aval[1] + " - line " + lineNum + " of " + txtname);
                            return;
                        }
                    } else if (aval[0].equals("material")) {
                        mt = MaterialType.valueOf(aval[1]);
                        if (mt == null) {
                            Log.warning("Bad custom material type: " + aval[1]);
                        }
                    }
                }
                if ((fname != null) && (id != null)) {
                    /* Register the file */
                    int fid = findOrAddDynamicTileFile(fname, modname, xdim, ydim, fmt, args);
                    filetoidx.put(id, fid);
                    /* Save lookup */
                    if (mt != null) {
                        addonfiles.get(fid).material = mt;
                    }
                } else {
                    Log.severe("Format error - line " + lineNum + " of " + txtname);
                    return;
                }
            } 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 */
                    return;
                /* Quit */
                } else /* If setting is not defined or false, quit */
                if (config.getBoolean(line, false) == false) {
                    return;
                } else {
                    Log.info(line + " textures enabled");
                }
            } 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 " + lineNum + " of " + txtname);
                        return;
                    }
                    try {
                        int val = Integer.valueOf(v[1]);
                        /* Parse default value */
                        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 " + lineNum + " of " + txtname + ": " + nfx.getMessage());
                        return;
                    }
                }
            } else if (typeid.equals("cfgfile")) {
                /* If config file */
                if (!mod_cfg_loaded) {
                    mod_cfg_needed = true;
                }
                File cfgfile = new File(line);
                ForgeConfigFile cfg = new ForgeConfigFile(cfgfile);
                if (cfg.load()) {
                    cfg.addBlockIDs(varvals);
                    mod_cfg_needed = false;
                    mod_cfg_loaded = true;
                }
            } else if (typeid.equals("modname")) {
                String[] names = line.split(",");
                boolean found = false;
                for (String n : names) {
                    String[] ntok = n.split("[\\[\\]]");
                    String rng = null;
                    if (ntok.length > 1) {
                        n = ntok[0].trim();
                        rng = ntok[1].trim();
                    }
                    n = n.trim();
                    // If already supplied by mod, quit processing this file
                    if (loadedmods.contains(n)) {
                        return;
                    }
                    String modver = core.getServer().getModVersion(n);
                    if ((modver != null) && ((rng == null) || HDBlockModels.checkVersionRange(modver, rng))) {
                        found = true;
                        Log.info(n + "[" + modver + "] textures enabled");
                        modname = n;
                        modversion = modver;
                        if (texturemod == null)
                            texturemod = modname;
                        loadedmods.add(n);
                        // Prime values from block and item unique IDs
                        core.addModBlockItemIDs(modname, varvals);
                        break;
                    }
                }
                if (!found)
                    return;
            } else if (typeid.equals("texturemod")) {
                texturemod = line;
            } else if (typeid.equals("texturepath")) {
                texturepath = line.trim();
                if (texturepath.charAt(texturepath.length() - 1) != '/') {
                    texturepath += "/";
                }
            } else if (typeid.equals("biome")) {
                String[] args = line.split(",");
                int id = 0;
                int grasscolormult = -1;
                int foliagecolormult = -1;
                int watercolormult = -1;
                double rain = -1.0;
                double tmp = -1.0;
                for (int i = 0; i < args.length; i++) {
                    String[] v = args[i].split("=");
                    if (v.length < 2) {
                        Log.severe("Format error - line " + lineNum + " of " + txtname);
                        return;
                    }
                    if (v[0].equals("id")) {
                        id = getIntValue(varvals, v[1]);
                    } else if (v[0].equals("grassColorMult")) {
                        grasscolormult = Integer.valueOf(v[1], 16);
                    } else if (v[0].equals("foliageColorMult")) {
                        foliagecolormult = Integer.valueOf(v[1], 16);
                    } else if (v[0].equals("waterColorMult")) {
                        watercolormult = Integer.valueOf(v[1], 16);
                    } else if (v[0].equals("temp")) {
                        tmp = Double.parseDouble(v[1]);
                    } else if (v[0].equals("rain")) {
                        rain = Double.parseDouble(v[1]);
                    }
                }
                if (id > 0) {
                    BiomeMap b = BiomeMap.byBiomeID(id);
                    /* Find biome */
                    if (b == null) {
                        Log.severe("Format error - line " + lineNum + " of " + txtname + ": " + id);
                    } else {
                        if (foliagecolormult != -1)
                            b.setFoliageColorMultiplier(foliagecolormult);
                        if (grasscolormult != -1)
                            b.setGrassColorMultiplier(grasscolormult);
                        if (watercolormult != -1)
                            b.setWaterColorMultiplier(watercolormult);
                        if (tmp != -1.0)
                            b.setTemperature(tmp);
                        if (rain != -1.0)
                            b.setRainfall(rain);
                    }
                }
            } else if (typeid.equals("version")) {
                if (!HDBlockModels.checkVersionRange(mcver, line)) {
                    return;
                }
            } else if (typeid.equals("noterrainpng")) {
                if (line.startsWith("true")) {
                    terrain_ok = false;
                } else {
                    terrain_ok = true;
                }
            }
        }
        if (mod_cfg_needed) {
            Log.severe("Error loading configuration file for " + modname);
        }
        Log.verboseinfo("Loaded " + cnt + " texture mappings from " + txtname);
    } catch (IOException iox) {
        Log.severe("Error reading " + txtname + " - " + iox.toString());
    } catch (NumberFormatException nfx) {
        Log.severe("Format error - line " + rdr.getLineNumber() + " of " + txtname + ": " + nfx.getMessage());
    } finally {
        if (rdr != null) {
            try {
                rdr.close();
                rdr = null;
            } catch (IOException e) {
            }
        }
    }
}
Also used : DynIntHashMap(org.dynmap.utils.DynIntHashMap) HashMap(java.util.HashMap) DynmapBlockState(org.dynmap.renderer.DynmapBlockState) LineNumberReader(java.io.LineNumberReader) ForgeConfigFile(org.dynmap.utils.ForgeConfigFile) InputStreamReader(java.io.InputStreamReader) BlockStateParser(org.dynmap.utils.BlockStateParser) BitSet(java.util.BitSet) CustomColorMultiplier(org.dynmap.renderer.CustomColorMultiplier) BiomeMap(org.dynmap.common.BiomeMap) IOException(java.io.IOException) ZipException(java.util.zip.ZipException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) ForgeConfigFile(org.dynmap.utils.ForgeConfigFile) ZipFile(java.util.zip.ZipFile) File(java.io.File)

Example 2 with ForgeConfigFile

use of org.dynmap.utils.ForgeConfigFile in project dynmap by webbukkit.

the class HDBlockModels method loadModelFile.

/**
 * Load models from file
 * @param core
 */
private static void loadModelFile(InputStream in, String fname, ConfigurationNode config, DynmapCore core, String blockset) {
    LineNumberReader rdr = null;
    int cnt = 0;
    boolean need_mod_cfg = false;
    boolean mod_cfg_loaded = false;
    String modname = "minecraft";
    String modversion = null;
    final String mcver = core.getDynmapPluginPlatformVersion();
    BlockStateParser bsp = new BlockStateParser();
    Map<DynmapBlockState, BitSet> bsprslt;
    try {
        String line;
        ArrayList<HDBlockVolumetricModel> modlist = new ArrayList<HDBlockVolumetricModel>();
        ArrayList<HDBlockPatchModel> pmodlist = new ArrayList<HDBlockPatchModel>();
        HashMap<String, Integer> varvals = new HashMap<String, Integer>();
        HashMap<String, PatchDefinition> patchdefs = new HashMap<String, PatchDefinition>();
        pdf.setPatchNameMape(patchdefs);
        int layerbits = 0;
        int rownum = 0;
        int scale = 0;
        rdr = new LineNumberReader(new InputStreamReader(in));
        while ((line = rdr.readLine()) != null) {
            boolean skip = false;
            int lineNum = rdr.getLineNumber();
            if ((line.length() > 0) && (line.charAt(0) == '[')) {
                // If version constrained like
                // Find end
                int end = line.indexOf(']');
                if (end < 0) {
                    Log.severe("Format error - line " + lineNum + " of " + fname + ": bad version limit");
                    return;
                }
                String vertst = line.substring(1, end);
                String tver = mcver;
                if (vertst.startsWith("mod:")) {
                    // If mod version ranged
                    tver = modversion;
                    vertst = vertst.substring(4);
                }
                if (!HDBlockModels.checkVersionRange(tver, vertst)) {
                    skip = true;
                }
                line = line.substring(end + 1);
            }
            // Comment line
            if (line.startsWith("#") || line.startsWith(";")) {
                skip = true;
            }
            // If we're skipping due to version restriction
            if (skip)
                continue;
            // Split off <type>:
            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;
                String[] args = line.split(",");
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("scale")) {
                        scale = Integer.parseInt(av[1]);
                    }
                }
                bsprslt = bsp.getMatchingStates();
                /* If we have everything, build block */
                if ((bsprslt.size() > 0) && (scale > 0)) {
                    modlist.clear();
                    for (DynmapBlockState bblk : bsprslt.keySet()) {
                        if (bblk.isNotAir()) {
                            modlist.add(new HDBlockVolumetricModel(bblk, bsprslt.get(bblk), scale, new long[0], blockset));
                            cnt++;
                        } else {
                            Log.severe("Invalid model block name " + bblk.blockName + " at line " + lineNum);
                        }
                    }
                } else {
                    Log.severe("Block model missing required parameters = line " + lineNum + " of " + fname);
                }
                layerbits = 0;
            } else if (typeid.equals("layer")) {
                String[] args = line.split(",");
                layerbits = 0;
                rownum = 0;
                for (String a : args) {
                    layerbits |= (1 << Integer.parseInt(a));
                }
            } else if (typeid.equals("rotate")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String[] args = line.split(",");
                int rot = -1;
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("rot")) {
                        rot = Integer.parseInt(av[1]);
                    }
                }
                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 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)) {
                    HDBlockVolumetricModel vmod = (HDBlockVolumetricModel) mod;
                    for (int x = 0; x < scale; x++) {
                        for (int y = 0; y < scale; y++) {
                            for (int z = 0; z < scale; z++) {
                                if (vmod.isSubblockSet(x, y, z) == false)
                                    continue;
                                switch(rot) {
                                    case 0:
                                        for (HDBlockVolumetricModel bm : modlist) {
                                            bm.setSubblock(x, y, z, true);
                                        }
                                        break;
                                    case 90:
                                        for (HDBlockVolumetricModel bm : modlist) {
                                            bm.setSubblock(scale - z - 1, y, x, true);
                                        }
                                        break;
                                    case 180:
                                        for (HDBlockVolumetricModel bm : modlist) {
                                            bm.setSubblock(scale - x - 1, y, scale - z - 1, true);
                                        }
                                        break;
                                    case 270:
                                        for (HDBlockVolumetricModel bm : modlist) {
                                            bm.setSubblock(z, y, scale - x - 1, true);
                                        }
                                        break;
                                }
                            }
                        }
                    }
                } else {
                    Log.severe("Invalid rotate error - line " + lineNum + " of " + fname);
                    continue;
                }
            } else if (typeid.equals("patchrotate")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String[] args = line.split(",");
                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("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]);
                    }
                }
                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()) {
                } 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++) {
                        newpatches[i] = (PatchDefinition) pdf.getRotatedPatch(patches[i], rotx, roty, rotz, patches[i].textureindex);
                    }
                    if (patches.length > max_patches)
                        max_patches = patches.length;
                    for (HDBlockPatchModel patchmod : pmodlist) {
                        patchmod.setPatches(newpatches);
                    }
                } else {
                    Log.severe("Invalid rotate error - line " + lineNum + " of " + fname);
                    return;
                }
            } 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()) {
                        BitSet bits = bsprslt.get(bbs);
                        for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) {
                            DynmapBlockState bs = bbs.getState(i);
                            changeIgnoredBlocks.set(bs.globalStateIndex);
                        }
                    } else {
                        Log.severe("Invalid update ignore block name " + bbs + " at line " + lineNum);
                    }
                }
            } 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 */
                    return;
                /* Quit */
                } else /* If setting is not defined or false, quit */
                if (config.getBoolean(line, false) == false) {
                    return;
                } else {
                    Log.info(line + " models enabled");
                }
            } 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 " + lineNum + " of " + fname);
                        return;
                    }
                    try {
                        int val = Integer.valueOf(v[1]);
                        /* Parse default value */
                        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 " + lineNum + " of " + fname);
                        return;
                    }
                }
            } 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;
                }
                if (cfg.load()) {
                    cfg.addBlockIDs(varvals);
                    need_mod_cfg = false;
                    mod_cfg_loaded = true;
                }
            } else if (typeid.equals("patch")) {
                String patchid = null;
                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;
                double p_xv = 1.0, p_yv = 0.0, p_zv = 0.0;
                double p_umin = 0.0, p_umax = 1.0;
                double p_vmin = 0.0, p_vmax = 1.0;
                double p_vmaxatumax = -1.0;
                double p_vminatumax = -1.0;
                double p_uplusvmax = -1.0;
                SideVisible p_sidevis = SideVisible.BOTH;
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("id")) {
                        patchid = av[1];
                    } else if (av[0].equals("Ox")) {
                        p_x0 = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Oy")) {
                        p_y0 = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Oz")) {
                        p_z0 = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Ux")) {
                        p_xu = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Uy")) {
                        p_yu = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Uz")) {
                        p_zu = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Vx")) {
                        p_xv = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Vy")) {
                        p_yv = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Vz")) {
                        p_zv = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Umin")) {
                        p_umin = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Umax")) {
                        p_umax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Vmin")) {
                        p_vmin = Double.parseDouble(av[1]);
                    } else if (av[0].equals("Vmax")) {
                        p_vmax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("UplusVmax")) {
                        Log.warning("UplusVmax deprecated - use VmaxAtUMax - line " + lineNum + " of " + fname);
                        p_uplusvmax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("VmaxAtUMax")) {
                        p_vmaxatumax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("VminAtUMax")) {
                        p_vminatumax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("visibility")) {
                        if (av[1].equals("top"))
                            p_sidevis = SideVisible.TOP;
                        else if (av[1].equals("topflip"))
                            p_sidevis = SideVisible.TOPFLIP;
                        else if (av[1].equals("topflipv"))
                            p_sidevis = SideVisible.TOPFLIPV;
                        else if (av[1].equals("topfliphv"))
                            p_sidevis = SideVisible.TOPFLIPHV;
                        else if (av[1].equals("bottom"))
                            p_sidevis = SideVisible.BOTTOM;
                        else if (av[1].equals("flip"))
                            p_sidevis = SideVisible.FLIP;
                        else
                            p_sidevis = SideVisible.BOTH;
                    }
                }
                // Deprecated: If set, compute umax, vmax, and vmaxatumax
                if (p_uplusvmax >= 0.0) {
                    p_umax = p_uplusvmax;
                    p_vmax = p_uplusvmax;
                    p_vmaxatumax = 0.0;
                }
                // If not set, match p_vmax by default
                if (p_vmaxatumax < 0.0) {
                    p_vmaxatumax = p_vmax;
                }
                // If not set, match p_vmin by default
                if (p_vminatumax < 0.0) {
                    p_vminatumax = p_vmin;
                }
                /* If completed, add to map */
                if (patchid != null) {
                    PatchDefinition pd = pdf.getPatch(p_x0, p_y0, p_z0, p_xu, p_yu, p_zu, p_xv, p_yv, p_zv, p_umin, p_umax, p_vmin, p_vminatumax, p_vmax, p_vmaxatumax, p_sidevis, 0);
                    if (pd != null) {
                        patchdefs.put(patchid, pd);
                    }
                }
            } else if (typeid.equals("patchblock")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String[] args = line.split(",");
                ArrayList<PatchDefinition> patches = new ArrayList<PatchDefinition>();
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].startsWith("patch")) {
                        int patchnum0, patchnum1;
                        String ids = av[0].substring(5);
                        String[] ids2 = ids.split("-");
                        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 " + lineNum + " of " + fname);
                            return;
                        }
                        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++) {
                            PatchDefinition pd = pdf.getPatchByName(patchid, i);
                            if (pd == null) {
                                Log.severe("Invalid patch ID " + patchid + " - line " + lineNum + " of " + fname);
                                return;
                            }
                            patches.add(i, pd);
                        }
                    }
                }
                /* If we have everything, build block */
                bsprslt = bsp.getMatchingStates();
                pmodlist.clear();
                if (bsprslt.size() > 0) {
                    PatchDefinition[] patcharray = patches.toArray(new PatchDefinition[patches.size()]);
                    if (patcharray.length > max_patches)
                        max_patches = patcharray.length;
                    for (DynmapBlockState bs : bsprslt.keySet()) {
                        if (bs.isNotAir()) {
                            pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset));
                            cnt++;
                        } else {
                            Log.severe("Invalid patchmodel block name " + bs + " at line " + lineNum);
                        }
                    }
                } else {
                    Log.severe("Patch block model missing required parameters = line " + lineNum + " of " + fname);
                }
            } else // Shortcut for defining a patchblock that is a simple rectangular prism, with sidex corresponding to full block sides
            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("xmin")) {
                        xmin = Double.parseDouble(av[1]);
                    } else if (av[0].equals("xmax")) {
                        xmax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("ymin")) {
                        ymin = Double.parseDouble(av[1]);
                    } else if (av[0].equals("ymax")) {
                        ymax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("zmin")) {
                        zmin = Double.parseDouble(av[1]);
                    } else if (av[0].equals("zmax")) {
                        zmax = Double.parseDouble(av[1]);
                    } else if (av[0].equals("patches")) {
                        String[] v = av[1].split("/");
                        patchlist = new int[6];
                        for (int vidx = 0; (vidx < v.length) && (vidx < patchlist.length); vidx++) {
                            patchlist[vidx] = getIntValue(varvals, v[vidx]);
                        }
                    }
                }
                /* If we have everything, build block */
                pmodlist.clear();
                bsprslt = bsp.getMatchingStates();
                if (bsprslt.size() > 0) {
                    ArrayList<RenderPatch> pd = new ArrayList<RenderPatch>();
                    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)
                        max_patches = patcharray.length;
                    for (DynmapBlockState bs : bsprslt.keySet()) {
                        if (bs.isNotAir()) {
                            pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset));
                            cnt++;
                        } else {
                            Log.severe("Invalid boxmodel block name " + bs + " at line " + lineNum);
                        }
                    }
                } else {
                    Log.severe("Box block model missing required parameters = line " + lineNum + " of " + fname);
                }
            } else // Shortcut for defining a patchblock that is a simple rectangular prism, with sidex corresponding to full block sides
            if (typeid.equals("boxlist")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String[] args = line.split(",");
                ArrayList<BoxLimits> boxes = new ArrayList<BoxLimits>();
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("box")) {
                        String[] prms = av[1].split(":");
                        BoxLimits box = new BoxLimits();
                        if (prms.length > 0)
                            box.xmin = Double.parseDouble(prms[0]);
                        if (prms.length > 1)
                            box.xmax = Double.parseDouble(prms[1]);
                        if (prms.length > 2)
                            box.ymin = Double.parseDouble(prms[2]);
                        if (prms.length > 3)
                            box.ymax = Double.parseDouble(prms[3]);
                        if (prms.length > 4)
                            box.zmin = Double.parseDouble(prms[4]);
                        if (prms.length > 5)
                            box.zmax = Double.parseDouble(prms[5]);
                        if (prms.length > 6) {
                            String[] pl = prms[6].split("/");
                            for (int p = 0; (p < 6) && (p < pl.length); p++) {
                                box.patches[p] = Integer.parseInt(pl[p]);
                            }
                        }
                        if (prms.length > 7) {
                            box.yrot = Integer.parseInt(prms[7]);
                        }
                        boxes.add(box);
                    }
                }
                /* If we have everything, build block */
                bsprslt = bsp.getMatchingStates();
                pmodlist.clear();
                if (bsprslt.size() > 0) {
                    ArrayList<RenderPatch> pd = new ArrayList<RenderPatch>();
                    for (BoxLimits bl : boxes) {
                        CustomRenderer.addBox(pdf, pd, bl.xmin, bl.xmax, bl.ymin, bl.ymax, bl.zmin, bl.zmax, bl.patches, bl.yrot);
                    }
                    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)
                        max_patches = patcharray.length;
                    for (DynmapBlockState bs : bsprslt.keySet()) {
                        if (bs.isNotAir()) {
                            pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset));
                            cnt++;
                        } else {
                            Log.severe("Invalid boxlist block name " + bs + " at line " + lineNum);
                        }
                    }
                } else {
                    Log.severe("Box list block model missing required parameters = line " + lineNum + " of " + fname);
                }
            } else // Shortcur for building JSON model style
            if (typeid.equals("modellist")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                String[] args = line.split(",");
                ArrayList<ModelBox> boxes = new ArrayList<ModelBox>();
                for (String a : args) {
                    String[] av = a.split("=");
                    if (av.length < 2)
                        continue;
                    if (av[0].equals("box")) {
                        // box=from-x/y/z:to-x/y/z/rotx/roty/rotz:<side - upnsew>/<txtidx>/umin/vmin/umax/vmax>:...
                        String[] prms = av[1].split(":");
                        ModelBox box = new ModelBox();
                        if (prms.length > 0) {
                            // Handle from (from-x/y/z or from-x/y/z/shadow)
                            String[] xyz = prms[0].split("/");
                            if ((xyz.length == 3) || (xyz.length == 4)) {
                                box.from[0] = Double.parseDouble(xyz[0]);
                                box.from[1] = Double.parseDouble(xyz[1]);
                                box.from[2] = Double.parseDouble(xyz[2]);
                                if ((xyz.length >= 4) && (xyz[3].equals("false"))) {
                                    box.shade = false;
                                }
                            } else {
                                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
                            String[] xyz = prms[1].split("/");
                            if (xyz.length >= 3) {
                                box.to[0] = Double.parseDouble(xyz[0]);
                                box.to[1] = Double.parseDouble(xyz[1]);
                                box.to[2] = Double.parseDouble(xyz[2]);
                                if (xyz.length >= 6) {
                                    // If 6, second set are rotations (xrot/yrot/zrot)
                                    box.xrot = Double.parseDouble(xyz[3]);
                                    box.yrot = Double.parseDouble(xyz[4]);
                                    box.zrot = Double.parseDouble(xyz[5]);
                                }
                                if (xyz.length >= 9) {
                                    // If 9, third set is rotation origin (xrot/yrot/zrot)
                                    box.xrotorig = Double.parseDouble(xyz[6]);
                                    box.yrotorig = Double.parseDouble(xyz[7]);
                                    box.zrotorig = Double.parseDouble(xyz[8]);
                                }
                            } else {
                                Log.severe("Invalid modellist TO value (" + prms[1] + " at line " + lineNum);
                            }
                        }
                        // OR R/mrx/mry/mrz for model rotation
                        for (int faceidx = 2; faceidx < prms.length; faceidx++) {
                            String v = prms[faceidx];
                            String[] flds = v.split("/");
                            // If rotation
                            if (flds[0].equals("R") && (flds.length == 4)) {
                                box.modrotx = Integer.parseInt(flds[1]);
                                box.modroty = Integer.parseInt(flds[2]);
                                box.modrotz = Integer.parseInt(flds[3]);
                                continue;
                            }
                            ModelBoxSide side = new ModelBoxSide();
                            side.rot = null;
                            if ((flds.length != 2) && (flds.length != 6)) {
                                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 " + lineNum);
                                    continue;
                                }
                                if (flds[0].length() > 1) {
                                    String r = flds[0].substring(1);
                                    switch(r) {
                                        case "90":
                                            side.rot = ModelBlockModel.SideRotation.DEG90;
                                            break;
                                        case "180":
                                            side.rot = ModelBlockModel.SideRotation.DEG180;
                                            break;
                                        case "270":
                                            side.rot = ModelBlockModel.SideRotation.DEG270;
                                            break;
                                    }
                                }
                            }
                            if (flds.length > 1) {
                                side.textureid = getIntValue(varvals, flds[1]);
                            }
                            if (flds.length >= 6) {
                                side.uv = new double[4];
                                side.uv[0] = Double.parseDouble(flds[2]);
                                side.uv[1] = Double.parseDouble(flds[3]);
                                side.uv[2] = Double.parseDouble(flds[4]);
                                side.uv[3] = Double.parseDouble(flds[5]);
                            }
                            box.sides.add(side);
                        }
                        boxes.add(box);
                    }
                }
                /* If we have everything, build block */
                bsprslt = bsp.getMatchingStates();
                pmodlist.clear();
                if (bsprslt.size() > 0) {
                    ArrayList<PatchDefinition> pd = new ArrayList<PatchDefinition>();
                    for (ModelBox bl : boxes) {
                        // Loop through faces
                        for (ModelBoxSide side : bl.sides) {
                            PatchDefinition patch = pdf.getModelFace(bl.from, bl.to, side.side, side.uv, side.rot, bl.shade, side.textureid);
                            if (patch != null) {
                                // If any rotations, apply them here
                                if ((bl.xrot != 0) || (bl.yrot != 0) || (bl.zrot != 0)) {
                                    patch = pdf.getPatch(patch, -bl.xrot, -bl.yrot, -bl.zrot, new Vector3D(bl.xrotorig / 16, bl.yrotorig / 16, bl.zrotorig / 16), patch.textureindex);
                                    if (patch == null)
                                        continue;
                                }
                                // If model rotation, apply too
                                if ((bl.modrotx != 0) || (bl.modroty != 0) || (bl.modrotz != 0)) {
                                    patch = pdf.getPatch(patch, bl.modrotx, bl.modroty, bl.modrotz, patch.textureindex);
                                    if (patch == null)
                                        continue;
                                }
                                pd.add(patch);
                            } else {
                                Log.severe(String.format("Invalid modellist patch for box %.02f/%.02f/%.02f:%.02f/%.02f/%.02f 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));
                                Log.verboseinfo(String.format("line = %s:%s", typeid, line));
                            }
                        }
                    }
                    PatchDefinition[] patcharray = new PatchDefinition[pd.size()];
                    for (int i = 0; i < patcharray.length; i++) {
                        patcharray[i] = pd.get(i);
                    }
                    if (patcharray.length > max_patches)
                        max_patches = patcharray.length;
                    for (DynmapBlockState bs : bsprslt.keySet()) {
                        if (bs.isNotAir()) {
                            pmodlist.add(new HDBlockPatchModel(bs, bsprslt.get(bs), patcharray, blockset));
                            cnt++;
                        } else {
                            Log.severe("Invalid modellist block name " + bs + " at line " + lineNum);
                        }
                    }
                } else {
                    Log.severe("Model list block model missing required parameters = line " + lineNum + " of " + fname);
                }
            } else if (typeid.equals("customblock")) {
                // Parse block states
                bsp.processLine(modname, line, lineNum, varvals);
                HashMap<String, String> custargs = new HashMap<String, String>();
                String[] args = line.split(",");
                String cls = null;
                for (String a : args) {
                    String[] av = a.split("=");
                    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("class")) {
                        cls = av[1];
                    } else {
                        /* See if substitution value available */
                        Integer vv = varvals.get(av[1]);
                        if (vv == null)
                            custargs.put(av[0], av[1]);
                        else
                            custargs.put(av[0], vv.toString());
                    }
                }
                /* If we have everything, build block */
                bsprslt = bsp.getMatchingStates();
                if ((bsprslt.size() > 0) && (cls != null)) {
                    for (DynmapBlockState bs : bsprslt.keySet()) {
                        if (bs.isNotAir()) {
                            CustomBlockModel cbm = new CustomBlockModel(bs, bsprslt.get(bs), cls, custargs, blockset);
                            if (cbm.render == null) {
                                Log.severe("Custom block model failed to initialize = line " + lineNum + " of " + fname);
                            } else {
                                /* Update maximum texture count */
                                int texturecnt = cbm.getTextureCount();
                                if (texturecnt > max_patches) {
                                    max_patches = texturecnt;
                                }
                            }
                            cnt++;
                        } else {
                            Log.severe("Invalid custommodel block name " + bs + " at line " + lineNum);
                        }
                    }
                } else {
                    Log.severe("Custom block model missing required parameters = line " + lineNum + " of " + fname);
                }
            } else if (typeid.equals("modname")) {
                String[] names = line.split(",");
                boolean found = false;
                for (String n : names) {
                    String[] ntok = n.split("[\\[\\]]");
                    String rng = null;
                    if (ntok.length > 1) {
                        n = ntok[0].trim();
                        rng = ntok[1].trim();
                    }
                    n = n.trim();
                    if (loadedmods.contains(n)) {
                        // Already supplied by mod itself?
                        return;
                    }
                    String modver = core.getServer().getModVersion(n);
                    if ((modver != null) && ((rng == null) || checkVersionRange(modver, rng))) {
                        found = true;
                        Log.info(n + "[" + modver + "] models enabled");
                        modname = n;
                        modversion = modver;
                        // Add to loaded mods
                        loadedmods.add(n);
                        // Prime values from block and item unique IDs
                        core.addModBlockItemIDs(modname, varvals);
                        break;
                    }
                }
                if (!found) {
                    return;
                }
            } else if (typeid.equals("version")) {
                if (!checkVersionRange(mcver, line)) {
                    return;
                }
            } else if (layerbits != 0) {
                /* Layerbits determine Y, rows count from North to South (X=0 to X=N-1), columns Z are West to East (N-1 to 0) */
                for (int i = 0; (i < scale) && (i < line.length()); i++) {
                    if (line.charAt(i) == '*') {
                        /* If an asterix, set flag */
                        for (int y = 0; y < scale; y++) {
                            if ((layerbits & (1 << y)) != 0) {
                                for (HDBlockVolumetricModel mod : modlist) {
                                    mod.setSubblock(rownum, y, scale - i - 1, true);
                                }
                            }
                        }
                    }
                }
                /* See if we're done with layer */
                rownum++;
                if (rownum >= scale) {
                    rownum = 0;
                    layerbits = 0;
                }
            }
        }
        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());
    } catch (NumberFormatException nfx) {
        Log.severe("Format error - line " + rdr.getLineNumber() + " of " + fname + ": " + nfx.getMessage());
    } finally {
        if (rdr != null) {
            try {
                rdr.close();
                rdr = null;
            } catch (IOException e) {
            }
        }
        pdf.setPatchNameMape(null);
    }
}
Also used : HashMap(java.util.HashMap) DynmapBlockState(org.dynmap.renderer.DynmapBlockState) ArrayList(java.util.ArrayList) LineNumberReader(java.io.LineNumberReader) ForgeConfigFile(org.dynmap.utils.ForgeConfigFile) Vector3D(org.dynmap.utils.Vector3D) SideVisible(org.dynmap.renderer.RenderPatchFactory.SideVisible) InputStreamReader(java.io.InputStreamReader) BlockStateParser(org.dynmap.utils.BlockStateParser) BitSet(java.util.BitSet) PatchDefinition(org.dynmap.utils.PatchDefinition) IOException(java.io.IOException) RenderPatch(org.dynmap.renderer.RenderPatch) ForgeConfigFile(org.dynmap.utils.ForgeConfigFile) ZipFile(java.util.zip.ZipFile) File(java.io.File)

Aggregations

File (java.io.File)2 IOException (java.io.IOException)2 InputStreamReader (java.io.InputStreamReader)2 LineNumberReader (java.io.LineNumberReader)2 BitSet (java.util.BitSet)2 HashMap (java.util.HashMap)2 ZipFile (java.util.zip.ZipFile)2 DynmapBlockState (org.dynmap.renderer.DynmapBlockState)2 BlockStateParser (org.dynmap.utils.BlockStateParser)2 ForgeConfigFile (org.dynmap.utils.ForgeConfigFile)2 FileNotFoundException (java.io.FileNotFoundException)1 ArrayList (java.util.ArrayList)1 ZipException (java.util.zip.ZipException)1 BiomeMap (org.dynmap.common.BiomeMap)1 CustomColorMultiplier (org.dynmap.renderer.CustomColorMultiplier)1 RenderPatch (org.dynmap.renderer.RenderPatch)1 SideVisible (org.dynmap.renderer.RenderPatchFactory.SideVisible)1 DynIntHashMap (org.dynmap.utils.DynIntHashMap)1 PatchDefinition (org.dynmap.utils.PatchDefinition)1 Vector3D (org.dynmap.utils.Vector3D)1