From 2b222f5d3ff4ef496dc25256debf2647b1f5b75d Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Sat, 12 Mar 2022 20:53:27 +0100 Subject: [PATCH 1/7] Add support for the Structure Block file format (.nbt files) --- .../format/DefaultSchematicFormats.java | 13 ++++ .../format/defaults/StructureNBT.java | 68 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java diff --git a/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java b/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java index fb20164bd..2d2736a00 100644 --- a/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java +++ b/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java @@ -21,6 +21,7 @@ import baritone.api.schematic.format.ISchematicFormat; import baritone.utils.schematic.format.defaults.MCEditSchematic; import baritone.utils.schematic.format.defaults.SpongeSchematic; +import baritone.utils.schematic.format.defaults.StructureNBT; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import org.apache.commons.io.FilenameUtils; @@ -65,6 +66,18 @@ public IStaticSchematic parse(InputStream input) throws IOException { throw new UnsupportedOperationException("Unsupported Version of a Sponge Schematic"); } } + }, + + /** + * The vanilla structure block file format. Commonly denoted by the ".nbt" file extension. + * + * @see . + */ + +package baritone.utils.schematic.format.defaults; + +import baritone.utils.schematic.StaticSchematic; +import net.minecraft.block.state.IBlockState; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.structure.template.Template; + +import java.lang.reflect.Field; +import java.util.List; + +/** + * @author Sam + * @since 03/11/2022 + */ +public final class StructureNBT extends StaticSchematic { + + public StructureNBT(NBTTagCompound schematic) { + Template template = new Template(); + template.read(schematic); + + BlockPos size = template.getSize(); + this.x = size.getX(); + this.y = size.getY(); + this.z = size.getZ(); + + List blocks; + try { + Field f = template.getClass().getDeclaredField("field_186270_a"); // Template.blocks + f.setAccessible(true); + blocks = (List) f.get(template); + } catch (final Exception e) { + // This should never happen since SRG names are canonical + throw new IllegalStateException("reflection error"); + } + + this.states = new IBlockState[this.x][this.z][this.y]; + for (Template.BlockInfo block : blocks ) { + this.states[block.pos.getX()][block.pos.getZ()][block.pos.getY()] = block.blockState; + } + } + + @Override + public boolean inSchematic(int x, int y, int z, IBlockState currentState) { + // Filtering out Structure Void + if (x >= 0 && x < widthX() && y >= 0 && y < heightY() && z >= 0 && z < lengthZ()) { + return this.states[x][z][y] != null; + } + return false; + } +} \ No newline at end of file From fd446b353c33375c3b6fdbc04e06083bc7f027df Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Sun, 13 Mar 2022 18:49:32 +0100 Subject: [PATCH 2/7] Use mixin instead of SRG name for compatibility --- .../baritone/launch/mixins/MixinTemplate.java | 33 +++++++++++++++++++ src/launch/resources/mixins.baritone.json | 1 + .../baritone/utils/accessor/ITemplate.java | 28 ++++++++++++++++ .../format/defaults/StructureNBT.java | 14 ++------ 4 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 src/launch/java/baritone/launch/mixins/MixinTemplate.java create mode 100644 src/main/java/baritone/utils/accessor/ITemplate.java diff --git a/src/launch/java/baritone/launch/mixins/MixinTemplate.java b/src/launch/java/baritone/launch/mixins/MixinTemplate.java new file mode 100644 index 000000000..7019aac74 --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinTemplate.java @@ -0,0 +1,33 @@ +/* + * 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.launch.mixins; + +import baritone.utils.accessor.ITemplate; +import net.minecraft.world.gen.structure.template.Template; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(Template.class) +public abstract class MixinTemplate implements ITemplate { + + @Override + @Accessor + public abstract List getBlocks(); +} diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json index fdcd14b92..632b16df6 100644 --- a/src/launch/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -30,6 +30,7 @@ "MixinRenderList", "MixinStateImplementation", "MixinTabCompleter", + "MixinTemplate", "MixinVboRenderList", "MixinWorldClient" ] diff --git a/src/main/java/baritone/utils/accessor/ITemplate.java b/src/main/java/baritone/utils/accessor/ITemplate.java new file mode 100644 index 000000000..c71bae70b --- /dev/null +++ b/src/main/java/baritone/utils/accessor/ITemplate.java @@ -0,0 +1,28 @@ +/* + * 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.accessor; + +import net.minecraft.world.gen.structure.template.Template; + +import java.util.List; + +public interface ITemplate { + + List getBlocks(); + +} diff --git a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java index 5a7bcf8a4..e36659dcc 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java @@ -17,6 +17,7 @@ package baritone.utils.schematic.format.defaults; +import baritone.utils.accessor.ITemplate; import baritone.utils.schematic.StaticSchematic; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; @@ -41,16 +42,7 @@ public StructureNBT(NBTTagCompound schematic) { this.y = size.getY(); this.z = size.getZ(); - List blocks; - try { - Field f = template.getClass().getDeclaredField("field_186270_a"); // Template.blocks - f.setAccessible(true); - blocks = (List) f.get(template); - } catch (final Exception e) { - // This should never happen since SRG names are canonical - throw new IllegalStateException("reflection error"); - } - + List blocks = ((ITemplate) template).getBlocks(); this.states = new IBlockState[this.x][this.z][this.y]; for (Template.BlockInfo block : blocks ) { this.states[block.pos.getX()][block.pos.getZ()][block.pos.getY()] = block.blockState; @@ -65,4 +57,4 @@ public boolean inSchematic(int x, int y, int z, IBlockState currentState) { } return false; } -} \ No newline at end of file +} From 38e2d158de1c8782987fb14f8e02d3800c4078c6 Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Sun, 13 Mar 2022 18:54:41 +0100 Subject: [PATCH 3/7] fix unused import --- .../baritone/utils/schematic/format/defaults/StructureNBT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java index e36659dcc..9fde47578 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java @@ -24,7 +24,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.structure.template.Template; -import java.lang.reflect.Field; import java.util.List; /** From 0b0de22c4f8f29cfab4c631e375e6bca624681bb Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Tue, 15 Mar 2022 19:34:05 +0100 Subject: [PATCH 4/7] fix NullPointerException by Overriding getDirect, getColumn and desiredState --- .../format/defaults/StructureNBT.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java index 9fde47578..285034ad3 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java @@ -20,6 +20,7 @@ import baritone.utils.accessor.ITemplate; import baritone.utils.schematic.StaticSchematic; import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.structure.template.Template; @@ -48,12 +49,34 @@ public StructureNBT(NBTTagCompound schematic) { } } + @Override + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { + IBlockState block = this.states[x][z][y]; + if (block != null) { + return block; + } + return current; + } + + @Override + public IBlockState getDirect(int x, int y, int z) { + // Use air blocks as placeholder for Structure Void + return desiredState(x, y, z, Blocks.AIR.getDefaultState(), null); + } + + @Override + public IBlockState[] getColumn(int x, int z) { + IBlockState[] column = this.states[x][z]; + for (int i = 0; i < column.length; i++) { + // Use air blocks as placeholder for Structure Void + if (column[i] == null) { column[i] = Blocks.AIR.getDefaultState(); } + } + return column; + } + @Override public boolean inSchematic(int x, int y, int z, IBlockState currentState) { // Filtering out Structure Void - if (x >= 0 && x < widthX() && y >= 0 && y < heightY() && z >= 0 && z < lengthZ()) { - return this.states[x][z][y] != null; - } - return false; + return (super.inSchematic(x, y, z, currentState) && this.states[x][z][y] != null); } } From 556f0e309f1ef71a6e35bf4ab8bfb794ad311a44 Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Tue, 15 Mar 2022 23:19:24 +0100 Subject: [PATCH 5/7] use ternary operator --- .../utils/schematic/format/defaults/StructureNBT.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java index 285034ad3..a8c94758a 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java @@ -52,10 +52,7 @@ public StructureNBT(NBTTagCompound schematic) { @Override public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { IBlockState block = this.states[x][z][y]; - if (block != null) { - return block; - } - return current; + return block != null ? block : current; } @Override From 315ab610e7017413ddfd07298f170f04dad09d50 Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Fri, 1 Apr 2022 14:16:30 +0200 Subject: [PATCH 6/7] formatting --- .../utils/schematic/format/defaults/StructureNBT.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java index a8c94758a..c22905a45 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java @@ -44,7 +44,7 @@ public StructureNBT(NBTTagCompound schematic) { List blocks = ((ITemplate) template).getBlocks(); this.states = new IBlockState[this.x][this.z][this.y]; - for (Template.BlockInfo block : blocks ) { + for (Template.BlockInfo block : blocks) { this.states[block.pos.getX()][block.pos.getZ()][block.pos.getY()] = block.blockState; } } @@ -66,7 +66,9 @@ public IBlockState[] getColumn(int x, int z) { IBlockState[] column = this.states[x][z]; for (int i = 0; i < column.length; i++) { // Use air blocks as placeholder for Structure Void - if (column[i] == null) { column[i] = Blocks.AIR.getDefaultState(); } + if (column[i] == null) { + column[i] = Blocks.AIR.getDefaultState(); + } } return column; } @@ -74,6 +76,6 @@ public IBlockState[] getColumn(int x, int z) { @Override public boolean inSchematic(int x, int y, int z, IBlockState currentState) { // Filtering out Structure Void - return (super.inSchematic(x, y, z, currentState) && this.states[x][z][y] != null); + return super.inSchematic(x, y, z, currentState) && this.states[x][z][y] != null; } } From ad4f257943be0c856d5f473c177fc919cc7f2da0 Mon Sep 17 00:00:00 2001 From: Samuel Burkhardt Date: Fri, 1 Apr 2022 14:17:21 +0200 Subject: [PATCH 7/7] clone column to avoid altering the original array --- .../baritone/utils/schematic/format/defaults/StructureNBT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java index c22905a45..c811532ad 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/StructureNBT.java @@ -63,7 +63,7 @@ public IBlockState getDirect(int x, int y, int z) { @Override public IBlockState[] getColumn(int x, int z) { - IBlockState[] column = this.states[x][z]; + IBlockState[] column = this.states[x][z].clone(); for (int i = 0; i < column.length; i++) { // Use air blocks as placeholder for Structure Void if (column[i] == null) {