Skip to content

Commit 00774a5

Browse files
committed
Add /assert items
1 parent 3d229ab commit 00774a5

5 files changed

Lines changed: 117 additions & 2 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ minecraft_version=24w12a
88
loader_version=0.15.7
99

1010
# Mod Properties
11-
mod_version=1.7.0-beta2
11+
mod_version=1.7.0-beta3
1212
maven_group=io.github.misode
1313
archives_base_name=packtest
1414

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.github.misode.packtest;
2+
3+
import net.minecraft.commands.arguments.item.ItemPredicateArgument;
4+
import net.minecraft.world.item.ItemStack;
5+
6+
import java.util.function.Predicate;
7+
8+
public record PackTestItemPredicate(Predicate<ItemStack> predicate, String source) implements ItemPredicateArgument.Result {
9+
@Override
10+
public boolean test(ItemStack itemStack) {
11+
return predicate.test(itemStack);
12+
}
13+
}

src/main/java/io/github/misode/packtest/commands/AssertCommand.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
import com.mojang.brigadier.context.CommandContext;
88
import com.mojang.brigadier.context.ContextChain;
99
import com.mojang.brigadier.exceptions.CommandSyntaxException;
10+
import com.mojang.brigadier.exceptions.Dynamic3CommandExceptionType;
1011
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
1112
import com.mojang.brigadier.suggestion.SuggestionProvider;
1213
import io.github.misode.packtest.*;
14+
import it.unimi.dsi.fastutil.ints.IntList;
1315
import net.minecraft.advancements.critereon.MinMaxBounds;
1416
import net.minecraft.commands.CommandBuildContext;
1517
import net.minecraft.commands.CommandSourceStack;
1618
import net.minecraft.commands.SharedSuggestionProvider;
1719
import net.minecraft.commands.arguments.*;
1820
import net.minecraft.commands.arguments.blocks.BlockPredicateArgument;
1921
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
22+
import net.minecraft.commands.arguments.item.ItemPredicateArgument;
2023
import net.minecraft.commands.arguments.selector.EntitySelector;
2124
import net.minecraft.commands.execution.ChainModifiers;
2225
import net.minecraft.commands.execution.CustomCommandExecutor;
@@ -32,7 +35,11 @@
3235
import net.minecraft.server.ReloadableServerRegistries;
3336
import net.minecraft.server.commands.data.DataCommands;
3437
import net.minecraft.server.level.ServerPlayer;
38+
import net.minecraft.world.Container;
3539
import net.minecraft.world.entity.Entity;
40+
import net.minecraft.world.inventory.SlotRange;
41+
import net.minecraft.world.item.ItemStack;
42+
import net.minecraft.world.level.block.entity.BlockEntity;
3643
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
3744
import net.minecraft.world.level.storage.loot.LootContext;
3845
import net.minecraft.world.level.storage.loot.LootParams;
@@ -61,6 +68,9 @@ public class AssertCommand {
6168
private static final SimpleCommandExceptionType ERROR_NO_HELPER = new SimpleCommandExceptionType(
6269
Component.literal("Not inside a test")
6370
);
71+
private static final Dynamic3CommandExceptionType ERROR_SOURCE_NOT_A_CONTAINER = new Dynamic3CommandExceptionType(
72+
(x, y, z) -> Component.translatableEscape("commands.item.source.not_a_container", x, y, z)
73+
);
6474
private static final SuggestionProvider<CommandSourceStack> SUGGEST_PREDICATE = (ctx, suggestions) -> {
6575
ReloadableServerRegistries.Holder registries = ctx.getSource().getServer().reloadableRegistries();
6676
return SharedSuggestionProvider.suggestResource(registries.getKeys(Registries.PREDICATE), suggestions);
@@ -92,6 +102,17 @@ public static void addConditions(LiteralArgumentBuilder<CommandSourceStack> buil
92102
.then(argument("predicate", ResourceOrIdArgument.lootPredicate(buildContext))
93103
.suggests(SUGGEST_PREDICATE)
94104
.executes(expect.apply(AssertCommand::assertPredicate))))
105+
.then(literal("items")
106+
.then(literal("entity")
107+
.then(argument("entities", EntityArgument.entities())
108+
.then(argument("slots", SlotsArgument.slots())
109+
.then(argument("item_predicate", ItemPredicateArgument.itemPredicate(buildContext))
110+
.executes(expect.apply(AssertCommand::assertItemsEntity))))))
111+
.then(literal("block")
112+
.then(argument("pos", BlockPosArgument.blockPos())
113+
.then(argument("slots", SlotsArgument.slots())
114+
.then(argument("item_predicate", ItemPredicateArgument.itemPredicate(buildContext))
115+
.executes(expect.apply(AssertCommand::assertItemsBlock)))))))
95116
.then(literal("score")
96117
.then(argument("target", ScoreHolderArgument.scoreHolder())
97118
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
@@ -177,6 +198,59 @@ private static AssertResult assertPredicate(CommandContext<CommandSourceStack> c
177198
return err(expected);
178199
}
179200

201+
private static AssertResult assertItemsEntity(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
202+
EntitySelector selector = ctx.getArgument("entities", EntitySelector.class);
203+
String selectorSource = ((PackTestArgumentSource)selector).packtest$getSource();
204+
List<? extends Entity> entities = selector.findEntities(ctx.getSource());
205+
SlotRange slotRange = SlotsArgument.getSlots(ctx, "slots");
206+
ItemPredicateArgument.Result itemPredicate = ItemPredicateArgument.getItemPredicate(ctx, "item_predicate");
207+
String itemPredicateSource = ((PackTestItemPredicate)itemPredicate).source();
208+
int count = 0;
209+
for(Entity entity : entities) {
210+
IntList slots = slotRange.slots();
211+
for(int i = 0; i < slots.size(); ++i) {
212+
ItemStack itemStack = entity.getSlot(slots.getInt(i)).get();
213+
if (itemPredicate.test(itemStack)) {
214+
count += itemStack.getCount();
215+
}
216+
}
217+
}
218+
String expected = selectorSource + " to have items " + itemPredicateSource;
219+
if (count > 0) {
220+
return ok(expected);
221+
}
222+
return err(expected);
223+
}
224+
225+
private static AssertResult assertItemsBlock(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
226+
BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
227+
SlotRange slotRange = SlotsArgument.getSlots(ctx, "slots");
228+
ItemPredicateArgument.Result itemPredicate = ItemPredicateArgument.getItemPredicate(ctx, "item_predicate");
229+
String itemPredicateSource = ((PackTestItemPredicate)itemPredicate).source();
230+
BlockEntity blockEntity = ctx.getSource().getLevel().getBlockEntity(pos);
231+
if (blockEntity instanceof Container container) {
232+
int count = 0;
233+
int lvt6 = container.getContainerSize();
234+
IntList slots = slotRange.slots();
235+
for(int i = 0; i < slots.size(); ++i) {
236+
int slot = slots.getInt(i);
237+
if (slot >= 0 && slot < lvt6) {
238+
ItemStack itemStack = container.getItem(slot);
239+
if (itemPredicate.test(itemStack)) {
240+
count += itemStack.getCount();
241+
}
242+
}
243+
}
244+
String expected = "block to have items " + itemPredicateSource;
245+
if (count > 0) {
246+
return ok(expected);
247+
}
248+
return err(expected);
249+
} else {
250+
throw ERROR_SOURCE_NOT_A_CONTAINER.create(pos.getX(), pos.getY(), pos.getZ());
251+
}
252+
}
253+
180254
private static LiteralArgumentBuilder<CommandSourceStack> addScoreCheck(String op, BiPredicate<Integer, Integer> predicate, Function<AssertPredicate, Command<CommandSourceStack>> expect) {
181255
return literal(op)
182256
.then(argument("source", ScoreHolderArgument.scoreHolder())
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.github.misode.packtest.mixin;
2+
3+
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
4+
import com.llamalad7.mixinextras.sugar.Local;
5+
import com.llamalad7.mixinextras.sugar.Share;
6+
import com.llamalad7.mixinextras.sugar.ref.LocalIntRef;
7+
import com.mojang.brigadier.StringReader;
8+
import io.github.misode.packtest.PackTestItemPredicate;
9+
import net.minecraft.commands.arguments.item.ItemPredicateArgument;
10+
import org.spongepowered.asm.mixin.Mixin;
11+
import org.spongepowered.asm.mixin.injection.At;
12+
import org.spongepowered.asm.mixin.injection.Inject;
13+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
14+
15+
@Mixin(ItemPredicateArgument.class)
16+
public class ItemPredicateArgumentMixin {
17+
18+
@Inject(method = "parse(Lcom/mojang/brigadier/StringReader;)Lnet/minecraft/commands/arguments/item/ItemPredicateArgument$Result;", at = @At("HEAD"))
19+
private void getCursor(StringReader stringReader, CallbackInfoReturnable<ItemPredicateArgument.Result> cir, @Share("cursor") LocalIntRef cursorRef) {
20+
cursorRef.set(stringReader.getCursor());
21+
}
22+
23+
@ModifyReturnValue(method = "parse(Lcom/mojang/brigadier/StringReader;)Lnet/minecraft/commands/arguments/item/ItemPredicateArgument$Result;", at = @At("RETURN"))
24+
private ItemPredicateArgument.Result returnPredicate(ItemPredicateArgument.Result predicate, @Local StringReader reader, @Share("cursor") LocalIntRef cursorRef) {
25+
return new PackTestItemPredicate(predicate, reader.getRead().substring(cursorRef.get()));
26+
}
27+
}

src/main/resources/packtest.mixins.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
"EntitySelectorMixin",
1414
"ForceLoadCommandMixin",
1515
"GameTestBatchMixin",
16-
"GameTestRunner1Mixin",
1716
"GameTestHelperMixin",
1817
"GameTestInfoMixin",
1918
"GameTestRegistryMixin",
19+
"GameTestRunner1Mixin",
2020
"GameTestSequenceMixin",
2121
"GameTestServerMixin",
22+
"ItemPredicateArgumentMixin",
2223
"LogTestReporterMixin",
2324
"LootDataTypeMixin",
2425
"MinecraftServerMixin",

0 commit comments

Comments
 (0)