Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add task to generate finalizeSpawn MethodRedirector coremod targets #1756

Merged
merged 4 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check-local-changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
run: ./gradlew generatePackageInfos

- name: Gen patches and ATs
run: ./gradlew :neoforge:genPatches :neoforge:generateAccessTransformers
run: ./gradlew :neoforge:genPatches :neoforge:generateAccessTransformers :neoforge:generateFinalizeSpawnTargets
Matyrobbrt marked this conversation as resolved.
Show resolved Hide resolved

- name: Run datagen with Gradle
run: ./gradlew :neoforge:runData :tests:runData
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package net.neoforged.neodev;

import com.google.gson.GsonBuilder;
import net.neoforged.neodev.utils.AsmUtils;
import net.neoforged.neodev.utils.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
* This task is used to generate targets for the finalizeSpawn MethodRedirector coremod.
*/
public abstract class GenerateFinalizeSpawnTargets extends DefaultTask {
@InputFile
public abstract RegularFileProperty getInput();

@OutputFile
public abstract RegularFileProperty getOutput();

@TaskAction
public void exec() throws IOException {
var visitor = new Visitor();
AsmUtils.visitAllClasses(
getInput().getAsFile().get(),
visitor,
ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);

var classList = List.copyOf(visitor.matchedClasses);

FileUtils.writeStringSafe(
getOutput().getAsFile().get().toPath(),
new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create().toJson(classList),
StandardCharsets.UTF_8);
}

static class Visitor extends ClassVisitor {
final Set<String> matchedClasses = new TreeSet<>();
String currentClass = null;

protected Visitor() {
super(Opcodes.ASM9);
}

@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
currentClass = name;
}

@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
// Ignore these classes as we special case them
if (currentClass.equals("net/minecraft/world/level/BaseSpawner")
|| currentClass.equals("net/minecraft/world/level/block/entity/trialspawner/TrialSpawner")) {
return null;
}

return new MethodVisitor(api) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
if (opcode == Opcodes.INVOKEVIRTUAL
&& name.equals("finalizeSpawn")
&& descriptor.equals("(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;")) {
matchedClasses.add(currentClass);
}
}
};
}
}
}
27 changes: 27 additions & 0 deletions buildSrc/src/main/java/net/neoforged/neodev/utils/AsmUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.neoforged.neodev.utils;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;

import java.io.File;
import java.io.IOException;
import java.util.zip.ZipFile;

public final class AsmUtils {
private AsmUtils() {}

public static void visitAllClasses(File jarFile, ClassVisitor visitor, int parsingOptions) throws IOException {
try (var zip = new ZipFile(jarFile)) {
var entries = zip.entries();
while (entries.hasMoreElements()) {
var next = entries.nextElement();
if (next.isDirectory() || !next.getName().endsWith(".class")) continue;

try (var in = zip.getInputStream(next)) {
var reader = new ClassReader(in);
reader.accept(visitor, parsingOptions);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.neoforged.neodev.utils.structure;

import net.neoforged.neodev.utils.AsmUtils;
import org.apache.commons.lang3.mutable.MutableInt;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
Expand All @@ -13,7 +14,6 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipFile;

public final class ClassStructureVisitor extends ClassVisitor {
private final Map<String, ClassInfo> classes;
Expand All @@ -26,19 +26,10 @@ private ClassStructureVisitor(Map<String, ClassInfo> classes) {

public static Map<String, ClassInfo> readJar(File file) throws IOException {
var map = new HashMap<String, ClassInfo>();
var visitor = new ClassStructureVisitor(map);
try (var zip = new ZipFile(file)) {
var entries = zip.entries();
while (entries.hasMoreElements()) {
var next = entries.nextElement();
if (next.isDirectory() || !next.getName().endsWith(".class")) continue;

try (var in = zip.getInputStream(next)) {
var reader = new ClassReader(in);
reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}
}
}
AsmUtils.visitAllClasses(
file,
new ClassStructureVisitor(map),
ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return map;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
[
"net/minecraft/server/commands/RaidCommand",
"net/minecraft/server/commands/SummonCommand",
"net/minecraft/world/entity/EntityType",
"net/minecraft/world/entity/ai/village/VillageSiege",
"net/minecraft/world/entity/animal/frog/Tadpole",
"net/minecraft/world/entity/animal/horse/SkeletonTrapGoal",
"net/minecraft/world/entity/monster/Evoker$EvokerSummonSpellGoal",
"net/minecraft/world/entity/monster/Spider",
"net/minecraft/world/entity/monster/Strider",
"net/minecraft/world/entity/monster/Zombie",
"net/minecraft/world/entity/monster/ZombieVillager",
"net/minecraft/world/entity/npc/CatSpawner",
"net/minecraft/world/entity/npc/Villager",
"net/minecraft/world/entity/raid/Raid",
"net/minecraft/world/level/NaturalSpawner",
"net/minecraft/world/level/levelgen/PatrolSpawner",
"net/minecraft/world/level/levelgen/PhantomSpawner",
"net/minecraft/world/level/levelgen/structure/structures/OceanMonumentPieces$OceanMonumentPiece",
"net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces$OceanRuinPiece",
"net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece",
"net/minecraft/world/level/levelgen/structure/structures/WoodlandMansionPieces$WoodlandMansionPiece",
"net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate"
"net/minecraft/server/commands/RaidCommand",
"net/minecraft/server/commands/SummonCommand",
"net/minecraft/world/entity/EntityType",
"net/minecraft/world/entity/ai/village/VillageSiege",
"net/minecraft/world/entity/animal/frog/Tadpole",
"net/minecraft/world/entity/animal/horse/SkeletonTrapGoal",
"net/minecraft/world/entity/monster/Evoker$EvokerSummonSpellGoal",
"net/minecraft/world/entity/monster/Spider",
"net/minecraft/world/entity/monster/Strider",
"net/minecraft/world/entity/monster/Zombie",
"net/minecraft/world/entity/monster/ZombieVillager",
"net/minecraft/world/entity/npc/CatSpawner",
"net/minecraft/world/entity/npc/Villager",
"net/minecraft/world/entity/raid/Raid",
"net/minecraft/world/level/NaturalSpawner",
"net/minecraft/world/level/levelgen/PatrolSpawner",
"net/minecraft/world/level/levelgen/PhantomSpawner",
"net/minecraft/world/level/levelgen/structure/structures/OceanMonumentPieces$OceanMonumentPiece",
"net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces$OceanRuinPiece",
"net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece",
"net/minecraft/world/level/levelgen/structure/structures/WoodlandMansionPieces$WoodlandMansionPiece",
"net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate"
]
8 changes: 8 additions & 0 deletions projects/neoforge/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import net.neoforged.jarcompatibilitychecker.gradle.JCCPlugin
import net.neoforged.jarcompatibilitychecker.gradle.CompatibilityTask
import net.neoforged.jarcompatibilitychecker.gradle.ProvideNeoForgeJarTask
import net.neoforged.neodev.GenerateFinalizeSpawnTargets

plugins {
id 'java-library'
Expand Down Expand Up @@ -222,6 +223,13 @@ generateAccessTransformers {
)
}

tasks.register("generateFinalizeSpawnTargets", GenerateFinalizeSpawnTargets.class) {
group generateAccessTransformers.group
description "Generate the targets for the finalizeSpawn MethodRedirector coremod"
input = generateAccessTransformers.input
output = rootProject.file("coremods/src/main/resources/net/neoforged/neoforge/coremods/finalize_spawn_targets.json")
}

tasks.withType(JavaCompile.class).configureEach {
// Increase memory used during compilation, to avoid OutOfMemoryErrors
options.forkOptions.memoryMaximumSize = '2g'
Expand Down
Loading