package net.minecraft.client.gui.screens.inventory; import com.mojang.blaze3d.platform.Lighting; import java.util.stream.IntStream; import javax.annotation.Nullable; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.font.TextFieldHelper; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.AbstractSignRenderer; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; import net.minecraft.util.ARGB; import net.minecraft.world.level.block.SignBlock; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignText; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.WoodType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import org.joml.Vector3f; @OnlyIn(Dist.CLIENT) public abstract class AbstractSignEditScreen extends Screen { protected final SignBlockEntity sign; private SignText text; private final String[] messages; private final boolean isFrontText; protected final WoodType woodType; private int frame; private int line; @Nullable private TextFieldHelper signField; public AbstractSignEditScreen(SignBlockEntity p_277842_, boolean p_277719_, boolean p_277969_) { this(p_277842_, p_277719_, p_277969_, Component.translatable("sign.edit")); } public AbstractSignEditScreen(SignBlockEntity p_277792_, boolean p_277607_, boolean p_278039_, Component p_277393_) { super(p_277393_); this.sign = p_277792_; this.text = p_277792_.getText(p_277607_); this.isFrontText = p_277607_; this.woodType = SignBlock.getWoodType(p_277792_.getBlockState().getBlock()); this.messages = IntStream.range(0, 4) .mapToObj(p_277214_ -> this.text.getMessage(p_277214_, p_278039_)) .map(Component::getString) .toArray(String[]::new); } @Override protected void init() { this.addRenderableWidget( Button.builder(CommonComponents.GUI_DONE, p_251194_ -> this.onDone()) .bounds(this.width / 2 - 100, this.height / 4 + 144, 200, 20) .build() ); this.signField = new TextFieldHelper( () -> this.messages[this.line], this::setMessage, TextFieldHelper.createClipboardGetter(this.minecraft), TextFieldHelper.createClipboardSetter(this.minecraft), p_280850_ -> this.minecraft.font.width(p_280850_) <= this.sign.getMaxTextLineWidth() ); } @Override public void tick() { this.frame++; if (!this.isValid()) { this.onDone(); } } private boolean isValid() { return this.minecraft != null && this.minecraft.player != null && !this.sign.isRemoved() && !this.sign.playerIsTooFarAwayToEdit(this.minecraft.player.getUUID()); } @Override public boolean keyPressed(int p_252300_, int p_250424_, int p_250697_) { if (p_252300_ == 265) { this.line = this.line - 1 & 3; this.signField.setCursorToEnd(); return true; } else if (p_252300_ == 264 || p_252300_ == 257 || p_252300_ == 335) { this.line = this.line + 1 & 3; this.signField.setCursorToEnd(); return true; } else { return this.signField.keyPressed(p_252300_) ? true : super.keyPressed(p_252300_, p_250424_, p_250697_); } } @Override public boolean charTyped(char p_252008_, int p_251178_) { this.signField.charTyped(p_252008_); return true; } @Override public void render(GuiGraphics p_282418_, int p_281700_, int p_283040_, float p_282799_) { super.render(p_282418_, p_281700_, p_283040_, p_282799_); p_282418_.flush(); Lighting.setupForFlatItems(); p_282418_.drawCenteredString(this.font, this.title, this.width / 2, 40, 16777215); this.renderSign(p_282418_); p_282418_.flush(); Lighting.setupFor3DItems(); } @Override public void renderBackground(GuiGraphics p_334358_, int p_335184_, int p_333439_, float p_335736_) { this.renderTransparentBackground(p_334358_); } @Override public void onClose() { this.onDone(); } @Override public void removed() { ClientPacketListener clientpacketlistener = this.minecraft.getConnection(); if (clientpacketlistener != null) { clientpacketlistener.send( new ServerboundSignUpdatePacket( this.sign.getBlockPos(), this.isFrontText, this.messages[0], this.messages[1], this.messages[2], this.messages[3] ) ); } } @Override public boolean isPauseScreen() { return false; } protected abstract void renderSignBackground(GuiGraphics p_281459_); protected abstract Vector3f getSignTextScale(); protected void offsetSign(GuiGraphics p_282672_, BlockState p_283056_) { p_282672_.pose().translate(this.width / 2.0F, 90.0F, 50.0F); } private void renderSign(GuiGraphics p_282006_) { p_282006_.pose().pushPose(); this.offsetSign(p_282006_, this.sign.getBlockState()); p_282006_.pose().pushPose(); this.renderSignBackground(p_282006_); p_282006_.pose().popPose(); this.renderSignText(p_282006_); p_282006_.pose().popPose(); } private void renderSignText(GuiGraphics p_282366_) { p_282366_.pose().translate(0.0F, 0.0F, 4.0F); Vector3f vector3f = this.getSignTextScale(); p_282366_.pose().scale(vector3f.x(), vector3f.y(), vector3f.z()); int i = this.text.hasGlowingText() ? this.text.getColor().getTextColor() : AbstractSignRenderer.getDarkColor(this.text); boolean flag = this.frame / 6 % 2 == 0; int j = this.signField.getCursorPos(); int k = this.signField.getSelectionPos(); int l = 4 * this.sign.getTextLineHeight() / 2; int i1 = this.line * this.sign.getTextLineHeight() - l; for (int j1 = 0; j1 < this.messages.length; j1++) { String s = this.messages[j1]; if (s != null) { if (this.font.isBidirectional()) { s = this.font.bidirectionalShaping(s); } int k1 = -this.font.width(s) / 2; p_282366_.drawString(this.font, s, k1, j1 * this.sign.getTextLineHeight() - l, i, false); if (j1 == this.line && j >= 0 && flag) { int l1 = this.font.width(s.substring(0, Math.max(Math.min(j, s.length()), 0))); int i2 = l1 - this.font.width(s) / 2; if (j >= s.length()) { p_282366_.drawString(this.font, "_", i2, i1, i, false); } } } } for (int k3 = 0; k3 < this.messages.length; k3++) { String s1 = this.messages[k3]; if (s1 != null && k3 == this.line && j >= 0) { int l3 = this.font.width(s1.substring(0, Math.max(Math.min(j, s1.length()), 0))); int i4 = l3 - this.font.width(s1) / 2; if (flag && j < s1.length()) { p_282366_.fill(i4, i1 - 1, i4 + 1, i1 + this.sign.getTextLineHeight(), ARGB.opaque(i)); } if (k != j) { int j4 = Math.min(j, k); int j2 = Math.max(j, k); int k2 = this.font.width(s1.substring(0, j4)) - this.font.width(s1) / 2; int l2 = this.font.width(s1.substring(0, j2)) - this.font.width(s1) / 2; int i3 = Math.min(k2, l2); int j3 = Math.max(k2, l2); p_282366_.fill(RenderType.guiTextHighlight(), i3, i1, j3, i1 + this.sign.getTextLineHeight(), -16776961); } } } } private void setMessage(String p_277913_) { this.messages[this.line] = p_277913_; this.text = this.text.setMessage(this.line, Component.literal(p_277913_)); this.sign.setText(this.text, this.isFrontText); } private void onDone() { this.minecraft.setScreen(null); } }