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

Merge pull request #13 from GeyserMC/feature/1.21.11

Update Rainbow to 1.21.11
This commit is contained in:
Eclipse
2025-12-17 12:22:56 +00:00
committed by GitHub
38 changed files with 216 additions and 210 deletions

View File

@@ -3,7 +3,6 @@ package org.geysermc.rainbow.client;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.item.ClientItem;
import net.minecraft.client.renderer.texture.SpriteContents;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.AtlasManager;
@@ -11,8 +10,8 @@ import net.minecraft.client.resources.model.EquipmentAssetManager;
import net.minecraft.client.resources.model.EquipmentClientInfo;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.item.equipment.EquipmentAsset;
import org.geysermc.rainbow.Rainbow;
@@ -40,13 +39,13 @@ public class MinecraftAssetResolver implements AssetResolver {
}
@Override
public Optional<ResolvedModel> getResolvedModel(ResourceLocation location) {
return ((ResolvedModelAccessor) modelManager).rainbow$getResolvedModel(location);
public Optional<ResolvedModel> getResolvedModel(Identifier identifier) {
return ((ResolvedModelAccessor) modelManager).rainbow$getResolvedModel(identifier);
}
@Override
public Optional<ClientItem> getClientItem(ResourceLocation location) {
return ((ResolvedModelAccessor) modelManager).rainbow$getClientItem(location);
public Optional<ClientItem> getClientItem(Identifier identifier) {
return ((ResolvedModelAccessor) modelManager).rainbow$getClientItem(identifier);
}
@Override
@@ -55,17 +54,17 @@ public class MinecraftAssetResolver implements AssetResolver {
}
@Override
public Optional<TextureResource> getTexture(ResourceLocation atlasId, ResourceLocation location) {
public Optional<TextureResource> getTexture(Identifier atlasId, Identifier identifier) {
if (atlasId == null) {
// Not in an atlas - so not animated, probably?
return RainbowIO.safeIO(() -> {
try (InputStream textureStream = resourceManager.open(Rainbow.decorateTextureLocation(location))) {
try (InputStream textureStream = resourceManager.open(Rainbow.decorateTextureIdentifier(identifier))) {
return new TextureResource(NativeImage.read(textureStream));
}
});
}
TextureAtlas atlas = atlasManager.getAtlasOrThrow(atlasId);
TextureAtlasSprite sprite = atlas.getSprite(location);
TextureAtlasSprite sprite = atlas.getSprite(identifier);
if (sprite == atlas.missingSprite()) {
return Optional.empty();
}

View File

@@ -4,10 +4,10 @@ import com.google.gson.JsonElement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.JsonOps;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.core.HolderLookup;
import net.minecraft.resources.RegistryOps;
import net.minecraft.util.Util;
import org.geysermc.rainbow.CodecUtil;
import org.geysermc.rainbow.RainbowIO;
import org.geysermc.rainbow.mapping.PackSerializer;

View File

@@ -113,7 +113,7 @@ Textures tried to export: FIXME
if (splash == null) {
return "Undefined Undefined :(";
}
return ((SplashRendererAccessor) splash).getSplash();
return ((SplashRendererAccessor) splash).getSplash().getString();
}
return randomBuiltinSummaryComment();
}

View File

@@ -22,7 +22,7 @@ public class RainbowClient implements ClientModInitializer {
ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> PackGeneratorCommand.register(dispatcher, packManager, packMapper));
ClientTickEvents.START_CLIENT_TICK.register(packMapper::tick);
ArgumentTypeRegistry.registerArgumentType(Rainbow.getModdedLocation("command_suggestions"),
ArgumentTypeRegistry.registerArgumentType(Rainbow.getModdedIdentifier("command_suggestions"),
CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new));
RainbowIO.registerExceptionListener(new RainbowClientIOHandler());

View File

@@ -2,7 +2,7 @@ package org.geysermc.rainbow.client.accessor;
import net.minecraft.client.renderer.item.ClientItem;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import java.util.Optional;
@@ -10,7 +10,7 @@ import java.util.Optional;
// This comes with some extra memory usage, but Rainbow should only be used to convert packs, so it should be fine
public interface ResolvedModelAccessor {
Optional<ResolvedModel> rainbow$getResolvedModel(ResourceLocation location);
Optional<ResolvedModel> rainbow$getResolvedModel(Identifier identifier);
Optional<ClientItem> rainbow$getClientItem(ResourceLocation location);
Optional<ClientItem> rainbow$getClientItem(Identifier identifier);
}

View File

@@ -7,7 +7,7 @@ import net.minecraft.client.renderer.item.ClientItem;
import net.minecraft.client.resources.model.ClientItemInfoLoader;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import org.geysermc.rainbow.client.accessor.ResolvedModelAccessor;
import org.spongepowered.asm.mixin.Mixin;
@@ -22,17 +22,17 @@ import java.util.concurrent.CompletableFuture;
@Mixin(ModelManager.class)
public abstract class ModelManagerMixin implements PreparableReloadListener, AutoCloseable, ResolvedModelAccessor {
@Unique
private Map<ResourceLocation, ResolvedModel> unbakedResolvedModels;
private Map<Identifier, ResolvedModel> unbakedResolvedModels;
@Unique
private Map<ResourceLocation, ClientItem> clientItems;
private Map<Identifier, ClientItem> clientItems;
@WrapOperation(method = "method_65753", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;join()Ljava/lang/Object;", ordinal = 1))
@WrapOperation(method = "method_65753", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;join()Ljava/lang/Object;", ordinal = 2))
private static Object setResolvedModels(CompletableFuture<?> instance, Operation<Object> original) {
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<ResourceLocation, ResolvedModel>) resolved.getClass().getRecordComponents()[1].getAccessor().invoke(resolved);
((ModelManagerMixin) (Object) Minecraft.getInstance().getModelManager()).unbakedResolvedModels = (Map<Identifier, ResolvedModel>) resolved.getClass().getRecordComponents()[1].getAccessor().invoke(resolved);
} catch (IllegalAccessException | InvocationTargetException | ClassCastException exception) {
throw new RuntimeException(exception);
}
@@ -40,7 +40,7 @@ public abstract class ModelManagerMixin implements PreparableReloadListener, Aut
}
@WrapOperation(method = "method_65753", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ClientItemInfoLoader$LoadedClientInfos;contents()Ljava/util/Map;"))
private static Map<ResourceLocation, ClientItem> setClientItems(ClientItemInfoLoader.LoadedClientInfos instance, Operation<Map<ResourceLocation, ClientItem>> original) {
private static Map<Identifier, ClientItem> setClientItems(ClientItemInfoLoader.LoadedClientInfos instance, Operation<Map<Identifier, ClientItem>> original) {
// Same note as above for not using "this"
ModelManagerMixin thiz = ((ModelManagerMixin) (Object) Minecraft.getInstance().getModelManager());
thiz.clientItems = original.call(instance);
@@ -48,12 +48,12 @@ public abstract class ModelManagerMixin implements PreparableReloadListener, Aut
}
@Override
public Optional<ResolvedModel> rainbow$getResolvedModel(ResourceLocation location) {
return unbakedResolvedModels == null ? Optional.empty() : Optional.ofNullable(unbakedResolvedModels.get(location));
public Optional<ResolvedModel> rainbow$getResolvedModel(Identifier identifier) {
return unbakedResolvedModels == null ? Optional.empty() : Optional.ofNullable(unbakedResolvedModels.get(identifier));
}
@Override
public Optional<ClientItem> rainbow$getClientItem(ResourceLocation location) {
return clientItems == null ? Optional.empty() : Optional.ofNullable(clientItems.get(location));
public Optional<ClientItem> rainbow$getClientItem(Identifier identifier) {
return clientItems == null ? Optional.empty() : Optional.ofNullable(clientItems.get(identifier));
}
}

View File

@@ -1,6 +1,7 @@
package org.geysermc.rainbow.client.mixin;
import net.minecraft.client.gui.components.SplashRenderer;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@@ -8,5 +9,5 @@ import org.spongepowered.asm.mixin.gen.Accessor;
public interface SplashRendererAccessor {
@Accessor
String getSplash();
Component getSplash();
}

View File

@@ -1,6 +1,6 @@
package org.geysermc.rainbow.client.render;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemStack;
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
import org.geysermc.rainbow.mapping.texture.TextureHolder;
@@ -11,7 +11,7 @@ public class MinecraftGeometryRenderer implements GeometryRenderer {
public static final MinecraftGeometryRenderer INSTANCE = new MinecraftGeometryRenderer();
@Override
public TextureHolder render(ResourceLocation location, ItemStack stack) {
return new RenderedTextureHolder(location, stack);
public TextureHolder render(Identifier identifier, ItemStack stack) {
return new RenderedTextureHolder(identifier, stack);
}
}

View File

@@ -12,7 +12,7 @@ import net.minecraft.client.gui.render.state.GuiItemRenderState;
import net.minecraft.client.gui.render.state.GuiRenderState;
import net.minecraft.client.gui.render.state.pip.OversizedItemRenderState;
import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
@@ -35,8 +35,8 @@ import java.util.concurrent.locks.ReentrantLock;
public class RenderedTextureHolder extends TextureHolder {
private final ItemStack stackToRender;
public RenderedTextureHolder(ResourceLocation location, ItemStack stackToRender) {
super(location);
public RenderedTextureHolder(Identifier identifier, ItemStack stackToRender) {
super(identifier);
this.stackToRender = stackToRender;
}

View File

@@ -5,7 +5,6 @@ import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.serialization.Codec;
import net.fabricmc.fabric.api.client.datagen.v1.provider.FabricModelProvider;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.minecraft.Util;
import net.minecraft.client.data.models.model.ModelInstance;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
@@ -19,10 +18,11 @@ import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataProvider;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.ProblemReporter;
import net.minecraft.util.Util;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.equipment.EquipmentAsset;
import org.geysermc.rainbow.Rainbow;
@@ -60,11 +60,11 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
private final Path packPath;
private Map<Item, ClientItem> itemInfos;
private Map<ResourceLocation, ModelInstance> models;
private Map<Identifier, ModelInstance> models;
protected RainbowModelProvider(FabricDataOutput output, CompletableFuture<HolderLookup.Provider> registries,
Map<ResourceKey<EquipmentAsset>, EquipmentClientInfo> equipmentInfos, String packName,
ResourceLocation outputRoot, Path geyserMappingsPath, Path packPath) {
Identifier outputRoot, Path geyserMappingsPath, Path packPath) {
super(output);
this.registries = registries;
this.equipmentInfos = equipmentInfos;
@@ -78,13 +78,13 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
protected RainbowModelProvider(FabricDataOutput output, CompletableFuture<HolderLookup.Provider> registries,
Map<ResourceKey<EquipmentAsset>, EquipmentClientInfo> equipmentInfos, String packName,
ResourceLocation outputRoot) {
Identifier outputRoot) {
this(output, registries, equipmentInfos, packName, outputRoot, Path.of("geyser_mappings.json"), Path.of("pack"));
}
protected RainbowModelProvider(FabricDataOutput output, CompletableFuture<HolderLookup.Provider> registries,
Map<ResourceKey<EquipmentAsset>, EquipmentClientInfo> equipmentInfos, String packName) {
this(output, registries, equipmentInfos, packName, ResourceLocation.withDefaultNamespace("bedrock"));
this(output, registries, equipmentInfos, packName, Identifier.withDefaultNamespace("bedrock"));
}
protected RainbowModelProvider(FabricDataOutput output, CompletableFuture<HolderLookup.Provider> registries, String packName) {
@@ -105,7 +105,7 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
BedrockPack pack = createBedrockPack(new Serializer(output, registries),
new DatagenResolver(resourceManager, equipmentInfos, itemInfos, models)).build();
Set<Item> sortedItemInfos = new TreeSet<>(Comparator.comparing(item -> item.builtInRegistryHolder().key().location()));
Set<Item> sortedItemInfos = new TreeSet<>(Comparator.comparing(item -> item.builtInRegistryHolder().key().identifier()));
sortedItemInfos.addAll(itemInfos.keySet());
for (Item item : sortedItemInfos) {
pack.map(getVanillaItem(item).builtInRegistryHolder(), getVanillaDataComponentPatch(item));
@@ -136,7 +136,7 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
}
@ApiStatus.Internal
public void setModels(Map<ResourceLocation, ModelInstance> models) {
public void setModels(Map<Identifier, ModelInstance> models) {
this.models = models;
}
@@ -162,33 +162,33 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
private static class DatagenResolver implements AssetResolver {
private final ResourceManager resourceManager;
private final Map<ResourceKey<EquipmentAsset>, EquipmentClientInfo> equipmentInfos;
private final Map<ResourceLocation, ClientItem> itemInfos;
private final Map<ResourceLocation, ModelInstance> models;
private final Map<ResourceLocation, Optional<ResolvedModel>> resolvedModelCache = new HashMap<>();
private final Map<Identifier, ClientItem> itemInfos;
private final Map<Identifier, ModelInstance> models;
private final Map<Identifier, Optional<ResolvedModel>> resolvedModelCache = new HashMap<>();
private DatagenResolver(ResourceManager resourceManager, Map<ResourceKey<EquipmentAsset>, EquipmentClientInfo> equipmentInfos,
Map<Item, ClientItem> itemInfos, Map<ResourceLocation, ModelInstance> models) {
Map<Item, ClientItem> itemInfos, Map<Identifier, ModelInstance> models) {
this.resourceManager = resourceManager;
this.equipmentInfos = equipmentInfos;
this.itemInfos = new HashMap<>();
for (Map.Entry<Item, ClientItem> entry : itemInfos.entrySet()) {
this.itemInfos.put(entry.getKey().builtInRegistryHolder().key().location(), entry.getValue());
this.itemInfos.put(entry.getKey().builtInRegistryHolder().key().identifier(), entry.getValue());
}
this.models = models;
}
@Override
public Optional<ResolvedModel> getResolvedModel(ResourceLocation location) {
return resolvedModelCache.computeIfAbsent(location, key -> Optional.ofNullable(models.get(location))
public Optional<ResolvedModel> getResolvedModel(Identifier identifier) {
return resolvedModelCache.computeIfAbsent(identifier, key -> Optional.ofNullable(models.get(identifier))
.<UnbakedModel>map(instance -> BlockModel.fromStream(new StringReader(instance.get().toString())))
.or(() -> {
if (location.equals(ItemModelGenerator.GENERATED_ITEM_MODEL_ID)) {
if (identifier.equals(ItemModelGenerator.GENERATED_ITEM_MODEL_ID)) {
return Optional.of(new ItemModelGenerator());
}
return Optional.empty();
})
.or(() -> RainbowIO.safeIO(() -> {
try (BufferedReader reader = resourceManager.openAsReader(location.withPrefix("models/").withSuffix(".json"))) {
try (BufferedReader reader = resourceManager.openAsReader(identifier.withPrefix("models/").withSuffix(".json"))) {
return BlockModel.fromStream(reader);
}
}))
@@ -205,14 +205,14 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
@Override
public @NotNull String debugName() {
return location.toString();
return identifier.toString();
}
}));
}
@Override
public Optional<ClientItem> getClientItem(ResourceLocation location) {
return Optional.ofNullable(itemInfos.get(location));
public Optional<ClientItem> getClientItem(Identifier identifier) {
return Optional.ofNullable(itemInfos.get(identifier));
}
@Override
@@ -221,9 +221,9 @@ public abstract class RainbowModelProvider extends FabricModelProvider {
}
@Override
public Optional<TextureResource> getTexture(ResourceLocation atlas, ResourceLocation location) {
public Optional<TextureResource> getTexture(Identifier atlas, Identifier identifier) {
// We don't care about atlas since there are none loaded at datagen
return resourceManager.getResource(Rainbow.decorateTextureLocation(location))
return resourceManager.getResource(Rainbow.decorateTextureIdentifier(identifier))
.flatMap(resource -> RainbowIO.safeIO(() -> {
Optional<AnimationMetadataSection> animationMetadata = resource.metadata().getSection(AnimationMetadataSection.TYPE);
try (InputStream textureStream = resource.open()) {

View File

@@ -2,7 +2,7 @@ package org.geysermc.rainbow.datagen.mixin;
import net.minecraft.client.data.models.ModelProvider;
import net.minecraft.client.data.models.model.ModelInstance;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@@ -12,5 +12,5 @@ import java.util.Map;
public interface SimpleModelCollectorAccessor {
@Accessor
Map<ResourceLocation, ModelInstance> getModels();
Map<Identifier, ModelInstance> getModels();
}

View File

@@ -1,5 +1,5 @@
org.gradle.jvmargs=-Xmx1G
# Mod Properties
mod_version=0.2.0-1.21.10-SNAPSHOT
mod_version=0.2.0-1.21.11-SNAPSHOT
maven_group=org.geysermc.rainbow

View File

@@ -1,11 +1,11 @@
[versions]
minecraft = "1.21.10"
minecraft-supported = ">=1.21.9 <=1.21.10"
minecraft = "1.21.11"
minecraft-supported = "1.21.11"
parchment = "2025.10.12"
fabric-loom = "1.11-SNAPSHOT"
fabric-loader = "0.17.3"
fabric-api = "0.135.0+1.21.10"
fabric-loom = "1.14-SNAPSHOT"
fabric-loader = "0.18.2"
fabric-api = "0.140.0+1.21.11"
creative = "817fa982c4"
packconverter = "3.4.1-20251013.173215-13"
@@ -23,4 +23,3 @@ creative-serializer-minecraft = {group = "com.github.GeyserMC.unnamed-creative",
packconverter = {group = "org.geysermc.pack", name = "converter", version.ref = "packconverter"}
[plugins]
fabric-loom = {id = "fabric-loom", version.ref = "fabric-loom"}

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,7 +1,7 @@
package org.geysermc.rainbow;
import com.mojang.logging.LogUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.slf4j.Logger;
public class Rainbow {
@@ -10,19 +10,19 @@ public class Rainbow {
public static final String MOD_NAME = "Rainbow";
public static final Logger LOGGER = LogUtils.getLogger();
public static ResourceLocation getModdedLocation(String path) {
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
public static Identifier getModdedIdentifier(String path) {
return Identifier.fromNamespaceAndPath(MOD_ID, path);
}
public static String safeResourceLocation(ResourceLocation location) {
return location.toString().replace(':', '.').replace('/', '_');
public static String bedrockSafeIdentifier(Identifier identifier) {
return identifier.toString().replace(':', '.').replace('/', '_');
}
public static ResourceLocation decorateResourceLocation(ResourceLocation location, String type, String extension) {
return location.withPath(path -> type + "/" + path + "." + extension);
public static Identifier decorateIdentifier(Identifier identifier, String type, String extension) {
return identifier.withPath(path -> type + "/" + path + "." + extension);
}
public static ResourceLocation decorateTextureLocation(ResourceLocation location) {
return decorateResourceLocation(location, "textures", "png");
public static Identifier decorateTextureIdentifier(Identifier identifier) {
return decorateIdentifier(identifier, "textures", "png");
}
}

View File

@@ -6,7 +6,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.definition.predicate.GeyserPredicate;
@@ -14,11 +14,12 @@ import java.util.List;
import java.util.Optional;
// TODO other keys, etc.
// TODO display name can be a component
public record GeyserBaseDefinition(ResourceLocation bedrockIdentifier, Optional<String> displayName,
// TODO display name can be a literal text component
public record GeyserBaseDefinition(Identifier bedrockIdentifier, Optional<String> displayName,
List<GeyserPredicate> predicates, BedrockOptions bedrockOptions, DataComponentPatch components) {
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,
DataComponents.ATTACK_RANGE, DataComponents.KINETIC_WEAPON, DataComponents.PIERCING_WEAPON, DataComponents.SWING_ANIMATION, DataComponents.USE_EFFECTS);
private static final MapCodec<DataComponentPatch> FILTERED_COMPONENT_MAP_CODEC = DataComponentPatch.CODEC.optionalFieldOf("components")
.xmap(optional -> optional.orElse(DataComponentPatch.EMPTY), patch -> {
@@ -38,7 +39,7 @@ public record GeyserBaseDefinition(ResourceLocation bedrockIdentifier, Optional<
public static final MapCodec<GeyserBaseDefinition> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserBaseDefinition::bedrockIdentifier),
Identifier.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserBaseDefinition::bedrockIdentifier),
Codec.STRING.optionalFieldOf("display_name").forGetter(GeyserBaseDefinition::displayName),
GeyserPredicate.LIST_CODEC.optionalFieldOf("predicate", List.of()).forGetter(GeyserBaseDefinition::predicates),
BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserBaseDefinition::bedrockOptions),
@@ -61,17 +62,17 @@ public record GeyserBaseDefinition(ResourceLocation bedrockIdentifier, Optional<
}
public String textureName() {
return bedrockOptions.icon.orElse(Rainbow.safeResourceLocation(bedrockIdentifier));
return bedrockOptions.icon.orElse(Rainbow.bedrockSafeIdentifier(bedrockIdentifier));
}
public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue, List<ResourceLocation> tags) {
public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue, List<Identifier> tags) {
public static final Codec<BedrockOptions> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
Codec.STRING.optionalFieldOf("icon").forGetter(BedrockOptions::icon),
Codec.BOOL.optionalFieldOf("allow_offhand", true).forGetter(BedrockOptions::allowOffhand),
Codec.BOOL.optionalFieldOf("display_handheld", false).forGetter(BedrockOptions::displayHandheld),
Codec.INT.optionalFieldOf("protection_value", 0).forGetter(BedrockOptions::protectionValue),
ResourceLocation.CODEC.listOf().optionalFieldOf("tags", List.of()).forGetter(BedrockOptions::tags)
Identifier.CODEC.listOf().optionalFieldOf("tags", List.of()).forGetter(BedrockOptions::tags)
).apply(instance, BedrockOptions::new)
);
public static final BedrockOptions DEFAULT = new BedrockOptions(Optional.empty(), true, false, 0, List.of());

View File

@@ -2,7 +2,7 @@ package org.geysermc.rainbow.definition;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
@@ -11,11 +11,11 @@ import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
public record GeyserGroupDefinition(Optional<ResourceLocation> model, List<GeyserMapping> definitions) implements GeyserMapping {
public record GeyserGroupDefinition(Optional<Identifier> model, List<GeyserMapping> definitions) implements GeyserMapping {
public static final MapCodec<GeyserGroupDefinition> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
ResourceLocation.CODEC.optionalFieldOf("model").forGetter(GeyserGroupDefinition::model),
Identifier.CODEC.optionalFieldOf("model").forGetter(GeyserGroupDefinition::model),
GeyserMapping.CODEC.listOf().fieldOf("definitions").forGetter(GeyserGroupDefinition::definitions)
).apply(instance, GeyserGroupDefinition::new)
);
@@ -26,12 +26,12 @@ public record GeyserGroupDefinition(Optional<ResourceLocation> model, List<Geyse
.toList());
}
public boolean isFor(Optional<ResourceLocation> model) {
public boolean isFor(Optional<Identifier> model) {
return this.model.isPresent() && model.isPresent() && this.model.get().equals(model.get());
}
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other) {
Optional<ResourceLocation> thisModel = model.or(() -> parentModel);
public boolean conflictsWith(Optional<Identifier> parentModel, GeyserItemDefinition other) {
Optional<Identifier> thisModel = model.or(() -> parentModel);
for (GeyserMapping definition : definitions) {
if (definition instanceof GeyserGroupDefinition group && group.conflictsWith(thisModel, other)) {
return true;
@@ -61,7 +61,7 @@ public record GeyserGroupDefinition(Optional<ResourceLocation> model, List<Geyse
@Override
public int compareTo(@NotNull GeyserMapping other) {
if (other instanceof GeyserGroupDefinition(Optional<ResourceLocation> otherModel, List<GeyserMapping> otherDefinitions)) {
if (other instanceof GeyserGroupDefinition(Optional<Identifier> otherModel, List<GeyserMapping> otherDefinitions)) {
if (model.isPresent() && otherModel.isPresent()) {
return model.get().compareTo(otherModel.get());
} else if (model.isPresent()) {

View File

@@ -1,6 +1,6 @@
package org.geysermc.rainbow.definition;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
@@ -9,7 +9,7 @@ public interface GeyserItemDefinition extends GeyserMapping {
GeyserBaseDefinition base();
boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other);
boolean conflictsWith(Optional<Identifier> parentModel, GeyserItemDefinition other);
@Override
default int compareTo(@NotNull GeyserMapping other) {

View File

@@ -3,7 +3,7 @@ package org.geysermc.rainbow.definition;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import java.util.Optional;
@@ -17,7 +17,7 @@ public record GeyserLegacyDefinition(GeyserBaseDefinition base, int customModelD
);
@Override
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other) {
public boolean conflictsWith(Optional<Identifier> parentModel, GeyserItemDefinition other) {
if (other instanceof GeyserLegacyDefinition otherLegacy) {
return customModelData == otherLegacy.customModelData && base.conflictsWith(otherLegacy.base);
}

View File

@@ -5,7 +5,7 @@ import com.google.common.collect.MultimapBuilder;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.Item;
import org.geysermc.rainbow.CodecUtil;
@@ -41,7 +41,7 @@ public class GeyserMappings {
}
public void map(Holder<Item> item, GeyserItemDefinition mapping) {
Optional<ResourceLocation> model = mapping instanceof GeyserSingleDefinition single ? Optional.of(single.model().orElseThrow()) : Optional.empty();
Optional<Identifier> model = mapping instanceof GeyserSingleDefinition single ? Optional.of(single.model().orElseThrow()) : Optional.empty();
Optional<GeyserGroupDefinition> modelGroup = Optional.empty();
Collection<GeyserMapping> existingMappings = new ArrayList<>(mappings.get(item));

View File

@@ -2,23 +2,23 @@ package org.geysermc.rainbow.definition;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import java.util.Optional;
public record GeyserSingleDefinition(GeyserBaseDefinition base, Optional<ResourceLocation> model) implements GeyserItemDefinition {
public record GeyserSingleDefinition(GeyserBaseDefinition base, Optional<Identifier> model) implements GeyserItemDefinition {
public static final MapCodec<GeyserSingleDefinition> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
GeyserBaseDefinition.MAP_CODEC.forGetter(GeyserSingleDefinition::base),
ResourceLocation.CODEC.optionalFieldOf("model").forGetter(GeyserSingleDefinition::model)
Identifier.CODEC.optionalFieldOf("model").forGetter(GeyserSingleDefinition::model)
).apply(instance, GeyserSingleDefinition::new)
);
@Override
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other) {
public boolean conflictsWith(Optional<Identifier> parentModel, GeyserItemDefinition other) {
if (other instanceof GeyserSingleDefinition otherSingle) {
ResourceLocation thisModel = model.or(() -> parentModel).orElseThrow();
ResourceLocation otherModel = otherSingle.model.or(() -> parentModel).orElseThrow();
Identifier thisModel = model.or(() -> parentModel).orElseThrow();
Identifier otherModel = otherSingle.model.or(() -> parentModel).orElseThrow();
return thisModel.equals(otherModel) && base.conflictsWith(other.base());
}
return false;

View File

@@ -3,8 +3,8 @@ package org.geysermc.rainbow.mapping;
import net.minecraft.client.renderer.item.ClientItem;
import net.minecraft.client.resources.model.EquipmentClientInfo;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.equipment.EquipmentAsset;
import org.geysermc.rainbow.mapping.texture.TextureResource;
@@ -12,11 +12,11 @@ import java.util.Optional;
public interface AssetResolver {
Optional<ResolvedModel> getResolvedModel(ResourceLocation location);
Optional<ResolvedModel> getResolvedModel(Identifier identifier);
Optional<ClientItem> getClientItem(ResourceLocation location);
Optional<ClientItem> getClientItem(Identifier identifier);
Optional<EquipmentClientInfo> getEquipmentInfo(ResourceKey<EquipmentAsset> key);
Optional<TextureResource> getTexture(ResourceLocation atlas, ResourceLocation location);
Optional<TextureResource> getTexture(Identifier atlas, Identifier identifier);
}

View File

@@ -25,8 +25,8 @@ import net.minecraft.client.renderer.item.properties.select.DisplayContext;
import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperties;
import net.minecraft.client.renderer.item.properties.select.TrimMaterialProperty;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.ProblemReporter;
@@ -52,6 +52,7 @@ import org.geysermc.rainbow.definition.predicate.GeyserRangeDispatchPredicate;
import org.geysermc.rainbow.mixin.LateBoundIdMapperAccessor;
import org.geysermc.rainbow.mixin.RangeSelectItemModelAccessor;
import org.geysermc.rainbow.pack.BedrockItem;
import org.jspecify.annotations.NonNull;
import java.util.List;
import java.util.Optional;
@@ -59,24 +60,24 @@ import java.util.function.Function;
import java.util.stream.Stream;
public class BedrockItemMapper {
private static final List<ResourceLocation> TRIMMABLE_ARMOR_TAGS = Stream.of("is_armor", "trimmable_armors")
.map(ResourceLocation::withDefaultNamespace)
private static final List<Identifier> TRIMMABLE_ARMOR_TAGS = Stream.of("is_armor", "trimmable_armors")
.map(Identifier::withDefaultNamespace)
.toList();
private static <T> ResourceLocation getId(ExtraCodecs.LateBoundIdMapper<ResourceLocation, T> mapper,
private static <T> Identifier getId(ExtraCodecs.LateBoundIdMapper<@NonNull Identifier, @NonNull T> mapper,
T type) {
//noinspection unchecked
return ((LateBoundIdMapperAccessor<ResourceLocation, ?>) mapper).getIdToValue().inverse().get(type);
return ((LateBoundIdMapperAccessor<Identifier, ?>) mapper).getIdToValue().inverse().get(type);
}
public static void tryMapStack(ItemStack stack, ResourceLocation modelLocation, ProblemReporter reporter, PackContext context) {
context.assetResolver().getClientItem(modelLocation).map(ClientItem::model)
.ifPresentOrElse(model -> mapItem(model, stack, reporter.forChild(() -> "client item definition " + modelLocation + " "), base -> new GeyserSingleDefinition(base, Optional.of(modelLocation)), context),
() -> reporter.report(() -> "missing client item definition " + modelLocation));
public static void tryMapStack(ItemStack stack, Identifier modelIdentifier, ProblemReporter reporter, PackContext context) {
context.assetResolver().getClientItem(modelIdentifier).map(ClientItem::model)
.ifPresentOrElse(model -> mapItem(model, stack, reporter.forChild(() -> "client item definition " + modelIdentifier + " "), base -> new GeyserSingleDefinition(base, Optional.of(modelIdentifier)), context),
() -> reporter.report(() -> "missing client item definition " + modelIdentifier));
}
public static void tryMapStack(ItemStack stack, int customModelData, ProblemReporter reporter, PackContext context) {
ResourceLocation itemModel = stack.get(DataComponents.ITEM_MODEL);
Identifier itemModel = stack.get(DataComponents.ITEM_MODEL);
ItemModel.Unbaked vanillaModel = context.assetResolver().getClientItem(itemModel).map(ClientItem::model).orElseThrow();
ProblemReporter childReporter = reporter.forChild(() -> "item model " + itemModel + " with custom model data " + customModelData + " ");
if (vanillaModel instanceof RangeSelectItemModel.Unbaked(RangeSelectItemModelProperty property, float scale, List<RangeSelectItemModel.Entry> entries, Optional<ItemModel.Unbaked> fallback)) {
@@ -117,24 +118,24 @@ public class BedrockItemMapper {
}
private static void mapBlockModelWrapper(BlockModelWrapper.Unbaked model, MappingContext context) {
ResourceLocation itemModelLocation = model.model();
Identifier itemModelIdentifier = model.model();
context.packContext().assetResolver().getResolvedModel(itemModelLocation)
context.packContext().assetResolver().getResolvedModel(itemModelIdentifier)
.ifPresentOrElse(itemModel -> {
ResourceLocation bedrockIdentifier;
if (itemModelLocation.getNamespace().equals(ResourceLocation.DEFAULT_NAMESPACE)) {
bedrockIdentifier = ResourceLocation.fromNamespaceAndPath("geyser_mc", itemModelLocation.getPath());
Identifier bedrockIdentifier;
if (itemModelIdentifier.getNamespace().equals(Identifier.DEFAULT_NAMESPACE)) {
bedrockIdentifier = Identifier.fromNamespaceAndPath("geyser_mc", itemModelIdentifier.getPath());
} else {
bedrockIdentifier = itemModelLocation;
bedrockIdentifier = itemModelIdentifier;
}
BedrockGeometryContext geometry = BedrockGeometryContext.create(bedrockIdentifier, itemModel, context.stack, context.packContext);
if (context.packContext.reportSuccesses()) {
// Not a problem, but just report to get the model printed in the report file
context.report("creating mapping for block model " + itemModelLocation);
context.report("creating mapping for block model " + itemModelIdentifier);
}
context.create(bedrockIdentifier, geometry);
}, () -> context.report("missing block model " + itemModelLocation));
}, () -> context.report("missing block model " + itemModelIdentifier));
}
private static void mapConditionalModel(ConditionalItemModel.Unbaked model, MappingContext context) {
@@ -230,8 +231,8 @@ public class BedrockItemMapper {
return new MappingContext(predicateStack, stack, reporter.forChild(() -> childName), definitionCreator, packContext);
}
public void create(ResourceLocation bedrockIdentifier, BedrockGeometryContext geometry) {
List<ResourceLocation> tags = stack.is(ItemTags.TRIMMABLE_ARMOR) ? TRIMMABLE_ARMOR_TAGS : List.of();
public void create(Identifier bedrockIdentifier, BedrockGeometryContext geometry) {
List<Identifier> tags = stack.is(ItemTags.TRIMMABLE_ARMOR) ? TRIMMABLE_ARMOR_TAGS : List.of();
GeyserBaseDefinition base = new GeyserBaseDefinition(bedrockIdentifier, Optional.ofNullable(stack.getHoverName().tryCollapseToString()), predicateStack,
new GeyserBaseDefinition.BedrockOptions(Optional.empty(), true, geometry.handheld(), calculateProtectionValue(stack), tags),

View File

@@ -5,7 +5,7 @@ import net.minecraft.client.resources.model.EquipmentAssetManager;
import net.minecraft.client.resources.model.EquipmentClientInfo;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.equipment.Equippable;
import org.geysermc.rainbow.mapping.AssetResolver;
@@ -32,7 +32,7 @@ public class AttachableMapper {
.mapSecond(info -> info.getLayers(getLayer(assetInfo.getFirst()))))
.filter(assetInfo -> !assetInfo.getSecond().isEmpty())
.map(assetInfo -> {
ResourceLocation equipmentTexture = getTexture(assetInfo.getSecond(), getLayer(assetInfo.getFirst()));
Identifier equipmentTexture = getTexture(assetInfo.getSecond(), getLayer(assetInfo.getFirst()));
textureConsumer.accept(TextureHolder.createBuiltIn(null, equipmentTexture));
return BedrockAttachable.equipment(bedrockIdentifier, assetInfo.getFirst(), equipmentTexture.getPath());
}))
@@ -53,13 +53,13 @@ public class AttachableMapper {
return slot == EquipmentSlot.LEGS ? EquipmentClientInfo.LayerType.HUMANOID_LEGGINGS : EquipmentClientInfo.LayerType.HUMANOID;
}
private static ResourceLocation getTexture(List<EquipmentClientInfo.Layer> info, EquipmentClientInfo.LayerType layer) {
private static Identifier getTexture(List<EquipmentClientInfo.Layer> info, EquipmentClientInfo.LayerType layer) {
return info.getFirst().textureId().withPath(path -> "entity/equipment/" + layer.getSerializedName() + "/" + path);
}
@FunctionalInterface
public interface AttachableCreator {
Optional<BedrockAttachable> create(ResourceLocation bedrockIdentifier, Consumer<TextureHolder> textureConsumer);
Optional<BedrockAttachable> create(Identifier bedrockIdentifier, Consumer<TextureHolder> textureConsumer);
}
}

View File

@@ -4,7 +4,7 @@ import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.data.AtlasIds;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemStack;
import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.mapping.PackContext;
@@ -19,14 +19,14 @@ import java.util.stream.Stream;
public record BedrockGeometryContext(Optional<MappedGeometry> geometry,
Optional<BedrockAnimationContext> animation, TextureHolder icon,
boolean handheld) {
private static final List<ResourceLocation> HANDHELD_MODELS = Stream.of("item/handheld", "item/handheld_rod", "item/handheld_mace")
.map(ResourceLocation::withDefaultNamespace)
private static final List<Identifier> HANDHELD_MODELS = Stream.of("item/handheld", "item/handheld_rod", "item/handheld_mace")
.map(Identifier::withDefaultNamespace)
.toList();
public static BedrockGeometryContext create(ResourceLocation bedrockIdentifier, ResolvedModel model, ItemStack stackToRender, PackContext context) {
public static BedrockGeometryContext create(Identifier bedrockIdentifier, ResolvedModel model, ItemStack stackToRender, PackContext context) {
ResolvedModel parentModel = model.parent();
// debugName() returns the resource location of the model as a string
boolean handheld = parentModel != null && HANDHELD_MODELS.contains(ResourceLocation.parse(parentModel.debugName()));
boolean handheld = parentModel != null && HANDHELD_MODELS.contains(Identifier.parse(parentModel.debugName()));
TextureSlots textures = model.getTopTextureSlots();
Material layer0Texture = textures.getMaterial("layer0");
@@ -43,7 +43,7 @@ public record BedrockGeometryContext(Optional<MappedGeometry> geometry,
// This check should probably be done differently (actually check if the model is 2D or 3D)
geometry = Optional.of(context.geometryCache().mapGeometry(bedrockIdentifier, model, stackToRender, context));
animation = Optional.of(AnimationMapper.mapAnimation(Rainbow.safeResourceLocation(bedrockIdentifier), "bone", model.getTopTransforms()));
animation = Optional.of(AnimationMapper.mapAnimation(Rainbow.bedrockSafeIdentifier(bedrockIdentifier), "bone", model.getTopTransforms()));
icon = geometry.get().icon();
}

View File

@@ -115,16 +115,23 @@ public class GeometryMapper {
// Same as above for inverting the X axis (thanks again Blockbench!!)
builder.withPivot(rotation.origin().div(0.0625F, new Vector3f()).sub(CENTRE_OFFSET).mul(-1.0F, 1.0F, 1.0F));
// Same as above but for some reason the Z axis too (thanks again, so much, Blockbench!!!)
Vector3f bedrockRotation = switch (rotation.axis()) {
case X -> new Vector3f(-rotation.angle(), 0.0F, 0.0F);
case Y -> new Vector3f(0.0F, rotation.angle(), 0.0F);
case Z -> new Vector3f(0.0F, 0.0F, -rotation.angle());
};
builder.withRotation(bedrockRotation);
builder.withRotation(getBedrockRotation(rotation.value()));
// TODO translate rescale property?
}
return builder;
}
private static Vector3fc getBedrockRotation(BlockElementRotation.RotationValue rotation) {
// Same as in the method above, but for some reason the Z axis too: X and Z axes have to be inverted (thanks again, so much, Blockbench!!!)
return switch (rotation) {
case BlockElementRotation.EulerXYZRotation(float x, float y, float z) -> new Vector3f(-x, y, -z); // TODO check if these angle transformations are right, they should be
case BlockElementRotation.SingleAxisRotation(Direction.Axis axis, float angle) -> switch (axis) {
case X -> new Vector3f(-angle, 0.0F, 0.0F);
case Y -> new Vector3f(0.0F, angle, 0.0F);
case Z -> new Vector3f(0.0F, 0.0F, -angle);
};
default -> throw new IllegalArgumentException("Don't know how to transform rotation of type " + rotation.getClass() + " to bedrock rotation");
};
}
}

View File

@@ -1,10 +1,10 @@
package org.geysermc.rainbow.mapping.geometry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemStack;
import org.geysermc.rainbow.mapping.texture.TextureHolder;
public interface GeometryRenderer {
TextureHolder render(ResourceLocation location, ItemStack stack);
TextureHolder render(Identifier identifier, ItemStack stack);
}

View File

@@ -1,11 +1,9 @@
package org.geysermc.rainbow.mapping.geometry;
import com.google.common.base.Suppliers;
import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ResolvedModel;
import net.minecraft.client.resources.model.UnbakedGeometry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemStack;
import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.mapping.PackContext;
@@ -20,22 +18,22 @@ import java.util.Map;
public class MappedGeometryCache {
private final Map<GeometryCacheKey, MappedGeometryInstance> cachedGeometry = new HashMap<>();
public MappedGeometry mapGeometry(ResourceLocation bedrockIdentifier, ResolvedModel model, ItemStack stackToRender, PackContext context) {
public MappedGeometry mapGeometry(Identifier bedrockIdentifier, ResolvedModel model, ItemStack stackToRender, PackContext context) {
GeometryCacheKey cacheKey = new GeometryCacheKey(model);
MappedGeometry cached = cachedGeometry.get(cacheKey);
if (cached != null) {
return cached.cachedCopy();
}
ResourceLocation modelLocation = ResourceLocation.parse(model.debugName());
ResourceLocation stitchedTexturesLocation = modelLocation.withSuffix("_stitched");
String safeIdentifier = Rainbow.safeResourceLocation(bedrockIdentifier);
Identifier modelIdentifier = Identifier.parse(model.debugName());
Identifier stitchedTexturesIdentifier = modelIdentifier.withSuffix("_stitched");
String safeIdentifier = Rainbow.bedrockSafeIdentifier(bedrockIdentifier);
StitchedTextures stitchedTextures = StitchedTextures.stitchModelTextures(model.getTopTextureSlots(), context);
BedrockGeometry geometry = GeometryMapper.mapGeometry(safeIdentifier, "bone", model, stitchedTextures);
TextureHolder icon = context.geometryRenderer().isPresent() ? context.geometryRenderer().orElseThrow().render(modelLocation, stackToRender)
: TextureHolder.createNonExistent(modelLocation);
MappedGeometryInstance instance = new MappedGeometryInstance(geometry, TextureHolder.createCustom(stitchedTexturesLocation, stitchedTextures.stitched()), icon);
TextureHolder icon = context.geometryRenderer().isPresent() ? context.geometryRenderer().orElseThrow().render(modelIdentifier, stackToRender)
: TextureHolder.createNonExistent(modelIdentifier);
MappedGeometryInstance instance = new MappedGeometryInstance(geometry, TextureHolder.createCustom(stitchedTexturesIdentifier, stitchedTextures.stitched()), icon);
cachedGeometry.put(cacheKey, instance);
return instance;
}

View File

@@ -1,7 +1,7 @@
package org.geysermc.rainbow.mapping.texture;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import org.geysermc.rainbow.RainbowIO;
import org.geysermc.rainbow.image.NativeImageUtil;
@@ -11,11 +11,11 @@ import java.util.Objects;
import java.util.Optional;
public class BuiltInTextureHolder extends TextureHolder {
private final ResourceLocation atlas;
private final ResourceLocation source;
private final Identifier atlas;
private final Identifier source;
public BuiltInTextureHolder(ResourceLocation location, ResourceLocation atlas, ResourceLocation source) {
super(location);
public BuiltInTextureHolder(Identifier identifier, Identifier atlas, Identifier source) {
super(identifier);
this.atlas = atlas;
this.source = source;
}

View File

@@ -1,6 +1,6 @@
package org.geysermc.rainbow.mapping.texture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import org.geysermc.rainbow.mapping.AssetResolver;
import org.geysermc.rainbow.mapping.PackSerializer;
@@ -11,8 +11,8 @@ import java.util.concurrent.CompletableFuture;
public class CopyTextureHolder extends TextureHolder {
public CopyTextureHolder(ResourceLocation location) {
super(location);
public CopyTextureHolder(Identifier identifier) {
super(identifier);
}
@Override

View File

@@ -1,7 +1,7 @@
package org.geysermc.rainbow.mapping.texture;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import org.geysermc.rainbow.RainbowIO;
import org.geysermc.rainbow.image.NativeImageUtil;
@@ -13,8 +13,8 @@ import java.util.function.Supplier;
public class CustomTextureHolder extends TextureHolder {
private final Supplier<NativeImage> supplier;
public CustomTextureHolder(ResourceLocation location, Supplier<NativeImage> supplier) {
super(location);
public CustomTextureHolder(Identifier identifier, Supplier<NativeImage> supplier) {
super(identifier);
this.supplier = supplier;
}

View File

@@ -1,6 +1,6 @@
package org.geysermc.rainbow.mapping.texture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import org.geysermc.rainbow.mapping.AssetResolver;
@@ -8,8 +8,8 @@ import java.util.Optional;
public class MissingTextureHolder extends TextureHolder {
public MissingTextureHolder(ResourceLocation location) {
super(location);
public MissingTextureHolder(Identifier identifier) {
super(identifier);
}
@Override

View File

@@ -1,14 +1,14 @@
package org.geysermc.rainbow.mapping.texture;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.Util;
import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.renderer.texture.SpriteContents;
import net.minecraft.client.renderer.texture.SpriteLoader;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.Material;
import net.minecraft.data.AtlasIds;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.Util;
import org.geysermc.rainbow.RainbowIO;
import org.geysermc.rainbow.mapping.PackContext;
import org.geysermc.rainbow.mixin.SpriteContentsAccessor;
@@ -50,9 +50,9 @@ public record StitchedTextures(Map<String, TextureAtlasSprite> sprites, Supplier
return new StitchedTextures(Map.copyOf(sprites), () -> stitchTextureAtlas(preparations), preparations.width(), preparations.height());
}
private static SpriteLoader.Preparations prepareStitching(Stream<ResourceLocation> textures, PackContext context) {
private static SpriteLoader.Preparations prepareStitching(Stream<Identifier> textures, PackContext context) {
// Atlas ID doesn't matter much here, but BLOCKS is the most appropriate
SpriteLoader spriteLoader = new SpriteLoader(AtlasIds.BLOCKS, MAX_TEXTURE_SIZE, 16, 16);
SpriteLoader spriteLoader = new SpriteLoader(AtlasIds.BLOCKS, MAX_TEXTURE_SIZE);
List<SpriteContents> sprites = textures.distinct()
.map(texture -> readSpriteContents(texture, context))
.<SpriteContents>mapMulti(Optional::ifPresent)
@@ -60,11 +60,11 @@ public record StitchedTextures(Map<String, TextureAtlasSprite> sprites, Supplier
return ((SpriteLoaderAccessor) spriteLoader).invokeStitch(sprites, 0, Util.backgroundExecutor());
}
private static Optional<SpriteContents> readSpriteContents(ResourceLocation location, PackContext context) {
private static Optional<SpriteContents> readSpriteContents(Identifier identifier, PackContext context) {
return RainbowIO.safeIO(() -> {
try (TextureResource texture = context.assetResolver().getTexture(AtlasIds.BLOCKS, location).orElse(null)) {
try (TextureResource texture = context.assetResolver().getTexture(AtlasIds.BLOCKS, identifier).orElse(null)) {
if (texture != null) {
return new SpriteContents(location, texture.sizeOfFrame(), texture.getFirstFrame(true));
return new SpriteContents(identifier, texture.sizeOfFrame(), texture.getFirstFrame(true));
}
}
return null;

View File

@@ -1,7 +1,7 @@
package org.geysermc.rainbow.mapping.texture;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import org.geysermc.rainbow.mapping.AssetResolver;
import org.geysermc.rainbow.mapping.PackSerializer;
@@ -12,10 +12,10 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
public abstract class TextureHolder {
protected final ResourceLocation location;
protected final Identifier identifier;
public TextureHolder(ResourceLocation location) {
this.location = location;
public TextureHolder(Identifier identifier) {
this.identifier = identifier;
}
public abstract Optional<byte[]> load(AssetResolver assetResolver, ProblemReporter reporter);
@@ -26,31 +26,31 @@ public abstract class TextureHolder {
.orElse(CompletableFuture.completedFuture(null));
}
public static TextureHolder createCustom(ResourceLocation location, Supplier<NativeImage> supplier) {
return new CustomTextureHolder(location, supplier);
public static TextureHolder createCustom(Identifier identifier, Supplier<NativeImage> supplier) {
return new CustomTextureHolder(identifier, supplier);
}
public static TextureHolder createBuiltIn(ResourceLocation location, ResourceLocation atlas, ResourceLocation source) {
return new BuiltInTextureHolder(location, atlas, source);
public static TextureHolder createBuiltIn(Identifier identifier, Identifier atlas, Identifier source) {
return new BuiltInTextureHolder(identifier, atlas, source);
}
public static TextureHolder createBuiltIn(ResourceLocation atlas, ResourceLocation location) {
return createBuiltIn(location, atlas, location);
public static TextureHolder createBuiltIn(Identifier atlas, Identifier identifier) {
return createBuiltIn(identifier, atlas, identifier);
}
public static TextureHolder createNonExistent(ResourceLocation location) {
return new MissingTextureHolder(location);
public static TextureHolder createNonExistent(Identifier identifier) {
return new MissingTextureHolder(identifier);
}
public static TextureHolder createCopy(TextureHolder original) {
return new CopyTextureHolder(original.location);
return new CopyTextureHolder(original.identifier);
}
public ResourceLocation location() {
return location;
public Identifier location() {
return identifier;
}
protected void reportMissing(ProblemReporter reporter) {
reporter.report(() -> "missing texture for " + location + "; please provide it manually");
reporter.report(() -> "missing texture for " + identifier + "; please provide it manually");
}
}

View File

@@ -1,6 +1,6 @@
package org.geysermc.rainbow.pack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.mapping.PackSerializer;
import org.geysermc.rainbow.mapping.attachable.AttachableMapper;
@@ -15,7 +15,7 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public record BedrockItem(ResourceLocation identifier, String textureName, BedrockGeometryContext geometryContext, AttachableMapper.AttachableCreator attachableCreator) {
public record BedrockItem(Identifier identifier, String textureName, BedrockGeometryContext geometryContext, AttachableMapper.AttachableCreator attachableCreator) {
public CompletableFuture<?> save(PackSerializer serializer, Path attachableDirectory, Path geometryDirectory, Path animationDirectory,
Function<TextureHolder, CompletableFuture<?>> textureSaver) {
@@ -26,7 +26,7 @@ public record BedrockItem(ResourceLocation identifier, String textureName, Bedro
createdAttachable.map(attachable -> attachable.save(serializer, attachableDirectory)).orElse(noop()),
CompletableFuture.allOf(attachableTextures.stream().map(textureSaver).toArray(CompletableFuture[]::new)),
geometryContext.geometry().map(geometry -> geometry.save(serializer, geometryDirectory, textureSaver)).orElse(noop()),
geometryContext.animation().map(context -> context.animation().save(serializer, animationDirectory, Rainbow.safeResourceLocation(identifier))).orElse(noop())
geometryContext.animation().map(context -> context.animation().save(serializer, animationDirectory, Rainbow.bedrockSafeIdentifier(identifier))).orElse(noop())
);
}

View File

@@ -4,7 +4,7 @@ import com.mojang.datafixers.util.Pair;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@@ -42,7 +42,7 @@ public class BedrockPack {
private final BedrockTextures.Builder itemTextures = BedrockTextures.builder();
private final Set<BedrockItem> bedrockItems = new HashSet<>();
private final Set<ResourceLocation> modelsMapped = new HashSet<>();
private final Set<Identifier> modelsMapped = new HashSet<>();
private final Set<Pair<Item, Integer>> customModelDataMapped = new HashSet<>();
private final PackContext context;
@@ -88,7 +88,7 @@ public class BedrockPack {
}
};
Optional<? extends ResourceLocation> patchedModel = stack.getComponentsPatch().get(DataComponents.ITEM_MODEL);
Optional<? extends Identifier> patchedModel = stack.getComponentsPatch().get(DataComponents.ITEM_MODEL);
//noinspection OptionalAssignedToNull - annoying Mojang
if (patchedModel == null || patchedModel.isEmpty()) {
CustomModelData customModelData = stack.get(DataComponents.CUSTOM_MODEL_DATA);
@@ -100,7 +100,7 @@ public class BedrockPack {
BedrockItemMapper.tryMapStack(stack, firstNumber.intValue(), mapReporter, context);
} else {
ResourceLocation model = patchedModel.get();
Identifier model = patchedModel.get();
if (!modelsMapped.add(model)) {
return MappingResult.NONE_MAPPED;
}
@@ -125,8 +125,8 @@ public class BedrockPack {
futures.add(serializer.saveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), paths.itemAtlas()));
Function<TextureHolder, CompletableFuture<?>> textureSaver = texture -> {
ResourceLocation textureLocation = Rainbow.decorateTextureLocation(texture.location());
return texture.save(context.assetResolver(), serializer, paths.packRoot().resolve(textureLocation.getPath()), reporter);
Identifier textureIdentifier = Rainbow.decorateTextureIdentifier(texture.location());
return texture.save(context.assetResolver(), serializer, paths.packRoot().resolve(textureIdentifier.getPath()), reporter);
};
for (BedrockItem item : bedrockItems) {

View File

@@ -5,7 +5,7 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.EquipmentSlot;
@@ -37,14 +37,14 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
public CompletableFuture<?> save(PackSerializer serializer, Path attachablesDirectory) {
// Get a safe attachable path by using Geyser's way of getting icons
return serializer.saveJson(CODEC, this, attachablesDirectory.resolve(Rainbow.safeResourceLocation(info.identifier) + ".json"));
return serializer.saveJson(CODEC, this, attachablesDirectory.resolve(Rainbow.bedrockSafeIdentifier(info.identifier) + ".json"));
}
public static Builder builder(ResourceLocation identifier) {
public static Builder builder(Identifier identifier) {
return new Builder(identifier);
}
public static BedrockAttachable.Builder equipment(ResourceLocation identifier, EquipmentSlot slot, String texture) {
public static BedrockAttachable.Builder equipment(Identifier identifier, EquipmentSlot slot, String texture) {
String script = switch (slot) {
case HEAD -> "v.helmet_layer_visible = 0.0;";
case CHEST -> "v.chest_layer_visible = 0.0;";
@@ -62,7 +62,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
.withRenderController(VanillaRenderControllers.ARMOR);
}
public static BedrockAttachable.Builder geometry(ResourceLocation identifier, MappedGeometry geometry) {
public static BedrockAttachable.Builder geometry(Identifier identifier, MappedGeometry geometry) {
return builder(identifier)
.withMaterial(DisplaySlot.DEFAULT, VanillaMaterials.ENTITY)
.withMaterial(DisplaySlot.ENCHANTED, VanillaMaterials.ENTITY_ALPHATEST_GLINT)
@@ -73,7 +73,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
}
public static class Builder {
private final ResourceLocation identifier;
private final Identifier identifier;
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
private final EnumMap<DisplaySlot, String> textures = new EnumMap<>(DisplaySlot.class);
private final EnumMap<DisplaySlot, String> geometries = new EnumMap<>(DisplaySlot.class);
@@ -81,7 +81,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
private final Map<String, List<Script>> scripts = new HashMap<>();
private final List<String> renderControllers = new ArrayList<>();
public Builder(ResourceLocation identifier) {
public Builder(Identifier identifier) {
this.identifier = identifier;
}
@@ -137,13 +137,13 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
}
}
public record AttachableInfo(ResourceLocation identifier, DisplayMap materials, DisplayMap textures,
public record AttachableInfo(Identifier identifier, DisplayMap materials, DisplayMap textures,
DisplayMap geometry, Map<String, String> animations, Scripts scripts,
List<String> renderControllers) {
private static final Codec<Map<String, String>> STRING_MAP_CODEC = Codec.unboundedMap(Codec.STRING, Codec.STRING);
public static final Codec<AttachableInfo> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("identifier").forGetter(AttachableInfo::identifier),
Identifier.CODEC.fieldOf("identifier").forGetter(AttachableInfo::identifier),
DisplayMap.CODEC.fieldOf("materials").forGetter(AttachableInfo::materials),
DisplayMap.CODEC.fieldOf("textures").forGetter(AttachableInfo::textures),
DisplayMap.CODEC.fieldOf("geometry").forGetter(AttachableInfo::geometry),