无敌三脚猫
首先,我想改的是net.minecraft.server.integrated.IntegratedPlayerManager构造函数里的数字8
  1. public IntegratedPlayerManager(IntegratedServer server, DynamicRegistryManager.Immutable registryManager, WorldSaveHandler saveHandler) {
  2.         super(server, registryManager, saveHandler, 8);
  3.         this.setViewDistance(10);
  4.     }
复制代码

一开始我试了@ModifyConstant,因为这里的字节码显然有个bipush 8,所以应该可以用吧……然后这是我写的
  1. @Mixin(IntegratedPlayerManager.class)
  2. public abstract class ExampleMixin {
  3.     @ModifyConstant(method = "<init>", constant = @Constant(intValue = 8)
  4.     )
  5.     private int modifyConstant(int maxplayer) {
  6.         return 20;
  7.     }
  8. }
复制代码
然后崩了
  1. java.lang.VerifyError: Bad type on operand stack
  2. Exception Details:
  3.   Location:
  4.     net/minecraft/class_1130.<init>(Lnet/minecraft/class_1132;Lnet/minecraft/class_5455$class_5457;Lnet/minecraft/class_29;)V @7: invokespecial
  5.   Reason:
  6.     Type uninitializedThis (current frame, stack[4]) is not assignable to 'net/minecraft/class_1130'
  7.   Current Frame:
  8.     bci: @7
  9.     flags: { flagThisUninit }
  10.     locals: { uninitializedThis, 'net/minecraft/class_1132', 'net/minecraft/class_5455$class_5457', 'net/minecraft/class_29' }
  11.     stack: { uninitializedThis, 'net/minecraft/class_1132', 'net/minecraft/class_5455$class_5457', 'net/minecraft/class_29', uninitializedThis, integer }
  12.   Bytecode:
  13.     0000000: 2a2b 2c2d 2a10 08b7 0016 b700 192a 100a
  14.     0000010: b600 1db1                              

  15.         at net.minecraft.class_1132.<init>(class_1132.java:57)
  16.         以下略
复制代码
照我看的mixin教程,mixin的这个注解不能直接修改常量的值,而是把这个常量放进函数里在返回出来,所以这个崩溃给我的感觉就是……mixin好像忘了增加这个构造函数的maxStack
然后我照着教程举的@ModifyArgs的例子写了(虽然是forge的教程,但mixin的写法应该是一样的吧)
  1. @Mixin(IntegratedPlayerManager.class)
  2. public abstract class ExampleMixin {
  3.     @ModifyArgs(
  4.         method = "<init>",
  5.         at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;<init>(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/util/registry/DynamicRegistryManager$Immutable;Lnet/minecraft/world/WorldSaveHandler;I)V",
  6.         remap = false)
  7.     )
  8.     private static void modifyArgs_$init$(Args args, IntegratedServer server,
  9.         DynamicRegistryManager.Immutable registryManager,
  10.         WorldSaveHandler saveHandler) {
  11.         args.set(3, 20);
  12.     }
  13. }
复制代码
然后还是崩
  1. Caused by: org.spongepowered.asm.mixin.transformer.throwables.InvalidMixinException: Unexpecteded ClassMetadataNotFoundException whilst transforming the mixin class: [MAIN Applicator Phase -> modid.mixins.json:ExampleMixin -> Apply Methods -> (Lorg/spongepowered/asm/mixin/injection/invoke/arg/Args;Lnet/minecraft/class_1132;Lnet/minecraft/class_5455$class_6890;Lnet/minecraft/class_29;)V:args$zih000$modifyArgs_$init$ -> Transform Descriptor -> desc=Lnet/minecraft/class_5455$class_6890;]
复制代码

后来我看到wiki里说@ModifyArg注解可以指定多参数方法中的其中一个参数(我看的教程里没有讲这个),于是我写了
  1. @Mixin(IntegratedPlayerManager.class)
  2. public abstract class ExampleMixin {
  3.     @ModifyArg(
  4.         method = "<init>",
  5.         at = @At(value = "INVOKE",
  6.         target = "Lnet/minecraft/server/PlayerManager;<init>(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/util/registry/DynamicRegistryManager$Immutable;Lnet/minecraft/world/WorldSaveHandler;I)V", remap = false),
  7.         index = 3)
  8.     private static int modifyArg(int max) {
  9.         return 20;
  10.     }
  11. }
复制代码
还是不行
  1. Caused by: org.spongepowered.asm.mixin.injection.throwables.InjectionError: Critical injection failure: Argument modifier method modifyArg(I)I in modid.mixins.json:ExampleMixin from mod modid failed injection check, (0/1) succeeded. Scanned 1 target(s). Using refmap fabric-example-mod-refmap.json
复制代码

这是我第一次用mixin,感觉不如隔壁forge的coremod

Ph-苯
@ModifyArg的index是从0开始的呀,如果是第三个参数的话应该是2。

无敌三脚猫
Ph-苯 发表于 2022-4-22 17:35
@ModifyArg的index是从0开始的呀,如果是第三个参数的话应该是2。

super(server, registryManager, saveHandler, 8);
这里“8”是第4个参数,所以写index=3应该没错呀

Ph-苯
无敌三脚猫 发表于 2022-4-23 20:42
super(server, registryManager, saveHandler, 8);
这里“8”是第4个参数,所以写index=3应该没错呀 ...

我眼抽了不好意思😂……
你试试这个?
  1. import net.minecraft.server.integrated.IntegratedPlayerManager;
  2. import net.minecraft.server.integrated.IntegratedServer;
  3. import net.minecraft.util.registry.DynamicRegistryManager;
  4. import net.minecraft.world.WorldSaveHandler;
  5. import org.spongepowered.asm.mixin.Mixin;
  6. import org.spongepowered.asm.mixin.injection.At;
  7. import org.spongepowered.asm.mixin.injection.Desc;
  8. import org.spongepowered.asm.mixin.injection.ModifyArg;
  9. @Mixin(IntegratedPlayerManager.class)
  10. public abstract class MixinIntegratedPlayerManager {
  11. @ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;<init>(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/util/registry/DynamicRegistryManager$Impl;Lnet/minecraft/world/WorldSaveHandler;I)V", desc = @Desc(value = "<init>", args = {IntegratedServer.class, DynamicRegistryManager.Impl.class, WorldSaveHandler.class})), index = 3)
  12. private static int chageMaxPlayers(int maxPlayers) {
  13.         return 20;
  14. }
  15. }
复制代码

teddyxlandlee
Mixin也可以直接改字节码。
不过需要一个假Mixin和MixinConfig套个壳。

See: Mixin套壳和真正的实现——向Abstract Enum中插入实现
See: 单独开一个mixins.json,声明MixinConfig

teddyxlandlee
诶楼主我好像明白了什么,出来挨打!
  1. super(server, registryManager, saveHandler, 8);
复制代码

这里的常量8不是index=3!是index=4!

为什么呢?因为this是0,所以对于non-static方法,第一个参数就是1,而不是0。