improve performance of chat rendering
This commit is contained in:
@@ -52,6 +52,7 @@ export default class GameWindow {
|
|||||||
// Create render layers
|
// Create render layers
|
||||||
this.canvasWorld = document.createElement('canvas');
|
this.canvasWorld = document.createElement('canvas');
|
||||||
this.canvasDebug = document.createElement('canvas');
|
this.canvasDebug = document.createElement('canvas');
|
||||||
|
this.canvasChat = document.createElement('canvas');
|
||||||
this.canvasPlayerList = document.createElement('canvas');
|
this.canvasPlayerList = document.createElement('canvas');
|
||||||
this.canvasItems = document.createElement('canvas');
|
this.canvasItems = document.createElement('canvas');
|
||||||
|
|
||||||
@@ -381,6 +382,11 @@ export default class GameWindow {
|
|||||||
this.canvasDebug.height = this.canvas.height;
|
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) {
|
if (this.canvasPlayerList.width !== this.canvas.width || this.canvasPlayerList.height !== this.canvas.height) {
|
||||||
this.canvasPlayerList.width = this.canvas.width;
|
this.canvasPlayerList.width = this.canvas.width;
|
||||||
this.canvasPlayerList.height = this.canvas.height;
|
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.currentScreen.setup(this.minecraft, this.width, this.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.minecraft.ingameOverlay.chatOverlay.setDirty();
|
||||||
|
|
||||||
// Render first frame
|
// Render first frame
|
||||||
if (this.minecraft.isInGame()) {
|
if (this.minecraft.isInGame()) {
|
||||||
this.minecraft.worldRenderer.render(0);
|
this.minecraft.worldRenderer.render(0);
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ export default class Minecraft {
|
|||||||
|
|
||||||
// TODO Add to settings
|
// TODO Add to settings
|
||||||
static PROXY = {
|
static PROXY = {
|
||||||
"address": "localhost",
|
"url": "wss://socket.labystudio.de/minecraft/"
|
||||||
"port": 30023
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -350,7 +349,8 @@ export default class Minecraft {
|
|||||||
|
|
||||||
// Open chat
|
// Open chat
|
||||||
if (button === this.settings.keyOpenChat) {
|
if (button === this.settings.keyOpenChat) {
|
||||||
this.displayScreen(new GuiChat());
|
this.displayScreen(new GuiChat(this));
|
||||||
|
this.ingameOverlay.chatOverlay.setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle debug overlay
|
// Toggle debug overlay
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import Command from "../Command.js";
|
|||||||
export default class TeleportCommand extends Command {
|
export default class TeleportCommand extends Command {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("tp", "<x> <y> <y>", "Teleport to a position")
|
super("tp", "<x> <y> <z>", "Teleport to a position")
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(minecraft, args) {
|
execute(minecraft, args) {
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ export default class ChatOverlay extends Gui {
|
|||||||
constructor(minecraft) {
|
constructor(minecraft) {
|
||||||
super(minecraft);
|
super(minecraft);
|
||||||
|
|
||||||
|
this.chatWidth = 320;
|
||||||
|
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
this.sentHistory = [];
|
this.sentHistory = [];
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(stack, mouseX, mouseY, partialTicks) {
|
render(stack, mouseX, mouseY, partialTicks) {
|
||||||
@@ -30,25 +33,43 @@ export default class ChatOverlay extends Gui {
|
|||||||
if (alpha > 0) {
|
if (alpha > 0) {
|
||||||
let y = this.minecraft.window.height - 40 - i * 9;
|
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.drawString(stack, message.message, 2, y, 0xffffff + (alpha << 24));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onTick() {
|
onTick() {
|
||||||
for (let i = 0; i < this.messages.length; i++) {
|
for (let i = 0; i < this.messages.length; i++) {
|
||||||
let message = this.messages[i];
|
let message = this.messages[i];
|
||||||
message.updateCounter++;
|
message.updateCounter++;
|
||||||
|
|
||||||
|
// Fade out animation
|
||||||
|
if (message.updateCounter >= 180 && message.updateCounter <= 200) {
|
||||||
|
this.dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addMessage(message) {
|
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) {
|
addMessageToSentHistory(message) {
|
||||||
this.sentHistory.splice(0, 0, 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
|
// Render hotbar
|
||||||
this.renderHotbar(stack, this.window.width / 2 - 91, this.window.height - 22);
|
this.renderHotbar(stack, this.window.width / 2 - 91, this.window.height - 22);
|
||||||
|
|
||||||
// Render chat
|
// Render chat canvas
|
||||||
this.chatOverlay.render(stack, mouseX, mouseY, partialTicks);
|
stack.drawImage(this.window.canvasChat, 0, 0);
|
||||||
|
|
||||||
// Render debug canvas on stack
|
// Render debug canvas on stack
|
||||||
if (this.minecraft.settings.debugOverlay) {
|
if (this.minecraft.settings.debugOverlay) {
|
||||||
@@ -70,6 +70,13 @@ export default class IngameOverlay extends Gui {
|
|||||||
|
|
||||||
this.ticksRendered++;
|
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) {
|
renderCrosshair(stack, x, y) {
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ import GuiTextField from "../widgets/GuiTextField.js";
|
|||||||
|
|
||||||
export default class GuiChat extends GuiScreen {
|
export default class GuiChat extends GuiScreen {
|
||||||
|
|
||||||
constructor() {
|
constructor(minecraft) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.minecraft = minecraft;
|
||||||
|
|
||||||
this.inputField = new GuiTextField(0, 0, 0, 0);
|
this.inputField = new GuiTextField(0, 0, 0, 0);
|
||||||
this.inputField.renderBackground = false;
|
this.inputField.renderBackground = false;
|
||||||
|
|
||||||
@@ -24,6 +26,11 @@ export default class GuiChat extends GuiScreen {
|
|||||||
this.buttonList.push(this.inputField);
|
this.buttonList.push(this.inputField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClose() {
|
||||||
|
super.onClose();
|
||||||
|
this.minecraft.ingameOverlay.chatOverlay.setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
||||||
this.drawRect(stack, 2, this.height - 14, this.width - 2, this.height - 2, '#000000', 0.5);
|
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) {
|
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.binaryType = "arraybuffer";
|
||||||
|
|
||||||
this.socket.onopen = e => this._onOpen(e);
|
this.socket.onopen = e => this._onOpen(e);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default class ServerJoinGamePacket extends Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
read(buffer) {
|
read(buffer) {
|
||||||
this.entityId = buffer.readVarInt();
|
this.entityId = buffer.readInt();
|
||||||
let bits = buffer.readByte();
|
let bits = buffer.readByte();
|
||||||
this.hardcoreMode = (bits & 8) === 8;
|
this.hardcoreMode = (bits & 8) === 8;
|
||||||
this.gameType = bits & -9;
|
this.gameType = bits & -9;
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ export default class FontRenderer {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
createBitMap(img) {
|
createBitMap(img) {
|
||||||
let canvas = document.createElement('canvas');
|
let canvas = document.createElement('canvas');
|
||||||
canvas.width = img.width;
|
canvas.width = img.width;
|
||||||
@@ -178,6 +177,54 @@ export default class FontRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
listFormattedStringToWidth(text, wrapWidth) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user