Begin work on serialization, improve structure performance.

This commit is contained in:
dfsek 2020-09-27 01:36:06 -07:00
parent 5669a0e9c4
commit 81d607b900
22 changed files with 416 additions and 148 deletions

View File

@ -1,63 +0,0 @@
package com.dfsek.terra;
import org.bukkit.Chunk;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.Random;
public class MaxMin implements Iterable<Integer> {
private final int min;
private final int max;
public MaxMin(int min, int max) {
this.max = max;
this.min = min;
}
public boolean isInRange(int test) {
return test >= min && test < max;
}
public int getMax() {
return max;
}
public int getMin() {
return min;
}
public int get(Random r) {
return r.nextInt((max-min)+1)+min;
}
@Override
public String toString() {
return "Min: " + getMin() + " Max:" + getMax();
}
@NotNull
@Override
public Iterator<Integer> iterator() {
return new MaxMinIterator(this);
}
private static class MaxMinIterator implements Iterator<Integer> {
private Integer current;
private final MaxMin m;
public MaxMinIterator(MaxMin m) {
this.m = m;
current = m.getMin();
}
@Override
public boolean hasNext() {
return current < m.getMax();
}
@Override
public Integer next() {
current++;
return current - 1;
}
}
}

View File

@ -0,0 +1,95 @@
package com.dfsek.terra;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.Random;
public class Range implements Iterable<Integer> {
private int min;
private int max;
public Range(int min, int max) {
if(min > max) throw new IllegalArgumentException("Minimum must not be grater than maximum!");
this.max = max;
this.min = min;
}
public boolean isInRange(int test) {
return test >= min && test < max;
}
public int getMax() {
return max;
}
public int getMin() {
return min;
}
public int get(Random r) {
return r.nextInt((max-min)+1)+min;
}
public Range intersects(Range other) {
try {
return new Range(Math.max(this.getMin(), other.getMin()), Math.min(this.getMax(), other.getMax()));
} catch(IllegalArgumentException e) {
return null;
}
}
public Range add(int add) {
this.min += add;
this.max += add;
return this;
}
public Range sub(int sub) {
this.min -= sub;
this.max -= sub;
return this;
}
@Override
public String toString() {
return "Min: " + getMin() + ", Max:" + getMax();
}
@Override
public int hashCode() {
return min * 31 + max;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Range)) return false;
Range other = (Range) obj;
return other.getMin() == this.getMin() && other.getMax() == this.getMax();
}
@NotNull
@Override
public Iterator<Integer> iterator() {
return new RangeIterator(this);
}
private static class RangeIterator implements Iterator<Integer> {
private Integer current;
private final Range m;
public RangeIterator(Range m) {
this.m = m;
current = m.getMin();
}
@Override
public boolean hasNext() {
return current < m.getMax();
}
@Override
public Integer next() {
current++;
return current - 1;
}
}
}

View File

@ -180,7 +180,7 @@ public class TerraCommand implements CommandExecutor, TabExecutor {
try {
GaeaStructure struc = GaeaStructure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[2] + ".tstructure"));
if("true".equals(args[3])) struc.paste(pl.getLocation());
//else struc.paste(pl.getLocation(), pl.getLocation().getChunk());
else struc.paste(pl.getLocation(), pl.getLocation().getChunk());
} catch(IOException e) {
e.printStackTrace();
sender.sendMessage("Structure not found.");

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.carving;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.Range;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.genconfig.BiomeConfig;
@ -15,12 +15,12 @@ public class UserDefinedCarver extends Carver {
private final double[] start; // 0, 1, 2 = x, y, z.
private final double[] mutate; // 0, 1, 2 = x, y, z. 3 = radius.
private final double[] radiusMultiplier;
private final MaxMin length;
private final MaxMin radius;
private final Range length;
private final Range radius;
private final int hash;
private final int topCut;
private final int bottomCut;
public UserDefinedCarver(MaxMin height, MaxMin radius, MaxMin length, double[] start, double[] mutate, double[] radiusMultiplier, int hash, int topCut, int bottomCut) {
public UserDefinedCarver(Range height, Range radius, Range length, double[] start, double[] mutate, double[] radiusMultiplier, int hash, int topCut, int bottomCut) {
super(height.getMin(), height.getMax());
this.radius = radius;
this.length = length;

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.Range;
import com.dfsek.terra.TerraTree;
import com.dfsek.terra.config.ConfigUtil;
import com.dfsek.terra.config.TerraConfigObject;
@ -15,7 +15,6 @@ import org.polydev.gaea.tree.TreeType;
import org.polydev.gaea.world.Flora;
import org.polydev.gaea.world.FloraType;
import org.polydev.gaea.world.palette.Palette;
import org.polydev.gaea.world.palette.Palette;
import org.polydev.gaea.world.palette.RandomPalette;
import java.io.File;
@ -29,8 +28,8 @@ import java.util.TreeMap;
public class AbstractBiomeConfig extends TerraConfigObject {
private static final Map<String, AbstractBiomeConfig> biomes = new HashMap<>();
private String biomeID;
private Map<OreConfig, MaxMin> ores;
private Map<OreConfig, MaxMin> oreHeights;
private Map<OreConfig, Range> ores;
private Map<OreConfig, Range> oreHeights;
private Map<CarverConfig, Integer> carvers;
private ProbabilityCollection<Flora> flora;
private ProbabilityCollection<Tree> trees;
@ -39,7 +38,7 @@ public class AbstractBiomeConfig extends TerraConfigObject {
private int treeDensity;
private String equation;
private int floraAttempts;
private Map<Flora, MaxMin> floraHeights;
private Map<Flora, Range> floraHeights;
private TreeMap<Integer, Palette<BlockData>> paletteMap;
private double slabThreshold;
private Map<Material, Palette<BlockData>> slabs;
@ -109,13 +108,13 @@ public class AbstractBiomeConfig extends TerraConfigObject {
Bukkit.getLogger().info("[Terra] Adding " + e.getKey() + " to biome's flora list with weight " + e.getValue());
Flora floraObj = FloraType.valueOf(e.getKey());
flora.add(floraObj, (Integer) val.get("weight"));
floraHeights.put(floraObj, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
floraHeights.put(floraObj, new Range((Integer) y.get("min"), (Integer) y.get("max")));
} catch(IllegalArgumentException ex) {
try {
Bukkit.getLogger().info("[Terra] Is custom flora: true");
Flora floraCustom = FloraConfig.fromID(e.getKey());
flora.add(floraCustom, (Integer) val.get("weight"));
floraHeights.put(floraCustom, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
floraHeights.put(floraCustom, new Range((Integer) y.get("min"), (Integer) y.get("max")));
} catch(NullPointerException ex2) {
throw new InvalidConfigurationException("SEVERE configuration error for flora in biome, ID " + getID() + "\n\nFlora with ID " + e.getKey() + " cannot be found!");
}
@ -146,8 +145,8 @@ public class AbstractBiomeConfig extends TerraConfigObject {
ores = new HashMap<>();
oreHeights = new HashMap<>();
for(Map.Entry<String, Object> m : Objects.requireNonNull(getConfigurationSection("ores")).getValues(false).entrySet()) {
ores.put(OreConfig.fromID(m.getKey()), new MaxMin(((ConfigurationSection) m.getValue()).getInt("min"), ((ConfigurationSection) m.getValue()).getInt("max")));
oreHeights.put(OreConfig.fromID(m.getKey()), new MaxMin(((ConfigurationSection) m.getValue()).getInt("min-height"), ((ConfigurationSection) m.getValue()).getInt("max-height")));
ores.put(OreConfig.fromID(m.getKey()), new Range(((ConfigurationSection) m.getValue()).getInt("min"), ((ConfigurationSection) m.getValue()).getInt("max")));
oreHeights.put(OreConfig.fromID(m.getKey()), new Range(((ConfigurationSection) m.getValue()).getInt("min-height"), ((ConfigurationSection) m.getValue()).getInt("max-height")));
}
}
@ -190,15 +189,15 @@ public class AbstractBiomeConfig extends TerraConfigObject {
return carvers;
}
public Map<OreConfig, MaxMin> getOreHeights() {
public Map<OreConfig, Range> getOreHeights() {
return oreHeights;
}
public Map<OreConfig, MaxMin> getOres() {
public Map<OreConfig, Range> getOres() {
return ores;
}
public Map<Flora, MaxMin> getFloraHeights() {
public Map<Flora, Range> getFloraHeights() {
return floraHeights;
}

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.Range;
import com.dfsek.terra.TerraTree;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.generation.UserDefinedDecorator;
@ -40,10 +40,10 @@ public class BiomeConfig extends TerraConfigObject {
private UserDefinedBiome biome;
private String biomeID;
private String friendlyName;
private Map<OreConfig, MaxMin> ores;
private Map<OreConfig, MaxMin> oreHeights;
private Map<OreConfig, Range> ores;
private Map<OreConfig, Range> oreHeights;
private Map<CarverConfig, Integer> carvers;
private Map<Flora, MaxMin> floraHeights;
private Map<Flora, Range> floraHeights;
private String eq;
private int floraAttempts;
private Map<Material, Palette<BlockData>> slabs;
@ -163,13 +163,13 @@ public class BiomeConfig extends TerraConfigObject {
Bukkit.getLogger().info("[Terra] Adding " + e.getKey() + " to biome's flora list with weight " + e.getValue());
Flora floraObj = FloraType.valueOf(e.getKey());
flora.add(floraObj, (Integer) val.get("weight"));
floraHeights.put(floraObj, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
floraHeights.put(floraObj, new Range((Integer) y.get("min"), (Integer) y.get("max")));
} catch(IllegalArgumentException ex) {
try {
Bukkit.getLogger().info("[Terra] Is custom flora: true");
Flora floraCustom = FloraConfig.fromID(e.getKey());
flora.add(floraCustom, (Integer) val.get("weight"));
floraHeights.put(floraCustom, new MaxMin((Integer) y.get("min"), (Integer) y.get("max")));
floraHeights.put(floraCustom, new Range((Integer) y.get("min"), (Integer) y.get("max")));
} catch(NullPointerException ex2) {
throw new InvalidConfigurationException("SEVERE configuration error for flora in biome " + getFriendlyName() + ", ID " + getID() + "\n\nFlora with ID " + e.getKey() + " cannot be found!");
}
@ -221,8 +221,8 @@ public class BiomeConfig extends TerraConfigObject {
} else if(contains("ores")) {
ores.clear();
for(Map.Entry<String, Object> m : Objects.requireNonNull(getConfigurationSection("ores")).getValues(false).entrySet()) {
ores.put(OreConfig.fromID(m.getKey()), new MaxMin(((ConfigurationSection) m.getValue()).getInt("min"), ((ConfigurationSection) m.getValue()).getInt("max")));
oreHeights.put(OreConfig.fromID(m.getKey()), new MaxMin(((ConfigurationSection) m.getValue()).getInt("min-height"), ((ConfigurationSection) m.getValue()).getInt("max-height")));
ores.put(OreConfig.fromID(m.getKey()), new Range(((ConfigurationSection) m.getValue()).getInt("min"), ((ConfigurationSection) m.getValue()).getInt("max")));
oreHeights.put(OreConfig.fromID(m.getKey()), new Range(((ConfigurationSection) m.getValue()).getInt("min-height"), ((ConfigurationSection) m.getValue()).getInt("max-height")));
}
} else {
ores = new HashMap<>();
@ -272,7 +272,7 @@ public class BiomeConfig extends TerraConfigObject {
biomes.put(biomeID, this);
}
public MaxMin getOreHeight(OreConfig c) {
public Range getOreHeight(OreConfig c) {
return oreHeights.get(c);
}
@ -292,12 +292,12 @@ public class BiomeConfig extends TerraConfigObject {
return friendlyName;
}
public Map<OreConfig, MaxMin> getOres() {
public Map<OreConfig, Range> getOres() {
return ores;
}
public MaxMin getFloraHeights(Flora f) {
return floraHeights.computeIfAbsent(f, input -> new MaxMin(-1, -1));
public Range getFloraHeights(Flora f) {
return floraHeights.computeIfAbsent(f, input -> new Range(-1, -1));
}
public static BiomeConfig fromBiome(UserDefinedBiome b) {

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.config.genconfig;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.Range;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.TerraConfigObject;
import org.bukkit.Bukkit;
@ -126,9 +126,9 @@ public class CarverConfig extends TerraConfigObject {
double[] start = new double[] {getDouble("start.x"), getDouble("start.y"), getDouble("start.z")};
double[] mutate = new double[] {getDouble("mutate.x"), getDouble("mutate.y"), getDouble("mutate.z"), getDouble("mutate.radius")};
double[] radiusMultiplier = new double[] {getDouble("start.radius.multiply.x"), getDouble("start.radius.multiply.y"), getDouble("start.radius.multiply.z")};
MaxMin length = new MaxMin(getInt("length.min"), getInt("length.max"));
MaxMin radius = new MaxMin(getInt("start.radius.min"), getInt("start.radius.max"));
MaxMin height = new MaxMin(getInt("start.height.min"), getInt("start.height.max"));
Range length = new Range(getInt("length.min"), getInt("length.max"));
Range radius = new Range(getInt("start.radius.min"), getInt("start.radius.max"));
Range height = new Range(getInt("start.height.min"), getInt("start.height.max"));
id = getString("id");
if(id == null) throw new InvalidConfigurationException("No ID specified for Carver!");
carver = new UserDefinedCarver(height, radius, length, start, mutate, radiusMultiplier, id.hashCode(), getInt("cut.top", 0), getInt("cut.bottom", 0));

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.population;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.Range;
import com.dfsek.terra.TerraProfiler;
import com.dfsek.terra.biome.TerraBiomeGrid;
import com.dfsek.terra.biome.UserDefinedBiome;
@ -23,7 +23,7 @@ public class OrePopulator extends GaeaBlockPopulator {
try (ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) {
Location l = chunk.getBlock(8, 0, 0).getLocation();
Biome b = TerraBiomeGrid.fromWorld(world).getBiome(l.getBlockX(), l.getBlockZ());
for(Map.Entry<OreConfig, MaxMin> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
for(Map.Entry<OreConfig, Range> e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) {
int num = e.getValue().get(random);
for(int i = 0; i < num; i++) {
int x = random.nextInt(16);

View File

@ -1,11 +1,12 @@
package com.dfsek.terra.structure;
import com.dfsek.terra.MaxMin;
import com.dfsek.terra.Range;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
@ -21,7 +22,6 @@ import java.io.Serializable;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;
public class GaeaStructure implements Serializable {
public static final long serialVersionUID = -6664585217063842035L;
@ -49,23 +49,30 @@ public class GaeaStructure implements Serializable {
for(int y = 0; y <= l2.getBlockY()-l1.getBlockY(); y++) {
for(int z = 0; z <= l2.getBlockZ()-l1.getBlockZ(); z++) {
Block b = Objects.requireNonNull(l1.getWorld()).getBlockAt(l1.clone().add(x, y, z));
BlockState state = b.getState();
BlockData d = b.getBlockData();
if(d instanceof Sign) {
boolean useState = true;
if(state instanceof Sign) {
Sign s = (Sign) b.getState();
if(s.getLine(0).equals("[TERRA]")) {
d = Bukkit.createBlockData(s.getLine(2)+s.getLine(3));
if(s.getLine(1).equals("[CENTER]")) {
centerX = x;
centerZ = z;
try {
d = Bukkit.createBlockData(s.getLine(2) + s.getLine(3));
useState = false;
if(s.getLine(1).equals("[CENTER]")) {
centerX = x;
centerZ = z;
}
} catch(IllegalArgumentException e) {
throw new InitializationException("Invalid Block Data on sign: \"" + s.getLine(2) + s.getLine(3) + "\"");
}
}
}
structure[x][y][z] = new StructureContainedBlock(x, y, z, d);
structure[x][y][z] = new StructureContainedBlock(x, y, z, useState ? state : null, d);
}
}
}
if(centerX == -1 || centerZ == -1) throw new InitializationException("No structure center specified.");
structureInfo = new GaeaStructureInfo(l2.getBlockX()-l1.getBlockX(), l2.getBlockY()-l1.getBlockY(), l2.getBlockZ()-l1.getBlockZ(), centerX, centerZ);
if(centerX < 0 || centerZ < 0) throw new InitializationException("No structure center specified.");
structureInfo = new GaeaStructureInfo(l2.getBlockX()-l1.getBlockX()+1, l2.getBlockY()-l1.getBlockY()+1, l2.getBlockZ()-l1.getBlockZ()+1, centerX, centerZ);
}
@NotNull
@ -74,19 +81,28 @@ public class GaeaStructure implements Serializable {
}
public void paste(@NotNull Location origin) {
for(StructureContainedBlock[][] bList2 : structure) {
for(StructureContainedBlock[] bList1 : bList2) {
for(StructureContainedBlock block : bList1) {
BlockData data = block.getBlockData();
Block worldBlock = origin.clone().add(block.getX(), block.getY(), block.getZ()).getBlock();
if(!data.getMaterial().equals(Material.STRUCTURE_VOID)) worldBlock.setBlockData(data);
}
}
this.executeForBlocksInRange(getRange(Axis.X), getRange(Axis.Y), getRange(Axis.Z), block -> pasteBlock(block, origin));
}
public void paste(Location origin, Chunk chunk) {
int xOr = (chunk.getX() << 4);
int zOr = (chunk.getZ() << 4);
Range intersectX = new Range(xOr, xOr+16).sub(origin.getBlockX() - structureInfo.getCenterX());
Range intersectZ = new Range(zOr, zOr+16).sub(origin.getBlockZ() - structureInfo.getCenterZ());
if(intersectX == null || intersectZ == null) return;
executeForBlocksInRange(intersectX, getRange(Axis.Y), intersectZ, block -> pasteBlock(block, origin));
}
private void pasteBlock(StructureContainedBlock block, Location origin) {
BlockData data = block.getBlockData();
Block worldBlock = origin.clone().add(block.getX()-structureInfo.getCenterX(), block.getY(), block.getZ()-structureInfo.getCenterZ()).getBlock();
if(!data.getMaterial().equals(Material.STRUCTURE_VOID)) worldBlock.setBlockData(data);
if(block.getState() != null) {
block.getState().getState(worldBlock.getState()).update();
}
}
private StructureContainedBlock[][][] executeForBlocksInRange(MaxMin xM, MaxMin yM, MaxMin zM, Consumer<StructureContainedBlock> exec) {
StructureContainedBlock[][][] temp = new StructureContainedBlock[xM.getMax()-xM.getMin()+1][yM.getMax()-yM.getMin()+1][zM.getMax()-zM.getMin()+1];
private void executeForBlocksInRange(Range xM, Range yM, Range zM, Consumer<StructureContainedBlock> exec) {
for(int x : xM) {
for(int y : yM) {
for(int z : zM) {
@ -94,11 +110,10 @@ public class GaeaStructure implements Serializable {
}
}
}
return temp;
}
private boolean isInStructure(int x, int y, int z) {
return x < structure.length && y < structure[0].length && z < structure[0][0].length;
return x < structureInfo.getSizeX() && y < structureInfo.getSizeY() && z < structureInfo.getSizeZ() && x >= 0 && y >= 0 && z >= 0;
}
public void save(@NotNull File f) throws IOException {
@ -136,4 +151,20 @@ public class GaeaStructure implements Serializable {
public UUID getUuid() {
return uuid;
}
public Range getRange(Axis a) {
switch(a) {
case X:
return new Range(0, structureInfo.getSizeX());
case Y:
return new Range(0, structureInfo.getSizeY());
case Z:
return new Range(0, structureInfo.getSizeZ());
default: return null;
}
}
enum Axis {
X, Y, Z
}
}

View File

@ -1,26 +1,31 @@
package com.dfsek.terra.structure;
import com.dfsek.terra.structure.serialize.SerializableBlockData;
import com.dfsek.terra.structure.serialize.block.SerializableBlockState;
import com.dfsek.terra.structure.serialize.block.SerializableSign;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.event.block.BlockDamageEvent;
import java.io.Serializable;
public class StructureContainedBlock implements Serializable {
public static final long serialVersionUID = 6143969483382710947L;
private final transient BlockData bl;
private final String dataString;
private final SerializableBlockData bl;
private transient BlockData data;
private final int x;
private final int y;
private final int z;
public StructureContainedBlock(int x, int y, int z, BlockData block) {
private final SerializableBlockState state;
public StructureContainedBlock(int x, int y, int z, BlockState state, BlockData d) {
if(state instanceof Sign) {
this.state = new SerializableSign((org.bukkit.block.Sign) state);
} else this.state = null;
this.x = x;
this.y = y;
this.z = z;
this.bl = block;
dataString = bl.getAsString(false);
this.bl = new SerializableBlockData(d);
}
public int getX() {
@ -36,10 +41,14 @@ public class StructureContainedBlock implements Serializable {
}
public BlockData getBlockData() {
return bl == null ? Bukkit.createBlockData(dataString) : bl;
if(data == null) {
data = bl.getData();
}
return data;
}
public String getDataAsString() {
return dataString;
public SerializableBlockState getState() {
return state;
}
}

View File

@ -0,0 +1,17 @@
package com.dfsek.terra.structure.serialize;
import org.bukkit.Bukkit;
import org.bukkit.block.data.BlockData;
import java.io.Serializable;
public class SerializableBlockData implements Serializable {
public static final long serialVersionUID = 5298928608478640008L;
private final String data;
public SerializableBlockData(BlockData d) {
this.data = d.getAsString(false);
}
public BlockData getData() {
return Bukkit.createBlockData(data);
}
}

View File

@ -0,0 +1,17 @@
package com.dfsek.terra.structure.serialize;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import java.io.Serializable;
public class SerializableEnchantment implements Serializable {
public static final long serialVersionUID = 5298928608478640006L;
private final SerializableNamespacedKey enchant;
public SerializableEnchantment(Enchantment e) {
enchant = new SerializableNamespacedKey(e.getKey());
}
public Enchantment toEnchantment() {
return Enchantment.getByKey(enchant.getNamespacedKey());
}
}

View File

@ -0,0 +1,19 @@
package com.dfsek.terra.structure.serialize;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.io.Serializable;
public class SerializableInventory implements Serializable {
public static final long serialVersionUID = 5298928608478640004L;
private SerializableItemStack[] items;
public SerializableInventory(Inventory inv) {
items = new SerializableItemStack[inv.getSize()];
for(int i = 0; i < inv.getSize(); i++) {
ItemStack item = inv.getItem(i);
if(item == null) return;
items[i] = new SerializableItemStack(item);
}
}
}

View File

@ -0,0 +1,12 @@
package com.dfsek.terra.structure.serialize;
import org.bukkit.attribute.Attribute;
import org.bukkit.inventory.meta.ItemMeta;
import java.io.Serializable;
public class SerializableItemMeta implements Serializable {
public static final long serialVersionUID = 5298928608478640009L;
public SerializableItemMeta(ItemMeta meta) {
}
}

View File

@ -0,0 +1,32 @@
package com.dfsek.terra.structure.serialize;
import org.bukkit.block.BlockState;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class SerializableItemStack implements Serializable {
public static final long serialVersionUID = 5298928608478640005L;
private final HashMap<SerializableEnchantment, Integer> enchantments = new HashMap<>();
private final SerializableBlockData blockData;
private transient ItemStack stack;
private final SerializableItemMeta meta;
private final int amount;
public SerializableItemStack(ItemStack item) {
for(Map.Entry<Enchantment, Integer> e : item.getEnchantments().entrySet()) {
this.enchantments.put(new SerializableEnchantment(e.getKey()), e.getValue());
}
this.meta = new SerializableItemMeta(item.getItemMeta());
this.blockData = new SerializableBlockData(item.getType().createBlockData());
this.amount = item.getAmount();
}
public ItemStack getStack() {
if(stack == null) {
stack = new ItemStack(blockData.getData().getMaterial(), amount);
}
return stack;
}
}

View File

@ -0,0 +1,18 @@
package com.dfsek.terra.structure.serialize;
import org.bukkit.NamespacedKey;
import java.io.Serializable;
public class SerializableNamespacedKey implements Serializable {
public static final long serialVersionUID = 5298928608478640007L;
private final String namespace;
private final String key;
public SerializableNamespacedKey(NamespacedKey key) {
this.namespace = key.getNamespace();
this.key = key.getKey();
}
public NamespacedKey getNamespacedKey() {
return new NamespacedKey(namespace, key);
}
}

View File

@ -0,0 +1,10 @@
package com.dfsek.terra.structure.serialize.block;
import org.bukkit.block.BlockState;
import java.io.Serializable;
public interface SerializableBlockState extends Serializable {
long serialVersionUID = 5298928608478640000L;
BlockState getState(BlockState orig);
}

View File

@ -0,0 +1,17 @@
package com.dfsek.terra.structure.serialize.block;
import org.bukkit.block.BlockState;
import org.bukkit.inventory.Inventory;
public class SerializableChest implements SerializableContainer {
long serialVersionUID = 5298928608478640003L;
@Override
public Inventory getInventory(Inventory orig) {
return null;
}
@Override
public BlockState getState(BlockState orig) {
return null;
}
}

View File

@ -0,0 +1,8 @@
package com.dfsek.terra.structure.serialize.block;
import org.bukkit.inventory.Inventory;
public interface SerializableContainer extends SerializableBlockState {
long serialVersionUID = 5298928608478640002L;
Inventory getInventory(Inventory orig);
}

View File

@ -0,0 +1,35 @@
package com.dfsek.terra.structure.serialize.block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
public class SerializableSign implements SerializableBlockState {
public static final long serialVersionUID = 5298928608478640001L;
private final String[] text;
private final boolean isEditable;
public SerializableSign(Sign orig) {
text = orig.getLines();
this.isEditable = orig.isEditable();
}
@Override
public BlockState getState(BlockState orig) {
if(!(orig instanceof Sign)) throw new IllegalArgumentException("Provided BlockState is not a sign.");
Sign sign = (Sign) orig;
for(int i = 0; i < text.length; i++) {
sign.setLine(i, text[i]);
}
sign.setEditable(isEditable);
return sign;
}
public String[] getLines() {
return text;
}
public String getLine(int index) {
return text[index];
}
public boolean isEditable() {
return isEditable;
}
}

View File

@ -1,17 +0,0 @@
import com.dfsek.terra.MaxMin;
import org.jetbrains.annotations.TestOnly;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MaxMinTest {
@Test
public void iterator() {
MaxMin m = new MaxMin(0, 100);
int i = 0;
for(int mint : m) {
assertEquals(i, mint);
i++;
}
assertEquals(100, i);
}
}

View File

@ -0,0 +1,29 @@
import com.dfsek.terra.Range;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class RangeTest {
@Test
public void iterator() {
Range m = new Range(0, 100);
int i = 0;
for(int mint : m) {
assertEquals(i, mint);
i++;
}
assertEquals(100, i);
}
@Test
public void intersect() {
Range one = new Range(10, 100);
Range two = new Range(1, 20);
Range intersect = one.intersects(two);
assertEquals(20, intersect.getMax());
assertEquals(10, intersect.getMin());
assertEquals(one.intersects(two), two.intersects(one));
one = new Range(25, 50);
assertNull(one.intersects(two));
}
}