Максимальная длина сообщения в чате 1.7.10

Версия Minecraft
1.7.10
11
0
По умолчанию, какой бы длины строку я не передавал в sendChatMessage - сообщение в чате (1.7.10) обрезается до 100 символов:
Код:
import net.minecraft.client.Minecraft;

Minecraft.getMinecraft().thePlayer.sendChatMessage("Сообщение");
Есть идеи как это обойти, увеличив максимальную длину до необходимого количества символов?
 
7,099
324
1,510
Разрезать на куски по 100 и отправить последовательно
---
Scala:
def slice(msg:String)=for(i<-0 to(msg.length,100)) yield msg.slice(i,i+100)
 
Последнее редактирование:
11
0
hohserg1, это конечно выход, но увы мне это не подойдет.

Xcom³, кажется нашел в исходниках нужное место, это net.minecraft.network.play.client.C01PacketChatMessage:
Java:
   public C01PacketChatMessage(String p_i45240_1_) {
      if(p_i45240_1_.length() > 100) {
         p_i45240_1_ = p_i45240_1_.substring(0, 100);
      }

      this.field_149440_a = p_i45240_1_;
   }

   public void readPacketData(PacketBuffer p_148837_1_) throws IOException {
      this.field_149440_a = p_148837_1_.readStringFromBuffer(100);
   }
Правильно ли я понял, что мне надо смотреть вот это?
 
11
0
В примере разбирается ситуация с изменением модификатора доступа, в моем же случае надо изменить аргументы методов substring и readStringFromBuffer, а так же условие if(p_i45240_1_.length() > 100).

Байт-код необходимого мне класса выглядит так:
Java:
// class version 50.0 (50)
// access flags 0x21
public class ir extends ft  {

  // compiled from: SourceFile

  // access flags 0x2
  private Ljava/lang/String; a

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 13 L0
    ALOAD 0
    INVOKESPECIAL ft.<init> ()V
   L1
    LINENUMBER 15 L1
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public <init>(Ljava/lang/String;)V
   L0
    LINENUMBER 17 L0
    ALOAD 0
    INVOKESPECIAL ft.<init> ()V
   L1
    LINENUMBER 18 L1
    ALOAD 1
    INVOKEVIRTUAL java/lang/String.length ()I
    BIPUSH 100
    IF_ICMPLE L2
   L3
    LINENUMBER 19 L3
    ALOAD 1
    ICONST_0
    BIPUSH 100
    INVOKEVIRTUAL java/lang/String.substring (II)Ljava/lang/String;
    ASTORE 1
   L2
    LINENUMBER 22 L2
   FRAME FULL [ir java/lang/String] []
    ALOAD 0
    ALOAD 1
    PUTFIELD ir.a : Ljava/lang/String;
   L4
    LINENUMBER 23 L4
    RETURN
    MAXSTACK = 3
    MAXLOCALS = 2

  // access flags 0x1
  public a(Let;)V
   L0
    LINENUMBER 27 L0
    ALOAD 0
    ALOAD 1
    BIPUSH 100
    INVOKEVIRTUAL et.c (I)Ljava/lang/String;
    PUTFIELD ir.a : Ljava/lang/String;
   L1
    LINENUMBER 28 L1
    RETURN
    MAXSTACK = 3
    MAXLOCALS = 2

  // access flags 0x1
  public b(Let;)V
   L0
    LINENUMBER 32 L0
    ALOAD 1
    ALOAD 0
    GETFIELD ir.a : Ljava/lang/String;
    INVOKEVIRTUAL et.a (Ljava/lang/String;)V
   L1
    LINENUMBER 33 L1
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1
  public a(Lio;)V
   L0
    LINENUMBER 37 L0
    ALOAD 1
    ALOAD 0
    INVOKEINTERFACE io.a (Lir;)V
   L1
    LINENUMBER 38 L1
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1
  public b()Ljava/lang/String;
   L0
    LINENUMBER 42 L0
    LDC "message='%s'"
    ICONST_1
    ANEWARRAY java/lang/Object
    DUP
    ICONST_0
    ALOAD 0
    GETFIELD ir.a : Ljava/lang/String;
    AASTORE
    INVOKESTATIC java/lang/String.format (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
    ARETURN
    MAXSTACK = 5
    MAXLOCALS = 1

  // access flags 0x1
  public c()Ljava/lang/String;
   L0
    LINENUMBER 46 L0
    ALOAD 0
    GETFIELD ir.a : Ljava/lang/String;
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1041
  public synthetic bridge a(Lfb;)V
   L0
    LINENUMBER 9 L0
    ALOAD 0
    ALOAD 1
    CHECKCAST io
    INVOKEVIRTUAL ir.a (Lio;)V
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 2
}
Если я все правильно понимаю, то мне нужно изменить все вхождения BIPUSH 100 например на BIPUSH 200. Как это сделать в ClassVisitor или MethodVisitor?
 
11
0
Agravaine, у меня цель не в том, чтобы "просто сделать", а в том, чтобы понять как правильно и научиться делать правильно. Собственно за этим я и здесь - если знаете, то покажите и расскажите как это сделать.
 
Последнее редактирование:
11
0
Разобрался, всем спасибо за помощь. Если вдруг что-то сделал неправильно, то жду критики. Делал по этой инструкции [Не просто][Не легко]Хуки:

HookLoader.java
Java:
package ---.---.hook;

import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;

import java.util.Map;

import ---.---.hook.ChatVisitor;

@MCVersion(value = "1.7.10")
@SuppressWarnings("unused")
public class HookLoader implements IFMLLoadingPlugin, IClassTransformer {
    @Override
    public String[] getASMTransformerClass() {
        return new String[]{getClass().getName()};
    }

    @Override
    public String getModContainerClass() {
        return null;
    }

    @Override
    public String getSetupClass() {
        return null;
    }

    @Override
    public void injectData(Map<String, Object> data) {
    }

    @Override
    public String getAccessTransformerClass() {
        return null;
    }

    @Override
    public byte[] transform(String name, String transformedName, byte[] basicClass) {
        if (transformedName.equals("net.minecraft.network.play.client.C01PacketChatMessage")) {
            ClassReader cr = new ClassReader(basicClass);
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            ChatVisitor cv = new ChatVisitor(cw);
            cr.accept(cv, ClassReader.SKIP_FRAMES);
            return cw.toByteArray();
        }

        return basicClass;
    }
}
ChatVisitor.java
Java:
package ---.---.hook;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class ChatVisitor extends ClassVisitor {
    public ChatVisitor(ClassVisitor cv) {
        super(Opcodes.ASM5, cv);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        return new MethodVisitor(Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions)) {
            @Override
            public void visitIntInsn(int opcode, int operand) {
                // Заменяем все int (их там 3 штуки и все == 100)
                super.visitIntInsn(Opcodes.SIPUSH, 512);
            }
        };
    }
}
Ну и в build.gradle добавил:
Код:
jar {
   manifest {
       attributes 'FMLCorePlugin': '---.---.hook.HookLoader'
       attributes 'FMLCorePluginContainsFMLMod': 'true'
   }
}
 
5,018
47
783
Многое что уже сделано надо брать готовым, а не пытаться понять с нуля:geek:
(с) Цитаты алмазных легионеров
 
11
0
hohserg1, боюсь прослыть занудой, но какой из вариантов решения моей задачи - лук, а какой - винтовка?

LG (Maxik001), в корне не согласен. Я считаю, что эффективно поддерживать код можно только тогда, когда досконально знаешь как он работает, а это возможно только тогда, когда написал его сам, то есть процент заимствованного чужого кода в проекте нужно стараться минимизировать.

Я пару раз в жизни сталкивался с ситуацией, когда используемая в проекте библиотека переставала поддерживаться или выходила мажорная версия с другим api без дальнейшей поддержки более ранних версий, в результате приходилось заниматься самостоятельной поддержкой чужого кода, а это куда сложнее чем написать заново.

Что касается данной конкретной задачи - не вижу смысла использовать тут весьма развесистую библиотеку, пусть даже она предоставляет куда более удобный уровень абстракции, при условии, что я не задействую и 10% от всех ее возможностей.
 
5,018
47
783
Тогда немедленно начинай учить машинный код. Первые программисты писали именно нулями и единичками. А Ада Ловлейс помойму вообще по другому как то делала...
 
11
0
Ну с подобным фанатизмом можно еще и не до такого абсурда докатиться... А если серьезно, то лично я предпочитаю в своих проектах использовать одну единственную core библиотеку, причем именно библиотеку, а не огромный фреймворк, большая часть кода которого будет лежать в проекте мертвым грузом, а весь функционал писать самостоятельно вокруг выбранной библиотеки. Причем библиотека должна быть заменяемой, то есть как минимум иметь пару аналогов с полной совместимостью.

Я не считаю подобный подход "единственно верным", но для себя и своих задач я нахожу его весьма эффективным: скорее всего этот подход больше подходит для модульного программирования.
 
7,099
324
1,510
Сверху