mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +00:00
Parallax Object Generation
This commit is contained in:
parent
fd561cd45d
commit
a4b571ccbc
@ -9,7 +9,7 @@ public class Settings
|
||||
|
||||
public static class PerformanceSettings
|
||||
{
|
||||
public PerformanceMode performanceMode = PerformanceMode.UNLIMITED;
|
||||
public PerformanceMode performanceMode = PerformanceMode.HALF_CPU;
|
||||
public boolean fastDecoration = true;
|
||||
public int threadPriority = Thread.MAX_PRIORITY;
|
||||
public int threadCount = 4;
|
||||
@ -17,6 +17,7 @@ public class Settings
|
||||
public int decorationAccuracy = 2;
|
||||
public boolean interpolation = true;
|
||||
public boolean surfaceNoise = true;
|
||||
public boolean noObjectFail = false;
|
||||
public boolean verbose = false;
|
||||
public int placeHistoryLimit = 8192;
|
||||
}
|
||||
@ -37,7 +38,7 @@ public class Settings
|
||||
public double heightScale = 0.56;
|
||||
public double baseHeight = 0.065;
|
||||
public int seaLevel = 63;
|
||||
public double caveDensity = 4;
|
||||
public double caveDensity = 5;
|
||||
public double caveScale = 1.45;
|
||||
public double biomeScale = 0.65;
|
||||
public boolean flatBedrock = true;
|
||||
|
@ -8,9 +8,9 @@ import ninja.bytecode.shuriken.collections.GMap;
|
||||
import ninja.bytecode.shuriken.execution.TaskExecutor;
|
||||
|
||||
public class ExecutionController implements IrisController
|
||||
{
|
||||
{
|
||||
GMap<String, TaskExecutor> executors;
|
||||
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
@ -20,16 +20,19 @@ public class ExecutionController implements IrisController
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
|
||||
for(TaskExecutor i : executors.v())
|
||||
{
|
||||
i.close();
|
||||
}
|
||||
}
|
||||
|
||||
public TaskExecutor getExecutor(World world)
|
||||
|
||||
public TaskExecutor getExecutor(World world, String f)
|
||||
{
|
||||
TaskExecutor x = new TaskExecutor(getTC(), Iris.settings.performance.threadPriority, "Iris Generator (" + world.getName() + ")");
|
||||
executors.put(world.getWorldFolder().getAbsolutePath() + " (" + world + ")", x);
|
||||
TaskExecutor x = new TaskExecutor(getTC(), Iris.settings.performance.threadPriority, "Iris " + f);
|
||||
executors.put(world.getWorldFolder().getAbsolutePath() + " (" + world + ") " + f, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
private int getTC()
|
||||
{
|
||||
switch(Iris.settings.performance.performanceMode)
|
||||
|
@ -142,6 +142,7 @@ public class PackController implements IrisController
|
||||
for(String i : compiledDimensions.k())
|
||||
{
|
||||
CompiledDimension d = compiledDimensions.get(i);
|
||||
d.computeObjectSize();
|
||||
L.i(ChatColor.GREEN + i + ChatColor.WHITE + " (" + d.getEnvironment().toString().toLowerCase() + ")");
|
||||
L.i(ChatColor.DARK_GREEN + " Biomes: " + ChatColor.GRAY + F.f(d.getBiomes().size()));
|
||||
L.i(ChatColor.DARK_GREEN + " Objects: " + ChatColor.GRAY + F.f(d.countObjects()));
|
||||
|
@ -1,13 +1,11 @@
|
||||
package ninja.bytecode.iris.generator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import mortar.util.text.C;
|
||||
@ -30,14 +28,15 @@ import ninja.bytecode.iris.util.AtomicChunkData;
|
||||
import ninja.bytecode.iris.util.ChunkPlan;
|
||||
import ninja.bytecode.iris.util.IrisInterpolation;
|
||||
import ninja.bytecode.iris.util.MB;
|
||||
import ninja.bytecode.iris.util.ParallelChunkGenerator;
|
||||
import ninja.bytecode.iris.util.ParallaxWorldGenerator;
|
||||
import ninja.bytecode.iris.util.SChunkVector;
|
||||
import ninja.bytecode.shuriken.collections.GList;
|
||||
import ninja.bytecode.shuriken.logging.L;
|
||||
import ninja.bytecode.shuriken.math.CNG;
|
||||
import ninja.bytecode.shuriken.math.M;
|
||||
import ninja.bytecode.shuriken.math.RNG;
|
||||
|
||||
public class IrisGenerator extends ParallelChunkGenerator
|
||||
public class IrisGenerator extends ParallaxWorldGenerator
|
||||
{
|
||||
//@builder
|
||||
public static final GList<MB> ROCK = new GList<MB>().add(new MB[] {
|
||||
@ -75,7 +74,6 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
private GenLayerCliffs glCliffs;
|
||||
private RNG rTerrain;
|
||||
private CompiledDimension dim;
|
||||
private World world;
|
||||
|
||||
public IrisGenerator()
|
||||
{
|
||||
@ -113,7 +111,6 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
}
|
||||
|
||||
//@builder
|
||||
this.world = world;
|
||||
rTerrain = new RNG(world.getSeed());
|
||||
glLNoise = new GenLayerLayeredNoise(this, world, random, rTerrain.nextParallelRNG(2));
|
||||
glBiome = new GenLayerBiome(this, world, random, rTerrain.nextParallelRNG(4), dim.getBiomes());
|
||||
@ -124,6 +121,7 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
glCliffs = new GenLayerCliffs(this, world, random, rTerrain.nextParallelRNG(9));
|
||||
scatterCache = new double[16][][];
|
||||
scatter = new CNG(rTerrain.nextParallelRNG(52), 1, 1).scale(10);
|
||||
god = new GenObjectDecorator(this);
|
||||
//@done
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
@ -242,11 +240,25 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome genColumn(int wxxf, int wzxf, int x, int z, ChunkPlan plan)
|
||||
public void onGenParallax(int x, int z, Random random)
|
||||
{
|
||||
try
|
||||
{
|
||||
god.decorateParallax(x, z, random);
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome onGenColumn(int wxxf, int wzxf, int x, int z, ChunkPlan plan, AtomicChunkData data)
|
||||
{
|
||||
if(disposed)
|
||||
{
|
||||
setBlock(x, 0, z, Material.MAGENTA_GLAZED_TERRACOTTA);
|
||||
data.setBlock(x, 0, z, Material.MAGENTA_GLAZED_TERRACOTTA);
|
||||
return Biome.VOID;
|
||||
}
|
||||
|
||||
@ -296,7 +308,7 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
for(int j = 0; j < snowHeight; j++)
|
||||
{
|
||||
highest = j == snowHeight - 1 ? highest < j ? j : highest : highest < j + 1 ? j + 1 : highest;
|
||||
setBlock(x, i + j + 1, z, j == snowHeight - 1 ? Material.SNOW : Material.SNOW_BLOCK, j == snowHeight - 1 ? (byte) layers : (byte) 0);
|
||||
data.setBlock(x, i + j + 1, z, j == snowHeight - 1 ? Material.SNOW : Material.SNOW_BLOCK, j == snowHeight - 1 ? (byte) layers : (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,24 +319,24 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
if(!mbx.material.equals(Material.AIR))
|
||||
{
|
||||
highest = i > highest ? i : highest;
|
||||
setBlock(x, i + 1, z, mbx.material, mbx.data);
|
||||
data.setBlock(x, i + 1, z, mbx.material, mbx.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
highest = i > highest ? i : highest;
|
||||
setBlock(x, i, z, mb.material, mb.data);
|
||||
data.setBlock(x, i, z, mb.material, mb.data);
|
||||
}
|
||||
|
||||
glCaves.genCaves(wxx, wzx, x, z, height, this);
|
||||
glCarving.genCarves(wxx, wzx, x, z, height, this, biome);
|
||||
glCaverns.genCaverns(wxx, wzx, x, z, height, this, biome);
|
||||
glCaves.genCaves(wxx, wzx, x, z, height, this, data);
|
||||
glCarving.genCarves(wxx, wzx, x, z, height, this, biome, data);
|
||||
glCaverns.genCaverns(wxx, wzx, x, z, height, this, biome, data);
|
||||
int hw = 0;
|
||||
int hl = 0;
|
||||
|
||||
for(int i = highest; i > 0; i--)
|
||||
{
|
||||
Material t = getType(x, i, z);
|
||||
Material t = data.getType(x, i, z);
|
||||
hw = i > seaLevel && hw == 0 && (t.equals(Material.WATER) || t.equals(Material.STATIONARY_WATER)) ? i : hw;
|
||||
hl = hl == 0 && !t.equals(Material.AIR) ? i : hl;
|
||||
}
|
||||
@ -336,31 +348,12 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
return biome.getRealBiome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decorateColumn(int wx, int wz, int x, int z, ChunkPlan plan)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPopulator> getDefaultPopulators(World world)
|
||||
{
|
||||
GList<BlockPopulator> p = new GList<>();
|
||||
|
||||
if(Iris.settings.gen.genObjects)
|
||||
{
|
||||
p.add(god = new GenObjectDecorator(this));
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private double getBiomedHeight(int x, int z, ChunkPlan plan)
|
||||
{
|
||||
double xh = plan.getHeight(x, z);
|
||||
@ -377,11 +370,6 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
return xh;
|
||||
}
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
public RNG getRTerrain()
|
||||
{
|
||||
return rTerrain;
|
||||
@ -398,7 +386,7 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
{
|
||||
return;
|
||||
}
|
||||
L.w(C.YELLOW + "Disposed Iris World " + C.RED + world.getName());
|
||||
L.w(C.YELLOW + "Disposed Iris World " + C.RED + getWorld().getName());
|
||||
disposed = true;
|
||||
dim = null;
|
||||
glLNoise = null;
|
||||
@ -407,6 +395,7 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
glCaverns = null;
|
||||
glSnow = null;
|
||||
glCliffs = null;
|
||||
god.dispose();
|
||||
}
|
||||
|
||||
public boolean isDisposed()
|
||||
@ -439,4 +428,16 @@ public class IrisGenerator extends ParallelChunkGenerator
|
||||
{
|
||||
return god.randomObject(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SChunkVector getParallaxSize()
|
||||
{
|
||||
return dim.getMaxChunkSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUnload()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
}
|
@ -98,7 +98,7 @@ public class GenObject
|
||||
}
|
||||
|
||||
mountHeight = avg(avy);
|
||||
mount = new BlockVector(avg(avx), 0, avg(avz));
|
||||
mount = new BlockVector(0, 0, 0);
|
||||
}
|
||||
|
||||
private int avg(double[] v)
|
||||
@ -255,7 +255,7 @@ public class GenObject
|
||||
|
||||
public Location place(int wx, int wy, int wz, IPlacer placer)
|
||||
{
|
||||
Location start = new Location(placer.getWorld(), wx, wy, wz).clone().add(sh(w), sh(h) + 1, sh(d));
|
||||
Location start = new Location(placer.getWorld(), wx, wy, wz).clone().add(0, sh(h) + 1, 0);
|
||||
|
||||
if(mount == null)
|
||||
{
|
||||
@ -279,21 +279,25 @@ public class GenObject
|
||||
MB b = getSchematic().get(i);
|
||||
Location f = start.clone().add(i.toBlockVector());
|
||||
|
||||
Material m = placer.get(f.clone().subtract(0, 1, 0)).material;
|
||||
if(i.getY() == mountHeight && (m.equals(Material.WATER) || m.equals(Material.STATIONARY_WATER) || m.equals(Material.LAVA) || m.equals(Material.STATIONARY_LAVA)))
|
||||
if(!Iris.settings.performance.noObjectFail)
|
||||
{
|
||||
for(Location j : undo.k())
|
||||
{
|
||||
placer.set(j, undo.get(j));
|
||||
}
|
||||
Material m = placer.get(f.clone().subtract(0, 1, 0)).material;
|
||||
|
||||
if(Iris.settings.performance.verbose)
|
||||
if(i.getY() == mountHeight && (m.equals(Material.WATER) || m.equals(Material.STATIONARY_WATER) || m.equals(Material.LAVA) || m.equals(Material.STATIONARY_LAVA)))
|
||||
{
|
||||
L.w(C.WHITE + "Object " + C.YELLOW + getName() + C.WHITE + " failed to place in " + C.YELLOW + m.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(f.getBlockX()) + " " + F.f(f.getBlockY()) + " " + F.f(f.getBlockZ()));
|
||||
}
|
||||
for(Location j : undo.k())
|
||||
{
|
||||
placer.set(j, undo.get(j));
|
||||
}
|
||||
|
||||
failures++;
|
||||
return null;
|
||||
if(Iris.settings.performance.verbose)
|
||||
{
|
||||
L.w(C.WHITE + "Object " + C.YELLOW + getName() + C.WHITE + " failed to place in " + C.YELLOW + m.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(f.getBlockX()) + " " + F.f(f.getBlockY()) + " " + F.f(f.getBlockZ()));
|
||||
}
|
||||
|
||||
failures++;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -2,41 +2,34 @@ package ninja.bytecode.iris.generator.genobject;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
|
||||
import mortar.logic.format.F;
|
||||
import mortar.util.text.C;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||
import ninja.bytecode.iris.generator.placer.BukkitPlacer;
|
||||
import ninja.bytecode.iris.generator.placer.NMSPlacer;
|
||||
import ninja.bytecode.iris.generator.placer.AtomicParallaxPlacer;
|
||||
import ninja.bytecode.iris.pack.IrisBiome;
|
||||
import ninja.bytecode.iris.util.IPlacer;
|
||||
import ninja.bytecode.iris.util.MB;
|
||||
import ninja.bytecode.iris.util.ParallaxCache;
|
||||
import ninja.bytecode.iris.util.SMCAVector;
|
||||
import ninja.bytecode.shuriken.collections.GList;
|
||||
import ninja.bytecode.shuriken.collections.GMap;
|
||||
import ninja.bytecode.shuriken.collections.GSet;
|
||||
import ninja.bytecode.shuriken.execution.ChronoLatch;
|
||||
import ninja.bytecode.shuriken.logging.L;
|
||||
import ninja.bytecode.shuriken.math.M;
|
||||
import ninja.bytecode.shuriken.math.RNG;
|
||||
|
||||
public class GenObjectDecorator extends BlockPopulator
|
||||
public class GenObjectDecorator
|
||||
{
|
||||
private GList<PlacedObject> placeHistory;
|
||||
private GMap<IrisBiome, GList<GenObjectGroup>> orderCache;
|
||||
private GMap<IrisBiome, GMap<GenObjectGroup, Double>> populationCache;
|
||||
private IPlacer placer;
|
||||
private Executor ex;
|
||||
private IrisGenerator g;
|
||||
private ChronoLatch cl = new ChronoLatch(250);
|
||||
|
||||
@ -46,7 +39,6 @@ public class GenObjectDecorator extends BlockPopulator
|
||||
placeHistory = new GList<>();
|
||||
populationCache = new GMap<>();
|
||||
orderCache = new GMap<>();
|
||||
ex = Executors.newSingleThreadExecutor();
|
||||
|
||||
for(IrisBiome i : generator.getDimension().getBiomes())
|
||||
{
|
||||
@ -100,25 +92,24 @@ public class GenObjectDecorator extends BlockPopulator
|
||||
L.i("Population Cache is " + populationCache.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(World world, Random rnotusingyou, Chunk source)
|
||||
public void decorateParallax(int cx, int cz, Random random)
|
||||
{
|
||||
if(g.isDisposed())
|
||||
try
|
||||
{
|
||||
placeHistory.clear();
|
||||
return;
|
||||
}
|
||||
if(g.isDisposed())
|
||||
{
|
||||
placeHistory.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
ex.execute(() ->
|
||||
{
|
||||
Random random = new Random(((source.getX() - 32) * (source.getZ() + 54)) + world.getSeed());
|
||||
ParallaxCache cache = new ParallaxCache(g);
|
||||
GSet<IrisBiome> hits = new GSet<>();
|
||||
|
||||
for(int i = 0; i < Iris.settings.performance.decorationAccuracy; i++)
|
||||
{
|
||||
int x = (source.getX() << 4) + random.nextInt(16);
|
||||
int z = (source.getZ() << 4) + random.nextInt(16);
|
||||
IrisBiome biome = g.getBiome((int) g.getOffsetX(x), (int) g.getOffsetX(z));
|
||||
int x = (cx << 4) + random.nextInt(16);
|
||||
int z = (cz << 4) + random.nextInt(16);
|
||||
IrisBiome biome = cache.getBiome(x, z);
|
||||
|
||||
if(hits.contains(biome))
|
||||
{
|
||||
@ -133,20 +124,19 @@ public class GenObjectDecorator extends BlockPopulator
|
||||
}
|
||||
|
||||
hits.add(biome);
|
||||
|
||||
populate(world, random, source, biome, orderCache.get(biome));
|
||||
populate(cx, cz, random, biome, cache);
|
||||
}
|
||||
}
|
||||
|
||||
if(Iris.settings.performance.verbose)
|
||||
{
|
||||
L.flush();
|
||||
}
|
||||
});
|
||||
catch(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void populate(World world, Random random, Chunk source, IrisBiome biome, GList<GenObjectGroup> order)
|
||||
private void populate(int cx, int cz, Random random, IrisBiome biome, ParallaxCache cache)
|
||||
{
|
||||
for(GenObjectGroup i : order)
|
||||
for(GenObjectGroup i : orderCache.get(biome))
|
||||
{
|
||||
if(biome.getSchematicGroups().get(i.getName()) == null)
|
||||
{
|
||||
@ -158,60 +148,65 @@ public class GenObjectDecorator extends BlockPopulator
|
||||
{
|
||||
if(M.r(Iris.settings.gen.objectDensity))
|
||||
{
|
||||
int x = (source.getX() << 4) + random.nextInt(16);
|
||||
int z = (source.getZ() << 4) + random.nextInt(16);
|
||||
Block b = world.getHighestBlockAt(x, z).getRelative(BlockFace.DOWN);
|
||||
Material t = b.getType();
|
||||
GenObject go = i.getSchematics().get(random.nextInt(i.getSchematics().size()));
|
||||
int x = (cx << 4) + random.nextInt(16);
|
||||
int z = (cz << 4) + random.nextInt(16);
|
||||
|
||||
if(!t.isSolid() || !biome.isSurface(t))
|
||||
if(i.getWorldChance() >= 0D)
|
||||
{
|
||||
if(Iris.settings.performance.verbose)
|
||||
{
|
||||
L.w(C.WHITE + "Object " + C.YELLOW + i.getName() + "/*" + C.WHITE + " failed to place in " + C.YELLOW + t.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(b.getX()) + " " + F.f(b.getY()) + " " + F.f(b.getZ()));
|
||||
}
|
||||
int rngx = (int) Math.floor(x / (double) (i.getWorldRadius() == 0 ? 32 : i.getWorldRadius()));
|
||||
int rngz = (int) Math.floor(z / (double) (i.getWorldRadius() == 0 ? 32 : i.getWorldRadius()));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(placer == null)
|
||||
{
|
||||
if(Iris.settings.performance.fastDecoration)
|
||||
{
|
||||
placer = new NMSPlacer(world);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
placer = new BukkitPlacer(world, false);
|
||||
}
|
||||
}
|
||||
|
||||
GenObject g = i.getSchematics().get(random.nextInt(i.getSchematics().size()));
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () ->
|
||||
{
|
||||
Location start = g.place(x, b.getY(), z, placer);
|
||||
|
||||
if(start != null)
|
||||
if(new RNG(new SMCAVector(rngx, rngz).hashCode()).nextDouble() < i.getWorldChance())
|
||||
{
|
||||
if(Iris.settings.performance.verbose)
|
||||
{
|
||||
L.v(C.GRAY + "Placed " + C.DARK_GREEN + i.getName() + C.WHITE + "/" + C.DARK_GREEN + g.getName() + C.GRAY + " at " + C.DARK_GREEN + F.f(start.getBlockX()) + " " + F.f(start.getBlockY()) + " " + F.f(start.getBlockZ()));
|
||||
L.w(C.WHITE + "Object " + C.YELLOW + i.getName() + "/*" + C.WHITE + " failed to place due to a world chance.");
|
||||
}
|
||||
|
||||
if(Iris.settings.performance.debugMode)
|
||||
{
|
||||
placeHistory.add(new PlacedObject(start.getBlockX(), start.getBlockY(), start.getBlockZ(), i.getName() + ":" + g.getName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(placeHistory.size() > Iris.settings.performance.placeHistoryLimit)
|
||||
int by = cache.getHeight(x, z);
|
||||
MB mb = cache.get(x, by, z);
|
||||
|
||||
if(!Iris.settings.performance.noObjectFail)
|
||||
{
|
||||
if(!mb.material.isSolid() || !biome.isSurface(mb.material))
|
||||
{
|
||||
if(Iris.settings.performance.verbose)
|
||||
{
|
||||
L.w(C.WHITE + "Object " + C.YELLOW + i.getName() + "/*" + C.WHITE + " failed to place in " + C.YELLOW + mb.material.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(x) + " " + F.f(by) + " " + F.f(z));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
placer = new AtomicParallaxPlacer(g, cache);
|
||||
Location start = go.place(x, by, z, placer);
|
||||
|
||||
if(start != null)
|
||||
{
|
||||
if(Iris.settings.performance.verbose)
|
||||
{
|
||||
L.v(C.GRAY + "Placed " + C.DARK_GREEN + i.getName() + C.WHITE + "/" + C.DARK_GREEN + go.getName() + C.GRAY + " at " + C.DARK_GREEN + F.f(start.getBlockX()) + " " + F.f(start.getBlockY()) + " " + F.f(start.getBlockZ()));
|
||||
}
|
||||
|
||||
if(Iris.settings.performance.debugMode)
|
||||
{
|
||||
placeHistory.add(new PlacedObject(start.getBlockX(), start.getBlockY(), start.getBlockZ(), i.getName() + ":" + go.getName()));
|
||||
|
||||
if(placeHistory.size() > Iris.settings.performance.placeHistoryLimit)
|
||||
{
|
||||
while(placeHistory.size() > Iris.settings.performance.placeHistoryLimit)
|
||||
{
|
||||
while(placeHistory.size() > Iris.settings.performance.placeHistoryLimit)
|
||||
{
|
||||
placeHistory.remove(0);
|
||||
}
|
||||
placeHistory.remove(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -249,6 +244,11 @@ public class GenObjectDecorator extends BlockPopulator
|
||||
return placeHistory;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public PlacedObject randomObject(String string)
|
||||
{
|
||||
GList<PlacedObject> v = new GList<>();
|
||||
|
@ -21,6 +21,8 @@ public class GenObjectGroup
|
||||
private GList<String> flags;
|
||||
private String name;
|
||||
private int priority;
|
||||
private double worldChance;
|
||||
private int worldRad;
|
||||
|
||||
public GenObjectGroup(String name)
|
||||
{
|
||||
@ -28,6 +30,8 @@ public class GenObjectGroup
|
||||
this.flags = new GList<>();
|
||||
this.name = name;
|
||||
priority = Integer.MIN_VALUE;
|
||||
worldChance = Integer.MIN_VALUE;
|
||||
worldRad = 32;
|
||||
}
|
||||
|
||||
public void read(DataInputStream din) throws IOException
|
||||
@ -295,4 +299,36 @@ public class GenObjectGroup
|
||||
return true;
|
||||
}
|
||||
|
||||
public double getWorldChance()
|
||||
{
|
||||
if(worldChance == Integer.MIN_VALUE)
|
||||
{
|
||||
for(String i : flags)
|
||||
{
|
||||
if(i.startsWith("world chance "))
|
||||
{
|
||||
worldChance = Double.valueOf(i.split("\\Q \\E")[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return worldChance;
|
||||
}
|
||||
|
||||
public double getWorldRadius()
|
||||
{
|
||||
if(worldRad == Integer.MIN_VALUE)
|
||||
{
|
||||
for(String i : flags)
|
||||
{
|
||||
if(i.startsWith("world radius "))
|
||||
{
|
||||
worldRad = Integer.valueOf(i.split("\\Q \\E")[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return worldRad;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import org.bukkit.World;
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||
import ninja.bytecode.iris.pack.IrisBiome;
|
||||
import ninja.bytecode.iris.util.AtomicChunkData;
|
||||
import ninja.bytecode.iris.util.GenLayer;
|
||||
import ninja.bytecode.iris.util.IrisInterpolation;
|
||||
import ninja.bytecode.iris.util.MB;
|
||||
@ -68,7 +69,7 @@ public class GenLayerCarving extends GenLayer
|
||||
return carver.noise(x + fx, y - fy, z + fz);
|
||||
}
|
||||
|
||||
public void genCarves(double wxx, double wzx, int x, int z, int s, IrisGenerator g, IrisBiome biome)
|
||||
public void genCarves(double wxx, double wzx, int x, int z, int s, IrisGenerator g, IrisBiome biome, AtomicChunkData data)
|
||||
{
|
||||
if(!Iris.settings.gen.genCarving)
|
||||
{
|
||||
@ -103,7 +104,7 @@ public class GenLayerCarving extends GenLayer
|
||||
if(carve(wxx, i, wzx) < IrisInterpolation.lerpBezier(0, ch, hill))
|
||||
{
|
||||
carved++;
|
||||
g.setBlock(x, i, z, Material.AIR);
|
||||
data.setBlock(x, i, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +114,7 @@ public class GenLayerCarving extends GenLayer
|
||||
|
||||
for(int i = Iris.settings.gen.maxCarvingHeight; i > Iris.settings.gen.minCarvingHeight; i--)
|
||||
{
|
||||
Material m = g.getType(x, i, z);
|
||||
Material m = data.getType(x, i, z);
|
||||
if(!m.equals(Material.AIR))
|
||||
{
|
||||
hit++;
|
||||
@ -126,7 +127,7 @@ public class GenLayerCarving extends GenLayer
|
||||
{
|
||||
for(int j = i; j > i - 5; j--)
|
||||
{
|
||||
if(g.getType(x, j, z).equals(Material.AIR))
|
||||
if(data.getType(x, j, z).equals(Material.AIR))
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
@ -137,12 +138,12 @@ public class GenLayerCarving extends GenLayer
|
||||
if(!fail)
|
||||
{
|
||||
MB mb = biome.getSurface(wxx, wzx, g.getRTerrain());
|
||||
g.setBlock(x, i, z, mb.material, mb.data);
|
||||
data.setBlock(x, i, z, mb.material, mb.data);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g.setBlock(x, i, z, Material.AIR);
|
||||
data.setBlock(x, i, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,12 +152,12 @@ public class GenLayerCarving extends GenLayer
|
||||
if(!fail)
|
||||
{
|
||||
MB mb = biome.getSubSurface(wxx, i, wzx, g.getRTerrain());
|
||||
g.setBlock(x, i, z, mb.material, mb.data);
|
||||
data.setBlock(x, i, z, mb.material, mb.data);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g.setBlock(x, i, z, Material.AIR);
|
||||
data.setBlock(x, i, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import org.bukkit.World;
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||
import ninja.bytecode.iris.pack.IrisBiome;
|
||||
import ninja.bytecode.iris.util.AtomicChunkData;
|
||||
import ninja.bytecode.iris.util.GenLayer;
|
||||
import ninja.bytecode.iris.util.IrisInterpolation;
|
||||
import ninja.bytecode.iris.util.MB;
|
||||
@ -68,7 +69,7 @@ public class GenLayerCaverns extends GenLayer
|
||||
return carver.noise(x + fx, y - fy, z + fz);
|
||||
}
|
||||
|
||||
public void genCaverns(double wxx, double wzx, int x, int z, int s, IrisGenerator g, IrisBiome biome)
|
||||
public void genCaverns(double wxx, double wzx, int x, int z, int s, IrisGenerator g, IrisBiome biome, AtomicChunkData data)
|
||||
{
|
||||
if(!Iris.settings.gen.genCaverns)
|
||||
{
|
||||
@ -103,7 +104,7 @@ public class GenLayerCaverns extends GenLayer
|
||||
if(cavern(wxx, i, wzx) < IrisInterpolation.lerpBezier(0, ch, hill))
|
||||
{
|
||||
carved++;
|
||||
g.setBlock(x, i, z, Material.AIR);
|
||||
data.setBlock(x, i, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +114,7 @@ public class GenLayerCaverns extends GenLayer
|
||||
|
||||
for(int i = Iris.settings.gen.maxCavernHeight; i > Iris.settings.gen.minCavernHeight; i--)
|
||||
{
|
||||
Material m = g.getType(x, i, z);
|
||||
Material m = data.getType(x, i, z);
|
||||
if(!m.equals(Material.AIR))
|
||||
{
|
||||
hit++;
|
||||
@ -126,7 +127,7 @@ public class GenLayerCaverns extends GenLayer
|
||||
{
|
||||
for(int j = i; j > i - 5; j--)
|
||||
{
|
||||
if(g.getType(x, j, z).equals(Material.AIR))
|
||||
if(data.getType(x, j, z).equals(Material.AIR))
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
@ -137,12 +138,12 @@ public class GenLayerCaverns extends GenLayer
|
||||
if(!fail)
|
||||
{
|
||||
MB mb = biome.getSurface(wxx, wzx, g.getRTerrain());
|
||||
g.setBlock(x, i, z, mb.material, mb.data);
|
||||
data.setBlock(x, i, z, mb.material, mb.data);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g.setBlock(x, i, z, Material.AIR);
|
||||
data.setBlock(x, i, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,12 +152,12 @@ public class GenLayerCaverns extends GenLayer
|
||||
if(!fail)
|
||||
{
|
||||
MB mb = biome.getSubSurface(wxx, i, wzx, g.getRTerrain());
|
||||
g.setBlock(x, i, z, mb.material, mb.data);
|
||||
data.setBlock(x, i, z, mb.material, mb.data);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g.setBlock(x, i, z, Material.AIR);
|
||||
data.setBlock(x, i, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import org.bukkit.World;
|
||||
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||
import ninja.bytecode.iris.util.AtomicChunkData;
|
||||
import ninja.bytecode.iris.util.GenLayer;
|
||||
import ninja.bytecode.iris.util.PolygonGenerator;
|
||||
import ninja.bytecode.shuriken.math.CNG;
|
||||
@ -18,7 +19,7 @@ public class GenLayerCaves extends GenLayer
|
||||
private CNG caveGirth;
|
||||
private CNG caveClamp;
|
||||
private PolygonGenerator caveVeins;
|
||||
|
||||
|
||||
public GenLayerCaves(IrisGenerator iris, World world, Random random, RNG rng)
|
||||
{
|
||||
super(iris, world, random, rng);
|
||||
@ -27,47 +28,47 @@ public class GenLayerCaves extends GenLayer
|
||||
caveClamp = new CNG(rng.nextParallelRNG(-10000), 1D, 3).scale(0.1422);
|
||||
caveVeins = new PolygonGenerator(rng.nextParallelRNG(-99999), 4, 0.002 * Iris.settings.gen.caveScale, 1, (g) -> g.fractureWith(new CNG(rng.nextParallelRNG(-5555), 1D, 4).scale(0.02), 70));
|
||||
}
|
||||
|
||||
public void genCaves(double wxx, double wzx, int x, int z, int s, IrisGenerator g)
|
||||
|
||||
public void genCaves(double wxx, double wzx, int x, int z, int s, IrisGenerator g, AtomicChunkData data)
|
||||
{
|
||||
if(!Iris.settings.gen.genCaves)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for(double itr = 0; itr < 0.1 * Iris.settings.gen.caveDensity; itr += 0.1)
|
||||
{
|
||||
double thickness = 0.25 + itr + (0.5 * caveClamp.noise(wxx, wzx));
|
||||
double size = 3.88D * thickness;
|
||||
double size = (3.88D * thickness);
|
||||
double variance = 8.34D * thickness;
|
||||
double w = size + (variance * caveGirth.noise(wxx, wzx));
|
||||
double h = size + (variance * caveGirth.noise(wzx, wxx));
|
||||
double width = 0;
|
||||
double height = h;
|
||||
double elevation = (caveHeight.noise(wxx + (19949D * itr), wzx - (19949D * itr)) * (350)) - 80;
|
||||
|
||||
while(width <= w && height > 1D)
|
||||
{
|
||||
width+=2;
|
||||
height-=2;
|
||||
width += 2;
|
||||
height -= 2;
|
||||
|
||||
if(caveVeins.hasBorder(3, width, wxx - (19949D * itr), wzx + (19949D * itr)))
|
||||
{
|
||||
double r = (((caveGirth.noise(wxx, wzx, width)) * variance) + height) / 2D;
|
||||
int f = 3;
|
||||
for(int i = (int) -r; i < r && f >= 0; i++)
|
||||
for(int i = (int) -r; i < r; i++)
|
||||
{
|
||||
if(i + height > s)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Material t = g.getType(x, (int) (elevation + i) - 55, z);
|
||||
|
||||
Material t = data.getType(x, (int) (elevation + i) - 55, z);
|
||||
if(t.equals(Material.BEDROCK) || t.equals(Material.WATER) || t.equals(Material.STATIONARY_WATER))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
g.setBlock(x, (int) (elevation + i) - 55, z, Material.AIR);
|
||||
|
||||
data.setBlock(x, (int) (elevation + i) - 55, z, Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package ninja.bytecode.iris.generator.placer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||
import ninja.bytecode.iris.util.IrisWorldData;
|
||||
import ninja.bytecode.iris.util.MB;
|
||||
import ninja.bytecode.iris.util.ParallaxCache;
|
||||
import ninja.bytecode.iris.util.Placer;
|
||||
|
||||
public class AtomicParallaxPlacer extends Placer
|
||||
{
|
||||
private IrisWorldData data;
|
||||
private ParallaxCache cache;
|
||||
|
||||
public AtomicParallaxPlacer(IrisGenerator g, ParallaxCache cache)
|
||||
{
|
||||
super(g.getWorld());
|
||||
this.data = g.getWorldData();
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MB get(Location l)
|
||||
{
|
||||
return cache.get(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void set(Location l, MB mb)
|
||||
{
|
||||
data.setBlock(l.getBlockX(), l.getBlockY(), l.getBlockZ(), mb.material.getId(), mb.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestY(Location l)
|
||||
{
|
||||
return cache.getHeight(l.getBlockX(), l.getBlockZ());
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package ninja.bytecode.iris.generator.placer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import ninja.bytecode.iris.util.AtomicChunkData;
|
||||
import ninja.bytecode.iris.util.ChunkPlan;
|
||||
import ninja.bytecode.iris.util.MB;
|
||||
import ninja.bytecode.iris.util.Placer;
|
||||
|
||||
public class AtomicPlacer extends Placer
|
||||
{
|
||||
private AtomicChunkData data;
|
||||
private ChunkPlan plan;
|
||||
|
||||
public AtomicPlacer(World world)
|
||||
{
|
||||
super(world);
|
||||
}
|
||||
|
||||
public void bind(AtomicChunkData data, ChunkPlan plan)
|
||||
{
|
||||
this.data = data;
|
||||
this.plan = plan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MB get(Location l)
|
||||
{
|
||||
return MB.of(data.getType(l.getBlockX(), l.getBlockY(), l.getBlockZ()), data.getData(l.getBlockX(), l.getBlockY(), l.getBlockZ()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void set(Location l, MB mb)
|
||||
{
|
||||
data.setBlock(l.getBlockX(), l.getBlockY(), l.getBlockZ(), mb.material.getId(), mb.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestY(Location l)
|
||||
{
|
||||
return plan.getRealHeight(l.getBlockX(), l.getBlockZ());
|
||||
}
|
||||
}
|
@ -13,7 +13,10 @@ import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import ninja.bytecode.iris.generator.genobject.GenObject;
|
||||
import ninja.bytecode.iris.generator.genobject.GenObjectGroup;
|
||||
import ninja.bytecode.iris.util.SChunkVector;
|
||||
import ninja.bytecode.iris.util.SBlockVector;
|
||||
import ninja.bytecode.shuriken.collections.GList;
|
||||
import ninja.bytecode.shuriken.collections.GMap;
|
||||
import ninja.bytecode.shuriken.io.CustomOutputStream;
|
||||
@ -29,6 +32,8 @@ public class CompiledDimension
|
||||
private GList<IrisBiome> biomes;
|
||||
private GMap<String, IrisBiome> biomeCache;
|
||||
private GMap<String, GenObjectGroup> objects;
|
||||
private SBlockVector maxSize;
|
||||
private SChunkVector maxChunkSize;
|
||||
|
||||
public CompiledDimension(IrisDimension dimension)
|
||||
{
|
||||
@ -36,6 +41,8 @@ public class CompiledDimension
|
||||
biomes = new GList<>();
|
||||
biomeCache = new GMap<>();
|
||||
objects = new GMap<>();
|
||||
maxSize = new SBlockVector(0, 0, 0);
|
||||
maxChunkSize = new SChunkVector(0, 0);
|
||||
}
|
||||
|
||||
public void read(InputStream in) throws IOException
|
||||
@ -182,4 +189,56 @@ public class CompiledDimension
|
||||
|
||||
objects.clear();
|
||||
}
|
||||
|
||||
public void computeObjectSize()
|
||||
{
|
||||
int maxWidth = 0;
|
||||
int maxHeight = 0;
|
||||
int maxDepth = 0;
|
||||
|
||||
for(GenObjectGroup i : objects.values())
|
||||
{
|
||||
for(GenObject j : i.getSchematics().copy())
|
||||
{
|
||||
maxWidth = j.getW() > maxWidth ? j.getW() : maxWidth;
|
||||
maxHeight = j.getH() > maxHeight ? j.getH() : maxHeight;
|
||||
maxDepth = j.getD() > maxDepth ? j.getD() : maxDepth;
|
||||
}
|
||||
}
|
||||
|
||||
maxSize = new SBlockVector(maxWidth, maxHeight, maxDepth);
|
||||
maxChunkSize = new SChunkVector(Math.ceil((double) (maxWidth) / 16D), Math.ceil((double) (maxDepth) / 16D));
|
||||
L.i("Max Object Bound is " + maxWidth + ", " + maxHeight + ", " + maxDepth);
|
||||
L.i("Max Object Region is " + maxChunkSize.getX() + " by " + maxChunkSize.getZ() + " Chunks");
|
||||
}
|
||||
|
||||
public static IrisBiome getTheVoid()
|
||||
{
|
||||
return theVoid;
|
||||
}
|
||||
|
||||
public IrisDimension getDimension()
|
||||
{
|
||||
return dimension;
|
||||
}
|
||||
|
||||
public GMap<String, IrisBiome> getBiomeCache()
|
||||
{
|
||||
return biomeCache;
|
||||
}
|
||||
|
||||
public GMap<String, GenObjectGroup> getObjects()
|
||||
{
|
||||
return objects;
|
||||
}
|
||||
|
||||
public SBlockVector getMaxSize()
|
||||
{
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
public SChunkVector getMaxChunkSize()
|
||||
{
|
||||
return maxChunkSize;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ -10,6 +15,8 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
import mortar.compute.math.M;
|
||||
|
||||
public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
{
|
||||
private static final Field t;
|
||||
@ -35,11 +42,125 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
private char[] s15;
|
||||
private char[][] m;
|
||||
private World w;
|
||||
private long lastUse;
|
||||
private int bits;
|
||||
|
||||
public AtomicChunkData(World world)
|
||||
{
|
||||
this.maxHeight = world.getMaxHeight();
|
||||
this.w = world;
|
||||
bits = 0;
|
||||
lastUse = M.ms();
|
||||
}
|
||||
|
||||
public long getTimeSinceLastUse()
|
||||
{
|
||||
return M.ms() - lastUse;
|
||||
}
|
||||
|
||||
public void read(InputStream in) throws IOException
|
||||
{
|
||||
read(in, true);
|
||||
}
|
||||
|
||||
public void read(InputStream in, boolean ignoreAir) throws IOException
|
||||
{
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
int bits = din.readInt();
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
int bit = getBit(i);
|
||||
if((bits & bit) == bit)
|
||||
{
|
||||
char[] section = getChunkSection(i << 4, true);
|
||||
|
||||
for(int j = 0; j < section.length; j++)
|
||||
{
|
||||
char c = din.readChar();
|
||||
|
||||
if(c == 0 && ignoreAir)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
section[j] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
din.close();
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException
|
||||
{
|
||||
DataOutputStream dos = new DataOutputStream(out);
|
||||
dos.writeInt(getDataBits());
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
if(hasDataBit(i))
|
||||
{
|
||||
char[] section = getChunkSection(i << 4, false);
|
||||
for(int j = 0; j < section.length; j++)
|
||||
{
|
||||
dos.writeChar(section[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dos.close();
|
||||
}
|
||||
|
||||
public boolean hasDataBit(int section)
|
||||
{
|
||||
int b = getBit(section);
|
||||
return (bits & b) == b;
|
||||
}
|
||||
|
||||
public void clearDataBits()
|
||||
{
|
||||
bits = 0;
|
||||
}
|
||||
|
||||
public void addDataBit(int section)
|
||||
{
|
||||
bits |= getBit(section);
|
||||
}
|
||||
|
||||
public void removeDataBit(int section)
|
||||
{
|
||||
bits ^= getBit(section);
|
||||
}
|
||||
|
||||
public int getDataBits()
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
|
||||
public int getBit(int index)
|
||||
{
|
||||
return (int) (index < 0 ? -1 : Math.pow(2, index));
|
||||
}
|
||||
|
||||
public int computeDataBits()
|
||||
{
|
||||
int bits = 0;
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
bits |= sections[i].get(this) != null ? getBit(i) : 0;
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,6 +201,7 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
@Override
|
||||
public Material getType(int x, int y, int z)
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return Material.getMaterial(getTypeId(x, y, z));
|
||||
}
|
||||
|
||||
@ -87,18 +209,27 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
@Override
|
||||
public MaterialData getTypeAndData(int x, int y, int z)
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return getType(x, y, z).getNewData(getData(x, y, z));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setBlock(int x, int y, int z, Material blockId, byte data)
|
||||
{
|
||||
setBlock(x, y, z, blockId.getId(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, int blockId)
|
||||
{
|
||||
lastUse = M.ms();
|
||||
setRegion(xMin, yMin, zMin, xMax, yMax, zMax, blockId, (byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, int blockId, int data)
|
||||
{
|
||||
lastUse = M.ms();
|
||||
throw new UnsupportedOperationException("AtomicChunkData does not support setting regions");
|
||||
}
|
||||
|
||||
@ -114,6 +245,31 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
setBlock(x, y, z, (char) (blockId << 4 | data));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public MB getMB(int x, int y, int z)
|
||||
{
|
||||
if(x != (x & 0xf) || y < 0 || y >= maxHeight || z != (z & 0xf))
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return MB.of(Material.AIR);
|
||||
}
|
||||
|
||||
char[] section = getChunkSection(y, false);
|
||||
|
||||
if(section == null)
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return MB.of(Material.AIR);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lastUse = M.ms();
|
||||
char xf = section[(y & 0xf) << 8 | z << 4 | x];
|
||||
return MB.of(Material.getMaterial(xf >> 4), xf & 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTypeId(int x, int y, int z)
|
||||
{
|
||||
@ -131,6 +287,7 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
|
||||
else
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return section[(y & 0xf) << 8 | z << 4 | x] >> 4;
|
||||
}
|
||||
}
|
||||
@ -140,6 +297,7 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
{
|
||||
if(x != (x & 0xf) || y < 0 || y >= maxHeight || z != (z & 0xf))
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return (byte) 0;
|
||||
}
|
||||
|
||||
@ -147,11 +305,13 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
|
||||
if(section == null)
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return (byte) 0;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lastUse = M.ms();
|
||||
return (byte) (section[(y & 0xf) << 8 | z << 4 | x] & 0xf);
|
||||
}
|
||||
}
|
||||
@ -163,6 +323,7 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
return;
|
||||
}
|
||||
|
||||
lastUse = M.ms();
|
||||
ReentrantLock l = locks[y >> 4];
|
||||
l.lock();
|
||||
getChunkSection(y, true)[(y & 0xf) << 8 | z << 4 | x] = type;
|
||||
@ -181,6 +342,7 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
{
|
||||
sf.set(this, new char[h]);
|
||||
section = (char[]) sf.get(this);
|
||||
addDataBit(s);
|
||||
}
|
||||
|
||||
return section;
|
||||
@ -263,4 +425,26 @@ public final class AtomicChunkData implements ChunkGenerator.ChunkData
|
||||
|
||||
t = x;
|
||||
}
|
||||
|
||||
public void inject(AtomicChunkData data)
|
||||
{
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
if(hasDataBit(i))
|
||||
{
|
||||
char[] fromSection = getChunkSection(i << 4, false);
|
||||
char[] toSection = data.getChunkSection(i << 4, true);
|
||||
|
||||
for(int j = 0; j < fromSection.length; j++)
|
||||
{
|
||||
char x = fromSection[j];
|
||||
|
||||
if(x != 0)
|
||||
{
|
||||
toSection[j] = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
src/main/java/ninja/bytecode/iris/util/AtomicMCAData.java
Normal file
80
src/main/java/ninja/bytecode/iris/util/AtomicMCAData.java
Normal file
@ -0,0 +1,80 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.jnbt.ByteArrayTag;
|
||||
import org.jnbt.CompoundTag;
|
||||
import org.jnbt.NBTInputStream;
|
||||
import org.jnbt.NBTOutputStream;
|
||||
import org.jnbt.Tag;
|
||||
|
||||
import ninja.bytecode.shuriken.collections.GMap;
|
||||
|
||||
public class AtomicMCAData
|
||||
{
|
||||
private final World world;
|
||||
private GMap<String, Tag> tag;
|
||||
|
||||
public AtomicMCAData(World world)
|
||||
{
|
||||
this.world = world;
|
||||
tag = new GMap<>();
|
||||
}
|
||||
|
||||
public void read(InputStream in) throws IOException
|
||||
{
|
||||
NBTInputStream nin = new NBTInputStream(in);
|
||||
tag = new GMap<>();
|
||||
tag.putAll(((CompoundTag) nin.readTag()).getValue());
|
||||
nin.close();
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException
|
||||
{
|
||||
NBTOutputStream nos = new NBTOutputStream(out);
|
||||
nos.writeTag(new CompoundTag("imca", tag));
|
||||
nos.close();
|
||||
}
|
||||
|
||||
public boolean contains(int rx, int rz)
|
||||
{
|
||||
return tag.containsKey(rx + "." + rz);
|
||||
}
|
||||
|
||||
public void delete(int rx, int rz)
|
||||
{
|
||||
tag.remove(rx + "." + rz);
|
||||
}
|
||||
|
||||
public void set(int rx, int rz, AtomicChunkData data) throws IOException
|
||||
{
|
||||
ByteArrayOutputStream boas = new ByteArrayOutputStream();
|
||||
data.write(boas);
|
||||
tag.put(rx + "." + rz, new ByteArrayTag(rx + "." + rz, boas.toByteArray()));
|
||||
}
|
||||
|
||||
public AtomicChunkData get(int rx, int rz) throws IOException
|
||||
{
|
||||
if(!contains(rx, rz))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AtomicChunkData data = new AtomicChunkData(world);
|
||||
ByteArrayTag btag = (ByteArrayTag) tag.get(rx + "." + rz);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(btag.getValue());
|
||||
data.read(in);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
}
|
157
src/main/java/ninja/bytecode/iris/util/AtomicWorldData.java
Normal file
157
src/main/java/ninja/bytecode/iris/util/AtomicWorldData.java
Normal file
@ -0,0 +1,157 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
import ninja.bytecode.shuriken.collections.GList;
|
||||
import ninja.bytecode.shuriken.collections.GMap;
|
||||
|
||||
public class AtomicWorldData
|
||||
{
|
||||
private World world;
|
||||
private GMap<SMCAVector, AtomicMCAData> loadedSections;
|
||||
|
||||
public AtomicWorldData(World world)
|
||||
{
|
||||
this.world = world;
|
||||
loadedSections = new GMap<>();
|
||||
getSubregionFolder().mkdirs();
|
||||
}
|
||||
|
||||
public GList<SMCAVector> getLoadedRegions()
|
||||
{
|
||||
return loadedSections.k();
|
||||
}
|
||||
|
||||
public AtomicMCAData getSubregion(int x, int z) throws IOException
|
||||
{
|
||||
if(!isSectionLoaded(x, z))
|
||||
{
|
||||
loadedSections.put(new SMCAVector(x, z), loadSection(x, z));
|
||||
}
|
||||
|
||||
AtomicMCAData f = loadedSections.get(new SMCAVector(x, z));
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public void saveAll() throws IOException
|
||||
{
|
||||
for(SMCAVector i : loadedSections.keySet())
|
||||
{
|
||||
saveSection(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadAll(boolean save) throws IOException
|
||||
{
|
||||
for(SMCAVector i : loadedSections.keySet())
|
||||
{
|
||||
unloadSection(i, save);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteSection(int x, int z) throws IOException
|
||||
{
|
||||
unloadSection(x, z, false);
|
||||
getSubregionFile(x, z).delete();
|
||||
}
|
||||
|
||||
public boolean isSectionLoaded(int x, int z)
|
||||
{
|
||||
return isSectionLoaded(new SMCAVector(x, z));
|
||||
}
|
||||
|
||||
public boolean isSectionLoaded(SMCAVector s)
|
||||
{
|
||||
return loadedSections.containsKey(s);
|
||||
}
|
||||
|
||||
public boolean unloadSection(int x, int z, boolean save) throws IOException
|
||||
{
|
||||
return unloadSection(new SMCAVector(x, z), save);
|
||||
}
|
||||
|
||||
public boolean unloadSection(SMCAVector s, boolean save) throws IOException
|
||||
{
|
||||
if(!isSectionLoaded(s))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(save)
|
||||
{
|
||||
saveSection(s);
|
||||
}
|
||||
|
||||
loadedSections.remove(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean saveSection(int x, int z) throws IOException
|
||||
{
|
||||
return saveSection(new SMCAVector(x, z));
|
||||
}
|
||||
|
||||
public boolean saveSection(SMCAVector s) throws IOException
|
||||
{
|
||||
if(!isSectionLoaded(s.getX(), s.getZ()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AtomicMCAData data = loadedSections.get(s);
|
||||
FileOutputStream fos = new FileOutputStream(getSubregionFile(s.getX(), s.getZ()));
|
||||
data.write(fos);
|
||||
fos.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
public AtomicMCAData loadSection(int x, int z) throws IOException
|
||||
{
|
||||
if(isSectionLoaded(x, z))
|
||||
{
|
||||
return loadedSections.get(new SMCAVector(x, z));
|
||||
}
|
||||
|
||||
File file = getSubregionFile(x, z);
|
||||
|
||||
if(!file.exists())
|
||||
{
|
||||
return createSection(x, z);
|
||||
}
|
||||
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
AtomicMCAData data = new AtomicMCAData(world);
|
||||
data.read(fin);
|
||||
fin.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
public AtomicMCAData createSection(int x, int z)
|
||||
{
|
||||
if(isSectionLoaded(x, z))
|
||||
{
|
||||
return loadedSections.get(new SMCAVector(x, z));
|
||||
}
|
||||
|
||||
AtomicMCAData data = new AtomicMCAData(world);
|
||||
loadedSections.put(new SMCAVector(x, z), data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public File getSubregionFile(int x, int z)
|
||||
{
|
||||
return new File(getSubregionFolder(), "sr." + x + "." + z + ".smca");
|
||||
}
|
||||
|
||||
public File getSubregionFolder()
|
||||
{
|
||||
return new File(world.getWorldFolder(), "subregion");
|
||||
}
|
||||
}
|
@ -5,10 +5,10 @@ import ninja.bytecode.shuriken.collections.GMap;
|
||||
|
||||
public class ChunkPlan
|
||||
{
|
||||
private final GMap<ChunkedVector, Integer> realHeightCache;
|
||||
private final GMap<ChunkedVector, Integer> realWaterHeightCache;
|
||||
private final GMap<ChunkedVector, Double> heightCache;
|
||||
private final GMap<ChunkedVector, IrisBiome> biomeCache;
|
||||
private final GMap<SChunkVector, Integer> realHeightCache;
|
||||
private final GMap<SChunkVector, Integer> realWaterHeightCache;
|
||||
private final GMap<SChunkVector, Double> heightCache;
|
||||
private final GMap<SChunkVector, IrisBiome> biomeCache;
|
||||
|
||||
public ChunkPlan()
|
||||
{
|
||||
@ -20,17 +20,17 @@ public class ChunkPlan
|
||||
|
||||
public IrisBiome getBiome(int x, int z)
|
||||
{
|
||||
return biomeCache.get(new ChunkedVector(x, z));
|
||||
return biomeCache.get(new SChunkVector(x, z));
|
||||
}
|
||||
|
||||
public void setBiome(int x, int z, IrisBiome cng)
|
||||
{
|
||||
biomeCache.put(new ChunkedVector(x, z), cng);
|
||||
biomeCache.put(new SChunkVector(x, z), cng);
|
||||
}
|
||||
|
||||
public double getHeight(int x, int z)
|
||||
{
|
||||
ChunkedVector c = new ChunkedVector(x, z);
|
||||
SChunkVector c = new SChunkVector(x, z);
|
||||
if(hasHeight(c))
|
||||
{
|
||||
return heightCache.get(c);
|
||||
@ -41,7 +41,7 @@ public class ChunkPlan
|
||||
|
||||
public int getRealHeight(int x, int z)
|
||||
{
|
||||
ChunkedVector c = new ChunkedVector(x, z);
|
||||
SChunkVector c = new SChunkVector(x, z);
|
||||
if(realHeightCache.containsKey(c))
|
||||
{
|
||||
return realHeightCache.get(c);
|
||||
@ -52,7 +52,7 @@ public class ChunkPlan
|
||||
|
||||
public int getRealWaterHeight(int x, int z)
|
||||
{
|
||||
ChunkedVector c = new ChunkedVector(x, z);
|
||||
SChunkVector c = new SChunkVector(x, z);
|
||||
|
||||
if(realWaterHeightCache.containsKey(c))
|
||||
{
|
||||
@ -62,43 +62,43 @@ public class ChunkPlan
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean hasHeight(ChunkedVector c)
|
||||
public boolean hasHeight(SChunkVector c)
|
||||
{
|
||||
return heightCache.containsKey(c);
|
||||
}
|
||||
|
||||
public boolean hasHeight(int x, int z)
|
||||
{
|
||||
return hasHeight(new ChunkedVector(x, z));
|
||||
return hasHeight(new SChunkVector(x, z));
|
||||
}
|
||||
|
||||
public void setHeight(ChunkedVector c, double h)
|
||||
public void setHeight(SChunkVector c, double h)
|
||||
{
|
||||
heightCache.put(c, h);
|
||||
}
|
||||
|
||||
public void setRealHeight(ChunkedVector c, int h)
|
||||
public void setRealHeight(SChunkVector c, int h)
|
||||
{
|
||||
realHeightCache.put(c, h);
|
||||
}
|
||||
|
||||
public void setRealHeight(int x, int z, int h)
|
||||
{
|
||||
setRealHeight(new ChunkedVector(x, z), h);
|
||||
setRealHeight(new SChunkVector(x, z), h);
|
||||
}
|
||||
|
||||
public void setRealWaterHeight(ChunkedVector c, int h)
|
||||
public void setRealWaterHeight(SChunkVector c, int h)
|
||||
{
|
||||
realWaterHeightCache.put(c, h);
|
||||
}
|
||||
|
||||
public void setRealWaterHeight(int x, int z, int h)
|
||||
{
|
||||
setRealWaterHeight(new ChunkedVector(x, z), h);
|
||||
setRealWaterHeight(new SChunkVector(x, z), h);
|
||||
}
|
||||
|
||||
public void setHeight(int x, int z, double h)
|
||||
{
|
||||
setHeight(new ChunkedVector(x, z), h);
|
||||
setHeight(new SChunkVector(x, z), h);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import org.bukkit.util.Vector;
|
||||
import mortar.api.nms.NMP;
|
||||
import mortar.api.world.MaterialBlock;
|
||||
import mortar.compute.math.M;
|
||||
import mortar.util.text.C;
|
||||
|
||||
public class GlowingBlock
|
||||
{
|
||||
|
253
src/main/java/ninja/bytecode/iris/util/IrisWorldData.java
Normal file
253
src/main/java/ninja/bytecode/iris/util/IrisWorldData.java
Normal file
@ -0,0 +1,253 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import mortar.logic.format.F;
|
||||
import mortar.util.text.C;
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.shuriken.collections.GList;
|
||||
import ninja.bytecode.shuriken.collections.GMap;
|
||||
import ninja.bytecode.shuriken.execution.ChronoLatch;
|
||||
import ninja.bytecode.shuriken.logging.L;
|
||||
|
||||
public class IrisWorldData
|
||||
{
|
||||
private final World world;
|
||||
private final AtomicWorldData data;
|
||||
private final GMap<SMCAVector, AtomicChunkData> loadedChunks;
|
||||
|
||||
public IrisWorldData(World world)
|
||||
{
|
||||
this.world = world;
|
||||
data = new AtomicWorldData(world);
|
||||
loadedChunks = new GMap<>();
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, this::softUnloadWorld, 200, 20);
|
||||
}
|
||||
|
||||
private void softUnloadWorld()
|
||||
{
|
||||
L.i("Load: " + F.f(getLoadedChunks().size()) + " Chunks in " + F.f(getLoadedRegions().size()) + " Regions");
|
||||
|
||||
for(SMCAVector i : getLoadedChunks())
|
||||
{
|
||||
try
|
||||
{
|
||||
AtomicChunkData d = getChunk(i.getX(), i.getZ());
|
||||
if(d.getTimeSinceLastUse() > 10000)
|
||||
{
|
||||
unloadChunk(i.getX(), i.getZ(), true);
|
||||
}
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for(SMCAVector i : getLoadedRegions())
|
||||
{
|
||||
softUnloadRegion(i.getX(), i.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean softUnloadRegion(int rx, int rz)
|
||||
{
|
||||
for(SMCAVector i : loadedChunks.keySet())
|
||||
{
|
||||
if(i.getX() >> 5 == rx && i.getZ() >> 5 == rz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
data.unloadSection(rx, rz, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
L.f(C.RED + "Failed to save Iris Subregion " + C.YELLOW + rx + " " + rz);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean deleteChunk(int x, int z)
|
||||
{
|
||||
if(isChunkLoaded(x, z))
|
||||
{
|
||||
unloadChunk(x, z, false);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AtomicMCAData region = data.getSubregion(x >> 5, z >> 5);
|
||||
region.delete(x & 31, z & 31);
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
L.f(C.RED + "Failed delete chunk " + C.YELLOW + x + " " + z + C.RED.toString() + " -> Failed to get Region " + C.YELLOW + (x >> 5) + " " + (z >> 5));
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean unloadChunk(int x, int z, boolean save)
|
||||
{
|
||||
if(!isChunkLoaded(x, z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(save)
|
||||
{
|
||||
saveChunk(x, z);
|
||||
}
|
||||
|
||||
loadedChunks.remove(new SMCAVector(x, z));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean saveChunk(int x, int z)
|
||||
{
|
||||
if(!isChunkLoaded(x, z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AtomicMCAData region = data.getSubregion(x >> 5, z >> 5);
|
||||
region.set(x & 31, z & 31, getChunk(x, z));
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
L.f(C.RED + "Failed save chunk " + C.YELLOW + x + " " + z + C.RED.toString() + " -> Failed to get Region " + C.YELLOW + (x >> 5) + " " + (z >> 5));
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public AtomicChunkData getOnly(int x, int z)
|
||||
{
|
||||
if(!isChunkLoaded(x, z))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getChunk(x, z);
|
||||
}
|
||||
|
||||
public AtomicChunkData getChunk(int x, int z)
|
||||
{
|
||||
if(!isChunkLoaded(x, z))
|
||||
{
|
||||
try
|
||||
{
|
||||
AtomicMCAData region = data.getSubregion(x >> 5, z >> 5);
|
||||
|
||||
if(region.contains(x & 31, z & 31))
|
||||
{
|
||||
AtomicChunkData chunk = region.get(x & 31, z & 31);
|
||||
loadedChunks.put(new SMCAVector(x, z), chunk);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
AtomicChunkData data = new AtomicChunkData(world);
|
||||
loadedChunks.put(new SMCAVector(x, z), data);
|
||||
}
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
L.f(C.RED + "Failed load chunk " + C.YELLOW + x + " " + z + C.RED.toString() + " -> Failed to get Region " + C.YELLOW + (x >> 5) + " " + (z >> 5));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return loadedChunks.get(new SMCAVector(x, z));
|
||||
}
|
||||
|
||||
public boolean isChunkLoaded(int x, int z)
|
||||
{
|
||||
return loadedChunks.containsKey(new SMCAVector(x, z));
|
||||
}
|
||||
|
||||
public void inject(int x, int z, AtomicChunkData data)
|
||||
{
|
||||
getChunk(x, z).inject(data);
|
||||
}
|
||||
|
||||
public boolean exists(int x, int z)
|
||||
{
|
||||
try
|
||||
{
|
||||
return isChunkLoaded(x, z) || data.getSubregion(x >> 5, z >> 5).contains(x & 31, z & 31);
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
L.f(C.RED + "Failed check chunk " + C.YELLOW + x + " " + z + C.RED.toString() + " -> Failed to get Region " + C.YELLOW + (x >> 5) + " " + (z >> 5));
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public GList<SMCAVector> getLoadedChunks()
|
||||
{
|
||||
return loadedChunks.k();
|
||||
}
|
||||
|
||||
public GList<SMCAVector> getLoadedRegions()
|
||||
{
|
||||
return data.getLoadedRegions();
|
||||
}
|
||||
|
||||
public void saveAll()
|
||||
{
|
||||
for(SMCAVector i : loadedChunks.k())
|
||||
{
|
||||
saveChunk(i.getX(), i.getZ());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
data.saveAll();
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, int id, byte data)
|
||||
{
|
||||
getChunk(x >> 4, z >> 4).setBlock(x & 15, y, z & 15, id, data);
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
for(SMCAVector i : getLoadedChunks())
|
||||
{
|
||||
unloadChunk(i.getX(), i.getZ(), true);
|
||||
}
|
||||
|
||||
softUnloadWorld();
|
||||
}
|
||||
}
|
44
src/main/java/ninja/bytecode/iris/util/ParallaxAnchor.java
Normal file
44
src/main/java/ninja/bytecode/iris/util/ParallaxAnchor.java
Normal file
@ -0,0 +1,44 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import ninja.bytecode.iris.pack.IrisBiome;
|
||||
|
||||
public class ParallaxAnchor
|
||||
{
|
||||
private final int height;
|
||||
private final int water;
|
||||
private final IrisBiome biome;
|
||||
private final AtomicChunkData data;
|
||||
|
||||
public ParallaxAnchor(int height, int water, IrisBiome biome, AtomicChunkData data)
|
||||
{
|
||||
this.height = height;
|
||||
this.water = water;
|
||||
this.biome = biome;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public AtomicChunkData getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getWater()
|
||||
{
|
||||
return water;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getWaterHeight()
|
||||
{
|
||||
return water;
|
||||
}
|
||||
|
||||
public IrisBiome getBiome()
|
||||
{
|
||||
return biome;
|
||||
}
|
||||
}
|
98
src/main/java/ninja/bytecode/iris/util/ParallaxCache.java
Normal file
98
src/main/java/ninja/bytecode/iris/util/ParallaxCache.java
Normal file
@ -0,0 +1,98 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||
import ninja.bytecode.iris.pack.IrisBiome;
|
||||
import ninja.bytecode.shuriken.collections.GMap;
|
||||
import ninja.bytecode.shuriken.collections.GSet;
|
||||
|
||||
public class ParallaxCache
|
||||
{
|
||||
private GMap<SMCAVector, ChunkPlan> cachePlan;
|
||||
private GMap<SMCAVector, AtomicChunkData> cacheData;
|
||||
private GSet<SMCAVector> contains;
|
||||
private IrisGenerator gen;
|
||||
|
||||
public ParallaxCache(IrisGenerator gen)
|
||||
{
|
||||
this.gen = gen;
|
||||
cacheData = new GMap<>();
|
||||
cachePlan = new GMap<>();
|
||||
contains = new GSet<>();
|
||||
}
|
||||
|
||||
public MB get(int x, int y, int z)
|
||||
{
|
||||
SMCAVector s = new SMCAVector(x, z);
|
||||
SMCAVector c = new SMCAVector(x >> 4, z >> 4);
|
||||
|
||||
if(contains.contains(s) && cacheData.containsKey(c) && cachePlan.containsKey(c) )
|
||||
{
|
||||
return cacheData.get(c).getMB(x & 15, y, z & 15);
|
||||
}
|
||||
|
||||
createData(x, z, s, c);
|
||||
|
||||
return cacheData.get(c).getMB(x & 15, y, z & 15);
|
||||
}
|
||||
|
||||
public IrisBiome getBiome(int x, int z)
|
||||
{
|
||||
SMCAVector s = new SMCAVector(x, z);
|
||||
SMCAVector c = new SMCAVector(x >> 4, z >> 4);
|
||||
|
||||
if(contains.contains(s) && cacheData.containsKey(c) && cachePlan.containsKey(c) )
|
||||
{
|
||||
return cachePlan.get(c).getBiome(x & 15, z & 15);
|
||||
}
|
||||
|
||||
createData(x, z, s, c);
|
||||
|
||||
return cachePlan.get(c).getBiome(x & 15, z & 15);
|
||||
}
|
||||
|
||||
public int getWaterHeight(int x, int z)
|
||||
{
|
||||
SMCAVector s = new SMCAVector(x, z);
|
||||
SMCAVector c = new SMCAVector(x >> 4, z >> 4);
|
||||
|
||||
if(contains.contains(s) && cacheData.containsKey(c) && cachePlan.containsKey(c) )
|
||||
{
|
||||
return cachePlan.get(c).getRealWaterHeight(x & 15, z & 15);
|
||||
}
|
||||
|
||||
createData(x, z, s, c);
|
||||
|
||||
return cachePlan.get(c).getRealWaterHeight(x & 15, z & 15);
|
||||
}
|
||||
|
||||
public int getHeight(int x, int z)
|
||||
{
|
||||
SMCAVector s = new SMCAVector(x, z);
|
||||
SMCAVector c = new SMCAVector(x >> 4, z >> 4);
|
||||
|
||||
if(contains.contains(s) && cacheData.containsKey(c) && cachePlan.containsKey(c) )
|
||||
{
|
||||
return cachePlan.get(c).getRealHeight(x & 15, z & 15);
|
||||
}
|
||||
|
||||
createData(x, z, s, c);
|
||||
|
||||
return cachePlan.get(c).getRealHeight(x & 15, z & 15);
|
||||
}
|
||||
|
||||
private void createData(int x, int z, SMCAVector s, SMCAVector c)
|
||||
{
|
||||
if(!cacheData.containsKey(c))
|
||||
{
|
||||
cacheData.put(c, new AtomicChunkData(gen.getWorld()));
|
||||
}
|
||||
|
||||
if(!cachePlan.containsKey(c))
|
||||
{
|
||||
cachePlan.put(c, new ChunkPlan());
|
||||
}
|
||||
|
||||
gen.computeAnchor(x, z, cachePlan.get(c), cacheData.get(c));
|
||||
contains.add(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
import mortar.api.nms.NMP;
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.iris.controller.TimingsController;
|
||||
import ninja.bytecode.shuriken.bench.PrecisionStopwatch;
|
||||
import ninja.bytecode.shuriken.collections.GSet;
|
||||
import ninja.bytecode.shuriken.execution.ChronoLatch;
|
||||
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup;
|
||||
import ninja.bytecode.shuriken.format.F;
|
||||
import ninja.bytecode.shuriken.math.RNG;
|
||||
|
||||
public abstract class ParallaxWorldGenerator extends ParallelChunkGenerator implements Listener
|
||||
{
|
||||
private World world;
|
||||
private IrisWorldData data;
|
||||
private RNG rMaster;
|
||||
private AtomicChunkData buffer;
|
||||
private GSet<Chunk> fix;
|
||||
private ChronoLatch cl;
|
||||
|
||||
@Override
|
||||
public final void init(World world, Random random)
|
||||
{
|
||||
this.world = world;
|
||||
cl = new ChronoLatch(3000);
|
||||
fix = new GSet<>();
|
||||
buffer = new AtomicChunkData(world);
|
||||
this.data = new IrisWorldData(world);
|
||||
this.rMaster = new RNG(world.getSeed() + 1);
|
||||
onInit(world, rMaster.nextParallelRNG(1));
|
||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(ChunkLoadEvent e)
|
||||
{
|
||||
if(e.getWorld().equals(world))
|
||||
{
|
||||
NMP.host.relight(e.getChunk());
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () -> fix.add(e.getChunk()), 20);
|
||||
|
||||
if(cl.flip())
|
||||
{
|
||||
for(Chunk i : fix)
|
||||
{
|
||||
for(Player f : e.getWorld().getPlayers())
|
||||
{
|
||||
NMP.CHUNK.refreshIgnorePosition(f, i);
|
||||
}
|
||||
}
|
||||
|
||||
fix.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldUnloadEvent e)
|
||||
{
|
||||
if(e.getWorld().equals(world))
|
||||
{
|
||||
getWorldData().dispose();
|
||||
onUnload();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldSaveEvent e)
|
||||
{
|
||||
if(e.getWorld().equals(world))
|
||||
{
|
||||
getWorldData().saveAll();
|
||||
}
|
||||
}
|
||||
|
||||
public ParallaxAnchor computeAnchor(int wx, int wz, ChunkPlan heightBuffer, AtomicChunkData data)
|
||||
{
|
||||
onGenColumn(wx, wz, wx & 15, wz & 15, heightBuffer, data);
|
||||
|
||||
return new ParallaxAnchor(heightBuffer.getRealHeight(wx & 15, wz & 15), heightBuffer.getRealWaterHeight(wx & 15, wz & 15), heightBuffer.getBiome(wx & 15, wz & 15), data);
|
||||
}
|
||||
|
||||
public ParallaxAnchor computeAnchor(int wx, int wz)
|
||||
{
|
||||
ChunkPlan heightBuffer = new ChunkPlan();
|
||||
onGenColumn(wx, wz, wx & 15, wz & 15, heightBuffer, buffer);
|
||||
|
||||
return new ParallaxAnchor(heightBuffer.getRealHeight(wx & 15, wz & 15), heightBuffer.getRealWaterHeight(wx & 15, wz & 15), heightBuffer.getBiome(wx & 15, wz & 15), buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ChunkPlan initChunk(World world, int x, int z, Random random)
|
||||
{
|
||||
PrecisionStopwatch ps = PrecisionStopwatch.start();
|
||||
TaskGroup g = startWork();
|
||||
int gg = 0;
|
||||
int gx = 0;
|
||||
for(int ii = -(getParallaxSize().getX() / 2) - 1; ii < (getParallaxSize().getX() / 2) + 1; ii++)
|
||||
{
|
||||
int i = ii;
|
||||
|
||||
for(int jj = -(getParallaxSize().getZ() / 2) - 1; jj < (getParallaxSize().getZ() / 2) + 1; jj++)
|
||||
{
|
||||
gx++;
|
||||
int j = jj;
|
||||
int cx = x + i;
|
||||
int cz = z + j;
|
||||
|
||||
if(!getWorldData().exists(cx, cz))
|
||||
{
|
||||
g.queue(() ->
|
||||
{
|
||||
onGenParallax(cx, cz, getRMaster(cx, cz, -59328));
|
||||
getWorldData().getChunk(cx, cz);
|
||||
});
|
||||
|
||||
gg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double a = ps.getMilliseconds();
|
||||
double b = g.execute().timeElapsed;
|
||||
|
||||
System.out.println("MS: " + F.duration(Iris.getController(TimingsController.class).getResult("terrain"), 2) + " \tQMS: " + F.duration(a, 2) + " " + " \tEMS: " + F.duration(b, 2) + "\tSCG: " + gg + " / " + gx + " (" + F.pc(((double) gg / (double) gx)) + ") " + " \tTC: " + F.f(getWorldData().getLoadedChunks().size()) + " \tTR: " + getWorldData().getLoadedRegions().size());
|
||||
|
||||
return onInitChunk(world, x, z, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void postChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan)
|
||||
{
|
||||
getWorldData().inject(x, z, data);
|
||||
onPostChunk(world, x, z, random, data, plan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data)
|
||||
{
|
||||
return onGenColumn(wx, wz, x, z, plan, data);
|
||||
}
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
public IrisWorldData getWorldData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public RNG getRMaster()
|
||||
{
|
||||
return rMaster;
|
||||
}
|
||||
|
||||
public RNG getRMaster(int x, int z, int signature)
|
||||
{
|
||||
return rMaster.nextParallelRNG((int) (signature + x * z + z + x * 2.12));
|
||||
}
|
||||
|
||||
protected abstract void onUnload();
|
||||
|
||||
protected abstract SChunkVector getParallaxSize();
|
||||
|
||||
public abstract void onGenParallax(int x, int z, Random random);
|
||||
|
||||
public abstract void onInit(World world, Random random);
|
||||
|
||||
public abstract ChunkPlan onInitChunk(World world, int x, int z, Random random);
|
||||
|
||||
public abstract Biome onGenColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data2);
|
||||
|
||||
public abstract void onPostChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan);
|
||||
}
|
@ -8,7 +8,6 @@ import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import mortar.logic.queue.ChronoLatch;
|
||||
import ninja.bytecode.iris.Iris;
|
||||
import ninja.bytecode.iris.controller.ExecutionController;
|
||||
import ninja.bytecode.iris.controller.TimingsController;
|
||||
@ -24,48 +23,64 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
|
||||
private int j;
|
||||
private int wx;
|
||||
private int wz;
|
||||
private AtomicChunkData data;
|
||||
private ReentrantLock biomeLock;
|
||||
private TaskGroup tg;
|
||||
private ChronoLatch el = new ChronoLatch(5000);
|
||||
private boolean ready = false;
|
||||
int cg = 0;
|
||||
private RollingSequence rs = new RollingSequence(512);
|
||||
private World world;
|
||||
private TaskExecutor genPool;
|
||||
private TaskExecutor genPar;
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
public Biome generateFullColumn(int a, int b, int c, int d, ChunkPlan p)
|
||||
public Biome generateFullColumn(int a, int b, int c, int d, ChunkPlan p, AtomicChunkData data)
|
||||
{
|
||||
return genColumn(a, b, c, d, p);
|
||||
return genColumn(a, b, c, d, p, data);
|
||||
}
|
||||
|
||||
public TaskGroup startParallaxWork()
|
||||
{
|
||||
if(genPar == null)
|
||||
{
|
||||
genPar = Iris.getController(ExecutionController.class).getExecutor(world, "Parallax");
|
||||
}
|
||||
|
||||
return genPar.startWork();
|
||||
}
|
||||
|
||||
public TaskGroup startWork()
|
||||
{
|
||||
if(genPool == null)
|
||||
{
|
||||
genPool = Iris.getController(ExecutionController.class).getExecutor(world, "Generator");
|
||||
}
|
||||
|
||||
return genPool.startWork();
|
||||
}
|
||||
|
||||
public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome)
|
||||
{
|
||||
AtomicChunkData data = new AtomicChunkData(world);
|
||||
|
||||
try
|
||||
{
|
||||
Iris.getController(TimingsController.class).started("terrain");
|
||||
if(genPool == null)
|
||||
{
|
||||
genPool = Iris.getController(ExecutionController.class).getExecutor(world);
|
||||
}
|
||||
|
||||
this.world = world;
|
||||
data = new AtomicChunkData(world);
|
||||
|
||||
if(!ready)
|
||||
{
|
||||
biomeLock = new ReentrantLock();
|
||||
onInit(world, random);
|
||||
init(world, random);
|
||||
ready = true;
|
||||
}
|
||||
|
||||
tg = genPool.startWork();
|
||||
tg = startWork();
|
||||
O<ChunkPlan> plan = new O<ChunkPlan>();
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
wx = (x << 4) + i;
|
||||
@ -79,7 +94,7 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
|
||||
int d = j;
|
||||
tg.queue(() ->
|
||||
{
|
||||
Biome f = generateFullColumn(a, b, c, d, plan.get());
|
||||
Biome f = generateFullColumn(a, b, c, d, plan.get(), data);
|
||||
biomeLock.lock();
|
||||
biome.setBiome(c, d, f);
|
||||
biomeLock.unlock();
|
||||
@ -87,9 +102,9 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
|
||||
}
|
||||
}
|
||||
|
||||
plan.set(onInitChunk(world, x, z, random));
|
||||
plan.set(initChunk(world, x, z, random));
|
||||
TaskResult r = tg.execute();
|
||||
onPostChunk(world, x, z, random, data, plan.get());
|
||||
postChunk(world, x, z, random, data, plan.get());
|
||||
rs.put(r.timeElapsed);
|
||||
cg++;
|
||||
Iris.getController(TimingsController.class).stopped("terrain");
|
||||
@ -97,61 +112,32 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
|
||||
|
||||
catch(Throwable e)
|
||||
{
|
||||
for(int i = 0; i < 16; i++)
|
||||
try
|
||||
{
|
||||
for(int j = 0; j < 16; j++)
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
data.setBlock(i, 0, j, Material.RED_GLAZED_TERRACOTTA);
|
||||
for(int j = 0; j < 16; j++)
|
||||
{
|
||||
data.setBlock(i, 0, j, Material.RED_GLAZED_TERRACOTTA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(el.flip())
|
||||
catch(Throwable ex)
|
||||
{
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return data.toChunkData();
|
||||
}
|
||||
|
||||
public abstract void onInit(World world, Random random);
|
||||
public abstract void init(World world, Random random);
|
||||
|
||||
public abstract ChunkPlan onInitChunk(World world, int x, int z, Random random);
|
||||
public abstract ChunkPlan initChunk(World world, int x, int z, Random random);
|
||||
|
||||
public abstract void onPostChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan);
|
||||
public abstract void postChunk(World world, int x, int z, Random random, AtomicChunkData data, ChunkPlan plan);
|
||||
|
||||
public abstract Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan);
|
||||
|
||||
public abstract void decorateColumn(int wx, int wz, int x, int z, ChunkPlan plan);
|
||||
|
||||
public void setBlock(int x, int y, int z, Material b)
|
||||
{
|
||||
setBlock(x, y, z, b, (byte) 0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setBlock(int x, int y, int z, Material b, byte d)
|
||||
{
|
||||
setBlock(x, y, z, b.getId(), d);
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, int b)
|
||||
{
|
||||
setBlock(x, y, z, b, (byte) 0);
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, int b, byte d)
|
||||
{
|
||||
data.setBlock(x, y, z, b, d);
|
||||
}
|
||||
|
||||
public Material getType(int x, int y, int z)
|
||||
{
|
||||
return data.getType(x, y, z);
|
||||
}
|
||||
|
||||
public byte getData(int x, int y, int z)
|
||||
{
|
||||
return data.getData(x, y, z);
|
||||
}
|
||||
public abstract Biome genColumn(int wx, int wz, int x, int z, ChunkPlan plan, AtomicChunkData data);
|
||||
}
|
@ -1,28 +1,28 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
public class ChunkedVector
|
||||
public class SChunkVector
|
||||
{
|
||||
private byte x;
|
||||
private byte z;
|
||||
|
||||
public ChunkedVector(int x, int z)
|
||||
public SChunkVector(int x, int z)
|
||||
{
|
||||
this.x = (byte) (x);
|
||||
this.z = (byte) (z);
|
||||
}
|
||||
|
||||
public ChunkedVector(byte x, byte z)
|
||||
public SChunkVector(byte x, byte z)
|
||||
{
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public ChunkedVector(double x, double z)
|
||||
public SChunkVector(double x, double z)
|
||||
{
|
||||
this((int) Math.round(x), (int) Math.round(z));
|
||||
}
|
||||
|
||||
public ChunkedVector()
|
||||
public SChunkVector()
|
||||
{
|
||||
this((byte) 0, (byte) 0);
|
||||
}
|
||||
@ -66,13 +66,11 @@ public class ChunkedVector
|
||||
return false;
|
||||
if(getClass() != obj.getClass())
|
||||
return false;
|
||||
ChunkedVector other = (ChunkedVector) obj;
|
||||
SChunkVector other = (SChunkVector) obj;
|
||||
if(x != other.x)
|
||||
return false;
|
||||
if(z != other.z)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
61
src/main/java/ninja/bytecode/iris/util/SMCAVector.java
Normal file
61
src/main/java/ninja/bytecode/iris/util/SMCAVector.java
Normal file
@ -0,0 +1,61 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SMCAVector
|
||||
{
|
||||
private int x;
|
||||
private int z;
|
||||
|
||||
public SMCAVector(int x, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public SMCAVector()
|
||||
{
|
||||
this(0, 0);
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x)
|
||||
{
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(int z)
|
||||
{
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(!(obj instanceof SMCAVector))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SMCAVector other = (SMCAVector) obj;
|
||||
return x == other.x && z == other.z;
|
||||
}
|
||||
}
|
82
src/main/java/org/jnbt/ByteArrayTag.java
Normal file
82
src/main/java/org/jnbt/ByteArrayTag.java
Normal file
@ -0,0 +1,82 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Byte_Array</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class ByteArrayTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final byte[] value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public ByteArrayTag(String name, byte[] value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder hex = new StringBuilder();
|
||||
for (byte b : value) {
|
||||
String hexDigits = Integer.toHexString(b).toUpperCase();
|
||||
if (hexDigits.length() == 1) {
|
||||
hex.append("0");
|
||||
}
|
||||
hex.append(hexDigits).append(" ");
|
||||
}
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Byte_Array" + append + ": " + hex.toString();
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/ByteTag.java
Normal file
74
src/main/java/org/jnbt/ByteTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Byte</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class ByteTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final byte value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public ByteTag(String name, byte value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Byte" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
83
src/main/java/org/jnbt/CompoundTag.java
Normal file
83
src/main/java/org/jnbt/CompoundTag.java
Normal file
@ -0,0 +1,83 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The <code>TAG_Compound</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class CompoundTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final Map<String, Tag> value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public CompoundTag(String name, Map<String, Tag> value) {
|
||||
super(name);
|
||||
this.value = Collections.unmodifiableMap(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Tag> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
bldr.append("TAG_Compound" + append + ": " + value.size() + " entries\r\n{\r\n");
|
||||
for (Map.Entry<String, Tag> entry : value.entrySet()) {
|
||||
bldr.append(" " + entry.getValue().toString().replaceAll("\r\n", "\r\n ") + "\r\n");
|
||||
}
|
||||
bldr.append("}");
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/DoubleTag.java
Normal file
74
src/main/java/org/jnbt/DoubleTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Double</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class DoubleTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public DoubleTag(String name, double value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Double" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
60
src/main/java/org/jnbt/EndTag.java
Normal file
60
src/main/java/org/jnbt/EndTag.java
Normal file
@ -0,0 +1,60 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_End</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class EndTag extends Tag {
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*/
|
||||
public EndTag() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TAG_End";
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/FloatTag.java
Normal file
74
src/main/java/org/jnbt/FloatTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Float</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class FloatTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final float value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public FloatTag(String name, float value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Float" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
76
src/main/java/org/jnbt/IntArrayTag.java
Normal file
76
src/main/java/org/jnbt/IntArrayTag.java
Normal file
@ -0,0 +1,76 @@
|
||||
package org.jnbt;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2015 Neil Wightman
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Int_Array</code> tag.
|
||||
*
|
||||
* @author Neil Wightman
|
||||
*
|
||||
*/
|
||||
public final class IntArrayTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final int[] value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public IntArrayTag(String name, int[] value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Int_Array" + append + ": " + Arrays.toString(value);
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/IntTag.java
Normal file
74
src/main/java/org/jnbt/IntTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Int</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class IntTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public IntTag(String name, int value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Int" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
99
src/main/java/org/jnbt/ListTag.java
Normal file
99
src/main/java/org/jnbt/ListTag.java
Normal file
@ -0,0 +1,99 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The <code>TAG_List</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class ListTag extends Tag {
|
||||
|
||||
/**
|
||||
* The type.
|
||||
*/
|
||||
private final Class<? extends Tag> type;
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final List<Tag> value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param type The type of item in the list.
|
||||
* @param value The value.
|
||||
*/
|
||||
public ListTag(String name, Class<? extends Tag> type, List<Tag> value) {
|
||||
super(name);
|
||||
this.type = type;
|
||||
this.value = Collections.unmodifiableList(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of item in this list.
|
||||
*
|
||||
* @return The type of item in this list.
|
||||
*/
|
||||
public Class<? extends Tag> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tag> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
bldr.append("TAG_List" + append + ": " + value.size() + " entries of type " + NBTUtils.getTypeName(type) + "\r\n{\r\n");
|
||||
for (Tag t : value) {
|
||||
bldr.append(" " + t.toString().replaceAll("\r\n", "\r\n ") + "\r\n");
|
||||
}
|
||||
bldr.append("}");
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/LongTag.java
Normal file
74
src/main/java/org/jnbt/LongTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Long</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class LongTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final long value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public LongTag(String name, long value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Long" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
77
src/main/java/org/jnbt/NBTConstants.java
Normal file
77
src/main/java/org/jnbt/NBTConstants.java
Normal file
@ -0,0 +1,77 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2015 Neil Wightman
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Changes : Neil Wightman - Support 19133 Tag_Int_Array tag
|
||||
*/
|
||||
/**
|
||||
* A class which holds constant values.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class NBTConstants {
|
||||
|
||||
/**
|
||||
* The character set used by NBT (UTF-8).
|
||||
*/
|
||||
public static final Charset CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
/**
|
||||
* Tag type constants.
|
||||
*/
|
||||
public static final int TYPE_END = 0,
|
||||
TYPE_BYTE = 1,
|
||||
TYPE_SHORT = 2,
|
||||
TYPE_INT = 3,
|
||||
TYPE_LONG = 4,
|
||||
TYPE_FLOAT = 5,
|
||||
TYPE_DOUBLE = 6,
|
||||
TYPE_BYTE_ARRAY = 7,
|
||||
TYPE_STRING = 8,
|
||||
TYPE_LIST = 9,
|
||||
TYPE_COMPOUND = 10,
|
||||
TYPE_INT_ARRAY = 11;
|
||||
|
||||
/**
|
||||
* Default private constructor.
|
||||
*/
|
||||
private NBTConstants() {
|
||||
|
||||
}
|
||||
|
||||
}
|
205
src/main/java/org/jnbt/NBTInputStream.java
Normal file
205
src/main/java/org/jnbt/NBTInputStream.java
Normal file
@ -0,0 +1,205 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2015 Neil Wightman
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* Changes :
|
||||
* Neil Wightman - Support 19133 Tag_Int_Array tag
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class reads <strong>NBT</strong>, or
|
||||
* <strong>Named Binary Tag</strong> streams, and produces an object graph of subclasses of the <code>Tag</code> object.</p>
|
||||
*
|
||||
* <p>
|
||||
* The NBT format was created by Markus Persson, and the specification may be found at <a href="http://www.minecraft.net/docs/NBT.txt">
|
||||
* http://www.minecraft.net/docs/NBT.txt</a>.</p>
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class NBTInputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* The data input stream.
|
||||
*/
|
||||
private final DataInputStream is;
|
||||
|
||||
/**
|
||||
* Create a new <code>NBTInputStream</code>, which will source its data from the specified input stream.
|
||||
* @param is The output stream
|
||||
*/
|
||||
public NBTInputStream(DataInputStream is) {
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>NBTInputStream</code>, which will source its data from the specified input stream.
|
||||
* The stream will be decompressed using GZIP.
|
||||
*
|
||||
* @param is The input stream.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public NBTInputStream(InputStream is) throws IOException {
|
||||
this.is = new DataInputStream(new GZIPInputStream(is));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an NBT tag from the stream.
|
||||
*
|
||||
* @return The tag that was read.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public Tag readTag() throws IOException {
|
||||
return readTag(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an NBT from the stream.
|
||||
*
|
||||
* @param depth The depth of this tag.
|
||||
* @return The tag that was read.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private Tag readTag(int depth) throws IOException {
|
||||
int type = is.readByte() & 0xFF;
|
||||
|
||||
String name;
|
||||
if (type != NBTConstants.TYPE_END) {
|
||||
int nameLength = is.readShort() & 0xFFFF;
|
||||
byte[] nameBytes = new byte[nameLength];
|
||||
is.readFully(nameBytes);
|
||||
name = new String(nameBytes, NBTConstants.CHARSET);
|
||||
} else {
|
||||
name = "";
|
||||
}
|
||||
|
||||
return readTagPayload(type, name, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the payload of a tag, given the name and type.
|
||||
*
|
||||
* @param type The type.
|
||||
* @param name The name.
|
||||
* @param depth The depth.
|
||||
* @return The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private Tag readTagPayload(int type, String name, int depth) throws IOException {
|
||||
switch (type) {
|
||||
case NBTConstants.TYPE_END:
|
||||
if (depth == 0) {
|
||||
throw new IOException("TAG_End found without a TAG_Compound/TAG_List tag preceding it.");
|
||||
} else {
|
||||
return new EndTag();
|
||||
}
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
return new ByteTag(name, is.readByte());
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return new ShortTag(name, is.readShort());
|
||||
case NBTConstants.TYPE_INT:
|
||||
return new IntTag(name, is.readInt());
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return new LongTag(name, is.readLong());
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
return new FloatTag(name, is.readFloat());
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
return new DoubleTag(name, is.readDouble());
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
int length = is.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new ByteArrayTag(name, bytes);
|
||||
case NBTConstants.TYPE_STRING:
|
||||
length = is.readShort();
|
||||
bytes = new byte[length];
|
||||
is.readFully(bytes);
|
||||
return new StringTag(name, new String(bytes, NBTConstants.CHARSET));
|
||||
case NBTConstants.TYPE_LIST:
|
||||
int childType = is.readByte();
|
||||
length = is.readInt();
|
||||
|
||||
List<Tag> tagList = new ArrayList<Tag>();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Tag tag = readTagPayload(childType, "", depth + 1);
|
||||
if (tag instanceof EndTag) {
|
||||
throw new IOException("TAG_End not permitted in a list.");
|
||||
}
|
||||
tagList.add(tag);
|
||||
}
|
||||
|
||||
return new ListTag(name, NBTUtils.getTypeClass(childType), tagList);
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
Map<String, Tag> tagMap = new HashMap<String, Tag>();
|
||||
while (true) {
|
||||
Tag tag = readTag(depth + 1);
|
||||
if (tag instanceof EndTag) {
|
||||
break;
|
||||
} else {
|
||||
tagMap.put(tag.getName(), tag);
|
||||
}
|
||||
}
|
||||
|
||||
return new CompoundTag(name, tagMap);
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
length = is.readInt();
|
||||
int[] value = new int[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
value[i] = is.readInt();
|
||||
}
|
||||
return new IntArrayTag(name, value);
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
is.close();
|
||||
}
|
||||
|
||||
}
|
301
src/main/java/org/jnbt/NBTOutputStream.java
Normal file
301
src/main/java/org/jnbt/NBTOutputStream.java
Normal file
@ -0,0 +1,301 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2015 Neil Wightman
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
import java.io.Closeable;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
/**
|
||||
* Changes : Neil Wightman - Support 19133 Tag_Int_Array tag
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class writes <strong>NBT</strong>, or
|
||||
* <strong>Named Binary Tag</strong> <code>Tag</code> objects to an underlying <code>OutputStream</code>.</p>
|
||||
*
|
||||
* <p>
|
||||
* The NBT format was created by Markus Persson, and the specification may be found at <a href="http://www.minecraft.net/docs/NBT.txt">
|
||||
* http://www.minecraft.net/docs/NBT.txt</a>.</p>
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class NBTOutputStream implements Closeable {
|
||||
|
||||
/**
|
||||
* The output stream.
|
||||
*/
|
||||
private final DataOutputStream os;
|
||||
|
||||
/**
|
||||
* Create a new <code>NBTOutputStream</code>, which will write data to the specified underlying output stream.
|
||||
* @param os The output stream
|
||||
*/
|
||||
public NBTOutputStream(DataOutputStream os) {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>NBTOutputStream</code>, which will write data to the specified underlying output stream.
|
||||
* the stream will be compressed using GZIP.
|
||||
*
|
||||
* @param os The output stream.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public NBTOutputStream(OutputStream os) throws IOException {
|
||||
this.os = new DataOutputStream(new GZIPOutputStream(os));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a tag.
|
||||
*
|
||||
* @param tag The tag to write.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void writeTag(Tag tag) throws IOException {
|
||||
int type = NBTUtils.getTypeCode(tag.getClass());
|
||||
String name = tag.getName();
|
||||
byte[] nameBytes = name.getBytes(NBTConstants.CHARSET);
|
||||
|
||||
os.writeByte(type);
|
||||
os.writeShort(nameBytes.length);
|
||||
os.write(nameBytes);
|
||||
|
||||
if (type == NBTConstants.TYPE_END) {
|
||||
throw new IOException("Named TAG_End not permitted.");
|
||||
}
|
||||
|
||||
writeTagPayload(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes tag payload.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeTagPayload(Tag tag) throws IOException {
|
||||
int type = NBTUtils.getTypeCode(tag.getClass());
|
||||
switch (type) {
|
||||
case NBTConstants.TYPE_END:
|
||||
writeEndTagPayload((EndTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
writeByteTagPayload((ByteTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
writeShortTagPayload((ShortTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_INT:
|
||||
writeIntTagPayload((IntTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LONG:
|
||||
writeLongTagPayload((LongTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
writeFloatTagPayload((FloatTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
writeDoubleTagPayload((DoubleTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
writeByteArrayTagPayload((ByteArrayTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_STRING:
|
||||
writeStringTagPayload((StringTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_LIST:
|
||||
writeListTagPayload((ListTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
writeCompoundTagPayload((CompoundTag) tag);
|
||||
break;
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
writeIntArrayTagPayload((IntArrayTag) tag);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Invalid tag type: " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Byte</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeByteTagPayload(ByteTag tag) throws IOException {
|
||||
os.writeByte(tag.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Byte_Array</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeByteArrayTagPayload(ByteArrayTag tag) throws IOException {
|
||||
byte[] bytes = tag.getValue();
|
||||
os.writeInt(bytes.length);
|
||||
os.write(bytes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Compound</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeCompoundTagPayload(CompoundTag tag) throws IOException {
|
||||
for (Tag childTag : tag.getValue().values()) {
|
||||
writeTag(childTag);
|
||||
}
|
||||
os.writeByte((byte) 0); // end tag - better way?
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_List</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeListTagPayload(ListTag tag) throws IOException {
|
||||
Class<? extends Tag> clazz = tag.getType();
|
||||
List<Tag> tags = tag.getValue();
|
||||
int size = tags.size();
|
||||
|
||||
os.writeByte(NBTUtils.getTypeCode(clazz));
|
||||
os.writeInt(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
writeTagPayload(tags.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_String</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeStringTagPayload(StringTag tag) throws IOException {
|
||||
byte[] bytes = tag.getValue().getBytes(NBTConstants.CHARSET);
|
||||
os.writeShort(bytes.length);
|
||||
os.write(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Double</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeDoubleTagPayload(DoubleTag tag) throws IOException {
|
||||
os.writeDouble(tag.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Float</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeFloatTagPayload(FloatTag tag) throws IOException {
|
||||
os.writeFloat(tag.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Long</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeLongTagPayload(LongTag tag) throws IOException {
|
||||
os.writeLong(tag.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Int</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeIntTagPayload(IntTag tag) throws IOException {
|
||||
os.writeInt(tag.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Short</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeShortTagPayload(ShortTag tag) throws IOException {
|
||||
os.writeShort(tag.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Empty</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeEndTagPayload(EndTag tag) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a <code>TAG_Int_Array</code> tag.
|
||||
*
|
||||
* @param tag The tag.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void writeIntArrayTagPayload(IntArrayTag tag) throws IOException {
|
||||
final int[] values = tag.getValue();
|
||||
os.writeInt(values.length);
|
||||
for(final int value : values) {
|
||||
os.writeInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
os.close();
|
||||
}
|
||||
|
||||
}
|
165
src/main/java/org/jnbt/NBTUtils.java
Normal file
165
src/main/java/org/jnbt/NBTUtils.java
Normal file
@ -0,0 +1,165 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2015 Neil Wightman
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* Changes : Neil Wightman - Support 19133 Tag_Int_Array tag
|
||||
*/
|
||||
/**
|
||||
* A class which contains NBT-related utility methods. This currently supports reading 19133 but <b>only</b> writing 19132.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class NBTUtils {
|
||||
|
||||
/**
|
||||
* Gets the type name of a tag.
|
||||
*
|
||||
* @param clazz The tag class.
|
||||
* @return The type name.
|
||||
*/
|
||||
public static String getTypeName(Class<? extends Tag> clazz) {
|
||||
if (clazz.equals(ByteArrayTag.class)) {
|
||||
return "TAG_Byte_Array";
|
||||
} else if (clazz.equals(ByteTag.class)) {
|
||||
return "TAG_Byte";
|
||||
} else if (clazz.equals(CompoundTag.class)) {
|
||||
return "TAG_Compound";
|
||||
} else if (clazz.equals(DoubleTag.class)) {
|
||||
return "TAG_Double";
|
||||
} else if (clazz.equals(EndTag.class)) {
|
||||
return "TAG_End";
|
||||
} else if (clazz.equals(FloatTag.class)) {
|
||||
return "TAG_Float";
|
||||
} else if (clazz.equals(IntTag.class)) {
|
||||
return "TAG_Int";
|
||||
} else if (clazz.equals(ListTag.class)) {
|
||||
return "TAG_List";
|
||||
} else if (clazz.equals(LongTag.class)) {
|
||||
return "TAG_Long";
|
||||
} else if (clazz.equals(ShortTag.class)) {
|
||||
return "TAG_Short";
|
||||
} else if (clazz.equals(StringTag.class)) {
|
||||
return "TAG_String";
|
||||
} else if (clazz.equals(IntArrayTag.class)) {
|
||||
return "TAG_Int_Array";
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid tag classs (" + clazz.getName() + ").");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type code of a tag class.
|
||||
*
|
||||
* @param clazz The tag class.
|
||||
* @return The type code.
|
||||
* @throws IllegalArgumentException if the tag class is invalid.
|
||||
*/
|
||||
public static int getTypeCode(Class<? extends Tag> clazz) {
|
||||
if (clazz.equals(ByteArrayTag.class)) {
|
||||
return NBTConstants.TYPE_BYTE_ARRAY;
|
||||
} else if (clazz.equals(ByteTag.class)) {
|
||||
return NBTConstants.TYPE_BYTE;
|
||||
} else if (clazz.equals(CompoundTag.class)) {
|
||||
return NBTConstants.TYPE_COMPOUND;
|
||||
} else if (clazz.equals(DoubleTag.class)) {
|
||||
return NBTConstants.TYPE_DOUBLE;
|
||||
} else if (clazz.equals(EndTag.class)) {
|
||||
return NBTConstants.TYPE_END;
|
||||
} else if (clazz.equals(FloatTag.class)) {
|
||||
return NBTConstants.TYPE_FLOAT;
|
||||
} else if (clazz.equals(IntTag.class)) {
|
||||
return NBTConstants.TYPE_INT;
|
||||
} else if (clazz.equals(ListTag.class)) {
|
||||
return NBTConstants.TYPE_LIST;
|
||||
} else if (clazz.equals(LongTag.class)) {
|
||||
return NBTConstants.TYPE_LONG;
|
||||
} else if (clazz.equals(ShortTag.class)) {
|
||||
return NBTConstants.TYPE_SHORT;
|
||||
} else if (clazz.equals(StringTag.class)) {
|
||||
return NBTConstants.TYPE_STRING;
|
||||
} else if (clazz.equals(IntArrayTag.class)) {
|
||||
return NBTConstants.TYPE_INT_ARRAY;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid tag classs (" + clazz.getName() + ").");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class of a type of tag.
|
||||
*
|
||||
* @param type The type.
|
||||
* @return The class.
|
||||
* @throws IllegalArgumentException if the tag type is invalid.
|
||||
*/
|
||||
public static Class<? extends Tag> getTypeClass(int type) {
|
||||
switch (type) {
|
||||
case NBTConstants.TYPE_END:
|
||||
return EndTag.class;
|
||||
case NBTConstants.TYPE_BYTE:
|
||||
return ByteTag.class;
|
||||
case NBTConstants.TYPE_SHORT:
|
||||
return ShortTag.class;
|
||||
case NBTConstants.TYPE_INT:
|
||||
return IntTag.class;
|
||||
case NBTConstants.TYPE_LONG:
|
||||
return LongTag.class;
|
||||
case NBTConstants.TYPE_FLOAT:
|
||||
return FloatTag.class;
|
||||
case NBTConstants.TYPE_DOUBLE:
|
||||
return DoubleTag.class;
|
||||
case NBTConstants.TYPE_BYTE_ARRAY:
|
||||
return ByteArrayTag.class;
|
||||
case NBTConstants.TYPE_STRING:
|
||||
return StringTag.class;
|
||||
case NBTConstants.TYPE_LIST:
|
||||
return ListTag.class;
|
||||
case NBTConstants.TYPE_COMPOUND:
|
||||
return CompoundTag.class;
|
||||
case NBTConstants.TYPE_INT_ARRAY:
|
||||
return IntArrayTag.class;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid tag type : " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor.
|
||||
*/
|
||||
private NBTUtils() {
|
||||
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/ShortTag.java
Normal file
74
src/main/java/org/jnbt/ShortTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_Short</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class ShortTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final short value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public ShortTag(String name, short value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_Short" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/org/jnbt/StringTag.java
Normal file
74
src/main/java/org/jnbt/StringTag.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* The <code>TAG_String</code> tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public final class StringTag extends Tag {
|
||||
|
||||
/**
|
||||
* The value.
|
||||
*/
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Creates the tag.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public StringTag(String name, String value) {
|
||||
super(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getName();
|
||||
String append = "";
|
||||
if (name != null && !name.equals("")) {
|
||||
append = "(\"" + this.getName() + "\")";
|
||||
}
|
||||
return "TAG_String" + append + ": " + value;
|
||||
}
|
||||
|
||||
}
|
73
src/main/java/org/jnbt/Tag.java
Normal file
73
src/main/java/org/jnbt/Tag.java
Normal file
@ -0,0 +1,73 @@
|
||||
package org.jnbt;
|
||||
|
||||
/*
|
||||
* JNBT License
|
||||
*
|
||||
* Copyright (c) 2010 Graham Edgecombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the JNBT team nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* Represents a single NBT tag.
|
||||
*
|
||||
* @author Graham Edgecombe
|
||||
*
|
||||
*/
|
||||
public abstract class Tag {
|
||||
|
||||
/**
|
||||
* The name of this tag.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Creates the tag with the specified name.
|
||||
*
|
||||
* @param name The name.
|
||||
*/
|
||||
public Tag(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this tag.
|
||||
*
|
||||
* @return The name of this tag.
|
||||
*/
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this tag.
|
||||
*
|
||||
* @return The value of this tag.
|
||||
*/
|
||||
public abstract Object getValue();
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user