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 static Stream<GeyserMapping> mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch,
ProblemReporter reporter) {
public static Stream<GeyserMapping_> mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch,
ProblemReporter reporter) {
ItemModel model = Minecraft.getInstance().getModelManager().getItemModel(modelLocation);
MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch, reporter.forChild(() -> "model " + modelLocation + " "));
return mapItem(model, context);
}
private static Stream<GeyserMapping> mapItem(ItemModel model, MappingContext context) {
private static Stream<GeyserMapping_> mapItem(ItemModel model, MappingContext context) {
switch (model) {
case BlockModelWrapper modelWrapper -> {
ResourceLocation itemModel = ((BlockModelWrapperLocationAccessor) modelWrapper).geyser_mappings_generator$getModelOrigin();
@@ -66,7 +66,7 @@ public class GeyserItemMapper {
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();
GeyserConditionPredicate.Property predicateProperty = switch (property) {
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
SelectItemModelProperty<T> property = ((SelectItemModelAccessor<T>) model).getProperty();
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));
}
public GeyserMapping create(ResourceLocation bedrockIdentifier) {
return new GeyserMapping(model, bedrockIdentifier, Optional.of(displayName), predicateStack,
new GeyserMapping.BedrockOptions(Optional.empty(), true, false, protectionValue), // TODO handheld prediction
public GeyserMapping_ create(ResourceLocation bedrockIdentifier) {
return new GeyserMapping_(model, bedrockIdentifier, Optional.of(displayName), predicateStack,
new GeyserMapping_.BedrockOptions(Optional.empty(), true, false, protectionValue), // TODO handheld prediction
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;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
@@ -13,8 +14,9 @@ import java.util.Optional;
import java.util.function.Function;
// TODO other keys, etc.
public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIdentifier, Optional<String> displayName,
List<GeyserPredicate> predicates, BedrockOptions bedrockOptions, DataComponentPatch components) {
// TODO sometimes still includes components key when patch before filtering is not empty but after is
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,
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();
});
public static final Codec<GeyserMapping> CODEC = RecordCodecBuilder.create(instance ->
public static final MapCodec<GeyserMapping_> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
Codec.STRING.fieldOf("type").forGetter(mapping -> "definition"), // TODO
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("predicate", List.of()).forGetter(GeyserMapping::predicates),
BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserMapping::bedrockOptions),
FILTERED_COMPONENT_MAP_CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(GeyserMapping::components)
).apply(instance, (type, model, bedrockIdentifier, displayName, predicates, bedrockOptions, components)
-> new GeyserMapping(model, bedrockIdentifier, displayName, predicates, bedrockOptions, components))
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("predicate", List.of()).forGetter(GeyserMapping_::predicates),
BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserMapping_::bedrockOptions),
FILTERED_COMPONENT_MAP_CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(GeyserMapping_::components)
).apply(instance, GeyserMapping_::new)
);
public String textureName() {
return bedrockOptions.icon.orElse(iconFromResourceLocation(bedrockIdentifier));
}
public static String iconFromResourceLocation(ResourceLocation location) {
return location.toString().replace(':', '.').replace('/', '_');
}
public boolean conflictsWith(GeyserMapping other) {
public boolean conflictsWith(GeyserMapping_ other) {
if (!model.equals(other.model)) {
return false;
} else if (predicates.size() == other.predicates.size()) {
@@ -69,6 +65,11 @@ public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIden
return false;
}
@Override
public Type type() {
return Type.SINGLE;
}
public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue) {
public static final Codec<BedrockOptions> CODEC = RecordCodecBuilder.create(instance ->
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 String iconFromResourceLocation(ResourceLocation location) {
return location.toString().replace(':', '.').replace('/', '_');
}
}

View File

@@ -21,7 +21,7 @@ import java.util.function.Function;
// TODO group definitions
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 ->
instance.group(
@@ -30,18 +30,18 @@ public class GeyserMappings {
).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() {}
private GeyserMappings(Map<Holder<Item>, Collection<GeyserMapping>> mappings) {
private GeyserMappings(Map<Holder<Item>, Collection<GeyserMapping_>> mappings) {
for (Holder<Item> item : mappings.keySet()) {
this.mappings.putAll(item, mappings.get(item));
}
}
public void map(Holder<Item> item, GeyserMapping mapping) {
for (GeyserMapping existing : mappings.get(item)) {
public void map(Holder<Item> item, GeyserMapping_ mapping) {
for (GeyserMapping_ existing : mappings.get(item)) {
if (existing.conflictsWith(mapping)) {
throw new IllegalArgumentException("Mapping conflicts with existing mapping");
}
@@ -53,7 +53,7 @@ public class GeyserMappings {
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);
//noinspection OptionalAssignedToNull - annoying Mojang
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();
}
}

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.serialization.Codec;
import org.geysermc.packgenerator.mapping.geyser.GeyserMapping;
import org.geysermc.packgenerator.mapping.geyser.GeyserMapping_;
import java.util.HashMap;
import java.util.List;
@@ -33,7 +33,7 @@ public record BedrockTextures(Map<String, String> textures) {
public static class Builder {
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);
}

View File

@@ -7,7 +7,7 @@ import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.EquipmentSlot;
import org.geysermc.packgenerator.CodecUtil;
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.BedrockVersion;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +53,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
public void save(Path attachablesPath) throws IOException {
// 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 {