diff --git a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java index ea4f7102f..91a39e89f 100644 --- a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java +++ b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java @@ -70,7 +70,6 @@ import dev.latvian.mods.kubejs.item.ItemBuilder; import dev.latvian.mods.kubejs.item.ItemEnchantmentsWrapper; import dev.latvian.mods.kubejs.item.ItemPredicate; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.item.ItemTintFunction; import dev.latvian.mods.kubejs.item.ItemToolTiers; import dev.latvian.mods.kubejs.item.JukeboxSongBuilder; @@ -80,7 +79,6 @@ import dev.latvian.mods.kubejs.item.custom.ShearsItemBuilder; import dev.latvian.mods.kubejs.item.custom.SmithingTemplateItemBuilder; import dev.latvian.mods.kubejs.item.custom.SwordItemBuilder; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.misc.CustomStatBuilder; import dev.latvian.mods.kubejs.misc.MobEffectBuilder; import dev.latvian.mods.kubejs.misc.PaintingVariantBuilder; @@ -565,8 +563,8 @@ public void registerTypeWrappers(TypeWrapperRegistry registry) { registry.register(Vec3.class, KubeJSTypeWrappers::vec3Of); registry.register(Vec3i.class, KubeJSTypeWrappers::blockPosOf); - registry.register(Item.class, ItemStackJS::getRawItem); - registry.register(ItemLike.class, ItemStackJS::getRawItem); + registry.register(Item.class, ItemWrapper::wrapItem); + registry.register(ItemLike.class, ItemWrapper::wrapItem); registry.registerEnumFromStringCodec(MobCategory.class, MobCategory.CODEC); registry.register(ItemEnchantments.class, ItemEnchantmentsWrapper::from); @@ -584,8 +582,8 @@ public void registerTypeWrappers(TypeWrapperRegistry registry) { registry.register(ColorRGBA.class, ColorWrapper::colorRGBAOf); // KubeJS // - registry.register(ItemStack.class, ItemStackJS::wrap); - registry.register(Ingredient.class, IngredientJS::wrap); + registry.register(ItemStack.class, ItemWrapper::wrap); + registry.register(Ingredient.class, IngredientWrapper::wrap); registry.register(ItemPredicate.class, ItemPredicate::wrap); registry.register(SizedIngredient.class, SizedIngredientWrapper::wrap); registry.register(BlockStatePredicate.class, BlockStatePredicate::wrap); @@ -629,7 +627,7 @@ public void registerTypeWrappers(TypeWrapperRegistry registry) { @Override public void registerTypeDescriptions(TypeDescriptionRegistry registry) { - registry.register(SlotFilter.class, ((RecordTypeInfo) TypeInfo.of(SlotFilter.class)).createCombinedType(TypeInfo.INT, IngredientJS.TYPE_INFO)); + registry.register(SlotFilter.class, ((RecordTypeInfo) TypeInfo.of(SlotFilter.class)).createCombinedType(TypeInfo.INT, IngredientWrapper.TYPE_INFO)); } @Override @@ -722,9 +720,9 @@ public void registerIngredientActionTypes(IngredientActionTypeRegistry registry) @Override @SuppressWarnings("deprecation") public void clearCaches() { - ItemStackJS.CACHED_ITEM_MAP.forget(); - ItemStackJS.CACHED_ITEM_LIST.forget(); - ItemStackJS.CACHED_ITEM_TYPE_LIST.forget(); + ItemWrapper.CACHED_ITEM_MAP.forget(); + ItemWrapper.CACHED_ITEM_LIST.forget(); + ItemWrapper.CACHED_ITEM_TYPE_LIST.forget(); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/IngredientWrapper.java b/src/main/java/dev/latvian/mods/kubejs/bindings/IngredientWrapper.java index cd5e44b14..01d04cd2c 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/IngredientWrapper.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/IngredientWrapper.java @@ -1,18 +1,54 @@ package dev.latvian.mods.kubejs.bindings; +import com.google.gson.JsonElement; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.JavaOps; +import com.mojang.serialization.JsonOps; +import dev.latvian.mods.kubejs.KubeJS; +import dev.latvian.mods.kubejs.component.DataComponentWrapper; +import dev.latvian.mods.kubejs.core.IngredientSupplierKJS; +import dev.latvian.mods.kubejs.ingredient.CreativeTabIngredient; +import dev.latvian.mods.kubejs.ingredient.NamespaceIngredient; +import dev.latvian.mods.kubejs.ingredient.RegExIngredient; import dev.latvian.mods.kubejs.ingredient.WildcardIngredient; import dev.latvian.mods.kubejs.typings.Info; +import dev.latvian.mods.kubejs.util.ListJS; +import dev.latvian.mods.kubejs.util.RegExpKJS; +import dev.latvian.mods.kubejs.util.RegistryAccessContainer; +import dev.latvian.mods.kubejs.util.UtilsJS; +import dev.latvian.mods.rhino.Context; +import dev.latvian.mods.rhino.Wrapper; +import dev.latvian.mods.rhino.regexp.NativeRegExp; +import dev.latvian.mods.rhino.type.TypeInfo; +import dev.latvian.mods.rhino.util.HideFromJS; +import net.minecraft.core.HolderSet; +import net.minecraft.core.component.DataComponentPredicate; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; +import net.neoforged.neoforge.common.crafting.CompoundIngredient; +import net.neoforged.neoforge.common.crafting.DataComponentIngredient; import net.neoforged.neoforge.common.crafting.SizedIngredient; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + @Info("Various Ingredient related helper methods") public interface IngredientWrapper { + TypeInfo TYPE_INFO = TypeInfo.of(Ingredient.class); + @Info("A completely empty ingredient that will only match air") Ingredient none = Ingredient.EMPTY; + @Info("An ingredient that matches everything") Ingredient all = WildcardIngredient.INSTANCE.toVanilla(); @@ -26,6 +62,170 @@ static SizedIngredient of(Ingredient ingredient, int count) { return ingredient.kjs$withCount(count); } + @HideFromJS + static Ingredient wrap(Context cx, @Nullable Object o) { + while (o instanceof Wrapper w) { + o = w.unwrap(); + } + + if (o == null || o == ItemStack.EMPTY || o == Items.AIR || o == Ingredient.EMPTY) { + return Ingredient.EMPTY; + } else if (o instanceof IngredientSupplierKJS ingr) { + return ingr.kjs$asIngredient(); + } else if (o instanceof TagKey tag) { + return Ingredient.of(ItemTags.create(tag.location())); + } else if (o instanceof Pattern || o instanceof NativeRegExp) { + var reg = RegExpKJS.wrap(o); + + if (reg != null) { + return new RegExIngredient(reg).toVanilla(); + } + + return Ingredient.EMPTY; + } else if (o instanceof JsonElement json) { + return parseJson(cx, json); + } else if (o instanceof CharSequence) { + return parseString(RegistryAccessContainer.of(cx), o.toString()); + } + + List list = ListJS.of(o); + + if (list != null) { + var inList = new ArrayList(list.size()); + + for (var o1 : list) { + var ingredient = wrap(cx, o1); + + if (ingredient != Ingredient.EMPTY) { + inList.add(ingredient); + } + } + + if (inList.isEmpty()) { + return Ingredient.EMPTY; + } else if (inList.size() == 1) { + return inList.getFirst(); + } else { + return CompoundIngredient.of(inList.toArray(new Ingredient[0])); + } + } + + var map = cx.optionalMapOf(o); + + if (map != null) { + return Ingredient.CODEC.decode(JavaOps.INSTANCE, map).result().map(Pair::getFirst).orElse(Ingredient.EMPTY); + } + + return ItemWrapper.wrap(cx, o).kjs$asIngredient(); + } + + static boolean isIngredientLike(Object from) { + return from instanceof Ingredient || from instanceof SizedIngredient || from instanceof ItemStack; + } + + static Ingredient parseJson(Context cx, JsonElement json) { + if (json == null || json.isJsonNull() || json.isJsonArray() && json.getAsJsonArray().isEmpty()) { + return Ingredient.EMPTY; + } else if (json.isJsonPrimitive()) { + return wrap(cx, json.getAsString()); + } else { + return Ingredient.CODEC.decode(JsonOps.INSTANCE, json).result().map(Pair::getFirst).orElseThrow(); + } + } + + static Ingredient parseString(RegistryAccessContainer registries, String s) { + if (s.isEmpty() || s.equals("-") || s.equals("air") || s.equals("minecraft:air")) { + return Ingredient.EMPTY; + } else if (s.equals("*")) { + return IngredientWrapper.all; + } else { + try { + return read(registries, new StringReader(s)); + } catch (CommandSyntaxException e) { + KubeJS.LOGGER.error("Failed to read ingredient from '" + s + "': " + e); + return Ingredient.EMPTY; + } + } + } + + static Ingredient read(RegistryAccessContainer registries, StringReader reader) throws CommandSyntaxException { + if (!reader.canRead()) { + return Ingredient.EMPTY; + } + + return switch (reader.peek()) { + case '-' -> { + reader.skip(); + yield Ingredient.EMPTY; + } + case '*' -> { + reader.skip(); + yield IngredientWrapper.all; + } + case '#' -> { + reader.skip(); + // yield new TagIngredient(registries.cachedItemTags, ItemTags.create(ResourceLocation.read(reader))).toVanilla(); + yield Ingredient.of(ItemTags.create(ResourceLocation.read(reader))); + } + case '@' -> { + reader.skip(); + yield new NamespaceIngredient(reader.readUnquotedString()).toVanilla(); + } + case '%' -> { + reader.skip(); + var id = ResourceLocation.read(reader); + var group = UtilsJS.findCreativeTab(id); + yield group == null ? Ingredient.EMPTY : new CreativeTabIngredient(group).toVanilla(); + } + case '/' -> { + var regex = RegExpKJS.read(reader); + yield new RegExIngredient(regex).toVanilla(); + } + case '[' -> { + reader.skip(); + reader.skipWhitespace(); + + if (!reader.canRead() || reader.peek() == ']') { + yield Ingredient.EMPTY; + } + + var ingredients = new ArrayList(2); + + while (true) { + ingredients.add(read(registries, reader)); + reader.skipWhitespace(); + + if (reader.canRead() && reader.peek() == ',') { + reader.skip(); + reader.skipWhitespace(); + } else if (!reader.canRead() || reader.peek() == ']') { + break; + } + } + + reader.expect(']'); + reader.skipWhitespace(); + yield CompoundIngredient.of(ingredients.toArray(new Ingredient[0])); + } + default -> { + var itemId = ResourceLocation.read(reader); + var item = BuiltInRegistries.ITEM.get(itemId); + + var next = reader.canRead() ? reader.peek() : 0; + + if (next == '[' || next == '{') { + var components = DataComponentWrapper.readPredicate(registries.nbt(), reader); + + if (components != DataComponentPredicate.EMPTY) { + yield new DataComponentIngredient(HolderSet.direct(item.builtInRegistryHolder()), components, false).toVanilla(); + } + } + + yield Ingredient.of(item); + } + }; + } + @Info(""" Checks if the passed in object is an Ingredient. Note that this does not mean it will not function as an Ingredient if passed to something that requests one. @@ -40,8 +240,8 @@ static ItemStack first(Ingredient ingredient) { @Nullable static TagKey tagKeyOf(Ingredient in) { - if (!in.isCustom() && in.getValues().length == 1 && in.getValues()[0] instanceof Ingredient.TagValue value) { - return value.tag(); + if (!in.isCustom() && in.getValues().length == 1 && in.getValues()[0] instanceof Ingredient.TagValue(TagKey tag)) { + return tag; } else { return null; } diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java b/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java index 6017b1298..dce9d47b7 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/ItemWrapper.java @@ -1,33 +1,104 @@ package dev.latvian.mods.kubejs.bindings; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; -import dev.latvian.mods.kubejs.item.ItemStackJS; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JsonOps; +import dev.latvian.mods.kubejs.component.DataComponentWrapper; +import dev.latvian.mods.kubejs.error.KubeRuntimeException; +import dev.latvian.mods.kubejs.ingredient.RegExIngredient; +import dev.latvian.mods.kubejs.script.SourceLine; import dev.latvian.mods.kubejs.typings.Info; +import dev.latvian.mods.kubejs.util.ID; import dev.latvian.mods.kubejs.util.JsonUtils; +import dev.latvian.mods.kubejs.util.Lazy; +import dev.latvian.mods.kubejs.util.RegExpKJS; +import dev.latvian.mods.kubejs.util.RegistryAccessContainer; +import dev.latvian.mods.rhino.Context; +import dev.latvian.mods.rhino.Wrapper; +import dev.latvian.mods.rhino.regexp.NativeRegExp; +import dev.latvian.mods.rhino.type.TypeInfo; +import dev.latvian.mods.rhino.util.HideFromJS; import net.minecraft.Util; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import net.minecraft.util.Mth; +import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackLinkedSet; import net.minecraft.world.item.Items; import net.minecraft.world.item.component.Fireworks; import net.minecraft.world.item.component.ResolvableProfile; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; import net.neoforged.neoforge.common.ItemAbility; import org.jetbrains.annotations.Nullable; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Base64; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; +import java.util.regex.Pattern; @Info("Various item related helper methods") public interface ItemWrapper { + ItemStack[] EMPTY_ARRAY = new ItemStack[0]; + TypeInfo ITEM_TYPE_INFO = TypeInfo.of(Item.class); + TypeInfo TYPE_INFO = TypeInfo.of(ItemStack.class); + + @HideFromJS + Lazy> CACHED_ITEM_TYPE_LIST = Lazy.of(() -> { + var cachedItemTypeList = new ArrayList(); + + for (var item : BuiltInRegistries.ITEM) { + cachedItemTypeList.add(item.kjs$getId()); + } + + return cachedItemTypeList; + }); + + @HideFromJS + Lazy>> CACHED_ITEM_MAP = Lazy.of(() -> { + var map = new HashMap>(); + var stackList = ItemStackLinkedSet.createTypeAndComponentsSet(); + + stackList.addAll(CreativeModeTabs.searchTab().getDisplayItems()); + + for (var stack : stackList) { + if (!stack.isEmpty()) { + map.computeIfAbsent( + stack.getItem().kjs$getIdLocation(), + _rl -> ItemStackLinkedSet.createTypeAndComponentsSet() + ).add(stack.kjs$withCount(1)); + } + } + + for (var itemId : CACHED_ITEM_TYPE_LIST.get()) { + var itemRl = ResourceLocation.parse(itemId); + map.computeIfAbsent(itemRl, id -> Set.of(BuiltInRegistries.ITEM.get(id).getDefaultInstance())); + } + + return map; + }); + + @HideFromJS + Lazy> CACHED_ITEM_LIST = Lazy.of(() -> CACHED_ITEM_MAP.get().values().stream().flatMap(Collection::stream).toList()); + @Info("Returns an ItemStack of the input") static ItemStack of(ItemStack in) { return in; @@ -38,18 +109,130 @@ static ItemStack of(ItemStack in, int count) { return in.kjs$withCount(count); } + @HideFromJS + static ItemStack wrap(Context cx, @Nullable Object o) { + if (o instanceof Wrapper w) { + o = w.unwrap(); + } + + if (o == null || o == ItemStack.EMPTY || o == Items.AIR) { + return ItemStack.EMPTY; + } else if (o instanceof ItemStack stack) { + return stack.isEmpty() ? ItemStack.EMPTY : stack; + } else if (o == Ingredient.EMPTY) { + throw new KubeRuntimeException("Tried to convert empy ingredient to ItemStack!").source(SourceLine.of(cx)); + } else if (o instanceof Ingredient) { + throw new KubeRuntimeException("Use .first of an ingredient to get its ItemStack!").source(SourceLine.of(cx)); + } else if (o instanceof ResourceLocation id) { + var item = BuiltInRegistries.ITEM.get(id); + + if (item == null || item == Items.AIR) { + return ItemStack.EMPTY; + } + + return item.getDefaultInstance(); + } else if (o instanceof ItemLike itemLike) { + return itemLike.asItem().getDefaultInstance(); + } else if (o instanceof JsonElement json) { + var registries = RegistryAccessContainer.of(cx); + return parseJson(registries.nbt(), json); + } else if (o instanceof StringTag tag) { + return wrap(cx, tag.getAsString()); + } else if (o instanceof Pattern || o instanceof NativeRegExp) { + var reg = RegExpKJS.wrap(o); + + if (reg != null) { + return new RegExIngredient(reg).toVanilla().kjs$getFirst(); + } + + return ItemStack.EMPTY; + } else if (o instanceof CharSequence) { + var os = o.toString().trim(); + var s = os; + var registries = RegistryAccessContainer.of(cx); + var cached = registries.itemStackParseCache().get(os); + + if (cached != null) { + return cached.copy(); + } + + var count = 1; + var spaceIndex = s.indexOf(' '); + + if (spaceIndex >= 2 && s.indexOf('x') == spaceIndex - 1) { + count = Integer.parseInt(s.substring(0, spaceIndex - 1)); + s = s.substring(spaceIndex + 1); + } + + cached = parseString(registries.nbt(), s); + cached.setCount(count); + registries.itemStackParseCache().put(os, cached); + return cached.copy(); + } + + var map = cx.optionalMapOf(o); + + if (map != null) { + if (map.containsKey("item")) { + var id = ID.mc(map.get("item").toString()); + var item = BuiltInRegistries.ITEM.get(id); + + if (item == null || item == Items.AIR) { + return ItemStack.EMPTY; + } + + var stack = new ItemStack(item); + + if (map.get("count") instanceof Number number) { + stack.setCount(number.intValue()); + } + + return stack; + } else if (map.containsKey("tag")) { + // var stack = new TagIngredient(registries.cachedItemTags, ItemTags.create(ID.mc(map.get("tag")))).toVanilla().kjs$getFirst(); + var stack = Ingredient.of(ItemTags.create(ID.mc(map.get("tag")))).kjs$getFirst(); + + if (map.containsKey("count")) { + stack.setCount(StringUtilsWrapper.parseInt(map.get("count"), 1)); + } + + return stack; + } + } + + return ItemStack.EMPTY; + } + + @HideFromJS + static Item wrapItem(Context cx, @Nullable Object o) { + if (o == null) { + return Items.AIR; + } else if (o instanceof ItemLike item) { + return item.asItem(); + } else if (o instanceof CharSequence) { + var s = o.toString(); + if (s.isEmpty()) { + return Items.AIR; + } else if (s.charAt(0) != '#') { + return BuiltInRegistries.ITEM.get(ID.mc(s)); + } + } + + return wrap(cx, o).getItem(); + } + @Info("Get a list of most items in the game. Items not in a creative tab are ignored") static List getList() { - return ItemStackJS.getList(); + return CACHED_ITEM_LIST.get(); } @Info("Get a list of all the item ids in the game") static List getTypeList() { - return ItemStackJS.getTypeList(); + return CACHED_ITEM_TYPE_LIST.get(); } static Map> getTypeToStackMap() { - return ItemStackJS.getTypeToStacks(); + return CACHED_ITEM_MAP.get(); } static Collection getVariants(ItemStack item) { @@ -86,7 +269,7 @@ static boolean exists(ResourceLocation id) { Note that this does not mean it will not function as an ItemStack if passed to something that requests one. """) static boolean isItem(@Nullable Object o) { - return o instanceof ItemStackJS; + return o instanceof ItemStack; } static ItemStack playerHead(String name) { @@ -135,4 +318,73 @@ static ItemAbility itemAbilityOf(Object object) { return null; } } + + static boolean isItemStackLike(Object from) { + return from instanceof ItemStack; + } + + static ItemStack parseJson(DynamicOps registryOps, @Nullable JsonElement json) { + if (json == null || json.isJsonNull()) { + return ItemStack.EMPTY; + } else if (json.isJsonPrimitive()) { + return parseString(registryOps, json.getAsString()); + } else if (json instanceof JsonObject) { + return ItemStack.OPTIONAL_CODEC.decode(JsonOps.INSTANCE, json).getOrThrow().getFirst(); + } + + return ItemStack.EMPTY; + } + + static ItemStack parseString(DynamicOps registryOps, String s) { + if (s.isEmpty() || s.equals("-") || s.equals("air") || s.equals("minecraft:air")) { + return ItemStack.EMPTY; + } else { + try { + var reader = new StringReader(s); + reader.skipWhitespace(); + + if (!reader.canRead()) { + return ItemStack.EMPTY; + } + + return read(registryOps, new StringReader(s)); + } catch (CommandSyntaxException ex) { + throw new RuntimeException(ex); + } + } + } + + static ItemStack read(DynamicOps registryOps, StringReader reader) throws CommandSyntaxException { + if (!reader.canRead()) { + return ItemStack.EMPTY; + } + + if (reader.peek() == '-') { + return ItemStack.EMPTY; + } + + int count = 1; + + if (reader.canRead() && StringReader.isAllowedNumber(reader.peek())) { + count = Mth.ceil(reader.readDouble()); + reader.skipWhitespace(); + reader.expect('x'); + reader.skipWhitespace(); + + if (count < 1) { + throw new IllegalArgumentException("Item count smaller than 1 is not allowed!"); + } + } + + var itemId = ResourceLocation.read(reader); + var itemStack = new ItemStack(BuiltInRegistries.ITEM.get(itemId), count); + + var next = reader.canRead() ? reader.peek() : 0; + + if (next == '[' || next == '{') { + itemStack.applyComponents(DataComponentWrapper.readPatch(registryOps, reader)); + } + + return itemStack; + } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/SizedIngredientWrapper.java b/src/main/java/dev/latvian/mods/kubejs/bindings/SizedIngredientWrapper.java index 111431eef..3cee99771 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/SizedIngredientWrapper.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/SizedIngredientWrapper.java @@ -2,7 +2,6 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.typings.Info; import dev.latvian.mods.kubejs.util.RegistryAccessContainer; import dev.latvian.mods.rhino.Context; @@ -57,7 +56,7 @@ static SizedIngredient wrap(Context cx, Object from) { } } - return IngredientJS.wrap(cx, from).kjs$asStack(); + return IngredientWrapper.wrap(cx, from).kjs$asStack(); } @HideFromJS @@ -75,6 +74,6 @@ static SizedIngredient read(RegistryAccessContainer registries, StringReader rea } } - return IngredientJS.read(registries, reader).kjs$withCount(count); + return IngredientWrapper.read(registries, reader).kjs$withCount(count); } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/event/ItemEvents.java b/src/main/java/dev/latvian/mods/kubejs/bindings/event/ItemEvents.java index 4a2652f33..af52ff910 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/event/ItemEvents.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/event/ItemEvents.java @@ -1,5 +1,6 @@ package dev.latvian.mods.kubejs.bindings.event; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.event.EventGroup; import dev.latvian.mods.kubejs.event.EventHandler; import dev.latvian.mods.kubejs.event.EventTargetType; @@ -15,7 +16,6 @@ import dev.latvian.mods.kubejs.item.ItemModificationKubeEvent; import dev.latvian.mods.kubejs.item.ItemPickedUpKubeEvent; import dev.latvian.mods.kubejs.item.ItemSmeltedKubeEvent; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.item.ModifyItemTooltipsKubeEvent; import dev.latvian.mods.kubejs.item.custom.ItemToolTierRegistryKubeEvent; import net.minecraft.core.registries.Registries; @@ -28,7 +28,7 @@ public interface ItemEvents { EventHandler MODIFICATION = GROUP.startup("modification", () -> ItemModificationKubeEvent.class); EventHandler TOOL_TIER_REGISTRY = GROUP.startup("toolTierRegistry", () -> ItemToolTierRegistryKubeEvent.class); - TargetedEventHandler> RIGHT_CLICKED = GROUP.common("rightClicked", () -> ItemClickedKubeEvent.class).hasResult(ItemStackJS.TYPE_INFO).supportsTarget(TARGET); + TargetedEventHandler> RIGHT_CLICKED = GROUP.common("rightClicked", () -> ItemClickedKubeEvent.class).hasResult(ItemWrapper.TYPE_INFO).supportsTarget(TARGET); TargetedEventHandler> CAN_PICK_UP = GROUP.common("canPickUp", () -> ItemPickedUpKubeEvent.class).hasResult().supportsTarget(TARGET); TargetedEventHandler> PICKED_UP = GROUP.common("pickedUp", () -> ItemPickedUpKubeEvent.class).supportsTarget(TARGET); TargetedEventHandler> DROPPED = GROUP.common("dropped", () -> ItemDroppedKubeEvent.class).hasResult().supportsTarget(TARGET); diff --git a/src/main/java/dev/latvian/mods/kubejs/bindings/event/ServerEvents.java b/src/main/java/dev/latvian/mods/kubejs/bindings/event/ServerEvents.java index c92ffef5b..aba0f5326 100644 --- a/src/main/java/dev/latvian/mods/kubejs/bindings/event/ServerEvents.java +++ b/src/main/java/dev/latvian/mods/kubejs/bindings/event/ServerEvents.java @@ -1,12 +1,12 @@ package dev.latvian.mods.kubejs.bindings.event; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.command.CommandRegistryKubeEvent; import dev.latvian.mods.kubejs.event.EventGroup; import dev.latvian.mods.kubejs.event.EventHandler; import dev.latvian.mods.kubejs.event.EventTargetType; import dev.latvian.mods.kubejs.event.TargetedEventHandler; import dev.latvian.mods.kubejs.generator.KubeDataGenerator; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.recipe.AfterRecipesLoadedKubeEvent; import dev.latvian.mods.kubejs.recipe.CompostableRecipesKubeEvent; import dev.latvian.mods.kubejs.recipe.ModifyCraftingItemKubeEvent; @@ -41,6 +41,6 @@ public interface ServerEvents { EventHandler RECIPES_AFTER_LOADED = GROUP.server("afterRecipes", () -> AfterRecipesLoadedKubeEvent.class); EventHandler SPECIAL_RECIPES = GROUP.server("specialRecipeSerializers", () -> SpecialRecipeSerializerManager.class); EventHandler COMPOSTABLE_RECIPES = GROUP.server("compostableRecipes", () -> CompostableRecipesKubeEvent.class); - TargetedEventHandler MODIFY_RECIPE_RESULT = GROUP.server("modifyRecipeResult", () -> ModifyCraftingItemKubeEvent.class).hasResult(ItemStackJS.TYPE_INFO).requiredTarget(EventTargetType.STRING); - TargetedEventHandler MODIFY_RECIPE_INGREDIENT = GROUP.server("modifyRecipeIngredient", () -> ModifyCraftingItemKubeEvent.class).hasResult(ItemStackJS.TYPE_INFO).requiredTarget(EventTargetType.STRING); + TargetedEventHandler MODIFY_RECIPE_RESULT = GROUP.server("modifyRecipeResult", () -> ModifyCraftingItemKubeEvent.class).hasResult(ItemWrapper.TYPE_INFO).requiredTarget(EventTargetType.STRING); + TargetedEventHandler MODIFY_RECIPE_INGREDIENT = GROUP.server("modifyRecipeIngredient", () -> ModifyCraftingItemKubeEvent.class).hasResult(ItemWrapper.TYPE_INFO).requiredTarget(EventTargetType.STRING); } diff --git a/src/main/java/dev/latvian/mods/kubejs/core/IngredientKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/IngredientKJS.java index 7281e50c2..f7dd9764d 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/IngredientKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/IngredientKJS.java @@ -6,7 +6,6 @@ import dev.latvian.mods.kubejs.error.KubeRuntimeException; import dev.latvian.mods.kubejs.ingredient.WildcardIngredient; import dev.latvian.mods.kubejs.item.ItemPredicate; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.Replaceable; import dev.latvian.mods.kubejs.util.WithCodec; @@ -75,7 +74,7 @@ default Codec getCodec(Context cx) { @Override default Object replaceThisWith(Context cx, Object with) { var t = kjs$self(); - var r = IngredientJS.wrap(cx, with); + var r = IngredientWrapper.wrap(cx, with); if (!r.equals(t)) { return r; diff --git a/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java index 6ea1a58b4..6350b20e9 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/ItemStackKJS.java @@ -2,9 +2,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DynamicOps; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.component.DataComponentWrapper; import dev.latvian.mods.kubejs.component.ItemComponentFunctions; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.level.LevelBlock; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.Replaceable; @@ -72,7 +72,7 @@ default boolean specialEquals(Context cx, Object o, boolean shallow) { return kjs$equalsIgnoringCount(s); } - return kjs$equalsIgnoringCount(ItemStackJS.wrap(cx, o)); + return kjs$equalsIgnoringCount(ItemWrapper.wrap(cx, o)); } default boolean kjs$equalsIgnoringCount(ItemStack stack) { @@ -275,7 +275,7 @@ default Codec getCodec(Context cx) { @Override default Object replaceThisWith(Context cx, Object with) { var t = kjs$self(); - var r = ItemStackJS.wrap(cx, with); + var r = ItemWrapper.wrap(cx, with); if (!ItemStack.isSameItemSameComponents(t, r)) { r.setCount(t.getCount()); diff --git a/src/main/java/dev/latvian/mods/kubejs/core/SizedIngredientKJS.java b/src/main/java/dev/latvian/mods/kubejs/core/SizedIngredientKJS.java index dbfc04aa5..0f3c4898a 100644 --- a/src/main/java/dev/latvian/mods/kubejs/core/SizedIngredientKJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/core/SizedIngredientKJS.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.core; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.Replaceable; import dev.latvian.mods.rhino.Context; @@ -15,7 +15,7 @@ public interface SizedIngredientKJS extends Replaceable, IngredientSupplierKJS, @Override default Object replaceThisWith(Context cx, Object with) { - var ingredient = IngredientJS.wrap(cx, with); + var ingredient = IngredientWrapper.wrap(cx, with); if (!ingredient.equals(kjs$self().ingredient())) { return new SizedIngredient(ingredient, kjs$self().count()); diff --git a/src/main/java/dev/latvian/mods/kubejs/ingredient/KubeJSIngredient.java b/src/main/java/dev/latvian/mods/kubejs/ingredient/KubeJSIngredient.java index c4bb1fbca..c8aa17c6f 100644 --- a/src/main/java/dev/latvian/mods/kubejs/ingredient/KubeJSIngredient.java +++ b/src/main/java/dev/latvian/mods/kubejs/ingredient/KubeJSIngredient.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.ingredient; import dev.latvian.mods.kubejs.CommonProperties; -import dev.latvian.mods.kubejs.item.ItemStackJS; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.common.crafting.ICustomIngredient; @@ -14,7 +14,7 @@ public interface KubeJSIngredient extends ICustomIngredient, Predicate getItems() { - return ItemStackJS.getList().stream().filter(this); + return ItemWrapper.getList().stream().filter(this); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ItemClickedKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/item/ItemClickedKubeEvent.java index cedf3f01f..17057d091 100644 --- a/src/main/java/dev/latvian/mods/kubejs/item/ItemClickedKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/item/ItemClickedKubeEvent.java @@ -1,5 +1,6 @@ package dev.latvian.mods.kubejs.item; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.entity.RayTraceResultJS; import dev.latvian.mods.kubejs.player.KubePlayerEvent; import dev.latvian.mods.kubejs.typings.Info; @@ -63,6 +64,6 @@ public ItemStack defaultExitValue(Context cx) { @Override @HideFromJS public TypeInfo getExitValueType() { - return ItemStackJS.TYPE_INFO; + return ItemWrapper.TYPE_INFO; } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ItemPredicate.java b/src/main/java/dev/latvian/mods/kubejs/item/ItemPredicate.java index c1fffc3e7..8f12ebd01 100644 --- a/src/main/java/dev/latvian/mods/kubejs/item/ItemPredicate.java +++ b/src/main/java/dev/latvian/mods/kubejs/item/ItemPredicate.java @@ -1,7 +1,8 @@ package dev.latvian.mods.kubejs.item; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.core.IngredientSupplierKJS; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.rhino.BaseFunction; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; @@ -34,7 +35,7 @@ static ItemPredicate wrap(Context cx, Object from) { } } - var in = IngredientJS.wrap(cx, from); + var in = IngredientWrapper.wrap(cx, from); if (in.isEmpty()) { return NONE; @@ -51,7 +52,7 @@ static ItemPredicate wrap(Context cx, Object from) { } default ItemStack[] kjs$getStackArray() { - return ItemStackJS.getList().stream().filter(this).toArray(ItemStack[]::new); + return ItemWrapper.getList().stream().filter(this).toArray(ItemStack[]::new); } default ItemStackSet kjs$getStacks() { @@ -61,7 +62,7 @@ static ItemPredicate wrap(Context cx, Object from) { default ItemStackSet kjs$getDisplayStacks() { var set = new ItemStackSet(); - for (var stack : ItemStackJS.getList()) { + for (var stack : ItemWrapper.getList()) { if (test(stack)) { set.add(stack); } diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java b/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java deleted file mode 100644 index 9d555d058..000000000 --- a/src/main/java/dev/latvian/mods/kubejs/item/ItemStackJS.java +++ /dev/null @@ -1,275 +0,0 @@ -package dev.latvian.mods.kubejs.item; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.serialization.DynamicOps; -import com.mojang.serialization.JsonOps; -import dev.latvian.mods.kubejs.bindings.StringUtilsWrapper; -import dev.latvian.mods.kubejs.component.DataComponentWrapper; -import dev.latvian.mods.kubejs.error.KubeRuntimeException; -import dev.latvian.mods.kubejs.ingredient.RegExIngredient; -import dev.latvian.mods.kubejs.util.ID; -import dev.latvian.mods.kubejs.util.Lazy; -import dev.latvian.mods.kubejs.util.RegExpKJS; -import dev.latvian.mods.kubejs.util.RegistryAccessContainer; -import dev.latvian.mods.rhino.Context; -import dev.latvian.mods.rhino.Wrapper; -import dev.latvian.mods.rhino.regexp.NativeRegExp; -import dev.latvian.mods.rhino.type.TypeInfo; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import net.minecraft.util.Mth; -import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ItemStackLinkedSet; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.ItemLike; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -public interface ItemStackJS { - ItemStack[] EMPTY_ARRAY = new ItemStack[0]; - TypeInfo ITEM_TYPE_INFO = TypeInfo.of(Item.class); - TypeInfo TYPE_INFO = TypeInfo.of(ItemStack.class); - - Lazy> CACHED_ITEM_TYPE_LIST = Lazy.of(() -> { - var cachedItemTypeList = new ArrayList(); - - for (var item : BuiltInRegistries.ITEM) { - cachedItemTypeList.add(item.kjs$getId()); - } - - return cachedItemTypeList; - }); - - Lazy>> CACHED_ITEM_MAP = Lazy.of(() -> { - var map = new HashMap>(); - var stackList = ItemStackLinkedSet.createTypeAndComponentsSet(); - - stackList.addAll(CreativeModeTabs.searchTab().getDisplayItems()); - - for (var stack : stackList) { - if (!stack.isEmpty()) { - map.computeIfAbsent( - stack.getItem().kjs$getIdLocation(), - _rl -> ItemStackLinkedSet.createTypeAndComponentsSet() - ).add(stack.kjs$withCount(1)); - } - } - - for (var itemId : CACHED_ITEM_TYPE_LIST.get()) { - var itemRl = ResourceLocation.parse(itemId); - map.computeIfAbsent(itemRl, id -> Set.of(BuiltInRegistries.ITEM.get(id).getDefaultInstance())); - } - - return map; - }); - - Lazy> CACHED_ITEM_LIST = Lazy.of(() -> CACHED_ITEM_MAP.get().values().stream().flatMap(Collection::stream).toList()); - - static ItemStack wrap(Context cx, @Nullable Object o) { - if (o instanceof Wrapper w) { - o = w.unwrap(); - } - - if (o == null || o == ItemStack.EMPTY || o == Items.AIR) { - return ItemStack.EMPTY; - } else if (o instanceof ItemStack stack) { - return stack.isEmpty() ? ItemStack.EMPTY : stack; - } else if (o instanceof Ingredient) { - throw new KubeRuntimeException("Use .first of an ingredient to get its ItemStack!"); - } else if (o instanceof ResourceLocation id) { - var item = BuiltInRegistries.ITEM.get(id); - - if (item == null || item == Items.AIR) { - return ItemStack.EMPTY; - } - - return item.getDefaultInstance(); - } else if (o instanceof ItemLike itemLike) { - return itemLike.asItem().getDefaultInstance(); - } else if (o instanceof JsonElement json) { - var registries = RegistryAccessContainer.of(cx); - return resultFromRecipeJson(registries.nbt(), json); - } else if (o instanceof StringTag tag) { - return wrap(cx, tag.getAsString()); - } else if (o instanceof Pattern || o instanceof NativeRegExp) { - var reg = RegExpKJS.wrap(o); - - if (reg != null) { - return new RegExIngredient(reg).toVanilla().kjs$getFirst(); - } - - return ItemStack.EMPTY; - } else if (o instanceof CharSequence) { - var os = o.toString().trim(); - var s = os; - var registries = RegistryAccessContainer.of(cx); - - var cached = registries.itemStackParseCache().get(os); - - if (cached != null) { - return cached.copy(); - } - - var count = 1; - var spaceIndex = s.indexOf(' '); - - if (spaceIndex >= 2 && s.indexOf('x') == spaceIndex - 1) { - count = Integer.parseInt(s.substring(0, spaceIndex - 1)); - s = s.substring(spaceIndex + 1); - } - - cached = ofString(registries.nbt(), s); - cached.setCount(count); - registries.itemStackParseCache().put(os, cached); - return cached.copy(); - } - - var map = cx.optionalMapOf(o); - - if (map != null) { - if (map.containsKey("item")) { - var id = ID.mc(map.get("item").toString()); - var item = BuiltInRegistries.ITEM.get(id); - - if (item == null || item == Items.AIR) { - return ItemStack.EMPTY; - } - - var stack = new ItemStack(item); - - if (map.get("count") instanceof Number number) { - stack.setCount(number.intValue()); - } - - return stack; - } else if (map.containsKey("tag")) { - // var stack = new TagIngredient(registries.cachedItemTags, ItemTags.create(ID.mc(map.get("tag")))).toVanilla().kjs$getFirst(); - var stack = Ingredient.of(ItemTags.create(ID.mc(map.get("tag")))).kjs$getFirst(); - - if (map.containsKey("count")) { - stack.setCount(StringUtilsWrapper.parseInt(map.get("count"), 1)); - } - - return stack; - } - } - - return ItemStack.EMPTY; - } - - static Item getRawItem(Context cx, @Nullable Object o) { - if (o == null) { - return Items.AIR; - } else if (o instanceof ItemLike item) { - return item.asItem(); - } else if (o instanceof CharSequence) { - var s = o.toString(); - if (s.isEmpty()) { - return Items.AIR; - } else if (s.charAt(0) != '#') { - return BuiltInRegistries.ITEM.get(ID.mc(s)); - } - } - - return wrap(cx, o).getItem(); - } - - // Use ItemStackJS.of(object) - - static ItemStack resultFromRecipeJson(DynamicOps registryOps, @Nullable JsonElement json) { - if (json == null || json.isJsonNull()) { - return ItemStack.EMPTY; - } else if (json.isJsonPrimitive()) { - return ofString(registryOps, json.getAsString()); - } else if (json instanceof JsonObject) { - return ItemStack.OPTIONAL_CODEC.decode(JsonOps.INSTANCE, json).getOrThrow().getFirst(); - } - - return ItemStack.EMPTY; - } - - static List getList() { - return CACHED_ITEM_LIST.get(); - } - - static List getTypeList() { - return CACHED_ITEM_TYPE_LIST.get(); - } - - static Map> getTypeToStacks() { - return CACHED_ITEM_MAP.get(); - } - - static boolean isItemStackLike(Object from) { - return from instanceof ItemStack; - } - - static ItemStack ofString(DynamicOps registryOps, String s) { - if (s.isEmpty() || s.equals("-") || s.equals("air") || s.equals("minecraft:air")) { - return ItemStack.EMPTY; - } else { - try { - var reader = new StringReader(s); - reader.skipWhitespace(); - - if (!reader.canRead()) { - return ItemStack.EMPTY; - } - - return read(registryOps, new StringReader(s)); - } catch (CommandSyntaxException ex) { - throw new RuntimeException(ex); - } - } - } - - static ItemStack read(DynamicOps registryOps, StringReader reader) throws CommandSyntaxException { - if (!reader.canRead()) { - return ItemStack.EMPTY; - } - - if (reader.peek() == '-') { - return ItemStack.EMPTY; - } - - int count = 1; - - if (reader.canRead() && StringReader.isAllowedNumber(reader.peek())) { - count = Mth.ceil(reader.readDouble()); - reader.skipWhitespace(); - reader.expect('x'); - reader.skipWhitespace(); - - if (count < 1) { - throw new IllegalArgumentException("Item count smaller than 1 is not allowed!"); - } - } - - var itemId = ResourceLocation.read(reader); - var itemStack = new ItemStack(BuiltInRegistries.ITEM.get(itemId), count); - - var next = reader.canRead() ? reader.peek() : 0; - - if (next == '[' || next == '{') { - itemStack.applyComponents(DataComponentWrapper.readPatch(registryOps, reader)); - } - - return itemStack; - } -} \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ItemStackSet.java b/src/main/java/dev/latvian/mods/kubejs/item/ItemStackSet.java index 895d453ec..1c803b647 100644 --- a/src/main/java/dev/latvian/mods/kubejs/item/ItemStackSet.java +++ b/src/main/java/dev/latvian/mods/kubejs/item/ItemStackSet.java @@ -1,5 +1,6 @@ package dev.latvian.mods.kubejs.item; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -62,7 +63,7 @@ public List toList() { } public ItemStack[] toArray() { - return map.isEmpty() ? ItemStackJS.EMPTY_ARRAY : map.values().toArray(ItemStackJS.EMPTY_ARRAY); + return map.isEmpty() ? ItemWrapper.EMPTY_ARRAY : map.values().toArray(ItemWrapper.EMPTY_ARRAY); } public boolean isEmpty() { diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ingredient/IngredientJS.java b/src/main/java/dev/latvian/mods/kubejs/item/ingredient/IngredientJS.java deleted file mode 100644 index dac7ada84..000000000 --- a/src/main/java/dev/latvian/mods/kubejs/item/ingredient/IngredientJS.java +++ /dev/null @@ -1,208 +0,0 @@ -package dev.latvian.mods.kubejs.item.ingredient; - -import com.google.gson.JsonElement; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.datafixers.util.Pair; -import com.mojang.serialization.JavaOps; -import com.mojang.serialization.JsonOps; -import dev.latvian.mods.kubejs.KubeJS; -import dev.latvian.mods.kubejs.bindings.IngredientWrapper; -import dev.latvian.mods.kubejs.component.DataComponentWrapper; -import dev.latvian.mods.kubejs.core.IngredientSupplierKJS; -import dev.latvian.mods.kubejs.ingredient.CreativeTabIngredient; -import dev.latvian.mods.kubejs.ingredient.NamespaceIngredient; -import dev.latvian.mods.kubejs.ingredient.RegExIngredient; -import dev.latvian.mods.kubejs.item.ItemStackJS; -import dev.latvian.mods.kubejs.util.ListJS; -import dev.latvian.mods.kubejs.util.RegExpKJS; -import dev.latvian.mods.kubejs.util.RegistryAccessContainer; -import dev.latvian.mods.kubejs.util.UtilsJS; -import dev.latvian.mods.rhino.Context; -import dev.latvian.mods.rhino.Wrapper; -import dev.latvian.mods.rhino.regexp.NativeRegExp; -import dev.latvian.mods.rhino.type.TypeInfo; -import net.minecraft.core.HolderSet; -import net.minecraft.core.component.DataComponentPredicate; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; -import net.neoforged.neoforge.common.crafting.CompoundIngredient; -import net.neoforged.neoforge.common.crafting.DataComponentIngredient; -import net.neoforged.neoforge.common.crafting.SizedIngredient; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; - -public interface IngredientJS { - TypeInfo TYPE_INFO = TypeInfo.of(Ingredient.class); - - static Ingredient wrap(Context cx, @Nullable Object o) { - while (o instanceof Wrapper w) { - o = w.unwrap(); - } - - if (o == null || o == ItemStack.EMPTY || o == Items.AIR || o == Ingredient.EMPTY) { - return Ingredient.EMPTY; - } else if (o instanceof IngredientSupplierKJS ingr) { - return ingr.kjs$asIngredient(); - } else if (o instanceof TagKey tag) { - return Ingredient.of(ItemTags.create(tag.location())); - } else if (o instanceof Pattern || o instanceof NativeRegExp) { - var reg = RegExpKJS.wrap(o); - - if (reg != null) { - return new RegExIngredient(reg).toVanilla(); - } - - return Ingredient.EMPTY; - } else if (o instanceof JsonElement json) { - return ofJson(cx, json); - } else if (o instanceof CharSequence) { - return ofString(RegistryAccessContainer.of(cx), o.toString()); - } - - List list = ListJS.of(o); - - if (list != null) { - var inList = new ArrayList(list.size()); - - for (var o1 : list) { - var ingredient = wrap(cx, o1); - - if (ingredient != Ingredient.EMPTY) { - inList.add(ingredient); - } - } - - if (inList.isEmpty()) { - return Ingredient.EMPTY; - } else if (inList.size() == 1) { - return inList.getFirst(); - } else { - return CompoundIngredient.of(inList.toArray(new Ingredient[0])); - } - } - - var map = cx.optionalMapOf(o); - - if (map != null) { - return Ingredient.CODEC.decode(JavaOps.INSTANCE, map).result().map(Pair::getFirst).orElse(Ingredient.EMPTY); - } - - return ItemStackJS.wrap(cx, o).kjs$asIngredient(); - } - - static Ingredient ofString(RegistryAccessContainer registries, String s) { - if (s.isEmpty() || s.equals("-") || s.equals("air") || s.equals("minecraft:air")) { - return Ingredient.EMPTY; - } else if (s.equals("*")) { - return IngredientWrapper.all; - } else { - try { - return read(registries, new StringReader(s)); - } catch (CommandSyntaxException e) { - KubeJS.LOGGER.error("Failed to read ingredient from '" + s + "': " + e); - return Ingredient.EMPTY; - } - } - } - - static Ingredient ofJson(Context cx, JsonElement json) { - if (json == null || json.isJsonNull() || json.isJsonArray() && json.getAsJsonArray().isEmpty()) { - return Ingredient.EMPTY; - } else if (json.isJsonPrimitive()) { - return wrap(cx, json.getAsString()); - } else { - return Ingredient.CODEC.decode(JsonOps.INSTANCE, json).result().map(Pair::getFirst).orElseThrow(); - } - } - - static boolean isIngredientLike(Object from) { - return from instanceof Ingredient || from instanceof SizedIngredient || from instanceof ItemStack; - } - - static Ingredient read(RegistryAccessContainer registries, StringReader reader) throws CommandSyntaxException { - if (!reader.canRead()) { - return Ingredient.EMPTY; - } - - return switch (reader.peek()) { - case '-' -> { - reader.skip(); - yield Ingredient.EMPTY; - } - case '*' -> { - reader.skip(); - yield IngredientWrapper.all; - } - case '#' -> { - reader.skip(); - // yield new TagIngredient(registries.cachedItemTags, ItemTags.create(ResourceLocation.read(reader))).toVanilla(); - yield Ingredient.of(ItemTags.create(ResourceLocation.read(reader))); - } - case '@' -> { - reader.skip(); - yield new NamespaceIngredient(reader.readUnquotedString()).toVanilla(); - } - case '%' -> { - reader.skip(); - var id = ResourceLocation.read(reader); - var group = UtilsJS.findCreativeTab(id); - yield group == null ? Ingredient.EMPTY : new CreativeTabIngredient(group).toVanilla(); - } - case '/' -> { - var regex = RegExpKJS.read(reader); - yield new RegExIngredient(regex).toVanilla(); - } - case '[' -> { - reader.skip(); - reader.skipWhitespace(); - - if (!reader.canRead() || reader.peek() == ']') { - yield Ingredient.EMPTY; - } - - var ingredients = new ArrayList(2); - - while (true) { - ingredients.add(read(registries, reader)); - reader.skipWhitespace(); - - if (reader.canRead() && reader.peek() == ',') { - reader.skip(); - reader.skipWhitespace(); - } else if (!reader.canRead() || reader.peek() == ']') { - break; - } - } - - reader.expect(']'); - reader.skipWhitespace(); - yield CompoundIngredient.of(ingredients.toArray(new Ingredient[0])); - } - default -> { - var itemId = ResourceLocation.read(reader); - var item = BuiltInRegistries.ITEM.get(itemId); - - var next = reader.canRead() ? reader.peek() : 0; - - if (next == '[' || next == '{') { - var components = DataComponentWrapper.readPredicate(registries.nbt(), reader); - - if (components != DataComponentPredicate.EMPTY) { - yield new DataComponentIngredient(HolderSet.direct(item.builtInRegistryHolder()), components, false).toVanilla(); - } - } - - yield Ingredient.of(item); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/item/ingredient/package-info.java b/src/main/java/dev/latvian/mods/kubejs/item/ingredient/package-info.java deleted file mode 100644 index 08058db29..000000000 --- a/src/main/java/dev/latvian/mods/kubejs/item/ingredient/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NonnullByDefault -package dev.latvian.mods.kubejs.item.ingredient; - -import dev.latvian.mods.kubejs.NonnullByDefault; \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/misc/PaintingVariantBuilder.java b/src/main/java/dev/latvian/mods/kubejs/misc/PaintingVariantBuilder.java index ac3607765..cbfed5a87 100644 --- a/src/main/java/dev/latvian/mods/kubejs/misc/PaintingVariantBuilder.java +++ b/src/main/java/dev/latvian/mods/kubejs/misc/PaintingVariantBuilder.java @@ -1,6 +1,7 @@ package dev.latvian.mods.kubejs.misc; import dev.latvian.mods.kubejs.registry.BuilderBase; +import dev.latvian.mods.kubejs.util.KubeResourceLocation; import dev.latvian.mods.rhino.util.ReturnsSelf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.decoration.PaintingVariant; @@ -29,8 +30,8 @@ public PaintingVariantBuilder size(int width, int height) { return this; } - public PaintingVariantBuilder assetId(ResourceLocation assetId) { - this.assetId = assetId; + public PaintingVariantBuilder assetId(KubeResourceLocation assetId) { + this.assetId = assetId.wrapped(); return this; } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/ModifyCraftingItemKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/ModifyCraftingItemKubeEvent.java index 85b552372..0f3e0e0ae 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/ModifyCraftingItemKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/ModifyCraftingItemKubeEvent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.recipe; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.event.KubeEvent; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import dev.latvian.mods.rhino.util.HideFromJS; @@ -36,6 +36,6 @@ public ItemStack defaultExitValue(Context cx) { @Override @HideFromJS public TypeInfo getExitValueType() { - return ItemStackJS.TYPE_INFO; + return ItemWrapper.TYPE_INFO; } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java index 2a9bddc8d..6f275e6a1 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java @@ -2,7 +2,6 @@ import com.mojang.serialization.Codec; import dev.latvian.mods.kubejs.bindings.IngredientWrapper; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; @@ -62,12 +61,12 @@ public Codec codec() { @Override public TypeInfo typeInfo() { - return IngredientJS.TYPE_INFO; + return IngredientWrapper.TYPE_INFO; } @Override public boolean hasPriority(Context cx, KubeRecipe recipe, Object from) { - return IngredientJS.isIngredientLike(from); + return IngredientWrapper.isIngredientLike(from); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java index 39090d548..252f57009 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java @@ -1,7 +1,7 @@ package dev.latvian.mods.kubejs.recipe.component; import com.mojang.serialization.Codec; -import dev.latvian.mods.kubejs.item.ItemStackJS; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; @@ -28,12 +28,12 @@ public Codec codec() { @Override public TypeInfo typeInfo() { - return ItemStackJS.TYPE_INFO; + return ItemWrapper.TYPE_INFO; } @Override public boolean hasPriority(Context cx, KubeRecipe recipe, Object from) { - return ItemStackJS.isItemStackLike(from); + return ItemWrapper.isItemStackLike(from); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java index f1187717d..2690de3dd 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java @@ -2,9 +2,9 @@ import com.google.gson.JsonPrimitive; import com.mojang.serialization.Codec; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.fluid.FluidWrapper; import dev.latvian.mods.kubejs.holder.HolderWrapper; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.schema.RecipeComponentFactory; import dev.latvian.mods.kubejs.registry.RegistryType; @@ -61,7 +61,7 @@ public Holder wrap(Context cx, KubeRecipe recipe, Object from) { } else if (from instanceof Item item) { return (Holder) item.builtInRegistryHolder(); } else { - return (Holder) ItemStackJS.wrap(cx, from).getItemHolder(); + return (Holder) ItemWrapper.wrap(cx, from).getItemHolder(); } } else if (registry == BuiltInRegistries.FLUID) { if (from instanceof FluidStack fs) { diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java index b86f1a4d6..bd1add352 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java @@ -3,7 +3,6 @@ import com.mojang.serialization.Codec; import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.bindings.SizedIngredientWrapper; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; @@ -35,7 +34,7 @@ public TypeInfo typeInfo() { @Override public boolean hasPriority(Context cx, KubeRecipe recipe, Object from) { - return from instanceof SizedIngredient || IngredientJS.isIngredientLike(from); + return IngredientWrapper.isIngredientLike(from); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/match/ReplacementMatch.java b/src/main/java/dev/latvian/mods/kubejs/recipe/match/ReplacementMatch.java index 6dee233c3..a557970c5 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/match/ReplacementMatch.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/match/ReplacementMatch.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.recipe.match; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.rhino.Context; public interface ReplacementMatch { @@ -17,7 +17,7 @@ static ReplacementMatch wrap(Context cx, Object o) { } else if (o instanceof ReplacementMatch m) { return m; } else { - var in = IngredientJS.wrap(cx, o); + var in = IngredientWrapper.wrap(cx, o); return in.isEmpty() ? NONE : in; } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/RecipeViewerEntryType.java b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/RecipeViewerEntryType.java index 1bc3a97da..7a505c3e1 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/RecipeViewerEntryType.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/RecipeViewerEntryType.java @@ -1,9 +1,9 @@ package dev.latvian.mods.kubejs.recipe.viewer; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.core.FluidKJS; import dev.latvian.mods.kubejs.fluid.FluidWrapper; import dev.latvian.mods.kubejs.item.ItemPredicate; -import dev.latvian.mods.kubejs.item.ItemStackJS; import dev.latvian.mods.kubejs.plugin.KubeJSPlugin; import dev.latvian.mods.kubejs.plugin.KubeJSPlugins; import dev.latvian.mods.kubejs.util.Lazy; @@ -34,13 +34,13 @@ public record Component(TypeInfo type, StreamCodec streamCodec, Predica } public static final RecipeViewerEntryType ITEM = new RecipeViewerEntryType("item", - new Component<>(ItemStackJS.TYPE_INFO, ItemStack.STREAM_CODEC, ItemStack::isEmpty), + new Component<>(ItemWrapper.TYPE_INFO, ItemStack.STREAM_CODEC, ItemStack::isEmpty), new Component<>(ItemPredicate.TYPE_INFO, Ingredient.CONTENTS_STREAM_CODEC, Ingredient::isEmpty), - new Component<>(ItemStackJS.ITEM_TYPE_INFO, ByteBufCodecs.registry(Registries.ITEM), i -> i == Items.AIR) + new Component<>(ItemWrapper.ITEM_TYPE_INFO, ByteBufCodecs.registry(Registries.ITEM), i -> i == Items.AIR) ) { @Override public Object wrapEntry(Context cx, Object from) { - return ItemStackJS.wrap(cx, from); + return ItemWrapper.wrap(cx, from); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemEntriesKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemEntriesKubeEvent.java index a4aa8c6cb..62b234ffa 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemEntriesKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemEntriesKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.recipe.viewer.server; -import dev.latvian.mods.kubejs.item.ItemStackJS; +import dev.latvian.mods.kubejs.bindings.ItemWrapper; import dev.latvian.mods.kubejs.recipe.viewer.AddEntriesKubeEvent; import dev.latvian.mods.rhino.Context; import net.minecraft.world.item.ItemStack; @@ -17,7 +17,7 @@ public ServerAddItemEntriesKubeEvent(List list) { @Override public void add(Context cx, Object[] items) { for (var item : items) { - list.add(ItemStackJS.wrap(cx, item)); + list.add(ItemWrapper.wrap(cx, item)); } } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemInformationKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemInformationKubeEvent.java index 6eaa0b3f4..e65bceadc 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemInformationKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerAddItemInformationKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.recipe.viewer.server; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.recipe.viewer.AddInformationKubeEvent; import dev.latvian.mods.rhino.Context; import net.minecraft.network.chat.Component; @@ -16,6 +16,6 @@ public ServerAddItemInformationKubeEvent(List list) { @Override public void add(Context cx, Object filter, List info) { - list.add(new ItemData.Info(IngredientJS.wrap(cx, filter), info)); + list.add(new ItemData.Info(IngredientWrapper.wrap(cx, filter), info)); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerGroupItemEntriesKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerGroupItemEntriesKubeEvent.java index 9a61185d9..6e4084ff5 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerGroupItemEntriesKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerGroupItemEntriesKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.recipe.viewer.server; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.recipe.viewer.GroupEntriesKubeEvent; import dev.latvian.mods.rhino.Context; import net.minecraft.network.chat.Component; @@ -17,6 +17,6 @@ public ServerGroupItemEntriesKubeEvent(List list) { @Override public void group(Context cx, Object filter, ResourceLocation groupId, Component description) { - list.add(new ItemData.Group(IngredientJS.wrap(cx, filter), groupId, description)); + list.add(new ItemData.Group(IngredientWrapper.wrap(cx, filter), groupId, description)); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRegisterItemSubtypesKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRegisterItemSubtypesKubeEvent.java index f7261685d..bdbfcef4d 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRegisterItemSubtypesKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRegisterItemSubtypesKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.recipe.viewer.server; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.recipe.viewer.RegisterSubtypesKubeEvent; import dev.latvian.mods.kubejs.recipe.viewer.SubtypeInterpreter; import dev.latvian.mods.rhino.Context; @@ -22,6 +22,6 @@ public void register(Context cx, Object filter, SubtypeInterpreter interpreter) @Override public void useComponents(Context cx, Object filter, List> components) { - list.add(new ItemData.DataComponentSubtypes(IngredientJS.wrap(cx, filter), components)); + list.add(new ItemData.DataComponentSubtypes(IngredientWrapper.wrap(cx, filter), components)); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRemoveItemEntriesKubeEvent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRemoveItemEntriesKubeEvent.java index 0c86f635d..77925cc25 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRemoveItemEntriesKubeEvent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/viewer/server/ServerRemoveItemEntriesKubeEvent.java @@ -1,6 +1,6 @@ package dev.latvian.mods.kubejs.recipe.viewer.server; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.recipe.viewer.RemoveEntriesKubeEvent; import dev.latvian.mods.rhino.Context; import net.minecraft.world.item.crafting.Ingredient; @@ -16,6 +16,6 @@ public ServerRemoveItemEntriesKubeEvent(List removedEntries) { @Override public void remove(Context cx, Object filter) { - removedEntries.add(IngredientJS.wrap(cx, filter)); + removedEntries.add(IngredientWrapper.wrap(cx, filter)); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/script/ScriptFile.java b/src/main/java/dev/latvian/mods/kubejs/script/ScriptFile.java index 6b2a87f2d..1375a1b76 100644 --- a/src/main/java/dev/latvian/mods/kubejs/script/ScriptFile.java +++ b/src/main/java/dev/latvian/mods/kubejs/script/ScriptFile.java @@ -107,6 +107,7 @@ public String skipLoading() { @Override public int compareTo(ScriptFile o) { - return Integer.compare(o.priority, priority); + int i = Integer.compare(o.priority, priority); + return i == 0 ? info.locationPath.compareToIgnoreCase(o.info.locationPath) : i; } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/script/ScriptFileInfo.java b/src/main/java/dev/latvian/mods/kubejs/script/ScriptFileInfo.java index e708ecda1..b006f3133 100644 --- a/src/main/java/dev/latvian/mods/kubejs/script/ScriptFileInfo.java +++ b/src/main/java/dev/latvian/mods/kubejs/script/ScriptFileInfo.java @@ -14,13 +14,15 @@ public class ScriptFileInfo { public final Path path; public final String file; public final ResourceLocation id; + public final String locationPath; public final String location; public ScriptFileInfo(ScriptPackInfo p, Path ph, String f) { - pack = p; - path = ph; - file = f; - id = ResourceLocation.fromNamespaceAndPath(pack.namespace, FILE_FIXER.matcher(pack.pathStart + file).replaceAll("_").toLowerCase(Locale.ROOT)); - location = ID.string(pack.namespace + ":" + pack.pathStart + file); + this.pack = p; + this.path = ph; + this.file = f; + this.id = ResourceLocation.fromNamespaceAndPath(pack.namespace, FILE_FIXER.matcher(pack.pathStart + file).replaceAll("_").toLowerCase(Locale.ROOT)); + this.locationPath = pack.pathStart + file; + this.location = ID.string(pack.namespace + ":" + locationPath); } } \ No newline at end of file diff --git a/src/main/java/dev/latvian/mods/kubejs/script/ScriptManager.java b/src/main/java/dev/latvian/mods/kubejs/script/ScriptManager.java index 99bc62a63..0cae7c8f3 100644 --- a/src/main/java/dev/latvian/mods/kubejs/script/ScriptManager.java +++ b/src/main/java/dev/latvian/mods/kubejs/script/ScriptManager.java @@ -118,8 +118,6 @@ public void loadPackFromDirectory(Path path, String name, boolean exampleFile) { for (var fileInfo : pack.info.scripts) { loadFile(pack, fileInfo); } - - pack.scripts.sort(null); } packs.put(pack.info.namespace, pack); @@ -175,6 +173,8 @@ private void load(long startAll) { for (var pack : packs.values()) { try { + pack.scripts.sort(null); + for (var file : pack.scripts) { t++; var start = System.currentTimeMillis(); diff --git a/src/main/java/dev/latvian/mods/kubejs/util/JsonIO.java b/src/main/java/dev/latvian/mods/kubejs/util/JsonIO.java index 44e415e54..9fed86073 100644 --- a/src/main/java/dev/latvian/mods/kubejs/util/JsonIO.java +++ b/src/main/java/dev/latvian/mods/kubejs/util/JsonIO.java @@ -5,15 +5,12 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; -import com.google.gson.internal.Streams; -import com.google.gson.stream.JsonWriter; import dev.latvian.mods.rhino.Context; import org.jetbrains.annotations.Nullable; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.io.Writer; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; @@ -91,15 +88,8 @@ public static String readString(Path path) throws IOException { public static void write(Path path, @Nullable JsonElement json) throws IOException { if (json == null || json.isJsonNull()) { Files.deleteIfExists(path); - return; - } - - try (Writer fileWriter = Files.newBufferedWriter(path)) { - var jsonWriter = new JsonWriter(fileWriter); - jsonWriter.setIndent("\t"); - jsonWriter.setSerializeNulls(true); - jsonWriter.setLenient(true); - Streams.write(json, jsonWriter); + } else { + Files.writeString(path, JsonUtils.toPrettyString(json)); } } diff --git a/src/main/java/dev/latvian/mods/kubejs/util/JsonUtils.java b/src/main/java/dev/latvian/mods/kubejs/util/JsonUtils.java index d164911cd..f2c54185a 100644 --- a/src/main/java/dev/latvian/mods/kubejs/util/JsonUtils.java +++ b/src/main/java/dev/latvian/mods/kubejs/util/JsonUtils.java @@ -7,18 +7,12 @@ import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSyntaxException; -import com.google.gson.internal.Streams; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import dev.latvian.mods.rhino.util.HideFromJS; import org.jetbrains.annotations.Nullable; -import java.io.IOException; -import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -26,7 +20,7 @@ public interface JsonUtils { @HideFromJS - Gson GSON = new GsonBuilder().disableHtmlEscaping().setLenient().create(); + Gson GSON = new GsonBuilder().disableHtmlEscaping().setLenient().serializeNulls().create(); static JsonElement copy(@Nullable JsonElement element) { if (element == null || element.isJsonNull()) { @@ -167,35 +161,14 @@ static Object toObject(@Nullable JsonElement json) { } static String toString(JsonElement json) { - var writer = new StringWriter(); - - try { - var jsonWriter = new JsonWriter(writer); - jsonWriter.setSerializeNulls(true); - jsonWriter.setLenient(true); - jsonWriter.setHtmlSafe(false); - Streams.write(json, jsonWriter); - } catch (IOException ex) { - ex.printStackTrace(); - } - - return writer.toString(); + return GSON.toJson(json); } static String toPrettyString(JsonElement json) { var writer = new StringWriter(); - - try { - var jsonWriter = new JsonWriter(writer); - jsonWriter.setIndent("\t"); - jsonWriter.setSerializeNulls(true); - jsonWriter.setLenient(true); - jsonWriter.setHtmlSafe(false); - Streams.write(json, jsonWriter); - } catch (IOException ex) { - ex.printStackTrace(); - } - + var jsonWriter = new JsonWriter(writer); + jsonWriter.setIndent("\t"); + GSON.toJson(json, jsonWriter); return writer.toString(); } @@ -205,16 +178,7 @@ static JsonElement fromString(@Nullable String string) { } try { - var jsonReader = new JsonReader(new StringReader(string)); - JsonElement element; - jsonReader.setLenient(true); - element = Streams.parse(jsonReader); - - if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) { - throw new JsonSyntaxException("Did not consume the entire document."); - } - - return element; + return GSON.fromJson(string, JsonElement.class); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/main/java/dev/latvian/mods/kubejs/util/ListJS.java b/src/main/java/dev/latvian/mods/kubejs/util/ListJS.java index 9058c29d7..a902f0c1a 100644 --- a/src/main/java/dev/latvian/mods/kubejs/util/ListJS.java +++ b/src/main/java/dev/latvian/mods/kubejs/util/ListJS.java @@ -29,11 +29,6 @@ static List of(@Nullable Object o) { return ofArray(o); } - static List orEmpty(@Nullable Object o) { - var l = of(o); - return l == null ? List.of() : l; - } - static List orSelf(@Nullable Object o) { var l = of(o); diff --git a/src/main/java/dev/latvian/mods/kubejs/util/SlotFilter.java b/src/main/java/dev/latvian/mods/kubejs/util/SlotFilter.java index 3d666bce7..0d6fbb924 100644 --- a/src/main/java/dev/latvian/mods/kubejs/util/SlotFilter.java +++ b/src/main/java/dev/latvian/mods/kubejs/util/SlotFilter.java @@ -2,7 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.regexp.NativeRegExp; import dev.latvian.mods.rhino.type.JSObjectTypeInfo; @@ -20,7 +20,7 @@ public record SlotFilter(Ingredient item, int index) { public static final SlotFilter EMPTY = new SlotFilter(Ingredient.EMPTY, -1); - public static final TypeInfo TYPE_INFO = TypeInfo.INT.or(IngredientJS.TYPE_INFO).or(new JSObjectTypeInfo(List.of(new JSOptionalParam("item", IngredientJS.TYPE_INFO, true), new JSOptionalParam("index", TypeInfo.INT, true)))); + public static final TypeInfo TYPE_INFO = TypeInfo.INT.or(IngredientWrapper.TYPE_INFO).or(new JSObjectTypeInfo(List.of(new JSOptionalParam("item", IngredientWrapper.TYPE_INFO, true), new JSOptionalParam("index", TypeInfo.INT, true)))); public static SlotFilter of(Ingredient ingredient, int index) { return ingredient.isEmpty() && index == -1 ? EMPTY : new SlotFilter(ingredient, index); @@ -41,7 +41,7 @@ public static SlotFilter wrap(Context cx, Object o, TypeInfo target) { if (o instanceof Number num) { return of(Ingredient.EMPTY, num.intValue()); } else if (o instanceof String || o instanceof Ingredient || o instanceof NativeRegExp || o instanceof Pattern) { - return of(IngredientJS.wrap(cx, o), -1); + return of(IngredientWrapper.wrap(cx, o), -1); } else { return (SlotFilter) ((RecordTypeInfo) target).wrap(cx, o, target); }