1013 lines
45 KiB
Java
1013 lines
45 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.authlib.GameProfile
|
|
* com.mojang.brigadier.exceptions.CommandSyntaxException
|
|
* com.mojang.datafixers.util.Either
|
|
* io.netty.channel.ChannelHandler
|
|
* io.netty.channel.embedded.EmbeddedChannel
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.gametest.framework;
|
|
|
|
import com.mojang.authlib.GameProfile;
|
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
import com.mojang.datafixers.util.Either;
|
|
import io.netty.channel.ChannelHandler;
|
|
import io.netty.channel.embedded.EmbeddedChannel;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.UUID;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Function;
|
|
import java.util.function.IntPredicate;
|
|
import java.util.function.Predicate;
|
|
import java.util.function.Supplier;
|
|
import java.util.stream.LongStream;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Holder;
|
|
import net.minecraft.core.registries.Registries;
|
|
import net.minecraft.gametest.framework.GameTestAssertException;
|
|
import net.minecraft.gametest.framework.GameTestAssertPosException;
|
|
import net.minecraft.gametest.framework.GameTestInfo;
|
|
import net.minecraft.gametest.framework.GameTestSequence;
|
|
import net.minecraft.network.Connection;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.protocol.PacketFlow;
|
|
import net.minecraft.resources.ResourceKey;
|
|
import net.minecraft.server.commands.FillBiomeCommand;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.server.network.CommonListenerCookie;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.tags.TagKey;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.damagesource.DamageSource;
|
|
import net.minecraft.world.effect.MobEffect;
|
|
import net.minecraft.world.effect.MobEffectInstance;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntitySpawnReason;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
import net.minecraft.world.entity.npc.InventoryCarrier;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.alchemy.PotionContents;
|
|
import net.minecraft.world.item.context.UseOnContext;
|
|
import net.minecraft.world.level.GameType;
|
|
import net.minecraft.world.level.biome.Biome;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.ButtonBlock;
|
|
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
|
import net.minecraft.world.level.block.LeverBlock;
|
|
import net.minecraft.world.level.block.Mirror;
|
|
import net.minecraft.world.level.block.Rotation;
|
|
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
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.level.pathfinder.Path;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class GameTestHelper {
|
|
private final GameTestInfo testInfo;
|
|
private boolean finalCheckAdded;
|
|
|
|
public GameTestHelper(GameTestInfo testInfo) {
|
|
this.testInfo = testInfo;
|
|
}
|
|
|
|
public GameTestAssertException assertionException(Component description) {
|
|
return new GameTestAssertException(description, this.testInfo.getTick());
|
|
}
|
|
|
|
public GameTestAssertException assertionException(String descriptionId, Object ... arguments) {
|
|
return this.assertionException(Component.translatableEscape(descriptionId, arguments));
|
|
}
|
|
|
|
public GameTestAssertPosException assertionException(BlockPos pos, Component description) {
|
|
return new GameTestAssertPosException(description, this.absolutePos(pos), pos, this.testInfo.getTick());
|
|
}
|
|
|
|
public GameTestAssertPosException assertionException(BlockPos pos, String descriptionId, Object ... arguments) {
|
|
return this.assertionException(pos, Component.translatableEscape(descriptionId, arguments));
|
|
}
|
|
|
|
public ServerLevel getLevel() {
|
|
return this.testInfo.getLevel();
|
|
}
|
|
|
|
public BlockState getBlockState(BlockPos pos) {
|
|
return this.getLevel().getBlockState(this.absolutePos(pos));
|
|
}
|
|
|
|
public <T extends BlockEntity> T getBlockEntity(BlockPos pos, Class<T> type) {
|
|
BlockEntity blockEntity = this.getLevel().getBlockEntity(this.absolutePos(pos));
|
|
if (blockEntity == null) {
|
|
throw this.assertionException(pos, "test.error.missing_block_entity", new Object[0]);
|
|
}
|
|
if (type.isInstance(blockEntity)) {
|
|
return (T)((BlockEntity)type.cast(blockEntity));
|
|
}
|
|
throw this.assertionException(pos, "test.error.wrong_block_entity", blockEntity.getType().builtInRegistryHolder().getRegisteredName());
|
|
}
|
|
|
|
public void killAllEntities() {
|
|
this.killAllEntitiesOfClass(Entity.class);
|
|
}
|
|
|
|
public void killAllEntitiesOfClass(Class<? extends Entity> baseClass) {
|
|
AABB bounds = this.getBounds();
|
|
List<Entity> entities = this.getLevel().getEntitiesOfClass(baseClass, bounds.inflate(1.0), mob -> !(mob instanceof Player));
|
|
entities.forEach(entity -> entity.kill(this.getLevel()));
|
|
}
|
|
|
|
public ItemEntity spawnItem(Item item, Vec3 pos) {
|
|
ServerLevel level = this.getLevel();
|
|
Vec3 absoluteVec = this.absoluteVec(pos);
|
|
ItemEntity itemEntity = new ItemEntity(level, absoluteVec.x, absoluteVec.y, absoluteVec.z, new ItemStack(item, 1));
|
|
itemEntity.setDeltaMovement(0.0, 0.0, 0.0);
|
|
level.addFreshEntity(itemEntity);
|
|
return itemEntity;
|
|
}
|
|
|
|
public ItemEntity spawnItem(Item item, float x, float y, float z) {
|
|
return this.spawnItem(item, new Vec3(x, y, z));
|
|
}
|
|
|
|
public ItemEntity spawnItem(Item item, BlockPos pos) {
|
|
return this.spawnItem(item, pos.getX(), pos.getY(), pos.getZ());
|
|
}
|
|
|
|
public <E extends Entity> E spawn(EntityType<E> entityType, BlockPos pos) {
|
|
return this.spawn(entityType, Vec3.atBottomCenterOf(pos));
|
|
}
|
|
|
|
public <E extends Entity> List<E> spawn(EntityType<E> entityType, BlockPos pos, int amount) {
|
|
return this.spawn(entityType, Vec3.atBottomCenterOf(pos), amount);
|
|
}
|
|
|
|
public <E extends Entity> List<E> spawn(EntityType<E> entityType, Vec3 pos, int amount) {
|
|
ArrayList<E> entities = new ArrayList<E>();
|
|
for (int i = 0; i < amount; ++i) {
|
|
entities.add(this.spawn(entityType, pos));
|
|
}
|
|
return entities;
|
|
}
|
|
|
|
public <E extends Entity> E spawn(EntityType<E> entityType, Vec3 pos) {
|
|
return this.spawn(entityType, pos, null);
|
|
}
|
|
|
|
public <E extends Entity> E spawn(EntityType<E> entityType, Vec3 pos, @Nullable EntitySpawnReason spawnReason) {
|
|
ServerLevel level = this.getLevel();
|
|
E entity = entityType.create(level, EntitySpawnReason.STRUCTURE);
|
|
if (entity == null) {
|
|
throw this.assertionException(BlockPos.containing(pos), "test.error.spawn_failure", entityType.builtInRegistryHolder().getRegisteredName());
|
|
}
|
|
if (entity instanceof Mob) {
|
|
Mob mob = (Mob)entity;
|
|
mob.setPersistenceRequired();
|
|
}
|
|
Vec3 absoluteVec = this.absoluteVec(pos);
|
|
float yRot = ((Entity)entity).rotate(this.getTestRotation());
|
|
((Entity)entity).snapTo(absoluteVec.x, absoluteVec.y, absoluteVec.z, yRot, ((Entity)entity).getXRot());
|
|
((Entity)entity).setYBodyRot(yRot);
|
|
((Entity)entity).setYHeadRot(yRot);
|
|
if (spawnReason != null && entity instanceof Mob) {
|
|
Mob mob = (Mob)entity;
|
|
mob.finalizeSpawn(this.getLevel(), this.getLevel().getCurrentDifficultyAt(mob.blockPosition()), spawnReason, null);
|
|
}
|
|
level.addFreshEntityWithPassengers((Entity)entity);
|
|
return entity;
|
|
}
|
|
|
|
public <E extends Mob> E spawn(EntityType<E> entityType, int x, int y, int z, EntitySpawnReason entitySpawnReason) {
|
|
return (E)((Mob)this.spawn(entityType, new Vec3(x, y, z), entitySpawnReason));
|
|
}
|
|
|
|
public void hurt(Entity entity, DamageSource source, float damage) {
|
|
entity.hurtServer(this.getLevel(), source, damage);
|
|
}
|
|
|
|
public void kill(Entity entity) {
|
|
entity.kill(this.getLevel());
|
|
}
|
|
|
|
public <E extends Entity> E findOneEntity(EntityType<E> entityType) {
|
|
return this.findClosestEntity(entityType, 0, 0, 0, 2.147483647E9);
|
|
}
|
|
|
|
public <E extends Entity> E findClosestEntity(EntityType<E> entityType, int x, int y, int z, double distance) {
|
|
List<E> entities = this.findEntities(entityType, x, y, z, distance);
|
|
if (entities.isEmpty()) {
|
|
throw this.assertionException("test.error.expected_entity_around", entityType.getDescription(), x, y, z);
|
|
}
|
|
if (entities.size() > 1) {
|
|
throw this.assertionException("test.error.too_many_entities", entityType.toShortString(), x, y, z, entities.size());
|
|
}
|
|
Vec3 center = this.absoluteVec(new Vec3(x, y, z));
|
|
entities.sort((e1, e2) -> {
|
|
double d1 = e1.position().distanceTo(center);
|
|
double d2 = e2.position().distanceTo(center);
|
|
return Double.compare(d1, d2);
|
|
});
|
|
return (E)((Entity)entities.get(0));
|
|
}
|
|
|
|
public <E extends Entity> List<E> findEntities(EntityType<E> entityType, int x, int y, int z, double distance) {
|
|
return this.findEntities(entityType, Vec3.atBottomCenterOf(new BlockPos(x, y, z)), distance);
|
|
}
|
|
|
|
public <E extends Entity> List<E> findEntities(EntityType<E> entityType, Vec3 pos, double distance) {
|
|
ServerLevel level = this.getLevel();
|
|
Vec3 absoluteVec = this.absoluteVec(pos);
|
|
AABB structureBounds = this.testInfo.getStructureBounds();
|
|
AABB containedBounds = new AABB(absoluteVec.add(-distance, -distance, -distance), absoluteVec.add(distance, distance, distance));
|
|
return level.getEntities(entityType, structureBounds, e -> e.getBoundingBox().intersects(containedBounds) && e.isAlive());
|
|
}
|
|
|
|
public <E extends Entity> E spawn(EntityType<E> entityType, int x, int y, int z) {
|
|
return this.spawn(entityType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public <E extends Entity> E spawn(EntityType<E> entityType, float x, float y, float z) {
|
|
return this.spawn(entityType, new Vec3(x, y, z));
|
|
}
|
|
|
|
public <E extends Mob> E spawnWithNoFreeWill(EntityType<E> entityType, BlockPos pos) {
|
|
Mob entity = (Mob)this.spawn(entityType, pos);
|
|
entity.removeFreeWill();
|
|
return (E)entity;
|
|
}
|
|
|
|
public <E extends Mob> E spawnWithNoFreeWill(EntityType<E> entityType, int x, int y, int z) {
|
|
return this.spawnWithNoFreeWill(entityType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public <E extends Mob> E spawnWithNoFreeWill(EntityType<E> entityType, Vec3 pos) {
|
|
Mob entity = (Mob)this.spawn(entityType, pos);
|
|
entity.removeFreeWill();
|
|
return (E)entity;
|
|
}
|
|
|
|
public <E extends Mob> E spawnWithNoFreeWill(EntityType<E> entityType, float x, float y, float z) {
|
|
return this.spawnWithNoFreeWill(entityType, new Vec3(x, y, z));
|
|
}
|
|
|
|
public void moveTo(Mob mob, float x, float y, float z) {
|
|
Vec3 absoluteVec = this.absoluteVec(new Vec3(x, y, z));
|
|
mob.snapTo(absoluteVec.x, absoluteVec.y, absoluteVec.z, mob.getYRot(), mob.getXRot());
|
|
}
|
|
|
|
public GameTestSequence walkTo(Mob mob, BlockPos targetPos, float speedModifier) {
|
|
return this.startSequence().thenExecuteAfter(2, () -> {
|
|
Path path = mob.getNavigation().createPath(this.absolutePos(targetPos), 0);
|
|
mob.getNavigation().moveTo(path, (double)speedModifier);
|
|
});
|
|
}
|
|
|
|
public void pressButton(int x, int y, int z) {
|
|
this.pressButton(new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void pressButton(BlockPos buttonPos) {
|
|
this.assertBlockTag(BlockTags.BUTTONS, buttonPos);
|
|
BlockPos absolutePos = this.absolutePos(buttonPos);
|
|
BlockState blockState = this.getLevel().getBlockState(absolutePos);
|
|
ButtonBlock buttonBlock = (ButtonBlock)blockState.getBlock();
|
|
buttonBlock.press(blockState, this.getLevel(), absolutePos, null);
|
|
}
|
|
|
|
public void useBlock(BlockPos relativePos) {
|
|
this.useBlock(relativePos, this.makeMockPlayer(GameType.CREATIVE));
|
|
}
|
|
|
|
public void useBlock(BlockPos relativePos, Player player) {
|
|
BlockPos absolutePos = this.absolutePos(relativePos);
|
|
this.useBlock(relativePos, player, new BlockHitResult(Vec3.atCenterOf(absolutePos), Direction.NORTH, absolutePos, true));
|
|
}
|
|
|
|
public void useBlock(BlockPos relativePos, Player player, BlockHitResult hitResult) {
|
|
InteractionHand hand;
|
|
BlockPos absolutePos = this.absolutePos(relativePos);
|
|
BlockState blockState = this.getLevel().getBlockState(absolutePos);
|
|
InteractionResult itemInteractionResult = blockState.useItemOn(player.getItemInHand(hand = InteractionHand.MAIN_HAND), this.getLevel(), player, hand, hitResult);
|
|
if (itemInteractionResult.consumesAction()) {
|
|
return;
|
|
}
|
|
if (itemInteractionResult instanceof InteractionResult.TryEmptyHandInteraction && blockState.useWithoutItem(this.getLevel(), player, hitResult).consumesAction()) {
|
|
return;
|
|
}
|
|
UseOnContext context = new UseOnContext(player, hand, hitResult);
|
|
player.getItemInHand(hand).useOn(context);
|
|
}
|
|
|
|
public LivingEntity makeAboutToDrown(LivingEntity entity) {
|
|
entity.setAirSupply(0);
|
|
entity.setHealth(0.25f);
|
|
return entity;
|
|
}
|
|
|
|
public LivingEntity withLowHealth(LivingEntity entity) {
|
|
entity.setHealth(0.25f);
|
|
return entity;
|
|
}
|
|
|
|
public Player makeMockPlayer(final GameType gameType) {
|
|
return new Player(this, this.getLevel(), new GameProfile(UUID.randomUUID(), "test-mock-player")){
|
|
|
|
@Override
|
|
public GameType gameMode() {
|
|
return gameType;
|
|
}
|
|
|
|
@Override
|
|
public boolean isClientAuthoritative() {
|
|
return false;
|
|
}
|
|
};
|
|
}
|
|
|
|
@Deprecated(forRemoval=true)
|
|
public ServerPlayer makeMockServerPlayerInLevel() {
|
|
CommonListenerCookie cookie = CommonListenerCookie.createInitial(new GameProfile(UUID.randomUUID(), "test-mock-player"), false);
|
|
ServerPlayer player = new ServerPlayer(this, this.getLevel().getServer(), this.getLevel(), cookie.gameProfile(), cookie.clientInformation()){
|
|
|
|
@Override
|
|
public GameType gameMode() {
|
|
return GameType.CREATIVE;
|
|
}
|
|
};
|
|
Connection connection = new Connection(PacketFlow.SERVERBOUND);
|
|
EmbeddedChannel channel = new EmbeddedChannel(new ChannelHandler[]{connection});
|
|
this.getLevel().getServer().getPlayerList().placeNewPlayer(connection, player, cookie);
|
|
return player;
|
|
}
|
|
|
|
public void pullLever(int x, int y, int z) {
|
|
this.pullLever(new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void pullLever(BlockPos leverPos) {
|
|
this.assertBlockPresent(Blocks.LEVER, leverPos);
|
|
BlockPos absolutePos = this.absolutePos(leverPos);
|
|
BlockState blockState = this.getLevel().getBlockState(absolutePos);
|
|
LeverBlock leverBlock = (LeverBlock)blockState.getBlock();
|
|
leverBlock.pull(blockState, this.getLevel(), absolutePos, null);
|
|
}
|
|
|
|
public void pulseRedstone(BlockPos pos, long duration) {
|
|
this.setBlock(pos, Blocks.REDSTONE_BLOCK);
|
|
this.runAfterDelay(duration, () -> this.setBlock(pos, Blocks.AIR));
|
|
}
|
|
|
|
public void destroyBlock(BlockPos pos) {
|
|
this.getLevel().destroyBlock(this.absolutePos(pos), false, null);
|
|
}
|
|
|
|
public void setBlock(int x, int y, int z, Block block) {
|
|
this.setBlock(new BlockPos(x, y, z), block);
|
|
}
|
|
|
|
public void setBlock(int x, int y, int z, BlockState state) {
|
|
this.setBlock(new BlockPos(x, y, z), state);
|
|
}
|
|
|
|
public void setBlock(BlockPos blockPos, Block block) {
|
|
this.setBlock(blockPos, block.defaultBlockState());
|
|
}
|
|
|
|
public void setBlock(BlockPos blockPos, BlockState state) {
|
|
this.getLevel().setBlock(this.absolutePos(blockPos), state, 3);
|
|
}
|
|
|
|
public void setBlock(BlockPos blockPos, Block block, Direction direction) {
|
|
this.setBlock(blockPos, block.defaultBlockState(), direction);
|
|
}
|
|
|
|
public void setBlock(BlockPos blockPos, BlockState blockState, Direction direction) {
|
|
BlockState state = blockState;
|
|
if (blockState.hasProperty(HorizontalDirectionalBlock.FACING)) {
|
|
state = (BlockState)blockState.setValue(HorizontalDirectionalBlock.FACING, direction);
|
|
}
|
|
if (blockState.hasProperty(BlockStateProperties.FACING)) {
|
|
state = (BlockState)blockState.setValue(BlockStateProperties.FACING, direction);
|
|
}
|
|
this.getLevel().setBlock(this.absolutePos(blockPos), state, 3);
|
|
}
|
|
|
|
public void assertBlockPresent(Block blockType, int x, int y, int z) {
|
|
this.assertBlockPresent(blockType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void assertBlockPresent(Block blockType, BlockPos pos) {
|
|
BlockState state = this.getBlockState(pos);
|
|
this.assertBlock(pos, block -> state.is(blockType), block -> Component.translatable("test.error.expected_block", blockType.getName(), block.getName()));
|
|
}
|
|
|
|
public void assertBlockNotPresent(Block blockType, int x, int y, int z) {
|
|
this.assertBlockNotPresent(blockType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void assertBlockNotPresent(Block blockType, BlockPos pos) {
|
|
this.assertBlock(pos, block -> !this.getBlockState(pos).is(blockType), block -> Component.translatable("test.error.unexpected_block", blockType.getName()));
|
|
}
|
|
|
|
public void assertBlockTag(TagKey<Block> tag, BlockPos pos) {
|
|
this.assertBlockState(pos, state -> state.is(tag), state -> Component.translatable("test.error.expected_block_tag", Component.translationArg(tag.location()), state.getBlock().getName()));
|
|
}
|
|
|
|
public void succeedWhenBlockPresent(Block block, int x, int y, int z) {
|
|
this.succeedWhenBlockPresent(block, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void succeedWhenBlockPresent(Block block, BlockPos pos) {
|
|
this.succeedWhen(() -> this.assertBlockPresent(block, pos));
|
|
}
|
|
|
|
public void assertBlock(BlockPos pos, Predicate<Block> predicate, Function<Block, Component> errorMessage) {
|
|
this.assertBlockState(pos, blockState -> predicate.test(blockState.getBlock()), state -> (Component)errorMessage.apply(state.getBlock()));
|
|
}
|
|
|
|
public <T extends Comparable<T>> void assertBlockProperty(BlockPos pos, Property<T> property, T value) {
|
|
BlockState blockState = this.getBlockState(pos);
|
|
boolean hasProperty = blockState.hasProperty(property);
|
|
if (!hasProperty) {
|
|
throw this.assertionException(pos, "test.error.block_property_missing", property.getName(), value);
|
|
}
|
|
if (!blockState.getValue(property).equals(value)) {
|
|
throw this.assertionException(pos, "test.error.block_property_mismatch", property.getName(), value, blockState.getValue(property));
|
|
}
|
|
}
|
|
|
|
public <T extends Comparable<T>> void assertBlockProperty(BlockPos pos, Property<T> property, Predicate<T> predicate, Component errorMessage) {
|
|
this.assertBlockState(pos, blockState -> {
|
|
if (!blockState.hasProperty(property)) {
|
|
return false;
|
|
}
|
|
Object value = blockState.getValue(property);
|
|
return predicate.test(value);
|
|
}, state -> errorMessage);
|
|
}
|
|
|
|
public void assertBlockState(BlockPos pos, BlockState expected) {
|
|
BlockState blockState = this.getBlockState(pos);
|
|
if (!blockState.equals(expected)) {
|
|
throw this.assertionException(pos, "test.error.state_not_equal", expected, blockState);
|
|
}
|
|
}
|
|
|
|
public void assertBlockState(BlockPos pos, Predicate<BlockState> predicate, Function<BlockState, Component> errorMessage) {
|
|
BlockState blockState = this.getBlockState(pos);
|
|
if (!predicate.test(blockState)) {
|
|
throw this.assertionException(pos, errorMessage.apply(blockState));
|
|
}
|
|
}
|
|
|
|
public <T extends BlockEntity> void assertBlockEntityData(BlockPos pos, Class<T> type, Predicate<T> predicate, Supplier<Component> errorMessage) {
|
|
T blockEntity = this.getBlockEntity(pos, type);
|
|
if (!predicate.test(blockEntity)) {
|
|
throw this.assertionException(pos, errorMessage.get());
|
|
}
|
|
}
|
|
|
|
public void assertRedstoneSignal(BlockPos pos, Direction direction, IntPredicate levelPredicate, Supplier<Component> errorMessage) {
|
|
BlockPos blockPos = this.absolutePos(pos);
|
|
ServerLevel level = this.getLevel();
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
int signal = blockState.getSignal(level, blockPos, direction);
|
|
if (!levelPredicate.test(signal)) {
|
|
throw this.assertionException(pos, errorMessage.get());
|
|
}
|
|
}
|
|
|
|
public void assertEntityPresent(EntityType<?> entityType) {
|
|
if (!this.getLevel().hasEntities(entityType, this.getBounds(), Entity::isAlive)) {
|
|
throw this.assertionException("test.error.expected_entity_in_test", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public void assertEntityPresent(EntityType<?> entityType, int x, int y, int z) {
|
|
this.assertEntityPresent(entityType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void assertEntityPresent(EntityType<?> entityType, BlockPos pos) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
if (!this.getLevel().hasEntities(entityType, new AABB(absolutePos), Entity::isAlive)) {
|
|
throw this.assertionException(pos, "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public void assertEntityPresent(EntityType<?> entityType, AABB relativeAABB) {
|
|
AABB absoluteAABB = this.absoluteAABB(relativeAABB);
|
|
if (!this.getLevel().hasEntities(entityType, absoluteAABB, Entity::isAlive)) {
|
|
throw this.assertionException(BlockPos.containing(relativeAABB.getCenter()), "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public void assertEntitiesPresent(EntityType<?> entityType, int expectedEntities) {
|
|
List<Entity> entities = this.getLevel().getEntities(entityType, this.getBounds(), Entity::isAlive);
|
|
if (entities.size() != expectedEntities) {
|
|
throw this.assertionException("test.error.expected_entity_count", expectedEntities, entityType.getDescription(), entities.size());
|
|
}
|
|
}
|
|
|
|
public void assertEntitiesPresent(EntityType<?> entityType, BlockPos pos, int numOfExpectedEntities, double distance) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
List<?> entities = this.getEntities(entityType, pos, distance);
|
|
if (entities.size() != numOfExpectedEntities) {
|
|
throw this.assertionException(pos, "test.error.expected_entity_count", numOfExpectedEntities, entityType.getDescription(), entities.size());
|
|
}
|
|
}
|
|
|
|
public void assertEntityPresent(EntityType<?> entityType, BlockPos pos, double distance) {
|
|
List<?> entities = this.getEntities(entityType, pos, distance);
|
|
if (entities.isEmpty()) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
throw this.assertionException(pos, "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public <T extends Entity> List<T> getEntities(EntityType<T> entityType, BlockPos pos, double distance) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
return this.getLevel().getEntities(entityType, new AABB(absolutePos).inflate(distance), Entity::isAlive);
|
|
}
|
|
|
|
public <T extends Entity> List<T> getEntities(EntityType<T> entityType) {
|
|
return this.getLevel().getEntities(entityType, this.getBounds(), Entity::isAlive);
|
|
}
|
|
|
|
public void assertEntityInstancePresent(Entity entity, int x, int y, int z) {
|
|
this.assertEntityInstancePresent(entity, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void assertEntityInstancePresent(Entity entity, BlockPos pos) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
List<Entity> entities = this.getLevel().getEntities(entity.getType(), new AABB(absolutePos), Entity::isAlive);
|
|
entities.stream().filter(it -> it == entity).findFirst().orElseThrow(() -> this.assertionException(pos, "test.error.expected_entity", entity.getType().getDescription()));
|
|
}
|
|
|
|
public void assertItemEntityCountIs(Item itemType, BlockPos pos, double distance, int count) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
List<ItemEntity> entities = this.getLevel().getEntities(EntityType.ITEM, new AABB(absolutePos).inflate(distance), Entity::isAlive);
|
|
int num = 0;
|
|
for (ItemEntity entity : entities) {
|
|
ItemStack itemStack = entity.getItem();
|
|
if (!itemStack.is(itemType)) continue;
|
|
num += itemStack.getCount();
|
|
}
|
|
if (num != count) {
|
|
throw this.assertionException(pos, "test.error.expected_items_count", count, itemType.getName(), num);
|
|
}
|
|
}
|
|
|
|
public void assertItemEntityPresent(Item itemType, BlockPos pos, double distance) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
Predicate<ItemEntity> isSameItem = entity -> entity.isAlive() && entity.getItem().is(itemType);
|
|
if (!this.getLevel().hasEntities(EntityType.ITEM, new AABB(absolutePos).inflate(distance), isSameItem)) {
|
|
throw this.assertionException(pos, "test.error.expected_item", itemType.getName());
|
|
}
|
|
}
|
|
|
|
public void assertItemEntityNotPresent(Item itemType, BlockPos pos, double distance) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
Predicate<ItemEntity> isSameItem = entity -> entity.isAlive() && entity.getItem().is(itemType);
|
|
if (this.getLevel().hasEntities(EntityType.ITEM, new AABB(absolutePos).inflate(distance), isSameItem)) {
|
|
throw this.assertionException(pos, "test.error.unexpected_item", itemType.getName());
|
|
}
|
|
}
|
|
|
|
public void assertItemEntityPresent(Item itemType) {
|
|
Predicate<ItemEntity> isSameItem = entity -> entity.isAlive() && entity.getItem().is(itemType);
|
|
if (!this.getLevel().hasEntities(EntityType.ITEM, this.getBounds(), isSameItem)) {
|
|
throw this.assertionException("test.error.expected_item", itemType.getName());
|
|
}
|
|
}
|
|
|
|
public void assertItemEntityNotPresent(Item itemType) {
|
|
Predicate<ItemEntity> isSameItem = entity -> entity.isAlive() && entity.getItem().is(itemType);
|
|
if (this.getLevel().hasEntities(EntityType.ITEM, this.getBounds(), isSameItem)) {
|
|
throw this.assertionException("test.error.unexpected_item", itemType.getName());
|
|
}
|
|
}
|
|
|
|
public void assertEntityNotPresent(EntityType<?> entityType) {
|
|
List<Entity> entities = this.getLevel().getEntities(entityType, this.getBounds(), Entity::isAlive);
|
|
if (!entities.isEmpty()) {
|
|
throw this.assertionException(entities.getFirst().blockPosition(), "test.error.unexpected_entity", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public void assertEntityNotPresent(EntityType<?> entityType, int x, int y, int z) {
|
|
this.assertEntityNotPresent(entityType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void assertEntityNotPresent(EntityType<?> entityType, BlockPos pos) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
if (this.getLevel().hasEntities(entityType, new AABB(absolutePos), Entity::isAlive)) {
|
|
throw this.assertionException(pos, "test.error.unexpected_entity", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public void assertEntityNotPresent(EntityType<?> entityType, AABB relativeAABB) {
|
|
AABB absoluteAABB = this.absoluteAABB(relativeAABB);
|
|
List<Entity> entities = this.getLevel().getEntities(entityType, absoluteAABB, Entity::isAlive);
|
|
if (!entities.isEmpty()) {
|
|
throw this.assertionException(entities.getFirst().blockPosition(), "test.error.unexpected_entity", entityType.getDescription());
|
|
}
|
|
}
|
|
|
|
public void assertEntityTouching(EntityType<?> entityType, double x, double y, double z) {
|
|
Vec3 vec = new Vec3(x, y, z);
|
|
Vec3 absoluteVec = this.absoluteVec(vec);
|
|
Predicate<Entity> predicate = e -> e.getBoundingBox().intersects(absoluteVec, absoluteVec);
|
|
if (!this.getLevel().hasEntities(entityType, this.getBounds(), predicate)) {
|
|
throw this.assertionException("test.error.expected_entity_touching", entityType.getDescription(), absoluteVec.x(), absoluteVec.y(), absoluteVec.z(), x, y, z);
|
|
}
|
|
}
|
|
|
|
public void assertEntityNotTouching(EntityType<?> entityType, double x, double y, double z) {
|
|
Vec3 vec = new Vec3(x, y, z);
|
|
Vec3 absoluteVec = this.absoluteVec(vec);
|
|
Predicate<Entity> predicate = e -> !e.getBoundingBox().intersects(absoluteVec, absoluteVec);
|
|
if (!this.getLevel().hasEntities(entityType, this.getBounds(), predicate)) {
|
|
throw this.assertionException("test.error.expected_entity_not_touching", entityType.getDescription(), absoluteVec.x(), absoluteVec.y(), absoluteVec.z(), x, y, z);
|
|
}
|
|
}
|
|
|
|
public <E extends Entity, T> void assertEntityData(BlockPos pos, EntityType<E> entityType, Predicate<E> test) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
List<Entity> entities = this.getLevel().getEntities(entityType, new AABB(absolutePos), Entity::isAlive);
|
|
if (entities.isEmpty()) {
|
|
throw this.assertionException(pos, "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
for (Entity entity : entities) {
|
|
if (test.test(entity)) continue;
|
|
throw this.assertionException(entity.blockPosition(), "test.error.expected_entity_data_predicate", entity.getName());
|
|
}
|
|
}
|
|
|
|
public <E extends Entity, T> void assertEntityData(BlockPos pos, EntityType<E> entityType, Function<? super E, T> dataAccessor, @Nullable T data) {
|
|
this.assertEntityData(new AABB(pos), entityType, dataAccessor, data);
|
|
}
|
|
|
|
public <E extends Entity, T> void assertEntityData(AABB box, EntityType<E> entityType, Function<? super E, T> dataAccessor, @Nullable T data) {
|
|
List<Entity> entities = this.getLevel().getEntities(entityType, this.absoluteAABB(box), Entity::isAlive);
|
|
if (entities.isEmpty()) {
|
|
throw this.assertionException(BlockPos.containing(box.getBottomCenter()), "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
for (Entity entity : entities) {
|
|
T actual = dataAccessor.apply(entity);
|
|
if (Objects.equals(actual, data)) continue;
|
|
throw this.assertionException(BlockPos.containing(box.getBottomCenter()), "test.error.expected_entity_data", data, actual);
|
|
}
|
|
}
|
|
|
|
public <E extends LivingEntity> void assertEntityIsHolding(BlockPos pos, EntityType<E> entityType, Item item) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
List<LivingEntity> entities = this.getLevel().getEntities(entityType, new AABB(absolutePos), Entity::isAlive);
|
|
if (entities.isEmpty()) {
|
|
throw this.assertionException(pos, "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
for (LivingEntity entity : entities) {
|
|
if (!entity.isHolding(item)) continue;
|
|
return;
|
|
}
|
|
throw this.assertionException(pos, "test.error.expected_entity_holding", item.getName());
|
|
}
|
|
|
|
public <E extends Entity> void assertEntityInventoryContains(BlockPos pos, EntityType<E> entityType, Item item) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
List<Entity> entities = this.getLevel().getEntities(entityType, new AABB(absolutePos), rec$ -> ((Entity)rec$).isAlive());
|
|
if (entities.isEmpty()) {
|
|
throw this.assertionException(pos, "test.error.expected_entity", entityType.getDescription());
|
|
}
|
|
for (Entity entity : entities) {
|
|
if (!((InventoryCarrier)((Object)entity)).getInventory().hasAnyMatching(itemStack -> itemStack.is(item))) continue;
|
|
return;
|
|
}
|
|
throw this.assertionException(pos, "test.error.expected_entity_having", item.getName());
|
|
}
|
|
|
|
public void assertContainerEmpty(BlockPos pos) {
|
|
BaseContainerBlockEntity container = this.getBlockEntity(pos, BaseContainerBlockEntity.class);
|
|
if (!container.isEmpty()) {
|
|
throw this.assertionException(pos, "test.error.expected_empty_container", new Object[0]);
|
|
}
|
|
}
|
|
|
|
public void assertContainerContainsSingle(BlockPos pos, Item item) {
|
|
BaseContainerBlockEntity container = this.getBlockEntity(pos, BaseContainerBlockEntity.class);
|
|
if (container.countItem(item) != 1) {
|
|
throw this.assertionException(pos, "test.error.expected_container_contents_single", item.getName());
|
|
}
|
|
}
|
|
|
|
public void assertContainerContains(BlockPos pos, Item item) {
|
|
BaseContainerBlockEntity container = this.getBlockEntity(pos, BaseContainerBlockEntity.class);
|
|
if (container.countItem(item) == 0) {
|
|
throw this.assertionException(pos, "test.error.expected_container_contents", item.getName());
|
|
}
|
|
}
|
|
|
|
public void assertSameBlockStates(BoundingBox sourceBoundingBox, BlockPos targetBoundingBoxCorner) {
|
|
BlockPos.betweenClosedStream(sourceBoundingBox).forEach(sourcePos -> {
|
|
BlockPos targetPos = targetBoundingBoxCorner.offset(sourcePos.getX() - sourceBoundingBox.minX(), sourcePos.getY() - sourceBoundingBox.minY(), sourcePos.getZ() - sourceBoundingBox.minZ());
|
|
this.assertSameBlockState((BlockPos)sourcePos, targetPos);
|
|
});
|
|
}
|
|
|
|
public void assertSameBlockState(BlockPos sourcePos, BlockPos targetPos) {
|
|
BlockState targetState;
|
|
BlockState sourceState = this.getBlockState(sourcePos);
|
|
if (sourceState != (targetState = this.getBlockState(targetPos))) {
|
|
throw this.assertionException(sourcePos, "test.error.state_not_equal", targetState, sourceState);
|
|
}
|
|
}
|
|
|
|
public void assertAtTickTimeContainerContains(long time, BlockPos pos, Item item) {
|
|
this.runAtTickTime(time, () -> this.assertContainerContainsSingle(pos, item));
|
|
}
|
|
|
|
public void assertAtTickTimeContainerEmpty(long time, BlockPos pos) {
|
|
this.runAtTickTime(time, () -> this.assertContainerEmpty(pos));
|
|
}
|
|
|
|
public <E extends Entity, T> void succeedWhenEntityData(BlockPos pos, EntityType<E> entityType, Function<E, T> dataAccessor, T data) {
|
|
this.succeedWhen(() -> this.assertEntityData(pos, entityType, dataAccessor, data));
|
|
}
|
|
|
|
public void assertEntityPosition(Entity entity, AABB aabb, Component message) {
|
|
if (!aabb.contains(this.relativeVec(entity.position()))) {
|
|
throw this.assertionException(message);
|
|
}
|
|
}
|
|
|
|
public <E extends Entity> void assertEntityProperty(E entity, Predicate<E> test, Component description) {
|
|
if (!test.test(entity)) {
|
|
throw this.assertionException(entity.blockPosition(), "test.error.entity_property", entity.getName(), description);
|
|
}
|
|
}
|
|
|
|
public <E extends Entity, T> void assertEntityProperty(E entity, Function<E, T> test, T expected, Component description) {
|
|
T actual = test.apply(entity);
|
|
if (!actual.equals(expected)) {
|
|
throw this.assertionException(entity.blockPosition(), "test.error.entity_property_details", entity.getName(), description, actual, expected);
|
|
}
|
|
}
|
|
|
|
public void assertLivingEntityHasMobEffect(LivingEntity entity, Holder<MobEffect> mobEffect, int amplifier) {
|
|
MobEffectInstance mobEffectInstance = entity.getEffect(mobEffect);
|
|
if (mobEffectInstance == null || mobEffectInstance.getAmplifier() != amplifier) {
|
|
throw this.assertionException("test.error.expected_entity_effect", entity.getName(), PotionContents.getPotionDescription(mobEffect, amplifier));
|
|
}
|
|
}
|
|
|
|
public void succeedWhenEntityPresent(EntityType<?> entityType, int x, int y, int z) {
|
|
this.succeedWhenEntityPresent(entityType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void succeedWhenEntityPresent(EntityType<?> entityType, BlockPos pos) {
|
|
this.succeedWhen(() -> this.assertEntityPresent(entityType, pos));
|
|
}
|
|
|
|
public void succeedWhenEntityNotPresent(EntityType<?> entityType, int x, int y, int z) {
|
|
this.succeedWhenEntityNotPresent(entityType, new BlockPos(x, y, z));
|
|
}
|
|
|
|
public void succeedWhenEntityNotPresent(EntityType<?> entityType, BlockPos pos) {
|
|
this.succeedWhen(() -> this.assertEntityNotPresent(entityType, pos));
|
|
}
|
|
|
|
public void succeed() {
|
|
this.testInfo.succeed();
|
|
}
|
|
|
|
private void ensureSingleFinalCheck() {
|
|
if (this.finalCheckAdded) {
|
|
throw new IllegalStateException("This test already has final clause");
|
|
}
|
|
this.finalCheckAdded = true;
|
|
}
|
|
|
|
public void succeedIf(Runnable asserter) {
|
|
this.ensureSingleFinalCheck();
|
|
this.testInfo.createSequence().thenWaitUntil(0L, asserter).thenSucceed();
|
|
}
|
|
|
|
public void succeedWhen(Runnable asserter) {
|
|
this.ensureSingleFinalCheck();
|
|
this.testInfo.createSequence().thenWaitUntil(asserter).thenSucceed();
|
|
}
|
|
|
|
public void succeedOnTickWhen(int tick, Runnable asserter) {
|
|
this.ensureSingleFinalCheck();
|
|
this.testInfo.createSequence().thenWaitUntil(tick, asserter).thenSucceed();
|
|
}
|
|
|
|
public void runAtTickTime(long time, Runnable asserter) {
|
|
this.testInfo.setRunAtTickTime(time, asserter);
|
|
}
|
|
|
|
public void runAfterDelay(long ticksToDelay, Runnable whatToRun) {
|
|
this.runAtTickTime((long)this.testInfo.getTick() + ticksToDelay, whatToRun);
|
|
}
|
|
|
|
public void randomTick(BlockPos pos) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
ServerLevel level = this.getLevel();
|
|
level.getBlockState(absolutePos).randomTick(level, absolutePos, level.random);
|
|
}
|
|
|
|
public void tickBlock(BlockPos pos) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
ServerLevel level = this.getLevel();
|
|
level.getBlockState(absolutePos).tick(level, absolutePos, level.random);
|
|
}
|
|
|
|
public void tickPrecipitation(BlockPos pos) {
|
|
BlockPos absolutePos = this.absolutePos(pos);
|
|
ServerLevel level = this.getLevel();
|
|
level.tickPrecipitation(absolutePos);
|
|
}
|
|
|
|
public void tickPrecipitation() {
|
|
AABB aabb = this.getRelativeBounds();
|
|
int maxX = (int)Math.floor(aabb.maxX);
|
|
int maxZ = (int)Math.floor(aabb.maxZ);
|
|
int maxY = (int)Math.floor(aabb.maxY);
|
|
for (int x = (int)Math.floor(aabb.minX); x < maxX; ++x) {
|
|
for (int z = (int)Math.floor(aabb.minZ); z < maxZ; ++z) {
|
|
this.tickPrecipitation(new BlockPos(x, maxY, z));
|
|
}
|
|
}
|
|
}
|
|
|
|
public int getHeight(Heightmap.Types heightmap, int x, int z) {
|
|
BlockPos absolutePos = this.absolutePos(new BlockPos(x, 0, z));
|
|
return this.relativePos(this.getLevel().getHeightmapPos(heightmap, absolutePos)).getY();
|
|
}
|
|
|
|
public void fail(Component message, BlockPos pos) {
|
|
throw this.assertionException(pos, message);
|
|
}
|
|
|
|
public void fail(Component message, Entity entity) {
|
|
throw this.assertionException(entity.blockPosition(), message);
|
|
}
|
|
|
|
public void fail(Component message) {
|
|
throw this.assertionException(message);
|
|
}
|
|
|
|
public void fail(String message) {
|
|
throw this.assertionException(Component.literal(message));
|
|
}
|
|
|
|
public void failIf(Runnable asserter) {
|
|
this.testInfo.createSequence().thenWaitUntil(asserter).thenFail(() -> this.assertionException("test.error.fail", new Object[0]));
|
|
}
|
|
|
|
public void failIfEver(Runnable asserter) {
|
|
LongStream.range(this.testInfo.getTick(), this.testInfo.getTimeoutTicks()).forEach(i -> this.testInfo.setRunAtTickTime(i, asserter::run));
|
|
}
|
|
|
|
public GameTestSequence startSequence() {
|
|
return this.testInfo.createSequence();
|
|
}
|
|
|
|
public BlockPos absolutePos(BlockPos relativePos) {
|
|
BlockPos testPos = this.testInfo.getTestOrigin();
|
|
BlockPos absolutePosBeforeTranform = testPos.offset(relativePos);
|
|
return StructureTemplate.transform(absolutePosBeforeTranform, Mirror.NONE, this.testInfo.getRotation(), testPos);
|
|
}
|
|
|
|
public BlockPos relativePos(BlockPos absolutePos) {
|
|
BlockPos testPos = this.testInfo.getTestOrigin();
|
|
Rotation inverseRotation = this.testInfo.getRotation().getRotated(Rotation.CLOCKWISE_180);
|
|
BlockPos absolutePosBeforeTransform = StructureTemplate.transform(absolutePos, Mirror.NONE, inverseRotation, testPos);
|
|
return absolutePosBeforeTransform.subtract(testPos);
|
|
}
|
|
|
|
public AABB absoluteAABB(AABB relativeAABB) {
|
|
Vec3 min = this.absoluteVec(relativeAABB.getMinPosition());
|
|
Vec3 max = this.absoluteVec(relativeAABB.getMaxPosition());
|
|
return new AABB(min, max);
|
|
}
|
|
|
|
public AABB relativeAABB(AABB absoluteAABB) {
|
|
Vec3 min = this.relativeVec(absoluteAABB.getMinPosition());
|
|
Vec3 max = this.relativeVec(absoluteAABB.getMaxPosition());
|
|
return new AABB(min, max);
|
|
}
|
|
|
|
public Vec3 absoluteVec(Vec3 relativeVec) {
|
|
Vec3 testPosVec = Vec3.atLowerCornerOf(this.testInfo.getTestOrigin());
|
|
return StructureTemplate.transform(testPosVec.add(relativeVec), Mirror.NONE, this.testInfo.getRotation(), this.testInfo.getTestOrigin());
|
|
}
|
|
|
|
public Vec3 relativeVec(Vec3 absoluteVec) {
|
|
Vec3 testPosVec = Vec3.atLowerCornerOf(this.testInfo.getTestOrigin());
|
|
return StructureTemplate.transform(absoluteVec.subtract(testPosVec), Mirror.NONE, this.testInfo.getRotation(), this.testInfo.getTestOrigin());
|
|
}
|
|
|
|
public Rotation getTestRotation() {
|
|
return this.testInfo.getRotation();
|
|
}
|
|
|
|
public Direction getTestDirection() {
|
|
return this.testInfo.getRotation().rotate(Direction.SOUTH);
|
|
}
|
|
|
|
public void assertTrue(boolean condition, Component errorMessage) {
|
|
if (!condition) {
|
|
throw this.assertionException(errorMessage);
|
|
}
|
|
}
|
|
|
|
public void assertTrue(boolean condition, String errorMessage) {
|
|
this.assertTrue(condition, Component.literal(errorMessage));
|
|
}
|
|
|
|
public <N> void assertValueEqual(N value, N expected, String valueName) {
|
|
this.assertValueEqual(value, expected, Component.literal(valueName));
|
|
}
|
|
|
|
public <N> void assertValueEqual(N value, N expected, Component valueName) {
|
|
if (!value.equals(expected)) {
|
|
throw this.assertionException("test.error.value_not_equal", valueName, value, expected);
|
|
}
|
|
}
|
|
|
|
public void assertFalse(boolean condition, Component errorMessage) {
|
|
this.assertTrue(!condition, errorMessage);
|
|
}
|
|
|
|
public void assertFalse(boolean condition, String errorMessage) {
|
|
this.assertFalse(condition, Component.literal(errorMessage));
|
|
}
|
|
|
|
public long getTick() {
|
|
return this.testInfo.getTick();
|
|
}
|
|
|
|
public AABB getBounds() {
|
|
return this.testInfo.getStructureBounds();
|
|
}
|
|
|
|
public AABB getRelativeBounds() {
|
|
AABB absolute = this.testInfo.getStructureBounds();
|
|
Rotation rotation = this.testInfo.getRotation();
|
|
switch (rotation) {
|
|
case COUNTERCLOCKWISE_90:
|
|
case CLOCKWISE_90: {
|
|
return new AABB(0.0, 0.0, 0.0, absolute.getZsize(), absolute.getYsize(), absolute.getXsize());
|
|
}
|
|
}
|
|
return new AABB(0.0, 0.0, 0.0, absolute.getXsize(), absolute.getYsize(), absolute.getZsize());
|
|
}
|
|
|
|
public void forEveryBlockInStructure(Consumer<BlockPos> forBlock) {
|
|
AABB aabb = this.getRelativeBounds().contract(1.0, 1.0, 1.0);
|
|
BlockPos.MutableBlockPos.betweenClosedStream(aabb).forEach(forBlock);
|
|
}
|
|
|
|
public void onEachTick(Runnable action) {
|
|
LongStream.range(this.testInfo.getTick(), this.testInfo.getTimeoutTicks()).forEach(i -> this.testInfo.setRunAtTickTime(i, action::run));
|
|
}
|
|
|
|
public void placeAt(Player player, ItemStack blockStack, BlockPos pos, Direction face) {
|
|
BlockPos absolute = this.absolutePos(pos.relative(face));
|
|
BlockHitResult hitResult = new BlockHitResult(Vec3.atCenterOf(absolute), face, absolute, false);
|
|
UseOnContext context = new UseOnContext(player, InteractionHand.MAIN_HAND, hitResult);
|
|
blockStack.useOn(context);
|
|
}
|
|
|
|
public void setBiome(ResourceKey<Biome> biome) {
|
|
AABB bounds = this.getBounds();
|
|
BlockPos low = BlockPos.containing(bounds.minX, bounds.minY, bounds.minZ);
|
|
BlockPos high = BlockPos.containing(bounds.maxX, bounds.maxY, bounds.maxZ);
|
|
Either<Integer, CommandSyntaxException> result = FillBiomeCommand.fill(this.getLevel(), low, high, this.getLevel().registryAccess().lookupOrThrow(Registries.BIOME).getOrThrow(biome));
|
|
if (result.right().isPresent()) {
|
|
throw this.assertionException("test.error.set_biome", new Object[0]);
|
|
}
|
|
}
|
|
}
|
|
|