diff --git a/src/main/java/org/geysermc/packgenerator/PackManager.java b/src/main/java/org/geysermc/packgenerator/PackManager.java index 116865c..d13ed4b 100644 --- a/src/main/java/org/geysermc/packgenerator/PackManager.java +++ b/src/main/java/org/geysermc/packgenerator/PackManager.java @@ -17,6 +17,7 @@ import org.geysermc.packgenerator.mappings.GeyserMappings; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.Optional; public final class PackManager { @@ -55,6 +56,7 @@ public final class PackManager { ResourceLocation model = patchedModel.get(); String displayName = stack.getHoverName().getString(); GeyserMapping mapping = new GeyserMapping(model, model, Optional.of(displayName), + List.of(), new GeyserMapping.BedrockOptions(Optional.empty(), true, false, 0), stack.getComponentsPatch()); mappings.map(stack.getItemHolder(), mapping); diff --git a/src/main/java/org/geysermc/packgenerator/mappings/GeyserMapping.java b/src/main/java/org/geysermc/packgenerator/mappings/GeyserMapping.java index 042c6a3..c75a1a3 100644 --- a/src/main/java/org/geysermc/packgenerator/mappings/GeyserMapping.java +++ b/src/main/java/org/geysermc/packgenerator/mappings/GeyserMapping.java @@ -6,6 +6,7 @@ import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; +import org.geysermc.packgenerator.mappings.predicate.GeyserPredicate; import java.util.List; import java.util.Optional; @@ -13,7 +14,7 @@ import java.util.function.Function; // TODO predicates, etc. public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIdentifier, Optional displayName, - BedrockOptions bedrockOptions, DataComponentPatch components) { + List predicates, BedrockOptions bedrockOptions, DataComponentPatch components) { private static final List> SUPPORTED_COMPONENTS = List.of(DataComponents.CONSUMABLE, DataComponents.EQUIPPABLE, DataComponents.FOOD, DataComponents.MAX_DAMAGE, DataComponents.MAX_STACK_SIZE, DataComponents.USE_COOLDOWN, DataComponents.ENCHANTABLE, DataComponents.ENCHANTMENT_GLINT_OVERRIDE); @@ -37,10 +38,11 @@ public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIden ResourceLocation.CODEC.fieldOf("model").forGetter(GeyserMapping::model), ResourceLocation.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserMapping::bedrockIdentifier), Codec.STRING.optionalFieldOf("display_name").forGetter(GeyserMapping::displayName), + GeyserPredicate.LIST_CODEC.optionalFieldOf("predicates", List.of()).forGetter(GeyserMapping::predicates), BedrockOptions.CODEC.fieldOf("bedrock_options").forGetter(GeyserMapping::bedrockOptions), FILTERED_COMPONENT_MAP_CODEC.fieldOf("components").forGetter(GeyserMapping::components) - ).apply(instance, (type, model, bedrockIdentifier, displayName, bedrockOptions, components) - -> new GeyserMapping(model, bedrockIdentifier, displayName, bedrockOptions, components)) + ).apply(instance, (type, model, bedrockIdentifier, displayName, predicates, bedrockOptions, components) + -> new GeyserMapping(model, bedrockIdentifier, displayName, predicates, bedrockOptions, components)) ); public record BedrockOptions(Optional icon, boolean allowOffhand, boolean displayHandheld, int protectionValue) { diff --git a/src/main/java/org/geysermc/packgenerator/mappings/predicate/GeyserConditionPredicate.java b/src/main/java/org/geysermc/packgenerator/mappings/predicate/GeyserConditionPredicate.java new file mode 100644 index 0000000..46e0b74 --- /dev/null +++ b/src/main/java/org/geysermc/packgenerator/mappings/predicate/GeyserConditionPredicate.java @@ -0,0 +1,92 @@ +package org.geysermc.packgenerator.mappings.predicate; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; +import org.jetbrains.annotations.NotNull; + +public record GeyserConditionPredicate(ConditionProperty property, boolean expected) implements GeyserPredicate { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> + instance.group( + ConditionProperty.CODEC.forGetter(GeyserConditionPredicate::property), + Codec.BOOL.optionalFieldOf("expected", true).forGetter(GeyserConditionPredicate::expected) + ).apply(instance, GeyserConditionPredicate::new) + ); + + public static final ConditionProperty BROKEN = unit(ConditionProperty.Type.BROKEN); + public static final ConditionProperty DAMAGED = unit(ConditionProperty.Type.DAMAGED); + public static final ConditionProperty FISHING_ROD_CAST = unit(ConditionProperty.Type.FISHING_ROD_CAST); + + @Override + public Type type() { + return Type.CONDITION; + } + + public interface ConditionProperty { + + MapCodec CODEC = Type.CODEC.dispatchMap("property", ConditionProperty::type, Type::codec); + + Type type(); + + enum Type implements StringRepresentable { + BROKEN("broken", MapCodec.unit(GeyserConditionPredicate.BROKEN)), + DAMAGED("damaged", MapCodec.unit(GeyserConditionPredicate.DAMAGED)), + CUSTOM_MODEL_DATA("custom_model_data", CustomModelData.CODEC), + HAS_COMPONENT("has_component", HasComponent.CODEC), + FISHING_ROD_CAST("fishing_rod_cast", MapCodec.unit(GeyserConditionPredicate.FISHING_ROD_CAST)); + + public static final Codec CODEC = StringRepresentable.fromEnum(Type::values); + + private final String name; + private final MapCodec codec; + + Type(String name, MapCodec codec) { + this.name = name; + this.codec = codec; + } + + public MapCodec codec() { + return codec; + } + + @Override + public @NotNull String getSerializedName() { + return name; + } + } + } + + public record CustomModelData(int index) implements ConditionProperty { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> + instance.group( + ExtraCodecs.NON_NEGATIVE_INT.optionalFieldOf("index", 0).forGetter(CustomModelData::index) + ).apply(instance, CustomModelData::new) + ); + + @Override + public Type type() { + return Type.CUSTOM_MODEL_DATA; + } + } + + public record HasComponent(DataComponentType component) implements ConditionProperty { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> + instance.group( + DataComponentType.CODEC.fieldOf("component").forGetter(HasComponent::component) + ).apply(instance, HasComponent::new) + ); + + @Override + public Type type() { + return Type.HAS_COMPONENT; + } + } + + private static ConditionProperty unit(ConditionProperty.Type type) { + return () -> type; + } +} diff --git a/src/main/java/org/geysermc/packgenerator/mappings/predicate/GeyserPredicate.java b/src/main/java/org/geysermc/packgenerator/mappings/predicate/GeyserPredicate.java new file mode 100644 index 0000000..f140e0d --- /dev/null +++ b/src/main/java/org/geysermc/packgenerator/mappings/predicate/GeyserPredicate.java @@ -0,0 +1,40 @@ +package org.geysermc.packgenerator.mappings.predicate; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface GeyserPredicate { + + Codec CODEC = Type.CODEC.dispatch(GeyserPredicate::type, Type::codec); + Codec> LIST_CODEC = ExtraCodecs.compactListCodec(CODEC); + + Type type(); + + enum Type implements StringRepresentable { + CONDITION("condition", GeyserConditionPredicate.CODEC); + + public static final Codec CODEC = StringRepresentable.fromEnum(Type::values); + + private final String name; + private final MapCodec codec; + + Type(String name, MapCodec codec) { + this.name = name; + this.codec = codec; + } + + public MapCodec codec() { + return codec; + } + + @Override + public @NotNull String getSerializedName() { + return name; + } + } +}