minecraft-source/src/net/minecraft/gametest/framework/StructureUtils.java

219 lines
10 KiB
Java

package net.minecraft.gametest.framework;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.levelgen.ChunkGeneratorSettings;
import net.minecraft.commands.arguments.blocks.BlockInput;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Collections;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import java.io.BufferedReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.io.IOException;
import net.minecraft.nbt.TagParser;
import java.io.Reader;
import org.apache.commons.io.IOUtils;
import java.nio.file.Files;
import net.minecraft.nbt.CompoundTag;
import java.nio.file.Path;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import java.nio.file.Paths;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.block.state.BlockState;
import com.google.common.collect.Lists;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Optional;
import java.util.List;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.block.state.properties.StructureMode;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
public class StructureUtils {
public static String testStructuresDir;
public static AABB getStructureBounds(final StructureBlockEntity bxi) {
final BlockPos fk2 = bxi.getBlockPos().offset(bxi.getStructurePos());
return new AABB(fk2, fk2.offset(bxi.getStructureSize()));
}
public static void addCommandBlockAndButtonToStartTest(final BlockPos fk, final ServerLevel xd) {
xd.setBlockAndUpdate(fk, Blocks.COMMAND_BLOCK.defaultBlockState());
final CommandBlockEntity bwn3 = (CommandBlockEntity)xd.getBlockEntity(fk);
bwn3.getCommandBlock().setCommand("test runthis");
xd.setBlockAndUpdate(fk.offset(0, 0, -1), Blocks.STONE_BUTTON.defaultBlockState());
}
public static void createNewEmptyStructureBlock(final String string, final BlockPos fk2, final BlockPos fk3, final int integer, final ServerLevel xd) {
final BoundingBox cky6 = createStructureBoundingBox(fk2, fk3, integer);
clearSpaceForStructure(cky6, fk2.getY(), xd);
xd.setBlockAndUpdate(fk2, Blocks.STRUCTURE_BLOCK.defaultBlockState());
final StructureBlockEntity bxi7 = (StructureBlockEntity)xd.getBlockEntity(fk2);
bxi7.setIgnoreEntities(false);
bxi7.setStructureName(new ResourceLocation(string));
bxi7.setStructureSize(fk3);
bxi7.setMode(StructureMode.SAVE);
bxi7.setShowBoundingBox(true);
}
public static StructureBlockEntity spawnStructure(final String string, final BlockPos fk, final int integer, final ServerLevel xd, final boolean boolean5) {
final BoundingBox cky6 = createStructureBoundingBox(fk, getStructureTemplate(string, xd).getSize(), integer);
forceLoadChunks(fk, xd);
clearSpaceForStructure(cky6, fk.getY(), xd);
final StructureBlockEntity bxi7 = createStructureBlock(string, fk, xd, boolean5);
xd.getBlockTicks().fetchTicksInArea(cky6, true, false);
xd.clearBlockEvents(cky6);
return bxi7;
}
private static void forceLoadChunks(final BlockPos fk, final ServerLevel xd) {
final ChunkPos bje3 = new ChunkPos(fk);
for (int integer4 = -1; integer4 < 4; ++integer4) {
for (int integer5 = -1; integer5 < 4; ++integer5) {
final int integer6 = bje3.x + integer4;
final int integer7 = bje3.z + integer5;
xd.setChunkForced(integer6, integer7, true);
}
}
}
public static void clearSpaceForStructure(final BoundingBox cky, final int integer, final ServerLevel xd) {
BlockPos.betweenClosedStream(cky).forEach(fk -> clearBlock(integer, fk, xd));
xd.getBlockTicks().fetchTicksInArea(cky, true, false);
xd.clearBlockEvents(cky);
final AABB cvc4 = new AABB(cky.x0, cky.y0, cky.z0, cky.x1, cky.y1, cky.z1);
final List<Entity> list5 = xd.<Entity>getEntitiesOfClass(Entity.class, cvc4, akn -> !(akn instanceof Player));
list5.forEach(Entity::remove);
}
public static BoundingBox createStructureBoundingBox(final BlockPos fk1, final BlockPos fk2, final int integer) {
final BlockPos fk3 = fk1.offset(-integer, -3, -integer);
final BlockPos fk4 = fk1.offset(fk2).offset(integer - 1, 30, integer - 1);
return BoundingBox.createProper(fk3.getX(), fk3.getY(), fk3.getZ(), fk4.getX(), fk4.getY(), fk4.getZ());
}
public static Optional<BlockPos> findStructureBlockContainingPos(final BlockPos fk, final int integer, final ServerLevel xd) {
return findStructureBlocks(fk, integer, xd).stream().filter(fk3 -> doesStructureContain(fk3, fk, xd)).findFirst();
}
@Nullable
public static BlockPos findNearestStructureBlock(final BlockPos fk, final int integer, final ServerLevel xd) {
final Comparator<BlockPos> comparator4 = Comparator.<BlockPos>comparingInt(fk2 -> fk2.distManhattan(fk));
final Collection<BlockPos> collection5 = findStructureBlocks(fk, integer, xd);
final Optional<BlockPos> optional6 = collection5.stream().min(comparator4);
return optional6.orElse(null);
}
public static Collection<BlockPos> findStructureBlocks(final BlockPos fk, final int integer, final ServerLevel xd) {
final Collection<BlockPos> collection4 = Lists.newArrayList();
AABB cvc5 = new AABB(fk);
cvc5 = cvc5.inflate(integer);
for (int integer2 = (int)cvc5.minX; integer2 <= (int)cvc5.maxX; ++integer2) {
for (int integer3 = (int)cvc5.minY; integer3 <= (int)cvc5.maxY; ++integer3) {
for (int integer4 = (int)cvc5.minZ; integer4 <= (int)cvc5.maxZ; ++integer4) {
final BlockPos fk2 = new BlockPos(integer2, integer3, integer4);
final BlockState byg10 = xd.getBlockState(fk2);
if (byg10.getBlock() == Blocks.STRUCTURE_BLOCK) {
collection4.add(fk2);
}
}
}
}
return collection4;
}
private static StructureTemplate getStructureTemplate(final String string, final ServerLevel xd) {
final StructureManager cml3 = xd.getStructureManager();
final StructureTemplate cmp4 = cml3.get(new ResourceLocation(string));
if (cmp4 != null) {
return cmp4;
}
final String string2 = string + ".snbt";
final Path path6 = Paths.get(StructureUtils.testStructuresDir, string2);
final CompoundTag jt7 = tryLoadStructure(path6);
if (jt7 == null) {
throw new RuntimeException("Could not find structure file " + path6 + ", and the structure is not available in the world structures either.");
}
return cml3.readStructure(jt7);
}
private static StructureBlockEntity createStructureBlock(final String string, final BlockPos fk, final ServerLevel xd, final boolean boolean4) {
xd.setBlockAndUpdate(fk, Blocks.STRUCTURE_BLOCK.defaultBlockState());
final StructureBlockEntity bxi5 = (StructureBlockEntity)xd.getBlockEntity(fk);
bxi5.setMode(StructureMode.LOAD);
bxi5.setIgnoreEntities(false);
bxi5.setStructureName(new ResourceLocation(string));
bxi5.loadStructure(boolean4);
if (bxi5.getStructureSize() != BlockPos.ZERO) {
return bxi5;
}
final StructureTemplate cmp6 = getStructureTemplate(string, xd);
bxi5.loadStructure(boolean4, cmp6);
if (bxi5.getStructureSize() == BlockPos.ZERO) {
throw new RuntimeException("Failed to load structure " + string);
}
return bxi5;
}
@Nullable
private static CompoundTag tryLoadStructure(final Path path) {
try {
final BufferedReader bufferedReader2 = Files.newBufferedReader(path);
final String string3 = IOUtils.toString((Reader)bufferedReader2);
return TagParser.parseTag(string3);
}
catch (IOException iOException2) {
return null;
}
catch (CommandSyntaxException commandSyntaxException2) {
throw new RuntimeException("Error while trying to load structure " + path, (Throwable)commandSyntaxException2);
}
}
private static void clearBlock(final int integer, final BlockPos fk, final ServerLevel xd) {
final ChunkGeneratorSettings cbn5 = (ChunkGeneratorSettings)xd.getChunkSource().getGenerator().getSettings();
BlockState byg4;
if (cbn5 instanceof FlatLevelGeneratorSettings) {
final BlockState[] arr6 = ((FlatLevelGeneratorSettings)cbn5).getLayers();
if (fk.getY() < integer) {
byg4 = arr6[fk.getY() - 1];
}
else {
byg4 = Blocks.AIR.defaultBlockState();
}
}
else if (fk.getY() == integer - 1) {
byg4 = xd.getBiome(fk).getSurfaceBuilderConfig().getTopMaterial();
}
else if (fk.getY() < integer - 1) {
byg4 = xd.getBiome(fk).getSurfaceBuilderConfig().getUnderMaterial();
}
else {
byg4 = Blocks.AIR.defaultBlockState();
}
final BlockInput ds6 = new BlockInput(byg4, Collections.<Property<?>>emptySet(), null);
ds6.place(xd, fk, 2);
xd.blockUpdated(fk, byg4.getBlock());
}
private static boolean doesStructureContain(final BlockPos fk1, final BlockPos fk2, final ServerLevel xd) {
final StructureBlockEntity bxi4 = (StructureBlockEntity)xd.getBlockEntity(fk1);
final AABB cvc5 = getStructureBounds(bxi4);
return cvc5.contains(new Vec3(fk2));
}
static {
StructureUtils.testStructuresDir = "gameteststructures";
}
}