diff --git a/src/main/java/dan200/computercraft/api/turtle/event/FakePlayer.java b/src/main/java/dan200/computercraft/api/turtle/event/FakePlayer.java index a167e439f..eabf5914c 100644 --- a/src/main/java/dan200/computercraft/api/turtle/event/FakePlayer.java +++ b/src/main/java/dan200/computercraft/api/turtle/event/FakePlayer.java @@ -19,7 +19,7 @@ import io.netty.util.concurrent.GenericFutureListener; import net.minecraft.block.entity.CommandBlockBlockEntity; import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.command.arguments.EntityAnchorArgumentType; +import net.minecraft.command.argument.EntityAnchorArgumentType; import net.minecraft.entity.Entity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.effect.StatusEffectInstance; @@ -139,7 +139,7 @@ public class FakePlayer extends ServerPlayerEntity { protected void consumeItem() { } @Override - public void lookAt(EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d) { } + public void lookAt(EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d) {} @Override public void method_14222(EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target) { } diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java index 3961e5e9b..080a8af0f 100644 --- a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java +++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java @@ -9,191 +9,320 @@ package dan200.computercraft.client.gui; import java.util.Arrays; import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import dan200.computercraft.client.FrameInfo; +import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.TextBuffer; +import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; import org.lwjgl.opengl.GL11; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderPhase; import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.texture.TextureManager; +import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Matrix4f; +@SuppressWarnings ({ + "MethodCallSideOnly", + "LocalVariableDeclarationSideOnly", + "VariableUseSideOnly" +}) public final class FixedWidthFontRenderer { - public static final Identifier BACKGROUND = new Identifier("computercraft", "textures/gui/term_background.png"); + private static final Matrix4f IDENTITY = AffineTransformation.identity().getMatrix(); + + private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" ); + public static final int FONT_HEIGHT = 9; public static final int FONT_WIDTH = 6; - private static final Identifier FONT = new Identifier("computercraft", "textures/gui/term_font.png"); - private static FixedWidthFontRenderer instance; - private final TextureManager m_textureManager; + public static final float WIDTH = 256.0f; - private FixedWidthFontRenderer() { - this.m_textureManager = MinecraftClient.getInstance() - .getTextureManager(); + public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; + public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; + + public static final RenderLayer TYPE = Type.MAIN; + + private FixedWidthFontRenderer() + { } - public static FixedWidthFontRenderer instance() { - if (instance != null) { - return instance; - } - return instance = new FixedWidthFontRenderer(); + public static float toGreyscale( double[] rgb ) + { + return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3); } - public void drawString(TextBuffer s, int x, int y, TextBuffer textColour, TextBuffer backgroundColour, double leftMarginSize, double rightMarginSize, - boolean greyScale, Palette p) { - // Draw background - if (backgroundColour != null) { - // Bind the background texture - this.m_textureManager.bindTextureInner(BACKGROUND); - - // Draw the quads - this.drawStringBackgroundPart(x, y, backgroundColour, leftMarginSize, rightMarginSize, greyScale, p); - } - - // Draw text - if (s != null && textColour != null) { - // Bind the font texture - this.bindFont(); - - // Draw the quads - this.drawStringTextPart(x, y, s, textColour, greyScale, p); - } + public static int getColour( char c, Colour def ) + { + return 15 - Terminal.getColour(c, def ); } - public void drawStringBackgroundPart(int x, int y, TextBuffer backgroundColour, double leftMarginSize, double rightMarginSize, boolean greyScale, - Palette p) { - // Draw the quads - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder renderer = tessellator.getBuffer(); - renderer.begin(GL11.GL_TRIANGLES, VertexFormats.POSITION_COLOR); - if (leftMarginSize > 0.0) { - int colour1 = "0123456789abcdef".indexOf(backgroundColour.charAt(0)); - if (colour1 < 0 || (greyScale && !this.isGreyScale(colour1))) { - colour1 = 15; + private static void drawQuad(Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b ) + { + buffer.vertex( transform, x, y, 0 ).color( r, g, b, 1.0f ).texture( BACKGROUND_START, BACKGROUND_START ).next(); + buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).texture( BACKGROUND_START, BACKGROUND_END ).next(); + buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).texture( BACKGROUND_END, BACKGROUND_START ).next(); + buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).texture( BACKGROUND_END, BACKGROUND_START ).next(); + buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).texture( BACKGROUND_START, BACKGROUND_END ).next(); + buffer.vertex( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).texture( BACKGROUND_END, BACKGROUND_END ).next(); + } + + private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex ) + { + double[] colour = palette.getColour( getColour( colourIndex, Colour.Black ) ); + float r, g, b; + if( greyscale ) + { + r = g = b = toGreyscale( colour ); + } + else + { + r = (float) colour[0]; + g = (float) colour[1]; + b = (float) colour[2]; + } + + drawQuad( transform, buffer, x, y, width, height, r, g, b ); + } + + private static void drawBackground( + Matrix4f transform, VertexConsumer renderer, float x, float y, + TextBuffer backgroundColour, Palette palette, boolean greyscale, + float leftMarginSize, float rightMarginSize, float height + ) + { + if( leftMarginSize > 0 ) + { + drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); + } + + if( rightMarginSize > 0 ) + { + drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) ); + } + + // Batch together runs of identical background cells. + int blockStart = 0; + char blockColour = '\0'; + for( int i = 0; i < backgroundColour.length(); i++ ) + { + char colourIndex = backgroundColour.charAt( i ); + if( colourIndex == blockColour ) continue; + + if( blockColour != '\0' ) + { + drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); } - this.drawQuad(renderer, x - leftMarginSize, y, colour1, leftMarginSize, p, greyScale); + + blockColour = colourIndex; + blockStart = i; } - if (rightMarginSize > 0.0) { - int colour2 = "0123456789abcdef".indexOf(backgroundColour.charAt(backgroundColour.length() - 1)); - if (colour2 < 0 || (greyScale && !this.isGreyScale(colour2))) { - colour2 = 15; - } - this.drawQuad(renderer, x + backgroundColour.length() * FONT_WIDTH, y, colour2, rightMarginSize, p, greyScale); + + if( blockColour != '\0' ) + { + drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour ); } - for (int i = 0; i < backgroundColour.length(); i++) { - int colour = "0123456789abcdef".indexOf(backgroundColour.charAt(i)); - if (colour < 0 || (greyScale && !this.isGreyScale(colour))) { - colour = 15; - } - this.drawQuad(renderer, x + i * FONT_WIDTH, y, colour, FONT_WIDTH, p, greyScale); - } - GlStateManager.disableTexture(); - tessellator.draw(); - GlStateManager.enableTexture(); } - public void bindFont() { - this.m_textureManager.bindTextureInner(FONT); - GlStateManager.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP); - } + public static void drawString( + Matrix4f transform, VertexConsumer renderer, float x, float y, + TextBuffer text, TextBuffer textColour, TextBuffer backgroundColour, + Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize + ) + { + if( backgroundColour != null ) + { + drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT ); + } - public void drawStringTextPart(int x, int y, TextBuffer s, TextBuffer textColour, boolean greyScale, Palette p) { - // Draw the quads - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder renderer = tessellator.getBuffer(); - renderer.begin(GL11.GL_TRIANGLES, VertexFormats.POSITION_TEXTURE_COLOR); - for (int i = 0; i < s.length(); i++) { - // Switch colour - int colour = "0123456789abcdef".indexOf(textColour.charAt(i)); - if (colour < 0 || (greyScale && !this.isGreyScale(colour))) { - colour = 0; + for( int i = 0; i < text.length(); i++ ) + { + double[] colour = palette.getColour( getColour( textColour.charAt( i ), Colour.Black ) ); + float r, g, b; + if( greyscale ) + { + r = g = b = toGreyscale( colour ); + } + else + { + r = (float) colour[0]; + g = (float) colour[1]; + b = (float) colour[2]; } // Draw char - int index = s.charAt(i); - if (index < 0 || index > 255) { - index = '?'; + int index = text.charAt( i ); + if( index > 255 ) index = '?'; + drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b ); + } + + } + + public static void drawString( + float x, float y, TextBuffer text, TextBuffer textColour, TextBuffer backgroundColour, + Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize + ) + { + bindFont(); + + VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + drawString( IDENTITY, ((VertexConsumerProvider) renderer).getBuffer( TYPE ), x, y, text, textColour, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize ); + renderer.draw(); + } + + public static void drawTerminalWithoutCursor( + Matrix4f transform, VertexConsumer buffer, float x, float y, + Terminal terminal, boolean greyscale, + float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize + ) + { + Palette palette = terminal.getPalette(); + int height = terminal.getHeight(); + + // Top and bottom margins + drawBackground( + transform, buffer, x, y - topMarginSize, + terminal.getBackgroundColourLine( 0 ), palette, greyscale, + leftMarginSize, rightMarginSize, topMarginSize + ); + + drawBackground( + transform, buffer, x, y + height * FONT_HEIGHT, + terminal.getBackgroundColourLine( height - 1 ), palette, greyscale, + leftMarginSize, rightMarginSize, bottomMarginSize + ); + + // The main text + for( int i = 0; i < height; i++ ) + { + drawString( + transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i, + terminal.getLine( i ), terminal.getTextColourLine( i ), terminal.getBackgroundColourLine( i ), + palette, greyscale, leftMarginSize, rightMarginSize + ); + } + } + + public static void drawCursor( + Matrix4f transform, VertexConsumer buffer, float x, float y, + Terminal terminal, boolean greyscale + ) + { + Palette palette = terminal.getPalette(); + int width = terminal.getWidth(); + int height = terminal.getHeight(); + + int cursorX = terminal.getCursorX(); + int cursorY = terminal.getCursorY(); + if(terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height && FrameInfo.getGlobalCursorBlink() ) + { + double[] colour = palette.getColour( 15 - terminal.getTextColour() ); + float r, g, b; + if( greyscale ) + { + r = g = b = toGreyscale( colour ); } - this.drawChar(renderer, x + i * FONT_WIDTH, y, index, colour, p, greyScale); + else + { + r = (float) colour[0]; + g = (float) colour[1]; + b = (float) colour[2]; + } + + drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b ); } - tessellator.draw(); } - private boolean isGreyScale(int colour) { - return colour == 0 || colour == 15 || colour == 7 || colour == 8; + public static void drawTerminal( + Matrix4f transform, VertexConsumer buffer, float x, float y, + Terminal terminal, boolean greyscale, + float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize + ) + { + drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + drawCursor( transform, buffer, x, y, terminal, greyscale ); } - private void drawQuad(BufferBuilder renderer, double x, double y, int color, double width, Palette p, boolean greyscale) { - double[] colour = p.getColour(15 - color); - if (greyscale) { - greyscaleify(colour); - } - float r = (float) colour[0]; - float g = (float) colour[1]; - float b = (float) colour[2]; + public static void drawTerminal( + Matrix4f transform, float x, float y, Terminal terminal, boolean greyscale, + float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize + ) + { + bindFont(); - renderer.vertex(x, y, 0.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x, y + FONT_HEIGHT, 0.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x + width, y, 0.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x + width, y, 0.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x, y + FONT_HEIGHT, 0.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x + width, y + FONT_HEIGHT, 0.0) - .color(r, g, b, 1.0f) - .next(); + VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + VertexConsumer buffer = renderer.getBuffer( TYPE ); + drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + renderer.draw( TYPE ); } - private void drawChar(BufferBuilder renderer, double x, double y, int index, int color, Palette p, boolean greyscale) { + public static void drawTerminal( + float x, float y, Terminal terminal, boolean greyscale, + float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize + ) + { + drawTerminal( IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); + } + + public static void drawEmptyTerminal( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float width, float height ) + { + Colour colour = Colour.Black; + drawQuad( transform, renderer.getBuffer( TYPE ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + } + + public static void drawEmptyTerminal( Matrix4f transform, float x, float y, float width, float height ) + { + bindFont(); + + VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + drawEmptyTerminal( transform, renderer, x, y, width, height ); + renderer.draw(); + } + + public static void drawEmptyTerminal( float x, float y, float width, float height ) + { + drawEmptyTerminal( IDENTITY, x, y, width, height ); + } + + public static void drawBlocker( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float width, float height ) + { + Colour colour = Colour.Black; + drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + } + + private static void bindFont() + { + MinecraftClient.getInstance().getTextureManager().bindTexture( FONT ); + RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); + } + + private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b ) + { + // Short circuit to avoid the common case - the texture should be blank here after all. + if( index == '\0' || index == ' ' ) return; + int column = index % 16; int row = index / 16; - double[] colour = p.getColour(15 - color); - if (greyscale) { - greyscaleify(colour); - } - float r = (float) colour[0]; - float g = (float) colour[1]; - float b = (float) colour[2]; - int xStart = 1 + column * (FONT_WIDTH + 2); int yStart = 1 + row * (FONT_HEIGHT + 2); - renderer.vertex(x, y, 0.0) - .texture(xStart / 256.0, yStart / 256.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x, y + FONT_HEIGHT, 0.0) - .texture(xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x + FONT_WIDTH, y, 0.0) - .texture((xStart + FONT_WIDTH) / 256.0, yStart / 256.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x + FONT_WIDTH, y, 0.0) - .texture((xStart + FONT_WIDTH) / 256.0, yStart / 256.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x, y + FONT_HEIGHT, 0.0) - .texture(xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0) - .color(r, g, b, 1.0f) - .next(); - renderer.vertex(x + FONT_WIDTH, y + FONT_HEIGHT, 0.0) - .texture((xStart + FONT_WIDTH) / 256.0, (yStart + FONT_HEIGHT) / 256.0) - .color(r, g, b, 1.0f) - .next(); + buffer.vertex( transform, x, y, 0f ).color( r, g, b, 1.0f ).texture( xStart / WIDTH, yStart / WIDTH ).next(); + buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).next(); + buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).next(); + buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).next(); + buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).next(); + buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).texture( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).next(); } + private static void greyscaleify(double[] rgb) { Arrays.fill(rgb, (rgb[0] + rgb[1] + rgb[2]) / 3.0f); } @@ -204,4 +333,39 @@ public final class FixedWidthFontRenderer { } return s.length() * FONT_WIDTH; } + + private static final class Type extends RenderPhase + { + private static final int GL_MODE = GL11.GL_TRIANGLES; + + private static final VertexFormat FORMAT = VertexFormats.POSITION_COLOR_TEXTURE; + + static final RenderLayer MAIN = RenderLayer.of( + "terminal_font", FORMAT, GL_MODE, 1024, + false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( new Texture(FONT, false, false ) ) // blur, minimap + .alpha( ONE_TENTH_ALPHA ) + .lightmap( DISABLE_LIGHTMAP ) + .writeMaskState( COLOR_MASK ) + .build( false ) + ); + + static final RenderLayer BLOCKER = RenderLayer.of( + "terminal_blocker", FORMAT, GL_MODE, 256, + false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( new Texture(FONT, false, false ) ) // blur, minimap + .alpha( ONE_TENTH_ALPHA ) + .writeMaskState( DEPTH_MASK ) + .lightmap( DISABLE_LIGHTMAP ) + .build( false ) + ); + + private Type( String name, Runnable setup, Runnable destroy ) + { + super( name, setup, destroy ); + } + + } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java index e9a1b6704..99e066cdf 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -25,6 +25,7 @@ import net.minecraft.text.LiteralText; import net.minecraft.util.Identifier; public class GuiComputer extends HandledScreen { + private static final MinecraftClient MINECRAFT = MinecraftClient.getInstance(); public static final Identifier BACKGROUND_NORMAL = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_normal.png"); public static final Identifier BACKGROUND_ADVANCED = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png"); public static final Identifier BACKGROUND_COMMAND = new Identifier(ComputerCraft.MOD_ID, "textures/gui/corners_command.png"); @@ -60,7 +61,7 @@ public class GuiComputer extends HandledScreen { @Override protected void init() { - MinecraftClient.getInstance().keyboard.enableRepeatEvents(true); + MinecraftClient.getInstance().keyboard.setRepeatEvents(true); int termPxWidth = this.m_termWidth * FixedWidthFontRenderer.FONT_WIDTH; int termPxHeight = this.m_termHeight * FixedWidthFontRenderer.FONT_HEIGHT; @@ -70,7 +71,7 @@ public class GuiComputer extends HandledScreen { super.init(); - this.terminal = new WidgetTerminal(minecraft, () -> this.m_computer, this.m_termWidth, this.m_termHeight, 2, 2, 2, 2); + this.terminal = new WidgetTerminal(MINECRAFT, () -> this.m_computer, this.m_termWidth, this.m_termHeight, 2, 2, 2, 2); this.terminalWrapper = new WidgetWrapper(this.terminal, 2 + 12 + this.x, 2 + 12 + this.y, termPxWidth, termPxHeight); this.children.add(this.terminalWrapper); @@ -100,16 +101,16 @@ public class GuiComputer extends HandledScreen { switch (this.m_family) { case Normal: default: - minecraft.getTextureManager() - .bindTextureInner(BACKGROUND_NORMAL); + MINECRAFT.getTextureManager() + .bindTexture(BACKGROUND_NORMAL); break; case Advanced: - minecraft.getTextureManager() - .bindTextureInner(BACKGROUND_ADVANCED); + MINECRAFT.getTextureManager() + .bindTexture(BACKGROUND_ADVANCED); break; case Command: - minecraft.getTextureManager() - .bindTextureInner(BACKGROUND_COMMAND); + MINECRAFT.getTextureManager() + .bindTexture(BACKGROUND_COMMAND); break; } @@ -152,7 +153,7 @@ public class GuiComputer extends HandledScreen { super.removed(); this.children.remove(this.terminal); this.terminal = null; - minecraft.keyboard.enableRepeatEvents(false); + MINECRAFT.keyboard.setRepeatEvents(false); } @Override diff --git a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java index 10c157e26..14fec5758 100644 --- a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -9,20 +9,23 @@ package dan200.computercraft.client.render; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.GlStateManager.DestFactor; -import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.util.Palette; import org.lwjgl.opengl.GL11; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderPhase; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexFormats; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Matrix4f; +@SuppressWarnings ({ + "LocalVariableDeclarationSideOnly", + "MethodCallSideOnly" +}) public final class PrintoutRenderer { /** * Width of a page @@ -45,7 +48,7 @@ public final class PrintoutRenderer { */ public static final int COVER_SIZE = 12; private static final Identifier BG = new Identifier("computercraft", "textures/gui/printout.png"); - private static final double BG_SIZE = 256.0; + private static final float BG_SIZE = 256.0f; /** * Width of the extra page texture */ @@ -55,125 +58,120 @@ public final class PrintoutRenderer { private PrintoutRenderer() {} - public static void drawText(int x, int y, int start, TextBuffer[] text, TextBuffer[] colours) { - FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance(); - - for (int line = 0; line < LINES_PER_PAGE && line < text.length; line++) { - fontRenderer.drawString(text[start + line], x, y + line * FONT_HEIGHT, colours[start + line], null, 0, 0, false, Palette.DEFAULT); + public static void drawText(Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours) { + VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) + { + FixedWidthFontRenderer.drawString( transform, buffer, + x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], null, Palette.DEFAULT, + false, 0, 0 + ); } } - public static void drawText(int x, int y, int start, String[] text, String[] colours) { - GlStateManager.color4f(1.0f, 1.0f, 1.0f, 1.0f); - GlStateManager.enableBlend(); - GlStateManager.enableTexture(); - GlStateManager.blendFuncSeparate(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO); - - FixedWidthFontRenderer fontRenderer = FixedWidthFontRenderer.instance(); - - for (int line = 0; line < LINES_PER_PAGE && line < text.length; line++) { - fontRenderer.drawString(new TextBuffer(text[start + line]), - x, - y + line * FONT_HEIGHT, - new TextBuffer(colours[start + line]), - null, - 0, - 0, - false, - Palette.DEFAULT); + public static void drawText(Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours) { + VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) + { + FixedWidthFontRenderer.drawString( transform, buffer, + x, y + line * FONT_HEIGHT, + new TextBuffer( text[start + line] ), new TextBuffer( colours[start + line] ), + null, Palette.DEFAULT, false, 0, 0 + ); } } - public static void drawBorder(double x, double y, double z, int page, int pages, boolean isBook) { - GlStateManager.color4f(1.0f, 1.0f, 1.0f, 1.0f); - GlStateManager.enableBlend(); - GlStateManager.enableTexture(); - GlStateManager.blendFuncSeparate(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO); - - MinecraftClient.getInstance() - .getTextureManager() - .bindTextureInner(BG); - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_TEXTURE); - + @SuppressWarnings ("MethodCallSideOnly") + public static void drawBorder(Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook) { int leftPages = page; int rightPages = pages - page - 1; - if (isBook) { + VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); + + if( isBook ) + { // Border - double offset = offsetAt(pages); - final double left = x - 4 - offset; - final double right = x + X_SIZE + offset - 4; + float offset = offsetAt( pages ); + float left = x - 4 - offset; + float right = x + X_SIZE + offset - 4; // Left and right border - drawTexture(buffer, left - 4, y - 8, z - 0.02, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2); - drawTexture(buffer, right, y - 8, z - 0.02, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2); + drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); + drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); // Draw centre panel (just stretched texture, sorry). - drawTexture(buffer, x - offset, y, z - 0.02, X_SIZE + offset * 2, Y_SIZE, COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE); + drawTexture( transform, buffer, + x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE, + COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE + ); - double borderX = left; - while (borderX < right) { - double thisWidth = Math.min(right - borderX, X_SIZE); - drawTexture(buffer, borderX, y - 8, z - 0.02, 0, COVER_Y, thisWidth, COVER_SIZE); - drawTexture(buffer, borderX, y + Y_SIZE - 4, z - 0.02, 0, COVER_Y + COVER_SIZE, thisWidth, COVER_SIZE); + float borderX = left; + while( borderX < right ) + { + double thisWidth = Math.min( right - borderX, X_SIZE ); + drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE ); + drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE ); borderX += thisWidth; } } // Left half - drawTexture(buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE); - for (int n = 0; n <= leftPages; n++) { - drawTexture(buffer, x - offsetAt(n), y, z - 1e-3 * n, - // Use the left "bold" fold for the outermost page - n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE); + drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE ); + for( int n = 0; n <= leftPages; n++ ) + { + drawTexture( transform, buffer, + x - offsetAt( n ), y, z - 1e-3f * n, + // Use the left "bold" fold for the outermost page + n == leftPages ? 0 : X_FOLD_SIZE, 0, + X_FOLD_SIZE, Y_SIZE + ); } // Right half - drawTexture(buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE); - for (int n = 0; n <= rightPages; n++) { - drawTexture(buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt(n), y, z - 1e-3 * n, - // Two folds, then the main page. Use the right "bold" fold for the outermost page. - X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE); + drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE ); + for( int n = 0; n <= rightPages; n++ ) + { + drawTexture( transform, buffer, + x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n, + // Two folds, then the main page. Use the right "bold" fold for the outermost page. + X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, + X_FOLD_SIZE, Y_SIZE + ); } - - tessellator.draw(); } - public static double offsetAt(int page) { - return 32 * (1 - Math.pow(1.2, -page)); + private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height ) + { + buffer.vertex( matrix, x, y + height, z ).texture( u / BG_SIZE, (v + height) / BG_SIZE ).next(); + buffer.vertex( matrix, x + width, y + height, z ).texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).next(); + buffer.vertex( matrix, x + width, y, z ).texture( (u + width) / BG_SIZE, v / BG_SIZE ).next(); + buffer.vertex( matrix, x, y, z ).texture( u / BG_SIZE, v / BG_SIZE ).next(); } - private static void drawTexture(BufferBuilder buffer, double x, double y, double z, double u, double v, double width, double height) { - buffer.vertex(x, y + height, z) - .texture(u / BG_SIZE, (v + height) / BG_SIZE) - .next(); - buffer.vertex(x + width, y + height, z) - .texture((u + width) / BG_SIZE, (v + height) / BG_SIZE) - .next(); - buffer.vertex(x + width, y, z) - .texture((u + width) / BG_SIZE, v / BG_SIZE) - .next(); - buffer.vertex(x, y, z) - .texture(u / BG_SIZE, v / BG_SIZE) - .next(); + private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight ) + { + buffer.vertex( matrix, x, y + height, z ).texture( u / BG_SIZE, (v + tHeight) / BG_SIZE ).next(); + buffer.vertex( matrix, x + width, y + height, z ).texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).next(); + buffer.vertex( matrix, x + width, y, z ).texture( (u + tWidth) / BG_SIZE, v / BG_SIZE ).next(); + buffer.vertex( matrix, x, y, z ).texture( u / BG_SIZE, v / BG_SIZE ).next(); } - private static void drawTexture(BufferBuilder buffer, double x, double y, double z, double width, double height, double u, double v, double tWidth, - double tHeight) { - buffer.vertex(x, y + height, z) - .texture(u / BG_SIZE, (v + tHeight) / BG_SIZE) - .next(); - buffer.vertex(x + width, y + height, z) - .texture((u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE) - .next(); - buffer.vertex(x + width, y, z) - .texture((u + tWidth) / BG_SIZE, v / BG_SIZE) - .next(); - buffer.vertex(x, y, z) - .texture(u / BG_SIZE, v / BG_SIZE) - .next(); + public static float offsetAt( int page ) + { + return (float) (32 * (1 - Math.pow( 1.2, -page ))); + } + + private static final class Type extends RenderPhase { + static final RenderLayer TYPE = RenderLayer.of("printout_background", VertexFormats.POSITION_COLOR_TEXTURE, GL11.GL_QUADS, 1024, false, false, + // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture(new RenderLayer.Texture(BG, false, false)) // blur, minimap + .alpha(ONE_TENTH_ALPHA) + .lightmap(DISABLE_LIGHTMAP) + .build(false)); + + private Type(String name, Runnable setup, Runnable destroy) { + super(name, setup, destroy); + } } } diff --git a/src/main/java/dan200/computercraft/core/terminal/Terminal.java b/src/main/java/dan200/computercraft/core/terminal/Terminal.java index d3d8bf64f..aee110554 100644 --- a/src/main/java/dan200/computercraft/core/terminal/Terminal.java +++ b/src/main/java/dan200/computercraft/core/terminal/Terminal.java @@ -6,6 +6,7 @@ package dan200.computercraft.core.terminal; +import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; import net.minecraft.nbt.CompoundTag; @@ -321,4 +322,11 @@ public class Terminal { } this.setChanged(); } + + public static int getColour( char c, Colour def ) + { + if( c >= '0' && c <= '9' ) return c - '0'; + if( c >= 'a' && c <= 'f' ) return c - 'a' + 10; + return 15 - def.ordinal(); + } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index d5ad648bb..c089207eb 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -173,8 +173,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } @Override - public void fromTag(CompoundTag nbt) { - super.fromTag(nbt); + public void fromTag(BlockState state, CompoundTag nbt) { + super.fromTag(state, nbt); this.customName = nbt.contains(NBT_NAME) ? LiteralText.Serializer.fromJson(nbt.getString(NBT_NAME)) : null; @@ -492,6 +492,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Nonnull @Override public Text getName() { + // todo possible crash problem + //noinspection MethodCallSideOnly return this.customName != null ? this.customName : this.getCachedState().getBlock() .getName(); }