improve performance of chat rendering

This commit is contained in:
LabyStudio
2024-01-26 13:25:53 +01:00
parent 97df7b6560
commit 468f942c49
9 changed files with 103 additions and 13 deletions
@@ -52,6 +52,7 @@ export default class GameWindow {
// Create render layers
this.canvasWorld = document.createElement('canvas');
this.canvasDebug = document.createElement('canvas');
this.canvasChat = document.createElement('canvas');
this.canvasPlayerList = document.createElement('canvas');
this.canvasItems = document.createElement('canvas');
@@ -381,6 +382,11 @@ export default class GameWindow {
this.canvasDebug.height = this.canvas.height;
}
if (this.canvasChat.width !== this.canvas.width || this.canvasChat.height !== this.canvas.height) {
this.canvasChat.width = this.canvas.width;
this.canvasChat.height = this.canvas.height;
}
if (this.canvasPlayerList.width !== this.canvas.width || this.canvasPlayerList.height !== this.canvas.height) {
this.canvasPlayerList.width = this.canvas.width;
this.canvasPlayerList.height = this.canvas.height;
@@ -394,6 +400,8 @@ export default class GameWindow {
this.minecraft.currentScreen.setup(this.minecraft, this.width, this.height);
}
this.minecraft.ingameOverlay.chatOverlay.setDirty();
// Render first frame
if (this.minecraft.isInGame()) {
this.minecraft.worldRenderer.render(0);
+3 -3
View File
@@ -32,8 +32,7 @@ export default class Minecraft {
// TODO Add to settings
static PROXY = {
"address": "localhost",
"port": 30023
"url": "wss://socket.labystudio.de/minecraft/"
};
/**
@@ -350,7 +349,8 @@ export default class Minecraft {
// Open chat
if (button === this.settings.keyOpenChat) {
this.displayScreen(new GuiChat());
this.displayScreen(new GuiChat(this));
this.ingameOverlay.chatOverlay.setDirty();
}
// Toggle debug overlay
@@ -3,7 +3,7 @@ import Command from "../Command.js";
export default class TeleportCommand extends Command {
constructor() {
super("tp", "<x> <y> <y>", "Teleport to a position")
super("tp", "<x> <y> <z>", "Teleport to a position")
}
execute(minecraft, args) {
@@ -8,8 +8,11 @@ export default class ChatOverlay extends Gui {
constructor(minecraft) {
super(minecraft);
this.chatWidth = 320;
this.messages = [];
this.sentHistory = [];
this.dirty = true;
}
render(stack, mouseX, mouseY, partialTicks) {
@@ -30,25 +33,43 @@ export default class ChatOverlay extends Gui {
if (alpha > 0) {
let y = this.minecraft.window.height - 40 - i * 9;
this.drawRect(stack, 2, y - 1, 2 + 320, y + 8, '#000000', alpha / 2 / 255);
this.drawRect(stack, 2, y - 1, 2 + this.chatWidth, y + 8, '#000000', alpha / 2 / 255);
this.drawString(stack, message.message, 2, y, 0xffffff + (alpha << 24));
}
}
this.dirty = false;
}
onTick() {
for (let i = 0; i < this.messages.length; i++) {
let message = this.messages[i];
message.updateCounter++;
// Fade out animation
if (message.updateCounter >= 180 && message.updateCounter <= 200) {
this.dirty = true;
}
}
}
addMessage(message) {
this.messages.splice(0, 0, new ChatLine(message));
for (let line of this.minecraft.fontRenderer.listFormattedStringToWidth(message, this.chatWidth)) {
this.messages.splice(0, 0, new ChatLine(line));
}
this.dirty = true;
}
addMessageToSentHistory(message) {
this.sentHistory.splice(0, 0, message);
this.dirty = true;
}
isDirty() {
return this.dirty;
}
setDirty() {
this.dirty = true;
}
}
@@ -34,8 +34,8 @@ export default class IngameOverlay extends Gui {
// Render hotbar
this.renderHotbar(stack, this.window.width / 2 - 91, this.window.height - 22);
// Render chat
this.chatOverlay.render(stack, mouseX, mouseY, partialTicks);
// Render chat canvas
stack.drawImage(this.window.canvasChat, 0, 0);
// Render debug canvas on stack
if (this.minecraft.settings.debugOverlay) {
@@ -70,6 +70,13 @@ export default class IngameOverlay extends Gui {
this.ticksRendered++;
}
// Render chat on tick if dirty
if (this.chatOverlay.isDirty()) {
let stack = this.window.canvasChat.getContext('2d');
stack.clearRect(0, 0, this.window.width, this.window.height);
this.chatOverlay.render(stack, 0, 0, 0);
}
}
renderCrosshair(stack, x, y) {
@@ -3,9 +3,11 @@ import GuiTextField from "../widgets/GuiTextField.js";
export default class GuiChat extends GuiScreen {
constructor() {
constructor(minecraft) {
super();
this.minecraft = minecraft;
this.inputField = new GuiTextField(0, 0, 0, 0);
this.inputField.renderBackground = false;
@@ -24,6 +26,11 @@ export default class GuiChat extends GuiScreen {
this.buttonList.push(this.inputField);
}
onClose() {
super.onClose();
this.minecraft.ingameOverlay.chatOverlay.setDirty();
}
drawScreen(stack, mouseX, mouseY, partialTicks) {
this.drawRect(stack, 2, this.height - 14, this.width - 2, this.height - 2, '#000000', 0.5);
@@ -31,7 +31,7 @@ export default class NetworkManager {
}
connect(address, port, proxy) {
this.socket = new WebSocket("ws://" + proxy.address + ":" + proxy.port);
this.socket = new WebSocket(proxy.url);
this.socket.binaryType = "arraybuffer";
this.socket.onopen = e => this._onOpen(e);
@@ -20,7 +20,7 @@ export default class ServerJoinGamePacket extends Packet {
}
read(buffer) {
this.entityId = buffer.readVarInt();
this.entityId = buffer.readInt();
let bits = buffer.readByte();
this.hardcoreMode = (bits & 8) === 8;
this.gameType = bits & -9;
@@ -140,7 +140,6 @@ export default class FontRenderer {
return length;
}
createBitMap(img) {
let canvas = document.createElement('canvas');
canvas.width = img.width;
@@ -178,6 +177,54 @@ export default class FontRenderer {
}
listFormattedStringToWidth(text, wrapWidth) {
return text.split("\n"); // TODO Implement wrap logic
let lines = [];
let currentColorCharacter = "r";
for (let line of text.split('\n')) {
let currentLine = '';
let currentLineWidth = 0;
// Split the text into words
for (let word of line.split(' ')) {
const wordWidth = this.getStringWidth(word + " ");
// If adding the word exceeds the wrap width, start a new line
if (currentLineWidth + wordWidth > wrapWidth) {
lines.push(FontRenderer.COLOR_PREFIX + currentColorCharacter + currentLine.trim());
currentColorCharacter = this.getLastColorCharacterOfText(currentLine);
currentLine = '';
currentLineWidth = 0;
}
// Add the word to the current line
currentLine += word + ' ';
currentLineWidth += wordWidth;
}
// Push the last line
if (currentLine.length > 0) {
lines.push(FontRenderer.COLOR_PREFIX + currentColorCharacter + currentLine.trim());
currentColorCharacter = this.getLastColorCharacterOfText(currentLine);
}
}
return lines;
}
getLastColorCharacterOfText(text) {
let character = "r";
let isColorCode = false;
// For each character
for (let i = 0; i < text.length; i++) {
if (text[i] === FontRenderer.COLOR_PREFIX) {
isColorCode = true;
} else {
if (isColorCode) {
character = text[i];
isColorCode = false;
}
}
}
return character;
}
}