650 Zeilen
23 KiB
Java
650 Zeilen
23 KiB
Java
/*
|
|
* This file is a part of the SteamWar software.
|
|
*
|
|
* Copyright (C) 2023 SteamWar.de-Serverteam
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package de.steamwar.advancedscripts.screen;
|
|
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import de.steamwar.advancedscripts.lexer.ScriptColorizer;
|
|
import de.steamwar.advancedscripts.lexer.Token;
|
|
import de.steamwar.advancedscripts.lexer.TokenTypeColors;
|
|
import net.minecraft.client.font.TextHandler;
|
|
import net.minecraft.client.gui.DrawContext;
|
|
import net.minecraft.client.gui.screen.Screen;
|
|
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
|
import net.minecraft.client.gui.screen.ingame.BookScreen;
|
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
|
import net.minecraft.client.gui.widget.PressableWidget;
|
|
import net.minecraft.client.render.GameRenderer;
|
|
import net.minecraft.client.util.NarratorManager;
|
|
import net.minecraft.client.util.SelectionManager;
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NbtCompound;
|
|
import net.minecraft.nbt.NbtList;
|
|
import net.minecraft.nbt.NbtString;
|
|
import net.minecraft.network.packet.c2s.play.BookUpdateC2SPacket;
|
|
import net.minecraft.text.Style;
|
|
import net.minecraft.text.Text;
|
|
import net.minecraft.util.Hand;
|
|
import org.apache.commons.lang3.mutable.MutableInt;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
public class ScriptEditScreen extends Screen {
|
|
|
|
private PlayerEntity player;
|
|
private ItemStack itemStack;
|
|
private Hand hand;
|
|
|
|
private List<String> lines = new ArrayList<>();
|
|
private int scroll = 0;
|
|
private int cursorY = 0;
|
|
private int cursorX = 0;
|
|
|
|
private int savedCursorY = -1;
|
|
private int savedCursorX = -1;
|
|
|
|
private int tickCounter;
|
|
|
|
private int keyCode = -1;
|
|
private long time;
|
|
|
|
public ScriptEditScreen(PlayerEntity player, ItemStack itemStack, Hand hand) {
|
|
super(NarratorManager.EMPTY);
|
|
this.player = player;
|
|
this.itemStack = itemStack;
|
|
this.hand = hand;
|
|
|
|
NbtCompound nbtCompound = itemStack.getNbt();
|
|
if (nbtCompound != null) {
|
|
BookScreen.filterPages(nbtCompound, s -> {
|
|
String[] split = s.split("\n");
|
|
for (String s1 : split) {
|
|
if (s1.equals(" ")) {
|
|
lines.add("");
|
|
} else {
|
|
lines.add(s1);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
if (lines.isEmpty()) {
|
|
lines.add("");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void init() {
|
|
this.addDrawableChild(
|
|
new Button(CANCEL, this.width / 2 - 100, height - 55, () -> this.client.setScreen(null))
|
|
);
|
|
this.addDrawableChild(
|
|
new Button(DONE, this.width / 2 + 2, height - 55, () -> {
|
|
this.client.setScreen(null);
|
|
finalizeBook();
|
|
})
|
|
);
|
|
this.addDrawableChild(
|
|
new Button(BOOK, this.width - 98 - 5, height - 20 - 5, () -> {
|
|
finalizeBook();
|
|
this.client.setScreen(new BookEditScreen(player, itemStack, hand));
|
|
})
|
|
);
|
|
}
|
|
|
|
public static final Text DONE = Text.translatable("gui.done");
|
|
public static final Text CANCEL = Text.translatable("gui.cancel");
|
|
public static final Text BOOK = Text.translatable("item.minecraft.book");
|
|
|
|
private static class Button extends PressableWidget {
|
|
private Runnable onPress;
|
|
|
|
public Button(Text text, int x, int y, Runnable onPress) {
|
|
super(x, y, 98, 20, text);
|
|
visible = true;
|
|
this.onPress = onPress;
|
|
}
|
|
|
|
@Override
|
|
public void onPress() {
|
|
onPress.run();
|
|
}
|
|
|
|
@Override
|
|
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
|
|
}
|
|
|
|
@Override
|
|
public boolean isNarratable() {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void setClipboard(String clipboard) {
|
|
if (this.client != null) {
|
|
SelectionManager.setClipboard(this.client, clipboard);
|
|
}
|
|
|
|
}
|
|
|
|
private String getClipboard() {
|
|
return this.client != null ? SelectionManager.getClipboard(this.client) : "";
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
++this.tickCounter;
|
|
if (keyCode != -1 && System.currentTimeMillis() - time > 500) {
|
|
key(keyCode);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
|
setFocused(null);
|
|
renderBackground(context);
|
|
RenderSystem.setShader(GameRenderer::getRenderTypeTextProgram);
|
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
context.fill(23, 23, this.width - 23, this.height - 63, TokenTypeColors.BACKGROUND);
|
|
|
|
int lineNumberLength = textRenderer.getWidth(lines.size() + "");
|
|
|
|
boolean hasSelection = savedCursorY != -1 && savedCursorX != -1;
|
|
int minSelectionY = Math.min(cursorY, savedCursorY);
|
|
int maxSelectionY = Math.max(cursorY, savedCursorY);
|
|
int minSelectionX = (minSelectionY == maxSelectionY ? Math.min(cursorX, savedCursorX) : (minSelectionY == cursorY ? cursorX : savedCursorX));
|
|
int maxSelectionX = (minSelectionY == maxSelectionY ? Math.max(cursorX, savedCursorX) : (maxSelectionY == cursorY ? cursorX : savedCursorX));
|
|
|
|
int lineNumberText = scroll + 1;
|
|
MutableInt lineNumber = new MutableInt();
|
|
TextHandler textHandler = this.textRenderer.getTextHandler();
|
|
for (int i = scroll; i < lines.size(); i++) {
|
|
String s = lines.get(i);
|
|
|
|
if (lineNumber.getValue() * 9 + 25 > this.height - 66) {
|
|
break;
|
|
}
|
|
|
|
if (s.isEmpty() && i == cursorY) {
|
|
drawCursor(context, 25 + lineNumberLength + 5, lineNumber.getValue() * 9 + 25, true);
|
|
}
|
|
|
|
// Line number
|
|
int height = this.textRenderer.getWrappedLinesHeight(s, this.width - 50 - lineNumberLength - 5);
|
|
if (lineTooLong(s)) {
|
|
context.fill(25 + lineNumberLength + 2, 25 + lineNumber.getValue() * 9, 25 + lineNumberLength + 3, 25 + lineNumber.getValue() * 9 + height, TokenTypeColors.ERROR);
|
|
}
|
|
context.drawText(this.textRenderer, Text.literal(String.valueOf(lineNumberText)), 25 + lineNumberLength - textRenderer.getWidth(String.valueOf(lineNumberText)), 25 + lineNumber.getValue() * 9, 0xFFFFFF, false);
|
|
lineNumberText++;
|
|
|
|
// Line text
|
|
List<Token> tokens = ScriptColorizer.colorize(s);
|
|
AtomicInteger x = new AtomicInteger(25 + lineNumberLength + 5);
|
|
AtomicInteger currentXIndex = new AtomicInteger(0);
|
|
for (Token token : tokens) {
|
|
int finalI = i;
|
|
textHandler.wrapLines(token.text, this.width - x.get() - 25, Style.EMPTY, true, (style, start, end) -> {
|
|
int y = lineNumber.getValue() * 9;
|
|
if (y + 25 > this.height - 66) {
|
|
return;
|
|
}
|
|
|
|
String line = token.text.substring(start, end);
|
|
int previousXIndex = currentXIndex.get();
|
|
currentXIndex.addAndGet(line.length());
|
|
|
|
if (hasSelection) {
|
|
int x1 = x.get();
|
|
int x2 = x.get() + textRenderer.getWidth(line);
|
|
|
|
if (finalI == minSelectionY) {
|
|
if (minSelectionX > currentXIndex.get()) {
|
|
x2 = 0;
|
|
} else if (minSelectionX <= currentXIndex.get() && minSelectionX >= previousXIndex) {
|
|
int startInLine = minSelectionX - previousXIndex;
|
|
x1 += textRenderer.getWidth(line.substring(0, startInLine));
|
|
}
|
|
}
|
|
if (finalI == maxSelectionY) {
|
|
if (maxSelectionX < previousXIndex) {
|
|
x2 = 0;
|
|
} else if (maxSelectionX <= currentXIndex.get()) {
|
|
int endInLine = maxSelectionX - previousXIndex;
|
|
x2 = x.get() + textRenderer.getWidth(line.substring(0, endInLine));
|
|
}
|
|
}
|
|
|
|
if (finalI >= minSelectionY && finalI <= maxSelectionY && x2 > x1) {
|
|
context.fill(x1, y + 25, x2, y + 25 + 9, TokenTypeColors.SELECTION);
|
|
}
|
|
}
|
|
|
|
if (finalI == cursorY && currentXIndex.get() >= cursorX && previousXIndex <= cursorX) {
|
|
drawCursor(context, x.get() + textRenderer.getWidth(line.substring(0, cursorX - previousXIndex)) - 1, 25 + y, isAtEndOfLine());
|
|
}
|
|
|
|
context.drawText(this.textRenderer, Text.literal(line), x.get(), 25 + y, token.color, false);
|
|
x.addAndGet(textRenderer.getWidth(line));
|
|
if (x.get() > this.width - 50 - lineNumberLength - 5) {
|
|
x.set(25 + lineNumberLength + 5);
|
|
lineNumber.increment();
|
|
}
|
|
});
|
|
}
|
|
lineNumber.increment();
|
|
}
|
|
|
|
super.render(context, mouseX, mouseY, delta);
|
|
}
|
|
|
|
private boolean lineTooLong(String s) {
|
|
if (s.length() >= 1024) {
|
|
return true;
|
|
}
|
|
return textRenderer.getWrappedLinesHeight(s, 114) > 128;
|
|
}
|
|
|
|
private void drawCursor(DrawContext context, int x, int y, boolean atEnd) {
|
|
if (this.tickCounter / 6 % 2 == 0) {
|
|
if (!atEnd) {
|
|
Objects.requireNonNull(this.textRenderer);
|
|
context.fill(x, y - 1, x + 1, y + 9, 0xFFFFFFFF);
|
|
} else {
|
|
context.drawText(this.textRenderer, Text.literal("_"), x, y, 0xFFFFFFFF, false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void key(int keyCode) {
|
|
setFocused(null);
|
|
if (Screen.isSelectAll(keyCode)) {
|
|
this.cursorX = 0;
|
|
this.cursorY = 0;
|
|
this.savedCursorX = lines.get(lines.size() - 1).length();
|
|
this.savedCursorY = lines.size() - 1;
|
|
return;
|
|
} else if (Screen.isCopy(keyCode)) {
|
|
String copied = selection(false);
|
|
if (copied != null) {
|
|
setClipboard(copied);
|
|
}
|
|
return;
|
|
} else if (Screen.isPaste(keyCode)) {
|
|
String copied = getClipboard();
|
|
if (copied != null) {
|
|
insert(copied);
|
|
}
|
|
return;
|
|
} else if (Screen.isCut(keyCode)) {
|
|
String copied = selection(true);
|
|
if (copied != null) {
|
|
setClipboard(copied);
|
|
}
|
|
return;
|
|
}
|
|
SelectionManager.SelectionType selectionType = Screen.hasControlDown() ? SelectionManager.SelectionType.WORD : SelectionManager.SelectionType.CHARACTER;
|
|
boolean valid = true;
|
|
int previousCursorX = cursorX;
|
|
int previousCursorY = cursorY;
|
|
switch (keyCode) {
|
|
case 258 -> {
|
|
insert(" ");
|
|
return;
|
|
}
|
|
case 257, 335 -> {
|
|
selection(true);
|
|
newLine();
|
|
valid = false;
|
|
}
|
|
case 259 -> {
|
|
if (selection(true) == null) backspace(selectionType);
|
|
valid = false;
|
|
}
|
|
case 261 -> {
|
|
if (selection(true) == null) delete(selectionType);
|
|
valid = false;
|
|
}
|
|
case 262 -> {
|
|
moveCursor(1, selectionType);
|
|
valid = Screen.hasShiftDown();
|
|
}
|
|
case 263 -> {
|
|
moveCursor(-1, selectionType);
|
|
valid = Screen.hasShiftDown();
|
|
}
|
|
case 264 -> {
|
|
moveDown();
|
|
valid = Screen.hasShiftDown();
|
|
}
|
|
case 265 -> {
|
|
moveUp();
|
|
valid = Screen.hasShiftDown();
|
|
}
|
|
case 268 -> {
|
|
cursorX = 0;
|
|
valid = Screen.hasShiftDown();
|
|
}
|
|
case 269 -> {
|
|
cursorX = lines.get(cursorY).length();
|
|
valid = Screen.hasShiftDown();
|
|
}
|
|
default -> {
|
|
}
|
|
}
|
|
if (valid) {
|
|
if (Screen.hasShiftDown() && savedCursorX == -1 && savedCursorY == -1) {
|
|
savedCursorX = previousCursorX;
|
|
savedCursorY = previousCursorY;
|
|
}
|
|
} else {
|
|
savedCursorY = -1;
|
|
savedCursorX = -1;
|
|
}
|
|
autoScroll();
|
|
}
|
|
|
|
@Override
|
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
|
setFocused(null);
|
|
if (super.keyPressed(keyCode, scanCode, modifiers)) {
|
|
return true;
|
|
}
|
|
key(keyCode);
|
|
this.keyCode = keyCode;
|
|
this.time = System.currentTimeMillis();
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
|
|
setFocused(null);
|
|
this.keyCode = -1;
|
|
return super.keyReleased(keyCode, scanCode, modifiers);
|
|
}
|
|
|
|
@Override
|
|
public boolean charTyped(char chr, int modifiers) {
|
|
setFocused(null);
|
|
if (super.charTyped(chr, modifiers)) {
|
|
return true;
|
|
}
|
|
selection(true);
|
|
boolean valid = insert(String.valueOf(chr));
|
|
savedCursorY = -1;
|
|
savedCursorX = -1;
|
|
autoScroll();
|
|
return valid;
|
|
}
|
|
|
|
private String selection(boolean remove) {
|
|
if (savedCursorX == -1 || savedCursorY == -1) {
|
|
return null;
|
|
}
|
|
int minSelectionY = Math.min(savedCursorY, cursorY);
|
|
int maxSelectionY = Math.max(savedCursorY, cursorY);
|
|
int minSelectionX = (minSelectionY == maxSelectionY ? Math.min(cursorX, savedCursorX) : (minSelectionY == cursorY ? cursorX : savedCursorX));
|
|
int maxSelectionX = (minSelectionY == maxSelectionY ? Math.max(cursorX, savedCursorX) : (maxSelectionY == cursorY ? cursorX : savedCursorX));
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
for (int i = minSelectionY; i <= maxSelectionY; i++) {
|
|
String line = lines.get(i);
|
|
if (i == minSelectionY && i == maxSelectionY) {
|
|
builder.append(line, minSelectionX, maxSelectionX);
|
|
} else if (i == minSelectionY) {
|
|
builder.append(line, minSelectionX, line.length());
|
|
} else if (i == maxSelectionY) {
|
|
builder.append(line, 0, Math.min(maxSelectionX, line.length()));
|
|
} else {
|
|
builder.append(line);
|
|
}
|
|
if (i != maxSelectionY) {
|
|
builder.append("\n");
|
|
}
|
|
}
|
|
if (remove) {
|
|
for (int i = maxSelectionY; i >= minSelectionY; i--) {
|
|
String line = lines.get(i);
|
|
if (i == minSelectionY && i == maxSelectionY) {
|
|
lines.set(i, line.substring(0, minSelectionX) + line.substring(maxSelectionX));
|
|
} else if (i == minSelectionY) {
|
|
lines.set(i, line.substring(0, minSelectionX));
|
|
} else if (i == maxSelectionY) {
|
|
lines.set(i, line.substring(Math.min(maxSelectionX, line.length())));
|
|
} else {
|
|
lines.remove(i);
|
|
}
|
|
}
|
|
if (minSelectionY != maxSelectionY) {
|
|
lines.set(minSelectionY, lines.get(minSelectionY) + lines.get(minSelectionY + 1));
|
|
lines.remove(minSelectionY + 1);
|
|
}
|
|
cursorX = minSelectionX;
|
|
cursorY = minSelectionY;
|
|
savedCursorX = -1;
|
|
savedCursorY = -1;
|
|
}
|
|
return builder.toString();
|
|
}
|
|
|
|
private boolean insert(String s) {
|
|
String[] split = s.split("\n");
|
|
for (int i = 0; i < split.length; i++) {
|
|
String line = lines.get(cursorY);
|
|
if (cursorX == line.length()) {
|
|
line += split[i];
|
|
} else {
|
|
line = line.substring(0, cursorX) + split[i] + line.substring(cursorX);
|
|
}
|
|
lines.set(cursorY, line);
|
|
cursorX += split[i].length();
|
|
if (i != split.length - 1) {
|
|
newLine();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean newLine() {
|
|
String line = lines.get(cursorY);
|
|
String newLine = line.substring(cursorX);
|
|
line = line.substring(0, cursorX);
|
|
lines.set(cursorY, line);
|
|
lines.add(cursorY + 1, newLine);
|
|
cursorY++;
|
|
cursorX = 0;
|
|
return true;
|
|
}
|
|
|
|
private boolean backspace(SelectionManager.SelectionType selectionType) {
|
|
if (cursorX == 0) {
|
|
if (cursorY == 0) {
|
|
return true;
|
|
}
|
|
String previousLine = lines.get(cursorY - 1);
|
|
lines.set(cursorY - 1, lines.get(cursorY - 1) + lines.remove(cursorY));
|
|
cursorY--;
|
|
cursorX = previousLine.length();
|
|
} else {
|
|
String line = lines.get(cursorY);
|
|
int remove = selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, -1);
|
|
line = line.substring(0, cursorX - remove) + line.substring(cursorX);
|
|
lines.set(cursorY, line);
|
|
cursorX -= remove;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean delete(SelectionManager.SelectionType selectionType) {
|
|
if (cursorX == lines.get(cursorY).length()) {
|
|
if (cursorY == lines.size() - 1) {
|
|
return true;
|
|
}
|
|
String nextLine = lines.get(cursorY + 1);
|
|
lines.remove(cursorY);
|
|
lines.set(cursorY, lines.get(cursorY) + nextLine);
|
|
} else {
|
|
String line = lines.get(cursorY);
|
|
int remove = selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, 1);
|
|
line = line.substring(0, cursorX) + line.substring(cursorX + remove);
|
|
lines.set(cursorY, line);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private int getWordLength(String line, int cursorX, int direction) {
|
|
int i = cursorX;
|
|
while (i >= 0 && i < line.length()) {
|
|
char c = line.charAt(i);
|
|
if (Character.isLetterOrDigit(c)) {
|
|
i += direction;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return Math.abs(i - cursorX);
|
|
}
|
|
|
|
private boolean moveCursor(int offset, SelectionManager.SelectionType selectionType) {
|
|
if (offset == 0) {
|
|
return true;
|
|
}
|
|
String line = lines.get(cursorY);
|
|
if (offset > 0) {
|
|
if (cursorX == line.length()) {
|
|
if (cursorY == lines.size() - 1) {
|
|
return true;
|
|
}
|
|
cursorY++;
|
|
cursorX = 0;
|
|
} else {
|
|
cursorX += selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, 1);
|
|
}
|
|
} else {
|
|
if (cursorX == 0) {
|
|
if (cursorY == 0) {
|
|
return true;
|
|
}
|
|
cursorY--;
|
|
cursorX = lines.get(cursorY).length();
|
|
} else {
|
|
cursorX -= selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, -1);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean moveDown() {
|
|
if (cursorY == lines.size() - 1) {
|
|
cursorX = lines.get(cursorY).length();
|
|
return true;
|
|
}
|
|
cursorY++;
|
|
cursorX = Math.min(cursorX, lines.get(cursorY).length());
|
|
return true;
|
|
}
|
|
|
|
private boolean moveUp() {
|
|
if (cursorY == 0) {
|
|
cursorX = 0;
|
|
return true;
|
|
}
|
|
cursorY--;
|
|
cursorX = Math.min(cursorX, lines.get(cursorY).length());
|
|
return true;
|
|
}
|
|
|
|
private void autoScroll() {
|
|
if (cursorY < scroll) {
|
|
scroll = cursorY;
|
|
} else if (cursorY >= scroll + ((this.height - 25 - 66) / 9)) {
|
|
scroll = cursorY - ((this.height - 25 - 66) / 9);
|
|
}
|
|
}
|
|
|
|
private boolean isAtEndOfLine() {
|
|
return cursorX == lines.get(cursorY).length();
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
|
scroll -= Math.signum(amount);
|
|
if (scroll > lines.size() - 1) {
|
|
scroll = lines.size() - 1;
|
|
}
|
|
if (scroll < 0) {
|
|
scroll = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
|
return super.mouseClicked(mouseX, mouseY, button);
|
|
}
|
|
|
|
private List<String> toPages() {
|
|
List<String> pages = new ArrayList<>();
|
|
StringBuilder page = new StringBuilder();
|
|
for (String line : lines) {
|
|
if (!page.isEmpty()) {
|
|
page.append("\n");
|
|
}
|
|
if (page.length() + line.length() > 1024) {
|
|
pages.add(page.toString());
|
|
page = new StringBuilder();
|
|
}
|
|
String temp = page + line;
|
|
if (textRenderer.getWrappedLinesHeight(temp, 114) > 128) {
|
|
pages.add(page.toString());
|
|
page = new StringBuilder();
|
|
}
|
|
if (line.isEmpty()) {
|
|
page.append(" ");
|
|
} else {
|
|
page.append(line);
|
|
}
|
|
}
|
|
if (!page.isEmpty()) {
|
|
pages.add(page.toString());
|
|
}
|
|
return pages;
|
|
}
|
|
|
|
private void finalizeBook() {
|
|
List<String> pages = toPages();
|
|
this.writeNbtData(pages);
|
|
int i = this.hand == Hand.MAIN_HAND ? this.player.getInventory().selectedSlot : 40;
|
|
this.client.getNetworkHandler().sendPacket(new BookUpdateC2SPacket(i, pages, Optional.empty()));
|
|
}
|
|
|
|
private void writeNbtData(List<String> pages) {
|
|
NbtList nbtList = new NbtList();
|
|
pages.stream().map(NbtString::of).forEach(nbtList::add);
|
|
if (!pages.isEmpty()) {
|
|
this.itemStack.setSubNbt("pages", nbtList);
|
|
}
|
|
}
|
|
}
|