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));
|
return bedrockOptions.icon.orElse(iconFromResourceLocation(bedrockIdentifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String iconFromResourceLocation(ResourceLocation location) {
|
public static String iconFromResourceLocation(ResourceLocation location) {
|
||||||
return location.toString().replace(':', '.').replace('/', '_');
|
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 net.minecraft.world.item.ItemStack;
|
||||||
import org.geysermc.packgenerator.CodecUtil;
|
import org.geysermc.packgenerator.CodecUtil;
|
||||||
import org.geysermc.packgenerator.PackConstants;
|
import org.geysermc.packgenerator.PackConstants;
|
||||||
|
import org.geysermc.packgenerator.mapping.attachable.AttachableMapper;
|
||||||
import org.geysermc.packgenerator.mapping.geyser.GeyserMappings;
|
import org.geysermc.packgenerator.mapping.geyser.GeyserMappings;
|
||||||
import org.geysermc.packgenerator.pack.attachable.BedrockAttachable;
|
import org.geysermc.packgenerator.pack.attachable.BedrockAttachable;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ import java.util.UUID;
|
|||||||
public class BedrockPack {
|
public class BedrockPack {
|
||||||
private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve("geyser");
|
private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve("geyser");
|
||||||
private static final Path PACK_DIRECTORY = Path.of("pack");
|
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 MAPPINGS_FILE = Path.of("geyser_mappings.json");
|
||||||
private static final Path MANIFEST_FILE = Path.of("manifest.json");
|
private static final Path MANIFEST_FILE = Path.of("manifest.json");
|
||||||
@@ -44,13 +46,19 @@ public class BedrockPack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void map(ItemStack stack) {
|
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 {
|
public void save() throws IOException {
|
||||||
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE));
|
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE));
|
||||||
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE));
|
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE));
|
||||||
CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), packPath.resolve(ITEM_ATLAS_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 {
|
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()),
|
.xmap(list -> BedrockVersion.of(list.getFirst(), list.get(1), list.getLast()),
|
||||||
version -> List.of(version.major, version.minor, version.patch));
|
version -> List.of(version.major, version.minor, version.patch));
|
||||||
public static final Codec<BedrockVersion> STRING_CODEC = Codec.STRING.comapFlatMap(string -> {
|
public static final Codec<BedrockVersion> STRING_CODEC = Codec.STRING.comapFlatMap(string -> {
|
||||||
String[] segments = string.split("\.");
|
String[] segments = string.split("\\.");
|
||||||
if (segments.length != 3) {
|
if (segments.length != 3) {
|
||||||
return DataResult.error(() -> "Semantic version must consist of 3 versions");
|
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.resources.ResourceLocation;
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
import net.minecraft.world.entity.EquipmentSlot;
|
import net.minecraft.world.entity.EquipmentSlot;
|
||||||
|
import org.geysermc.packgenerator.CodecUtil;
|
||||||
import org.geysermc.packgenerator.PackConstants;
|
import org.geysermc.packgenerator.PackConstants;
|
||||||
|
import org.geysermc.packgenerator.mapping.geyser.GeyserMapping;
|
||||||
import org.geysermc.packgenerator.pack.BedrockTextures;
|
import org.geysermc.packgenerator.pack.BedrockTextures;
|
||||||
import org.geysermc.packgenerator.pack.BedrockVersion;
|
import org.geysermc.packgenerator.pack.BedrockVersion;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -39,6 +43,11 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
|
|||||||
.build();
|
.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 {
|
public static class Builder {
|
||||||
private final ResourceLocation identifier;
|
private final ResourceLocation identifier;
|
||||||
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
|
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"BlockModelWrapperMixin",
|
"BlockModelWrapperMixin",
|
||||||
"BlockModelWrapperMixin$UnbakedMixin",
|
"BlockModelWrapperMixin$UnbakedMixin",
|
||||||
"ConditionalItemModelAccessor",
|
"ConditionalItemModelAccessor",
|
||||||
|
"EntityRenderDispatcherAccessor",
|
||||||
"SelectItemModelAccessor",
|
"SelectItemModelAccessor",
|
||||||
"SelectItemModelMixin",
|
"SelectItemModelMixin",
|
||||||
"SelectItemModelMixin$UnbakedSwitchMixin"
|
"SelectItemModelMixin$UnbakedSwitchMixin"
|
||||||
|
|||||||
Reference in New Issue
Block a user