Skip to content

Commit

Permalink
Add ModMixin to make it so that mixins for mod compats don't throw er…
Browse files Browse the repository at this point in the history
…rors because they won't load if the mod isn't installed
  • Loading branch information
Bennyboy1695 committed Oct 1, 2024
1 parent aa880c5 commit 161df8a
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.copycatsplus.copycats.foundation.annotation;

import com.copycatsplus.copycats.compat.Mods;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/*
* This annotation is used to make mixins only enable themselves if the required mod(s) are installed
*/

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModMixin {

Mods[] requiredMods();

boolean applyIfPresent() default true;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
package com.copycatsplus.copycats.mixin;

import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.llamalad7.mixinextras.MixinExtrasBootstrap;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.util.Annotations;

import java.io.IOException;
import java.util.List;
import java.util.Set;

public class MixinPlugin implements IMixinConfigPlugin {
public static final Logger LOGGER = LoggerFactory.getLogger("Copycats+ | MixinPlugin");
private boolean isFrameworkInstalled;

@Override
Expand All @@ -29,9 +39,34 @@ public String getRefMapperConfig() {

@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
try {
List<AnnotationNode> annotationNodes = MixinService.getService().getBytecodeProvider().getClassNode(mixinClassName).visibleAnnotations;
if (annotationNodes == null) return true;

boolean shouldApply = true;
for (AnnotationNode node : annotationNodes) {
if (node.desc.equals(Type.getDescriptor(ModMixin.class))) {
List<Mods> mods = Annotations.getValue(node, "requiredMods", true, Mods.class);
boolean applyIfPresent = Annotations.getValue(node, "applyIfPresent", Boolean.TRUE);
boolean anyModsLoaded = anyModsLoaded(mods);
shouldApply = anyModsLoaded == applyIfPresent;
LOGGER.debug("{} is {} being applied because the mod(s) {} are {} loaded", mixinClassName, shouldApply ? " " : " not ", mods, anyModsLoaded ? " " : " not ");
}
}
return shouldApply;
} catch (ClassNotFoundException | IOException e) {
LOGGER.error("An error occurred when checking if {} has the ModMixin annotation", mixinClassName, e);
}
return isFrameworkInstalled; // this makes sure that forge's helpful mods not found screen shows up
}

private static boolean anyModsLoaded(List<Mods> mods) {
for (Mods mod : mods) {
if (mod.isLoaded) return true;
}
return false;
}

@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.copycatsplus.copycats.mixin.compat.additionalplacements;

import com.copycatsplus.copycats.Copycats;
import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.firemerald.additionalplacements.common.ConfigCommon;
import net.minecraft.resources.ResourceLocation;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -14,6 +16,7 @@
* <p>
* Will appear to error but works and builds fine.
*/
@ModMixin(requiredMods = Mods.ADDITIONAL_PLACEMENTS)
@Pseudo
@Mixin(value = {ConfigCommon.class})
public class ConfigCommonMixin {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.copycatsplus.copycats.mixin.compat.additionalplacements;

import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.copycatsplus.copycats.foundation.copycat.ICopycatBlock;
import com.firemerald.additionalplacements.block.AdditionalPlacementBlock;
import net.minecraft.world.level.block.*;
Expand All @@ -11,6 +13,7 @@
/**
* Always report that our blocks have no extra states added by AdditionalPlacements.
*/
@ModMixin(requiredMods = Mods.ADDITIONAL_PLACEMENTS)
@Mixin(
value = {
AdditionalPlacementBlock.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.copycatsplus.copycats.mixin.compat.diagonalfences;

import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.copycatsplus.copycats.foundation.copycat.ICopycatBlock;
import net.minecraft.world.level.block.CrossCollisionBlock;
import net.minecraft.world.level.block.FenceBlock;
Expand All @@ -13,6 +15,7 @@
* <p>
* This patch has to be applied after Diagonal Fences modifies the FenceBlock class
*/
@ModMixin(requiredMods = Mods.DIAGONAL_FENCES)
@Mixin(value = FenceBlock.class, priority = 1100)
public abstract class FenceBlockMixin extends CrossCollisionBlock {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.copycatsplus.copycats.mixin.compat.radium;

import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.content.copycat.slab.CopycatSlabBlock;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.world.level.block.Block;
Expand All @@ -13,6 +15,7 @@
/**
* Make sure Radium's pathfinding algorithm considers slabs properly, since they do not extend from {@link net.minecraft.world.level.block.SlabBlock}.
*/
@ModMixin(requiredMods = Mods.INDIUM)
@Mixin(targets = "me.jellysquid.mods.lithium.common.ai.pathing.PathNodeDefaults")
@Pseudo
public class PathNodeDefaultsMixin {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.copycatsplus.copycats.mixin.compat.rubidium;

import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.copycatsplus.copycats.foundation.copycat.ICopycatBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
Expand All @@ -14,6 +16,7 @@
/**
* Makes sure that copycat blocks are not occluded by Rubidium
*/
@ModMixin(requiredMods = Mods.SODIUM)
@Mixin(targets = "me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache")
@Pseudo
public class BlockOcclusionCacheMixin {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.copycatsplus.copycats.mixin.compat.rubidium;

import com.copycatsplus.copycats.compat.Mods;
import com.copycatsplus.copycats.foundation.annotation.ModMixin;
import com.copycatsplus.copycats.foundation.copycat.multistate.MultiStateRenderManager;
import com.copycatsplus.copycats.foundation.copycat.multistate.MultiStateTextureAtlasSprite;
import me.jellysquid.mods.sodium.client.model.color.ColorProvider;
Expand All @@ -18,6 +20,7 @@
* <p>
* Rubidium compatible version of {@link com.copycatsplus.copycats.mixin.foundation.copycat.multistate.ModelBlockRendererMixin}.
*/
@ModMixin(requiredMods = Mods.SODIUM)
@Mixin(BlockRenderer.class)
@Pseudo
public class BlockRendererMixin {
Expand Down

0 comments on commit 161df8a

Please sign in to comment.