2025-11-24 22:52:51 +03:00

149 lines
7.6 KiB
Java

/*
* Decompiled with CFR 0.152.
*/
package net.minecraft.gametest.framework;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
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.core.registries.Registries;
import net.minecraft.gametest.framework.GameTestInstance;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.village.poi.PoiManager;
import net.minecraft.world.entity.ai.village.poi.PoiTypes;
import net.minecraft.world.entity.player.Player;
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.TestInstanceBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
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 net.minecraft.world.ticks.LevelTicks;
public class StructureUtils {
public static final int DEFAULT_Y_SEARCH_RADIUS = 10;
public static final String DEFAULT_TEST_STRUCTURES_DIR = "Minecraft.Server/src/test/convertables/data";
public static Path testStructuresDir = Paths.get("Minecraft.Server/src/test/convertables/data", new String[0]);
public static Rotation getRotationForRotationSteps(int rotationSteps) {
switch (rotationSteps) {
case 0: {
return Rotation.NONE;
}
case 1: {
return Rotation.CLOCKWISE_90;
}
case 2: {
return Rotation.CLOCKWISE_180;
}
case 3: {
return Rotation.COUNTERCLOCKWISE_90;
}
}
throw new IllegalArgumentException("rotationSteps must be a value from 0-3. Got value " + rotationSteps);
}
public static int getRotationStepsForRotation(Rotation rotation) {
switch (rotation) {
case NONE: {
return 0;
}
case CLOCKWISE_90: {
return 1;
}
case CLOCKWISE_180: {
return 2;
}
case COUNTERCLOCKWISE_90: {
return 3;
}
}
throw new IllegalArgumentException("Unknown rotation value, don't know how many steps it represents: " + String.valueOf(rotation));
}
public static TestInstanceBlockEntity createNewEmptyTest(Identifier id, BlockPos structurePos, Vec3i size, Rotation rotation, ServerLevel level) {
BoundingBox structureBoundingBox = StructureUtils.getStructureBoundingBox(TestInstanceBlockEntity.getStructurePos(structurePos), size, rotation);
StructureUtils.clearSpaceForStructure(structureBoundingBox, level);
level.setBlockAndUpdate(structurePos, Blocks.TEST_INSTANCE_BLOCK.defaultBlockState());
TestInstanceBlockEntity test = (TestInstanceBlockEntity)level.getBlockEntity(structurePos);
ResourceKey<GameTestInstance> key = ResourceKey.create(Registries.TEST_INSTANCE, id);
test.set(new TestInstanceBlockEntity.Data(Optional.of(key), size, rotation, false, TestInstanceBlockEntity.Status.CLEARED, Optional.empty()));
return test;
}
public static void clearSpaceForStructure(BoundingBox structureBoundingBox, ServerLevel level) {
int groundHeight = structureBoundingBox.minY() - 1;
BlockPos.betweenClosedStream(structureBoundingBox).forEach(pos -> StructureUtils.clearBlock(groundHeight, pos, level));
((LevelTicks)level.getBlockTicks()).clearArea(structureBoundingBox);
level.clearBlockEvents(structureBoundingBox);
AABB bounds = AABB.of(structureBoundingBox);
List<Entity> livingEntities = level.getEntitiesOfClass(Entity.class, bounds, mob -> !(mob instanceof Player));
livingEntities.forEach(Entity::discard);
}
public static BlockPos getTransformedFarCorner(BlockPos structurePosition, Vec3i size, Rotation rotation) {
BlockPos farCornerBeforeTransform = structurePosition.offset(size).offset(-1, -1, -1);
return StructureTemplate.transform(farCornerBeforeTransform, Mirror.NONE, rotation, structurePosition);
}
public static BoundingBox getStructureBoundingBox(BlockPos northWestCorner, Vec3i size, Rotation rotation) {
BlockPos farCorner = StructureUtils.getTransformedFarCorner(northWestCorner, size, rotation);
BoundingBox boundingBox = BoundingBox.fromCorners(northWestCorner, farCorner);
int currentNorthWestCornerX = Math.min(boundingBox.minX(), boundingBox.maxX());
int currentNorthWestCornerZ = Math.min(boundingBox.minZ(), boundingBox.maxZ());
return boundingBox.move(northWestCorner.getX() - currentNorthWestCornerX, 0, northWestCorner.getZ() - currentNorthWestCornerZ);
}
public static Optional<BlockPos> findTestContainingPos(BlockPos pos, int searchRadius, ServerLevel level) {
return StructureUtils.findTestBlocks(pos, searchRadius, level).filter(testBlockPosToCheck -> StructureUtils.doesStructureContain(testBlockPosToCheck, pos, level)).findFirst();
}
public static Optional<BlockPos> findNearestTest(BlockPos relativeToPos, int searchRadius, ServerLevel level) {
Comparator<BlockPos> distanceToPlayer = Comparator.comparingInt(pos -> pos.distManhattan(relativeToPos));
return StructureUtils.findTestBlocks(relativeToPos, searchRadius, level).min(distanceToPlayer);
}
public static Stream<BlockPos> findTestBlocks(BlockPos centerPos, int searchRadius, ServerLevel level) {
return level.getPoiManager().findAll(p -> p.is(PoiTypes.TEST_INSTANCE), p -> true, centerPos, searchRadius, PoiManager.Occupancy.ANY).map(BlockPos::immutable);
}
public static Stream<BlockPos> lookedAtTestPos(BlockPos pos, Entity camera, ServerLevel level) {
int radius = 250;
Vec3 start = camera.getEyePosition();
Vec3 end = start.add(camera.getLookAngle().scale(250.0));
return StructureUtils.findTestBlocks(pos, 250, level).map(blockPos -> level.getBlockEntity((BlockPos)blockPos, BlockEntityType.TEST_INSTANCE_BLOCK)).flatMap(Optional::stream).filter(blockEntity -> blockEntity.getStructureBounds().clip(start, end).isPresent()).map(BlockEntity::getBlockPos).sorted(Comparator.comparing(pos::distSqr)).limit(1L);
}
private static void clearBlock(int airIfAboveThisY, BlockPos pos, ServerLevel level) {
BlockState blockState = pos.getY() < airIfAboveThisY ? Blocks.STONE.defaultBlockState() : Blocks.AIR.defaultBlockState();
BlockInput blockInput = new BlockInput(blockState, Collections.emptySet(), null);
blockInput.place(level, pos, 818);
level.updateNeighborsAt(pos, blockState.getBlock());
}
private static boolean doesStructureContain(BlockPos testInstanceBlockPos, BlockPos pos, ServerLevel level) {
BlockEntity blockEntity = level.getBlockEntity(testInstanceBlockPos);
if (blockEntity instanceof TestInstanceBlockEntity) {
TestInstanceBlockEntity blockEntity2 = (TestInstanceBlockEntity)blockEntity;
return blockEntity2.getStructureBoundingBox().isInside(pos);
}
return false;
}
}