Skip to content

Commit

Permalink
Add /assert items
Browse files Browse the repository at this point in the history
  • Loading branch information
misode committed Mar 21, 2024
1 parent 3d229ab commit 00774a5
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 2 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ minecraft_version=24w12a
loader_version=0.15.7

# Mod Properties
mod_version=1.7.0-beta2
mod_version=1.7.0-beta3
maven_group=io.github.misode
archives_base_name=packtest

Expand Down
13 changes: 13 additions & 0 deletions src/main/java/io/github/misode/packtest/PackTestItemPredicate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.github.misode.packtest;

import net.minecraft.commands.arguments.item.ItemPredicateArgument;
import net.minecraft.world.item.ItemStack;

import java.util.function.Predicate;

public record PackTestItemPredicate(Predicate<ItemStack> predicate, String source) implements ItemPredicateArgument.Result {
@Override
public boolean test(ItemStack itemStack) {
return predicate.test(itemStack);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.ContextChain;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.Dynamic3CommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import io.github.misode.packtest.*;
import it.unimi.dsi.fastutil.ints.IntList;
import net.minecraft.advancements.critereon.MinMaxBounds;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.arguments.*;
import net.minecraft.commands.arguments.blocks.BlockPredicateArgument;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.commands.arguments.item.ItemPredicateArgument;
import net.minecraft.commands.arguments.selector.EntitySelector;
import net.minecraft.commands.execution.ChainModifiers;
import net.minecraft.commands.execution.CustomCommandExecutor;
Expand All @@ -32,7 +35,11 @@
import net.minecraft.server.ReloadableServerRegistries;
import net.minecraft.server.commands.data.DataCommands;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.inventory.SlotRange;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootParams;
Expand Down Expand Up @@ -61,6 +68,9 @@ public class AssertCommand {
private static final SimpleCommandExceptionType ERROR_NO_HELPER = new SimpleCommandExceptionType(
Component.literal("Not inside a test")
);
private static final Dynamic3CommandExceptionType ERROR_SOURCE_NOT_A_CONTAINER = new Dynamic3CommandExceptionType(
(x, y, z) -> Component.translatableEscape("commands.item.source.not_a_container", x, y, z)
);
private static final SuggestionProvider<CommandSourceStack> SUGGEST_PREDICATE = (ctx, suggestions) -> {
ReloadableServerRegistries.Holder registries = ctx.getSource().getServer().reloadableRegistries();
return SharedSuggestionProvider.suggestResource(registries.getKeys(Registries.PREDICATE), suggestions);
Expand Down Expand Up @@ -92,6 +102,17 @@ public static void addConditions(LiteralArgumentBuilder<CommandSourceStack> buil
.then(argument("predicate", ResourceOrIdArgument.lootPredicate(buildContext))
.suggests(SUGGEST_PREDICATE)
.executes(expect.apply(AssertCommand::assertPredicate))))
.then(literal("items")
.then(literal("entity")
.then(argument("entities", EntityArgument.entities())
.then(argument("slots", SlotsArgument.slots())
.then(argument("item_predicate", ItemPredicateArgument.itemPredicate(buildContext))
.executes(expect.apply(AssertCommand::assertItemsEntity))))))
.then(literal("block")
.then(argument("pos", BlockPosArgument.blockPos())
.then(argument("slots", SlotsArgument.slots())
.then(argument("item_predicate", ItemPredicateArgument.itemPredicate(buildContext))
.executes(expect.apply(AssertCommand::assertItemsBlock)))))))
.then(literal("score")
.then(argument("target", ScoreHolderArgument.scoreHolder())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
Expand Down Expand Up @@ -177,6 +198,59 @@ private static AssertResult assertPredicate(CommandContext<CommandSourceStack> c
return err(expected);
}

private static AssertResult assertItemsEntity(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
EntitySelector selector = ctx.getArgument("entities", EntitySelector.class);
String selectorSource = ((PackTestArgumentSource)selector).packtest$getSource();
List<? extends Entity> entities = selector.findEntities(ctx.getSource());
SlotRange slotRange = SlotsArgument.getSlots(ctx, "slots");
ItemPredicateArgument.Result itemPredicate = ItemPredicateArgument.getItemPredicate(ctx, "item_predicate");
String itemPredicateSource = ((PackTestItemPredicate)itemPredicate).source();
int count = 0;
for(Entity entity : entities) {
IntList slots = slotRange.slots();
for(int i = 0; i < slots.size(); ++i) {
ItemStack itemStack = entity.getSlot(slots.getInt(i)).get();
if (itemPredicate.test(itemStack)) {
count += itemStack.getCount();
}
}
}
String expected = selectorSource + " to have items " + itemPredicateSource;
if (count > 0) {
return ok(expected);
}
return err(expected);
}

private static AssertResult assertItemsBlock(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
SlotRange slotRange = SlotsArgument.getSlots(ctx, "slots");
ItemPredicateArgument.Result itemPredicate = ItemPredicateArgument.getItemPredicate(ctx, "item_predicate");
String itemPredicateSource = ((PackTestItemPredicate)itemPredicate).source();
BlockEntity blockEntity = ctx.getSource().getLevel().getBlockEntity(pos);
if (blockEntity instanceof Container container) {
int count = 0;
int lvt6 = container.getContainerSize();
IntList slots = slotRange.slots();
for(int i = 0; i < slots.size(); ++i) {
int slot = slots.getInt(i);
if (slot >= 0 && slot < lvt6) {
ItemStack itemStack = container.getItem(slot);
if (itemPredicate.test(itemStack)) {
count += itemStack.getCount();
}
}
}
String expected = "block to have items " + itemPredicateSource;
if (count > 0) {
return ok(expected);
}
return err(expected);
} else {
throw ERROR_SOURCE_NOT_A_CONTAINER.create(pos.getX(), pos.getY(), pos.getZ());
}
}

private static LiteralArgumentBuilder<CommandSourceStack> addScoreCheck(String op, BiPredicate<Integer, Integer> predicate, Function<AssertPredicate, Command<CommandSourceStack>> expect) {
return literal(op)
.then(argument("source", ScoreHolderArgument.scoreHolder())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.github.misode.packtest.mixin;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalIntRef;
import com.mojang.brigadier.StringReader;
import io.github.misode.packtest.PackTestItemPredicate;
import net.minecraft.commands.arguments.item.ItemPredicateArgument;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(ItemPredicateArgument.class)
public class ItemPredicateArgumentMixin {

@Inject(method = "parse(Lcom/mojang/brigadier/StringReader;)Lnet/minecraft/commands/arguments/item/ItemPredicateArgument$Result;", at = @At("HEAD"))
private void getCursor(StringReader stringReader, CallbackInfoReturnable<ItemPredicateArgument.Result> cir, @Share("cursor") LocalIntRef cursorRef) {
cursorRef.set(stringReader.getCursor());
}

@ModifyReturnValue(method = "parse(Lcom/mojang/brigadier/StringReader;)Lnet/minecraft/commands/arguments/item/ItemPredicateArgument$Result;", at = @At("RETURN"))
private ItemPredicateArgument.Result returnPredicate(ItemPredicateArgument.Result predicate, @Local StringReader reader, @Share("cursor") LocalIntRef cursorRef) {
return new PackTestItemPredicate(predicate, reader.getRead().substring(cursorRef.get()));
}
}
3 changes: 2 additions & 1 deletion src/main/resources/packtest.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
"EntitySelectorMixin",
"ForceLoadCommandMixin",
"GameTestBatchMixin",
"GameTestRunner1Mixin",
"GameTestHelperMixin",
"GameTestInfoMixin",
"GameTestRegistryMixin",
"GameTestRunner1Mixin",
"GameTestSequenceMixin",
"GameTestServerMixin",
"ItemPredicateArgumentMixin",
"LogTestReporterMixin",
"LootDataTypeMixin",
"MinecraftServerMixin",
Expand Down

0 comments on commit 00774a5

Please sign in to comment.