Spaces:
Build error
Build error
package net.minecraft.gametest.framework; | |
import com.mojang.logging.LogUtils; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.List; | |
import java.util.Objects; | |
import java.util.Optional; | |
import java.util.stream.Stream; | |
import net.minecraft.commands.arguments.blocks.BlockInput; | |
import net.minecraft.core.BlockPos; | |
import net.minecraft.core.Vec3i; | |
import net.minecraft.resources.ResourceLocation; | |
import net.minecraft.server.level.ServerLevel; | |
import net.minecraft.world.entity.Entity; | |
import net.minecraft.world.entity.player.Player; | |
import net.minecraft.world.level.ChunkPos; | |
import net.minecraft.world.level.block.Blocks; | |
import net.minecraft.world.level.block.Mirror; | |
import net.minecraft.world.level.block.Rotation; | |
import net.minecraft.world.level.block.entity.BlockEntity; | |
import net.minecraft.world.level.block.entity.BlockEntityType; | |
import net.minecraft.world.level.block.entity.CommandBlockEntity; | |
import net.minecraft.world.level.block.entity.StructureBlockEntity; | |
import net.minecraft.world.level.block.state.BlockState; | |
import net.minecraft.world.level.block.state.properties.StructureMode; | |
import net.minecraft.world.level.levelgen.Heightmap; | |
import net.minecraft.world.level.levelgen.structure.BoundingBox; | |
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; | |
import net.minecraft.world.phys.AABB; | |
import net.minecraft.world.phys.Vec3; | |
import org.slf4j.Logger; | |
public class StructureUtils { | |
private static final Logger LOGGER = LogUtils.getLogger(); | |
public static final int DEFAULT_Y_SEARCH_RADIUS = 10; | |
public static final String DEFAULT_TEST_STRUCTURES_DIR = "gameteststructures"; | |
public static String testStructuresDir = "gameteststructures"; | |
public static Rotation getRotationForRotationSteps(int p_127836_) { | |
switch (p_127836_) { | |
case 0: | |
return Rotation.NONE; | |
case 1: | |
return Rotation.CLOCKWISE_90; | |
case 2: | |
return Rotation.CLOCKWISE_180; | |
case 3: | |
return Rotation.COUNTERCLOCKWISE_90; | |
default: | |
throw new IllegalArgumentException("rotationSteps must be a value from 0-3. Got value " + p_127836_); | |
} | |
} | |
public static int getRotationStepsForRotation(Rotation p_177752_) { | |
switch (p_177752_) { | |
case NONE: | |
return 0; | |
case CLOCKWISE_90: | |
return 1; | |
case CLOCKWISE_180: | |
return 2; | |
case COUNTERCLOCKWISE_90: | |
return 3; | |
default: | |
throw new IllegalArgumentException("Unknown rotation value, don't know how many steps it represents: " + p_177752_); | |
} | |
} | |
public static AABB getStructureBounds(StructureBlockEntity p_127848_) { | |
return AABB.of(getStructureBoundingBox(p_127848_)); | |
} | |
public static BoundingBox getStructureBoundingBox(StructureBlockEntity p_127905_) { | |
BlockPos blockpos = getStructureOrigin(p_127905_); | |
BlockPos blockpos1 = getTransformedFarCorner(blockpos, p_127905_.getStructureSize(), p_127905_.getRotation()); | |
return BoundingBox.fromCorners(blockpos, blockpos1); | |
} | |
public static BlockPos getStructureOrigin(StructureBlockEntity p_311311_) { | |
return p_311311_.getBlockPos().offset(p_311311_.getStructurePos()); | |
} | |
public static void addCommandBlockAndButtonToStartTest(BlockPos p_127876_, BlockPos p_127877_, Rotation p_127878_, ServerLevel p_127879_) { | |
BlockPos blockpos = StructureTemplate.transform(p_127876_.offset(p_127877_), Mirror.NONE, p_127878_, p_127876_); | |
p_127879_.setBlockAndUpdate(blockpos, Blocks.COMMAND_BLOCK.defaultBlockState()); | |
CommandBlockEntity commandblockentity = (CommandBlockEntity)p_127879_.getBlockEntity(blockpos); | |
commandblockentity.getCommandBlock().setCommand("test runclosest"); | |
BlockPos blockpos1 = StructureTemplate.transform(blockpos.offset(0, 0, -1), Mirror.NONE, p_127878_, blockpos); | |
p_127879_.setBlockAndUpdate(blockpos1, Blocks.STONE_BUTTON.defaultBlockState().rotate(p_127878_)); | |
} | |
public static void createNewEmptyStructureBlock(String p_177765_, BlockPos p_177766_, Vec3i p_177767_, Rotation p_177768_, ServerLevel p_177769_) { | |
BoundingBox boundingbox = getStructureBoundingBox(p_177766_.above(), p_177767_, p_177768_); | |
clearSpaceForStructure(boundingbox, p_177769_); | |
p_177769_.setBlockAndUpdate(p_177766_, Blocks.STRUCTURE_BLOCK.defaultBlockState()); | |
StructureBlockEntity structureblockentity = (StructureBlockEntity)p_177769_.getBlockEntity(p_177766_); | |
structureblockentity.setIgnoreEntities(false); | |
structureblockentity.setStructureName(ResourceLocation.parse(p_177765_)); | |
structureblockentity.setMetaData(p_177765_); | |
structureblockentity.setStructureSize(p_177767_); | |
structureblockentity.setMode(StructureMode.SAVE); | |
structureblockentity.setShowBoundingBox(true); | |
} | |
public static BlockPos getStartCorner(GameTestInfo p_364513_, BlockPos p_364702_, Rotation p_360789_, ServerLevel p_360785_) { | |
Vec3i vec3i = p_360785_.getStructureManager() | |
.get(ResourceLocation.parse(p_364513_.getStructureName())) | |
.orElseThrow(() -> new IllegalStateException("Missing test structure: " + p_364513_.getStructureName())) | |
.getSize(); | |
BlockPos blockpos; | |
if (p_360789_ == Rotation.NONE) { | |
blockpos = p_364702_; | |
} else if (p_360789_ == Rotation.CLOCKWISE_90) { | |
blockpos = p_364702_.offset(vec3i.getZ() - 1, 0, 0); | |
} else if (p_360789_ == Rotation.CLOCKWISE_180) { | |
blockpos = p_364702_.offset(vec3i.getX() - 1, 0, vec3i.getZ() - 1); | |
} else { | |
if (p_360789_ != Rotation.COUNTERCLOCKWISE_90) { | |
throw new IllegalArgumentException("Invalid rotation: " + p_360789_); | |
} | |
blockpos = p_364702_.offset(0, 0, vec3i.getX() - 1); | |
} | |
return blockpos; | |
} | |
public static StructureBlockEntity prepareTestStructure(GameTestInfo p_311701_, BlockPos p_311042_, Rotation p_310584_, ServerLevel p_312330_) { | |
Vec3i vec3i = p_312330_.getStructureManager() | |
.get(ResourceLocation.parse(p_311701_.getStructureName())) | |
.orElseThrow(() -> new IllegalStateException("Missing test structure: " + p_311701_.getStructureName())) | |
.getSize(); | |
BoundingBox boundingbox = getStructureBoundingBox(p_311042_, vec3i, p_310584_); | |
BlockPos blockpos = getStartCorner(p_311701_, p_311042_, p_310584_, p_312330_); | |
forceLoadChunks(boundingbox, p_312330_); | |
clearSpaceForStructure(boundingbox, p_312330_); | |
return createStructureBlock(p_311701_, blockpos.below(), p_310584_, p_312330_); | |
} | |
public static void encaseStructure(AABB p_330422_, ServerLevel p_331249_, boolean p_328180_) { | |
BlockPos blockpos = BlockPos.containing(p_330422_.minX, p_330422_.minY, p_330422_.minZ).offset(-1, 0, -1); | |
BlockPos blockpos1 = BlockPos.containing(p_330422_.maxX, p_330422_.maxY, p_330422_.maxZ); | |
BlockPos.betweenClosedStream(blockpos, blockpos1) | |
.forEach( | |
p_325964_ -> { | |
boolean flag = p_325964_.getX() == blockpos.getX() | |
|| p_325964_.getX() == blockpos1.getX() | |
|| p_325964_.getZ() == blockpos.getZ() | |
|| p_325964_.getZ() == blockpos1.getZ(); | |
boolean flag1 = p_325964_.getY() == blockpos1.getY(); | |
if (flag || flag1 && p_328180_) { | |
p_331249_.setBlockAndUpdate(p_325964_, Blocks.BARRIER.defaultBlockState()); | |
} | |
} | |
); | |
} | |
public static void removeBarriers(AABB p_336061_, ServerLevel p_334551_) { | |
BlockPos blockpos = BlockPos.containing(p_336061_.minX, p_336061_.minY, p_336061_.minZ).offset(-1, 0, -1); | |
BlockPos blockpos1 = BlockPos.containing(p_336061_.maxX, p_336061_.maxY, p_336061_.maxZ); | |
BlockPos.betweenClosedStream(blockpos, blockpos1) | |
.forEach( | |
p_325970_ -> { | |
boolean flag = p_325970_.getX() == blockpos.getX() | |
|| p_325970_.getX() == blockpos1.getX() | |
|| p_325970_.getZ() == blockpos.getZ() | |
|| p_325970_.getZ() == blockpos1.getZ(); | |
boolean flag1 = p_325970_.getY() == blockpos1.getY(); | |
if (p_334551_.getBlockState(p_325970_).is(Blocks.BARRIER) && (flag || flag1)) { | |
p_334551_.setBlockAndUpdate(p_325970_, Blocks.AIR.defaultBlockState()); | |
} | |
} | |
); | |
} | |
private static void forceLoadChunks(BoundingBox p_312219_, ServerLevel p_127859_) { | |
p_312219_.intersectingChunks().forEach(p_308541_ -> p_127859_.setChunkForced(p_308541_.x, p_308541_.z, true)); | |
} | |
public static void clearSpaceForStructure(BoundingBox p_127850_, ServerLevel p_127852_) { | |
int i = p_127850_.minY() - 1; | |
BoundingBox boundingbox = new BoundingBox( | |
p_127850_.minX() - 2, | |
p_127850_.minY() - 3, | |
p_127850_.minZ() - 3, | |
p_127850_.maxX() + 3, | |
p_127850_.maxY() + 20, | |
p_127850_.maxZ() + 3 | |
); | |
BlockPos.betweenClosedStream(boundingbox).forEach(p_177748_ -> clearBlock(i, p_177748_, p_127852_)); | |
p_127852_.getBlockTicks().clearArea(boundingbox); | |
p_127852_.clearBlockEvents(boundingbox); | |
AABB aabb = AABB.of(boundingbox); | |
List<Entity> list = p_127852_.getEntitiesOfClass(Entity.class, aabb, p_177750_ -> !(p_177750_ instanceof Player)); | |
list.forEach(Entity::discard); | |
} | |
public static BlockPos getTransformedFarCorner(BlockPos p_310098_, Vec3i p_312132_, Rotation p_309587_) { | |
BlockPos blockpos = p_310098_.offset(p_312132_).offset(-1, -1, -1); | |
return StructureTemplate.transform(blockpos, Mirror.NONE, p_309587_, p_310098_); | |
} | |
public static BoundingBox getStructureBoundingBox(BlockPos p_177761_, Vec3i p_177762_, Rotation p_177763_) { | |
BlockPos blockpos = getTransformedFarCorner(p_177761_, p_177762_, p_177763_); | |
BoundingBox boundingbox = BoundingBox.fromCorners(p_177761_, blockpos); | |
int i = Math.min(boundingbox.minX(), boundingbox.maxX()); | |
int j = Math.min(boundingbox.minZ(), boundingbox.maxZ()); | |
return boundingbox.move(p_177761_.getX() - i, 0, p_177761_.getZ() - j); | |
} | |
public static Optional<BlockPos> findStructureBlockContainingPos(BlockPos p_127854_, int p_127855_, ServerLevel p_127856_) { | |
return findStructureBlocks(p_127854_, p_127855_, p_127856_).filter(p_177756_ -> doesStructureContain(p_177756_, p_127854_, p_127856_)).findFirst(); | |
} | |
public static Optional<BlockPos> findNearestStructureBlock(BlockPos p_127907_, int p_127908_, ServerLevel p_127909_) { | |
Comparator<BlockPos> comparator = Comparator.comparingInt(p_177759_ -> p_177759_.distManhattan(p_127907_)); | |
return findStructureBlocks(p_127907_, p_127908_, p_127909_).min(comparator); | |
} | |
public static Stream<BlockPos> findStructureByTestFunction(BlockPos p_333272_, int p_332388_, ServerLevel p_333747_, String p_332891_) { | |
return findStructureBlocks(p_333272_, p_332388_, p_333747_) | |
.map(p_325972_ -> (StructureBlockEntity)p_333747_.getBlockEntity(p_325972_)) | |
.filter(Objects::nonNull) | |
.filter(p_325954_ -> Objects.equals(p_325954_.getStructureName(), p_332891_)) | |
.map(BlockEntity::getBlockPos) | |
.map(BlockPos::immutable); | |
} | |
public static Stream<BlockPos> findStructureBlocks(BlockPos p_127911_, int p_127912_, ServerLevel p_127913_) { | |
BoundingBox boundingbox = getBoundingBoxAtGround(p_127911_, p_127912_, p_127913_); | |
return BlockPos.betweenClosedStream(boundingbox).filter(p_325959_ -> p_127913_.getBlockState(p_325959_).is(Blocks.STRUCTURE_BLOCK)).map(BlockPos::immutable); | |
} | |
private static StructureBlockEntity createStructureBlock(GameTestInfo p_309598_, BlockPos p_127892_, Rotation p_127893_, ServerLevel p_127894_) { | |
p_127894_.setBlockAndUpdate(p_127892_, Blocks.STRUCTURE_BLOCK.defaultBlockState()); | |
StructureBlockEntity structureblockentity = (StructureBlockEntity)p_127894_.getBlockEntity(p_127892_); | |
structureblockentity.setMode(StructureMode.LOAD); | |
structureblockentity.setRotation(p_127893_); | |
structureblockentity.setIgnoreEntities(false); | |
structureblockentity.setStructureName(ResourceLocation.parse(p_309598_.getStructureName())); | |
structureblockentity.setMetaData(p_309598_.getTestName()); | |
if (!structureblockentity.loadStructureInfo(p_127894_)) { | |
throw new RuntimeException("Failed to load structure info for test: " + p_309598_.getTestName() + ". Structure name: " + p_309598_.getStructureName()); | |
} else { | |
return structureblockentity; | |
} | |
} | |
private static BoundingBox getBoundingBoxAtGround(BlockPos p_329849_, int p_332427_, ServerLevel p_328726_) { | |
BlockPos blockpos = BlockPos.containing( | |
(double)p_329849_.getX(), (double)p_328726_.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, p_329849_).getY(), (double)p_329849_.getZ() | |
); | |
return new BoundingBox(blockpos).inflatedBy(p_332427_, 10, p_332427_); | |
} | |
public static Stream<BlockPos> lookedAtStructureBlockPos(BlockPos p_333762_, Entity p_333965_, ServerLevel p_336162_) { | |
int i = 200; | |
Vec3 vec3 = p_333965_.getEyePosition(); | |
Vec3 vec31 = vec3.add(p_333965_.getLookAngle().scale(200.0)); | |
return findStructureBlocks(p_333762_, 200, p_336162_) | |
.map(p_325966_ -> p_336162_.getBlockEntity(p_325966_, BlockEntityType.STRUCTURE_BLOCK)) | |
.flatMap(Optional::stream) | |
.filter(p_325957_ -> getStructureBounds(p_325957_).clip(vec3, vec31).isPresent()) | |
.map(BlockEntity::getBlockPos) | |
.sorted(Comparator.comparing(p_333762_::distSqr)) | |
.limit(1L); | |
} | |
private static void clearBlock(int p_127842_, BlockPos p_127843_, ServerLevel p_127844_) { | |
BlockState blockstate; | |
if (p_127843_.getY() < p_127842_) { | |
blockstate = Blocks.STONE.defaultBlockState(); | |
} else { | |
blockstate = Blocks.AIR.defaultBlockState(); | |
} | |
BlockInput blockinput = new BlockInput(blockstate, Collections.emptySet(), null); | |
blockinput.place(p_127844_, p_127843_, 2); | |
p_127844_.blockUpdated(p_127843_, blockstate.getBlock()); | |
} | |
private static boolean doesStructureContain(BlockPos p_127868_, BlockPos p_127869_, ServerLevel p_127870_) { | |
StructureBlockEntity structureblockentity = (StructureBlockEntity)p_127870_.getBlockEntity(p_127868_); | |
return getStructureBoundingBox(structureblockentity).isInside(p_127869_); | |
} | |
} |