mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Attachable generation from equipment assets
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package org.geysermc.packgenerator.mapping.attachable;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.model.EquipmentAssetManager;
|
||||
import net.minecraft.client.resources.model.EquipmentClientInfo;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.geysermc.packgenerator.mixin.EntityRenderDispatcherAccessor;
|
||||
import org.geysermc.packgenerator.pack.attachable.BedrockAttachable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AttachableMapper {
|
||||
|
||||
public static Optional<BedrockAttachable> mapItem(ItemStack stack, ResourceLocation bedrockIdentifier) {
|
||||
// Crazy optional statement
|
||||
return Optional.ofNullable(stack.get(DataComponents.EQUIPPABLE))
|
||||
.flatMap(equippable -> {
|
||||
EquipmentAssetManager equipmentAssets = ((EntityRenderDispatcherAccessor) Minecraft.getInstance().getEntityRenderDispatcher()).getEquipmentAssets();
|
||||
return equippable.assetId().map(asset -> Pair.of(equippable.slot(), equipmentAssets.get(asset)));
|
||||
})
|
||||
.filter(assetInfo -> assetInfo.getSecond() != EquipmentAssetManager.MISSING)
|
||||
.map(assetInfo -> assetInfo
|
||||
.mapSecond(info -> info.getLayers(getLayer(assetInfo.getFirst()))))
|
||||
.filter(assetInfo -> !assetInfo.getSecond().isEmpty())
|
||||
.map(assetInfo -> BedrockAttachable.equipment(bedrockIdentifier, assetInfo.getFirst(), getTexture(assetInfo.getSecond(), getLayer(assetInfo.getFirst()))));
|
||||
}
|
||||
|
||||
private static EquipmentClientInfo.LayerType getLayer(EquipmentSlot slot) {
|
||||
return slot == EquipmentSlot.LEGS ? EquipmentClientInfo.LayerType.HUMANOID_LEGGINGS : EquipmentClientInfo.LayerType.HUMANOID;
|
||||
}
|
||||
|
||||
private static String getTexture(List<EquipmentClientInfo.Layer> info, EquipmentClientInfo.LayerType layer) {
|
||||
return "entity/equipment/" + layer.getSerializedName() + "/" + info.getFirst().textureId().getPath();
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public record GeyserMapping(ResourceLocation model, ResourceLocation bedrockIden
|
||||
return bedrockOptions.icon.orElse(iconFromResourceLocation(bedrockIdentifier));
|
||||
}
|
||||
|
||||
private static String iconFromResourceLocation(ResourceLocation location) {
|
||||
public static String iconFromResourceLocation(ResourceLocation location) {
|
||||
return location.toString().replace(':', '.').replace('/', '_');
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.geysermc.packgenerator.mixin;
|
||||
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.resources.model.EquipmentAssetManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(EntityRenderDispatcher.class)
|
||||
public interface EntityRenderDispatcherAccessor {
|
||||
|
||||
@Accessor
|
||||
EquipmentAssetManager getEquipmentAssets();
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.geysermc.packgenerator.CodecUtil;
|
||||
import org.geysermc.packgenerator.PackConstants;
|
||||
import org.geysermc.packgenerator.mapping.attachable.AttachableMapper;
|
||||
import org.geysermc.packgenerator.mapping.geyser.GeyserMappings;
|
||||
import org.geysermc.packgenerator.pack.attachable.BedrockAttachable;
|
||||
|
||||
@@ -16,6 +17,7 @@ import java.util.UUID;
|
||||
public class BedrockPack {
|
||||
private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve("geyser");
|
||||
private static final Path PACK_DIRECTORY = Path.of("pack");
|
||||
private static final Path ATTACHABLES_DIRECTORY = Path.of("attachables");
|
||||
|
||||
private static final Path MAPPINGS_FILE = Path.of("geyser_mappings.json");
|
||||
private static final Path MANIFEST_FILE = Path.of("manifest.json");
|
||||
@@ -44,13 +46,19 @@ public class BedrockPack {
|
||||
}
|
||||
|
||||
public void map(ItemStack stack) {
|
||||
mappings.map(stack, mapping -> itemTextures.withItemTexture(mapping, mapping.bedrockIdentifier().getPath()));
|
||||
mappings.map(stack, mapping -> {
|
||||
itemTextures.withItemTexture(mapping, mapping.bedrockIdentifier().getPath());
|
||||
AttachableMapper.mapItem(stack, mapping.bedrockIdentifier()).ifPresent(attachables::add);
|
||||
});
|
||||
}
|
||||
|
||||
public void save() throws IOException {
|
||||
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE));
|
||||
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE));
|
||||
CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), packPath.resolve(ITEM_ATLAS_FILE));
|
||||
for (BedrockAttachable attachable : attachables) {
|
||||
attachable.save(packPath.resolve(ATTACHABLES_DIRECTORY));
|
||||
}
|
||||
}
|
||||
|
||||
private static Path createPackDirectory(String name) throws IOException {
|
||||
|
||||
@@ -10,7 +10,7 @@ public record BedrockVersion(int major, int minor, int patch) {
|
||||
.xmap(list -> BedrockVersion.of(list.getFirst(), list.get(1), list.getLast()),
|
||||
version -> List.of(version.major, version.minor, version.patch));
|
||||
public static final Codec<BedrockVersion> STRING_CODEC = Codec.STRING.comapFlatMap(string -> {
|
||||
String[] segments = string.split("\.");
|
||||
String[] segments = string.split("\\.");
|
||||
if (segments.length != 3) {
|
||||
return DataResult.error(() -> "Semantic version must consist of 3 versions");
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
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.pack.BedrockTextures;
|
||||
import org.geysermc.packgenerator.pack.BedrockVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
@@ -39,6 +43,11 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
|
||||
.build();
|
||||
}
|
||||
|
||||
public void save(Path attachablesPath) throws IOException {
|
||||
// Get a save attachable path by using Geyser's way of getting icons
|
||||
CodecUtil.trySaveJson(CODEC, this, attachablesPath.resolve(GeyserMapping.iconFromResourceLocation(info.identifier)));
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final ResourceLocation identifier;
|
||||
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"BlockModelWrapperMixin",
|
||||
"BlockModelWrapperMixin$UnbakedMixin",
|
||||
"ConditionalItemModelAccessor",
|
||||
"EntityRenderDispatcherAccessor",
|
||||
"SelectItemModelAccessor",
|
||||
"SelectItemModelMixin",
|
||||
"SelectItemModelMixin$UnbakedSwitchMixin"
|
||||
|
||||
Reference in New Issue
Block a user