diff --git a/src/main/java/ninja/bytecode/iris/Iris.java b/src/main/java/ninja/bytecode/iris/Iris.java index 97c84343e..2bd462f5b 100644 --- a/src/main/java/ninja/bytecode/iris/Iris.java +++ b/src/main/java/ninja/bytecode/iris/Iris.java @@ -27,13 +27,17 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.util.Vector; +import org.zeroturnaround.zip.ZipUtil; import com.google.gson.Gson; import ninja.bytecode.iris.generator.IrisChunkGenerator; import ninja.bytecode.iris.object.IrisBiome; import ninja.bytecode.iris.object.IrisDimension; +import ninja.bytecode.iris.object.IrisGenerator; import ninja.bytecode.iris.object.IrisObject; +import ninja.bytecode.iris.object.IrisObjectPlacement; +import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.util.BiomeResult; import ninja.bytecode.iris.util.BlockDataTools; import ninja.bytecode.iris.util.BoardManager; @@ -51,10 +55,12 @@ import ninja.bytecode.iris.util.ScoreDirection; import ninja.bytecode.iris.wand.WandController; import ninja.bytecode.shuriken.collections.KList; import ninja.bytecode.shuriken.collections.KMap; +import ninja.bytecode.shuriken.collections.KSet; import ninja.bytecode.shuriken.execution.J; import ninja.bytecode.shuriken.format.Form; import ninja.bytecode.shuriken.json.JSONException; import ninja.bytecode.shuriken.json.JSONObject; +import ninja.bytecode.shuriken.logging.L; import ninja.bytecode.shuriken.math.RollingSequence; import ninja.bytecode.shuriken.reaction.O; import ninja.bytecode.shuriken.tools.JarScanner; @@ -587,6 +593,114 @@ public class Iris extends JavaPlugin implements BoardProvider } } + if(args[0].equalsIgnoreCase("package") || args[0].equalsIgnoreCase("pkg")) + { + String dim = "overworld"; + + if(args.length > 1) + { + dim = args[1]; + } + + boolean obfuscate = false; + + for(String i : args) + { + if(i.equalsIgnoreCase("-o")) + { + obfuscate = true; + } + } + + String dimm = dim; + IrisDimension dimension = data.getDimensionLoader().load(dimm); + File folder = new File(getDataFolder(), "exports/" + dimension.getLoadKey()); + folder.mkdirs(); + Iris.info("Packaging Dimension " + dimension.getName()); + KSet regions = new KSet<>(); + KSet biomes = new KSet<>(); + KSet generators = new KSet<>(); + dimension.getRegions().forEach((i) -> regions.add(data.getRegionLoader().load(i))); + regions.forEach((i) -> biomes.addAll(i.getAllBiomes())); + biomes.forEach((i) -> i.getGenerators().forEach((j) -> generators.add(j.getCachedGenerator()))); + KMap renameObjects = new KMap<>(); + + for(IrisBiome i : biomes) + { + for(IrisObjectPlacement j : i.getObjects()) + { + KList newNames = new KList<>(); + + for(String k : j.getPlace()) + { + if(renameObjects.containsKey(k)) + { + newNames.add(renameObjects.get(k)); + continue; + } + + String name = obfuscate ? UUID.randomUUID().toString().replaceAll("-", "") : k; + newNames.add(name); + renameObjects.put(k, name); + } + + if(obfuscate) + { + j.setPlace(newNames); + } + } + } + + KMap> lookupObjects = renameObjects.flip(); + + biomes.forEach((i) -> i.getObjects().forEach((j) -> j.getPlace().forEach((k) -> + { + try + { + Iris.info("- " + k + " (Object)"); + IO.copyFile(Iris.data.getObjectLoader().findFile(lookupObjects.get(k).get(0)), new File(folder, "objects/" + k + ".iob")); + } + + catch(Throwable e) + { + + } + }))); + + try + { + IO.writeAll(new File(folder, "dimensions/" + dimension.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(dimension)).toString(0)); + + for(IrisGenerator i : generators) + { + Iris.info("- " + i.getLoadKey() + " (Generator)"); + IO.writeAll(new File(folder, "generators/" + i.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(i)).toString(0)); + } + + for(IrisRegion i : regions) + { + Iris.info("- " + i.getName() + " (Region)"); + IO.writeAll(new File(folder, "regions/" + i.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(i)).toString(0)); + } + + for(IrisBiome i : biomes) + { + Iris.info("- " + i.getName() + " (Biome)"); + IO.writeAll(new File(folder, "biomes/" + i.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(i)).toString(0)); + } + + ZipUtil.pack(folder, new File(getDataFolder(), "exports/" + dimension.getLoadKey() + ".iris")); + IO.delete(folder); + } + + catch(Throwable e) + { + L.ex(e); + } + + sender.sendMessage("Done!"); + } + if(args[0].equalsIgnoreCase("dev")) { String dim = "overworld"; diff --git a/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java index c4240b51f..89f89206e 100644 --- a/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java @@ -9,14 +9,17 @@ import lombok.Data; import lombok.EqualsAndHashCode; import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.IrisContext; +import ninja.bytecode.iris.object.IrisBiome; import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.util.BiomeResult; +import ninja.bytecode.shuriken.collections.KMap; @Data @EqualsAndHashCode(callSuper = false) public class IrisChunkGenerator extends CeilingChunkGenerator implements IrisContext { private Method initLighting; + private KMap b = new KMap<>(); public IrisChunkGenerator(String dimensionName, int threads) { diff --git a/src/main/java/ninja/bytecode/iris/generator/PostBlockChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/PostBlockChunkGenerator.java index c025ff675..6012c9003 100644 --- a/src/main/java/ninja/bytecode/iris/generator/PostBlockChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/PostBlockChunkGenerator.java @@ -8,6 +8,8 @@ import org.bukkit.block.data.BlockData; import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.layer.post.PostNippleSmoother; import ninja.bytecode.iris.layer.post.PostPotholeFiller; +import ninja.bytecode.iris.layer.post.PostSlabber; +import ninja.bytecode.iris.layer.post.PostWallPatcher; import ninja.bytecode.iris.object.IrisDimension; import ninja.bytecode.iris.util.IPostBlockAccess; import ninja.bytecode.iris.util.IrisPostBlockFilter; @@ -40,12 +42,20 @@ public abstract class PostBlockChunkGenerator extends ParallaxChunkGenerator imp super.onInit(world, rng); filters.add(new PostNippleSmoother(this)); filters.add(new PostPotholeFiller(this)); + filters.add(new PostWallPatcher(this)); + filters.add(new PostSlabber(this)); } @Override protected void onGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid) { super.onGenerate(random, x, z, data, grid); + + if(!getDimension().isPostProcess()) + { + return; + } + currentData = data; currentPostX = x; currentPostZ = z; @@ -64,7 +74,10 @@ public abstract class PostBlockChunkGenerator extends ParallaxChunkGenerator imp { for(IrisPostBlockFilter f : filters) { - f.onPost(rxx, rzz); + int rxxx = rxx; + int rzzx = rzz; + + f.onPost(rxxx, rzzx); } }); } diff --git a/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java index 6bea72950..5061830ab 100644 --- a/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java @@ -17,6 +17,7 @@ import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.object.atomics.AtomicSliver; import ninja.bytecode.iris.util.BiomeMap; import ninja.bytecode.iris.util.BiomeResult; +import ninja.bytecode.iris.util.BlockDataTools; import ninja.bytecode.iris.util.HeightMap; import ninja.bytecode.iris.util.RNG; import ninja.bytecode.shuriken.collections.KList; @@ -132,11 +133,24 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator } } + if(onto.equals(Material.ACACIA_LEAVES) || onto.equals(Material.BIRCH_LEAVES) || onto.equals(Material.DARK_OAK_LEAVES) || onto.equals(Material.JUNGLE_LEAVES) || onto.equals(Material.OAK_LEAVES) || onto.equals(Material.SPRUCE_LEAVES)) + { + if(!mat.isSolid()) + { + return false; + } + } + return true; } private void decorateLand(IrisBiome biome, AtomicSliver sliver, double wx, int k, double wz, int rx, int rz, BlockData block) { + if(!getDimension().isDecorate()) + { + return; + } + int j = 0; for(IrisBiomeDecorator i : biome.getDecorators()) @@ -155,6 +169,14 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator continue; } + if(d.getMaterial().equals(Material.CACTUS)) + { + if(!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND)) + { + sliver.set(k, BlockDataTools.getBlockData("RED_SAND")); + } + } + if(d instanceof Bisected && k < 254) { Bisected t = ((Bisected) d.clone()); @@ -190,6 +212,11 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator private void decorateUnderwater(IrisBiome biome, AtomicSliver sliver, double wx, int y, double wz, int rx, int rz, BlockData block) { + if(!getDimension().isDecorate()) + { + return; + } + int j = 0; for(IrisBiomeDecorator i : biome.getDecorators()) @@ -257,7 +284,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator double wx = getModifiedX(x, z); double wz = getModifiedZ(x, z); IrisRegion region = sampleRegion(x, z); - int height = sampleHeight(x, z); + int height = (int) Math.round(getTerrainHeight(x, z)); double sh = region.getShoreHeight(wx, wz); IrisBiome current = sampleBiome(x, z).getBiome(); diff --git a/src/main/java/ninja/bytecode/iris/layer/GenLayerCave.java b/src/main/java/ninja/bytecode/iris/layer/GenLayerCave.java index fe610fa90..3a34af494 100644 --- a/src/main/java/ninja/bytecode/iris/layer/GenLayerCave.java +++ b/src/main/java/ninja/bytecode/iris/layer/GenLayerCave.java @@ -29,9 +29,9 @@ public class GenLayerCave extends GenLayer { //@builder super(iris, rng); - shuffle = CNG.signature(rng.nextParallelRNG(2348566)); - gincline = new CNG(rng.nextParallelRNG(1112), 1D, 3).scale(0.00452); - gg = new FastNoise(324895 * rng.nextParallelRNG(45678).imax()); + shuffle = CNG.signature(rng.nextParallelRNG(1348566)); + gincline = new CNG(rng.nextParallelRNG(26512), 1D, 3).scale(0.00452); + gg = new FastNoise(324895 * rng.nextParallelRNG(49678).imax()); //@done } diff --git a/src/main/java/ninja/bytecode/iris/layer/post/PostSlabber.java b/src/main/java/ninja/bytecode/iris/layer/post/PostSlabber.java new file mode 100644 index 000000000..07843dc11 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/layer/post/PostSlabber.java @@ -0,0 +1,50 @@ +package ninja.bytecode.iris.layer.post; + +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Waterlogged; + +import ninja.bytecode.iris.generator.PostBlockChunkGenerator; +import ninja.bytecode.iris.util.IrisPostBlockFilter; +import ninja.bytecode.iris.util.RNG; + +public class PostSlabber extends IrisPostBlockFilter +{ + public static final Material AIR = Material.AIR; + public static final Material WATER = Material.WATER; + private RNG rng; + + public PostSlabber(PostBlockChunkGenerator gen) + { + super(gen); + rng = gen.getMasterRandom().nextParallelRNG(1239456); + } + + @Override + public void onPost(int x, int z) + { + int h = highestTerrainBlock(x, z); + + if(highestTerrainBlock(x + 1, z) == h + 1 || highestTerrainBlock(x, z + 1) == h + 1 || highestTerrainBlock(x - 1, z) == h + 1 || highestTerrainBlock(x, z - 1) == h + 1) + { + BlockData d = gen.sampleTrueBiome(x, z).getBiome().getSlab().get(rng, x, h, z); + if(d != null) + { + if(d.getMaterial().equals(AIR)) + { + return; + } + + if(d instanceof Waterlogged) + { + ((Waterlogged) d).setWaterlogged(getPostBlock(x, h + 1, z).getMaterial().equals(Material.WATER)); + } + + if(getPostBlock(x, h + 2, z).getMaterial().equals(AIR) || getPostBlock(x, h + 2, z).getMaterial().equals(WATER)) + { + setPostBlock(x, h + 1, z, d); + } + } + } + } +} diff --git a/src/main/java/ninja/bytecode/iris/layer/post/PostWallPatcher.java b/src/main/java/ninja/bytecode/iris/layer/post/PostWallPatcher.java new file mode 100644 index 000000000..fed25ab91 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/layer/post/PostWallPatcher.java @@ -0,0 +1,56 @@ +package ninja.bytecode.iris.layer.post; + +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; + +import ninja.bytecode.iris.generator.PostBlockChunkGenerator; +import ninja.bytecode.iris.object.IrisBiome; +import ninja.bytecode.iris.util.IrisPostBlockFilter; +import ninja.bytecode.iris.util.RNG; + +public class PostWallPatcher extends IrisPostBlockFilter +{ + public static final Material AIR = Material.AIR; + private RNG rng; + + public PostWallPatcher(PostBlockChunkGenerator gen) + { + super(gen); + rng = gen.getMasterRandom().nextParallelRNG(1239456); + } + + @Override + public void onPost(int x, int z) + { + IrisBiome biome = gen.sampleTrueBiome(x, z).getBiome(); + + if(!biome.getWall().getPalette().isEmpty()) + { + int h = highestTerrainBlock(x, z); + int ha = highestTerrainBlock(x + 1, z); + int hb = highestTerrainBlock(x, z + 1); + int hc = highestTerrainBlock(x - 1, z); + int hd = highestTerrainBlock(x, z - 1); + + if(ha < h - 2 || hb < h - 2 || hc < h - 2 || hd < h - 2) + { + int max = Math.abs(Math.max(h - ha, Math.max(h - hb, Math.max(h - hc, h - hd)))); + + for(int i = h; i > h - max; i--) + { + BlockData d = biome.getWall().get(rng, x + i, i + h, z + i); + + if(d != null) + { + if(d.getMaterial().equals(AIR)) + { + continue; + } + + setPostBlock(x, i, z, d); + } + } + } + } + } +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java index b9a020807..249edb9d0 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java @@ -49,6 +49,12 @@ public class IrisBiome extends IrisRegistrant @Desc("List any biome names (file names without.json) here as children. Portions of this biome can sometimes morph into their children. Iris supports cyclic relationships such as A > B > A > B. Iris will stop checking 9 biomes down the tree.") private KList children = new KList<>(); + @Desc("The default slab if iris decides to place a slab in this biome. Default is no slab.") + private IrisBiomePaletteLayer slab = new IrisBiomePaletteLayer().zero(); + + @Desc("The default wall if iris decides to place a wall higher than 2 blocks (steep hills or possibly cliffs)") + private IrisBiomePaletteLayer wall = new IrisBiomePaletteLayer().zero(); + @Desc("This defines the layers of materials in this biome. Each layer has a palette and min/max height and some other properties. Usually a grassy/sandy layer then a dirt layer then a stone layer. Iris will fill in the remaining blocks below your layers with stone.") private KList layers = new KList().qadd(new IrisBiomePaletteLayer()); diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java b/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java index 6e0a1cacd..a8209a49f 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiomePaletteLayer.java @@ -65,6 +65,11 @@ public class IrisBiomePaletteLayer } } + if(getBlockData().isEmpty()) + { + return null; + } + return getBlockData().get(0); } @@ -109,4 +114,10 @@ public class IrisBiomePaletteLayer return blockData; } + + public IrisBiomePaletteLayer zero() + { + palette.clear(); + return this; + } } diff --git a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java index 6f91e57b4..42eaef0ea 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java @@ -39,6 +39,15 @@ public class IrisDimension extends IrisRegistrant @Desc("Generate caves or not.") private boolean caves = true; + @Desc("Carve terrain or not") + private boolean carving = true; + + @Desc("Generate decorations or not") + private boolean decorate = true; + + @Desc("Use post processing features. Usually for production only as there is a gen speed cost.") + private boolean postProcess = true; + @Desc("The ceiling dimension. Leave blank for normal sky.") private String ceiling = ""; diff --git a/src/main/java/ninja/bytecode/iris/object/IrisRegion.java b/src/main/java/ninja/bytecode/iris/object/IrisRegion.java index cf3e9e6ee..cf93a7333 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisRegion.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisRegion.java @@ -4,10 +4,13 @@ import java.util.concurrent.locks.ReentrantLock; import lombok.Data; import lombok.EqualsAndHashCode; +import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.util.CNG; import ninja.bytecode.iris.util.Desc; import ninja.bytecode.iris.util.RNG; import ninja.bytecode.shuriken.collections.KList; +import ninja.bytecode.shuriken.collections.KMap; +import ninja.bytecode.shuriken.collections.KSet; @Desc("Represents an iris region") @Data @@ -91,4 +94,34 @@ public class IrisRegion extends IrisRegistrant return shoreHeightGenerator.fitDoubleD(shoreHeightMin, shoreHeightMax, x / shoreHeightZoom, z / shoreHeightZoom); } + + public KList getAllBiomes() + { + KMap b = new KMap<>(); + KSet names = new KSet<>(); + names.addAll(landBiomes); + names.addAll(seaBiomes); + names.addAll(shoreBiomes); + spotBiomes.forEach((i) -> names.add(i.getBiome())); + ridgeBiomes.forEach((i) -> names.add(i.getBiome())); + + while(!names.isEmpty()) + { + for(String i : new KList<>(names)) + { + if(b.containsKey(i)) + { + names.remove(i); + continue; + } + + IrisBiome biome = Iris.data.getBiomeLoader().load(i); + b.put(biome.getLoadKey(), biome); + names.remove(i); + names.addAll(biome.getChildren()); + } + } + + return b.v(); + } } diff --git a/src/main/java/ninja/bytecode/iris/object/atomics/AtomicWorldData.java b/src/main/java/ninja/bytecode/iris/object/atomics/AtomicWorldData.java index 89e9197ac..940ce7e25 100644 --- a/src/main/java/ninja/bytecode/iris/object/atomics/AtomicWorldData.java +++ b/src/main/java/ninja/bytecode/iris/object/atomics/AtomicWorldData.java @@ -7,6 +7,7 @@ import java.io.IOException; import org.bukkit.World; +import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.util.ChronoLatch; import ninja.bytecode.iris.util.ChunkPosition; import ninja.bytecode.shuriken.collections.KMap; @@ -18,6 +19,7 @@ public class AtomicWorldData private KMap loadedChunks; private KMap loadedSections; private KMap lastRegion; + private KMap lastChunk; private String prefix; private ChronoLatch cl = new ChronoLatch(15000); @@ -27,6 +29,7 @@ public class AtomicWorldData loadedSections = new KMap<>(); loadedChunks = new KMap<>(); lastRegion = new KMap<>(); + lastChunk = new KMap<>(); this.prefix = prefix; getSubregionFolder().mkdirs(); } @@ -165,7 +168,7 @@ public class AtomicWorldData public AtomicSliverMap loadChunk(int x, int z) throws IOException { ChunkPosition pos = new ChunkPosition(x, z); - + lastChunk.put(pos, M.ms()); if(loadedChunks.containsKey(pos)) { return loadedChunks.get(pos); @@ -262,5 +265,21 @@ public class AtomicWorldData } } } + + for(ChunkPosition i : lastChunk.k()) + { + if(M.ms() - lastChunk.get(i) > 60000) + { + try + { + saveChunk(i); + } + + catch(IOException e) + { + Iris.warn("Failed to save chunk"); + } + } + } } } diff --git a/src/main/java/ninja/bytecode/iris/util/IO.java b/src/main/java/ninja/bytecode/iris/util/IO.java index d2ad16dba..992e329d4 100644 --- a/src/main/java/ninja/bytecode/iris/util/IO.java +++ b/src/main/java/ninja/bytecode/iris/util/IO.java @@ -61,7 +61,7 @@ public class IO * The system line separator string. */ public static final String LINE_SEPARATOR; - + /** * The default buffer size to use. */ @@ -128,7 +128,7 @@ public class IO return new String(hexChars).toUpperCase(); } - + /** * Transfers the length of the buffer amount of data from the input stream to * the output stream @@ -378,6 +378,7 @@ public class IO public static void writeAll(File f, Object c) throws IOException { + f.getParentFile().mkdirs(); PrintWriter pw = new PrintWriter(new FileWriter(f)); pw.println(c.toString()); pw.close(); @@ -567,13 +568,13 @@ public class IO destFile.setLastModified(srcFile.lastModified()); } } - + // ----------------------------------------------------------------------- /** * Unconditionally close an Reader. *

- * Equivalent to {@link Reader#close()}, except any exceptions will be - * ignored. This is typically used in finally blocks. + * Equivalent to {@link Reader#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. * * @param input * the Reader to close, may be null or already closed @@ -586,17 +587,18 @@ public class IO { input.close(); } - } catch(IOException ioe) + } + catch(IOException ioe) { // ignore } } - + /** * Unconditionally close a Writer. *

- * Equivalent to {@link Writer#close()}, except any exceptions will be - * ignored. This is typically used in finally blocks. + * Equivalent to {@link Writer#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. * * @param output * the Writer to close, may be null or already closed @@ -609,12 +611,13 @@ public class IO { output.close(); } - } catch(IOException ioe) + } + catch(IOException ioe) { // ignore } } - + /** * Unconditionally close an InputStream. *

@@ -632,12 +635,13 @@ public class IO { input.close(); } - } catch(IOException ioe) + } + catch(IOException ioe) { // ignore } } - + /** * Unconditionally close an OutputStream. *

@@ -655,12 +659,13 @@ public class IO { output.close(); } - } catch(IOException ioe) + } + catch(IOException ioe) { // ignore } } - + // read toByteArray // ----------------------------------------------------------------------- /** @@ -683,10 +688,10 @@ public class IO copy(input, output); return output.toByteArray(); } - + /** - * Get the contents of a Reader as a byte[] using - * the default character encoding of the platform. + * Get the contents of a Reader as a byte[] using the + * default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * BufferedReader. @@ -705,10 +710,10 @@ public class IO copy(input, output); return output.toByteArray(); } - + /** - * Get the contents of a Reader as a byte[] using - * the specified character encoding. + * Get the contents of a Reader as a byte[] using the + * specified character encoding. *

* Character encoding names can be found at * IANA. @@ -733,10 +738,10 @@ public class IO copy(input, output, encoding); return output.toByteArray(); } - + /** - * Get the contents of a String as a byte[] using - * the default character encoding of the platform. + * Get the contents of a String as a byte[] using the + * default character encoding of the platform. *

* This is the same as {@link String#getBytes()}. * @@ -753,12 +758,12 @@ public class IO { return input.getBytes(); } - + // read char[] // ----------------------------------------------------------------------- /** - * Get the contents of an InputStream as a character array - * using the default character encoding of the platform. + * Get the contents of an InputStream as a character array using + * the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * BufferedInputStream. @@ -778,10 +783,10 @@ public class IO copy(is, output); return output.toCharArray(); } - + /** - * Get the contents of an InputStream as a character array - * using the specified character encoding. + * Get the contents of an InputStream as a character array using + * the specified character encoding. *

* Character encoding names can be found at * IANA. @@ -806,7 +811,7 @@ public class IO copy(is, output, encoding); return output.toCharArray(); } - + /** * Get the contents of a Reader as a character array. *

@@ -828,12 +833,12 @@ public class IO copy(input, sw); return sw.toCharArray(); } - + // read toString // ----------------------------------------------------------------------- /** - * Get the contents of an InputStream as a String using the - * default character encoding of the platform. + * Get the contents of an InputStream as a String using the default + * character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * BufferedInputStream. @@ -852,7 +857,7 @@ public class IO copy(input, sw); return sw.toString(); } - + /** * Get the contents of an InputStream as a String using the * specified character encoding. @@ -879,7 +884,7 @@ public class IO copy(input, sw, encoding); return sw.toString(); } - + /** * Get the contents of a Reader as a String. *

@@ -900,7 +905,7 @@ public class IO copy(input, sw); return sw.toString(); } - + /** * Get the contents of a byte[] as a String using the default * character encoding of the platform. @@ -918,7 +923,7 @@ public class IO { return new String(input); } - + /** * Get the contents of a byte[] as a String using the specified * character encoding. @@ -942,12 +947,13 @@ public class IO if(encoding == null) { return new String(input); - } else + } + else { return new String(input, encoding); } } - + // readLines // ----------------------------------------------------------------------- /** @@ -971,7 +977,7 @@ public class IO InputStreamReader reader = new InputStreamReader(input); return readLines(reader); } - + /** * Get the contents of an InputStream as a list of Strings, one * entry per line, using the specified character encoding. @@ -998,16 +1004,17 @@ public class IO if(encoding == null) { return readLines(input); - } else + } + else { InputStreamReader reader = new InputStreamReader(input, encoding); return readLines(reader); } } - + /** - * Get the contents of a Reader as a list of Strings, one entry - * per line. + * Get the contents of a Reader as a list of Strings, one entry per + * line. *

* This method buffers the input internally, so there is no need to use a * BufferedReader. @@ -1033,11 +1040,11 @@ public class IO } return list; } - + // ----------------------------------------------------------------------- /** - * Convert the specified string to an input stream, encoded as bytes using - * the default character encoding of the platform. + * Convert the specified string to an input stream, encoded as bytes using the + * default character encoding of the platform. * * @param input * the string to convert @@ -1049,10 +1056,10 @@ public class IO byte[] bytes = input.getBytes(); return new ByteArrayInputStream(bytes); } - + /** - * Convert the specified string to an input stream, encoded as bytes using - * the specified character encoding. + * Convert the specified string to an input stream, encoded as bytes using the + * specified character encoding. *

* Character encoding names can be found at * IANA. @@ -1071,15 +1078,14 @@ public class IO byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes(); return new ByteArrayInputStream(bytes); } - + // write byte[] // ----------------------------------------------------------------------- /** * Writes bytes from a byte[] to an OutputStream. * * @param data - * the byte array to write, do not modify during output, null - * ignored + * the byte array to write, do not modify during output, null ignored * @param output * the OutputStream to write to * @throws NullPointerException @@ -1095,7 +1101,7 @@ public class IO output.write(data); } } - + /** * Writes bytes from a byte[] to chars on a Writer * using the default character encoding of the platform. @@ -1103,8 +1109,7 @@ public class IO * This method uses {@link String#String(byte[])}. * * @param data - * the byte array to write, do not modify during output, null - * ignored + * the byte array to write, do not modify during output, null ignored * @param output * the Writer to write to * @throws NullPointerException @@ -1120,7 +1125,7 @@ public class IO output.write(new String(data)); } } - + /** * Writes bytes from a byte[] to chars on a Writer * using the specified character encoding. @@ -1131,8 +1136,7 @@ public class IO * This method uses {@link String#String(byte[], String)}. * * @param data - * the byte array to write, do not modify during output, null - * ignored + * the byte array to write, do not modify during output, null ignored * @param output * the Writer to write to * @param encoding @@ -1150,22 +1154,22 @@ public class IO if(encoding == null) { write(data, output); - } else + } + else { output.write(new String(data, encoding)); } } } - + // write char[] // ----------------------------------------------------------------------- /** - * Writes chars from a char[] to a Writer using - * the default character encoding of the platform. + * Writes chars from a char[] to a Writer using the + * default character encoding of the platform. * * @param data - * the char array to write, do not modify during output, null - * ignored + * the char array to write, do not modify during output, null ignored * @param output * the Writer to write to * @throws NullPointerException @@ -1181,17 +1185,15 @@ public class IO output.write(data); } } - + /** * Writes chars from a char[] to bytes on an * OutputStream. *

- * This method uses {@link String#String(char[])} and - * {@link String#getBytes()}. + * This method uses {@link String#String(char[])} and {@link String#getBytes()}. * * @param data - * the char array to write, do not modify during output, null - * ignored + * the char array to write, do not modify during output, null ignored * @param output * the OutputStream to write to * @throws NullPointerException @@ -1207,7 +1209,7 @@ public class IO output.write(new String(data).getBytes()); } } - + /** * Writes chars from a char[] to bytes on an * OutputStream using the specified character encoding. @@ -1219,8 +1221,7 @@ public class IO * {@link String#getBytes(String)}. * * @param data - * the char array to write, do not modify during output, null - * ignored + * the char array to write, do not modify during output, null ignored * @param output * the OutputStream to write to * @param encoding @@ -1238,13 +1239,14 @@ public class IO if(encoding == null) { write(data, output); - } else + } + else { output.write(new String(data).getBytes(encoding)); } } } - + // write String // ----------------------------------------------------------------------- /** @@ -1267,7 +1269,7 @@ public class IO output.write(data); } } - + /** * Writes chars from a String to bytes on an * OutputStream using the default character encoding of the @@ -1292,7 +1294,7 @@ public class IO output.write(data.getBytes()); } } - + /** * Writes chars from a String to bytes on an * OutputStream using the specified character encoding. @@ -1321,13 +1323,14 @@ public class IO if(encoding == null) { write(data, output); - } else + } + else { output.write(data.getBytes(encoding)); } } } - + // write StringBuffer // ----------------------------------------------------------------------- /** @@ -1350,7 +1353,7 @@ public class IO output.write(data.toString()); } } - + /** * Writes chars from a StringBuffer to bytes on an * OutputStream using the default character encoding of the @@ -1375,7 +1378,7 @@ public class IO output.write(data.toString().getBytes()); } } - + /** * Writes chars from a StringBuffer to bytes on an * OutputStream using the specified character encoding. @@ -1404,27 +1407,27 @@ public class IO if(encoding == null) { write(data, output); - } else + } + else { output.write(data.toString().getBytes(encoding)); } } } - + // writeLines // ----------------------------------------------------------------------- /** - * Writes the toString() value of each item in a collection to - * an OutputStream line by line, using the default character - * encoding of the platform and the specified line ending. + * Writes the toString() value of each item in a collection to an + * OutputStream line by line, using the default character encoding + * of the platform and the specified line ending. * * @param lines * the lines to write, null entries produce blank lines * @param lineEnding * the line separator to use, null is system default * @param output - * the OutputStream to write to, not null, not - * closed + * the OutputStream to write to, not null, not closed * @throws NullPointerException * if the output is null * @throws IOException @@ -1451,10 +1454,10 @@ public class IO output.write(lineEnding.getBytes()); } } - + /** - * Writes the toString() value of each item in a collection to - * an OutputStream line by line, using the specified character + * Writes the toString() value of each item in a collection to an + * OutputStream line by line, using the specified character * encoding and the specified line ending. *

* Character encoding names can be found at @@ -1465,8 +1468,7 @@ public class IO * @param lineEnding * the line separator to use, null is system default * @param output - * the OutputStream to write to, not null, not - * closed + * the OutputStream to write to, not null, not closed * @param encoding * the encoding to use, null means platform default * @throws NullPointerException @@ -1480,7 +1482,8 @@ public class IO if(encoding == null) { writeLines(lines, lineEnding, output); - } else + } + else { if(lines == null) { @@ -1501,10 +1504,10 @@ public class IO } } } - + /** - * Writes the toString() value of each item in a collection to - * a Writer line by line, using the specified line ending. + * Writes the toString() value of each item in a collection to a + * Writer line by line, using the specified line ending. * * @param lines * the lines to write, null entries produce blank lines @@ -1538,19 +1541,18 @@ public class IO writer.write(lineEnding); } } - + // copy from InputStream // ----------------------------------------------------------------------- /** - * Copy bytes from an InputStream to an - * OutputStream. + * Copy bytes from an InputStream to an OutputStream. *

* This method buffers the input internally, so there is no need to use a * BufferedInputStream. *

- * Large streams (over 2GB) will return a bytes copied value of - * -1 after the copy has completed since the correct number of - * bytes cannot be returned as an int. For large streams use the + * Large streams (over 2GB) will return a bytes copied value of -1 + * after the copy has completed since the correct number of bytes cannot be + * returned as an int. For large streams use the * copyLarge(InputStream, OutputStream) method. * * @param input @@ -1575,7 +1577,7 @@ public class IO } return (int) count; } - + /** * Copy bytes from a large (over 2GB) InputStream to an * OutputStream. @@ -1606,10 +1608,10 @@ public class IO } return count; } - + /** - * Copy bytes from an InputStream to chars on a - * Writer using the default character encoding of the platform. + * Copy bytes from an InputStream to chars on a Writer + * using the default character encoding of the platform. *

* This method buffers the input internally, so there is no need to use a * BufferedInputStream. @@ -1631,10 +1633,10 @@ public class IO InputStreamReader in = new InputStreamReader(input); copy(in, output); } - + /** - * Copy bytes from an InputStream to chars on a - * Writer using the specified character encoding. + * Copy bytes from an InputStream to chars on a Writer + * using the specified character encoding. *

* This method buffers the input internally, so there is no need to use a * BufferedInputStream. @@ -1661,13 +1663,14 @@ public class IO if(encoding == null) { copy(input, output); - } else + } + else { InputStreamReader in = new InputStreamReader(input, encoding); copy(in, output); } } - + // copy from Reader // ----------------------------------------------------------------------- /** @@ -1676,9 +1679,9 @@ public class IO * This method buffers the input internally, so there is no need to use a * BufferedReader. *

- * Large streams (over 2GB) will return a chars copied value of - * -1 after the copy has completed since the correct number of - * chars cannot be returned as an int. For large streams use the + * Large streams (over 2GB) will return a chars copied value of -1 + * after the copy has completed since the correct number of chars cannot be + * returned as an int. For large streams use the * copyLarge(Reader, Writer) method. * * @param input @@ -1703,7 +1706,7 @@ public class IO } return (int) count; } - + /** * Copy chars from a large (over 2GB) Reader to a * Writer. @@ -1734,7 +1737,7 @@ public class IO } return count; } - + /** * Copy chars from a Reader to bytes on an * OutputStream using the default character encoding of the @@ -1765,11 +1768,11 @@ public class IO // have to flush here. out.flush(); } - + /** * Copy chars from a Reader to bytes on an - * OutputStream using the specified character encoding, and - * calling flush. + * OutputStream using the specified character encoding, and calling + * flush. *

* This method buffers the input internally, so there is no need to use a * BufferedReader. @@ -1799,7 +1802,8 @@ public class IO if(encoding == null) { copy(input, output); - } else + } + else { OutputStreamWriter out = new OutputStreamWriter(output, encoding); copy(input, out); @@ -1807,12 +1811,11 @@ public class IO out.flush(); } } - + // content equals // ----------------------------------------------------------------------- /** - * Compare the contents of two Streams to determine if they are equal or - * not. + * Compare the contents of two Streams to determine if they are equal or not. *

* This method buffers the input internally using * BufferedInputStream if they are not already buffered. @@ -1838,7 +1841,7 @@ public class IO { input2 = new BufferedInputStream(input2); } - + int ch = input1.read(); while(-1 != ch) { @@ -1849,17 +1852,16 @@ public class IO } ch = input1.read(); } - + int ch2 = input2.read(); return (ch2 == -1); } - + /** - * Compare the contents of two Readers to determine if they are equal or - * not. + * Compare the contents of two Readers to determine if they are equal or not. *

- * This method buffers the input internally using - * BufferedReader if they are not already buffered. + * This method buffers the input internally using BufferedReader if + * they are not already buffered. * * @param input1 * the first reader @@ -1883,7 +1885,7 @@ public class IO { input2 = new BufferedReader(input2); } - + int ch = input1.read(); while(-1 != ch) { @@ -1894,11 +1896,11 @@ public class IO } ch = input1.read(); } - + int ch2 = input2.read(); return (ch2 == -1); } - + static { // avoid security issues diff --git a/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java b/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java index 6860dcf12..9296f727e 100644 --- a/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java +++ b/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java @@ -149,6 +149,33 @@ public class ObjectResourceLoader extends ResourceLoader } } + public File findFile(String name) + { + lock.lock(); + for(File i : getFolders(name)) + { + for(File j : i.listFiles()) + { + if(j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) + { + return j; + } + } + + File file = new File(i, name + ".iob"); + + if(file.exists()) + { + return file; + } + } + + Iris.warn("Couldn't find " + resourceTypeName + ": " + name); + + lock.unlock(); + return null; + } + public IrisObject load(String name) { String key = name + "-" + objectClass.getCanonicalName();