1
0
mirror of https://github.com/GeyserMC/Rainbow.git synced 2025-12-19 14:59:16 +00:00

Work on implementing group definitions

This commit is contained in:
Eclipse
2025-07-03 07:47:01 +00:00
parent 4b229a170d
commit 7348fc60cb
7 changed files with 101 additions and 36 deletions

View File

@@ -38,14 +38,14 @@ import java.util.stream.Stream;
public class GeyserItemMapper { public class GeyserItemMapper {
public static Stream<GeyserMapping> mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch, public static Stream<GeyserMapping_> mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch,
ProblemReporter reporter) { ProblemReporter reporter) {
ItemModel model = Minecraft.getInstance().getModelManager().getItemModel(modelLocation); ItemModel model = Minecraft.getInstance().getModelManager().getItemModel(modelLocation);
MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch, reporter.forChild(() -> "model " + modelLocation + " ")); MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch, reporter.forChild(() -> "model " + modelLocation + " "));
return mapItem(model, context); return mapItem(model, context);
} }
private static Stream<GeyserMapping> mapItem(ItemModel model, MappingContext context) { private static Stream<GeyserMapping_> mapItem(ItemModel model, MappingContext context) {
switch (model) { switch (model) {
case BlockModelWrapper modelWrapper -> { case BlockModelWrapper modelWrapper -> {
ResourceLocation itemModel = ((BlockModelWrapperLocationAccessor) modelWrapper).geyser_mappings_generator$getModelOrigin(); ResourceLocation itemModel = ((BlockModelWrapperLocationAccessor) modelWrapper).geyser_mappings_generator$getModelOrigin();
@@ -66,7 +66,7 @@ public class GeyserItemMapper {
return Stream.empty(); return Stream.empty();
} }
private static Stream<GeyserMapping> mapConditionalModel(ConditionalItemModel model, MappingContext context) { private static Stream<GeyserMapping_> mapConditionalModel(ConditionalItemModel model, MappingContext context) {
ItemModelPropertyTest property = ((ConditionalItemModelAccessor) model).getProperty(); ItemModelPropertyTest property = ((ConditionalItemModelAccessor) model).getProperty();
GeyserConditionPredicate.Property predicateProperty = switch (property) { GeyserConditionPredicate.Property predicateProperty = switch (property) {
case Broken ignored -> GeyserConditionPredicate.BROKEN; case Broken ignored -> GeyserConditionPredicate.BROKEN;
@@ -90,7 +90,7 @@ public class GeyserItemMapper {
); );
} }
private static <T> Stream<GeyserMapping> mapSelectModel(SelectItemModel<T> model, MappingContext context) { private static <T> Stream<GeyserMapping_> mapSelectModel(SelectItemModel<T> model, MappingContext context) {
//noinspection unchecked //noinspection unchecked
SelectItemModelProperty<T> property = ((SelectItemModelAccessor<T>) model).getProperty(); SelectItemModelProperty<T> property = ((SelectItemModelAccessor<T>) model).getProperty();
Function<T, GeyserMatchPredicate.MatchPredicateData> dataConstructor = switch (property) { Function<T, GeyserMatchPredicate.MatchPredicateData> dataConstructor = switch (property) {
@@ -127,9 +127,9 @@ public class GeyserItemMapper {
return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName)); return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName));
} }
public GeyserMapping create(ResourceLocation bedrockIdentifier) { public GeyserMapping_ create(ResourceLocation bedrockIdentifier) {
return new GeyserMapping(model, bedrockIdentifier, Optional.of(displayName), predicateStack, return new GeyserMapping_(model, bedrockIdentifier, Optional.of(displayName), predicateStack,
new GeyserMapping.BedrockOptions(Optional.empty(), true, false, protectionValue), // TODO handheld prediction new GeyserMapping_.BedrockOptions(Optional.empty(), true, false, protectionValue), // TODO handheld prediction
componentPatch); componentPatch);
} }
} }

View File

@@ -0,0 +1,37 @@
package org.geysermc.packgenerator.mapping.geyser;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.util.StringRepresentable;
import org.jetbrains.annotations.NotNull;
public interface GeyserMappingNew {
Codec<GeyserMappingNew> CODEC = Type.CODEC.dispatch(GeyserMappingNew::type, Type::codec);
Type type();
enum Type implements StringRepresentable {
SINGLE("definition", GeyserMapping_.CODEC),
GROUP("group", GroupDefinition.CODEC);
public static final Codec<Type> CODEC = StringRepresentable.fromEnum(Type::values);
private final String name;
private final MapCodec<? extends GeyserMappingNew> codec;
Type(String name, MapCodec<? extends GeyserMappingNew> codec) {
this.name = name;
this.codec = codec;
}
public MapCodec<? extends GeyserMappingNew> codec() {
return codec;
}
@Override
public @NotNull String getSerializedName() {
return name;
}
}
}

View File

@@ -1,6 +1,7 @@
package org.geysermc.packgenerator.mapping.geyser; package org.geysermc.packgenerator.mapping.geyser;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponentType;
@@ -13,8 +14,9 @@ import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
// TODO other keys, etc. // TODO other keys, etc.
public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIdentifier, Optional<String> displayName, // TODO sometimes still includes components key when patch before filtering is not empty but after is
List<GeyserPredicate> predicates, BedrockOptions bedrockOptions, DataComponentPatch components) { public record GeyserMapping_(ResourceLocation model, ResourceLocation bedrockIdentifier, Optional<String> displayName,
List<GeyserPredicate> predicates, BedrockOptions bedrockOptions, DataComponentPatch components) implements GeyserMappingNew {
private static final List<DataComponentType<?>> SUPPORTED_COMPONENTS = List.of(DataComponents.CONSUMABLE, DataComponents.EQUIPPABLE, DataComponents.FOOD, private static final List<DataComponentType<?>> 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); DataComponents.MAX_DAMAGE, DataComponents.MAX_STACK_SIZE, DataComponents.USE_COOLDOWN, DataComponents.ENCHANTABLE, DataComponents.ENCHANTMENT_GLINT_OVERRIDE);
@@ -32,28 +34,22 @@ public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIden
return filtered.build(); return filtered.build();
}); });
public static final Codec<GeyserMapping> CODEC = RecordCodecBuilder.create(instance -> public static final MapCodec<GeyserMapping_> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group( instance.group(
Codec.STRING.fieldOf("type").forGetter(mapping -> "definition"), // TODO ResourceLocation.CODEC.fieldOf("model").forGetter(GeyserMapping_::model),
ResourceLocation.CODEC.fieldOf("model").forGetter(GeyserMapping::model), ResourceLocation.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserMapping_::bedrockIdentifier),
ResourceLocation.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserMapping::bedrockIdentifier), Codec.STRING.optionalFieldOf("display_name").forGetter(GeyserMapping_::displayName),
Codec.STRING.optionalFieldOf("display_name").forGetter(GeyserMapping::displayName), GeyserPredicate.LIST_CODEC.optionalFieldOf("predicate", List.of()).forGetter(GeyserMapping_::predicates),
GeyserPredicate.LIST_CODEC.optionalFieldOf("predicate", List.of()).forGetter(GeyserMapping::predicates), BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserMapping_::bedrockOptions),
BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserMapping::bedrockOptions), FILTERED_COMPONENT_MAP_CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(GeyserMapping_::components)
FILTERED_COMPONENT_MAP_CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(GeyserMapping::components) ).apply(instance, GeyserMapping_::new)
).apply(instance, (type, model, bedrockIdentifier, displayName, predicates, bedrockOptions, components)
-> new GeyserMapping(model, bedrockIdentifier, displayName, predicates, bedrockOptions, components))
); );
public String textureName() { public String textureName() {
return bedrockOptions.icon.orElse(iconFromResourceLocation(bedrockIdentifier)); return bedrockOptions.icon.orElse(iconFromResourceLocation(bedrockIdentifier));
} }
public static String iconFromResourceLocation(ResourceLocation location) { public boolean conflictsWith(GeyserMapping_ other) {
return location.toString().replace(':', '.').replace('/', '_');
}
public boolean conflictsWith(GeyserMapping other) {
if (!model.equals(other.model)) { if (!model.equals(other.model)) {
return false; return false;
} else if (predicates.size() == other.predicates.size()) { } else if (predicates.size() == other.predicates.size()) {
@@ -69,6 +65,11 @@ public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIden
return false; return false;
} }
@Override
public Type type() {
return Type.SINGLE;
}
public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue) { public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue) {
public static final Codec<BedrockOptions> CODEC = RecordCodecBuilder.create(instance -> public static final Codec<BedrockOptions> CODEC = RecordCodecBuilder.create(instance ->
instance.group( instance.group(
@@ -80,4 +81,8 @@ public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIden
); );
public static final BedrockOptions DEFAULT = new BedrockOptions(Optional.empty(), true, false, 0); public static final BedrockOptions DEFAULT = new BedrockOptions(Optional.empty(), true, false, 0);
} }
public static String iconFromResourceLocation(ResourceLocation location) {
return location.toString().replace(':', '.').replace('/', '_');
}
} }

View File

@@ -21,7 +21,7 @@ import java.util.function.Function;
// TODO group definitions // TODO group definitions
public class GeyserMappings { public class GeyserMappings {
private static final Codec<Map<Holder<Item>, Collection<GeyserMapping>>> MAPPINGS_CODEC = Codec.unboundedMap(Item.CODEC, GeyserMapping.CODEC.listOf().xmap(Function.identity(), ArrayList::new)); private static final Codec<Map<Holder<Item>, Collection<GeyserMapping_>>> MAPPINGS_CODEC = Codec.unboundedMap(Item.CODEC, GeyserMapping_.CODEC.listOf().xmap(Function.identity(), ArrayList::new));
public static final Codec<GeyserMappings> CODEC = RecordCodecBuilder.create(instance -> public static final Codec<GeyserMappings> CODEC = RecordCodecBuilder.create(instance ->
instance.group( instance.group(
@@ -30,18 +30,18 @@ public class GeyserMappings {
).apply(instance, (format, mappings) -> new GeyserMappings(mappings)) ).apply(instance, (format, mappings) -> new GeyserMappings(mappings))
); );
private final Multimap<Holder<Item>, GeyserMapping> mappings = MultimapBuilder.hashKeys().hashSetValues().build(); private final Multimap<Holder<Item>, GeyserMapping_> mappings = MultimapBuilder.hashKeys().hashSetValues().build();
public GeyserMappings() {} public GeyserMappings() {}
private GeyserMappings(Map<Holder<Item>, Collection<GeyserMapping>> mappings) { private GeyserMappings(Map<Holder<Item>, Collection<GeyserMapping_>> mappings) {
for (Holder<Item> item : mappings.keySet()) { for (Holder<Item> item : mappings.keySet()) {
this.mappings.putAll(item, mappings.get(item)); this.mappings.putAll(item, mappings.get(item));
} }
} }
public void map(Holder<Item> item, GeyserMapping mapping) { public void map(Holder<Item> item, GeyserMapping_ mapping) {
for (GeyserMapping existing : mappings.get(item)) { for (GeyserMapping_ existing : mappings.get(item)) {
if (existing.conflictsWith(mapping)) { if (existing.conflictsWith(mapping)) {
throw new IllegalArgumentException("Mapping conflicts with existing mapping"); throw new IllegalArgumentException("Mapping conflicts with existing mapping");
} }
@@ -53,7 +53,7 @@ public class GeyserMappings {
return mappings.size(); return mappings.size();
} }
public void map(ItemStack stack, ProblemReporter reporter, Consumer<GeyserMapping> mappingConsumer) { public void map(ItemStack stack, ProblemReporter reporter, Consumer<GeyserMapping_> mappingConsumer) {
Optional<? extends ResourceLocation> patchedModel = stack.getComponentsPatch().get(DataComponents.ITEM_MODEL); Optional<? extends ResourceLocation> patchedModel = stack.getComponentsPatch().get(DataComponents.ITEM_MODEL);
//noinspection OptionalAssignedToNull - annoying Mojang //noinspection OptionalAssignedToNull - annoying Mojang
if (patchedModel == null || patchedModel.isEmpty()) { if (patchedModel == null || patchedModel.isEmpty()) {
@@ -76,7 +76,7 @@ public class GeyserMappings {
}); });
} }
public Map<Holder<Item>, Collection<GeyserMapping>> mappings() { public Map<Holder<Item>, Collection<GeyserMapping_>> mappings() {
return mappings.asMap(); return mappings.asMap();
} }
} }

View File

@@ -0,0 +1,23 @@
package org.geysermc.packgenerator.mapping.geyser;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import java.util.List;
import java.util.Optional;
public record GroupDefinition(Optional<ResourceLocation> model, List<GeyserMappingNew> definitions) implements GeyserMappingNew {
public static final MapCodec<GroupDefinition> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
ResourceLocation.CODEC.optionalFieldOf("model").forGetter(GroupDefinition::model),
GeyserMappingNew.CODEC.listOf().fieldOf("definitions").forGetter(GroupDefinition::definitions)
).apply(instance, GroupDefinition::new)
);
@Override
public Type type() {
return Type.GROUP;
}
}

View File

@@ -2,7 +2,7 @@ package org.geysermc.packgenerator.pack;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import org.geysermc.packgenerator.mapping.geyser.GeyserMapping; import org.geysermc.packgenerator.mapping.geyser.GeyserMapping_;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -33,7 +33,7 @@ public record BedrockTextures(Map<String, String> textures) {
public static class Builder { public static class Builder {
private final Map<String, String> textures = new HashMap<>(); private final Map<String, String> textures = new HashMap<>();
public Builder withItemTexture(GeyserMapping mapping, String texturePath) { public Builder withItemTexture(GeyserMapping_ mapping, String texturePath) {
return withTexture(mapping.textureName(), TEXTURES_FOLDER + texturePath); return withTexture(mapping.textureName(), TEXTURES_FOLDER + texturePath);
} }

View File

@@ -7,7 +7,7 @@ import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
import org.geysermc.packgenerator.CodecUtil; import org.geysermc.packgenerator.CodecUtil;
import org.geysermc.packgenerator.PackConstants; import org.geysermc.packgenerator.PackConstants;
import org.geysermc.packgenerator.mapping.geyser.GeyserMapping; import org.geysermc.packgenerator.mapping.geyser.GeyserMapping_;
import org.geysermc.packgenerator.pack.BedrockTextures; import org.geysermc.packgenerator.pack.BedrockTextures;
import org.geysermc.packgenerator.pack.BedrockVersion; import org.geysermc.packgenerator.pack.BedrockVersion;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -53,7 +53,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
public void save(Path attachablesPath) throws IOException { public void save(Path attachablesPath) throws IOException {
// Get a safe attachable path by using Geyser's way of getting icons // Get a safe attachable path by using Geyser's way of getting icons
CodecUtil.trySaveJson(CODEC, this, attachablesPath.resolve(GeyserMapping.iconFromResourceLocation(info.identifier) + ".json")); CodecUtil.trySaveJson(CODEC, this, attachablesPath.resolve(GeyserMapping_.iconFromResourceLocation(info.identifier) + ".json"));
} }
public static class Builder { public static class Builder {