Update mod version and add Mixin support

This commit is contained in:
2026-01-06 20:20:55 +01:00
parent 0d87401849
commit f8df852136
9 changed files with 158 additions and 59 deletions
@@ -1,6 +1,5 @@
package net.fretux.mindmotion.client.effects;
import io.redspace.ironsspellbooks.api.registry.AttributeRegistry;
import net.fretux.mindmotion.ConfigMM;
import net.fretux.mindmotion.player.PlayerCapabilityProvider;
import net.minecraft.world.entity.ai.attributes.Attribute;
@@ -9,38 +8,65 @@ import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.fml.ModList;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.UUID;
public final class IronsSpellbooksCompatMM {
private static final UUID TEMPO_MANA_REGEN_UUID =
UUID.fromString("de4f16ad-73b3-4b99-bf77-44c9878222aa");
private static final String IRONS_MODID = "irons_spellbooks";
private static final String ATTR_REGISTRY_CLASS = "io.redspace.ironsspellbooks.api.registry.AttributeRegistry";
private static final String MANA_REGEN_FIELD = "MANA_REGEN";
private static boolean resolved = false;
private static boolean available = false;
private static Object manaRegenHolder = null;
private static Method holderGetMethod = null;
private IronsSpellbooksCompatMM() {
}
public static int getTempoPerPercent() {
return ConfigMM.COMMON.TEMPO_PER_MANA_REGEN_PERCENT.get();
}
private static final UUID TEMPO_MANA_REGEN_UUID =
UUID.fromString("de4f16ad-73b3-4b99-bf77-44c9878222aa");
private IronsSpellbooksCompatMM() {}
public static boolean isLoaded() {
return ModList.get().isLoaded("irons_spellbooks");
return ModList.get().isLoaded(IRONS_MODID);
}
public static void applyTempo(Player player) {
if (!isLoaded()) return;
resolveOnce();
if (!available) return;
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempoCap -> {
int tempo = tempoCap.getTempo();
applyTempoToManaRegen(player, tempo);
});
}
private static void resolveOnce() {
if (resolved) return;
resolved = true;
try {
Class<?> attrReg = Class.forName(ATTR_REGISTRY_CLASS);
Field manaRegenField = attrReg.getField(MANA_REGEN_FIELD);
manaRegenHolder = manaRegenField.get(null);
if (manaRegenHolder == null) return;
holderGetMethod = manaRegenHolder.getClass().getMethod("get");
available = true;
} catch (Throwable t) {
available = false;
}
}
public static void applyTempoToManaRegen(Player player, int tempo) {
Attribute manaRegenAttr = (Attribute) AttributeRegistry.MANA_REGEN.get();
if (!available) return;
Attribute manaRegenAttr = getManaRegenAttribute();
if (manaRegenAttr == null) return;
AttributeInstance inst = player.getAttribute(manaRegenAttr);
if (inst == null) return;
inst.removeModifier(TEMPO_MANA_REGEN_UUID);
if (tempo <= 0) {
return;
}
if (tempo <= 0) return;
double bonusPercent = (double) tempo / getTempoPerPercent();
double multiplier = bonusPercent / 100.0;
inst.addTransientModifier(new AttributeModifier(
@@ -50,4 +76,13 @@ public final class IronsSpellbooksCompatMM {
AttributeModifier.Operation.MULTIPLY_BASE
));
}
private static Attribute getManaRegenAttribute() {
try {
Object attrObj = holderGetMethod.invoke(manaRegenHolder);
return (attrObj instanceof Attribute a) ? a : null;
} catch (Throwable t) {
return null;
}
}
}
@@ -1,8 +1,10 @@
package net.fretux.mindmotion.client.effects;
import com.mojang.logging.LogUtils;
import net.fretux.mindmotion.ConfigMM;
import net.fretux.mindmotion.client.ClientData;
import net.fretux.mindmotion.client.shader.VentShaderHandler;
import net.fretux.mindmotion.mixin.PostChainAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.renderer.PostPass;
@@ -13,29 +15,34 @@ import net.minecraftforge.client.event.RenderLevelStageEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import org.slf4j.Logger;
import java.lang.reflect.Field;
import java.util.List;
@Mod.EventBusSubscriber(modid = "mindmotion", value = Dist.CLIENT)
@Mod.EventBusSubscriber(modid = "mindmotion", value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class SanityShaderHandler {
private static final ResourceLocation DESAT_EFFECT =
new ResourceLocation("mindmotion", "shaders/post/desaturate.json");
ResourceLocation.fromNamespaceAndPath("mindmotion", "shaders/post/desaturate.json");
private static float currentStrength = 0f;
private static Field passesField;
private static final Logger LOGGER = LogUtils.getLogger();
private static final Field PASSES_FIELD =
ObfuscationReflectionHelper.findField(PostChain.class, "f_110009_");
private static List<PostPass> getPasses(PostChain chain) throws IllegalAccessException, NoSuchFieldException {
if (passesField == null) {
passesField = PostChain.class.getDeclaredField("passes");
passesField.setAccessible(true);
@SuppressWarnings("unchecked")
private static List<PostPass> safeGetPasses(PostChain chain) {
try {
return (List<PostPass>) PASSES_FIELD.get(chain);
} catch (IllegalAccessException e) {
LOGGER.error("Failed to access PostChain.passes", e);
return List.of();
}
@SuppressWarnings("unchecked")
List<PostPass> passes = (List<PostPass>) passesField.get(chain);
return passes;
}
@SubscribeEvent
public static void onRenderWorld(RenderLevelStageEvent event) {
Minecraft mc = Minecraft.getInstance();
@@ -48,6 +55,7 @@ public class SanityShaderHandler {
float desatMultiplier = ConfigMM.CLIENT.SANITY_DESAT_MULTIPLIER.get().floatValue();
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_LEVEL) return;
if (mc.player == null || mc.level == null) return;
LOGGER.debug("SanityShaderHandler tick stage={}", event.getStage());
float sanity = ClientData.SANITY;
float insanity = ClientData.INSANITY;
float maxSanity = ClientData.MAX_SANITY;
@@ -71,15 +79,34 @@ public class SanityShaderHandler {
if (mc.gameRenderer.currentEffect() == null) {
try {
mc.gameRenderer.loadEffect(DESAT_EFFECT);
PostChain chain = mc.gameRenderer.currentEffect();
LOGGER.info("Loaded post chain = {}", chain != null);
if (chain != null) {
try {
for (PostPass pass : safeGetPasses(chain)) {
EffectInstance fx = pass.getEffect();
LOGGER.info("pass fx={}", fx != null ? fx.getName() : "null");
if (fx != null) {
LOGGER.info(" Desat uniform={}", fx.getUniform("Desat") != null);
}
}
} catch (Throwable t) {
LOGGER.error("Failed to read PostChain passes via reflection", t);
}
}
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("Failed to read PostChain passes via reflection", e);
return;
}
}
PostChain chain = mc.gameRenderer.currentEffect();
LOGGER.info("effect class={}, accessorApplied={}",
chain == null ? "null" : chain.getClass().getName(),
chain instanceof PostChainAccessor
);
if (chain == null) return;
try {
for (PostPass pass : getPasses(chain)) {
for (PostPass pass : safeGetPasses(chain)) {
EffectInstance effect = pass.getEffect();
if (effect == null) continue;
var uDesat = effect.getUniform("Desat");
@@ -144,7 +171,7 @@ public class SanityShaderHandler {
}
}
} catch (Exception e) {
e.printStackTrace();
LOGGER.info("Error loading post chain{}", e.getMessage());
}
}
@@ -0,0 +1,14 @@
package net.fretux.mindmotion.mixin;
import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.renderer.PostPass;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(PostChain.class)
public interface PostChainAccessor {
@Accessor("passes")
List<PostPass> mindmotion$getPasses();
}