diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 88338a01..a7a17160 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -39,6 +39,7 @@ import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; import baritone.utils.PathingCommandContext; import baritone.utils.schematic.MapArtSchematic; +import baritone.utils.schematic.StaticSchematic; import baritone.utils.schematic.format.SchematicFormat; import baritone.utils.schematic.schematica.SchematicaHelper; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; @@ -129,7 +130,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } if (Baritone.settings().mapArtMode.value) { - parsed = new MapArtSchematic(parsed); + parsed = new MapArtSchematic((StaticSchematic) parsed); } build(name, parsed, origin); diff --git a/src/main/java/baritone/utils/schematic/MapArtSchematic.java b/src/main/java/baritone/utils/schematic/MapArtSchematic.java index a6bd2021..dc2edf2c 100644 --- a/src/main/java/baritone/utils/schematic/MapArtSchematic.java +++ b/src/main/java/baritone/utils/schematic/MapArtSchematic.java @@ -17,46 +17,16 @@ package baritone.utils.schematic; -import baritone.api.schematic.ISchematic; import baritone.api.schematic.MaskSchematic; -import net.minecraft.block.BlockAir; import net.minecraft.block.state.IBlockState; -import java.util.OptionalInt; -import java.util.function.Predicate; - public class MapArtSchematic extends MaskSchematic { private final int[][] heightMap; - public MapArtSchematic(ISchematic schematic) { + public MapArtSchematic(StaticSchematic schematic) { super(schematic); - - heightMap = new int[schematic.widthX()][schematic.lengthZ()]; - - for (int x = 0; x < schematic.widthX(); x++) { - for (int z = 0; z < schematic.lengthZ(); z++) { - IBlockState[] column = /*states[x][z]*/null; - - OptionalInt lowestBlockY = lastIndexMatching(column, state -> !(state.getBlock() instanceof BlockAir)); - if (lowestBlockY.isPresent()) { - heightMap[x][z] = lowestBlockY.getAsInt(); - } else { - System.out.println("Column " + x + "," + z + " has no blocks, but it's apparently map art? wtf"); - System.out.println("Letting it be whatever"); - heightMap[x][z] = 256; - } - } - } - } - - private static OptionalInt lastIndexMatching(T[] arr, Predicate predicate) { - for (int y = arr.length - 1; y >= 0; y--) { - if (predicate.test(arr[y])) { - return OptionalInt.of(y); - } - } - return OptionalInt.empty(); + this.heightMap = schematic.getHeightMap(); } @Override diff --git a/src/main/java/baritone/utils/schematic/StaticSchematic.java b/src/main/java/baritone/utils/schematic/StaticSchematic.java new file mode 100644 index 00000000..97fc91cd --- /dev/null +++ b/src/main/java/baritone/utils/schematic/StaticSchematic.java @@ -0,0 +1,88 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.utils.schematic; + +import baritone.api.schematic.AbstractSchematic; +import net.minecraft.block.BlockAir; +import net.minecraft.block.state.IBlockState; + +import java.util.List; +import java.util.OptionalInt; +import java.util.function.Predicate; + +/** + * @author Brady + * @since 12/23/2019 + */ +public abstract class StaticSchematic extends AbstractSchematic { + + /** + * Block states for this schematic stored in [x, z, y] indexing order + */ + protected IBlockState[][][] states; + + /** + * The maximum height of a given block in this schematic, indexed as [x, z]. + * This is lazily initialized by {@link #getHeightMap()}. + */ + protected int[][] heightMap; + + public StaticSchematic() { + super(); + } + + public StaticSchematic(int x, int y, int z) { + super(x, y, z); + } + + @Override + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { + return this.states[x][z][y]; + } + + public final int[][] getHeightMap() { + if (this.heightMap == null) { + this.heightMap = new int[this.x][this.z]; + + for (int x = 0; x < this.x; x++) { + for (int z = 0; z < this.z; z++) { + IBlockState[] column = states[x][z]; + + OptionalInt lowestBlockY = lastIndexMatching(column, state -> !(state.getBlock() instanceof BlockAir)); + if (lowestBlockY.isPresent()) { + this.heightMap[x][z] = lowestBlockY.getAsInt(); + } else { + System.out.println("Column " + x + "," + z + " has no blocks, but it's apparently map art? wtf"); + System.out.println("Letting it be whatever"); + this.heightMap[x][z] = 256; + } + } + } + } + return this.heightMap; + } + + private static OptionalInt lastIndexMatching(T[] arr, Predicate predicate) { + for (int y = arr.length - 1; y >= 0; y--) { + if (predicate.test(arr[y])) { + return OptionalInt.of(y); + } + } + return OptionalInt.empty(); + } +} diff --git a/src/main/java/baritone/utils/schematic/parse/ISchematicParser.java b/src/main/java/baritone/utils/schematic/parse/ISchematicParser.java index 040addc1..8bc716f1 100644 --- a/src/main/java/baritone/utils/schematic/parse/ISchematicParser.java +++ b/src/main/java/baritone/utils/schematic/parse/ISchematicParser.java @@ -17,7 +17,7 @@ package baritone.utils.schematic.parse; -import baritone.api.schematic.ISchematic; +import baritone.utils.schematic.StaticSchematic; import java.io.IOException; import java.io.InputStream; @@ -28,5 +28,5 @@ import java.io.InputStream; */ public interface ISchematicParser { - ISchematic parse(InputStream input) throws IOException; + StaticSchematic parse(InputStream input) throws IOException; } diff --git a/src/main/java/baritone/utils/schematic/parse/MCEditParser.java b/src/main/java/baritone/utils/schematic/parse/MCEditParser.java index dce2c856..54d78201 100644 --- a/src/main/java/baritone/utils/schematic/parse/MCEditParser.java +++ b/src/main/java/baritone/utils/schematic/parse/MCEditParser.java @@ -17,8 +17,7 @@ package baritone.utils.schematic.parse; -import baritone.api.schematic.AbstractSchematic; -import baritone.api.schematic.ISchematic; +import baritone.utils.schematic.StaticSchematic; import baritone.utils.schematic.format.SchematicFormat; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; @@ -27,7 +26,6 @@ import net.minecraft.nbt.NBTTagCompound; import java.io.IOException; import java.io.InputStream; -import java.util.List; /** * An implementation of {@link ISchematicParser} for {@link SchematicFormat#MCEDIT} @@ -39,13 +37,11 @@ public enum MCEditParser implements ISchematicParser { INSTANCE; @Override - public ISchematic parse(InputStream input) throws IOException { + public StaticSchematic parse(InputStream input) throws IOException { return new MCEditSchematic(CompressedStreamTools.readCompressed(input)); } - private static final class MCEditSchematic extends AbstractSchematic { - - private final IBlockState[][][] states; + private static final class MCEditSchematic extends StaticSchematic { MCEditSchematic(NBTTagCompound schematic) { String type = schematic.getString("Materials"); @@ -85,10 +81,5 @@ public enum MCEditParser implements ISchematicParser { } } } - - @Override - public final IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { - return this.states[x][z][y]; - } } } diff --git a/src/main/java/baritone/utils/schematic/parse/SpongeParser.java b/src/main/java/baritone/utils/schematic/parse/SpongeParser.java index 190c6d48..48cc60aa 100644 --- a/src/main/java/baritone/utils/schematic/parse/SpongeParser.java +++ b/src/main/java/baritone/utils/schematic/parse/SpongeParser.java @@ -17,8 +17,7 @@ package baritone.utils.schematic.parse; -import baritone.api.schematic.AbstractSchematic; -import baritone.api.schematic.ISchematic; +import baritone.utils.schematic.StaticSchematic; import baritone.utils.schematic.format.SchematicFormat; import baritone.utils.type.VarInt; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; @@ -32,7 +31,6 @@ import net.minecraft.util.ResourceLocation; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.regex.Matcher; @@ -48,7 +46,7 @@ public enum SpongeParser implements ISchematicParser { INSTANCE; @Override - public ISchematic parse(InputStream input) throws IOException { + public StaticSchematic parse(InputStream input) throws IOException { NBTTagCompound nbt = CompressedStreamTools.readCompressed(input); int version = nbt.getInteger("Version"); switch (version) { @@ -56,7 +54,7 @@ public enum SpongeParser implements ISchematicParser { case 2: return new SpongeSchematic(nbt); default: - throw new UnsupportedOperationException("Unsupported Version of the a Sponge Schematic"); + throw new UnsupportedOperationException("Unsupported Version of a Sponge Schematic"); } } @@ -64,12 +62,8 @@ public enum SpongeParser implements ISchematicParser { * Implementation of the Sponge Schematic Format supporting both V1 and V2. (For the current * use case, there is no difference between reading a V1 and V2 schematic). */ - private static final class SpongeSchematic extends AbstractSchematic { + private static final class SpongeSchematic extends StaticSchematic { - /** - * Block states for this schematic stored in [x, z, y] indexing order - */ - private IBlockState[][][] states; SpongeSchematic(NBTTagCompound nbt) { this.x = nbt.getInteger("Width"); @@ -123,11 +117,6 @@ public enum SpongeParser implements ISchematicParser { } } } - - @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { - return this.states[x][z][y]; - } } private static final class SerializedBlockState {