diff options
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/citresewn/java/ConditionDirectAccessHelper.kt | 59 | ||||
-rw-r--r-- | src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java | 123 |
2 files changed, 182 insertions, 0 deletions
diff --git a/src/compat/citresewn/java/ConditionDirectAccessHelper.kt b/src/compat/citresewn/java/ConditionDirectAccessHelper.kt new file mode 100644 index 0000000..af97a40 --- /dev/null +++ b/src/compat/citresewn/java/ConditionDirectAccessHelper.kt @@ -0,0 +1,59 @@ +package moe.nea.firmament.compat.citresewn + +import java.lang.invoke.MethodHandles +import java.util.function.BiPredicate +import java.util.function.Function +import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionNBT + +object ConditionNBTMixin { + class Helper<StringMatcher> { + // TODO: make lambdametafactory work by way of modifying the actual modifiers + + val stringMatcherType = ConditionNBT::class.java.getDeclaredField("matchString").type + + val accessMatcher = run { + val matchStringF = ConditionNBT::class.java.getDeclaredField("matchString"); + matchStringF.isAccessible = true + val l = MethodHandles.privateLookupIn(ConditionNBT::class.java, MethodHandles.lookup()) +// val mt = MethodType.methodType(stringMatcherType, ConditionNBT::class.java) +// val callsite = LambdaMetafactory.metafactory( +// l, "apply", +// MethodType.methodType(Function::class.java), +// MethodType.methodType(java.lang.Object::class.java, java.lang.Object::class.java), +// l.unreflectGetter(matchStringF), +// mt +// ) + val getter = l.unreflectGetter(matchStringF) + Function<ConditionNBT, StringMatcher> { getter.invoke(it) as StringMatcher } + } + val directCaller = run { + val matchM = stringMatcherType.getDeclaredMethod("matches", String::class.java); + matchM.isAccessible = true + val l = MethodHandles.privateLookupIn(ConditionNBT::class.java, MethodHandles.lookup()) +// val mt = MethodType.methodType(java.lang.Boolean.TYPE, stringMatcherType, String::class.java) +// val callsite = LambdaMetafactory.metafactory( +// l, "test", +// MethodType.methodType(BiPredicate::class.java), +// mt, +// l.unreflect(matchM), +// mt +// ) + val func = l.unreflect(matchM) + BiPredicate<StringMatcher, String> { a, b -> func.invoke(a, b) as Boolean } + } + + fun test(condition: ConditionNBT, text: String): Boolean { + return directCaller.test(accessMatcher.apply(condition), text) as Boolean + } + } + + val helper = Helper<Any>() + + @JvmStatic + fun invokeDirectConditionNBTStringMatch( + nbt: ConditionNBT, + text: String, + ): Boolean { + return helper.test(nbt, text) + } +} diff --git a/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java b/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java new file mode 100644 index 0000000..0743d40 --- /dev/null +++ b/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java @@ -0,0 +1,123 @@ +package moe.nea.firmament.mixins.compat.citresewn; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; +import moe.nea.firmament.compat.citresewn.ConditionNBTMixin; +import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; +import net.minecraft.component.ComponentType; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionComponents; +import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionNBT; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyKey; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; + +// People are complaining but this really is not my place to fix things + +@Mixin(ConditionComponents.class) +@Pseudo +public class MixinConditionComponents { + @Shadow + private ComponentType<?> componentType; + + @Shadow(remap = false) + private ConditionNBT fallbackNBTCheck; + @Unique + private String[] pathCheck; + @Unique + private int loreInt = -1; + + @Inject(method = "load", at = @At("HEAD"), remap = false) + public void addExtraAttributeSupport(PropertyKey key, PropertyValue value, PropertyGroup properties, CallbackInfo ci, + @Local(argsOnly = true) LocalRef<PropertyKey> keyRef, + @Local(argsOnly = true) LocalRef<PropertyValue> valueRef) { + if (!CustomSkyBlockTextures.TConfig.INSTANCE.getEnableLegacyCIT()) return; + if (!"nbt".equals(key.path())) return; + if (!value.keyMetadata().startsWith("ExtraAttributes.")) return; + keyRef.set(new PropertyKey(key.namespace(), "component")); + valueRef.set(new PropertyValue( + "minecraft:custom_data" + value.keyMetadata().substring("ExtraAttributes".length()), + value.value(), + value.separator(), + value.position(), + value.propertiesIdentifier(), + value.packName() + )); + CITResewn.logWarnLoading(properties.messageWithDescriptorOf("NBT condition is not supported since 1.21. THIS IS A FIRMAMENT SPECIAL FEATURE ALLOWING YOU TO CONTINUE TO USE nbt.ExtraAttributes.* PROPERTIES FOR A LIMITED TIME! UPDATE YOUR .PROPERTIES FILES OR SWITCH TO FIRMAMENT CIT (https://github.com/FirmamentMC/CitToFirm)", + value.position())); + } + + @Inject(method = "load", + at = @At(value = "INVOKE", remap = false, target = "Lshcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionNBT;loadNbtCondition(Lshcm/shsupercm/fabric/citresewn/pack/format/PropertyValue;Lshcm/shsupercm/fabric/citresewn/pack/format/PropertyGroup;[Ljava/lang/String;Ljava/lang/String;)V"), + remap = false) + private void onLoadSavePath(PropertyKey key, PropertyValue value, PropertyGroup properties, CallbackInfo ci, + @Local String[] path) { + this.pathCheck = path; + this.loreInt = -1; + } + + @Unique + private boolean matchStringDirect(String directString, CITContext context) { + return ConditionNBTMixin.invokeDirectConditionNBTStringMatch(fallbackNBTCheck, directString); + } + + @WrapOperation(method = "test", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;encodeStart(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;"), remap = false) + DataResult fastPathUnsafeNbtComponent( + Codec instance, + DynamicOps dynamicOps, + Object o, + Operation<DataResult> original) { + if (o instanceof NbtComponent nbtComponent) { + return DataResult.success(nbtComponent.getNbt()); + } + return original.call(instance, dynamicOps, o); + } + + @Inject(method = "test", at = @At("HEAD"), cancellable = true, remap = false) + void fastPathDisplayName(CITContext context, CallbackInfoReturnable<Boolean> cir) { + if (this.componentType == DataComponentTypes.CUSTOM_NAME && pathCheck.length == 0) { + var displayName = context.stack.getComponents().get(DataComponentTypes.CUSTOM_NAME); + if (displayName != null) { + cir.setReturnValue(matchStringDirect((displayName.getString()), context)); + } + } + if (this.componentType == DataComponentTypes.LORE && pathCheck.length == 1) { + var lore = context.stack.getComponents().get(DataComponentTypes.LORE); + if (lore != null) { + var loreLines = lore.lines(); + if (pathCheck[0].equals("*")) { + for (var loreLine : loreLines) { + if (matchStringDirect((loreLine.getString()), context)) { + cir.setReturnValue(true); + return; + } + } + cir.setReturnValue(false); + } else { + if (loreInt < 0) + loreInt = Integer.parseInt(pathCheck[0]); + cir.setReturnValue(0 <= loreInt && loreInt < loreLines.size() && + matchStringDirect((loreLines.get(loreInt).getString()), context)); + } + } + } + } + + +} |