From dcce9d3722e50da89ae1532a3d1f57eac80845a3 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Fri, 4 Jul 2025 12:03:07 +0000 Subject: [PATCH] Proper handheld detection and model -> texture --- .../mapping/geyser/GeyserItemMapper.java | 90 ++++++++++--------- .../mapping/geyser/GeyserMappings.java | 9 +- .../mixin/ModelManagerMixin.java | 1 + .../packgenerator/pack/BedrockPack.java | 9 +- 4 files changed, 55 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserItemMapper.java b/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserItemMapper.java index 5d0eeef..62322de 100644 --- a/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserItemMapper.java +++ b/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserItemMapper.java @@ -16,6 +16,8 @@ import net.minecraft.client.renderer.item.properties.select.Charge; import net.minecraft.client.renderer.item.properties.select.ContextDimension; import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperty; import net.minecraft.client.renderer.item.properties.select.TrimMaterialProperty; +import net.minecraft.client.resources.model.Material; +import net.minecraft.client.resources.model.ResolvedModel; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -34,49 +36,56 @@ import org.geysermc.packgenerator.mixin.SelectItemModelAccessor; import java.util.List; import java.util.Optional; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Stream; public class GeyserItemMapper { + private static final List HANDHELD_MODELS = Stream.of("item/handheld", "item/handheld_rod", "item/handheld_mace") + .map(ResourceLocation::withDefaultNamespace) + .toList(); - public static Stream mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch, - ProblemReporter reporter) { + public static void mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter, + BiConsumer mappingTextureConsumer) { ItemModel model = Minecraft.getInstance().getModelManager().getItemModel(modelLocation); - MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch, reporter.forChild(() -> "client item definition " + modelLocation + " ")); - return mapItem(model, context); + MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch, reporter.forChild(() -> "client item definition " + modelLocation + " "), mappingTextureConsumer); + mapItem(model, context); } - private static Stream mapItem(ItemModel model, MappingContext context) { + private static void mapItem(ItemModel model, MappingContext context) { switch (model) { case BlockModelWrapper modelWrapper -> { ResourceLocation itemModelLocation = ((BlockModelWrapperLocationAccessor) modelWrapper).geyser_mappings_generator$getModelOrigin(); - return ((ResolvedModelAccessor) Minecraft.getInstance().getModelManager()).geyser_mappings_generator$getResolvedModel(itemModelLocation) - .map(itemModel -> { + ((ResolvedModelAccessor) Minecraft.getInstance().getModelManager()).geyser_mappings_generator$getResolvedModel(itemModelLocation) + .ifPresentOrElse(itemModel -> { + ResolvedModel parentModel = itemModel.parent(); + boolean handheld = false; + if (parentModel != null) { + // debugName() returns the resource location of the model as a string + handheld = HANDHELD_MODELS.contains(ResourceLocation.parse(parentModel.debugName())); + } + ResourceLocation bedrockIdentifier = itemModelLocation; if (bedrockIdentifier.getNamespace().equals(ResourceLocation.DEFAULT_NAMESPACE)) { bedrockIdentifier = ResourceLocation.fromNamespaceAndPath("geyser_mc", itemModelLocation.getPath()); } - return Stream.of(context.create(bedrockIdentifier)); - }) - .orElseGet(() -> { - context.reporter.report(() -> "missing block model " + itemModelLocation); - return Stream.empty(); - }); + + ResourceLocation texture = itemModelLocation; + Material layer0Texture = itemModel.getTopTextureSlots().getMaterial("layer0"); + if (layer0Texture != null) { + texture = layer0Texture.texture(); + } + context.create(bedrockIdentifier, texture, handheld); + }, () -> context.reporter.report(() -> "missing block model " + itemModelLocation)); } - case ConditionalItemModel conditional -> { - return mapConditionalModel(conditional, context.child("condition " + conditional + " ")); - } - case SelectItemModel select -> { - return mapSelectModel(select, context.child("select " + select + " ")); - } - default -> {} + case ConditionalItemModel conditional -> mapConditionalModel(conditional, context.child("condition " + conditional + " ")); + case SelectItemModel select -> mapSelectModel(select, context.child("select " + select + " ")); + default -> context.reporter.report(() -> "unable to map item model " + model.getClass()); } - context.reporter.report(() -> "unable to map item model " + model.getClass()); - return Stream.empty(); } - private static Stream mapConditionalModel(ConditionalItemModel model, MappingContext context) { + private static void mapConditionalModel(ConditionalItemModel model, MappingContext context) { ItemModelPropertyTest property = ((ConditionalItemModelAccessor) model).getProperty(); GeyserConditionPredicate.Property predicateProperty = switch (property) { case Broken ignored -> GeyserConditionPredicate.BROKEN; @@ -88,19 +97,17 @@ public class GeyserItemMapper { }; if (predicateProperty == null) { context.reporter.report(() -> "unsupported conditional model property " + property); - return Stream.empty(); + return; } ItemModel onTrue = ((ConditionalItemModelAccessor) model).getOnTrue(); ItemModel onFalse = ((ConditionalItemModelAccessor) model).getOnFalse(); - return Stream.concat( - mapItem(onTrue, context.with(new GeyserConditionPredicate(predicateProperty, true), "condition on true ")), - mapItem(onFalse, context.with(new GeyserConditionPredicate(predicateProperty, false), "condition on false ")) - ); + mapItem(onTrue, context.with(new GeyserConditionPredicate(predicateProperty, true), "condition on true ")); + mapItem(onFalse, context.with(new GeyserConditionPredicate(predicateProperty, false), "condition on false ")); } - private static Stream mapSelectModel(SelectItemModel model, MappingContext context) { + private static void mapSelectModel(SelectItemModel model, MappingContext context) { //noinspection unchecked SelectItemModelProperty property = ((SelectItemModelAccessor) model).getProperty(); Function dataConstructor = switch (property) { @@ -113,34 +120,31 @@ public class GeyserItemMapper { }; if (dataConstructor == null) { context.reporter.report(() -> "unsupported select model property " + property); - return Stream.empty(); + return; } //noinspection unchecked Object2ObjectMap cases = ((SelectItemModelCasesAccessor) model).geyser_mappings_generator$getCases(); - return Stream.concat( - cases.entrySet().stream() - .flatMap(caze -> mapItem(caze.getValue(), context.with(new GeyserMatchPredicate(dataConstructor.apply(caze.getKey())), "select case " + caze.getKey() + " "))), - mapItem(cases.defaultReturnValue(), context.child("default case ")) - ); + + cases.entrySet().forEach(caze -> mapItem(caze.getValue(), context.with(new GeyserMatchPredicate(dataConstructor.apply(caze.getKey())), "select case " + caze.getKey() + " "))); + mapItem(cases.defaultReturnValue(), context.child("default case ")); } - private record MappingContext(List predicateStack, ResourceLocation model, String displayName, int protectionValue, DataComponentPatch componentPatch, - ProblemReporter reporter) { + private record MappingContext(List predicateStack, ResourceLocation model, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter, + BiConsumer mappingTextureConsumer) { public MappingContext with(GeyserPredicate predicate, String childName) { return new MappingContext(Stream.concat(predicateStack.stream(), Stream.of(predicate)).toList(), model, displayName, protectionValue, componentPatch, - reporter.forChild(() -> childName)); + reporter.forChild(() -> childName), mappingTextureConsumer); } public MappingContext child(String childName) { - return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName)); + return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName), mappingTextureConsumer); } - public GeyserSingleDefinition create(ResourceLocation bedrockIdentifier) { - return new GeyserSingleDefinition(Optional.of(model), bedrockIdentifier, Optional.of(displayName), predicateStack, - new GeyserSingleDefinition.BedrockOptions(Optional.empty(), true, false, protectionValue), // TODO handheld prediction - componentPatch); + public void create(ResourceLocation bedrockIdentifier, ResourceLocation texture, boolean displayHandheld) { + mappingTextureConsumer.accept(new GeyserSingleDefinition(Optional.of(model), bedrockIdentifier, Optional.of(displayName), predicateStack, + new GeyserSingleDefinition.BedrockOptions(Optional.empty(), true, displayHandheld, protectionValue), componentPatch), texture); } } } diff --git a/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserMappings.java b/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserMappings.java index 8543595..138c479 100644 --- a/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserMappings.java +++ b/src/main/java/org/geysermc/packgenerator/mapping/geyser/GeyserMappings.java @@ -17,6 +17,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; @@ -74,19 +75,19 @@ public class GeyserMappings { return mappings.size(); } - public void map(ItemStack stack, ResourceLocation model, ProblemReporter reporter, Consumer mappingConsumer) { + public void map(ItemStack stack, ResourceLocation model, ProblemReporter reporter, BiConsumer mappingTextureConsumer) { String displayName = stack.getHoverName().getString(); int protectionValue = 0; // TODO check the attributes - GeyserItemMapper.mapItem(model, displayName, protectionValue, stack.getComponentsPatch(), reporter) - .forEach(mapping -> { + GeyserItemMapper.mapItem(model, displayName, protectionValue, stack.getComponentsPatch(), reporter, + (mapping, texture) -> { try { map(stack.getItemHolder(), mapping); } catch (IllegalArgumentException exception) { reporter.forChild(() -> "mapping with bedrock identifier " + mapping.bedrockIdentifier() + " ").report(() -> "failed to add mapping to mappings file: " + exception.getMessage()); return; } - mappingConsumer.accept(mapping); + mappingTextureConsumer.accept(mapping, texture); }); } diff --git a/src/main/java/org/geysermc/packgenerator/mixin/ModelManagerMixin.java b/src/main/java/org/geysermc/packgenerator/mixin/ModelManagerMixin.java index 528ddd5..78e2e43 100644 --- a/src/main/java/org/geysermc/packgenerator/mixin/ModelManagerMixin.java +++ b/src/main/java/org/geysermc/packgenerator/mixin/ModelManagerMixin.java @@ -27,6 +27,7 @@ public abstract class ModelManagerMixin implements PreparableReloadListener, Aut Object resolved = original.call(instance); try { // Couldn't be bothered setting up access wideners, this resolves the second component of the ResolvedModels record, which is called "models" + // Ideally we'd somehow use the "this" instance, but that's not possible here since the lambda we inject into is a static one ((ModelManagerMixin) (Object) Minecraft.getInstance().getModelManager()).unbakedResolvedModels = (Map) resolved.getClass().getRecordComponents()[1].getAccessor().invoke(resolved); } catch (IllegalAccessException | InvocationTargetException | ClassCastException exception) { throw new RuntimeException(exception); diff --git a/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java b/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java index de59a20..5248e5e 100644 --- a/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java +++ b/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java @@ -101,13 +101,8 @@ public class BedrockPack { } }; - mappings.map(stack, model, mapReporter, mapping -> { - // TODO a proper way to get texture from item model - itemTextures.withItemTexture(mapping, mapping.bedrockIdentifier().getPath()); - ResourceLocation texture = mapping.bedrockIdentifier(); - if (texture.getNamespace().equals("geyser_mc")) { - texture = ResourceLocation.withDefaultNamespace(texture.getPath()); - } + mappings.map(stack, model, mapReporter, (mapping, texture) -> { + itemTextures.withItemTexture(mapping, texture.getPath()); texturesToExport.add(texture); AttachableMapper.mapItem(stack, mapping.bedrockIdentifier(), texturesToExport::add).ifPresent(attachables::add); });