mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
Parallax 2
This commit is contained in:
parent
ccc7a947cd
commit
2500fa54e4
@ -8,7 +8,7 @@ import org.bukkit.inventory.Inventory;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.object.InventorySlotType;
|
||||
import com.volmit.iris.object.IrisLootTable;
|
||||
import com.volmit.iris.util.KSet;
|
||||
import com.volmit.iris.util.KList;
|
||||
import com.volmit.iris.util.MortarCommand;
|
||||
import com.volmit.iris.util.MortarSender;
|
||||
import com.volmit.iris.util.O;
|
||||
@ -30,9 +30,9 @@ public class CommandIrisLoot extends MortarCommand
|
||||
if(sender.isPlayer())
|
||||
{
|
||||
Player p = sender.player();
|
||||
KSet<IrisLootTable> tables = Iris.proj.getCurrentProject().getGlUpdate().getLootTables(p.getLocation().getBlock());
|
||||
KList<IrisLootTable> tables = Iris.proj.getCurrentProject().getGlUpdate().getLootTables(RNG.r, p.getLocation().getBlock());
|
||||
Inventory inv = Bukkit.createInventory(null, 27 * 2);
|
||||
Iris.proj.getCurrentProject().getGlUpdate().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
|
||||
Iris.proj.getCurrentProject().getGlUpdate().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ(), 1);
|
||||
p.openInventory(inv);
|
||||
|
||||
for(IrisLootTable i : tables)
|
||||
@ -74,7 +74,7 @@ public class CommandIrisLoot extends MortarCommand
|
||||
inv.clear();
|
||||
}
|
||||
|
||||
Iris.proj.getCurrentProject().getGlUpdate().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
|
||||
Iris.proj.getCurrentProject().getGlUpdate().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ(), 1);
|
||||
}, 0, fast ? 5 : 35));
|
||||
|
||||
return true;
|
||||
|
@ -17,7 +17,6 @@ import com.volmit.iris.object.IrisBiomeMutation;
|
||||
import com.volmit.iris.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.object.IrisRegion;
|
||||
import com.volmit.iris.object.IrisStructurePlacement;
|
||||
import com.volmit.iris.object.TileResult;
|
||||
import com.volmit.iris.util.BiomeMap;
|
||||
import com.volmit.iris.util.CaveResult;
|
||||
import com.volmit.iris.util.ChunkPosition;
|
||||
@ -27,6 +26,7 @@ import com.volmit.iris.util.IrisLock;
|
||||
import com.volmit.iris.util.IrisStructureResult;
|
||||
import com.volmit.iris.util.KList;
|
||||
import com.volmit.iris.util.KMap;
|
||||
import com.volmit.iris.util.NBTInputStream;
|
||||
import com.volmit.iris.util.NastyRunnable;
|
||||
import com.volmit.iris.util.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.RNG;
|
||||
@ -106,7 +106,7 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
NBTInputStream
|
||||
return h;
|
||||
}
|
||||
|
||||
@ -218,61 +218,7 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
|
||||
|
||||
public IrisStructureResult getStructure(int x, int y, int z)
|
||||
{
|
||||
IrisBiome b = sampleTrueBiome(x, z).getBiome();
|
||||
IrisRegion r = sampleRegion(x, z);
|
||||
RNG ro = getMasterRandom().nextParallelRNG(496888 + (x >> 4) + (z >> 4));
|
||||
int h = (int) Math.round(getTerrainHeight(x, z));
|
||||
KList<IrisStructurePlacement> p = new KList<>();
|
||||
|
||||
for(IrisStructurePlacement i : r.getStructures())
|
||||
{
|
||||
if(i.getHeight() > -1)
|
||||
{
|
||||
if(y >= i.getHeight() && y <= i.getHeight() + (i.getStructure(this).getGridHeight() * i.getStructure(this).getMaxLayers()))
|
||||
{
|
||||
p.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
else if(y >= h && y <= i.getStructure(this).getGridHeight() + h)
|
||||
{
|
||||
p.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
for(IrisStructurePlacement i : b.getStructures())
|
||||
{
|
||||
if(i.getHeight() > -1)
|
||||
{
|
||||
if(y >= i.getHeight() && y <= i.getHeight() + (i.getStructure(this).getGridHeight() * i.getStructure(this).getMaxLayers()))
|
||||
{
|
||||
p.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
else if(y >= h && y <= i.getStructure(this).getGridHeight() + h)
|
||||
{
|
||||
p.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
for(IrisStructurePlacement i : p)
|
||||
{
|
||||
if(!i.hasStructure(ro, x, y, z))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int hv = (i.getHeight() == -1 ? 0 : i.getHeight()) + (Math.floorDiv(y, i.getStructure(this).getGridHeight()) * i.getStructure(this).getGridHeight());
|
||||
TileResult tile = i.getStructure(this).getTile(ro, Math.floorDiv(i.gridSize(this), x) * i.gridSize(this), hv, Math.floorDiv(i.gridSize(this), z) * i.gridSize(this));
|
||||
|
||||
if(tile != null && tile.getTile() != null)
|
||||
{
|
||||
return new IrisStructureResult(tile.getTile(), i.getStructure(this));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return getParallaxChunk(x >> 4, z >> 4).getStructure(this, y);
|
||||
}
|
||||
|
||||
protected void onGenerateParallax(RNG random, int x, int z)
|
||||
|
@ -25,24 +25,24 @@ import lombok.Data;
|
||||
public class AtomicSliver
|
||||
{
|
||||
public static final BlockData AIR = B.getBlockData("AIR");
|
||||
private transient KMap<Integer, IrisBiome> truebiome;
|
||||
private transient KMap<Integer, Biome> biome;
|
||||
private transient IrisLock lock = new IrisLock("Sliver");
|
||||
private transient int highestBiome = 0;
|
||||
private transient long last = M.ms();
|
||||
private transient int x;
|
||||
private transient int z;
|
||||
private transient boolean modified = false;
|
||||
private KMap<Integer, BlockData> block;
|
||||
private KMap<Integer, IrisBiome> truebiome;
|
||||
private KMap<Integer, Biome> biome;
|
||||
private KSet<Integer> update;
|
||||
private IrisLock lock = new IrisLock("Sliver");
|
||||
private KSet<Integer> blockUpdates;
|
||||
private int highestBlock = 0;
|
||||
private int highestBiome = 0;
|
||||
private long last = M.ms();
|
||||
private int x;
|
||||
private int z;
|
||||
boolean modified = false;
|
||||
|
||||
public AtomicSliver(int x, int z)
|
||||
{
|
||||
lock.setDisabled(true);
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
update = new KSet<>();
|
||||
blockUpdates = new KSet<>();
|
||||
this.block = new KMap<>();
|
||||
this.biome = new KMap<>();
|
||||
this.truebiome = new KMap<>();
|
||||
@ -55,17 +55,17 @@ public class AtomicSliver
|
||||
|
||||
public KSet<Integer> getUpdatables()
|
||||
{
|
||||
return update;
|
||||
return blockUpdates;
|
||||
}
|
||||
|
||||
public void update(int y)
|
||||
{
|
||||
update.add(y);
|
||||
blockUpdates.add(y);
|
||||
}
|
||||
|
||||
public void dontUpdate(int y)
|
||||
{
|
||||
update.remove(y);
|
||||
blockUpdates.remove(y);
|
||||
}
|
||||
|
||||
public BlockData get(int h)
|
||||
@ -81,6 +81,19 @@ public class AtomicSliver
|
||||
return b;
|
||||
}
|
||||
|
||||
public BlockData getOrNull(int h)
|
||||
{
|
||||
BlockData b = block.get(h);
|
||||
last = M.ms();
|
||||
|
||||
if(b.getMaterial().equals(Material.AIR))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
public void set(int h, BlockData d)
|
||||
{
|
||||
setSilently(h, d);
|
||||
@ -190,6 +203,8 @@ public class AtomicSliver
|
||||
{
|
||||
lock.lock();
|
||||
this.block = new KMap<Integer, BlockData>();
|
||||
|
||||
// Block Palette
|
||||
int h = din.readByte() - Byte.MIN_VALUE;
|
||||
int p = din.readByte() - Byte.MIN_VALUE;
|
||||
int u = din.readByte() - Byte.MIN_VALUE;
|
||||
@ -202,11 +217,13 @@ public class AtomicSliver
|
||||
palette.add(B.getBlockData(din.readUTF()));
|
||||
}
|
||||
|
||||
// Blocks
|
||||
for(int i = 0; i <= h; i++)
|
||||
{
|
||||
block.put(i, palette.get(din.readByte() - Byte.MIN_VALUE).clone());
|
||||
}
|
||||
|
||||
// Updates
|
||||
for(int i = 0; i <= u; i++)
|
||||
{
|
||||
update(din.readByte() - Byte.MIN_VALUE);
|
||||
@ -220,6 +237,8 @@ public class AtomicSliver
|
||||
{
|
||||
lock.lock();
|
||||
dos.writeByte(highestBlock + Byte.MIN_VALUE);
|
||||
|
||||
// Block Palette
|
||||
KList<String> palette = new KList<>();
|
||||
|
||||
for(int i = 0; i <= highestBlock; i++)
|
||||
@ -234,13 +253,14 @@ public class AtomicSliver
|
||||
}
|
||||
|
||||
dos.writeByte(palette.size() + Byte.MIN_VALUE);
|
||||
dos.writeByte(update.size() + Byte.MIN_VALUE);
|
||||
dos.writeByte(blockUpdates.size() + Byte.MIN_VALUE);
|
||||
|
||||
for(String i : palette)
|
||||
{
|
||||
dos.writeUTF(i);
|
||||
}
|
||||
|
||||
// Blocks
|
||||
for(int i = 0; i <= highestBlock; i++)
|
||||
{
|
||||
BlockData dat = block.get(i);
|
||||
@ -248,6 +268,7 @@ public class AtomicSliver
|
||||
dos.writeByte(palette.indexOf(d) + Byte.MIN_VALUE);
|
||||
}
|
||||
|
||||
// Updates
|
||||
for(Integer i : getUpdatables())
|
||||
{
|
||||
dos.writeByte(i + Byte.MIN_VALUE);
|
||||
@ -296,6 +317,6 @@ public class AtomicSliver
|
||||
|
||||
public void inject(KSet<Integer> updatables)
|
||||
{
|
||||
update.addAll(updatables);
|
||||
blockUpdates.addAll(updatables);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,13 @@ import java.io.OutputStream;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
|
||||
import com.volmit.iris.gen.DimensionChunkGenerator;
|
||||
import com.volmit.iris.object.IrisStructure;
|
||||
import com.volmit.iris.object.IrisStructureTile;
|
||||
import com.volmit.iris.util.HeightMap;
|
||||
import com.volmit.iris.util.IrisStructureResult;
|
||||
import com.volmit.iris.util.KList;
|
||||
import com.volmit.iris.util.KMap;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -17,11 +23,13 @@ import lombok.Data;
|
||||
public class AtomicSliverMap
|
||||
{
|
||||
private final AtomicSliver[] slivers;
|
||||
private KMap<Integer, String> structures;
|
||||
private boolean parallaxGenerated;
|
||||
private boolean worldGenerated;
|
||||
|
||||
public AtomicSliverMap()
|
||||
{
|
||||
structures = new KMap<>();
|
||||
parallaxGenerated = false;
|
||||
worldGenerated = false;
|
||||
slivers = new AtomicSliver[256];
|
||||
@ -43,6 +51,32 @@ public class AtomicSliverMap
|
||||
}
|
||||
}
|
||||
|
||||
public void setStructure(int y, IrisStructure s, IrisStructureTile t)
|
||||
{
|
||||
structures.put(y, s.getLoadKey() + "." + s.getTiles().indexOf(t));
|
||||
}
|
||||
|
||||
public IrisStructureResult getStructure(DimensionChunkGenerator g, int y)
|
||||
{
|
||||
String v = structures.get(y);
|
||||
|
||||
if(v == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] a = v.split("\\Q.\\E");
|
||||
|
||||
IrisStructure s = g.getData().getStructureLoader().load(a[0]);
|
||||
|
||||
if(s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new IrisStructureResult(s.getTiles().get(Integer.valueOf(a[1])), s);
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException
|
||||
{
|
||||
DataOutputStream dos = new DataOutputStream(out);
|
||||
@ -53,6 +87,33 @@ public class AtomicSliverMap
|
||||
slivers[i].write(dos);
|
||||
}
|
||||
|
||||
KList<String> structurePalette = new KList<>();
|
||||
|
||||
for(Integer i : structures.k())
|
||||
{
|
||||
String struct = structures.get(i);
|
||||
|
||||
if(!structurePalette.contains(struct))
|
||||
{
|
||||
structurePalette.add(struct);
|
||||
}
|
||||
}
|
||||
|
||||
dos.writeByte(structurePalette.size() + Byte.MIN_VALUE);
|
||||
|
||||
for(String i : structurePalette)
|
||||
{
|
||||
dos.writeUTF(i);
|
||||
}
|
||||
|
||||
dos.writeByte(structures.size() + Byte.MIN_VALUE);
|
||||
|
||||
for(Integer i : structures.k())
|
||||
{
|
||||
dos.writeByte(i + Byte.MIN_VALUE);
|
||||
dos.writeByte(structurePalette.indexOf(structures.get(i)) + Byte.MIN_VALUE);
|
||||
}
|
||||
|
||||
dos.flush();
|
||||
}
|
||||
|
||||
@ -74,6 +135,21 @@ public class AtomicSliverMap
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int spc = din.readByte() - Byte.MIN_VALUE;
|
||||
KList<String> spal = new KList<>();
|
||||
for(int i = 0; i < spc; i++)
|
||||
{
|
||||
spal.add(din.readUTF());
|
||||
}
|
||||
|
||||
int smc = din.readByte() - Byte.MIN_VALUE;
|
||||
structures.clear();
|
||||
|
||||
for(int i = 0; i < smc; i++)
|
||||
{
|
||||
structures.put(din.readByte() - Byte.MIN_VALUE, spal.get(din.readByte() - Byte.MIN_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
public AtomicSliver getSliver(int x, int z)
|
||||
@ -122,7 +198,7 @@ public class AtomicSliverMap
|
||||
for(int j = 0; j < 16; j++)
|
||||
{
|
||||
getSliver(i, j).inject(map.getSliver(i, j).getUpdatables());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import com.volmit.iris.object.LootMode;
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.IrisStructureResult;
|
||||
import com.volmit.iris.util.KList;
|
||||
import com.volmit.iris.util.KSet;
|
||||
import com.volmit.iris.util.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.RNG;
|
||||
|
||||
@ -81,7 +80,7 @@ public class GenLayerUpdate extends BlockPopulator
|
||||
}
|
||||
}
|
||||
|
||||
public void injectTables(KSet<IrisLootTable> list, IrisLootReference r)
|
||||
public void injectTables(KList<IrisLootTable> list, IrisLootReference r)
|
||||
{
|
||||
if(r.getMode().equals(LootMode.CLEAR) || r.getMode().equals(LootMode.REPLACE))
|
||||
{
|
||||
@ -91,15 +90,16 @@ public class GenLayerUpdate extends BlockPopulator
|
||||
list.addAll(r.getLootTables(gen));
|
||||
}
|
||||
|
||||
public KSet<IrisLootTable> getLootTables(Block b)
|
||||
public KList<IrisLootTable> getLootTables(RNG rng, Block b)
|
||||
{
|
||||
int rx = b.getX();
|
||||
int rz = b.getZ();
|
||||
IrisRegion region = gen.sampleRegion(rx, rz);
|
||||
IrisBiome biomeSurface = gen.sampleTrueBiome(rx, rz).getBiome();
|
||||
IrisBiome biomeUnder = gen.sampleTrueBiome(rx, b.getY(), rz).getBiome();
|
||||
KSet<IrisLootTable> tables = new KSet<>();
|
||||
KList<IrisLootTable> tables = new KList<IrisLootTable>();
|
||||
IrisStructureResult structure = gen.getStructure(rx, b.getY(), rz);
|
||||
double multiplier = 1D * gen.getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
|
||||
injectTables(tables, gen.getDimension().getLoot());
|
||||
injectTables(tables, region.getLoot());
|
||||
injectTables(tables, biomeSurface.getLoot());
|
||||
@ -109,20 +109,38 @@ public class GenLayerUpdate extends BlockPopulator
|
||||
{
|
||||
injectTables(tables, structure.getStructure().getLoot());
|
||||
injectTables(tables, structure.getTile().getLoot());
|
||||
multiplier *= structure.getStructure().getLoot().getMultiplier() * structure.getTile().getLoot().getMultiplier();
|
||||
}
|
||||
|
||||
if(tables.isNotEmpty())
|
||||
{
|
||||
int target = (int) Math.round(tables.size() * multiplier);
|
||||
|
||||
while(tables.size() < target && tables.isNotEmpty())
|
||||
{
|
||||
tables.add(tables.get(rng.i(tables.size() - 1)));
|
||||
}
|
||||
|
||||
while(tables.size() > target && tables.isNotEmpty())
|
||||
{
|
||||
tables.remove(rng.i(tables.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
public void addItems(boolean debug, Inventory inv, RNG rng, KSet<IrisLootTable> tables, InventorySlotType slot, int x, int y, int z)
|
||||
public void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, int x, int y, int z, int mgf)
|
||||
{
|
||||
KList<ItemStack> items = new KList<>();
|
||||
|
||||
for(int t = 0; t < gen.getDimension().getLootTries(); t++)
|
||||
{
|
||||
int b = 4;
|
||||
for(IrisLootTable i : tables)
|
||||
{
|
||||
items.addAll(i.getLoot(debug, rng.nextParallelRNG(345911 * -t), slot, x, y, z));
|
||||
b++;
|
||||
items.addAll(i.getLoot(debug, rng.nextParallelRNG(345911 * -t), slot, x, y, z, t + b + b, mgf + b));
|
||||
}
|
||||
|
||||
for(ItemStack i : items)
|
||||
@ -135,6 +153,8 @@ public class GenLayerUpdate extends BlockPopulator
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scramble(inv, rng);
|
||||
}
|
||||
|
||||
public void updateStorage(Block b, BlockData data, int rx, int rz, RNG rng)
|
||||
@ -148,12 +168,12 @@ public class GenLayerUpdate extends BlockPopulator
|
||||
|
||||
if(slot != null)
|
||||
{
|
||||
KSet<IrisLootTable> tables = getLootTables(b);
|
||||
KList<IrisLootTable> tables = getLootTables(rng.nextParallelRNG(4568111), b);
|
||||
|
||||
try
|
||||
{
|
||||
InventoryHolder m = (InventoryHolder) b.getState();
|
||||
addItems(false, m.getInventory(), rng, tables, slot, rx, b.getY(), rz);
|
||||
addItems(false, m.getInventory(), rng, tables, slot, rx, b.getY(), rz, 15);
|
||||
}
|
||||
|
||||
catch(Throwable e)
|
||||
@ -164,6 +184,68 @@ public class GenLayerUpdate extends BlockPopulator
|
||||
}
|
||||
}
|
||||
|
||||
private void scramble(Inventory inventory, RNG rng)
|
||||
{
|
||||
KList<ItemStack> v = new KList<>();
|
||||
|
||||
for(ItemStack i : inventory.getContents())
|
||||
{
|
||||
if(i == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
v.add(i);
|
||||
}
|
||||
|
||||
inventory.clear();
|
||||
int sz = inventory.getSize();
|
||||
int tr = 5;
|
||||
|
||||
while(v.isNotEmpty())
|
||||
{
|
||||
int slot = rng.i(0, sz - 1);
|
||||
|
||||
if(inventory.getItem(slot) == null)
|
||||
{
|
||||
tr = tr < 5 ? tr + 1 : tr;
|
||||
int pick = rng.i(0, v.size() - 1);
|
||||
ItemStack g = v.get(pick);
|
||||
|
||||
if(g.getAmount() == 1)
|
||||
{
|
||||
v.remove(pick);
|
||||
inventory.setItem(pick, g);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int portion = rng.i(1, g.getAmount() - 1);
|
||||
ItemStack port = g.clone();
|
||||
port.setAmount(portion);
|
||||
g.setAmount(g.getAmount() - portion);
|
||||
v.add(g);
|
||||
inventory.setItem(slot, port);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
tr--;
|
||||
}
|
||||
|
||||
if(tr <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(ItemStack i : v)
|
||||
{
|
||||
inventory.addItem(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLight(Block b, BlockData data)
|
||||
{
|
||||
b.setType(Material.AIR, false);
|
||||
|
157
src/main/java/com/volmit/iris/gen/parallax/ParallaxChunk.java
Normal file
157
src/main/java/com/volmit/iris/gen/parallax/ParallaxChunk.java
Normal file
@ -0,0 +1,157 @@
|
||||
package com.volmit.iris.gen.parallax;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.gen.atomics.AtomicSliver;
|
||||
import com.volmit.iris.util.Writable;
|
||||
|
||||
public class ParallaxChunk implements Writable
|
||||
{
|
||||
private static final ParallaxSection EMPTY = new ParallaxSection();
|
||||
private final ParallaxSection[] sections;
|
||||
private boolean parallaxGenerated;
|
||||
private boolean worldGenerated;
|
||||
|
||||
public ParallaxChunk(DataInputStream in) throws IOException
|
||||
{
|
||||
this();
|
||||
read(in);
|
||||
}
|
||||
|
||||
public ParallaxChunk()
|
||||
{
|
||||
parallaxGenerated = false;
|
||||
worldGenerated = false;
|
||||
sections = new ParallaxSection[16];
|
||||
}
|
||||
|
||||
public boolean isParallaxGenerated()
|
||||
{
|
||||
return parallaxGenerated;
|
||||
}
|
||||
|
||||
public void setParallaxGenerated(boolean parallaxGenerated)
|
||||
{
|
||||
this.parallaxGenerated = parallaxGenerated;
|
||||
}
|
||||
|
||||
public boolean isWorldGenerated()
|
||||
{
|
||||
return worldGenerated;
|
||||
}
|
||||
|
||||
public void setWorldGenerated(boolean worldGenerated)
|
||||
{
|
||||
this.worldGenerated = worldGenerated;
|
||||
}
|
||||
|
||||
public void export(ChunkData d)
|
||||
{
|
||||
for(ParallaxSection i : sections)
|
||||
{
|
||||
if(i != null)
|
||||
{
|
||||
for(int x = 0; x < 16; x++)
|
||||
{
|
||||
for(int y = 0; y < 16; y++)
|
||||
{
|
||||
for(int z = 0; z < 16; z++)
|
||||
{
|
||||
BlockData b = get(x, y, z);
|
||||
|
||||
if(b == null || b.getMaterial().equals(Material.AIR))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
d.setBlock(x, y, z, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void injectUpdates(AtomicSliver sliver, int x, int z)
|
||||
{
|
||||
for(Integer i : sliver.getUpdatables())
|
||||
{
|
||||
if(i > 255 || i < 0)
|
||||
{
|
||||
Iris.warn("Block Update out of bounds: " + i);
|
||||
}
|
||||
|
||||
getSection(i >> 4, true).update(x, i, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream o) throws IOException
|
||||
{
|
||||
o.writeBoolean(isParallaxGenerated());
|
||||
o.writeBoolean(isWorldGenerated());
|
||||
|
||||
for(int i = 15; i > 0; i--)
|
||||
{
|
||||
ParallaxSection c = sections[i];
|
||||
|
||||
if(c != null)
|
||||
{
|
||||
o.writeBoolean(true);
|
||||
c.write(o);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
o.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream i) throws IOException
|
||||
{
|
||||
setParallaxGenerated(i.readBoolean());
|
||||
setWorldGenerated(i.readBoolean());
|
||||
|
||||
for(int iv = 15; iv > 0; iv--)
|
||||
{
|
||||
if(i.readBoolean())
|
||||
{
|
||||
sections[iv] = new ParallaxSection(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockData get(int x, int y, int z)
|
||||
{
|
||||
return getSection(y >> 4, false).getBlock(x, y & 15, z);
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, BlockData d)
|
||||
{
|
||||
getSection(y >> 4, true).setBlock(x, y & 15, z, d);
|
||||
}
|
||||
|
||||
private final ParallaxSection getSection(int y, boolean create)
|
||||
{
|
||||
if(sections[y] == null)
|
||||
{
|
||||
if(create)
|
||||
{
|
||||
sections[y] = new ParallaxSection();
|
||||
}
|
||||
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
return sections[y];
|
||||
}
|
||||
}
|
128
src/main/java/com/volmit/iris/gen/parallax/ParallaxRegion.java
Normal file
128
src/main/java/com/volmit/iris/gen/parallax/ParallaxRegion.java
Normal file
@ -0,0 +1,128 @@
|
||||
package com.volmit.iris.gen.parallax;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import com.volmit.iris.IrisSettings;
|
||||
import com.volmit.iris.util.CustomOutputStream;
|
||||
import com.volmit.iris.util.M;
|
||||
import com.volmit.iris.util.Writable;
|
||||
|
||||
public class ParallaxRegion implements Writable
|
||||
{
|
||||
private static final ParallaxChunk EMPTY = new ParallaxChunk();
|
||||
private ParallaxChunk[] chunks;
|
||||
private transient long last;
|
||||
|
||||
public ParallaxRegion(File i) throws IOException
|
||||
{
|
||||
this();
|
||||
|
||||
if(i.exists())
|
||||
{
|
||||
FileInputStream in = new FileInputStream(i);
|
||||
GZIPInputStream vin = new GZIPInputStream(in);
|
||||
DataInputStream min = new DataInputStream(vin);
|
||||
read(min);
|
||||
min.close();
|
||||
}
|
||||
}
|
||||
|
||||
public ParallaxRegion(DataInputStream i) throws IOException
|
||||
{
|
||||
this();
|
||||
read(i);
|
||||
}
|
||||
|
||||
public ParallaxRegion()
|
||||
{
|
||||
last = M.ms();
|
||||
chunks = new ParallaxChunk[1024];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream o) throws IOException
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
for(ParallaxChunk i : chunks)
|
||||
{
|
||||
if(i != null)
|
||||
{
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
o.writeShort(c);
|
||||
|
||||
for(int i = 0; i < 1024; i++)
|
||||
{
|
||||
ParallaxChunk ch = chunks[i];
|
||||
if(ch != null)
|
||||
{
|
||||
ch.write(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write(File file) throws IOException
|
||||
{
|
||||
file.getParentFile().mkdirs();
|
||||
FileOutputStream o = new FileOutputStream(file);
|
||||
CustomOutputStream g = new CustomOutputStream(o, IrisSettings.get().parallaxCompressionLevel);
|
||||
DataOutputStream d = new DataOutputStream(g);
|
||||
write(d);
|
||||
d.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream i) throws IOException
|
||||
{
|
||||
int v = i.readShort();
|
||||
|
||||
for(int b = 0; b < v; b++)
|
||||
{
|
||||
chunks[b] = new ParallaxChunk(i);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOlderThan(long time)
|
||||
{
|
||||
return M.ms() - time > last;
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, BlockData d)
|
||||
{
|
||||
getChunk(x >> 4, z >> 4, true).set(x & 15, y, z & 15, d);
|
||||
}
|
||||
|
||||
public BlockData get(int x, int y, int z)
|
||||
{
|
||||
return getChunk(x >> 4, z >> 4, false).get(x & 15, y, z & 15);
|
||||
}
|
||||
|
||||
private final ParallaxChunk getChunk(int x, int z, boolean create)
|
||||
{
|
||||
last = M.ms();
|
||||
int v = (z << 5) | x;
|
||||
|
||||
if(chunks[v] == null)
|
||||
{
|
||||
if(create)
|
||||
{
|
||||
chunks[v] = new ParallaxChunk();
|
||||
}
|
||||
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
return chunks[v];
|
||||
}
|
||||
}
|
103
src/main/java/com/volmit/iris/gen/parallax/ParallaxSection.java
Normal file
103
src/main/java/com/volmit/iris/gen/parallax/ParallaxSection.java
Normal file
@ -0,0 +1,103 @@
|
||||
package com.volmit.iris.gen.parallax;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.DataPalette;
|
||||
import com.volmit.iris.util.KSet;
|
||||
import com.volmit.iris.util.Writable;
|
||||
|
||||
public class ParallaxSection implements Writable
|
||||
{
|
||||
private final DataPalette<BlockData> block;
|
||||
private final KSet<Short> updates;
|
||||
|
||||
public ParallaxSection(DataInputStream in) throws IOException
|
||||
{
|
||||
this();
|
||||
read(in);
|
||||
}
|
||||
|
||||
public ParallaxSection()
|
||||
{
|
||||
updates = new KSet<Short>();
|
||||
this.block = new DataPalette<BlockData>(B.get("AIR"))
|
||||
{
|
||||
@Override
|
||||
public void writeType(BlockData t, DataOutputStream o) throws IOException
|
||||
{
|
||||
o.writeUTF(t.getAsString(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData readType(DataInputStream i) throws IOException
|
||||
{
|
||||
return B.get(i.readUTF());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void clearUpdates()
|
||||
{
|
||||
updates.clear();
|
||||
}
|
||||
|
||||
public void update(int x, int y, int z)
|
||||
{
|
||||
updates.add((short) (y << 8 | z << 4 | x));
|
||||
}
|
||||
|
||||
public void dontUpdate(int x, int y, int z)
|
||||
{
|
||||
updates.remove((short) (y << 8 | z << 4 | x));
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, BlockData d)
|
||||
{
|
||||
block.set(x, y, z, d);
|
||||
|
||||
if(B.isUpdatable(d))
|
||||
{
|
||||
update(x, y, z);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
dontUpdate(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
public BlockData getBlock(int x, int y, int z)
|
||||
{
|
||||
return block.get(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream o) throws IOException
|
||||
{
|
||||
block.write(o);
|
||||
o.writeShort(updates.size());
|
||||
|
||||
for(Short i : updates)
|
||||
{
|
||||
o.writeShort(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream i) throws IOException
|
||||
{
|
||||
block.read(i);
|
||||
updates.clear();
|
||||
int m = i.readShort();
|
||||
|
||||
for(int v = 0; v < m; v++)
|
||||
{
|
||||
updates.add(i.readShort());
|
||||
}
|
||||
}
|
||||
}
|
121
src/main/java/com/volmit/iris/gen/parallax/ParallaxWorld.java
Normal file
121
src/main/java/com/volmit/iris/gen/parallax/ParallaxWorld.java
Normal file
@ -0,0 +1,121 @@
|
||||
package com.volmit.iris.gen.parallax;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.KMap;
|
||||
|
||||
public class ParallaxWorld
|
||||
{
|
||||
private final KMap<Long, ParallaxRegion> loadedRegions;
|
||||
private final File dataFolder;
|
||||
|
||||
public ParallaxWorld(File dataFolder)
|
||||
{
|
||||
loadedRegions = new KMap<>();
|
||||
this.dataFolder = dataFolder;
|
||||
}
|
||||
|
||||
public void unloadAll()
|
||||
{
|
||||
for(long i : loadedRegions.k())
|
||||
{
|
||||
try
|
||||
{
|
||||
unload(i);
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
Iris.error("Failed to save region " + i);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clean(long time)
|
||||
{
|
||||
for(long i : loadedRegions.k())
|
||||
{
|
||||
ParallaxRegion r = loadedRegions.get(i);
|
||||
|
||||
if(r.isOlderThan(time))
|
||||
{
|
||||
try
|
||||
{
|
||||
unload(i);
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
Iris.error("Failed to save region " + i);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unload(long i) throws IOException
|
||||
{
|
||||
ParallaxRegion r = loadedRegions.get(i);
|
||||
r.write(new File(dataFolder, i + ".plx"));
|
||||
loadedRegions.remove(i);
|
||||
}
|
||||
|
||||
public BlockData getBlock(int x, int y, int z)
|
||||
{
|
||||
if(y > 255 || y < 0)
|
||||
{
|
||||
throw new IllegalArgumentException(y + " exceeds 0-255");
|
||||
}
|
||||
|
||||
return getRegion(x >> 5, z >> 5).get(x & 511, y, z & 511);
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, BlockData d)
|
||||
{
|
||||
if(d == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Block data cannot be null");
|
||||
}
|
||||
|
||||
if(y > 255 || y < 0)
|
||||
{
|
||||
throw new IllegalArgumentException(y + " exceeds 0-255");
|
||||
}
|
||||
|
||||
getRegion(x >> 5, z >> 5).set(x & 511, y, z & 511, d);
|
||||
}
|
||||
|
||||
public ParallaxRegion getRegion(int x, int z)
|
||||
{
|
||||
Long vb = (((long) x) << 32) | (z & 0xffffffffL);
|
||||
File ff = new File(dataFolder, vb + ".plx");
|
||||
|
||||
return loadedRegions.compute(vb, (k, v) ->
|
||||
{
|
||||
if(k == null || v == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ParallaxRegion(ff);
|
||||
}
|
||||
|
||||
catch(IOException e)
|
||||
{
|
||||
Iris.error("Failed to load parallax file: " + ff.getAbsolutePath() + " Assuming empty region!");
|
||||
ff.deleteOnExit();
|
||||
ff.delete();
|
||||
return new ParallaxRegion();
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
});
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import com.volmit.iris.util.ArrayType;
|
||||
import com.volmit.iris.util.Desc;
|
||||
import com.volmit.iris.util.DontObfuscate;
|
||||
import com.volmit.iris.util.KList;
|
||||
import com.volmit.iris.util.MinNumber;
|
||||
import com.volmit.iris.util.RegistryListLoot;
|
||||
|
||||
import lombok.Data;
|
||||
@ -24,6 +25,11 @@ public class IrisLootReference
|
||||
@Desc("Add loot table registries here")
|
||||
private KList<String> tables = new KList<>();
|
||||
|
||||
@MinNumber(0)
|
||||
@DontObfuscate
|
||||
@Desc("Increase the chance of loot in this area")
|
||||
private double multiplier = 1D;
|
||||
|
||||
private transient AtomicCache<KList<IrisLootTable>> tt = new AtomicCache<>();
|
||||
|
||||
public IrisLootReference()
|
||||
|
@ -27,12 +27,17 @@ public class IrisLootTable extends IrisRegistrant
|
||||
@Desc("The rarity as in 1 in X chance")
|
||||
private int rarity = 1;
|
||||
|
||||
@MinNumber(1)
|
||||
@DontObfuscate
|
||||
@Desc("The maximum amount of loot that can be picked in this table at a time.")
|
||||
private int maxPicked = 3;
|
||||
|
||||
@DontObfuscate
|
||||
@Desc("The loot in this table")
|
||||
@ArrayType(min = 1, type = IrisLoot.class)
|
||||
private KList<IrisLoot> loot = new KList<>();
|
||||
|
||||
public KList<ItemStack> getLoot(boolean debug, RNG rng, InventorySlotType slot, int x, int y, int z)
|
||||
public KList<ItemStack> getLoot(boolean debug, RNG rng, InventorySlotType slot, int x, int y, int z, int gg, int ffs)
|
||||
{
|
||||
KList<ItemStack> lootf = new KList<>();
|
||||
|
||||
@ -42,7 +47,7 @@ public class IrisLootTable extends IrisRegistrant
|
||||
{
|
||||
if(i.getSlotTypes().equals(slot))
|
||||
{
|
||||
ItemStack item = i.get(debug, this, rng.nextParallelRNG(294788 + x + y - z * z + (m * -4125)), x, y, z);
|
||||
ItemStack item = i.get(debug, this, rng, x, y, z);
|
||||
|
||||
if(item != null)
|
||||
{
|
||||
@ -51,6 +56,11 @@ public class IrisLootTable extends IrisRegistrant
|
||||
}
|
||||
|
||||
m++;
|
||||
|
||||
if(m > maxPicked)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lootf;
|
||||
|
@ -8,6 +8,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -17,6 +18,7 @@ import org.bukkit.block.data.type.Leaves;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import com.volmit.iris.util.B;
|
||||
import com.volmit.iris.util.BlockPosition;
|
||||
import com.volmit.iris.util.ChunkPosition;
|
||||
import com.volmit.iris.util.IObjectPlacer;
|
||||
import com.volmit.iris.util.KMap;
|
||||
@ -127,7 +129,12 @@ public class IrisObject extends IrisRegistrant
|
||||
place(x, -1, z, placer, config, rng);
|
||||
}
|
||||
|
||||
public void place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng)
|
||||
public int place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng)
|
||||
{
|
||||
return place(x, yv, z, placer, config, rng, null);
|
||||
}
|
||||
|
||||
public int place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, Consumer<BlockPosition> listener)
|
||||
{
|
||||
int spinx = rng.imax() / 1000;
|
||||
int spiny = rng.imax() / 1000;
|
||||
@ -135,7 +142,6 @@ public class IrisObject extends IrisRegistrant
|
||||
int rty = config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY();
|
||||
int ty = config.getTranslate().translate(new BlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY();
|
||||
int y = -1;
|
||||
KMap<ChunkPosition, Integer> paintmap = null;
|
||||
|
||||
if(yv < 0)
|
||||
{
|
||||
@ -233,7 +239,6 @@ public class IrisObject extends IrisRegistrant
|
||||
else if(config.getMode().equals(ObjectPlaceMode.PAINT))
|
||||
{
|
||||
y = placer.getHighest(x, z, config.isUnderwater()) + rty;
|
||||
paintmap = new KMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,18 +258,18 @@ public class IrisObject extends IrisRegistrant
|
||||
{
|
||||
if(!config.isUnderwater() && !config.isOnwater() && placer.isUnderwater(x, z))
|
||||
{
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(config.isUnderwater() && y + rty + ty >= placer.getFluidHeight())
|
||||
{
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!config.getClamp().canPlace(y + rty + ty, y - rty + ty))
|
||||
{
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(config.isBore())
|
||||
@ -309,17 +314,9 @@ public class IrisObject extends IrisRegistrant
|
||||
int yy = y + (int) Math.round(i.getY());
|
||||
int zz = z + (int) Math.round(i.getZ());
|
||||
|
||||
if(config.getMode().equals(ObjectPlaceMode.PAINT))
|
||||
if(yv < 0 && config.getMode().equals(ObjectPlaceMode.PAINT))
|
||||
{
|
||||
yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + paintmap.compute(new ChunkPosition(xx, zz), (k, v) ->
|
||||
{
|
||||
if(k == null || v == null)
|
||||
{
|
||||
return placer.getHighest(xx, zz, config.isUnderwater());
|
||||
}
|
||||
|
||||
return v;
|
||||
});
|
||||
yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + placer.getHighest(xx, zz, config.isUnderwater());
|
||||
}
|
||||
|
||||
if(heightmap != null)
|
||||
@ -347,6 +344,11 @@ public class IrisObject extends IrisRegistrant
|
||||
((Waterlogged) data).setWaterlogged(true);
|
||||
}
|
||||
|
||||
if(listener != null)
|
||||
{
|
||||
listener.accept(new BlockPosition(xx, yy, zz));
|
||||
}
|
||||
|
||||
placer.set(xx, yy, zz, data);
|
||||
}
|
||||
|
||||
@ -373,6 +375,8 @@ public class IrisObject extends IrisRegistrant
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
public void place(Location at)
|
||||
|
@ -147,7 +147,7 @@ public class IrisStructurePlacement
|
||||
}
|
||||
|
||||
o = o != null ? o : load(g, t.getTile().getObjects().get(rnp.nextInt(t.getTile().getObjects().size())));
|
||||
o.place(Math.floorDiv(i, s) * s, height == -1 ? -1 : h, Math.floorDiv(j, s) * s, g, t.getPlacement(), rng);
|
||||
o.place(Math.floorDiv(i, s) * s, height == -1 ? -1 : h, Math.floorDiv(j, s) * s, g, t.getPlacement(), rng, (gg) -> g.getParallaxChunk(gg.getChunkX(), gg.getChunkZ()).setStructure(gg.getY(), t.getStructure(), t.getTile()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,6 @@ public class IrisStructureTile
|
||||
private KList<String> objects = new KList<>();
|
||||
|
||||
@RegistryListObject
|
||||
@Required
|
||||
@ArrayType(min = 1, type = IrisRareObject.class)
|
||||
@DontObfuscate
|
||||
@Desc("List of objects to place centered in this tile but with rarity. These items only place some of the time so specify objects for common stuff too.")
|
||||
|
125
src/main/java/com/volmit/iris/util/DataPalette.java
Normal file
125
src/main/java/com/volmit/iris/util/DataPalette.java
Normal file
@ -0,0 +1,125 @@
|
||||
package com.volmit.iris.util;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class DataPalette<T> implements Writable
|
||||
{
|
||||
private static final int DEFAULT_BITS_PER_BLOCK = 4;
|
||||
private static final int CAPACITY = 4096;
|
||||
private int bpb;
|
||||
private NibbleArray data;
|
||||
private KList<T> palette;
|
||||
|
||||
public DataPalette(T defaultValue)
|
||||
{
|
||||
palette = new KList<>();
|
||||
bpb = DEFAULT_BITS_PER_BLOCK;
|
||||
data = new NibbleArray(bpb, CAPACITY);
|
||||
data.setAll(Byte.MIN_VALUE);
|
||||
getPaletteId(defaultValue);
|
||||
}
|
||||
|
||||
public abstract T readType(DataInputStream i) throws IOException;
|
||||
|
||||
public abstract void writeType(T t, DataOutputStream o) throws IOException;
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream o) throws IOException
|
||||
{
|
||||
o.writeByte(bpb + Byte.MIN_VALUE);
|
||||
o.writeByte(palette.size() + Byte.MIN_VALUE);
|
||||
|
||||
for(T i : palette)
|
||||
{
|
||||
writeType(i, o);
|
||||
}
|
||||
|
||||
data.write(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream i) throws IOException
|
||||
{
|
||||
bpb = i.readByte() - Byte.MIN_VALUE;
|
||||
palette = new KList<>();
|
||||
int v = i.readByte() - Byte.MIN_VALUE;
|
||||
|
||||
for(int j = 0; j < v; j++)
|
||||
{
|
||||
palette.add(readType(i));
|
||||
}
|
||||
|
||||
data = new NibbleArray(CAPACITY, i);
|
||||
}
|
||||
|
||||
private final void expand()
|
||||
{
|
||||
if(bpb < 8)
|
||||
{
|
||||
changeBitsPerBlock(bpb + 1);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
throw new IndexOutOfBoundsException("The Data Palette can only handle at most 256 block types per 16x16x16 region. We cannot use more than 8 bits per block!");
|
||||
}
|
||||
}
|
||||
|
||||
public final void optimize()
|
||||
{
|
||||
int targetBits = bpb;
|
||||
int needed = palette.size();
|
||||
|
||||
for(int i = 1; i < bpb; i++)
|
||||
{
|
||||
if(Math.pow(2, i) > needed)
|
||||
{
|
||||
targetBits = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
changeBitsPerBlock(targetBits);
|
||||
}
|
||||
|
||||
private final void changeBitsPerBlock(int bits)
|
||||
{
|
||||
bpb = bits;
|
||||
data = new NibbleArray(bpb, CAPACITY, data);
|
||||
}
|
||||
|
||||
public final void set(int x, int y, int z, T d)
|
||||
{
|
||||
data.set(getCoordinateIndex(x, y, z), getPaletteId(d));
|
||||
}
|
||||
|
||||
public final T get(int x, int y, int z)
|
||||
{
|
||||
return palette.get(data.get(getCoordinateIndex(x, y, z)));
|
||||
}
|
||||
|
||||
private final int getPaletteId(T d)
|
||||
{
|
||||
int index = palette.indexOf(d);
|
||||
|
||||
if(index == -1)
|
||||
{
|
||||
index = palette.size();
|
||||
palette.add(d);
|
||||
|
||||
if(palette.size() > Math.pow(2, bpb))
|
||||
{
|
||||
expand();
|
||||
}
|
||||
}
|
||||
|
||||
return index + Byte.MIN_VALUE;
|
||||
}
|
||||
|
||||
private final int getCoordinateIndex(int x, int y, int z)
|
||||
{
|
||||
return y << 8 | z << 4 | x;
|
||||
}
|
||||
}
|
212
src/main/java/com/volmit/iris/util/NibbleArray.java
Normal file
212
src/main/java/com/volmit/iris/util/NibbleArray.java
Normal file
@ -0,0 +1,212 @@
|
||||
package com.volmit.iris.util;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public class NibbleArray implements Writable
|
||||
{
|
||||
private byte[] data;
|
||||
private int depth;
|
||||
private final int size;
|
||||
private byte mask;
|
||||
private final Object lock = new Object();
|
||||
|
||||
public NibbleArray(int capacity, DataInputStream in) throws IOException
|
||||
{
|
||||
size = capacity;
|
||||
read(in);
|
||||
}
|
||||
|
||||
public NibbleArray(int nibbleDepth, int capacity)
|
||||
{
|
||||
if(nibbleDepth > 8 || nibbleDepth < 1)
|
||||
{
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
int neededBits = nibbleDepth * capacity;
|
||||
|
||||
size = capacity;
|
||||
depth = nibbleDepth;
|
||||
data = new byte[(neededBits + neededBits % 8) / 8];
|
||||
mask = (byte) maskFor(nibbleDepth);
|
||||
}
|
||||
|
||||
public NibbleArray(int nibbleDepth, int capacity, NibbleArray existing)
|
||||
{
|
||||
if(nibbleDepth > 8 || nibbleDepth < 1)
|
||||
{
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
int neededBits = nibbleDepth * capacity;
|
||||
size = capacity;
|
||||
depth = nibbleDepth;
|
||||
data = new byte[(neededBits + neededBits % 8) / 8];
|
||||
mask = (byte) maskFor(nibbleDepth);
|
||||
|
||||
for(int i = 0; i < Math.min(size, existing.size()); i++)
|
||||
{
|
||||
set(i, existing.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream o) throws IOException
|
||||
{
|
||||
o.writeByte(depth + Byte.MIN_VALUE);
|
||||
o.write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream i) throws IOException
|
||||
{
|
||||
depth = i.readByte() - Byte.MIN_VALUE;
|
||||
int neededBits = depth * size;
|
||||
data = new byte[(neededBits + neededBits % 8) / 8];
|
||||
mask = (byte) maskFor(depth);
|
||||
i.read(data);
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public byte get(int index)
|
||||
{
|
||||
synchronized(lock)
|
||||
{
|
||||
bitIndex = index * depth;
|
||||
byteIndex = bitIndex >> 3;
|
||||
bitInByte = bitIndex & 7;
|
||||
int value = data[byteIndex] >> bitInByte;
|
||||
|
||||
if(bitInByte + depth > 8)
|
||||
{
|
||||
value |= data[byteIndex + 1] << bitInByte;
|
||||
}
|
||||
|
||||
return (byte) (value & mask);
|
||||
}
|
||||
}
|
||||
|
||||
public byte getAsync(int index)
|
||||
{
|
||||
int bitIndex = index * depth;
|
||||
int byteIndex = bitIndex >> 3;
|
||||
int bitInByte = bitIndex & 7;
|
||||
int value = data[byteIndex] >> bitInByte;
|
||||
|
||||
if(bitInByte + depth > 8)
|
||||
{
|
||||
value |= data[byteIndex + 1] << bitInByte;
|
||||
}
|
||||
|
||||
return (byte) (value & mask);
|
||||
}
|
||||
|
||||
private transient int bitIndex, byteIndex, bitInByte;
|
||||
|
||||
public void set(int index, int nibble)
|
||||
{
|
||||
set(index, (byte) nibble);
|
||||
}
|
||||
|
||||
public void set(int index, byte nybble)
|
||||
{
|
||||
synchronized(lock)
|
||||
{
|
||||
bitIndex = index * depth;
|
||||
byteIndex = bitIndex >> 3;
|
||||
bitInByte = bitIndex & 7;
|
||||
data[byteIndex] = (byte) (((~(data[byteIndex] & (mask << bitInByte)) & data[byteIndex]) | ((nybble & mask) << bitInByte)) & 0xff);
|
||||
|
||||
if(bitInByte + depth > 8)
|
||||
{
|
||||
data[byteIndex + 1] = (byte) (((~(data[byteIndex + 1] & MASKS[bitInByte + depth - 8]) & data[byteIndex + 1]) | ((nybble & mask) >> (8 - bitInByte))) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toBitsString()
|
||||
{
|
||||
return toBitsString(ByteOrder.BIG_ENDIAN);
|
||||
}
|
||||
|
||||
public String toBitsString(ByteOrder byteOrder)
|
||||
{
|
||||
StringJoiner joiner = new StringJoiner(" ");
|
||||
|
||||
for(int i = 0; i < data.length; i++)
|
||||
{
|
||||
joiner.add(binaryString(data[i], byteOrder));
|
||||
}
|
||||
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
Arrays.fill(data, (byte) 0);
|
||||
}
|
||||
|
||||
public void setAll(byte nibble)
|
||||
{
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
set(i, nibble);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAll(int nibble)
|
||||
{
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
set(i, (byte) nibble);
|
||||
}
|
||||
}
|
||||
|
||||
public static int maskFor(int amountOfBits)
|
||||
{
|
||||
return powerOfTwo(amountOfBits) - 1;
|
||||
}
|
||||
|
||||
public static int powerOfTwo(int power)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
for(int i = 0; i < power; i++)
|
||||
{
|
||||
result *= 2;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final int[] MASKS = new int[8];
|
||||
|
||||
static
|
||||
{
|
||||
for(int i = 0; i < MASKS.length; i++)
|
||||
{
|
||||
MASKS[i] = maskFor(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static String binaryString(byte b, ByteOrder byteOrder)
|
||||
{
|
||||
String str = String.format("%8s", Integer.toBinaryString(b & 0xff)).replace(' ', '0');
|
||||
|
||||
return byteOrder.equals(ByteOrder.BIG_ENDIAN) ? str : reverse(str);
|
||||
}
|
||||
|
||||
public static String reverse(String str)
|
||||
{
|
||||
return new StringBuilder(str).reverse().toString();
|
||||
}
|
||||
}
|
12
src/main/java/com/volmit/iris/util/Writable.java
Normal file
12
src/main/java/com/volmit/iris/util/Writable.java
Normal file
@ -0,0 +1,12 @@
|
||||
package com.volmit.iris.util;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface Writable
|
||||
{
|
||||
public void write(DataOutputStream o) throws IOException;
|
||||
|
||||
public void read(DataInputStream i) throws IOException;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user