Fixed the registry lag

This commit is contained in:
FalsePattern committed 2023-08-12 15:04:04 +02:00
1 parent b61711280b
commit 344b788108
4 files changed
+146 -16

No files matched your search

@@ -2,13 +2,18 @@ package com.falsepattern.endlessids.asm;
import com.falsepattern.endlessids.asm.transformer.ChunkProviderSuperPatcher;
import com.falsepattern.endlessids.asm.transformer.FmlRegistry;
import com.falsepattern.endlessids.asm.transformer.GameDataAccelerator;
import com.falsepattern.endlessids.asm.transformer.SpaceCoreModInfoGenerator;
import com.falsepattern.endlessids.config.GeneralConfig;
import lombok.val;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BooleanSupplier;
import java.util.stream.Collectors;
public enum ClassEdit {
ChunkProviderSuperPatcher(new ChunkProviderSuperPatcher(), () -> GeneralConfig.extendBiome),
@@ -17,15 +22,17 @@ public enum ClassEdit {
"cpw.mods.fml.common.registry.GameData",
"cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry"),
SpaceCoreModInfoGenerator(new SpaceCoreModInfoGenerator(), () -> true,
"com.spacechase0.minecraft.spacecore.mcp.ModInfoGenerator");
"com.spacechase0.minecraft.spacecore.mcp.ModInfoGenerator"),
GameDataAccelerator(new GameDataAccelerator(), () -> true, "cpw.mods.fml.common.registry.GameData"),
;
private static final Map<String, ClassEdit> editMap;
private static final Map<String, List<ClassEdit>> editMap;
static {
editMap = new HashMap<>();
for (final ClassEdit edit : values()) {
for (final String name : edit.classNames) {
ClassEdit.editMap.put(name, edit);
ClassEdit.editMap.computeIfAbsent(name, (ignored) -> new ArrayList<>()).add(edit);
}
}
}
@@ -40,9 +47,14 @@ public enum ClassEdit {
this.classNames = classNames;
}
public static ClassEdit get(final String className) {
val ret = ClassEdit.editMap.get(className);
return ret != null && ret.cond.getAsBoolean() ? ret : null;
public static List<ClassEdit> get(final String className) {
val edit = ClassEdit.editMap.get(className);
if (edit == null) {
return Collections.emptyList();
}
return edit.stream()
.filter(r -> r.cond.getAsBoolean())
.collect(Collectors.toList());
}
public String getName() {
@@ -0,0 +1,31 @@
package com.falsepattern.endlessids.asm;
import lombok.var;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.WeakHashMap;
public class GameDataHooks {
private static final WeakHashMap<Block, WeakReference<ItemBlock>> itemBlockCache = new WeakHashMap<>();
public static void cacheItemBlock(ItemBlock itemBlock) {
itemBlockCache.put(itemBlock.field_150939_a, new WeakReference<>(itemBlock));
}
public static ItemBlock fetchCachedItemBlock(Block block) {
var weakItem = itemBlockCache.get(block);
if (weakItem != null) {
return weakItem.get();
}
return null;
}
public static Iterable<Item> fakeIterable() {
return Collections.emptyList();
}
}
@@ -4,6 +4,7 @@ import com.falsepattern.endlessids.Tags;
import com.falsepattern.endlessids.asm.transformer.ChunkProviderSuperPatcher;
import com.falsepattern.endlessids.asm.transformer.DevFixer;
import lombok.val;
import lombok.var;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.ClassReader;
@@ -37,8 +38,7 @@ public class IETransformer implements IClassTransformer {
if (blacklist.contains(transformedName)) {
return bytes;
}
ClassEdit[] edits = new ClassEdit[2];
edits[0] = ClassEdit.get(transformedName);
var edits = new ArrayList<ClassEdit>(ClassEdit.get(transformedName));
ClassNode cn = new ClassNode(Opcodes.ASM5);
{
val reader = new ClassReader(bytes);
@@ -52,20 +52,15 @@ public class IETransformer implements IClassTransformer {
val reader = new ClassReader(bytes);
reader.accept(cn, ClassReader.EXPAND_FRAMES);
}
if (edits[0] == null) {
edits[0] = ClassEdit.ChunkProviderSuperPatcher;
} else {
edits[1] = ClassEdit.ChunkProviderSuperPatcher;
}
edits.add(ClassEdit.ChunkProviderSuperPatcher);
}
if (edits[0] == null) {
if (edits.size() == 0) {
return isObfuscated ? bytes : DevFixer.fixDev(bytes);
}
if (!isObfuscated) {
DevFixer.transform(cn);
}
for (int i = 0; i < edits.length; i++) {
val edit = edits[i];
for (final ClassEdit edit : edits) {
if (edit == null) {
continue;
}
@@ -0,0 +1,92 @@
package com.falsepattern.endlessids.asm.transformer;
import com.falsepattern.endlessids.asm.IClassNodeTransformer;
import com.falsepattern.endlessids.asm.IETransformer;
import lombok.val;
import lombok.var;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
public class GameDataAccelerator implements IClassNodeTransformer {
private static final int MASK_REGISTER_BLOCK = 0b1;
private static final int MASK_REGISTER_ITEM = 0b10;
@Override
public void transform(ClassNode classNode, boolean obfuscated) {
int tweaksLeft = MASK_REGISTER_BLOCK | MASK_REGISTER_ITEM;
for (val method: classNode.methods) {
if ((tweaksLeft & MASK_REGISTER_BLOCK) != 0 &&
method.name.equals("registerBlock") &&
method.desc.equals("(Lnet/minecraft/block/Block;Ljava/lang/String;I)I")) {
transformRegisterBlock(method);
tweaksLeft &= ~MASK_REGISTER_BLOCK;
}
if ((tweaksLeft & MASK_REGISTER_ITEM) != 0 &&
method.name.equals("registerItem") &&
method.desc.equals("(Lnet/minecraft/item/Item;Ljava/lang/String;I)I")) {
transformRegisterItem(method);
tweaksLeft &= ~MASK_REGISTER_ITEM;
}
if (tweaksLeft == 0) {
break;
}
}
if (tweaksLeft != 0) {
IETransformer.logger.error("Could not accelerate block registration!");
}
}
private void transformRegisterItem(MethodNode method) {
var iter = method.instructions.iterator();
while (iter.hasNext()) {
var insn = iter.next();
if (!(insn instanceof FieldInsnNode))
continue;
var typeInsn = (FieldInsnNode) insn;
if (!(typeInsn.owner.equals("net/minecraft/item/ItemBlock") &&
typeInsn.name.equals("field_150939_a") &&
typeInsn.desc.equals("Lnet/minecraft/block/Block;")))
continue;
iter.previous();
iter.add(new InsnNode(Opcodes.DUP));
iter.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/falsepattern/endlessids/asm/GameDataHooks", "cacheItemBlock", "(Lnet/minecraft/item/ItemBlock;)V", false));
return;
}
transformError(method);
}
private static void transformError(MethodNode method) {
IETransformer.logger.error("Could not add caching code to GameData." + method.name + method.desc);
}
private void transformRegisterBlock(MethodNode method) {
var iter = method.instructions.iterator();
while (iter.hasNext()) {
var insn = iter.next();
if (!(insn instanceof FieldInsnNode))
continue;
var fieldInsn = (FieldInsnNode) insn;
if (!(fieldInsn.owner.equals("cpw/mods/fml/common/registry/GameData") &&
fieldInsn.name.equals("iItemRegistry") &&
fieldInsn.desc.equals("Lcpw/mods/fml/common/registry/FMLControlledNamespacedRegistry;")))
continue;
iter.previous();
iter.previous();
iter.remove();
iter.next();
iter.remove();
iter.next();
iter.remove();
iter.add(new VarInsnNode(Opcodes.ALOAD, 1));
iter.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/falsepattern/endlessids/asm/GameDataHooks", "fetchCachedItemBlock", "(Lnet/minecraft/block/Block;)Lnet/minecraft/item/ItemBlock;", false));
iter.add(new VarInsnNode(Opcodes.ASTORE, 4));
iter.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/falsepattern/endlessids/asm/GameDataHooks", "fakeIterable", "()Ljava/lang/Iterable;", false));
return;
}
transformError(method);
}
}