mojira.dev
MC-192263

Sign editor will not be filled with existing text data

The bug

After calling a PacketPlayOutOpenSignEditor packet with a block position to an existing sign the sign editor opens without any text but still synchronizes further typed characters.

An example is attached.

Attachments

Comments 5

Please provide reproduction steps on how to call the "PacketPlayOutOpenSignEditor" exactly in your example.

Here is an example how to open the sign editor.

import net.minecraft.server.v1_16_R1.BlockPosition;
import net.minecraft.server.v1_16_R1.PacketPlayOutOpenSignEditor;
import org.bukkit.Location;
import org.bukkit.block.Sign;
import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;

public class MojangReproductionTest {
    //Sign s has already text on every line. However, the sign editor displays a blank sign instead of showing the existing text.
    public static void openSignEditor(Player player, Sign s) {
        Location l = s.getLocation();
        BlockPosition position = new BlockPosition(l.getBlockX(), l.getBlockY(), l.getBlockZ());
        PacketPlayOutOpenSignEditor packet = new PacketPlayOutOpenSignEditor(position);
        ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
    }
}

After analyzing the Minecraft 1.16.1 client code, I found that the bug is indeed in the client and caused by the rework of how lines are stored in net.minecraft.client.gui.screens.inventory.SignEditScreen.

In Minecraft 1.15.2, the previous major version, SignEditScreen used a single source of truth for the lines of the sign: net.minecraft.world.level.block.entity.SignBlockEntity.

In Minecraft 1.16.1, there is a new String[] messages field that gets initialized with 4 empty strings and never imports lines from the SignBlockEntity passed into the constructor. The corresponding TextFieldHelper (created in SignEditScreen.init()) then accesses those empty strings.

To fix the bug, the String[] messages field in SignEditScreen needs to import the sign lines from the SignBlockEntity sign field either in the constructor (better place) or early in the SignEditScreen.init() method (worse place). Alternatively, for cleaner code, the introduction of String[] messages should be reverted. Minecraft 1.15.2 had a working getter (SignBlockEntity.getMessage()) and setter (SignBlockEntity.setMessage()), so why not keep using them?

The members and constructor as they are in Minecraft 1.16.1:

public class SignEditScreen extends Screen {
   private final SignRenderer.SignModel signModel = new SignRenderer.SignModel();
   private final SignBlockEntity sign;
   private int frame;
   private int line;
   private TextFieldHelper signField;
   private final String[] messages = (String[])Util.make(new String[4], (var0) -> {
      Arrays.fill(var0, "");
   });

   public SignEditScreen(SignBlockEntity var1) {
      super(new TranslatableComponent("sign.edit"));
      this.sign = var1;
   }
…

The quickest way to fix the bug (assuming that SignBlockEntity.getMessage() still returns a net.minecraft.network.chat.Component like in Minecraft 1.15.2) should be to change the constructor to this:

public SignEditScreen(SignBlockEntity var1) {
      super(new TranslatableComponent("sign.edit"));
      this.sign = var1;
      Arrays.setAll(messages, i -> sign.getMessage(i).getString());
   }

Please respect the rules of the bug tracker. This is not a forum for discussion. I removed all the recent comments on this ticket.

This is a feature request, but we will look into adding the functionality.

I can only repeat what Adrian has said: This is considered a feature request at this moment, and this is a bug tracker.

For suggestions, visit the Feedback website, or visit Minecraft Suggestions on Reddit.

Quick Links:
πŸ““ Issue Guidelines – πŸ›  Community Support – πŸ“§ Customer Support – ✍️ Feedback and Suggestions – πŸ“– Game Wiki
πŸ’¬ Mojira Subreddit – πŸ’¬ Mojira Discord

CodingAir

(Unassigned)

Community Consensus

Normal

Block states

1.16.1

Retrieved