From 3ebd71a152a42361b6424d5f367c9c851bd09792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E9=9B=A8=E8=90=BD?= <53731501+qyl27@users.noreply.github.com> Date: Tue, 20 Sep 2022 15:32:04 +0800 Subject: [PATCH] Sort field added by mixin (1.18). (#743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋雨落 --- .../protocol/game/SChatPacketMixin.java | 3 +- .../common/mod/ArclightMixinPlugin.java | 61 +++++++++++++++---- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/SChatPacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/SChatPacketMixin.java index c654b7e6..35a9485d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/SChatPacketMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/SChatPacketMixin.java @@ -1,5 +1,6 @@ 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.chat.ComponentSerializer; import net.minecraft.network.FriendlyByteBuf; @@ -22,7 +23,7 @@ public class SChatPacketMixin { @Shadow private UUID sender; // @formatter:on - public BaseComponent[] components; + @ArclightMixinPlugin.SortField(after = "f_131821_" /* message */) public BaseComponent[] components; /** * @author IzzelAliz diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java index 10a353c0..55c649f6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java @@ -5,25 +5,27 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -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.objectweb.asm.Type; +import org.objectweb.asm.tree.*; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import java.util.HashSet; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.*; 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, List>> accessTransformer = ImmutableMap., List>>builder() .put("net.minecraft.world.level.Level", @@ -128,6 +130,10 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin { .add("net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess") .build(); + private final Set sortFields = ImmutableSet.builder() + .add("net.minecraft.network.protocol.game.ClientboundChatPacket") + .build(); + @Override public void onLoad(String mixinPackage) { @@ -172,6 +178,35 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin { } } modifyConstructor(targetClassName, targetClass); + sortFields(targetClassName, targetClass); + } + + private void sortFields(String targetClassName, ClassNode classNode) { + if (sortFields.contains(targetClassName)) { + TreeMap insertions = new TreeMap<>(); + for (ListIterator 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 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) {