Skip to content

Commit 7437c08

Browse files
authored
Account for logical breaking change in ASMAPI.findFirstInstructionBefore() (#56)
Add new methods that include a boolean parameter for fixing the logic. This overrides the behavior imposed by CoreMods to fix the logic based on MC version.
1 parent 9478a16 commit 7437c08

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

src/main/java/net/minecraftforge/coremod/CoreModEngine.java

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package net.minecraftforge.coremod;
66

7+
import cpw.mods.modlauncher.Launcher;
78
import cpw.mods.modlauncher.api.*;
89
import net.minecraftforge.forgespi.coremod.*;
910
import org.apache.logging.log4j.LogManager;
@@ -51,6 +52,18 @@ public class CoreModEngine {
5152
"org.objectweb.asm.Label","org.objectweb.asm.Type",
5253
"org.objectweb.asm.TypePath","org.objectweb.asm.TypeReference"
5354
));
55+
56+
// this is enabled by FML in Minecraft 1.21.1 and earlier, but disabled in 1.21.3 and later
57+
// see ASMAPI.findFirstInstructionBefore for more details
58+
public static final boolean DO_NOT_FIX_INSNBEFORE;
59+
60+
static {
61+
var blackboardVar = Launcher.INSTANCE.blackboard().get(TypesafeMap.Key.getOrCreate(Launcher.INSTANCE.blackboard(), "coremods.use_old_findFirstInstructionBefore", Boolean.class));
62+
if (DO_NOT_FIX_INSNBEFORE = blackboardVar.isPresent() && blackboardVar.get()) {
63+
LOGGER.debug("CoreMods will preserve legacy behavior of ASMAPI.findFirstInstructionBefore for backwards-compatibility");
64+
}
65+
}
66+
5467
void loadCoreMod(ICoreModFile coremod) {
5568
// We have a factory per coremod, to provide namespace and functional isolation between coremods
5669
final ScriptEngine scriptEngine = NashornFactory.createEngine();

src/main/java/net/minecraftforge/coremod/api/ASMAPI.java

+42-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import cpw.mods.modlauncher.Launcher;
88
import cpw.mods.modlauncher.api.INameMappingService;
9+
import net.minecraftforge.coremod.CoreModEngine;
910
import net.minecraftforge.coremod.CoreModTracker;
1011
import org.jetbrains.annotations.Nullable;
1112
import org.objectweb.asm.Opcodes;
@@ -305,22 +306,60 @@ public static AbstractInsnNode findFirstInstructionAfter(MethodNode method, int
305306
* @param opCode the opcode to search for
306307
* @param startIndex the index at which to start searching (inclusive)
307308
* @return the found instruction node or null if none matched before the given startIndex
309+
*
310+
* @apiNote In Minecraft 1.21.1 and earlier, this method contains broken logic that ignores the {@code startIndex}
311+
* parameter and searches for the requested instruction at the end of the method. This behavior is preserved to
312+
* not disrupt older coremods. If you are on one of these older versions and need to use the fixed logic, please
313+
* use {@link #findFirstInstructionBefore(MethodNode, int, int, boolean)}.
308314
*/
309315
public static AbstractInsnNode findFirstInstructionBefore(MethodNode method, int opCode, int startIndex) {
310316
return findFirstInstructionBefore(method, opCode, null, startIndex);
311317
}
312318

319+
/**
320+
* Finds the first instruction with matching opcode before the given index in reverse search.
321+
*
322+
* @param method the method to search in
323+
* @param opCode the opcode to search for
324+
* @param startIndex the index at which to start searching (inclusive)
325+
* @param fixLogic whether to use the fixed logic for finding instructions before the given startIndex (true by
326+
* default on versions since 1.21.3, false otherwise)
327+
* @return the found instruction node or null if none matched before the given startIndex
328+
*/
329+
public static AbstractInsnNode findFirstInstructionBefore(MethodNode method, int opCode, int startIndex, boolean fixLogic) {
330+
return findFirstInstructionBefore(method, opCode, null, startIndex, fixLogic);
331+
}
332+
313333
/**
314334
* Finds the first instruction with matching opcode before the given index in reverse search
315335
*
316-
* @param method the method to search in
317-
* @param opCode the opcode to search for
336+
* @param method the method to search in
337+
* @param opCode the opcode to search for
318338
* @param startIndex the index at which to start searching (inclusive)
319339
* @return the found instruction node or null if none matched before the given startIndex
340+
*
341+
* @apiNote In Minecraft 1.21.1 and earlier, this method contains broken logic that ignores the {@code startIndex}
342+
* parameter and searches for the requested instruction at the end of the method. This behavior is preserved to
343+
* not disrupt older coremods. If you are on one of these older versions and need to use the fixed logic, please
344+
* use {@link #findFirstInstructionBefore(MethodNode, int, InsnType, int, boolean)}.
320345
*/
321346
public static AbstractInsnNode findFirstInstructionBefore(MethodNode method, int opCode, @Nullable InsnType type, int startIndex) {
347+
return findFirstInstructionBefore(method, opCode, type, startIndex, !CoreModEngine.DO_NOT_FIX_INSNBEFORE);
348+
}
349+
350+
/**
351+
* Finds the first instruction with matching opcode before the given index in reverse search
352+
*
353+
* @param method the method to search in
354+
* @param opCode the opcode to search for
355+
* @param startIndex the index at which to start searching (inclusive)
356+
* @param fixLogic whether to use the fixed logic for finding instructions before the given startIndex (true by
357+
* default on versions since 1.21.3, false otherwise)
358+
* @return the found instruction node or null if none matched before the given startIndex
359+
*/
360+
public static AbstractInsnNode findFirstInstructionBefore(MethodNode method, int opCode, @Nullable InsnType type, int startIndex, boolean fixLogic) {
322361
boolean checkType = type != null;
323-
for (int i = Math.min(method.instructions.size() - 1, startIndex); i >= 0; i--) {
362+
for (int i = fixLogic ? Math.min(method.instructions.size() - 1, startIndex) : startIndex; i >= 0; i--) {
324363
AbstractInsnNode ain = method.instructions.get(i);
325364
if (ain.getOpcode() == opCode) {
326365
if (!checkType || type.get() == ain.getType()) {

0 commit comments

Comments
 (0)