diff --git a/build.gradle b/build.gradle index b49f56074..b831ba06c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.7-SNAPSHOT' + id 'fabric-loom' version '0.9-SNAPSHOT' id 'maven-publish' id "checkstyle" id "com.github.hierynomus.license" version "0.15.0" @@ -21,12 +21,17 @@ repositories { mavenCentral() maven { url 'https://jitpack.io' } maven { url "https://maven.shedaniel.me/" } + maven { url "https://maven.terraformersmc.com/" } maven { name "SquidDev" url "https://squiddev.cc/maven" } } +loom { + accessWidenerPath = file("src/main/resources/cc.accesswidener") +} + configurations { implementation.extendsFrom shade } @@ -42,7 +47,7 @@ dependencies { modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") { exclude(group: "net.fabricmc.fabric-api") } - modImplementation "io.github.prospector:modmenu:${modmenu_version}" + modImplementation "com.terraformersmc:modmenu:${modmenu_version}" modImplementation "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}" implementation 'com.electronwill.night-config:toml:3.6.3' @@ -55,8 +60,8 @@ dependencies { include 'com.electronwill.night-config:toml:3.6.3' include "me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}" - modRuntime "me.shedaniel:RoughlyEnoughItems-api:6.0.254-alpha" - modRuntime "me.shedaniel:RoughlyEnoughItems:6.0.254-alpha" + modRuntime "me.shedaniel:RoughlyEnoughItems-api-fabric:6.0.254-alpha" + modRuntime "me.shedaniel:RoughlyEnoughItems-fabric:6.0.254-alpha" } processResources { diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java index c77ba5d3c..ced11128e 100644 --- a/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -7,6 +7,7 @@ package dan200.computercraft; import dan200.computercraft.api.turtle.event.TurtleAction; +import dan200.computercraft.client.render.MonitorTextureBufferShader; import dan200.computercraft.core.apis.http.options.Action; import dan200.computercraft.core.apis.http.options.AddressRule; import dan200.computercraft.shared.common.ColourableRecipe; @@ -30,6 +31,7 @@ import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.fabricmc.fabric.api.resource.ResourcePackActivationType; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.render.*; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; @@ -37,6 +39,7 @@ import net.minecraft.util.registry.Registry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import javax.annotation.Nullable; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; @@ -81,6 +84,7 @@ public final class ComputerCraft implements ModInitializer public static int maxNotesPerTick = 8; public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; public static double monitorDistanceSq = 4096; + public static int monitorDistance = 65; public static long monitorBandwidth = 1_000_000; public static boolean turtlesNeedFuel = true; diff --git a/src/main/java/dan200/computercraft/client/ClientRegistry.java b/src/main/java/dan200/computercraft/client/ClientRegistry.java index eb66e181a..25ac05541 100644 --- a/src/main/java/dan200/computercraft/client/ClientRegistry.java +++ b/src/main/java/dan200/computercraft/client/ClientRegistry.java @@ -77,7 +77,7 @@ public final class ClientRegistry } @SuppressWarnings( "NewExpressionSideOnly" ) - public static void onModelBakeEvent( ResourceManager manager, Consumer out ) + public static void onModelBakeEvent( ResourceManager manager, Consumer out ) { for( String model : EXTRA_MODELS ) { diff --git a/src/main/java/dan200/computercraft/client/gui/ComputerScreenBase.java b/src/main/java/dan200/computercraft/client/gui/ComputerScreenBase.java new file mode 100644 index 000000000..c48837f29 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/gui/ComputerScreenBase.java @@ -0,0 +1,96 @@ +package dan200.computercraft.client.gui; + +import dan200.computercraft.client.gui.widgets.WidgetTerminal; +import dan200.computercraft.shared.computer.core.ClientComputer; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import org.lwjgl.glfw.GLFW; + +import javax.annotation.Nonnull; + +public abstract class ComputerScreenBase extends HandledScreen { + + private static final Text OK = new TranslatableText( "gui.ok" ); + private static final Text CANCEL = new TranslatableText( "gui.cancel" ); + private static final Text OVERWRITE = new TranslatableText( "gui.computercraft.upload.overwrite_button" ); + + protected WidgetTerminal terminal; + protected final ClientComputer computer; + protected final ComputerFamily family; + + protected final int sidebarYOffset = 0; + + public ComputerScreenBase(T container, PlayerInventory player, Text title, int sidebarYOffset ) + { + super( container, player, title ); + computer = (ClientComputer) container.getComputer(); + family = container.getFamily(); +// this.sidebarYOffset = sidebarYOffset; + } + + protected abstract WidgetTerminal createTerminal(); + + @Override + protected final void init() + { + super.init(); + client.keyboard.setRepeatEvents( true ); + + terminal = addDrawableChild( createTerminal() ); +// ComputerSidebar.addButtons( this, computer, this::addButton, leftPos, topPos + sidebarYOffset ); + setFocused( terminal ); + } + + @Override + public final void removed() + { + super.removed(); + client.keyboard.setRepeatEvents( false ); + } + + @Override + public final void handledScreenTick() + { + super.handledScreenTick(); + terminal.update(); + } + + @Override + public final boolean keyPressed( int key, int scancode, int modifiers ) + { + // Forward the tab key to the terminal, rather than moving between controls. + if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminal ) + { + return getFocused().keyPressed( key, scancode, modifiers ); + } + + return super.keyPressed( key, scancode, modifiers ); + } + + @Override + public final void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) + { + renderBackground( stack ); + super.render( stack, mouseX, mouseY, partialTicks ); + drawMouseoverTooltip( stack, mouseX, mouseY ); + } + + @Override + public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) + { + return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY )) + || super.mouseDragged( x, y, button, deltaX, deltaY ); + } + + @Override + protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) + { + // Skip rendering labels. + } + +} diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java index 72d9ec931..9134c2c74 100644 --- a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java +++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java @@ -7,9 +7,13 @@ package dan200.computercraft.client.gui; import com.mojang.blaze3d.systems.RenderSystem; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.FrameInfo; +import dan200.computercraft.client.render.MonitorTextureBufferShader; +import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.TextBuffer; +//import dan200.computercraft.fabric.mixin.RenderLayerAccessor; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; import net.minecraft.client.MinecraftClient; @@ -30,45 +34,17 @@ public final class FixedWidthFontRenderer public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; private static final Matrix4f IDENTITY = AffineTransformation.identity() - .getMatrix(); + .getMatrix(); public static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" ); // public static final RenderLayer TYPE = Type.MAIN; +// public static final RenderLayer MONITOR_TBO = Type.MONITOR_TBO; +// public static final Shader FONT_SHADER = new Shader(); private FixedWidthFontRenderer() { } - public static void drawString( float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, - @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize ) - { - bindFont(); - - VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - drawString( IDENTITY, - Tessellator.getInstance().getBuffer(), - x, - y, - text, - textColour, - backgroundColour, - palette, - greyscale, - leftMarginSize, - rightMarginSize ); - renderer.draw(); - } - - private static void bindFont() - { - MinecraftClient.getInstance() - .getTextureManager() - .bindTexture( FONT ); - RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); - } - public static void drawString( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize ) @@ -342,12 +318,12 @@ public final class FixedWidthFontRenderer public static void drawTerminal( @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize ) { - bindFont(); +// bindFont(); VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() .getBufferBuilders() .getEntityVertexConsumers(); - VertexConsumer buffer = Tessellator.getInstance().getBuffer(); + VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ); drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); renderer.draw(); } @@ -360,12 +336,13 @@ public final class FixedWidthFontRenderer public static void drawEmptyTerminal( float x, float y, float width, float height ) { + Colour colour = Colour.BLACK; drawEmptyTerminal( IDENTITY, x, y, width, height ); } public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height ) { - bindFont(); +// bindFont(); VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() .getBufferBuilders() @@ -378,44 +355,12 @@ public final class FixedWidthFontRenderer float height ) { Colour colour = Colour.BLACK; - drawQuad( transform, Tessellator.getInstance().getBuffer(), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); } public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, float height ) { Colour colour = Colour.BLACK; - drawQuad( transform, Tessellator.getInstance().getBuffer(), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); + drawQuad( transform, renderer.getBuffer(RenderTypes.TERMINAL_BLOCKER), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); } - -// 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 RenderPhase.Texture( FONT, -// false, -// false ) ) // blur, minimap -// .transparency( TRANSLUCENT_TRANSPARENCY ) -// .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 RenderPhase.Texture( FONT, -// false, -// false ) ) // blur, minimap -// .transparency( TRANSLUCENT_TRANSPARENCY ) -// .writeMaskState( ALL_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 775c74109..79534ab71 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -11,6 +11,7 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetWrapper; import dan200.computercraft.client.render.ComputerBorderRenderer; +import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.inventory.ContainerComputer; @@ -25,29 +26,23 @@ import org.lwjgl.glfw.GLFW; import javax.annotation.Nonnull; -import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; -import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; - import java.util.List; -public class GuiComputer extends HandledScreen +import static dan200.computercraft.client.render.ComputerBorderRenderer.*; + +public final class GuiComputer extends ComputerScreenBase { - protected final ComputerFamily family; - protected final ClientComputer computer; private final int termWidth; private final int termHeight; - protected WidgetTerminal terminal; - protected WidgetWrapper terminalWrapper; - - protected GuiComputer( T container, PlayerInventory player, Text title, int termWidth, int termHeight ) + private GuiComputer( T container, PlayerInventory player, Text title, int termWidth, int termHeight ) { - super( container, player, title ); - this.family = container.getFamily(); - this.computer = (ClientComputer) container.getComputer(); + super( container, player, title, BORDER ); this.termWidth = termWidth; this.termHeight = termHeight; - this.terminal = null; + + backgroundWidth = WidgetTerminal.getWidth( termWidth ) + BORDER * 2; + backgroundHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2; } public static GuiComputer create( ContainerComputer container, PlayerInventory inventory, Text component ) @@ -65,96 +60,18 @@ public class GuiComputer extends HandledScreen< return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() ); } - protected void initTerminal( int border, int widthExtra, int heightExtra ) - { - client.keyboard.setRepeatEvents( true ); - - int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH; - int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT; - - backgroundWidth = termPxWidth + MARGIN * 2 + border * 2 + widthExtra; - backgroundHeight = termPxHeight + MARGIN * 2 + border * 2 + heightExtra; - - super.init(); - - terminal = new WidgetTerminal( client, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN ); - terminalWrapper = new WidgetWrapper( terminal, MARGIN + border + x, MARGIN + border + y, termPxWidth, termPxHeight ); - - ((List)children()).add( terminalWrapper ); //FIXME: This is bad. - setFocused( terminalWrapper ); - } - @Override - protected void init() + protected WidgetTerminal createTerminal() { - initTerminal( BORDER, 0, 0 ); + return new WidgetTerminal( computer, + x + BORDER, y + BORDER, termWidth, termHeight + ); } - - @Override - public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) - { - this.renderBackground( stack ); - super.render( stack, mouseX, mouseY, partialTicks ); - drawMouseoverTooltip( stack, mouseX, mouseY ); - } - - @Override - protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) - { - // Skip rendering labels. - } - @Override public void drawBackground( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY ) { - // Draw terminal - terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() ); - - // Draw a border around the terminal - RenderSystem.clearColor( 1, 1, 1, 1 ); - client.getTextureManager() - .bindTexture( ComputerBorderRenderer.getTexture( family ) ); - ComputerBorderRenderer.render( terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, - getZOffset(), terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2 ); - } - - @Override - public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) - { - return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY ); - } - - @Override - public boolean mouseReleased( double mouseX, double mouseY, int button ) - { - return (getFocused() != null && getFocused().mouseReleased( mouseX, mouseY, button )) || super.mouseReleased( x, y, button ); - } - - @Override - public boolean keyPressed( int key, int scancode, int modifiers ) - { - // Forward the tab key to the terminal, rather than moving between controls. - if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper ) - { - return getFocused().keyPressed( key, scancode, modifiers ); - } - - return super.keyPressed( key, scancode, modifiers ); - } - - @Override - public void removed() - { - super.removed(); - children().remove( terminal ); - terminal = null; - client.keyboard.setRepeatEvents( false ); - } - - @Override - public void handledScreenTick() - { - super.handledScreenTick(); // FIXME most likely unneeded. - terminal.update(); + ComputerBorderRenderer.render( + getTexture(family), terminal.x, terminal.y, getZOffset(), + RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() ); } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java index d1d647e82..127f78896 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java @@ -7,8 +7,10 @@ package dan200.computercraft.client.gui; import com.mojang.blaze3d.systems.RenderSystem; +import dan200.computercraft.client.render.ComputerBorderRenderer; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.render.GameRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.text.Text; @@ -36,9 +38,9 @@ public class GuiDiskDrive extends HandledScreen @Override protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) { - RenderSystem.clearColor( 1.0F, 1.0F, 1.0F, 1.0F ); - client.getTextureManager() - .bindTexture( BACKGROUND ); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, BACKGROUND); drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight ); } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java index afdab5ae0..e6517ff7d 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java @@ -8,6 +8,8 @@ package dan200.computercraft.client.gui; import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; +import dan200.computercraft.client.gui.widgets.WidgetTerminal; +import dan200.computercraft.client.render.ComputerBorderRenderer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import net.minecraft.client.util.math.MatrixStack; @@ -17,40 +19,51 @@ import net.minecraft.util.Identifier; import javax.annotation.Nonnull; -public class GuiTurtle extends GuiComputer +import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.BORDER; + +public class GuiTurtle extends ComputerScreenBase { private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" ); private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" ); - private final ContainerTurtle container; + + private static final int TEX_WIDTH = 254; + private static final int TEX_HEIGHT = 217; + + private final ComputerFamily family; public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title ) { - super( container, player, title, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight ); + super( container, player, title, BORDER ); - this.container = container; + family = container.getFamily(); + backgroundWidth = TEX_WIDTH; + backgroundHeight = TEX_HEIGHT; + + } + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + System.out.println(mouseX + " " + mouseY + " " + button); + return super.mouseClicked(mouseX, mouseY, button); } @Override - protected void init() + protected WidgetTerminal createTerminal() { - initTerminal( 8, 0, 80 ); + return new WidgetTerminal( + computer, x + BORDER, y + BORDER, + ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight + ); } @Override public void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) { - // Draw term - Identifier texture = family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; - terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() ); - - // Draw border/inventory - RenderSystem.clearColor( 1.0F, 1.0F, 1.0F, 1.0F ); - client.getTextureManager() - .bindTexture( texture ); - drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight ); + boolean advanced = family == ComputerFamily.ADVANCED; + RenderSystem.setShaderTexture( 0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL ); + drawTexture( transform, x, y, 0, 0, TEX_WIDTH, TEX_HEIGHT ); // Draw selection slot - int slot = container.getSelectedSlot(); + int slot = getScreenHandler().getSelectedSlot(); if( slot >= 0 ) { int slotX = slot % 4; @@ -61,5 +74,7 @@ public class GuiTurtle extends GuiComputer 24, 24 ); } + + RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL ); } } diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java index 495a98a96..85e308f02 100644 --- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java +++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java @@ -8,57 +8,67 @@ package dan200.computercraft.client.gui.widgets; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.command.text.ChatHelpers; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.IComputer; import net.minecraft.SharedConstants; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.ChatUtil; +import net.minecraft.util.math.Matrix4f; import org.lwjgl.glfw.GLFW; +import javax.annotation.Nonnull; import java.util.BitSet; import java.util.function.Supplier; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; +import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; -public class WidgetTerminal implements Element -{ +public class WidgetTerminal extends ClickableWidget { private static final float TERMINATE_TIME = 0.5f; - private final MinecraftClient client; - private final Supplier computer; - private final int termWidth; - private final int termHeight; - private final int leftMargin; - private final int rightMargin; - private final int topMargin; - private final int bottomMargin; +// private final MinecraftClient client; + private final ClientComputer computer; + + // The positions of the actual terminal + private final int innerX; + private final int innerY; + private final int innerWidth; + private final int innerHeight; + private final BitSet keysDown = new BitSet( 256 ); - private boolean focused; +// private boolean focused; private float terminateTimer = -1; private float rebootTimer = -1; private float shutdownTimer = -1; + private int lastMouseButton = -1; private int lastMouseX = -1; private int lastMouseY = -1; - public WidgetTerminal( MinecraftClient client, Supplier computer, int termWidth, int termHeight, int leftMargin, int rightMargin, - int topMargin, int bottomMargin ) + public WidgetTerminal( @Nonnull ClientComputer computer, int x, int y, int termWidth, int termHeight ) { - this.client = client; + super( x, y, termWidth * FONT_WIDTH + MARGIN * 2, termHeight * FONT_HEIGHT + MARGIN * 2, LiteralText.EMPTY); + this.computer = computer; - this.termWidth = termWidth; - this.termHeight = termHeight; - this.leftMargin = leftMargin; - this.rightMargin = rightMargin; - this.topMargin = topMargin; - this.bottomMargin = bottomMargin; + + innerX = x + MARGIN; + innerY = y + MARGIN; + innerWidth = termWidth * FONT_WIDTH; + innerHeight = termHeight * FONT_HEIGHT; } @Override public boolean mouseClicked( double mouseX, double mouseY, int button ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer == null || !computer.isColour() || button < 0 || button > 2 ) { return false; @@ -85,7 +95,7 @@ public class WidgetTerminal implements Element @Override public boolean mouseReleased( double mouseX, double mouseY, int button ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer == null || !computer.isColour() || button < 0 || button > 2 ) { return false; @@ -115,7 +125,7 @@ public class WidgetTerminal implements Element @Override public boolean mouseDragged( double mouseX, double mouseY, int button, double v2, double v3 ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer == null || !computer.isColour() || button < 0 || button > 2 ) { return false; @@ -143,7 +153,7 @@ public class WidgetTerminal implements Element @Override public boolean mouseScrolled( double mouseX, double mouseY, double delta ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer == null || !computer.isColour() || delta == 0 ) { return false; @@ -198,7 +208,7 @@ public class WidgetTerminal implements Element case GLFW.GLFW_KEY_V: // Ctrl+V for paste - String clipboard = client.keyboard.getClipboard(); + String clipboard = MinecraftClient.getInstance().keyboard.getClipboard(); if( clipboard != null ) { // Clip to the first occurrence of \r or \n @@ -239,7 +249,7 @@ public class WidgetTerminal implements Element // Queue the "key" event and add to the down set boolean repeat = keysDown.get( key ); keysDown.set( key ); - IComputer computer = this.computer.get(); + IComputer computer = this.computer; if( computer != null ) { computer.keyDown( key, repeat ); @@ -256,7 +266,7 @@ public class WidgetTerminal implements Element if( key >= 0 && keysDown.get( key ) ) { keysDown.set( key, false ); - IComputer computer = this.computer.get(); + IComputer computer = this.computer; if( computer != null ) { computer.keyUp( key ); @@ -296,35 +306,26 @@ public class WidgetTerminal implements Element } @Override - public boolean changeFocus( boolean reversed ) + public void onFocusedChanged( boolean focused ) { - if( focused ) + if( !focused ) { // When blurring, we should make all keys go up for( int key = 0; key < keysDown.size(); key++ ) { - if( keysDown.get( key ) ) - { - queueEvent( "key_up", key ); - } + if( keysDown.get( key ) ) computer.keyUp( key ); } keysDown.clear(); // When blurring, we should make the last mouse button go up if( lastMouseButton > 0 ) { - IComputer computer = this.computer.get(); - if( computer != null ) - { - computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 ); - } + computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 ); lastMouseButton = -1; } shutdownTimer = terminateTimer = rebootTimer = -1; } - focused = !focused; - return true; } @Override @@ -335,7 +336,7 @@ public class WidgetTerminal implements Element private void queueEvent( String event, Object... args ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer != null ) { computer.queueEvent( event, args ); @@ -351,7 +352,7 @@ public class WidgetTerminal implements Element if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer != null ) { computer.shutdown(); @@ -360,7 +361,7 @@ public class WidgetTerminal implements Element if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer != null ) { computer.reboot(); @@ -370,31 +371,41 @@ public class WidgetTerminal implements Element private void queueEvent( String event ) { - ClientComputer computer = this.computer.get(); + ClientComputer computer = this.computer; if( computer != null ) { computer.queueEvent( event ); } } - public void draw( int originX, int originY ) + @Override + public void render(@Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks ) { - synchronized( computer ) + if( !visible ) return; + Matrix4f matrix = transform.peek().getModel(); + Terminal terminal = computer.getTerminal(); + if( terminal != null ) { - // Draw the screen contents - ClientComputer computer = this.computer.get(); - Terminal terminal = computer != null ? computer.getTerminal() : null; - if( terminal != null ) - { - FixedWidthFontRenderer.drawTerminal( originX, originY, terminal, !computer.isColour(), topMargin, bottomMargin, leftMargin, - rightMargin ); - } - else - { - FixedWidthFontRenderer.drawEmptyTerminal( originX - leftMargin, - originY - rightMargin, termWidth * FONT_WIDTH + leftMargin + rightMargin, - termHeight * FONT_HEIGHT + topMargin + bottomMargin ); - } + FixedWidthFontRenderer.drawTerminal( matrix, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); + } + else + { + FixedWidthFontRenderer.drawEmptyTerminal( matrix, x, y, width, height ); } } + + @Override + public void appendNarrations(NarrationMessageBuilder builder) { + + } + + public static int getWidth( int termWidth ) + { + return termWidth * FONT_WIDTH + MARGIN * 2; + } + + public static int getHeight( int termHeight ) + { + return termHeight * FONT_HEIGHT + MARGIN * 2; + } } diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index dc5df9bbe..5120c8595 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -19,6 +19,7 @@ import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.ContainerHeldItem; import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.common.TileGeneric; +import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputer; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; @@ -34,6 +35,7 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +//import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; @@ -77,7 +79,6 @@ public final class ComputerCraftProxyClient implements ClientModInitializer // While turtles themselves are not transparent, their upgrades may be. BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderLayer.getTranslucent() ); BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderLayer.getTranslucent() ); - // Monitors' textures have transparent fronts and so count as cutouts. BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderLayer.getCutout() ); BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderLayer.getCutout() ); @@ -90,7 +91,7 @@ public final class ComputerCraftProxyClient implements ClientModInitializer ClientSpriteRegistryCallback.event( PlayerScreenHandler.BLOCK_ATLAS_TEXTURE ) .register( ClientRegistry::onTextureStitchEvent ); - ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent ); + ModelLoadingRegistry.INSTANCE.registerModelProvider( ClientRegistry::onModelBakeEvent ); ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) -> TurtleModelLoader.INSTANCE.accepts( name ) ? TurtleModelLoader.INSTANCE.loadModel( name ) : null ); diff --git a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java index 91466b927..332c4355f 100644 --- a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java @@ -8,11 +8,7 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.Tessellator; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.*; import net.minecraft.util.Identifier; import net.minecraft.util.math.Matrix4f; import org.lwjgl.opengl.GL11; @@ -55,11 +51,14 @@ public class ComputerBorderRenderer private final int z; private final float r, g, b; - public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, float r, float g, float b ) + private final int light; + + public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b ) { this.transform = transform; this.builder = builder; this.z = z; + this.light = light; this.r = r; this.g = g; this.b = b; @@ -81,31 +80,17 @@ public class ComputerBorderRenderer } } - public static void render( int x, int y, int z, int width, int height ) + public static void render(Identifier location, int x, int y, int z, int light, int width, int height ) { - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin( VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE ); - - render( IDENTITY, buffer, x, y, z, width, height ); - -// RenderSystem.enableDepthTest(); //TODO: enableAlphaTest(). FIXME - tessellator.draw(); + VertexConsumerProvider.Immediate source = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer()); + render( IDENTITY, source.getBuffer(RenderLayer.getText(location)), x, y, z, light, width, height, false, 1, 1, 1 ); + source.draw(); } - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height ) - { - render( transform, buffer, x, y, z, width, height, 1, 1, 1 ); - } - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b ) + public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b ) { - render( transform, buffer, x, y, z, width, height, false, r, g, b ); - } - - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, boolean withLight, float r, float g, float b ) - { - new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, withLight ); + new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight ); } public void doRender( int x, int y, int width, int height, boolean withLight ) @@ -158,18 +143,22 @@ public class ComputerBorderRenderer builder.vertex( transform, x, y + height, z ) .color( r, g, b, 1.0f ) .texture( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ) + .light(light) .next(); builder.vertex( transform, x + width, y + height, z ) .color( r, g, b, 1.0f ) .texture( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ) + .light(light) .next(); builder.vertex( transform, x + width, y, z ) .color( r, g, b, 1.0f ) .texture( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ) + .light(light) .next(); builder.vertex( transform, x, y, z ) .color( r, g, b, 1.0f ) .texture( u * TEX_SCALE, v * TEX_SCALE ) + .light(light) .next(); } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index 2bf5d3571..1f9c4f5d3 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -117,7 +117,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer BufferBuilder buffer = tessellator.getBuffer(); buffer.begin( VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE ); - ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b ); +// ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b ); tessellator.draw(); } diff --git a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java index d0117b2ac..1d3d5383e 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java @@ -12,13 +12,11 @@ import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.*; import net.minecraft.world.World; import java.util.EnumSet; @@ -49,13 +47,11 @@ public final class MonitorHighlightRenderer World world = entity.getEntityWorld(); BlockEntity tile = world.getBlockEntity( pos ); - if( !(tile instanceof TileMonitor) ) + if( !(tile instanceof TileMonitor monitor) ) { return false; } - TileMonitor monitor = (TileMonitor) tile; - // Determine which sides are part of the external faces of the monitor, and so which need to be rendered. EnumSet faces = EnumSet.allOf( Direction.class ); Direction front = monitor.getFront(); @@ -87,53 +83,54 @@ public final class MonitorHighlightRenderer // I wish I could think of a better way to do this Matrix4f transform = matrixStack.peek() .getModel(); + Matrix3f normal = matrixStack.peek().getNormal(); if( faces.contains( NORTH ) || faces.contains( WEST ) ) { - line( vertexConsumer, transform, 0, 0, 0, UP ); + line( vertexConsumer, transform, normal, 0, 0, 0, UP ); } if( faces.contains( SOUTH ) || faces.contains( WEST ) ) { - line( vertexConsumer, transform, 0, 0, 1, UP ); + line( vertexConsumer, transform, normal, 0, 0, 1, UP ); } if( faces.contains( NORTH ) || faces.contains( EAST ) ) { - line( vertexConsumer, transform, 1, 0, 0, UP ); + line( vertexConsumer, transform, normal, 1, 0, 0, UP ); } if( faces.contains( SOUTH ) || faces.contains( EAST ) ) { - line( vertexConsumer, transform, 1, 0, 1, UP ); + line( vertexConsumer, transform, normal, 1, 0, 1, UP ); } if( faces.contains( NORTH ) || faces.contains( DOWN ) ) { - line( vertexConsumer, transform, 0, 0, 0, EAST ); + line( vertexConsumer, transform, normal, 0, 0, 0, EAST ); } if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) { - line( vertexConsumer, transform, 0, 0, 1, EAST ); + line( vertexConsumer, transform, normal, 0, 0, 1, EAST ); } if( faces.contains( NORTH ) || faces.contains( UP ) ) { - line( vertexConsumer, transform, 0, 1, 0, EAST ); + line( vertexConsumer, transform, normal, 0, 1, 0, EAST ); } if( faces.contains( SOUTH ) || faces.contains( UP ) ) { - line( vertexConsumer, transform, 0, 1, 1, EAST ); + line( vertexConsumer, transform, normal, 0, 1, 1, EAST ); } if( faces.contains( WEST ) || faces.contains( DOWN ) ) { - line( vertexConsumer, transform, 0, 0, 0, SOUTH ); + line( vertexConsumer, transform, normal, 0, 0, 0, SOUTH ); } if( faces.contains( EAST ) || faces.contains( DOWN ) ) { - line( vertexConsumer, transform, 1, 0, 0, SOUTH ); + line( vertexConsumer, transform, normal, 1, 0, 0, SOUTH ); } if( faces.contains( WEST ) || faces.contains( UP ) ) { - line( vertexConsumer, transform, 0, 1, 0, SOUTH ); + line( vertexConsumer, transform, normal, 0, 1, 0, SOUTH ); } if( faces.contains( EAST ) || faces.contains( UP ) ) { - line( vertexConsumer, transform, 1, 1, 0, SOUTH ); + line( vertexConsumer, transform, normal, 1, 1, 0, SOUTH ); } matrixStack.pop(); @@ -141,13 +138,15 @@ public final class MonitorHighlightRenderer return true; } - private static void line( VertexConsumer buffer, Matrix4f transform, float x, float y, float z, Direction direction ) + private static void line( VertexConsumer buffer, Matrix4f transform, Matrix3f normal, float x, float y, float z, Direction direction ) { buffer.vertex( transform, x, y, z ) .color( 0, 0, 0, 0.4f ) + .normal(normal, direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ()) .next(); buffer.vertex( transform, x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ() ) .color( 0, 0, 0, 0.4f ) + .normal(normal, direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ()) .next(); } } diff --git a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java index 98f336ba1..f78e134e0 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java @@ -1,186 +1,105 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ package dan200.computercraft.client.render; -import com.google.common.base.Strings; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.TextureUtil; -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.shared.util.Palette; -import net.minecraft.util.math.Matrix4f; -import org.lwjgl.BufferUtils; +import net.minecraft.client.gl.GlUniform; +import net.minecraft.client.render.Shader; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.resource.ResourceFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL20; -import java.io.InputStream; +import javax.annotation.Nullable; +import java.io.IOException; import java.nio.FloatBuffer; -import java.util.List; -class MonitorTextureBufferShader +public class MonitorTextureBufferShader extends Shader { static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; - private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 ); - private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 ); + private static final Logger LOGGER = LogManager.getLogger(); - private static int uniformMv; + private final GlUniform palette; + private final GlUniform width; + private final GlUniform height; - private static int uniformFont; - private static int uniformWidth; - private static int uniformHeight; - private static int uniformTbo; - private static int uniformPalette; + public MonitorTextureBufferShader(ResourceFactory factory, String name, VertexFormat format) throws IOException { + super(factory, name, format); - private static boolean initialised; - private static boolean ok; - private static int program; + width = getUniformChecked( "Width" ); + height = getUniformChecked( "Height" ); + palette = new GlUniform( "Palette", GlUniform.field_32044 /* UT_FLOAT3 */, 16 * 3, this ); + updateUniformLocation( palette ); - static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale ) + GlUniform tbo = getUniformChecked( "Tbo" ); + if( tbo != null ) tbo.set( TEXTURE_INDEX - GL13.GL_TEXTURE0 ); + } + + void setupUniform( int width, int height, Palette palette, boolean greyscale ) { - MATRIX_BUFFER.rewind(); - transform.write( MATRIX_BUFFER, true ); //FIXME: Row major or Column major? guessing row major, since that is like C. - MATRIX_BUFFER.rewind(); - RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); + if( this.width != null ) this.width.set( width ); + if( this.height != null ) this.height.set( height ); + setupPalette( palette, greyscale ); + } - RenderSystem.glUniform1i( uniformWidth, width ); - RenderSystem.glUniform1i( uniformHeight, height ); + private void setupPalette( Palette palette, boolean greyscale ) + { + if( this.palette == null ) return; - PALETTE_BUFFER.rewind(); + FloatBuffer paletteBuffer = this.palette.getFloatData(); + paletteBuffer.rewind(); for( int i = 0; i < 16; i++ ) { double[] colour = palette.getColour( i ); if( greyscale ) { float f = FixedWidthFontRenderer.toGreyscale( colour ); - PALETTE_BUFFER.put( f ) - .put( f ) - .put( f ); + paletteBuffer.put( f ).put( f ).put( f ); } else { - PALETTE_BUFFER.put( (float) colour[0] ) - .put( (float) colour[1] ) - .put( (float) colour[2] ); + paletteBuffer.put( (float) colour[0] ).put( (float) colour[1] ).put( (float) colour[2] ); } } - PALETTE_BUFFER.flip(); - RenderSystem.glUniform3( uniformPalette, PALETTE_BUFFER ); - } - - static boolean use() - { - if( initialised ) - { - if( ok ) - { - GlStateManager.glLinkProgram( program ); - } - return ok; - } - - if( ok = load() ) - { - GL20.glUseProgram( program ); - RenderSystem.glUniform1i( uniformFont, 0 ); - RenderSystem.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 ); - } - - return ok; - } - - private static boolean load() - { - initialised = true; - - try - { - int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" ); - int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" ); - - program = GlStateManager.glCreateProgram(); - GlStateManager.glAttachShader( program, vertexShader ); - GlStateManager.glAttachShader( program, fragmentShader ); - GL20.glBindAttribLocation( program, 0, "v_pos" ); - - GlStateManager.glLinkProgram( program ); - - boolean ok = GlStateManager.glGetProgrami( program, GL20.GL_LINK_STATUS ) != 0; - String log = GlStateManager.glGetProgramInfoLog( program, Short.MAX_VALUE ) - .trim(); - if( !Strings.isNullOrEmpty( log ) ) - { - ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log ); - } - - GL20.glDetachShader( program, vertexShader ); - GL20.glDetachShader( program, fragmentShader ); - GlStateManager.glDeleteShader( vertexShader ); - GlStateManager.glDeleteShader( fragmentShader ); - - if( !ok ) - { - return false; - } - - uniformMv = getUniformLocation( program, "u_mv" ); - uniformFont = getUniformLocation( program, "u_font" ); - uniformWidth = getUniformLocation( program, "u_width" ); - uniformHeight = getUniformLocation( program, "u_height" ); - uniformTbo = getUniformLocation( program, "u_tbo" ); - uniformPalette = getUniformLocation( program, "u_palette" ); - - ComputerCraft.log.info( "Loaded monitor shader." ); - return true; - } - catch( Exception e ) - { - ComputerCraft.log.error( "Cannot load monitor shaders", e ); - return false; - } } - private static int loadShader( int kind, String path ) + @Override + public void bind() { - InputStream stream = TileEntityMonitorRenderer.class.getClassLoader() - .getResourceAsStream( path ); - if( stream == null ) - { - throw new IllegalArgumentException( "Cannot find " + path ); - } - List contents = TextureUtil.readResourceAsString(stream).lines().toList(); - - int shader = GlStateManager.glCreateShader( kind ); - - GlStateManager.glShaderSource( shader, contents ); - GlStateManager.glCompileShader( shader ); - - boolean ok = GlStateManager.glGetShaderi( shader, GL20.GL_COMPILE_STATUS ) != 0; - String log = GlStateManager.glGetShaderInfoLog( shader, Short.MAX_VALUE ) - .trim(); - if( !Strings.isNullOrEmpty( log ) ) - { - ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log ); - } - - if( !ok ) - { - throw new IllegalStateException( "Cannot compile shader " + path ); - } - return shader; + super.bind(); + palette.upload(); } - private static int getUniformLocation( int program, String name ) + @Override + public void close() { - int uniform = GlStateManager._glGetUniformLocation( program, name ); - if( uniform == -1 ) + palette.close(); + super.close(); + } + + private void updateUniformLocation( GlUniform uniform ) + { + int id = GlUniform.getUniformLocation( getProgramRef(), uniform.getName() ); + if( id == -1 ) { - throw new IllegalStateException( "Cannot find uniform " + name ); + LOGGER.warn( "Shader {} could not find uniform named {} in the specified shader program.", getName(), uniform.getName() ); } + else + { + uniform.setLoc( id ); + } + } + + @Nullable + private GlUniform getUniformChecked( String name ) + { + GlUniform uniform = getUniform( name ); + if( uniform == null ) + { + LOGGER.warn( "Monitor shader {} should have uniform {}, but it was not present.", getName(), name ); + } + return uniform; } } diff --git a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java index 8e255509e..1bff1d435 100644 --- a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -53,7 +53,7 @@ public final class PrintoutRenderer public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours ) { - VertexConsumer buffer = Tessellator.getInstance().getBuffer(); + /*VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) { FixedWidthFontRenderer.drawString( transform, @@ -67,12 +67,12 @@ public final class PrintoutRenderer false, 0, 0 ); - } + }*/ } public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours ) { - VertexConsumer buffer = Tessellator.getInstance().getBuffer(); + /*VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) { FixedWidthFontRenderer.drawString( transform, @@ -86,7 +86,7 @@ public final class PrintoutRenderer false, 0, 0 ); - } + }*/ } public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook ) @@ -187,28 +187,22 @@ public final class PrintoutRenderer .next(); } -// private static final class Type extends RenderLayer -// { -// -// static final RenderLayer TYPE = RenderLayer.of( "printout_background", -// VertexFormats.POSITION_TEXTURE, -// GL11.GL_QUADS, -// 1024, -// false, -// false, -// // useDelegate, needsSorting -// Type.MultiPhaseParameters.builder() -// .texture( new RenderPhase.Texture( BG, false, false ) ) // blur, minimap -// .transparency( TRANSLUCENT_TRANSPARENCY) -// .lightmap( DISABLE_LIGHTMAP ) -// .build( false ) ); -// -// public Type( String name, VertexFormat vertexFormat, DrawMode drawMode, -// int expectedBufferSize, boolean hasCrumbling, boolean translucent, -// Runnable startAction, Runnable endAction ) -// { -// super( name, vertexFormat, drawMode, expectedBufferSize, hasCrumbling, translucent, -// startAction, endAction ); -// } -// } + private static final class Type extends RenderLayer + { + static final RenderLayer TYPE = null;/*RenderLayer.of( "printout_background", + VertexFormats.POSITION_TEXTURE, + VertexFormat.DrawMode.QUADS, + 1024, + // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( new RenderPhase.Texture( BG, false, false ) ) // blur, minimap + .transparency( TRANSLUCENT_TRANSPARENCY ) + .lightmap( DISABLE_LIGHTMAP ) + .build( false ));*/ + + private Type( String name, VertexFormat vertexFormat, VertexFormat.DrawMode drawMode, int expectedBufferSize, boolean hasCrumbling, boolean translucent, RenderLayer.MultiPhaseParameters phases, Runnable setup, Runnable destroy ) + { + super( name, vertexFormat, drawMode, expectedBufferSize, hasCrumbling, hasCrumbling, setup, destroy ); + } + } } diff --git a/src/main/java/dan200/computercraft/client/render/RenderTypes.java b/src/main/java/dan200/computercraft/client/render/RenderTypes.java new file mode 100644 index 000000000..a7cd959dd --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/RenderTypes.java @@ -0,0 +1,88 @@ +package dan200.computercraft.client.render; + +import dan200.computercraft.client.gui.FixedWidthFontRenderer; +import net.minecraft.client.render.*; +import net.minecraft.util.Identifier; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class RenderTypes { + + public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20); + + @Nullable + public static MonitorTextureBufferShader monitorTboShader; + + @Nullable + public static Shader terminalShader; + + public static final RenderLayer TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH; + public static final RenderLayer MONITOR_TBO = Types.MONITOR_TBO; + public static final RenderLayer TERMINAL_BLOCKER = Types.BLOCKER; + public static final RenderLayer TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH; + + @Nonnull + static MonitorTextureBufferShader getMonitorTextureBufferShader() + { + if( monitorTboShader == null ) throw new NullPointerException( "MonitorTboShader has not been registered" ); + return monitorTboShader; + } + + @Nonnull + static Shader getTerminalShader() + { + if( terminalShader == null ) throw new NullPointerException( "MonitorTboShader has not been registered" ); + return terminalShader; + } + + private static final class Types extends RenderPhase + { + private static final VertexFormat.DrawMode GL_MODE = VertexFormat.DrawMode.TRIANGLES; + private static final VertexFormat FORMAT = VertexFormats.POSITION_COLOR_TEXTURE; + private static final Shader TERM_SHADER = new Shader( RenderTypes::getTerminalShader ); + + private static final RenderPhase.Texture TERM_FONT_TEXTURE = new RenderPhase.Texture( + FixedWidthFontRenderer.FONT, + false, false // blur, minimap + ); + + public static final RenderLayer MONITOR_TBO = RenderLayer.of( "monitor_tbo", VertexFormats.POSITION_TEXTURE, VertexFormat.DrawMode.TRIANGLE_STRIP, 128, false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture(TERM_FONT_TEXTURE ) // blur, minimap + .shader(new RenderPhase.Shader(RenderTypes::getMonitorTextureBufferShader)) + .writeMaskState( RenderLayer.ALL_MASK ) + .build( false ) ); + + static final RenderLayer TERMINAL_WITHOUT_DEPTH = RenderLayer.of( + "terminal_without_depth", FORMAT, GL_MODE, 1024, + false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( TERM_FONT_TEXTURE ) + .shader( TERM_SHADER ) + .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( TERM_FONT_TEXTURE ) + .shader(TERM_SHADER) + .writeMaskState( DEPTH_MASK ) + .build( false ) ); + + static final RenderLayer TERMINAL_WITH_DEPTH = RenderLayer.of( + "terminal_with_depth", FORMAT, GL_MODE, 1024, + false, false, // useDelegate, needsSorting + RenderLayer.MultiPhaseParameters.builder() + .texture( TERM_FONT_TEXTURE ) + .shader( TERM_SHADER ) + .build( false ) + ); + + private Types( String name, Runnable setup, Runnable destroy ) + { + super( name, setup, destroy ); + } + } +} diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java index 1ac740c93..5b24b8a00 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -7,6 +7,8 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.FrameInfo; import dan200.computercraft.client.gui.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; @@ -39,6 +41,7 @@ import java.nio.Buffer; import java.nio.ByteBuffer; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*; +import static net.minecraft.client.util.GlAllocationUtils.allocateByteBuffer; public class TileEntityMonitorRenderer implements BlockEntityRenderer { //FIXME get rid of GL Calls. Buffered things or whatever, more research needed. @@ -52,7 +55,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer private final Random random = new Random( 0 ); + BlockEntityRenderDispatcher dispatcher; + public TileEntityTurtleRenderer( BlockEntityRendererFactory.Context context ) { -// super( rendererDispatcher ); + dispatcher = context.getRenderDispatcher(); } public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured ) diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java index 1f975f963..751f14195 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java @@ -117,7 +117,6 @@ public class TurtleMultiModel implements BakedModel return baseModel.isBuiltin(); } - @Nonnull @Override @Deprecated public Sprite getParticleSprite() @@ -125,6 +124,14 @@ public class TurtleMultiModel implements BakedModel return baseModel.getParticleSprite(); } +// @Nonnull +// @Override +// @Deprecated +// public Sprite getSprite() +// { +// return baseModel.getSprite(); +// } + @Nonnull @Override @Deprecated diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java index 914354c0c..8490bcc79 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java @@ -142,7 +142,6 @@ public class TurtleSmartItemModel implements BakedModel return familyModel.isBuiltin(); } - @Nonnull @Override @Deprecated public Sprite getParticleSprite() @@ -150,6 +149,14 @@ public class TurtleSmartItemModel implements BakedModel return familyModel.getParticleSprite(); } +// @Nonnull +// @Override +// @Deprecated +// public Sprite getSprite() +// { +// return familyModel.getSprite(); +// } + @Nonnull @Override @Deprecated diff --git a/src/main/java/dan200/computercraft/fabric/mixin/GameRendererMixin.java b/src/main/java/dan200/computercraft/fabric/mixin/GameRendererMixin.java new file mode 100644 index 000000000..ecc5957ef --- /dev/null +++ b/src/main/java/dan200/computercraft/fabric/mixin/GameRendererMixin.java @@ -0,0 +1,41 @@ +package dan200.computercraft.fabric.mixin; + +import com.mojang.datafixers.util.Pair; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.client.gui.FixedWidthFontRenderer; +import dan200.computercraft.client.render.MonitorTextureBufferShader; +import dan200.computercraft.client.render.RenderTypes; +import net.minecraft.client.gl.Program; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.Shader; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.io.IOException; +import java.util.List; +import java.util.function.Consumer; + +@Mixin(GameRenderer.class) +public class GameRendererMixin { + @SuppressWarnings("UnresolvedMixinReference") + @Inject(method = "loadShaders", at = @At(value = "INVOKE_ASSIGN", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 53), locals = LocalCapture.CAPTURE_FAILSOFT) + private void loadShaders(ResourceManager manager, CallbackInfo info, List list, List>> list2) throws IOException { + list2.add(Pair.of(new Shader( + manager, + "terminal", + RenderTypes.TERMINAL_WITHOUT_DEPTH.getVertexFormat() + ), (shader) -> RenderTypes.terminalShader = shader)); + list2.add(Pair.of(new MonitorTextureBufferShader( + manager, + "monitor_tbo", + RenderTypes.MONITOR_TBO.getVertexFormat() + ), (shader) -> RenderTypes.monitorTboShader = (MonitorTextureBufferShader) shader)); + } +} diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java index 014015a47..1484b5762 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinBlock.java @@ -27,14 +27,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin( Block.class ) public class MixinBlock { - @Inject( method = "dropStack(Lnet/minecraft/world/World;Ljava/util/function/Supplier;Lnet/minecraft/item/ItemStack;)V", - at = @At( value = "HEAD" ), - cancellable = true ) - private static void dropStack( World world, Supplier itemEntitySupplier, ItemStack stack, CallbackInfo callbackInfo ) - { - if( DropConsumer.onHarvestDrops( world, itemEntitySupplier.get().getBlockPos(), stack ) ) - { - callbackInfo.cancel(); - } - } +// @Inject( method = "dropStack", +// at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), +// cancellable = true ) +// private static void dropStack( World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo ) +// { +// if( DropConsumer.onHarvestDrops( world, itemEntitySupplier.get().getBlockPos(), stack ) ) +// { +// callbackInfo.cancel(); +// } +// } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java index 5bb1671b9..5f493552c 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinEntity.java @@ -22,14 +22,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin( Entity.class ) public class MixinEntity { - @Inject( method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", - at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), - cancellable = true ) - public void dropStack( ItemStack stack, float height, CallbackInfoReturnable callbackInfo ) - { - if( DropConsumer.onLivingDrops( (Entity) (Object) this, stack ) ) - { - callbackInfo.setReturnValue( null ); - } - } +// @Inject( method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", +// at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), +// cancellable = true ) +// public void dropStack( ItemStack stack, float height, CallbackInfoReturnable callbackInfo ) +// { +// if( DropConsumer.onLivingDrops( (Entity) (Object) this, stack ) ) +// { +// callbackInfo.setReturnValue( null ); +// } +// } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java index f8424b0c9..ac515be7a 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/MixinWorld.java @@ -30,13 +30,13 @@ public class MixinWorld protected boolean iteratingTickingBlockEntities; // @Inject( method = "setBlockEntity", at = @At( "HEAD" ) ) -// public void setBlockEntity( BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info ) -// { -// if( entity != null && !entity.isRemoved() && entity.getWorld().isInBuildLimit(pos) && iteratingTickingBlockEntities ) -// { -// setWorld( entity, this ); -// } -// } + public void setBlockEntity( BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info ) + { + if( entity != null && !entity.isRemoved() && entity.getWorld().isInBuildLimit(pos) && iteratingTickingBlockEntities ) + { + setWorld( entity, this ); + } + } private static void setWorld( BlockEntity entity, Object world ) { @@ -47,14 +47,14 @@ public class MixinWorld } // @Inject( method = "addBlockEntities", at = @At( "HEAD" ) ) -// public void addBlockEntities( Collection entities, CallbackInfo info ) -// { -// if( iteratingTickingBlockEntities ) -// { -// for( BlockEntity entity : entities ) -// { -// setWorld( entity, this ); -// } -// } -// } + public void addBlockEntities( Collection entities, CallbackInfo info ) + { + if( iteratingTickingBlockEntities ) + { + for( BlockEntity entity : entities ) + { + setWorld( entity, this ); + } + } + } } diff --git a/src/main/java/dan200/computercraft/fabric/mixin/RenderLayerAccessor.java b/src/main/java/dan200/computercraft/fabric/mixin/RenderLayerAccessor.java new file mode 100644 index 000000000..b24efc1bd --- /dev/null +++ b/src/main/java/dan200/computercraft/fabric/mixin/RenderLayerAccessor.java @@ -0,0 +1,18 @@ +//package dan200.computercraft.fabric.mixin; +// +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.gen.Accessor; +//import org.spongepowered.asm.mixin.gen.Invoker; +// +//import net.minecraft.client.render.RenderLayer; +//import net.minecraft.client.render.VertexFormat; +// +//@Mixin(RenderLayer.class) +//public interface RenderLayerAccessor { +// +// @Accessor +// static RenderLayer.MultiPhaseParameters callOf(String name, VertexFormat vertexFormat, VertexFormat.DrawMode drawMode, int expectedBufferSize, boolean hasCrumbling, boolean translucent, RenderLayer.MultiPhaseParameters phases) { +// throw new UnsupportedOperationException(); +// } +// +//} diff --git a/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java b/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java index 2d716e57e..a8f5bf5b6 100644 --- a/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java +++ b/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java @@ -42,13 +42,11 @@ import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.turtle.items.ItemTurtle; import dan200.computercraft.shared.turtle.upgrades.*; +//import dan200.computercraft.shared.util.FixedPointTileEntityType; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; -import net.minecraft.block.AbstractBlock; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.block.Material; +import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.EntityType; @@ -61,6 +59,7 @@ import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import java.util.Objects; @@ -108,8 +107,8 @@ public final class ComputerCraftRegistry public static final BlockSpeaker SPEAKER = register( "speaker", new BlockSpeaker( properties() ) ); public static final BlockDiskDrive DISK_DRIVE = register( "disk_drive", new BlockDiskDrive( properties() ) ); public static final BlockPrinter PRINTER = register( "printer", new BlockPrinter( properties() ) ); - public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL ) ); - public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED ) ); + public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL, false ) ); + public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED, true ) ); public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register( "wireless_modem_normal", new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_NORMAL ) ); public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register( "wireless_modem_advanced", @@ -149,53 +148,53 @@ public final class ComputerCraftRegistry public static class ModTiles { - public static final BlockEntityType MONITOR_NORMAL = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_NORMAL, false, blockPos, blockState ), - ModBlocks.MONITOR_NORMAL ) - .build(); - public static final BlockEntityType MONITOR_ADVANCED = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_ADVANCED, false, blockPos, blockState ), - ModBlocks.MONITOR_ADVANCED ) - .build(); - public static final BlockEntityType COMPUTER_NORMAL = FabricBlockEntityTypeBuilder.create( - ( blockPos, blockState ) -> new TileComputer( ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL, blockPos, blockState ), - ModBlocks.COMPUTER_NORMAL ).build(); - public static final BlockEntityType COMPUTER_ADVANCED = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileComputer( ComputerFamily.ADVANCED, ModTiles.COMPUTER_ADVANCED, blockPos, - blockState ), ModBlocks.COMPUTER_ADVANCED ) - .build(); - public static final BlockEntityType COMPUTER_COMMAND = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileCommandComputer( ComputerFamily.COMMAND, ModTiles.COMPUTER_COMMAND, blockPos, - blockState ), ModBlocks.COMPUTER_COMMAND ) - .build(); - public static final BlockEntityType TURTLE_NORMAL = FabricBlockEntityTypeBuilder.create( - ( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_NORMAL, ComputerFamily.NORMAL, blockPos, blockState ), - ModBlocks.TURTLE_NORMAL ).build(); - public static final BlockEntityType TURTLE_ADVANCED = FabricBlockEntityTypeBuilder.create( - ( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_ADVANCED, ComputerFamily.ADVANCED, blockPos, blockState ), - ModBlocks.TURTLE_ADVANCED ).build(); - public static final BlockEntityType SPEAKER = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileSpeaker( ModTiles.SPEAKER, blockPos, blockState ), ModBlocks.SPEAKER ) - .build(); - public static final BlockEntityType DISK_DRIVE = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileDiskDrive( ModTiles.DISK_DRIVE, blockPos, blockState ), - ModBlocks.DISK_DRIVE ) - .build(); - public static final BlockEntityType PRINTER = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TilePrinter( ModTiles.PRINTER, blockPos, blockState ), ModBlocks.PRINTER ) - .build(); - public static final BlockEntityType WIRED_MODEM_FULL = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileWiredModemFull( ModTiles.WIRED_MODEM_FULL, blockPos, blockState ), - ModBlocks.WIRED_MODEM_FULL ) - .build(); - public static final BlockEntityType CABLE = FabricBlockEntityTypeBuilder - .create( ( blockPos, blockState ) -> new TileCable( ModTiles.CABLE, blockPos, blockState ), ModBlocks.CABLE ).build(); - public static final BlockEntityType WIRELESS_MODEM_NORMAL = FabricBlockEntityTypeBuilder.create( - ( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_NORMAL, false, blockPos, blockState ), - ModBlocks.WIRELESS_MODEM_NORMAL ).build(); - public static final BlockEntityType WIRELESS_MODEM_ADVANCED = FabricBlockEntityTypeBuilder.create( - ( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_ADVANCED, true, blockPos, blockState ), - ModBlocks.WIRELESS_MODEM_ADVANCED ).build(); + public static final BlockEntityType MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL, + "monitor_normal", + (blockPos, blockState) -> new TileMonitor(ModTiles.MONITOR_NORMAL, false, blockPos, blockState) ); + public static final BlockEntityType MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED, + "monitor_advanced", + (blockPos, blockState) -> new TileMonitor(ModTiles.MONITOR_ADVANCED, true, blockPos, blockState) ); + public static final BlockEntityType COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL, + "computer_normal", + (blockPos, blockState) -> new TileComputer(ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL, blockPos, blockState) ); + public static final BlockEntityType COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED, + "computer_advanced", + (blockPos, blockState) -> new TileComputer(ComputerFamily.ADVANCED, ModTiles.COMPUTER_ADVANCED, blockPos, blockState) ); + public static final BlockEntityType COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND, + "computer_command", + (blockPos, blockState) -> new TileCommandComputer(ComputerFamily.COMMAND, ModTiles.COMPUTER_COMMAND, blockPos, blockState) ); + public static final BlockEntityType TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL, + "turtle_normal", + (blockPos, blockState) -> new TileTurtle(ModTiles.TURTLE_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) ); + public static final BlockEntityType TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED, + "turtle_advanced", + (blockPos, blockState) -> new TileTurtle(ModTiles.TURTLE_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) ); + public static final BlockEntityType SPEAKER = ofBlock( ModBlocks.SPEAKER, "speaker", + (blockPos, blockState) -> new TileSpeaker(ModTiles.SPEAKER, blockPos, blockState ) ); + public static final BlockEntityType DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, "disk_drive", + (blockPos, blockState) -> new TileDiskDrive(ModTiles.DISK_DRIVE, blockPos, blockState ) ); + public static final BlockEntityType PRINTER = ofBlock( ModBlocks.PRINTER, "printer", + (blockPos, blockState) -> new TilePrinter(ModTiles.PRINTER, blockPos, blockState ) ); + public static final BlockEntityType WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, + "wired_modem_full", + (blockPos, blockState) -> new TileWiredModemFull(ModTiles.WIRED_MODEM_FULL, blockPos, blockState ) ); + public static final BlockEntityType CABLE = ofBlock( ModBlocks.CABLE, "cable", + (blockPos, blockState) -> new TileCable(ModTiles.CABLE, blockPos, blockState ) ); + public static final BlockEntityType WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, + "wireless_modem_normal", + (blockPos, blockState) -> new TileWirelessModem(ModTiles.WIRELESS_MODEM_NORMAL, false, blockPos, blockState) ); + public static final BlockEntityType WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, + "wireless_modem_advanced", + (blockPos, blockState) -> new TileWirelessModem(ModTiles.WIRELESS_MODEM_ADVANCED, true, blockPos, blockState) ); + + private static BlockEntityType ofBlock( Block block, String id, BiFunction factory ) + { + BlockEntityType blockEntityType = FabricBlockEntityTypeBuilder.create(factory::apply, block).build(); + return Registry.register( BLOCK_ENTITY_TYPE, + new Identifier( MOD_ID, id ), + blockEntityType + ); + } } public static final class ModItems diff --git a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java index f93a40494..26b744131 100644 --- a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java @@ -35,6 +35,10 @@ public abstract class BlockGeneric extends BlockWithEntity this.type = type; } + public BlockEntityType getType() { + return type; + } + @Override public BlockRenderType getRenderType( BlockState state ) { @@ -96,6 +100,9 @@ public abstract class BlockGeneric extends BlockWithEntity @Override public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { - return type.instantiate(pos, state); + if (this.type != null) { + return type.instantiate(pos, state); + } + return null; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java index f597a84e2..3f1e872c8 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java @@ -6,11 +6,16 @@ package dan200.computercraft.shared.computer.blocks; +import dan200.computercraft.shared.ComputerCraftRegistry; +import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.ComputerRegistry; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.items.ComputerItemFactory; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemStack; @@ -18,7 +23,9 @@ import net.minecraft.state.StateManager; import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.world.World; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -56,4 +63,20 @@ public class BlockComputer extends BlockComputerBase { return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY; } + + public BlockEntityType getTypeByFamily(ComputerFamily family) + { + return switch (family) { + case COMMAND -> ComputerCraftRegistry.ModTiles.COMPUTER_COMMAND; + case ADVANCED -> ComputerCraftRegistry.ModTiles.COMPUTER_ADVANCED; + default -> ComputerCraftRegistry.ModTiles.COMPUTER_NORMAL; + }; + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) + { + return new TileComputer(getFamily(), getTypeByFamily(getFamily()), pos, state); + } } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java index 4f98a1e54..0f0dd0149 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java @@ -8,13 +8,17 @@ package dan200.computercraft.shared.computer.blocks; import dan200.computercraft.ComputerCraft; import dan200.computercraft.core.computer.ComputerSide; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; import dan200.computercraft.shared.common.IBundledRedstoneBlock; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.turtle.blocks.BlockTurtle; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -211,4 +215,14 @@ public abstract class BlockComputerBase extends Bloc state.onStacksDropped( serverWorld, pos, player.getMainHandStack() ); } } + + @Nullable + @Override + public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type) { + return world.isClient ? null : (world1, pos, state1, tile) -> { + if (tile instanceof TileComputerBase computer) { + TileComputerBase.tick(world1, pos, state1, computer); + } + }; + } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java index f04d00ae3..124b0516d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java @@ -8,6 +8,7 @@ package dan200.computercraft.shared.peripheral.diskdrive; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; +import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker; import dan200.computercraft.shared.peripheral.speaker.TileSpeaker; import net.minecraft.block.Block; @@ -53,13 +54,13 @@ public class BlockDiskDrive extends BlockGeneric placement.getPlayerFacing() .getOpposite() ); } - + @Nullable @Override public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type){ return world.isClient ? null : BlockDiskDrive.checkType( type, ComputerCraftRegistry.ModTiles.DISK_DRIVE, TileDiskDrive::tick ); } - + @Override public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te, @Nonnull ItemStack stack @@ -98,4 +99,11 @@ public class BlockDiskDrive extends BlockGeneric { properties.add( FACING, STATE ); } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) + { + return new TileDiskDrive(ComputerCraftRegistry.ModTiles.DISK_DRIVE, pos, state); + } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java index b0c634aeb..837d5276e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java @@ -7,7 +7,9 @@ package dan200.computercraft.shared.peripheral.monitor; import dan200.computercraft.api.turtle.FakePlayer; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; +import dan200.computercraft.shared.computer.blocks.TileComputer; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -34,9 +36,12 @@ public class BlockMonitor extends BlockGeneric static final EnumProperty STATE = EnumProperty.of( "state", MonitorEdgeState.class ); - public BlockMonitor( Settings settings, BlockEntityType type ) + public boolean advanced = false; + + public BlockMonitor( Settings settings, BlockEntityType type, boolean advanced ) { super( settings, type ); + this.advanced = advanced; // TODO: Test underwater - do we need isSolid at all? setDefaultState( getStateManager().getDefaultState() .with( ORIENTATION, Direction.NORTH ) @@ -97,4 +102,11 @@ public class BlockMonitor extends BlockGeneric { builder.add( ORIENTATION, FACING, STATE ); } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) + { + return new TileMonitor(advanced ? ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED : ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, advanced, pos, state); + } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java index da084d1a3..0ee58fea5 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java @@ -9,6 +9,7 @@ package dan200.computercraft.shared.turtle.blocks; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.BlockComputerBase; +import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.computer.blocks.TileComputerBase; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive; @@ -140,9 +141,8 @@ public class BlockTurtle extends BlockComputerBase implements Waterl super.onPlaced( world, pos, state, player, stack ); BlockEntity tile = world.getBlockEntity( pos ); - if( !world.isClient && tile instanceof TileTurtle ) + if( !world.isClient && tile instanceof TileTurtle turtle ) { - TileTurtle turtle = (TileTurtle) tile; if( player instanceof PlayerEntity ) { @@ -180,10 +180,25 @@ public class BlockTurtle extends BlockComputerBase implements Waterl } } } - + + public BlockEntityType getTypeByFamily(ComputerFamily family) + { + if (family == ComputerFamily.ADVANCED) { + return ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED; + } + return ComputerCraftRegistry.ModTiles.TURTLE_NORMAL; + } + @Nullable @Override - public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type){ - return world.isClient ? null : BlockTurtle.checkType( type, ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileTurtle::tick ); + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) + { + return new TileTurtle(getTypeByFamily(getFamily()), pos, state, getFamily()); } + +// @Nullable +// @Override +// public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type){ +// return world.isClient ? BlockTurtle.checkType( type, getTypeByFamily(getFamily()), TileTurtle::tick ) : super.getTicker(world, state, type); +// } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index 26e3af5fb..57679c5dc 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -12,7 +12,7 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.fabric.mixin.MixinBlockEntity; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.computer.blocks.ComputerProxy; import dan200.computercraft.shared.computer.blocks.TileComputerBase; @@ -64,10 +64,9 @@ public class TileTurtle extends TileComputerBase private TurtleBrain brain = new TurtleBrain( this ); private MoveState moveState = MoveState.NOT_MOVED; - public TileTurtle( BlockEntityType type, - ComputerFamily family, BlockPos pos, BlockState state ) + public TileTurtle( BlockEntityType type, BlockPos pos, BlockState state, ComputerFamily family ) { - super( type, family, pos, state ); + super(type, family, pos, state ); } @Override @@ -256,10 +255,10 @@ public class TileTurtle extends TileComputerBase // Open GUI or whatever return super.onActivate( player, hand, hit ); } - - public void setBlockPos( BlockPos pos ) { - ((MixinBlockEntity) (Object) this).setBlockPos(pos); // FIXME this looks really bad. - } + +// public void setBlockPos( BlockPos pos ) { +// ((MixinBlockEntity) (Object) this).setBlockPos(pos); // FIXME this looks really bad. +// } @Override public void onNeighbourChange( @Nonnull BlockPos neighbour ) @@ -282,8 +281,8 @@ public class TileTurtle extends TileComputerBase public static void tick( World world, BlockPos pos, BlockState state, TileTurtle tileTurtle ) { - tileTurtle.brain.update(); - if( !tileTurtle.getWorld().isClient && tileTurtle.inventoryChanged ) + tileTurtle.brain.update(); + if( !world.isClient && tileTurtle.inventoryChanged ) { ServerComputer computer = tileTurtle.getServerComputer(); if( computer != null ) @@ -565,6 +564,7 @@ public class TileTurtle extends TileComputerBase public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) { + System.out.println(inventory.player.getDisplayName()); return new ContainerTurtle( id, inventory, brain ); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index f61a34b41..3c2c3b7fa 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -256,7 +256,7 @@ public class TurtleBrain implements ITurtleAccess { // Copy the old turtle state into the new turtle TileTurtle newTurtle = (TileTurtle) newTile; - newTurtle.setBlockPos( pos ); //FIXME: setLocation no longer exists. + // newTurtle.setLocation( world, pos ); //FIXME: setLocation no longer exists. newTurtle.transferStateFrom( oldOwner ); newTurtle.createServerComputer() .setWorld( world ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java index f090722b8..80dbf56d3 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java @@ -23,12 +23,18 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.ArrayPropertyDelegate; import net.minecraft.screen.PropertyDelegate; import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.crash.CrashException; +import net.minecraft.util.crash.CrashReport; +import net.minecraft.util.crash.CrashReportSection; +import net.minecraft.util.registry.Registry; import javax.annotation.Nonnull; import java.util.function.Predicate; public class ContainerTurtle extends ContainerComputerBase { + public static final int BORDER = 8; public static final int PLAYER_START_Y = 134; public static final int TURTLE_START_X = 175; @@ -53,6 +59,8 @@ public class ContainerTurtle extends ContainerComputerBase super( ComputerCraftRegistry.ModContainers.TURTLE, id, canUse, computer, family ); this.properties = properties; + System.out.println("Contaienr Turtle init" + properties); + addProperties( properties ); // Turtle inventory @@ -105,6 +113,7 @@ public class ContainerTurtle extends ContainerComputerBase @Override public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotNum ) { + System.out.println("transferSlot"); if( slotNum >= 0 && slotNum < 16 ) { return tryItemMerge( player, slotNum, 16, 52, true ); @@ -119,6 +128,7 @@ public class ContainerTurtle extends ContainerComputerBase @Nonnull private ItemStack tryItemMerge( PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse ) { + System.out.println("tryItemMerge"); Slot slot = slots.get( slotNum ); ItemStack originalStack = ItemStack.EMPTY; if( slot != null && slot.hasStack() ) @@ -150,4 +160,10 @@ public class ContainerTurtle extends ContainerComputerBase } return originalStack; } + @Override + public void onSlotClick(int slotIndex, int button, SlotActionType actionType, PlayerEntity player) { + super.onSlotClick(slotIndex, button, actionType, player); + + System.out.println("on slot click: " + slotIndex); + } } diff --git a/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java b/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java index 85fa969c2..93c86b179 100644 --- a/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java +++ b/src/main/java/dan200/computercraft/shared/util/FixedPointTileEntityType.java @@ -3,17 +3,17 @@ // * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. // * Send enquiries to dratcliffe@gmail.com // */ -// //package dan200.computercraft.shared.util; // //import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; //import net.minecraft.block.Block; +//import net.minecraft.block.BlockState; //import net.minecraft.block.entity.BlockEntity; //import net.minecraft.block.entity.BlockEntityType; +//import net.minecraft.util.math.BlockPos; // //import javax.annotation.Nonnull; //import java.util.Collections; -//import java.util.function.Function; //import java.util.function.Supplier; // ///** @@ -23,40 +23,52 @@ // */ //public final class FixedPointTileEntityType extends BlockEntityType //{ -// private final Supplier block; +// private final Supplier block; // -// private FixedPointTileEntityType( Supplier block, Supplier builder ) +// private FixedPointTileEntityType( Supplier block, FabricBlockEntityTypeBuilder.Factory builder ) // { -// super( builder, Collections.emptySet(), null ); //FIXME: Replace with the new BlockEntity handlers. +// super(builder, Collections.emptySet(), null ); // this.block = block; // } // -// public static FixedPointTileEntityType create( Supplier block, Function, T> builder ) +// public static FixedPointTileEntityType create( Supplier block, FixedPointBlockEntitySupplier builder ) // { // return new FixedPointSupplier<>( block, builder ).factory; // } // -//// @Override -//// public boolean supports( @Nonnull Block block ) -//// { -//// return block == this.block.get(); -//// } +// @Override +// public boolean supports( @Nonnull BlockState block ) +// { +// return block.getBlock() == this.block.get(); +// } // -// private static final class FixedPointSupplier implements Supplier +// public Block getBlock() +// { +// return block.get(); +// } +// +// private static final class FixedPointSupplier implements FabricBlockEntityTypeBuilder.Factory // { // final FixedPointTileEntityType factory; -// private final Function, T> builder; +// private final FixedPointBlockEntitySupplier builder; // -// private FixedPointSupplier( Supplier block, Function, T> builder ) +// private FixedPointSupplier( Supplier block, FixedPointBlockEntitySupplier builder ) // { -// factory = FabricBlockEntityTypeBuilder.create( this, block ); +// factory = new FixedPointTileEntityType<>( block, this ); // this.builder = builder; // } // +// @Nonnull // @Override -// public T get() +// public T create(@Nonnull BlockPos pos, @Nonnull BlockState state ) // { -// return builder.apply( factory ); +// return builder.create( factory, pos, state ); // } // } +// +// @FunctionalInterface +// public interface FixedPointBlockEntitySupplier +// { +// T create( BlockEntityType type, BlockPos pos, BlockState state ); +// } //} diff --git a/src/main/resources/assets/computercraft/shaders/monitor_tbo.fsh b/src/main/resources/assets/computercraft/shaders/monitor_tbo.fsh new file mode 100644 index 000000000..f89635ca5 --- /dev/null +++ b/src/main/resources/assets/computercraft/shaders/monitor_tbo.fsh @@ -0,0 +1,40 @@ +#version 150 + +#define FONT_WIDTH 6.0 +#define FONT_HEIGHT 9.0 + +uniform sampler2D Sampler0; // Font +uniform int Width; +uniform int Height; +uniform usamplerBuffer Tbo; +uniform vec3 Palette[16]; + +in vec2 f_pos; + +out vec4 colour; + +vec2 texture_corner(int index) { + float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0); + float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0); + return vec2(x, y); +} + +void main() { + vec2 term_pos = vec2(f_pos.x / FONT_WIDTH, f_pos.y / FONT_HEIGHT); + vec2 corner = floor(term_pos); + + ivec2 cell = ivec2(corner); + int index = 3 * (clamp(cell.x, 0, Width - 1) + clamp(cell.y, 0, Height - 1) * Width); + + // 1 if 0 <= x, y < Width, Height, 0 otherwise + vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(Width) - 1.0, float(Height) - 1.0)); + float mult = outside.x * outside.y; + + int character = int(texelFetch(Tbo, index).r); + int fg = int(texelFetch(Tbo, index + 1).r); + int bg = int(texelFetch(Tbo, index + 2).r); + + vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT); + vec4 img = texture(Sampler0, (texture_corner(character) + pos) / 256.0); + colour = vec4(mix(Palette[bg], img.rgb * Palette[fg], img.a * mult), 1.0); +} diff --git a/src/main/resources/assets/computercraft/shaders/monitor_tbo.json b/src/main/resources/assets/computercraft/shaders/monitor_tbo.json new file mode 100644 index 000000000..8f9a900d6 --- /dev/null +++ b/src/main/resources/assets/computercraft/shaders/monitor_tbo.json @@ -0,0 +1,13 @@ +{ + "vertex": "computercraft:monitor_tbo", + "fragment": "computercraft:monitor_tbo", + "attributes": [ "Position" ], + "samplers": [ { "name": "Sampler0" } ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "Width", "type": "int", "count": 1, "values": [ 1 ] }, + { "name": "Height", "type": "int", "count": 1, "values": [ 1 ] }, + { "name": "Tbo", "type": "int", "count": 1, "values": [ 3 ] } + ] +} diff --git a/src/main/resources/assets/computercraft/shaders/monitor_tbo.vsh b/src/main/resources/assets/computercraft/shaders/monitor_tbo.vsh new file mode 100644 index 000000000..8b673710b --- /dev/null +++ b/src/main/resources/assets/computercraft/shaders/monitor_tbo.vsh @@ -0,0 +1,14 @@ +#version 150 + +in vec3 Position; +in vec2 UV0; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out vec2 f_pos; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1); + f_pos = UV0; +} diff --git a/src/main/resources/assets/minecraft/shaders/core/monitor.frag b/src/main/resources/assets/minecraft/shaders/core/monitor.frag new file mode 100644 index 000000000..f19a6a9eb --- /dev/null +++ b/src/main/resources/assets/minecraft/shaders/core/monitor.frag @@ -0,0 +1,40 @@ +#version 140 + +#define FONT_WIDTH 6.0 +#define FONT_HEIGHT 9.0 + +uniform sampler2D u_font; +uniform int u_width; +uniform int u_height; +uniform usamplerBuffer u_tbo; +uniform vec3 u_palette[16]; + +in vec2 f_pos; + +out vec4 colour; + +vec2 texture_corner(int index) { + float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0); + float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0); + return vec2(x, y); +} + +void main() { + vec2 term_pos = vec2(f_pos.x / FONT_WIDTH, f_pos.y / FONT_HEIGHT); + vec2 corner = floor(term_pos); + + ivec2 cell = ivec2(corner); + int index = 3 * (clamp(cell.x, 0, u_width - 1) + clamp(cell.y, 0, u_height - 1) * u_width); + + // 1 if 0 <= x, y < width, height, 0 otherwise + vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(u_width) - 1.0, float(u_height) - 1.0)); + float mult = outside.x * outside.y; + + int character = int(texelFetch(u_tbo, index).r); + int fg = int(texelFetch(u_tbo, index + 1).r); + int bg = int(texelFetch(u_tbo, index + 2).r); + + vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT); + vec4 img = texture(u_font, (texture_corner(character) + pos) / 256.0); + colour = vec4(mix(u_palette[bg], img.rgb * u_palette[fg], img.a * mult), 1.0); +} diff --git a/src/main/resources/assets/minecraft/shaders/core/monitor.vert b/src/main/resources/assets/minecraft/shaders/core/monitor.vert new file mode 100644 index 000000000..15b81fbb7 --- /dev/null +++ b/src/main/resources/assets/minecraft/shaders/core/monitor.vert @@ -0,0 +1,12 @@ +#version 130 + +uniform mat4 u_mv; + +in vec3 v_pos; + +out vec2 f_pos; + +void main() { + gl_Position = gl_ProjectionMatrix * u_mv * vec4(v_pos.x, v_pos.y, 0, 1); + f_pos = v_pos.xy; +} diff --git a/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.fsh b/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.fsh new file mode 100644 index 000000000..f89635ca5 --- /dev/null +++ b/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.fsh @@ -0,0 +1,40 @@ +#version 150 + +#define FONT_WIDTH 6.0 +#define FONT_HEIGHT 9.0 + +uniform sampler2D Sampler0; // Font +uniform int Width; +uniform int Height; +uniform usamplerBuffer Tbo; +uniform vec3 Palette[16]; + +in vec2 f_pos; + +out vec4 colour; + +vec2 texture_corner(int index) { + float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0); + float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0); + return vec2(x, y); +} + +void main() { + vec2 term_pos = vec2(f_pos.x / FONT_WIDTH, f_pos.y / FONT_HEIGHT); + vec2 corner = floor(term_pos); + + ivec2 cell = ivec2(corner); + int index = 3 * (clamp(cell.x, 0, Width - 1) + clamp(cell.y, 0, Height - 1) * Width); + + // 1 if 0 <= x, y < Width, Height, 0 otherwise + vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(Width) - 1.0, float(Height) - 1.0)); + float mult = outside.x * outside.y; + + int character = int(texelFetch(Tbo, index).r); + int fg = int(texelFetch(Tbo, index + 1).r); + int bg = int(texelFetch(Tbo, index + 2).r); + + vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT); + vec4 img = texture(Sampler0, (texture_corner(character) + pos) / 256.0); + colour = vec4(mix(Palette[bg], img.rgb * Palette[fg], img.a * mult), 1.0); +} diff --git a/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.json b/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.json new file mode 100644 index 000000000..9196160ee --- /dev/null +++ b/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.json @@ -0,0 +1,13 @@ +{ + "vertex": "monitor_tbo", + "fragment": "monitor_tbo", + "attributes": [ "Position" ], + "samplers": [ { "name": "Sampler0" } ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "Width", "type": "int", "count": 1, "values": [ 1 ] }, + { "name": "Height", "type": "int", "count": 1, "values": [ 1 ] }, + { "name": "Tbo", "type": "int", "count": 1, "values": [ 3 ] } + ] +} diff --git a/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.vsh b/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.vsh new file mode 100644 index 000000000..8b673710b --- /dev/null +++ b/src/main/resources/assets/minecraft/shaders/core/monitor_tbo.vsh @@ -0,0 +1,14 @@ +#version 150 + +in vec3 Position; +in vec2 UV0; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +out vec2 f_pos; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1); + f_pos = UV0; +} diff --git a/src/main/resources/assets/minecraft/shaders/core/terminal.json b/src/main/resources/assets/minecraft/shaders/core/terminal.json new file mode 100644 index 000000000..2cd53c182 --- /dev/null +++ b/src/main/resources/assets/minecraft/shaders/core/terminal.json @@ -0,0 +1,11 @@ +{ + "vertex": "position_color_tex", + "fragment": "position_color_tex", + "attributes": [ "Position", "Color", "UV0" ], + "samplers": [ { "name": "Sampler0" } ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] } + ] +} diff --git a/src/main/resources/cc.accesswidener b/src/main/resources/cc.accesswidener new file mode 100644 index 000000000..ff0086ba7 --- /dev/null +++ b/src/main/resources/cc.accesswidener @@ -0,0 +1,13 @@ +accessWidener v1 named + +accessible class net/minecraft/client/render/RenderLayer$MultiPhase +accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters +accessible method net/minecraft/client/render/RenderLayer of (Ljava/lang/String;Lnet/minecraft/client/render/VertexFormat;Lnet/minecraft/client/render/VertexFormat$DrawMode;IZZLnet/minecraft/client/render/RenderLayer$MultiPhaseParameters;)Lnet/minecraft/client/render/RenderLayer$MultiPhase; + +accessible class net/minecraft/client/render/RenderPhase$Shader +accessible field net/minecraft/client/render/RenderPhase ALL_MASK Lnet/minecraft/client/render/RenderPhase$WriteMaskState; +accessible field net/minecraft/client/render/RenderPhase LIGHTNING_TRANSPARENCY Lnet/minecraft/client/render/RenderPhase$Transparency; +accessible field net/minecraft/client/render/RenderPhase TRANSLUCENT_TRANSPARENCY Lnet/minecraft/client/render/RenderPhase$Transparency; +accessible field net/minecraft/client/render/RenderPhase WEATHER_TARGET Lnet/minecraft/client/render/RenderPhase$Target; +accessible field net/minecraft/client/render/RenderPhase DISABLE_LIGHTMAP Lnet/minecraft/client/render/RenderPhase$Lightmap; +accessible class net/minecraft/client/render/RenderPhase$Texture diff --git a/src/main/resources/computercraft.mixins.json b/src/main/resources/computercraft.mixins.json index da87a6920..c3da4edb3 100644 --- a/src/main/resources/computercraft.mixins.json +++ b/src/main/resources/computercraft.mixins.json @@ -13,7 +13,8 @@ "SoundEventAccess", "WorldSavePathAccess", "MixinServerPlayerInteractionManager", - "MusicDiscItemAccessor" + "MusicDiscItemAccessor", + "GameRendererMixin" ], "client": [ "AffineTransformationAccess", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index d91178c18..32343f71f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -32,6 +32,7 @@ "canvas": "*", "iris": "*" }, + "accessWidener": "cc.accesswidener", "environment": "*", "entrypoints": { "main": [