From b111faed7feca0e2384fcafb095a70e35434241d Mon Sep 17 00:00:00 2001 From: SHsuperCM Date: Thu, 9 Sep 2021 18:12:31 +0300 Subject: v0.5.1, "Broken Path" mixins wont be injected if config is turned off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Changing config for broken paths now requires a restart to apply and it being disabled completely removes the effects it has on the game. • Organized mixins into packages fixes #14 --- .../fabric/citresewn/config/CITResewnConfig.java | 3 - .../config/CITResewnConfigScreenFactory.java | 8 +- .../config/CITResewnMixinConfiguration.java | 45 +++++ .../mixin/AbstractFileResourcePackMixin.java | 50 ------ .../citresewn/mixin/ArmorFeatureRendererMixin.java | 54 ------ .../mixin/ElytraFeatureRendererMixin.java | 50 ------ .../fabric/citresewn/mixin/IdentifierMixin.java | 17 -- .../fabric/citresewn/mixin/ItemRendererMixin.java | 26 --- .../citresewn/mixin/JsonUnbakedModelAccessor.java | 22 --- .../fabric/citresewn/mixin/ModelLoaderMixin.java | 185 --------------------- .../citresewn/mixin/NbtCompoundAccessor.java | 14 -- .../mixin/ReloadableResourceManagerImplMixin.java | 32 ---- .../mixin/ResourcePackCompatibilityMixin.java | 26 --- .../citresewn/mixin/SpriteAtlasTextureMixin.java | 18 -- .../AbstractFileResourcePackMixin.java | 49 ++++++ .../mixin/broken_paths/IdentifierMixin.java | 17 ++ .../ReloadableResourceManagerImplMixin.java | 29 ++++ .../ResourcePackCompatibilityMixin.java | 26 +++ .../mixin/citarmor/ArmorFeatureRendererMixin.java | 54 ++++++ .../citelytra/ElytraFeatureRendererMixin.java | 50 ++++++ .../citresewn/mixin/cititem/ItemRendererMixin.java | 26 +++ .../mixin/core/JsonUnbakedModelAccessor.java | 22 +++ .../citresewn/mixin/core/ModelLoaderMixin.java | 185 +++++++++++++++++++++ .../citresewn/mixin/core/NbtCompoundAccessor.java | 14 ++ .../mixin/core/SpriteAtlasTextureMixin.java | 18 ++ .../citresewn/pack/ResewnItemModelIdentifier.java | 3 +- .../citresewn/pack/ResewnTextureIdentifier.java | 3 +- .../shsupercm/fabric/citresewn/pack/cits/CIT.java | 4 +- .../fabric/citresewn/pack/cits/CITItem.java | 2 +- 29 files changed, 543 insertions(+), 509 deletions(-) create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnMixinConfiguration.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/AbstractFileResourcePackMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ArmorFeatureRendererMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ElytraFeatureRendererMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/IdentifierMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ItemRendererMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/JsonUnbakedModelAccessor.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ModelLoaderMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ReloadableResourceManagerImplMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ResourcePackCompatibilityMixin.java delete mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/SpriteAtlasTextureMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/AbstractFileResourcePackMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/IdentifierMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ReloadableResourceManagerImplMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ResourcePackCompatibilityMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citarmor/ArmorFeatureRendererMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citelytra/ElytraFeatureRendererMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/cititem/ItemRendererMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/JsonUnbakedModelAccessor.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/ModelLoaderMixin.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/NbtCompoundAccessor.java create mode 100644 src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/SpriteAtlasTextureMixin.java (limited to 'src/main/java/shcm/shsupercm/fabric/citresewn') diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfig.java b/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfig.java index 5bc059e..c1c5148 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfig.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfig.java @@ -24,13 +24,10 @@ public class CITResewnConfig { if (!FILE.exists()) return new CITResewnConfig().write(); - CITParser.REGISTRY.put("test", CITItem::new); - Reader reader = null; try { return new Gson().fromJson(reader = new FileReader(FILE), CITResewnConfig.class); } catch (Exception e) { - CITResewn.LOG.error("Couldn't load config"); e.printStackTrace(); throw new RuntimeException(e); } finally { diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfigScreenFactory.java b/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfigScreenFactory.java index b85a55c..6fd51f7 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfigScreenFactory.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnConfigScreenFactory.java @@ -45,13 +45,9 @@ public class CITResewnConfigScreenFactory { category.addEntry(entryBuilder.startBooleanToggle(new TranslatableText("config.citresewn.broken_paths.title"), currentConfig.broken_paths) .setTooltip(new TranslatableText("config.citresewn.broken_paths.tooltip")) - .setSaveConsumer(newConfig -> { - if (currentConfig.broken_paths != newConfig) { - currentConfig.broken_paths = newConfig; - MinecraftClient.getInstance().reloadResources(); - } - }) + .setSaveConsumer(newConfig -> currentConfig.broken_paths = newConfig) .setDefaultValue(defaultConfig.broken_paths) + .requireRestart() .build()); return builder.build(); diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnMixinConfiguration.java b/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnMixinConfiguration.java new file mode 100644 index 0000000..e3d8243 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/config/CITResewnMixinConfiguration.java @@ -0,0 +1,45 @@ +package shcm.shsupercm.fabric.citresewn.config; + +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public class CITResewnMixinConfiguration implements IMixinConfigPlugin { + private static final String MIXINS_ROOT = "shcm.shsupercm.fabric.citresewn.mixin"; + + private boolean broken_paths; + + @Override + public void onLoad(String mixinPackage) { + CITResewnConfig launchConfig = CITResewnConfig.read(); + + this.broken_paths = launchConfig.broken_paths; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if (!mixinClassName.startsWith(MIXINS_ROOT)) + return false; + mixinClassName = mixinClassName.substring(MIXINS_ROOT.length() + 1); + + if (mixinClassName.startsWith("broken_paths")) + return broken_paths; + + return true; + } + + + @Override + public String getRefMapperConfig() { return null; } + @Override + public List getMixins() { return null; } + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { } + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/AbstractFileResourcePackMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/AbstractFileResourcePackMixin.java deleted file mode 100644 index acc0f38..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/AbstractFileResourcePackMixin.java +++ /dev/null @@ -1,50 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.resource.AbstractFileResourcePack; -import net.minecraft.resource.DirectoryResourcePack; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ZipResourcePack; -import net.minecraft.resource.metadata.PackResourceMetadata; -import net.minecraft.resource.metadata.ResourceMetadataReader; -import net.minecraft.util.Identifier; -import net.minecraft.util.InvalidIdentifierException; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.zip.ZipFile; - -@Mixin(AbstractFileResourcePack.class) -public abstract class AbstractFileResourcePackMixin implements ResourcePack { - @Shadow @Final protected File base; - - @SuppressWarnings({"unchecked", "ConstantConditions", "EqualsBetweenInconvertibleTypes"}) - @Inject(method = "parseMetadata(Lnet/minecraft/resource/metadata/ResourceMetadataReader;)Ljava/lang/Object;", cancellable = true, at = @At("RETURN")) - public void parseMetadata(ResourceMetadataReader metaReader, CallbackInfoReturnable cir) { - if (CITResewnConfig.INSTANCE().broken_paths && cir.getReturnValue() != null) - try { - if (this.getClass().equals(ZipResourcePack.class)) { - try (ZipFile zipFile = new ZipFile(base)) { - zipFile.stream() - .forEach(entry -> { - if (entry.getName().startsWith("assets")) - new Identifier("minecraft", entry.getName()); - }); - } - } else if (this.getClass().equals(DirectoryResourcePack.class)) { - final Path assets = new File(base, "assets").toPath(); - Files.walk(assets) - .forEach(path -> new Identifier("minecraft", assets.relativize(path).toString().replace('\\', '/'))); - } - } catch (InvalidIdentifierException e) { - cir.setReturnValue((T) new PackResourceMetadata(cir.getReturnValue().getDescription(), Integer.MAX_VALUE - 53)); - } catch (Exception ignored) {} - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ArmorFeatureRendererMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ArmorFeatureRendererMixin.java deleted file mode 100644 index 02f4689..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ArmorFeatureRendererMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ArmorItem; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.CITResewn; -import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; - -import java.lang.ref.WeakReference; -import java.util.Map; - -@Mixin(ArmorFeatureRenderer.class) -public class ArmorFeatureRendererMixin, A extends BipedEntityModel> { - private WeakReference> armorTexturesCached = null; - - @Inject(method = "renderArmor", cancellable = true, at = @At("HEAD")) - public void renderArmor(MatrixStack matrices, VertexConsumerProvider vertexConsumers, T entity, EquipmentSlot armorSlot, int light, A model, CallbackInfo ci) { - if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) - return; - - ItemStack itemStack = entity.getEquippedStack(armorSlot); - Map armorTextures = CITResewn.INSTANCE.activeCITs.getArmorTextures(itemStack, entity.world, entity); - if (armorTextures != null) { - armorTexturesCached = new WeakReference<>(armorTextures); - return; - } - - armorTexturesCached = null; - } - - @Inject(method = "getArmorTexture", cancellable = true, at = @At("HEAD")) - public void getArmorTexture(ArmorItem item, boolean legs, String overlay, CallbackInfoReturnable cir) { - if (armorTexturesCached == null) - return; - Map armorTextures = armorTexturesCached.get(); - if (armorTextures == null) - return; - - Identifier identifier = armorTextures.get(item.getMaterial().getName() + "_layer_" + (legs ? "2" : "1") + (overlay == null ? "" : "_" + overlay)); - if (identifier != null) - cir.setReturnValue(identifier); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ElytraFeatureRendererMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ElytraFeatureRendererMixin.java deleted file mode 100644 index a774de4..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ElytraFeatureRendererMixin.java +++ /dev/null @@ -1,50 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.feature.ElytraFeatureRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import shcm.shsupercm.fabric.citresewn.CITResewn; -import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; - -import java.lang.ref.WeakReference; - -@Mixin(ElytraFeatureRenderer.class) -public class ElytraFeatureRendererMixin { - private WeakReference elytraItemCached = new WeakReference<>(null); - private WeakReference livingEntityCached = new WeakReference<>(null); - - @Inject(method = "render", cancellable = true, at = @At("HEAD")) - public void render(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, LivingEntity livingEntity, float f, float g, float h, float j, float k, float l, CallbackInfo ci) { - if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) - return; - - this.elytraItemCached = new WeakReference<>(livingEntity.getEquippedStack(EquipmentSlot.CHEST)); - this.livingEntityCached = new WeakReference<>(livingEntity); - } - - @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getArmorCutoutNoCull(Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;")) - public RenderLayer getArmorCutoutNoCull(Identifier originalIdentifier) { - if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) - return RenderLayer.getArmorCutoutNoCull(originalIdentifier); - - ItemStack itemStack = this.elytraItemCached.get(); - LivingEntity livingEntity = livingEntityCached.get(); - if (itemStack != null && livingEntity != null) { - Identifier elytraTexture = CITResewn.INSTANCE.activeCITs.getElytraTexture(itemStack, livingEntity.world, livingEntity); - if (elytraTexture != null) - return RenderLayer.getArmorCutoutNoCull(elytraTexture); - } - - return RenderLayer.getArmorCutoutNoCull(originalIdentifier); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/IdentifierMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/IdentifierMixin.java deleted file mode 100644 index 4892abc..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/IdentifierMixin.java +++ /dev/null @@ -1,17 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.CITResewn; - -@Mixin(Identifier.class) -public class IdentifierMixin { - @Inject(method = "isPathValid", cancellable = true, at = @At("HEAD")) - private static void processBrokenPaths(String path, CallbackInfoReturnable cir) { - if (CITResewn.INSTANCE != null && CITResewn.INSTANCE.processingBrokenPaths) - cir.setReturnValue(true); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ItemRendererMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ItemRendererMixin.java deleted file mode 100644 index 58b5fe2..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ItemRendererMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.CITResewn; -import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; - -@Mixin(ItemRenderer.class) -public class ItemRendererMixin { - @Inject(method = "getHeldItemModel", cancellable = true, at = @At("RETURN")) - public void injectCIT(ItemStack stack, World world, LivingEntity entity, int seed, CallbackInfoReturnable cir) { - if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) - return; - - BakedModel citModel = CITResewn.INSTANCE.activeCITs.getItemModel(stack, cir.getReturnValue(), world, entity); - if (citModel != null) - cir.setReturnValue(citModel); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/JsonUnbakedModelAccessor.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/JsonUnbakedModelAccessor.java deleted file mode 100644 index 70a3815..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/JsonUnbakedModelAccessor.java +++ /dev/null @@ -1,22 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import com.mojang.datafixers.util.Either; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(JsonUnbakedModel.class) -public interface JsonUnbakedModelAccessor { - @Accessor - Map> getTextureMap(); - - @Accessor - Identifier getParentId(); - - @Accessor - void setParentId(Identifier parentId); -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ModelLoaderMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ModelLoaderMixin.java deleted file mode 100644 index af55496..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ModelLoaderMixin.java +++ /dev/null @@ -1,185 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import com.mojang.datafixers.util.Either; -import net.minecraft.client.render.model.*; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import net.minecraft.client.texture.TextureManager; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.resource.Resource; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; -import net.minecraft.util.profiler.Profiler; -import org.apache.commons.io.IOUtils; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.ActiveCITs; -import shcm.shsupercm.fabric.citresewn.CITResewn; -import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; -import shcm.shsupercm.fabric.citresewn.pack.CITParser; -import shcm.shsupercm.fabric.citresewn.pack.ResewnItemModelIdentifier; -import shcm.shsupercm.fabric.citresewn.pack.ResewnTextureIdentifier; -import shcm.shsupercm.fabric.citresewn.pack.cits.CIT; -import shcm.shsupercm.fabric.citresewn.pack.cits.CITItem; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.stream.Collectors; - -import static shcm.shsupercm.fabric.citresewn.CITResewn.info; - -@Mixin(ModelLoader.class) -public abstract class ModelLoaderMixin { - @Shadow @Final private ResourceManager resourceManager; - @Shadow @Final private Set modelsToLoad; - @Shadow @Final private Map unbakedModels; - @Shadow @Final private Map modelsToBake; - @Shadow @Final private Map bakedModels; - @Shadow protected abstract JsonUnbakedModel loadModelFromJson(Identifier id) throws IOException; - - private Map citOverrideCacheMap = new HashMap<>(); - - @Inject(method = "addModel", at = @At("TAIL")) - public void loadCIT(ModelIdentifier eventModelId, CallbackInfo ci) { if (eventModelId != ModelLoader.MISSING_ID) return; - if (CITResewn.INSTANCE.activeCITs != null) { - info("Clearing active CITs.."); - CITResewn.INSTANCE.activeCITs.dispose(); - CITResewn.INSTANCE.activeCITs = null; - } - - if (!CITResewnConfig.INSTANCE().enabled) - return; - - info("Loading CIT Resewn.."); - - info("Parsing CITs..."); - Collection parsed = CITParser.parse(resourceManager.streamResourcePacks().collect(Collectors.toCollection(ArrayList::new))); - - if (parsed.size() > 0) { - info("Loading CITItem models.."); - for (CIT cit : parsed) - if (cit instanceof CITItem citItem) { - try { - citItem.loadUnbakedAssets(resourceManager); - - for (JsonUnbakedModel unbakedModel : citItem.unbakedAssets.values()) { - ResewnItemModelIdentifier id = new ResewnItemModelIdentifier(unbakedModel.id); - this.unbakedModels.put(id, unbakedModel); - this.modelsToLoad.addAll(unbakedModel.getModelDependencies()); - this.modelsToBake.put(id, unbakedModel); - } - } catch (Exception e) { - CITResewn.logErrorLoading(e.getMessage()); - } - } - - info("Activating CITs..."); - CITResewn.INSTANCE.activeCITs = new ActiveCITs(parsed); - } else - info("No cit packs found."); - } - - @Inject(method = "bake", at = @At("RETURN")) - public void onBake(Identifier id, ModelBakeSettings settings, CallbackInfoReturnable cir) { - if (CITResewn.INSTANCE.activeCITs == null) - return; - - this.citOverrideCacheMap.put(id, cir.getReturnValue()); - } - - @Inject(method = "upload", at = @At("RETURN")) - public void linkBakedModels(TextureManager textureManager, Profiler profiler, CallbackInfoReturnable cir) { - if (CITResewn.INSTANCE.activeCITs == null) - return; - - profiler.push("citresewn_linking"); - info("Linking baked models to CITItems..."); - - if (CITResewn.INSTANCE.activeCITs != null) { - for (CITItem citItem : CITResewn.INSTANCE.activeCITs.citItems.values().stream().flatMap(Collection::stream).distinct().collect(Collectors.toList())) { - for (Map.Entry citModelEntry : citItem.unbakedAssets.entrySet()) { - if (citModelEntry.getKey() == null) { - citItem.bakedModel = this.bakedModels.get(new ResewnItemModelIdentifier(citModelEntry.getValue().id)); - } else { - if (citItem.subItems == null) - citItem.subItems = new HashMap<>(); - - BakedModel override = citOverrideCacheMap.get(citModelEntry.getKey()); - - if (override == null) - override = citOverrideCacheMap.get(new ModelIdentifier(citModelEntry.getKey().getNamespace(), citModelEntry.getKey().getPath().substring(5), "inventory")); - - if (override != null) - citItem.subItems.put(override, this.bakedModels.get(new ResewnItemModelIdentifier(citModelEntry.getValue().id))); - else { - CITResewn.logErrorLoading("Skipping sub cit: No such sub item model \"" + citModelEntry.getKey().getPath().substring(5) + "\" in " + citItem.pack.resourcePack.getName() + " -> " + citItem.propertiesIdentifier.getPath()); - } - } - } - citItem.unbakedAssets = null; - } - } - - this.citOverrideCacheMap = null; - - profiler.pop(); - } - - - @Inject(method = "loadModelFromJson", cancellable = true, at = @At("HEAD")) - public void forceLiteralResewnModelIdentifier(Identifier id, CallbackInfoReturnable cir) { - if (id instanceof ResewnItemModelIdentifier) { - InputStream is = null; - Resource resource = null; - try { - JsonUnbakedModel json = JsonUnbakedModel.deserialize(IOUtils.toString(is = (resource = resourceManager.getResource(id)).getInputStream(), StandardCharsets.UTF_8)); - json.id = id.toString(); - json.id = json.id.substring(0, json.id.length() - 5); - - ((JsonUnbakedModelAccessor) json).getTextureMap().replaceAll((layer, original) -> { - Optional left = original.left(); - if (left.isPresent()) { - String originalPath = left.get().getTextureId().getPath(); - String[] split = originalPath.split("/"); - if (originalPath.startsWith("./") || (split.length > 2 && split[1].equals("cit"))) { - Identifier resolvedIdentifier = CIT.resolvePath(id, originalPath, ".png", identifier -> resourceManager.containsResource(identifier)); - if (resolvedIdentifier != null) - return Either.left(new SpriteIdentifier(left.get().getAtlasId(), new ResewnTextureIdentifier(resolvedIdentifier))); - } - } - return original; - }); - - Identifier parentId = ((JsonUnbakedModelAccessor) json).getParentId(); - if (parentId != null) { - String[] parentIdPathSplit = parentId.getPath().split("/"); - if (parentId.getPath().startsWith("./") || (parentIdPathSplit.length > 2 && parentIdPathSplit[1].equals("cit"))) { - parentId = CIT.resolvePath(id, parentId.getPath(), ".json", identifier -> resourceManager.containsResource(identifier)); - if (parentId != null) - ((JsonUnbakedModelAccessor) json).setParentId(new ResewnItemModelIdentifier(parentId)); - } - } - - cir.setReturnValue(json); - } catch (Exception ignored) { - } finally { - IOUtils.closeQuietly(is, resource); - } - } - } - - @Redirect(method = "loadModelFromJson", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;")) - public Resource getResource(ResourceManager resourceManager, Identifier id) throws IOException { - if (id.getPath().endsWith(".json.json") && id.getPath().contains("cit")) - return resourceManager.getResource(new Identifier(id.getNamespace(), id.getPath().substring(7, id.getPath().length() - 5))); - return resourceManager.getResource(id); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java deleted file mode 100644 index 2264638..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/NbtCompoundAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(NbtCompound.class) -public interface NbtCompoundAccessor { - @Accessor - Map getEntries(); -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ReloadableResourceManagerImplMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ReloadableResourceManagerImplMixin.java deleted file mode 100644 index 8ee0498..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ReloadableResourceManagerImplMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.resource.ReloadableResourceManagerImpl; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourceReload; -import net.minecraft.resource.ResourceType; -import net.minecraft.util.Unit; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.CITResewn; -import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; - -@Mixin(ReloadableResourceManagerImpl.class) -public class ReloadableResourceManagerImplMixin { - @Shadow @Final private ResourceType type; - - @Inject(method = "reload", at = @At("RETURN")) - public void onReload(Executor prepareExecutor, Executor applyExecutor, CompletableFuture initialStage, List packs, CallbackInfoReturnable cir) { - if (CITResewn.INSTANCE.processingBrokenPaths = (this.type == ResourceType.CLIENT_RESOURCES && CITResewnConfig.INSTANCE().broken_paths)) - cir.getReturnValue().whenComplete().thenRun(() -> { - CITResewn.INSTANCE.processingBrokenPaths = false; - }); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ResourcePackCompatibilityMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ResourcePackCompatibilityMixin.java deleted file mode 100644 index c41ddad..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/ResourcePackCompatibilityMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.resource.ResourcePackCompatibility; -import net.minecraft.resource.ResourceType; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ResourcePackCompatibility.class) -public abstract class ResourcePackCompatibilityMixin { - private static final ResourcePackCompatibility BROKEN_PATHS = ResourcePackCompatibility("BROKEN_PATHS", -1, "broken_paths"); - - @SuppressWarnings("InvokerTarget") - @Invoker("") - public static ResourcePackCompatibility ResourcePackCompatibility(String internalName, int internalId, String translationSuffix) { - throw new AssertionError(); - } - - @Inject(method = "from(ILnet/minecraft/resource/ResourceType;)Lnet/minecraft/resource/ResourcePackCompatibility;", cancellable = true, at = @At("HEAD")) - private static void redirectBrokenPathsCompatibility(int packVersion, ResourceType type, CallbackInfoReturnable cir) { - if (packVersion == Integer.MAX_VALUE - 53) - cir.setReturnValue(BROKEN_PATHS); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/SpriteAtlasTextureMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/SpriteAtlasTextureMixin.java deleted file mode 100644 index dc21ae1..0000000 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/SpriteAtlasTextureMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package shcm.shsupercm.fabric.citresewn.mixin; - -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import shcm.shsupercm.fabric.citresewn.pack.ResewnTextureIdentifier; - -@Mixin(SpriteAtlasTexture.class) -public class SpriteAtlasTextureMixin { - @Inject(method = "getTexturePath", cancellable = true, at = @At("HEAD")) - public void forceLiteralResewnTextureIdentifier(Identifier id, CallbackInfoReturnable cir) { - if (id instanceof ResewnTextureIdentifier) - cir.setReturnValue(id); - } -} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/AbstractFileResourcePackMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/AbstractFileResourcePackMixin.java new file mode 100644 index 0000000..b6d2474 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/AbstractFileResourcePackMixin.java @@ -0,0 +1,49 @@ +package shcm.shsupercm.fabric.citresewn.mixin.broken_paths; + +import net.minecraft.resource.AbstractFileResourcePack; +import net.minecraft.resource.DirectoryResourcePack; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ZipResourcePack; +import net.minecraft.resource.metadata.PackResourceMetadata; +import net.minecraft.resource.metadata.ResourceMetadataReader; +import net.minecraft.util.Identifier; +import net.minecraft.util.InvalidIdentifierException; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipFile; + +@Mixin(AbstractFileResourcePack.class) // Only registered if CITResewnConfig#broken_paths is true +public abstract class AbstractFileResourcePackMixin implements ResourcePack { + @Shadow @Final protected File base; + + @SuppressWarnings({"unchecked", "ConstantConditions", "EqualsBetweenInconvertibleTypes"}) + @Inject(method = "parseMetadata(Lnet/minecraft/resource/metadata/ResourceMetadataReader;)Ljava/lang/Object;", cancellable = true, at = @At("RETURN")) + public void parseMetadata(ResourceMetadataReader metaReader, CallbackInfoReturnable cir) { + if (cir.getReturnValue() != null) + try { + if (this.getClass().equals(ZipResourcePack.class)) { + try (ZipFile zipFile = new ZipFile(base)) { + zipFile.stream() + .forEach(entry -> { + if (entry.getName().startsWith("assets")) + new Identifier("minecraft", entry.getName()); + }); + } + } else if (this.getClass().equals(DirectoryResourcePack.class)) { + final Path assets = new File(base, "assets").toPath(); + Files.walk(assets) + .forEach(path -> new Identifier("minecraft", assets.relativize(path).toString().replace('\\', '/'))); + } + } catch (InvalidIdentifierException e) { + cir.setReturnValue((T) new PackResourceMetadata(cir.getReturnValue().getDescription(), Integer.MAX_VALUE - 53)); + } catch (Exception ignored) {} + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/IdentifierMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/IdentifierMixin.java new file mode 100644 index 0000000..0ae5291 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/IdentifierMixin.java @@ -0,0 +1,17 @@ +package shcm.shsupercm.fabric.citresewn.mixin.broken_paths; + +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.CITResewn; + +@Mixin(Identifier.class) // Only registered if CITResewnConfig#broken_paths is true +public class IdentifierMixin { + @Inject(method = "isPathValid", cancellable = true, at = @At("HEAD")) + private static void processBrokenPaths(String path, CallbackInfoReturnable cir) { + if (CITResewn.INSTANCE != null && CITResewn.INSTANCE.processingBrokenPaths) + cir.setReturnValue(true); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ReloadableResourceManagerImplMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ReloadableResourceManagerImplMixin.java new file mode 100644 index 0000000..8833b4c --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ReloadableResourceManagerImplMixin.java @@ -0,0 +1,29 @@ +package shcm.shsupercm.fabric.citresewn.mixin.broken_paths; + +import net.minecraft.resource.ReloadableResourceManagerImpl; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourceReload; +import net.minecraft.resource.ResourceType; +import net.minecraft.util.Unit; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.CITResewn; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +@Mixin(ReloadableResourceManagerImpl.class) // Only registered if CITResewnConfig#broken_paths is true +public class ReloadableResourceManagerImplMixin { + @Shadow @Final private ResourceType type; + + @Inject(method = "reload", at = @At("RETURN")) + public void onReload(Executor prepareExecutor, Executor applyExecutor, CompletableFuture initialStage, List packs, CallbackInfoReturnable cir) { + if (CITResewn.INSTANCE.processingBrokenPaths = this.type == ResourceType.CLIENT_RESOURCES) + cir.getReturnValue().whenComplete().thenRun(() -> CITResewn.INSTANCE.processingBrokenPaths = false); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ResourcePackCompatibilityMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ResourcePackCompatibilityMixin.java new file mode 100644 index 0000000..4fe07ce --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/broken_paths/ResourcePackCompatibilityMixin.java @@ -0,0 +1,26 @@ +package shcm.shsupercm.fabric.citresewn.mixin.broken_paths; + +import net.minecraft.resource.ResourcePackCompatibility; +import net.minecraft.resource.ResourceType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ResourcePackCompatibility.class) // Only registered if CITResewnConfig#broken_paths is true +public abstract class ResourcePackCompatibilityMixin { + private static final ResourcePackCompatibility BROKEN_PATHS = ResourcePackCompatibility("BROKEN_PATHS", -1, "broken_paths"); + + @SuppressWarnings("InvokerTarget") + @Invoker("") + public static ResourcePackCompatibility ResourcePackCompatibility(String internalName, int internalId, String translationSuffix) { + throw new AssertionError(); + } + + @Inject(method = "from(ILnet/minecraft/resource/ResourceType;)Lnet/minecraft/resource/ResourcePackCompatibility;", cancellable = true, at = @At("HEAD")) + private static void redirectBrokenPathsCompatibility(int packVersion, ResourceType type, CallbackInfoReturnable cir) { + if (packVersion == Integer.MAX_VALUE - 53) + cir.setReturnValue(BROKEN_PATHS); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citarmor/ArmorFeatureRendererMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citarmor/ArmorFeatureRendererMixin.java new file mode 100644 index 0000000..5fe1965 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citarmor/ArmorFeatureRendererMixin.java @@ -0,0 +1,54 @@ +package shcm.shsupercm.fabric.citresewn.mixin.citarmor; + +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.CITResewn; +import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; + +import java.lang.ref.WeakReference; +import java.util.Map; + +@Mixin(ArmorFeatureRenderer.class) +public class ArmorFeatureRendererMixin, A extends BipedEntityModel> { + private WeakReference> armorTexturesCached = null; + + @Inject(method = "renderArmor", cancellable = true, at = @At("HEAD")) + public void renderArmor(MatrixStack matrices, VertexConsumerProvider vertexConsumers, T entity, EquipmentSlot armorSlot, int light, A model, CallbackInfo ci) { + if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) + return; + + ItemStack itemStack = entity.getEquippedStack(armorSlot); + Map armorTextures = CITResewn.INSTANCE.activeCITs.getArmorTextures(itemStack, entity.world, entity); + if (armorTextures != null) { + armorTexturesCached = new WeakReference<>(armorTextures); + return; + } + + armorTexturesCached = null; + } + + @Inject(method = "getArmorTexture", cancellable = true, at = @At("HEAD")) + public void getArmorTexture(ArmorItem item, boolean legs, String overlay, CallbackInfoReturnable cir) { + if (armorTexturesCached == null) + return; + Map armorTextures = armorTexturesCached.get(); + if (armorTextures == null) + return; + + Identifier identifier = armorTextures.get(item.getMaterial().getName() + "_layer_" + (legs ? "2" : "1") + (overlay == null ? "" : "_" + overlay)); + if (identifier != null) + cir.setReturnValue(identifier); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citelytra/ElytraFeatureRendererMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citelytra/ElytraFeatureRendererMixin.java new file mode 100644 index 0000000..f44871b --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/citelytra/ElytraFeatureRendererMixin.java @@ -0,0 +1,50 @@ +package shcm.shsupercm.fabric.citresewn.mixin.citelytra; + +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.feature.ElytraFeatureRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import shcm.shsupercm.fabric.citresewn.CITResewn; +import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; + +import java.lang.ref.WeakReference; + +@Mixin(ElytraFeatureRenderer.class) +public class ElytraFeatureRendererMixin { + private WeakReference elytraItemCached = new WeakReference<>(null); + private WeakReference livingEntityCached = new WeakReference<>(null); + + @Inject(method = "render", cancellable = true, at = @At("HEAD")) + public void render(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, LivingEntity livingEntity, float f, float g, float h, float j, float k, float l, CallbackInfo ci) { + if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) + return; + + this.elytraItemCached = new WeakReference<>(livingEntity.getEquippedStack(EquipmentSlot.CHEST)); + this.livingEntityCached = new WeakReference<>(livingEntity); + } + + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getArmorCutoutNoCull(Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;")) + public RenderLayer getArmorCutoutNoCull(Identifier originalIdentifier) { + if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) + return RenderLayer.getArmorCutoutNoCull(originalIdentifier); + + ItemStack itemStack = this.elytraItemCached.get(); + LivingEntity livingEntity = livingEntityCached.get(); + if (itemStack != null && livingEntity != null) { + Identifier elytraTexture = CITResewn.INSTANCE.activeCITs.getElytraTexture(itemStack, livingEntity.world, livingEntity); + if (elytraTexture != null) + return RenderLayer.getArmorCutoutNoCull(elytraTexture); + } + + return RenderLayer.getArmorCutoutNoCull(originalIdentifier); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/cititem/ItemRendererMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/cititem/ItemRendererMixin.java new file mode 100644 index 0000000..1014a44 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/cititem/ItemRendererMixin.java @@ -0,0 +1,26 @@ +package shcm.shsupercm.fabric.citresewn.mixin.cititem; + +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.CITResewn; +import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; + +@Mixin(ItemRenderer.class) +public class ItemRendererMixin { + @Inject(method = "getHeldItemModel", cancellable = true, at = @At("RETURN")) + public void getItemModel(ItemStack stack, World world, LivingEntity entity, int seed, CallbackInfoReturnable cir) { + if (!CITResewnConfig.INSTANCE().enabled || CITResewn.INSTANCE.activeCITs == null) + return; + + BakedModel citModel = CITResewn.INSTANCE.activeCITs.getItemModel(stack, cir.getReturnValue(), world, entity); + if (citModel != null) + cir.setReturnValue(citModel); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/JsonUnbakedModelAccessor.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/JsonUnbakedModelAccessor.java new file mode 100644 index 0000000..aa582bf --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/JsonUnbakedModelAccessor.java @@ -0,0 +1,22 @@ +package shcm.shsupercm.fabric.citresewn.mixin.core; + +import com.mojang.datafixers.util.Either; +import net.minecraft.client.render.model.json.JsonUnbakedModel; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(JsonUnbakedModel.class) +public interface JsonUnbakedModelAccessor { + @Accessor + Map> getTextureMap(); + + @Accessor + Identifier getParentId(); + + @Accessor + void setParentId(Identifier parentId); +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/ModelLoaderMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/ModelLoaderMixin.java new file mode 100644 index 0000000..0ece247 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/ModelLoaderMixin.java @@ -0,0 +1,185 @@ +package shcm.shsupercm.fabric.citresewn.mixin.core; + +import com.mojang.datafixers.util.Either; +import net.minecraft.client.render.model.*; +import net.minecraft.client.render.model.json.JsonUnbakedModel; +import net.minecraft.client.texture.TextureManager; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; +import org.apache.commons.io.IOUtils; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.ActiveCITs; +import shcm.shsupercm.fabric.citresewn.CITResewn; +import shcm.shsupercm.fabric.citresewn.config.CITResewnConfig; +import shcm.shsupercm.fabric.citresewn.pack.CITParser; +import shcm.shsupercm.fabric.citresewn.pack.ResewnItemModelIdentifier; +import shcm.shsupercm.fabric.citresewn.pack.ResewnTextureIdentifier; +import shcm.shsupercm.fabric.citresewn.pack.cits.CIT; +import shcm.shsupercm.fabric.citresewn.pack.cits.CITItem; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +import static shcm.shsupercm.fabric.citresewn.CITResewn.info; + +@Mixin(ModelLoader.class) +public abstract class ModelLoaderMixin { + @Shadow @Final private ResourceManager resourceManager; + @Shadow @Final private Set modelsToLoad; + @Shadow @Final private Map unbakedModels; + @Shadow @Final private Map modelsToBake; + @Shadow @Final private Map bakedModels; + @Shadow protected abstract JsonUnbakedModel loadModelFromJson(Identifier id) throws IOException; + + private Map citOverrideCacheMap = new HashMap<>(); + + @Inject(method = "addModel", at = @At("TAIL")) + public void loadCIT(ModelIdentifier eventModelId, CallbackInfo ci) { if (eventModelId != ModelLoader.MISSING_ID) return; + if (CITResewn.INSTANCE.activeCITs != null) { + info("Clearing active CITs.."); + CITResewn.INSTANCE.activeCITs.dispose(); + CITResewn.INSTANCE.activeCITs = null; + } + + if (!CITResewnConfig.INSTANCE().enabled) + return; + + info("Loading CIT Resewn.."); + + info("Parsing CITs..."); + Collection parsed = CITParser.parse(resourceManager.streamResourcePacks().collect(Collectors.toCollection(ArrayList::new))); + + if (parsed.size() > 0) { + info("Loading CITItem models.."); + for (CIT cit : parsed) + if (cit instanceof CITItem citItem) { + try { + citItem.loadUnbakedAssets(resourceManager); + + for (JsonUnbakedModel unbakedModel : citItem.unbakedAssets.values()) { + ResewnItemModelIdentifier id = new ResewnItemModelIdentifier(unbakedModel.id); + this.unbakedModels.put(id, unbakedModel); + this.modelsToLoad.addAll(unbakedModel.getModelDependencies()); + this.modelsToBake.put(id, unbakedModel); + } + } catch (Exception e) { + CITResewn.logErrorLoading(e.getMessage()); + } + } + + info("Activating CITs..."); + CITResewn.INSTANCE.activeCITs = new ActiveCITs(parsed); + } else + info("No cit packs found."); + } + + @Inject(method = "bake", at = @At("RETURN")) + public void onBake(Identifier id, ModelBakeSettings settings, CallbackInfoReturnable cir) { + if (CITResewn.INSTANCE.activeCITs == null) + return; + + this.citOverrideCacheMap.put(id, cir.getReturnValue()); + } + + @Inject(method = "upload", at = @At("RETURN")) + public void linkBakedModels(TextureManager textureManager, Profiler profiler, CallbackInfoReturnable cir) { + if (CITResewn.INSTANCE.activeCITs == null) + return; + + profiler.push("citresewn_linking"); + info("Linking baked models to CITItems..."); + + if (CITResewn.INSTANCE.activeCITs != null) { + for (CITItem citItem : CITResewn.INSTANCE.activeCITs.citItems.values().stream().flatMap(Collection::stream).distinct().collect(Collectors.toList())) { + for (Map.Entry citModelEntry : citItem.unbakedAssets.entrySet()) { + if (citModelEntry.getKey() == null) { + citItem.bakedModel = this.bakedModels.get(new ResewnItemModelIdentifier(citModelEntry.getValue().id)); + } else { + if (citItem.subItems == null) + citItem.subItems = new HashMap<>(); + + BakedModel override = citOverrideCacheMap.get(citModelEntry.getKey()); + + if (override == null) + override = citOverrideCacheMap.get(new ModelIdentifier(citModelEntry.getKey().getNamespace(), citModelEntry.getKey().getPath().substring(5), "inventory")); + + if (override != null) + citItem.subItems.put(override, this.bakedModels.get(new ResewnItemModelIdentifier(citModelEntry.getValue().id))); + else { + CITResewn.logErrorLoading("Skipping sub cit: No such sub item model \"" + citModelEntry.getKey().getPath().substring(5) + "\" in " + citItem.pack.resourcePack.getName() + " -> " + citItem.propertiesIdentifier.getPath()); + } + } + } + citItem.unbakedAssets = null; + } + } + + this.citOverrideCacheMap = null; + + profiler.pop(); + } + + + @Inject(method = "loadModelFromJson", cancellable = true, at = @At("HEAD")) + public void forceLiteralResewnModelIdentifier(Identifier id, CallbackInfoReturnable cir) { + if (id instanceof ResewnItemModelIdentifier) { + InputStream is = null; + Resource resource = null; + try { + JsonUnbakedModel json = JsonUnbakedModel.deserialize(IOUtils.toString(is = (resource = resourceManager.getResource(id)).getInputStream(), StandardCharsets.UTF_8)); + json.id = id.toString(); + json.id = json.id.substring(0, json.id.length() - 5); + + ((JsonUnbakedModelAccessor) json).getTextureMap().replaceAll((layer, original) -> { + Optional left = original.left(); + if (left.isPresent()) { + String originalPath = left.get().getTextureId().getPath(); + String[] split = originalPath.split("/"); + if (originalPath.startsWith("./") || (split.length > 2 && split[1].equals("cit"))) { + Identifier resolvedIdentifier = CIT.resolvePath(id, originalPath, ".png", identifier -> resourceManager.containsResource(identifier)); + if (resolvedIdentifier != null) + return Either.left(new SpriteIdentifier(left.get().getAtlasId(), new ResewnTextureIdentifier(resolvedIdentifier))); + } + } + return original; + }); + + Identifier parentId = ((JsonUnbakedModelAccessor) json).getParentId(); + if (parentId != null) { + String[] parentIdPathSplit = parentId.getPath().split("/"); + if (parentId.getPath().startsWith("./") || (parentIdPathSplit.length > 2 && parentIdPathSplit[1].equals("cit"))) { + parentId = CIT.resolvePath(id, parentId.getPath(), ".json", identifier -> resourceManager.containsResource(identifier)); + if (parentId != null) + ((JsonUnbakedModelAccessor) json).setParentId(new ResewnItemModelIdentifier(parentId)); + } + } + + cir.setReturnValue(json); + } catch (Exception ignored) { + } finally { + IOUtils.closeQuietly(is, resource); + } + } + } + + @Redirect(method = "loadModelFromJson", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;")) + public Resource getResource(ResourceManager resourceManager, Identifier id) throws IOException { + if (id.getPath().endsWith(".json.json") && id.getPath().contains("cit")) + return resourceManager.getResource(new Identifier(id.getNamespace(), id.getPath().substring(7, id.getPath().length() - 5))); + return resourceManager.getResource(id); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/NbtCompoundAccessor.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/NbtCompoundAccessor.java new file mode 100644 index 0000000..8ced305 --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/NbtCompoundAccessor.java @@ -0,0 +1,14 @@ +package shcm.shsupercm.fabric.citresewn.mixin.core; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(NbtCompound.class) +public interface NbtCompoundAccessor { + @Accessor + Map getEntries(); +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/SpriteAtlasTextureMixin.java b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/SpriteAtlasTextureMixin.java new file mode 100644 index 0000000..8cc195b --- /dev/null +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/mixin/core/SpriteAtlasTextureMixin.java @@ -0,0 +1,18 @@ +package shcm.shsupercm.fabric.citresewn.mixin.core; + +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.pack.ResewnTextureIdentifier; + +@Mixin(SpriteAtlasTexture.class) +public class SpriteAtlasTextureMixin { + @Inject(method = "getTexturePath", cancellable = true, at = @At("HEAD")) + public void forceLiteralResewnTextureIdentifier(Identifier id, CallbackInfoReturnable cir) { + if (id instanceof ResewnTextureIdentifier) + cir.setReturnValue(id); + } +} diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnItemModelIdentifier.java b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnItemModelIdentifier.java index baa1018..c531983 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnItemModelIdentifier.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnItemModelIdentifier.java @@ -1,10 +1,11 @@ package shcm.shsupercm.fabric.citresewn.pack; import net.minecraft.util.Identifier; +import shcm.shsupercm.fabric.citresewn.mixin.core.ModelLoaderMixin; /** * Marks models as cit item models. - * @see shcm.shsupercm.fabric.citresewn.mixin.ModelLoaderMixin + * @see ModelLoaderMixin */ public class ResewnItemModelIdentifier extends Identifier { public ResewnItemModelIdentifier(String id) { diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnTextureIdentifier.java b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnTextureIdentifier.java index 4a13bc2..033c567 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnTextureIdentifier.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/ResewnTextureIdentifier.java @@ -1,10 +1,11 @@ package shcm.shsupercm.fabric.citresewn.pack; import net.minecraft.util.Identifier; +import shcm.shsupercm.fabric.citresewn.mixin.core.SpriteAtlasTextureMixin; /** * Marks path identifiers as forced literal texture paths. - * @see shcm.shsupercm.fabric.citresewn.mixin.SpriteAtlasTextureMixin + * @see SpriteAtlasTextureMixin */ public class ResewnTextureIdentifier extends Identifier { public ResewnTextureIdentifier(Identifier identifier) { diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java index 5c0bcf7..e618a6f 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CIT.java @@ -6,8 +6,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.*; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourceType; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.Pair; @@ -15,7 +13,7 @@ import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import org.apache.commons.lang3.StringEscapeUtils; import shcm.shsupercm.fabric.citresewn.ex.CITParseException; -import shcm.shsupercm.fabric.citresewn.mixin.NbtCompoundAccessor; +import shcm.shsupercm.fabric.citresewn.mixin.core.NbtCompoundAccessor; import shcm.shsupercm.fabric.citresewn.pack.CITPack; import java.util.*; diff --git a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CITItem.java b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CITItem.java index 68eccea..7df8a17 100644 --- a/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CITItem.java +++ b/src/main/java/shcm/shsupercm/fabric/citresewn/pack/cits/CITItem.java @@ -20,7 +20,7 @@ import org.apache.commons.io.IOUtils; import shcm.shsupercm.fabric.citresewn.CITResewn; import shcm.shsupercm.fabric.citresewn.ex.CITLoadException; import shcm.shsupercm.fabric.citresewn.ex.CITParseException; -import shcm.shsupercm.fabric.citresewn.mixin.JsonUnbakedModelAccessor; +import shcm.shsupercm.fabric.citresewn.mixin.core.JsonUnbakedModelAccessor; import shcm.shsupercm.fabric.citresewn.pack.CITPack; import shcm.shsupercm.fabric.citresewn.pack.ResewnItemModelIdentifier; import shcm.shsupercm.fabric.citresewn.pack.ResewnTextureIdentifier; -- cgit