diff --git a/src/main/java/com/dfsek/terra/MaxMin.java b/src/main/java/com/dfsek/terra/MaxMin.java deleted file mode 100644 index 9cdc0a353..000000000 --- a/src/main/java/com/dfsek/terra/MaxMin.java +++ /dev/null @@ -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 { - 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 iterator() { - return new MaxMinIterator(this); - } - private static class MaxMinIterator implements Iterator { - 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; - } - } -} diff --git a/src/main/java/com/dfsek/terra/Range.java b/src/main/java/com/dfsek/terra/Range.java new file mode 100644 index 000000000..455debd83 --- /dev/null +++ b/src/main/java/com/dfsek/terra/Range.java @@ -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 { + 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 iterator() { + return new RangeIterator(this); + } + private static class RangeIterator implements Iterator { + 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; + } + } +} diff --git a/src/main/java/com/dfsek/terra/TerraCommand.java b/src/main/java/com/dfsek/terra/TerraCommand.java index b4a3a6fb7..d66b72cfc 100644 --- a/src/main/java/com/dfsek/terra/TerraCommand.java +++ b/src/main/java/com/dfsek/terra/TerraCommand.java @@ -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."); diff --git a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index 17064be9c..0b088cba8 100644 --- a/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -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; diff --git a/src/main/java/com/dfsek/terra/config/genconfig/AbstractBiomeConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/AbstractBiomeConfig.java index 290cff977..578608943 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/AbstractBiomeConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/AbstractBiomeConfig.java @@ -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 biomes = new HashMap<>(); private String biomeID; - private Map ores; - private Map oreHeights; + private Map ores; + private Map oreHeights; private Map carvers; private ProbabilityCollection flora; private ProbabilityCollection trees; @@ -39,7 +38,7 @@ public class AbstractBiomeConfig extends TerraConfigObject { private int treeDensity; private String equation; private int floraAttempts; - private Map floraHeights; + private Map floraHeights; private TreeMap> paletteMap; private double slabThreshold; private Map> 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 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 getOreHeights() { + public Map getOreHeights() { return oreHeights; } - public Map getOres() { + public Map getOres() { return ores; } - public Map getFloraHeights() { + public Map getFloraHeights() { return floraHeights; } diff --git a/src/main/java/com/dfsek/terra/config/genconfig/BiomeConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/BiomeConfig.java index 7c53a4346..d8342ce2f 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/BiomeConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/BiomeConfig.java @@ -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 ores; - private Map oreHeights; + private Map ores; + private Map oreHeights; private Map carvers; - private Map floraHeights; + private Map floraHeights; private String eq; private int floraAttempts; private Map> 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 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 getOres() { + public Map 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) { diff --git a/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java b/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java index 02628fd25..b5c250f18 100644 --- a/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java +++ b/src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java @@ -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)); diff --git a/src/main/java/com/dfsek/terra/population/OrePopulator.java b/src/main/java/com/dfsek/terra/population/OrePopulator.java index 65fe93b9e..29350dabb 100644 --- a/src/main/java/com/dfsek/terra/population/OrePopulator.java +++ b/src/main/java/com/dfsek/terra/population/OrePopulator.java @@ -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 e : BiomeConfig.fromBiome((UserDefinedBiome) b).getOres().entrySet()) { + for(Map.Entry 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); diff --git a/src/main/java/com/dfsek/terra/structure/GaeaStructure.java b/src/main/java/com/dfsek/terra/structure/GaeaStructure.java index af8d548f3..8bcba2a80 100644 --- a/src/main/java/com/dfsek/terra/structure/GaeaStructure.java +++ b/src/main/java/com/dfsek/terra/structure/GaeaStructure.java @@ -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 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 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 + } } diff --git a/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java b/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java index 5f84a0d2e..4cda779d5 100644 --- a/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java +++ b/src/main/java/com/dfsek/terra/structure/StructureContainedBlock.java @@ -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; } } diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableBlockData.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableBlockData.java new file mode 100644 index 000000000..f3f607c84 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/SerializableBlockData.java @@ -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); + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableEnchantment.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableEnchantment.java new file mode 100644 index 000000000..f67a92ef4 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/SerializableEnchantment.java @@ -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()); + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableInventory.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableInventory.java new file mode 100644 index 000000000..1c368c537 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/SerializableInventory.java @@ -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); + } + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableItemMeta.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableItemMeta.java new file mode 100644 index 000000000..b7bd52520 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/SerializableItemMeta.java @@ -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) { + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableItemStack.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableItemStack.java new file mode 100644 index 000000000..d75c79ae8 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/SerializableItemStack.java @@ -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 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 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; + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/SerializableNamespacedKey.java b/src/main/java/com/dfsek/terra/structure/serialize/SerializableNamespacedKey.java new file mode 100644 index 000000000..33d0ec6d1 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/SerializableNamespacedKey.java @@ -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); + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBlockState.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBlockState.java new file mode 100644 index 000000000..a0692eb7d --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableBlockState.java @@ -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); +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableChest.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableChest.java new file mode 100644 index 000000000..5846c2d07 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableChest.java @@ -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; + } +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableContainer.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableContainer.java new file mode 100644 index 000000000..bd1c743a5 --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableContainer.java @@ -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); +} diff --git a/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableSign.java b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableSign.java new file mode 100644 index 000000000..a8eb4ec9a --- /dev/null +++ b/src/main/java/com/dfsek/terra/structure/serialize/block/SerializableSign.java @@ -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; + } +} diff --git a/src/test/java/MaxMinTest.java b/src/test/java/MaxMinTest.java deleted file mode 100644 index 5479c9e51..000000000 --- a/src/test/java/MaxMinTest.java +++ /dev/null @@ -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); - } -} diff --git a/src/test/java/RangeTest.java b/src/test/java/RangeTest.java new file mode 100644 index 000000000..36955cfeb --- /dev/null +++ b/src/test/java/RangeTest.java @@ -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)); + } +}