diff --git a/src/main/java/com/falsepattern/lib/mixin/v2/IMixinPlugin.java b/src/main/java/com/falsepattern/lib/mixin/v2/IMixinPlugin.java
new file mode 100644
index 0000000..0fd3343
--- /dev/null
+++ b/src/main/java/com/falsepattern/lib/mixin/v2/IMixinPlugin.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of FalsePatternLib.
+ *
+ * Copyright (C) 2022-2025 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * FalsePatternLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * FalsePatternLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FalsePatternLib. If not, see .
+ */
+
+package com.falsepattern.lib.mixin.v2;
+
+import com.gtnewhorizon.gtnhmixins.builders.IMixins;
+import lombok.val;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.Nullable;
+import org.spongepowered.asm.lib.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 interface IMixinPlugin & IMixins> extends IMixinConfigPlugin {
+ static Logger createLogger(String modName) {
+ return LogManager.getLogger(modName + " Mixin Loader");
+ }
+
+ Logger getLogger();
+
+ Class getMixinEnum();
+
+ @Override
+ default void onLoad(String mixinPackage) {}
+
+ @Override
+ default @Nullable String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ default boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ return true;
+ }
+
+ @Override
+ default void acceptTargets(Set myTargets, Set otherTargets) {}
+
+ @Override
+ default List getMixins() {
+ val logger = getLogger();
+ logger.info("Scanning mixins...");
+ try {
+ return IMixins.getMixins(getMixinEnum());
+ } finally {
+ logger.info("Mixins scanned.");
+ }
+ }
+
+ @Override
+ default void preApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) {}
+
+ @Override
+ default void postApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) {}
+}
diff --git a/src/main/java/com/falsepattern/lib/mixin/v2/MixinHelper.java b/src/main/java/com/falsepattern/lib/mixin/v2/MixinHelper.java
new file mode 100644
index 0000000..e89b847
--- /dev/null
+++ b/src/main/java/com/falsepattern/lib/mixin/v2/MixinHelper.java
@@ -0,0 +1,112 @@
+/*
+ * This file is part of FalsePatternLib.
+ *
+ * Copyright (C) 2022-2025 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * FalsePatternLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * FalsePatternLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FalsePatternLib. If not, see .
+ */
+
+package com.falsepattern.lib.mixin.v2;
+
+import com.gtnewhorizon.gtnhmixins.builders.IBaseTransformer;
+import com.gtnewhorizon.gtnhmixins.builders.ITargetMod;
+import com.gtnewhorizon.gtnhmixins.builders.MixinBuilder;
+import lombok.val;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.BooleanSupplier;
+
+public class MixinHelper {
+ public static @NotNull MixinBuilder builder(@NotNull SidedMixins @NotNull ... mixins) {
+ return builderImpl(null, null, mixins);
+ }
+
+ public static @NotNull MixinBuilder builder(@Nullable BooleanSupplier cond, @NotNull SidedMixins @NotNull ... mixins) {
+ return builderImpl(cond, null, mixins);
+ }
+
+ public static @NotNull MixinBuilder builder(@NotNull TaggedMod mod, @NotNull SidedMixins @NotNull ... mixins) {
+ return builderImpl(null, mods(mod), mixins);
+ }
+
+ public static @NotNull MixinBuilder builder(@NotNull TaggedMod @Nullable [] mods, @NotNull SidedMixins @NotNull ... mixins) {
+ return builderImpl(null, mods, mixins);
+ }
+
+ public static @NotNull MixinBuilder builder(@NotNull BooleanSupplier cond, @NotNull TaggedMod mod, @NotNull SidedMixins @NotNull ... mixins) {
+ return builderImpl(cond, mods(mod), mixins);
+ }
+
+ public static @NotNull MixinBuilder builder(@NotNull BooleanSupplier cond, @NotNull TaggedMod @NotNull [] mods, @NotNull SidedMixins @NotNull ... mixins) {
+ return builderImpl(cond, mods, mixins);
+ }
+
+ private static @NotNull MixinBuilder builderImpl(@Nullable BooleanSupplier cond, @NotNull TaggedMod @Nullable [] requiredMods, @NotNull SidedMixins @NotNull ... mixins) {
+ val builder = new MixinBuilder();
+ if (requiredMods != null) {
+ for (val mod : requiredMods) {
+ if (mod.require) {
+ builder.addRequiredMod(mod.mod);
+ } else {
+ builder.addExcludedMod(mod.mod);
+ }
+ }
+ }
+ for (val mixin : mixins) {
+ builder.addSidedMixins(mixin.side, mixin.mixins);
+ }
+ if (cond != null) {
+ builder.setApplyIf(cond::getAsBoolean);
+ }
+ return builder;
+ }
+
+ public static @NotNull SidedMixins common(@NotNull String @NotNull ... mixins) {
+ for (int i = 0; i < mixins.length; i++) {
+ mixins[i] = "common." + mixins[i];
+ }
+ return new SidedMixins(IBaseTransformer.Side.COMMON, mixins);
+ }
+
+ public static @NotNull SidedMixins client(@NotNull String @NotNull ... mixins) {
+ for (int i = 0; i < mixins.length; i++) {
+ mixins[i] = "client." + mixins[i];
+ }
+ return new SidedMixins(IBaseTransformer.Side.CLIENT, mixins);
+ }
+
+ public static @NotNull SidedMixins server(@NotNull String @NotNull ... mixins) {
+ for (int i = 0; i < mixins.length; i++) {
+ mixins[i] = "server." + mixins[i];
+ }
+ return new SidedMixins(IBaseTransformer.Side.SERVER, mixins);
+ }
+
+ public static @NotNull TaggedMod require(@NotNull ITargetMod mod) {
+ return new TaggedMod(true, mod);
+ }
+
+ public static @NotNull TaggedMod avoid(@NotNull ITargetMod mod) {
+ return new TaggedMod(false, mod);
+ }
+
+ public static @NotNull TaggedMod @NotNull [] mods(@NotNull TaggedMod @NotNull ... t) {
+ return t;
+ }
+
+}
diff --git a/src/main/java/com/falsepattern/lib/mixin/v2/SidedMixins.java b/src/main/java/com/falsepattern/lib/mixin/v2/SidedMixins.java
new file mode 100644
index 0000000..6acb9e4
--- /dev/null
+++ b/src/main/java/com/falsepattern/lib/mixin/v2/SidedMixins.java
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FalsePatternLib.
+ *
+ * Copyright (C) 2022-2025 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * FalsePatternLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * FalsePatternLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FalsePatternLib. If not, see .
+ */
+
+package com.falsepattern.lib.mixin.v2;
+
+import com.gtnewhorizon.gtnhmixins.builders.IBaseTransformer;
+import lombok.RequiredArgsConstructor;
+import org.jetbrains.annotations.NotNull;
+
+@RequiredArgsConstructor
+public class SidedMixins {
+ public final IBaseTransformer.@NotNull Side side;
+ public final @NotNull String @NotNull [] mixins;
+}
diff --git a/src/main/java/com/falsepattern/lib/mixin/v2/TaggedMod.java b/src/main/java/com/falsepattern/lib/mixin/v2/TaggedMod.java
new file mode 100644
index 0000000..ea029d4
--- /dev/null
+++ b/src/main/java/com/falsepattern/lib/mixin/v2/TaggedMod.java
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FalsePatternLib.
+ *
+ * Copyright (C) 2022-2025 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * FalsePatternLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * FalsePatternLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FalsePatternLib. If not, see .
+ */
+
+package com.falsepattern.lib.mixin.v2;
+
+import com.gtnewhorizon.gtnhmixins.builders.ITargetMod;
+import lombok.RequiredArgsConstructor;
+import org.jetbrains.annotations.NotNull;
+
+@RequiredArgsConstructor
+public class TaggedMod {
+ public final boolean require;
+ public final @NotNull ITargetMod mod;
+}
\ No newline at end of file
diff --git a/src/main/java/com/falsepattern/lib/mixin/v2/TargetMod.java b/src/main/java/com/falsepattern/lib/mixin/v2/TargetMod.java
new file mode 100644
index 0000000..6065453
--- /dev/null
+++ b/src/main/java/com/falsepattern/lib/mixin/v2/TargetMod.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of FalsePatternLib.
+ *
+ * Copyright (C) 2022-2025 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * FalsePatternLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * FalsePatternLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FalsePatternLib. If not, see .
+ */
+
+package com.falsepattern.lib.mixin.v2;
+
+import com.gtnewhorizon.gtnhmixins.builders.ITargetMod;
+import com.gtnewhorizon.gtnhmixins.builders.TargetModBuilder;
+import lombok.Getter;
+import org.intellij.lang.annotations.Language;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.Consumer;
+
+public class TargetMod implements ITargetMod {
+ @Getter
+ private final TargetModBuilder builder;
+
+ private final String name;
+
+ public TargetMod(@NotNull String name, @Language(value = "JAVA", prefix = "import ", suffix = ";") @NotNull String className) {
+ this(name, className, null);
+ }
+
+ public TargetMod(@NotNull String name, @Language(value = "JAVA", prefix = "import ", suffix = ";") @NotNull String className, @Nullable Consumer cfg) {
+ this.name = name;
+ builder = new TargetModBuilder();
+ builder.setTargetClass(className);
+ if (cfg != null) {
+ cfg.accept(builder);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/src/main/java/com/falsepattern/lib/mixin/v2/package-info.java b/src/main/java/com/falsepattern/lib/mixin/v2/package-info.java
new file mode 100644
index 0000000..c655b20
--- /dev/null
+++ b/src/main/java/com/falsepattern/lib/mixin/v2/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * This file is part of FalsePatternLib.
+ *
+ * Copyright (C) 2022-2025 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * FalsePatternLib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, only version 3 of the License.
+ *
+ * FalsePatternLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FalsePatternLib. If not, see .
+ */
+
+/**
+ * @since 1.9.0
+ */
+@ApiStatus.Experimental
+package com.falsepattern.lib.mixin.v2;
+
+import org.jetbrains.annotations.ApiStatus;
\ No newline at end of file