-
-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '1.21.1' into elements_model_root_xform
- Loading branch information
Showing
181 changed files
with
4,916 additions
and
3,199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
plugins { | ||
id 'java-library' | ||
id 'com.diffplug.spotless' | ||
id 'net.neoforged.licenser' | ||
id 'neoforge.formatting-conventions' | ||
} | ||
|
||
repositories { | ||
maven { url = 'https://maven.neoforged.net/releases' } | ||
maven { | ||
name 'Mojang' | ||
url 'https://libraries.minecraft.net' | ||
} | ||
mavenCentral() | ||
} | ||
|
||
jar { | ||
manifest { | ||
attributes( | ||
"Automatic-Module-Name": "neoforge.coremods", | ||
FMLModType: "LIBRARY", | ||
) | ||
} | ||
} | ||
|
||
java { | ||
toolchain { | ||
languageVersion.set(JavaLanguageVersion.of(project.java_version)) | ||
} | ||
} | ||
|
||
dependencies { | ||
compileOnly "org.jetbrains:annotations:${project.jetbrains_annotations_version}" | ||
compileOnly "com.google.code.gson:gson:${gson_version}" | ||
compileOnly "org.slf4j:slf4j-api:${slf4j_api_version}" | ||
compileOnly "net.neoforged.fancymodloader:loader:${project.fancy_mod_loader_version}" | ||
} | ||
|
||
license { | ||
header = rootProject.file('codeformat/HEADER.txt') | ||
include '**/*.java' | ||
} | ||
|
||
tasks.withType(JavaCompile).configureEach { | ||
options.encoding = 'UTF-8' | ||
} |
79 changes: 79 additions & 0 deletions
79
coremods/src/main/java/net/neoforged/neoforge/coremods/CoremodUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright (c) NeoForged and contributors | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.neoforged.neoforge.coremods; | ||
|
||
import com.google.gson.Gson; | ||
import com.google.gson.reflect.TypeToken; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Objects; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.objectweb.asm.tree.ClassNode; | ||
import org.objectweb.asm.tree.FieldNode; | ||
import org.objectweb.asm.tree.MethodNode; | ||
|
||
final class CoremodUtils { | ||
private static final Gson GSON = new Gson(); | ||
|
||
CoremodUtils() {} | ||
|
||
static <T> T loadResource(String filename, TypeToken<T> type) { | ||
var stream = NeoForgeCoreMod.class.getResourceAsStream(filename); | ||
if (stream == null) { | ||
throw new IllegalStateException("Missing resource: " + filename); | ||
} | ||
try (var reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { | ||
return GSON.fromJson(reader, type); | ||
} catch (IOException e) { | ||
throw new IllegalStateException("Failed to read JSON resource " + filename); | ||
} | ||
} | ||
|
||
static <T> T loadResource(String filename, Class<T> type) { | ||
return loadResource(filename, TypeToken.get(type)); | ||
} | ||
|
||
static FieldNode getFieldByName(ClassNode classNode, String fieldName) { | ||
FieldNode foundField = null; | ||
for (var fieldNode : classNode.fields) { | ||
if (Objects.equals(fieldNode.name, fieldName)) { | ||
if (foundField == null) { | ||
foundField = fieldNode; | ||
} else { | ||
throw new IllegalStateException("Found multiple fields with name " + fieldName + " in " + classNode.name); | ||
} | ||
} | ||
} | ||
if (foundField == null) { | ||
throw new IllegalStateException("No field with name " + fieldName + " found in class " + classNode.name); | ||
} | ||
return foundField; | ||
} | ||
|
||
static MethodNode getMethodByDescriptor(ClassNode classNode, @Nullable String methodName, String methodSignature) { | ||
MethodNode foundMethod = null; | ||
for (var methodNode : classNode.methods) { | ||
if (Objects.equals(methodNode.desc, methodSignature) | ||
&& (methodName == null || Objects.equals(methodNode.name, methodName))) { | ||
if (foundMethod == null) { | ||
foundMethod = methodNode; | ||
} else { | ||
throw new IllegalStateException("Found duplicate method with signature " + methodSignature + " in " + classNode.name); | ||
} | ||
} | ||
} | ||
|
||
if (foundMethod == null) { | ||
if (methodName != null) { | ||
throw new IllegalStateException("Unable to find method " + methodSignature + " with name " + methodName + " in " + classNode.name); | ||
} else { | ||
throw new IllegalStateException("Unable to find method " + methodSignature + " in " + classNode.name); | ||
} | ||
} | ||
return foundMethod; | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
coremods/src/main/java/net/neoforged/neoforge/coremods/MethodRedirector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright (c) NeoForged and contributors | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.neoforged.neoforge.coremods; | ||
|
||
import cpw.mods.modlauncher.api.ITransformer; | ||
import cpw.mods.modlauncher.api.ITransformerVotingContext; | ||
import cpw.mods.modlauncher.api.TargetType; | ||
import cpw.mods.modlauncher.api.TransformerVoteResult; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.function.Function; | ||
import org.objectweb.asm.Opcodes; | ||
import org.objectweb.asm.tree.ClassNode; | ||
import org.objectweb.asm.tree.MethodInsnNode; | ||
|
||
/** | ||
* Redirect calls to one method to another. | ||
*/ | ||
public class MethodRedirector implements ITransformer<ClassNode> { | ||
private final Map<String, List<MethodRedirection>> redirectionsByClass = new HashMap<>(); | ||
private final Set<Target<ClassNode>> targets = new HashSet<>(); | ||
|
||
private static final List<MethodRedirection> REDIRECTIONS = List.of( | ||
new MethodRedirection( | ||
Opcodes.INVOKEVIRTUAL, | ||
"finalizeSpawn", | ||
"(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;", | ||
"finalize_spawn_targets.json", | ||
methodInsnNode -> new MethodInsnNode( | ||
Opcodes.INVOKESTATIC, | ||
"net/neoforged/neoforge/event/EventHooks", | ||
"finalizeMobSpawn", | ||
"(Lnet/minecraft/world/entity/Mob;Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;", | ||
false))); | ||
|
||
public MethodRedirector() { | ||
for (var redirection : REDIRECTIONS) { | ||
var targetClassNames = CoremodUtils.loadResource(redirection.targetClassListFile, String[].class); | ||
for (var targetClassName : targetClassNames) { | ||
targets.add(Target.targetClass(targetClassName)); | ||
var redirections = redirectionsByClass.computeIfAbsent(targetClassName, s -> new ArrayList<>()); | ||
redirections.add(redirection); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public TargetType<ClassNode> getTargetType() { | ||
return TargetType.CLASS; | ||
} | ||
|
||
@Override | ||
public Set<Target<ClassNode>> targets() { | ||
return targets; | ||
} | ||
|
||
@Override | ||
public ClassNode transform(ClassNode classNode, ITransformerVotingContext votingContext) { | ||
var redirections = redirectionsByClass.getOrDefault(classNode.name, Collections.emptyList()); | ||
|
||
var methods = classNode.methods; | ||
for (var method : methods) { | ||
var instr = method.instructions; | ||
for (var i = 0; i < instr.size(); i++) { | ||
var node = instr.get(i); | ||
if (node instanceof MethodInsnNode methodInsnNode) { | ||
for (var redirection : redirections) { | ||
if (redirection.invokeOpCode == methodInsnNode.getOpcode() | ||
&& redirection.methodName.equals(methodInsnNode.name) | ||
&& redirection.methodDescriptor.equals(methodInsnNode.desc)) { | ||
// Found a match for the target method | ||
instr.set( | ||
methodInsnNode, | ||
redirection.redirector.apply(methodInsnNode)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return classNode; | ||
} | ||
|
||
@Override | ||
public TransformerVoteResult castVote(ITransformerVotingContext context) { | ||
return TransformerVoteResult.YES; | ||
} | ||
|
||
private record MethodRedirection( | ||
int invokeOpCode, | ||
String methodName, | ||
String methodDescriptor, | ||
String targetClassListFile, | ||
Function<MethodInsnNode, MethodInsnNode> redirector) {} | ||
} |
30 changes: 30 additions & 0 deletions
30
coremods/src/main/java/net/neoforged/neoforge/coremods/NeoForgeCoreMod.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (c) NeoForged and contributors | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.neoforged.neoforge.coremods; | ||
|
||
import cpw.mods.modlauncher.api.ITransformer; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import net.neoforged.neoforgespi.coremod.ICoreMod; | ||
|
||
public class NeoForgeCoreMod implements ICoreMod { | ||
@Override | ||
public Iterable<? extends ITransformer<?>> getTransformers() { | ||
List<ITransformer<?>> transformers = new ArrayList<>(); | ||
transformers.add(new ReplaceFieldWithGetterAccess("net.minecraft.world.level.biome.Biome", Map.of( | ||
"climateSettings", "getModifiedClimateSettings", | ||
"specialEffects", "getModifiedSpecialEffects"))); | ||
transformers.add(new ReplaceFieldWithGetterAccess("net.minecraft.world.level.levelgen.structure.Structure", Map.of( | ||
"settings", "getModifiedStructureSettings"))); | ||
transformers.add(new ReplaceFieldWithGetterAccess("net.minecraft.world.level.block.FlowerPotBlock", Map.of( | ||
"potted", "getPotted"))); | ||
|
||
transformers.add(new MethodRedirector()); | ||
|
||
return transformers; | ||
} | ||
} |
Oops, something went wrong.