Sort field added by mixin (1.18). (#743)

Signed-off-by: 秋雨落 <i@rain.cx>
This commit is contained in:
秋雨落 2022-09-20 15:32:04 +08:00 committed by GitHub
parent 90ed5201f3
commit 3ebd71a152
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 14 deletions

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.core.network.protocol.game; package io.izzel.arclight.common.mixin.core.network.protocol.game;
import io.izzel.arclight.common.mod.ArclightMixinPlugin;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.chat.ComponentSerializer;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
@ -22,7 +23,7 @@ public class SChatPacketMixin {
@Shadow private UUID sender; @Shadow private UUID sender;
// @formatter:on // @formatter:on
public BaseComponent[] components; @ArclightMixinPlugin.SortField(after = "f_131821_" /* message */) public BaseComponent[] components;
/** /**
* @author IzzelAliz * @author IzzelAliz

View File

@ -5,25 +5,27 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo; import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.HashSet; import java.lang.annotation.ElementType;
import java.util.List; import java.lang.annotation.Retention;
import java.util.ListIterator; import java.lang.annotation.RetentionPolicy;
import java.util.Map; import java.lang.annotation.Target;
import java.util.Objects; import java.util.*;
import java.util.Set;
public class ArclightMixinPlugin implements IMixinConfigPlugin { public class ArclightMixinPlugin implements IMixinConfigPlugin {
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface SortField {
String after();
}
private static final String SORT_FIELD_TYPE = Type.getDescriptor(SortField.class);
private final Map<String, Map.Entry<List<FieldNode>, List<MethodNode>>> accessTransformer = private final Map<String, Map.Entry<List<FieldNode>, List<MethodNode>>> accessTransformer =
ImmutableMap.<String, Map.Entry<List<FieldNode>, List<MethodNode>>>builder() ImmutableMap.<String, Map.Entry<List<FieldNode>, List<MethodNode>>>builder()
.put("net.minecraft.world.level.Level", .put("net.minecraft.world.level.Level",
@ -128,6 +130,10 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
.add("net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess") .add("net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess")
.build(); .build();
private final Set<String> sortFields = ImmutableSet.<String>builder()
.add("net.minecraft.network.protocol.game.ClientboundChatPacket")
.build();
@Override @Override
public void onLoad(String mixinPackage) { public void onLoad(String mixinPackage) {
@ -172,6 +178,35 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
} }
} }
modifyConstructor(targetClassName, targetClass); modifyConstructor(targetClassName, targetClass);
sortFields(targetClassName, targetClass);
}
private void sortFields(String targetClassName, ClassNode classNode) {
if (sortFields.contains(targetClassName)) {
TreeMap<Integer, FieldNode> insertions = new TreeMap<>();
for (ListIterator<FieldNode> iterator = classNode.fields.listIterator(); iterator.hasNext(); ) {
FieldNode node = iterator.next();
if (node.invisibleAnnotations == null) continue;
for (AnnotationNode annotation : node.invisibleAnnotations) {
if (SORT_FIELD_TYPE.equals(annotation.desc)) {
String name = annotation.values.get(1).toString();
int index = 0;
for (FieldNode field : classNode.fields) {
if (field.name.equals(name)) break;
else index++;
}
if (index >= classNode.fields.size())
throw new IllegalArgumentException(String.format("SortField cannot find %s in %s", name, targetClassName));
insertions.put(index + 1, node);
iterator.remove();
}
}
}
for (Map.Entry<Integer, FieldNode> entry : insertions.descendingMap().entrySet()) {
classNode.fields.add(entry.getKey(), entry.getValue());
entry.getValue().invisibleAnnotations.removeIf(it -> SORT_FIELD_TYPE.equals(it.desc));
}
}
} }
private void modifyConstructor(String targetClassName, ClassNode classNode) { private void modifyConstructor(String targetClassName, ClassNode classNode) {