diff --git a/src/main/java/carpet/script/api/Inventories.java b/src/main/java/carpet/script/api/Inventories.java index c7adf51774..99a9469354 100644 --- a/src/main/java/carpet/script/api/Inventories.java +++ b/src/main/java/carpet/script/api/Inventories.java @@ -8,30 +8,38 @@ import carpet.script.exception.Throwables; import carpet.script.external.Vanilla; import carpet.script.utils.InputValidator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.FormattedTextValue; import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; +import carpet.script.value.MapValue; import carpet.script.value.NBTSerializableValue; import carpet.script.value.NumericValue; import carpet.script.value.ScreenValue; import carpet.script.value.StringValue; import carpet.script.value.Value; import carpet.script.value.ValueConversions; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.OptionalInt; -import java.util.Set; - import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; @@ -95,6 +103,32 @@ public static void apply(Expression expression) return tagSet.isEmpty() ? Value.NULL : BooleanValue.of(tagSet.get().stream().anyMatch(h -> h.value() == item)); }); + expression.addContextFunction("item_components", 1, (c, t, lv) -> { + CarpetContext cc = (CarpetContext) c; + ItemStack stack = ValueConversions.getItemStackFromValue(lv.getFirst(), true, cc.registryAccess()); + + Stream> stream = (Stream>)(Object)stack.getComponents().keySet().stream(); + Map lst = stream.filter(Predicate.not(DataComponentType::isTransient)) + .collect(Collectors.toMap( + ck -> ValueConversions.of(BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(ck)), + ck -> { + var cvalue = stack.get(ck); + return switch (cvalue) { + case Number n -> NumericValue.of(n); + case Boolean b -> BooleanValue.of(b); + case Component ft -> FormattedTextValue.of(ft); + default -> NBTSerializableValue.of(ck.codec() + .encodeStart( + cc.registryAccess().createSerializationContext(NbtOps.INSTANCE), + cvalue) + .result().orElse(null)); + }; + + })); + + return MapValue.wrap(lst); + }); + expression.addContextFunction("recipe_data", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c;