InventoryChangeTrigger.java

net.minecraft.advancements.criterion.InventoryChangeTrigger

信息

  • 全限定名:net.minecraft.advancements.criterion.InventoryChangeTrigger
  • 类型:public class
  • 包:net.minecraft.advancements.criterion
  • 源码路径:src/main/java/net/minecraft/advancements/criterion/InventoryChangeTrigger.java
  • 起始行号:L18
  • 继承:SimpleCriterionTrigger<InventoryChangeTrigger.TriggerInstance>
  • 职责:

    TODO

字段/常量

内部类/嵌套类型

  • net.minecraft.advancements.criterion.InventoryChangeTrigger.TriggerInstance

    • 类型: record
    • 修饰符: public
    • 源码定位: L48
    • 说明:

      TODO

  • net.minecraft.advancements.criterion.InventoryChangeTrigger.TriggerInstance.Slots

    • 类型: record
    • 修饰符: public
    • 源码定位: L108
    • 说明:

      TODO

构造器

方法

下面的方法块按源码顺序生成。

public Codec<InventoryChangeTrigger.TriggerInstance> codec() @ L19

  • 方法名:codec
  • 源码定位:L19
  • 返回类型:Codec<InventoryChangeTrigger.TriggerInstance>
  • 修饰符:public

参数:

说明:

TODO

public void trigger(ServerPlayer player, Inventory inventory, ItemStack changedItem) @ L24

  • 方法名:trigger
  • 源码定位:L24
  • 返回类型:void
  • 修饰符:public

参数:

  • player: ServerPlayer
  • inventory: Inventory
  • changedItem: ItemStack

说明:

TODO

private void trigger(ServerPlayer player, Inventory inventory, ItemStack changedItem, int slotsFull, int slotsEmpty, int slotsOccupied) @ L44

  • 方法名:trigger
  • 源码定位:L44
  • 返回类型:void
  • 修饰符:private

参数:

  • player: ServerPlayer
  • inventory: Inventory
  • changedItem: ItemStack
  • slotsFull: int
  • slotsEmpty: int
  • slotsOccupied: int

说明:

TODO

代码

public class InventoryChangeTrigger extends SimpleCriterionTrigger<InventoryChangeTrigger.TriggerInstance> {
    @Override
    public Codec<InventoryChangeTrigger.TriggerInstance> codec() {
        return InventoryChangeTrigger.TriggerInstance.CODEC;
    }
 
    public void trigger(ServerPlayer player, Inventory inventory, ItemStack changedItem) {
        int slotsFull = 0;
        int slotsEmpty = 0;
        int slotsOccupied = 0;
 
        for (int slot = 0; slot < inventory.getContainerSize(); slot++) {
            ItemStack itemStack = inventory.getItem(slot);
            if (itemStack.isEmpty()) {
                slotsEmpty++;
            } else {
                slotsOccupied++;
                if (itemStack.getCount() >= itemStack.getMaxStackSize()) {
                    slotsFull++;
                }
            }
        }
 
        this.trigger(player, inventory, changedItem, slotsFull, slotsEmpty, slotsOccupied);
    }
 
    private void trigger(ServerPlayer player, Inventory inventory, ItemStack changedItem, int slotsFull, int slotsEmpty, int slotsOccupied) {
        this.trigger(player, t -> t.matches(inventory, changedItem, slotsFull, slotsEmpty, slotsOccupied));
    }
 
    public record TriggerInstance(Optional<ContextAwarePredicate> player, InventoryChangeTrigger.TriggerInstance.Slots slots, List<ItemPredicate> items)
        implements SimpleCriterionTrigger.SimpleInstance {
        public static final Codec<InventoryChangeTrigger.TriggerInstance> CODEC = RecordCodecBuilder.create(
            i -> i.group(
                    EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(InventoryChangeTrigger.TriggerInstance::player),
                    InventoryChangeTrigger.TriggerInstance.Slots.CODEC
                        .optionalFieldOf("slots", InventoryChangeTrigger.TriggerInstance.Slots.ANY)
                        .forGetter(InventoryChangeTrigger.TriggerInstance::slots),
                    ItemPredicate.CODEC.listOf().optionalFieldOf("items", List.of()).forGetter(InventoryChangeTrigger.TriggerInstance::items)
                )
                .apply(i, InventoryChangeTrigger.TriggerInstance::new)
        );
 
        public static Criterion<InventoryChangeTrigger.TriggerInstance> hasItems(ItemPredicate.Builder... items) {
            return hasItems(Stream.of(items).map(ItemPredicate.Builder::build).toArray(ItemPredicate[]::new));
        }
 
        public static Criterion<InventoryChangeTrigger.TriggerInstance> hasItems(ItemPredicate... items) {
            return CriteriaTriggers.INVENTORY_CHANGED
                .createCriterion(new InventoryChangeTrigger.TriggerInstance(Optional.empty(), InventoryChangeTrigger.TriggerInstance.Slots.ANY, List.of(items)));
        }
 
        public static Criterion<InventoryChangeTrigger.TriggerInstance> hasItems(ItemLike... items) {
            ItemPredicate[] predicates = new ItemPredicate[items.length];
 
            for (int i = 0; i < items.length; i++) {
                predicates[i] = new ItemPredicate(
                    Optional.of(HolderSet.direct(items[i].asItem().builtInRegistryHolder())), MinMaxBounds.Ints.ANY, DataComponentMatchers.ANY
                );
            }
 
            return hasItems(predicates);
        }
 
        public boolean matches(Inventory inventory, ItemStack changedItem, int slotsFull, int slotsEmpty, int slotsOccupied) {
            if (!this.slots.matches(slotsFull, slotsEmpty, slotsOccupied)) {
                return false;
            } else if (this.items.isEmpty()) {
                return true;
            } else if (this.items.size() != 1) {
                List<ItemPredicate> predicates = new ObjectArrayList<>(this.items);
                int count = inventory.getContainerSize();
 
                for (int slot = 0; slot < count; slot++) {
                    if (predicates.isEmpty()) {
                        return true;
                    }
 
                    ItemStack itemStack = inventory.getItem(slot);
                    if (!itemStack.isEmpty()) {
                        predicates.removeIf(predicate -> predicate.test((ItemInstance)itemStack));
                    }
                }
 
                return predicates.isEmpty();
            } else {
                return !changedItem.isEmpty() && this.items.get(0).test((ItemInstance)changedItem);
            }
        }
 
        public record Slots(MinMaxBounds.Ints occupied, MinMaxBounds.Ints full, MinMaxBounds.Ints empty) {
            public static final Codec<InventoryChangeTrigger.TriggerInstance.Slots> CODEC = RecordCodecBuilder.create(
                i -> i.group(
                        MinMaxBounds.Ints.CODEC
                            .optionalFieldOf("occupied", MinMaxBounds.Ints.ANY)
                            .forGetter(InventoryChangeTrigger.TriggerInstance.Slots::occupied),
                        MinMaxBounds.Ints.CODEC.optionalFieldOf("full", MinMaxBounds.Ints.ANY).forGetter(InventoryChangeTrigger.TriggerInstance.Slots::full),
                        MinMaxBounds.Ints.CODEC.optionalFieldOf("empty", MinMaxBounds.Ints.ANY).forGetter(InventoryChangeTrigger.TriggerInstance.Slots::empty)
                    )
                    .apply(i, InventoryChangeTrigger.TriggerInstance.Slots::new)
            );
            public static final InventoryChangeTrigger.TriggerInstance.Slots ANY = new InventoryChangeTrigger.TriggerInstance.Slots(
                MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY
            );
 
            public boolean matches(int slotsFull, int slotsEmpty, int slotsOccupied) {
                if (!this.full.matches(slotsFull)) {
                    return false;
                } else {
                    return !this.empty.matches(slotsEmpty) ? false : this.occupied.matches(slotsOccupied);
                }
            }
        }
    }
}

引用的其他类