diff --git a/.github/workflows/main-ci.yml b/.github/workflows/main-ci.yml
index 3c5793c2d..b69180785 100644
--- a/.github/workflows/main-ci.yml
+++ b/.github/workflows/main-ci.yml
@@ -12,10 +12,10 @@ jobs:
- name: Checkout submodules
run: git submodule update --init --recursive
- - name: Set up Java 8
+ - name: Set up Java 16
uses: actions/setup-java@v1
with:
- java-version: 8
+ java-version: 16
- name: Cache gradle dependencies
uses: actions/cache@v2
diff --git a/.gitignore b/.gitignore
index 4efc71fe5..8288d3541 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@
.gradle
*.DS_Store
.project
+*.launch
diff --git a/build.gradle b/build.gradle
index 6cdcf6eb8..44ca32f99 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,13 +1,13 @@
plugins {
- id 'fabric-loom' version '0.8-SNAPSHOT'
+ id 'fabric-loom' version '0.9-SNAPSHOT'
id 'maven-publish'
id "checkstyle"
- id "com.github.hierynomus.license" version "0.15.0"
+ id "com.github.hierynomus.license" version "0.16.1"
}
java {
toolchain {
- languageVersion = JavaLanguageVersion.of(8)
+ languageVersion = JavaLanguageVersion.of(16)
vendor = JvmVendorSpec.ADOPTOPENJDK
}
}
@@ -22,18 +22,23 @@ repositories {
maven { url 'https://jitpack.io' }
maven { url 'https://api.modrinth.com/maven'}
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
}
dependencies {
- checkstyle "com.puppycrawl.tools:checkstyle:8.25"
+ checkstyle 'com.puppycrawl.tools:checkstyle:8.45.1'
minecraft "com.mojang:minecraft:${mc_version}"
mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}:v2"
@@ -43,7 +48,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'
@@ -56,21 +61,16 @@ 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:5.12.248"
- modRuntime "me.shedaniel:RoughlyEnoughItems:5.12.248"
+ modRuntime "me.shedaniel:RoughlyEnoughItems-api-fabric:6.0.254-alpha"
+ modRuntime "me.shedaniel:RoughlyEnoughItems-fabric:6.0.254-alpha"
}
processResources {
inputs.property "version", project.version
- from(sourceSets.main.resources.srcDirs) {
- include "fabric.mod.json"
- expand "version": project.version
- }
-
- from(sourceSets.main.resources.srcDirs) {
- exclude "fabric.mod.json"
- }
+ filesMatching("fabric.mod.json") {
+ expand "version": project.version
+ }
}
// ensure that the encoding is set to UTF-8, no matter what the system default is
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index aaafdfd01..ebc62360c 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -58,13 +58,13 @@
-
+
-
+
diff --git a/gradle.properties b/gradle.properties
index 03bde43ce..dd8208c4f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,12 +6,12 @@ mod_version=1.96.1-rc1
# Minecraft properties
mc_version=1.17.1
-mappings_version=10
+mappings_version=61
# Dependencies
cloth_config_version=5.0.34
-fabric_loader_version=0.11.6
-fabric_api_version=0.36.1+1.17
+fabric_loader_version=0.11.7
+fabric_api_version=0.40.1+1.17
jankson_version=1.2.0
-modmenu_version=1.16.9
+modmenu_version=2.0.2
cloth_api_version=2.0.54
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 05679dc3c..ffed3a254 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java
index 27aa35429..2dc474c22 100644
--- a/src/main/java/dan200/computercraft/ComputerCraft.java
+++ b/src/main/java/dan200/computercraft/ComputerCraft.java
@@ -73,6 +73,8 @@ public final class ComputerCraft implements ModInitializer
) );
public static int httpMaxRequests = 16;
public static int httpMaxWebsockets = 4;
+ public static int httpDownloadBandwidth = 32 * 1024 * 1024;
+ public static int httpUploadBandwidth = 32 * 1024 * 1024;
public static boolean enableCommandBlock = false;
public static int modemRange = 64;
@@ -82,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/api/client/TransformedModel.java b/src/main/java/dan200/computercraft/api/client/TransformedModel.java
index c44d6f04d..201d53333 100644
--- a/src/main/java/dan200/computercraft/api/client/TransformedModel.java
+++ b/src/main/java/dan200/computercraft/api/client/TransformedModel.java
@@ -6,16 +6,17 @@
package dan200.computercraft.api.client;
-import dan200.computercraft.fabric.mixin.AffineTransformationAccess;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.util.ModelIdentifier;
+import net.minecraft.util.math.AffineTransformation;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
-import net.minecraft.util.math.AffineTransformation;
+import net.minecraft.util.math.Vec3f;
+
import javax.annotation.Nonnull;
import java.util.Objects;
@@ -72,22 +73,14 @@ public final class TransformedModel
{
matrixStack.push();
- AffineTransformationAccess access = (AffineTransformationAccess) (Object) matrix;
- if( access.getTranslation() != null )
- {
- matrixStack.translate( access.getTranslation().getX(), access.getTranslation().getY(), access.getTranslation().getZ() );
- }
+ Vec3f translation = matrix.getTranslation();
+ matrixStack.translate( translation.getX(), translation.getY(), translation.getZ() );
matrixStack.multiply( matrix.getRotation2() );
- if( access.getScale() != null )
- {
- matrixStack.scale( access.getScale().getX(), access.getScale().getY(), access.getScale().getZ() );
- }
+ Vec3f scale = matrix.getScale();
+ matrixStack.scale( scale.getX(), scale.getY(), scale.getZ() );
- if( access.getRotation1() != null )
- {
- matrixStack.multiply( access.getRotation1() );
- }
+ matrixStack.multiply( matrix.getRotation1() );
}
}
diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaContext.java b/src/main/java/dan200/computercraft/api/lua/ILuaContext.java
index d871786e4..6d1aba949 100644
--- a/src/main/java/dan200/computercraft/api/lua/ILuaContext.java
+++ b/src/main/java/dan200/computercraft/api/lua/ILuaContext.java
@@ -9,17 +9,18 @@ package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
/**
- * An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods that allow the peripheral call to interface
- * with the computer.
+ * An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods
+ * that allow the peripheral call to interface with the computer.
*/
public interface ILuaContext
{
/**
- * Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to complete. This should be used when you
- * need to interact with the world in a thread-safe manner but do not care about the result or you wish to run asynchronously.
+ * Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
+ * complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
+ * about the result or you wish to run asynchronously.
*
- * When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success value and the return values, or an
- * error message if it failed.
+ * When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
+ * value and the return values, or an error message if it failed.
*
* @param task The task to execute on the main thread.
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
@@ -27,4 +28,18 @@ public interface ILuaContext
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
*/
long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
+
+ /**
+ * Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
+ * This should be used when you need to interact with the world in a thread-safe manner.
+ *
+ * Note that the return values of your task are handled as events, meaning more complex objects such as maps or
+ * {@link IDynamicLuaObject} will not preserve their identities.
+ *
+ * @param task The task to execute on the main thread.
+ * @return The objects returned by {@code task}.
+ * @throws LuaException If the task could not be queued, or if the task threw an exception.
+ */
+ @Nonnull
+ MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
}
diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java
deleted file mode 100644
index eba77bc19..000000000
--- a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is part of the public ComputerCraft API - http://www.computercraft.info
- * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
- * For help using the API, and posting your mods, visit the forums at computercraft.info.
- */
-package dan200.computercraft.api.lua;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-public interface ILuaObject
-{
- @Nonnull
- String[] getMethodNames();
-
- @Nullable
- Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
-}
diff --git a/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java b/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java
index d17820409..6599d7e90 100644
--- a/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java
+++ b/src/main/java/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java
@@ -6,12 +6,15 @@
package dan200.computercraft.api.pocket;
+import dan200.computercraft.shared.util.NonNullSupplier;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
+import java.util.function.Supplier;
/**
* A base class for {@link IPocketUpgrade}s.
@@ -22,27 +25,49 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
{
private final Identifier id;
private final String adjective;
- private final ItemStack stack;
+ private final NonNullSupplier stack;
- protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
- {
- this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item );
- }
-
- protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item )
- {
- this.id = id;
- this.adjective = adjective;
- stack = new ItemStack( item );
- }
-
- protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
+ protected AbstractPocketUpgrade( Identifier id, String adjective, NonNullSupplier stack )
{
this.id = id;
this.adjective = adjective;
this.stack = stack;
}
+ protected AbstractPocketUpgrade( Identifier id, NonNullSupplier item )
+ {
+ this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item );
+ }
+
+ protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
+ {
+ this( id, adjective, () -> stack );
+ }
+
+ protected AbstractPocketUpgrade( Identifier id, ItemStack stack )
+ {
+ this( id, () -> stack );
+ }
+
+ protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item )
+ {
+ this( id, adjective, new CachedStack( () -> item ) );
+ }
+
+ protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
+ {
+ this( id, new CachedStack( () -> item ) );
+ }
+
+ protected AbstractPocketUpgrade( Identifier id, String adjective, Supplier extends ItemConvertible> item )
+ {
+ this( id, adjective, new CachedStack( item ) );
+ }
+
+ protected AbstractPocketUpgrade( Identifier id, Supplier extends ItemConvertible> item )
+ {
+ this( id, new CachedStack( item ) );
+ }
@Nonnull
@Override
@@ -62,6 +87,32 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
@Override
public final ItemStack getCraftingItem()
{
- return stack;
+ return stack.get();
+ }
+
+ /**
+ * Caches the construction of an item stack.
+ *
+ * @see dan200.computercraft.api.turtle.AbstractTurtleUpgrade For explanation of this class.
+ */
+ private static final class CachedStack implements NonNullSupplier
+ {
+ private final Supplier extends ItemConvertible> provider;
+ private Item item;
+ private ItemStack stack;
+
+ CachedStack( Supplier extends ItemConvertible> provider )
+ {
+ this.provider = provider;
+ }
+
+ @Nonnull
+ @Override
+ public ItemStack get()
+ {
+ Item item = provider.get().asItem();
+ if( item == this.item && stack != null ) return stack;
+ return stack = new ItemStack( this.item = item );
+ }
}
}
diff --git a/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java b/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java
index e53215bbd..7046cc808 100644
--- a/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java
+++ b/src/main/java/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java
@@ -6,12 +6,15 @@
package dan200.computercraft.api.turtle;
+import dan200.computercraft.shared.util.NonNullSupplier;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
+import java.util.function.Supplier;
/**
* A base class for {@link ITurtleUpgrade}s.
@@ -23,14 +26,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
private final Identifier id;
private final TurtleUpgradeType type;
private final String adjective;
- private final ItemStack stack;
+ private final NonNullSupplier stack;
- protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
- {
- this( id, type, adjective, new ItemStack( item ) );
- }
-
- protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, NonNullSupplier stack )
{
this.id = id;
this.type = type;
@@ -38,16 +36,40 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
this.stack = stack;
}
- protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
- {
- this( id, type, new ItemStack( item ) );
- }
-
- protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, NonNullSupplier stack )
{
this( id, type, Util.createTranslationKey( "upgrade", id ) + ".adjective", stack );
}
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
+ {
+ this( id, type, adjective, () -> stack );
+ }
+
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
+ {
+ this( id, type, () -> stack );
+ }
+
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
+ {
+ this( id, type, adjective, new CachedStack( () -> item ) );
+ }
+
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
+ {
+ this( id, type, new CachedStack( () -> item ) );
+ }
+
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, Supplier extends ItemConvertible> item )
+ {
+ this( id, type, adjective, new CachedStack( item ) );
+ }
+
+ protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, Supplier extends ItemConvertible> item )
+ {
+ this( id, type, new CachedStack( item ) );
+ }
@Nonnull
@Override
@@ -74,6 +96,32 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
@Override
public final ItemStack getCraftingItem()
{
- return stack;
+ return stack.get();
+ }
+
+ /**
+ * A supplier which converts an item into an item stack.
+ *
+ * Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
+ */
+ private static final class CachedStack implements NonNullSupplier
+ {
+ private final Supplier extends ItemConvertible> provider;
+ private Item item;
+ private ItemStack stack;
+
+ CachedStack( Supplier extends ItemConvertible> provider )
+ {
+ this.provider = provider;
+ }
+
+ @Nonnull
+ @Override
+ public ItemStack get()
+ {
+ Item item = provider.get().asItem();
+ if( item == this.item && stack != null ) return stack;
+ return stack = new ItemStack( this.item = item );
+ }
}
}
diff --git a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java
index a73471f6b..e534e648e 100644
--- a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java
+++ b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java
@@ -23,20 +23,16 @@ import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
import net.minecraft.recipe.Recipe;
import net.minecraft.screen.NamedScreenHandlerFactory;
-import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
-import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
-import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.TradeOfferList;
-import net.minecraft.world.GameMode;
import javax.annotation.Nullable;
import javax.crypto.Cipher;
@@ -53,7 +49,7 @@ public class FakePlayer extends ServerPlayerEntity
{
public FakePlayer( ServerWorld world, GameProfile gameProfile )
{
- super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) );
+ super( world.getServer(), world, gameProfile );
networkHandler = new FakeNetHandler( this );
}
@@ -137,30 +133,30 @@ public class FakePlayer extends ServerPlayerEntity
{
}
- @Override
- public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack )
- {
- }
-
- @Override
- public void onHandlerRegistered( ScreenHandler container, DefaultedList defaultedList )
- {
- }
-
- @Override
- public void onPropertyUpdate( ScreenHandler container, int key, int value )
- {
- }
+ // @Override
+ // public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack )
+ // {
+ // }
+ //
+ // @Override
+ // public void onHandlerRegistered( ScreenHandler container, DefaultedList defaultedList )
+ // {
+ // }
+ //
+ // @Override
+ // public void onPropertyUpdate( ScreenHandler container, int key, int value )
+ // {
+ // }
@Override
public void closeHandledScreen()
{
}
- @Override
- public void updateCursorStack()
- {
- }
+ // @Override
+ // public void updateCursorStack()
+ // {
+ // }
@Override
public int unlockRecipes( Collection> recipes )
@@ -196,12 +192,12 @@ public class FakePlayer extends ServerPlayerEntity
}
@Override
- protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance )
+ protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance, @Nullable Entity source )
{
}
@Override
- protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles )
+ protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles, @Nullable Entity source )
{
}
@@ -215,10 +211,10 @@ public class FakePlayer extends ServerPlayerEntity
{
}
- @Override
- public void changeGameMode( GameMode gameMode )
- {
- }
+ // @Override
+ // public void setGameMode( GameMode gameMode )
+ // {
+ // }
@Override
public void sendMessage( Text message, MessageType type, UUID senderUuid )
@@ -232,15 +228,15 @@ public class FakePlayer extends ServerPlayerEntity
return "[Fake Player]";
}
- @Override
- public void sendResourcePackUrl( String url, String hash )
- {
- }
+ // @Override
+ // public void sendResourcePackUrl( String url, String hash )
+ // {
+ // }
- @Override
- public void onStoppedTracking( Entity entity )
- {
- }
+ // @Override
+ // public void onStoppedTracking( Entity entity )
+ // {
+ // }
@Override
public void setCameraEntity( Entity entity )
@@ -347,10 +343,5 @@ public class FakePlayer extends ServerPlayerEntity
public void disableAutoRead()
{
}
-
- @Override
- public void setCompressionThreshold( int size )
- {
- }
}
}
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/ClientTableFormatter.java b/src/main/java/dan200/computercraft/client/ClientTableFormatter.java
index 8a0fdb581..194c23689 100644
--- a/src/main/java/dan200/computercraft/client/ClientTableFormatter.java
+++ b/src/main/java/dan200/computercraft/client/ClientTableFormatter.java
@@ -21,10 +21,6 @@ import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
-@SuppressWarnings( {
- "MethodCallSideOnly",
- "LocalVariableDeclarationSideOnly"
-} )
public class ClientTableFormatter implements TableFormatter
{
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
diff --git a/src/main/java/dan200/computercraft/client/SoundManager.java b/src/main/java/dan200/computercraft/client/SoundManager.java
new file mode 100644
index 000000000..d3c67ab5e
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/SoundManager.java
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.sound.AbstractSoundInstance;
+import net.minecraft.client.sound.SoundInstance;
+import net.minecraft.client.sound.TickableSoundInstance;
+import net.minecraft.sound.SoundCategory;
+import net.minecraft.sound.SoundEvent;
+import net.minecraft.util.math.Vec3d;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class SoundManager
+{
+ private static final Map sounds = new HashMap<>();
+
+ public static void playSound( UUID source, Vec3d position, SoundEvent event, float volume, float pitch )
+ {
+ var soundManager = MinecraftClient.getInstance().getSoundManager();
+
+ MoveableSound oldSound = sounds.get( source );
+ if( oldSound != null ) soundManager.stop( oldSound );
+
+ MoveableSound newSound = new MoveableSound( event, position, volume, pitch );
+ sounds.put( source, newSound );
+ soundManager.play( newSound );
+ }
+
+ public static void stopSound( UUID source )
+ {
+ SoundInstance sound = sounds.remove( source );
+ if( sound == null ) return;
+
+ MinecraftClient.getInstance().getSoundManager().stop( sound );
+ }
+
+ public static void moveSound( UUID source, Vec3d position )
+ {
+ MoveableSound sound = sounds.get( source );
+ if( sound != null ) sound.setPosition( position );
+ }
+
+ public static void reset()
+ {
+ sounds.clear();
+ }
+
+ private static class MoveableSound extends AbstractSoundInstance implements TickableSoundInstance
+ {
+ protected MoveableSound( SoundEvent sound, Vec3d position, float volume, float pitch )
+ {
+ super( sound, SoundCategory.RECORDS );
+ setPosition( position );
+ this.volume = volume;
+ this.pitch = pitch;
+ attenuationType = SoundInstance.AttenuationType.LINEAR;
+ }
+
+ void setPosition( Vec3d position )
+ {
+ x = (float) position.getX();
+ y = (float) position.getY();
+ z = (float) position.getZ();
+ }
+
+ @Override
+ public boolean isDone()
+ {
+ return false;
+ }
+
+ @Override
+ public void tick()
+ {
+ }
+ }
+}
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..1373bbc61
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/gui/ComputerScreenBase.java
@@ -0,0 +1,230 @@
+/*
+ * 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.gui;
+
+import dan200.computercraft.ComputerCraft;
+import dan200.computercraft.client.gui.widgets.ComputerSidebar;
+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 dan200.computercraft.shared.computer.upload.FileUpload;
+import dan200.computercraft.shared.computer.upload.UploadResult;
+import dan200.computercraft.shared.network.NetworkHandler;
+import dan200.computercraft.shared.network.server.ContinueUploadMessage;
+import dan200.computercraft.shared.network.server.UploadFileMessage;
+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;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+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;
+
+ 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::addDrawableChild, x, y + 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.
+ }
+
+ @Override
+ public void filesDragged( @Nonnull List files )
+ {
+ // TODO: this thing doesn't work in Tweaked at this moment
+ if ( true ) return;
+ if( files.isEmpty() ) return;
+
+ if( computer == null || !computer.isOn() )
+ {
+ alert( UploadResult.FAILED_TITLE, UploadResult.COMPUTER_OFF_MSG );
+ return;
+ }
+
+ long size = 0;
+
+ List toUpload = new ArrayList<>();
+ for( Path file : files )
+ {
+ // TODO: Recurse directories? If so, we probably want to shunt this off-thread.
+ if( !Files.isRegularFile( file ) ) continue;
+
+ try( SeekableByteChannel sbc = Files.newByteChannel( file ) )
+ {
+ long fileSize = sbc.size();
+ if( fileSize > UploadFileMessage.MAX_SIZE || (size += fileSize) >= UploadFileMessage.MAX_SIZE )
+ {
+ alert( UploadResult.FAILED_TITLE, UploadResult.TOO_MUCH_MSG );
+ return;
+ }
+
+ String name = file.getFileName().toString();
+ if( name.length() > UploadFileMessage.MAX_FILE_NAME )
+ {
+ alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.name_too_long" ) );
+ return;
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocateDirect( (int) fileSize );
+ sbc.read( buffer );
+ buffer.flip();
+
+ byte[] digest = FileUpload.getDigest( buffer );
+ if( digest == null )
+ {
+ alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.corrupted" ) );
+ return;
+ }
+
+ buffer.rewind();
+ toUpload.add( new FileUpload( name, buffer, digest ) );
+ }
+ catch( IOException e )
+ {
+ ComputerCraft.log.error( "Failed uploading files", e );
+ alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.generic", "Cannot compute checksum" ) );
+ }
+ }
+
+ if( toUpload.size() > UploadFileMessage.MAX_FILES )
+ {
+ alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.too_many_files" ) );
+ return;
+ }
+
+ if( toUpload.size() > 0 )
+ {
+ UploadFileMessage.send( computer.getInstanceID(), toUpload );
+ }
+ }
+
+ public void uploadResult( UploadResult result, Text message )
+ {
+ switch( result )
+ {
+ case SUCCESS:
+ alert( UploadResult.SUCCESS_TITLE, message );
+ break;
+ case ERROR:
+ alert( UploadResult.FAILED_TITLE, message );
+ break;
+ case CONFIRM_OVERWRITE:
+ OptionScreen.show(
+ client, UploadResult.UPLOAD_OVERWRITE, message,
+ Arrays.asList(
+ OptionScreen.newButton( CANCEL, b -> cancelUpload() ),
+ OptionScreen.newButton( OVERWRITE, b -> continueUpload() )
+ ),
+ this::cancelUpload
+ );
+ break;
+ }
+ }
+
+ private void continueUpload()
+ {
+ if( client.currentScreen instanceof OptionScreen ) ((OptionScreen) client.currentScreen).disable();
+ NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
+ }
+
+ private void cancelUpload()
+ {
+ client.setScreen( this );
+ NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), false ) );
+ }
+
+ private void alert( Text title, Text message )
+ {
+ OptionScreen.show( client, title, message,
+ Collections.singletonList( OptionScreen.newButton( OK, b -> client.setScreen( this ) ) ),
+ () -> client.setScreen( this )
+ );
+ }
+
+}
diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java
index 0e42a3ead..b0456bd69 100644
--- a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java
+++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java
@@ -6,22 +6,24 @@
package dan200.computercraft.client.gui;
-import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.client.FrameInfo;
+import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.render.*;
+import net.minecraft.client.render.VertexConsumer;
+import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.AffineTransformation;
import net.minecraft.util.math.Matrix4f;
-import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
+
public final class FixedWidthFontRenderer
{
public static final int FONT_HEIGHT = 9;
@@ -31,47 +33,16 @@ public final class FixedWidthFontRenderer
public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
private static final Matrix4f IDENTITY = AffineTransformation.identity()
.getMatrix();
- private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" );
- public static final RenderLayer TYPE = Type.MAIN;
+ public static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" );
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,
- ((VertexConsumerProvider) renderer).getBuffer( TYPE ),
- 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 )
+ float leftMarginSize, float rightMarginSize, int light )
{
if( backgroundColour != null )
{
@@ -99,7 +70,7 @@ public final class FixedWidthFontRenderer
{
index = '?';
}
- drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b );
+ drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b, light );
}
}
@@ -170,7 +141,7 @@ public final class FixedWidthFontRenderer
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
}
- private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b )
+ private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light )
{
// Short circuit to avoid the common case - the texture should be blank here after all.
if( index == '\0' || index == ' ' )
@@ -187,26 +158,32 @@ public final class FixedWidthFontRenderer
buffer.vertex( transform, x, y, 0f )
.color( r, g, b, 1.0f )
.texture( xStart / WIDTH, yStart / WIDTH )
+ .light( light )
.next();
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
.color( r, g, b, 1.0f )
.texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
+ .light( light )
.next();
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
.color( r, g, b, 1.0f )
.texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
+ .light( light )
.next();
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
.color( r, g, b, 1.0f )
.texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
+ .light( light )
.next();
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
.color( r, g, b, 1.0f )
.texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
+ .light( light )
.next();
buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f )
.color( r, g, b, 1.0f )
.texture( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
+ .light( light )
.next();
}
@@ -300,7 +277,7 @@ public final class FixedWidthFontRenderer
palette,
greyscale,
leftMarginSize,
- rightMarginSize );
+ rightMarginSize, FULL_BRIGHT_LIGHTMAP );
}
}
@@ -328,7 +305,7 @@ public final class FixedWidthFontRenderer
b = (float) colour[2];
}
- drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b );
+ drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b, FULL_BRIGHT_LIGHTMAP );
}
}
@@ -342,14 +319,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();
-
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
.getBufferBuilders()
.getEntityVertexConsumers();
- VertexConsumer buffer = renderer.getBuffer( TYPE );
+ VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH );
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
- renderer.draw( TYPE );
+ renderer.draw();
}
public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
@@ -360,13 +335,12 @@ 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();
-
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
.getBufferBuilders()
.getEntityVertexConsumers();
@@ -378,44 +352,12 @@ public final class FixedWidthFontRenderer
float height )
{
Colour colour = Colour.BLACK;
- drawQuad( transform, renderer.getBuffer( TYPE ), 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, renderer.getBuffer( Type.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
- .alpha( ONE_TENTH_ALPHA )
- .lightmap( DISABLE_LIGHTMAP )
- .writeMaskState( COLOR_MASK )
- .build( false ) );
-
- static final RenderLayer BLOCKER = RenderLayer.of( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting
- RenderLayer.MultiPhaseParameters.builder()
- .texture( new RenderPhase.Texture( FONT,
- false,
- false ) ) // blur, minimap
- .alpha( ONE_TENTH_ALPHA )
- .writeMaskState( ALL_MASK )
- .lightmap( DISABLE_LIGHTMAP )
- .build( false ) );
-
- private Type( String name, Runnable setup, Runnable destroy )
- {
- super( name, setup, destroy );
- }
+ drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
}
}
diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java
index a4f40a783..5160b806d 100644
--- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java
+++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java
@@ -6,54 +6,45 @@
package dan200.computercraft.client.gui;
-import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
+import dan200.computercraft.client.gui.widgets.ComputerSidebar;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
-import dan200.computercraft.client.gui.widgets.WidgetWrapper;
import dan200.computercraft.client.render.ComputerBorderRenderer;
-import dan200.computercraft.shared.computer.core.ClientComputer;
-import dan200.computercraft.shared.computer.core.ComputerFamily;
-import dan200.computercraft.shared.computer.inventory.ContainerComputer;
+import dan200.computercraft.client.render.RenderTypes;
+//import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
-import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
-import net.minecraft.client.gui.screen.ingame.HandledScreen;
+//import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
-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 static dan200.computercraft.client.render.ComputerBorderRenderer.getTexture;
-public class GuiComputer extends HandledScreen
+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 + ComputerSidebar.WIDTH;
+ backgroundHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
}
- public static GuiComputer create( ContainerComputer container, PlayerInventory inventory, Text component )
+ public static GuiComputer create( ContainerComputerBase container, PlayerInventory inventory, Text component )
{
return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight );
}
- public static GuiComputer createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component )
+ public static GuiComputer createPocket( ContainerComputerBase container, PlayerInventory inventory, Text component )
{
return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight );
}
@@ -63,96 +54,19 @@ 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 );
-
- children.add( terminalWrapper );
- setFocused( terminalWrapper );
- }
-
@Override
- protected void init()
+ protected WidgetTerminal createTerminal()
{
- initTerminal( BORDER, 0, 0 );
+ return new WidgetTerminal( computer,
+ x + ComputerSidebar.WIDTH + 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.color4f( 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 tick()
- {
- super.tick();
- terminal.update();
+ ComputerBorderRenderer.render(
+ getTexture( family ), terminal.x, terminal.y, getZOffset(),
+ RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() );
+ ComputerSidebar.renderBackground( stack, x, y + sidebarYOffset );
}
}
diff --git a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java
index 773ac2c00..0cfbc3daa 100644
--- a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java
+++ b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java
@@ -9,6 +9,7 @@ package dan200.computercraft.client.gui;
import com.mojang.blaze3d.systems.RenderSystem;
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 +37,9 @@ public class GuiDiskDrive extends HandledScreen
@Override
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
- RenderSystem.color4f( 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/GuiPrinter.java b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java
index f0e29a49b..917a6861a 100644
--- a/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java
+++ b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java
@@ -25,14 +25,6 @@ public class GuiPrinter extends HandledScreen
super( container, player, title );
}
- /*@Override
- protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
- {
- String title = getTitle().getFormattedText();
- font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
- font.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 );
- }*/
-
@Override
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
@@ -44,9 +36,8 @@ public class GuiPrinter extends HandledScreen
@Override
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
- RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
- client.getTextureManager()
- .bindTexture( BACKGROUND );
+ RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
+ RenderSystem.setShaderTexture( 0, BACKGROUND );
drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight );
if( getScreenHandler().isPrinting() )
diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java
index 261948e19..2163ef355 100644
--- a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java
+++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java
@@ -22,6 +22,7 @@ import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull;
import static dan200.computercraft.client.render.PrintoutRenderer.*;
+import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
public class GuiPrintout extends HandledScreen
{
@@ -108,7 +109,7 @@ public class GuiPrintout extends HandledScreen
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
// Draw the printout
- RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
+ RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f );
RenderSystem.enableDepthTest();
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
@@ -116,8 +117,8 @@ public class GuiPrintout extends HandledScreen
.getEntityVertexConsumers();
Matrix4f matrix = transform.peek()
.getModel();
- drawBorder( matrix, renderer, x, y, getZOffset(), page, pages, book );
- drawText( matrix, renderer, x + X_TEXT_MARGIN, y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, text, colours );
+ drawBorder( matrix, renderer, x, y, getZOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP );
+ drawText( matrix, renderer, x + X_TEXT_MARGIN, y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours );
renderer.draw();
}
diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java
index af78829ad..56dd0b1be 100644
--- a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java
+++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java
@@ -8,6 +8,9 @@ package dan200.computercraft.client.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft;
+import dan200.computercraft.client.gui.widgets.ComputerSidebar;
+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 +20,46 @@ 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 );
+
+ family = container.getFamily();
+ backgroundWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
+ backgroundHeight = TEX_HEIGHT;
- this.container = container;
}
@Override
- protected void init()
+ protected WidgetTerminal createTerminal()
{
- initTerminal( 8, 0, 80 );
+ return new WidgetTerminal(
+ computer, x + BORDER + ComputerSidebar.WIDTH, 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.color4f( 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 + ComputerSidebar.WIDTH, 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 +70,8 @@ public class GuiTurtle extends GuiComputer
24,
24 );
}
+
+ RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
+ ComputerSidebar.renderBackground( transform, x, y + sidebarYOffset );
}
}
diff --git a/src/main/java/dan200/computercraft/client/gui/NoTermComputerScreen.java b/src/main/java/dan200/computercraft/client/gui/NoTermComputerScreen.java
new file mode 100644
index 000000000..9c03f5f6b
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/gui/NoTermComputerScreen.java
@@ -0,0 +1,118 @@
+/*
+ * 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.gui;
+
+import dan200.computercraft.ComputerCraft;
+import dan200.computercraft.client.gui.widgets.WidgetTerminal;
+import dan200.computercraft.shared.computer.core.ClientComputer;
+import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
+import net.minecraft.client.font.TextRenderer;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.text.OrderedText;
+import net.minecraft.text.Text;
+import net.minecraft.text.TranslatableText;
+import org.lwjgl.glfw.GLFW;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+
+public class NoTermComputerScreen extends Screen implements ScreenHandlerProvider
+{
+ private final T menu;
+ private WidgetTerminal terminal;
+
+ public NoTermComputerScreen( T menu, PlayerInventory player, Text title )
+ {
+ super( title );
+ this.menu = menu;
+ }
+
+ @Nonnull
+ @Override
+ public T getScreenHandler()
+ {
+ return menu;
+ }
+
+ @Override
+ protected void init()
+ {
+ this.passEvents = true;
+ client.mouse.lockCursor();
+ client.currentScreen = this;
+ super.init();
+ client.keyboard.setRepeatEvents( true );
+
+ terminal = addDrawableChild( new WidgetTerminal( (ClientComputer) menu.getComputer(), 0, 0, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ) );
+ terminal.visible = false;
+ terminal.active = false;
+ setFocused( terminal );
+ }
+
+ @Override
+ public final void removed()
+ {
+ super.removed();
+ client.keyboard.setRepeatEvents( false );
+ }
+
+ @Override
+ public final void tick()
+ {
+ super.tick();
+ terminal.update();
+ }
+
+ @Override
+ public boolean mouseScrolled( double pMouseX, double pMouseY, double pDelta )
+ {
+ client.player.getInventory().scrollInHotbar( pDelta );
+ return super.mouseScrolled( pMouseX, pMouseY, pDelta );
+ }
+
+ @Override
+ public void onClose()
+ {
+ client.player.closeHandledScreen();
+ super.onClose();
+ }
+
+ @Override
+ public boolean isPauseScreen()
+ {
+ return false;
+ }
+
+ @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 void render( MatrixStack transform, int mouseX, int mouseY, float partialTicks )
+ {
+ super.render( transform, mouseX, mouseY, partialTicks );
+
+ TextRenderer font = client.textRenderer;
+ List lines = font.wrapLines( new TranslatableText( "gui.computercraft.pocket_computer_overlay" ), (int) (width * 0.8) );
+ float y = 10.0f;
+ for( OrderedText line : lines )
+ {
+ font.drawWithShadow( transform, line, (float) ((width / 2) - (client.textRenderer.getWidth( line ) / 2)), y, 0xFFFFFF );
+ y += 9.0f;
+ }
+ }
+}
diff --git a/src/main/java/dan200/computercraft/client/gui/OptionScreen.java b/src/main/java/dan200/computercraft/client/gui/OptionScreen.java
new file mode 100644
index 000000000..23de17f2a
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/gui/OptionScreen.java
@@ -0,0 +1,128 @@
+/*
+ * 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.gui;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.font.MultilineText;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.gui.widget.ClickableWidget;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+
+public final class OptionScreen extends Screen
+{
+ private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/blank_screen.png" );
+
+ public static final int BUTTON_WIDTH = 100;
+ public static final int BUTTON_HEIGHT = 20;
+
+ private static final int PADDING = 16;
+ private static final int FONT_HEIGHT = 9;
+
+ private int x;
+ private int y;
+ private int innerWidth;
+ private int innerHeight;
+
+ private MultilineText messageRenderer;
+ private final Text message;
+ private final List buttons;
+ private final Runnable exit;
+
+ private final Screen originalScreen;
+
+ private OptionScreen( Text title, Text message, List buttons, Runnable exit, Screen originalScreen )
+ {
+ super( title );
+ this.message = message;
+ this.buttons = buttons;
+ this.exit = exit;
+ this.originalScreen = originalScreen;
+ }
+
+ public static void show( MinecraftClient client, Text title, Text message, List buttons, Runnable exit )
+ {
+ client.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( client.currentScreen ) ) );
+ }
+
+ public static Screen unwrap( Screen screen )
+ {
+ return screen instanceof OptionScreen ? ((OptionScreen) screen).getOriginalScreen() : screen;
+ }
+
+ @Override
+ public void init()
+ {
+ super.init();
+
+ int buttonWidth = BUTTON_WIDTH * buttons.size() + PADDING * (buttons.size() - 1);
+ int innerWidth = this.innerWidth = Math.max( 256, buttonWidth + PADDING * 2 );
+
+ messageRenderer = MultilineText.create( textRenderer, message, innerWidth - PADDING * 2 );
+
+ int textHeight = messageRenderer.count() * FONT_HEIGHT + PADDING * 2;
+ innerHeight = textHeight + (buttons.isEmpty() ? 0 : buttons.get( 0 ).getHeight()) + PADDING;
+
+ x = (width - innerWidth) / 2;
+ y = (height - innerHeight) / 2;
+
+ int x = (width - buttonWidth) / 2;
+ for( ClickableWidget button : buttons )
+ {
+ button.x = x;
+ button.y = y + textHeight;
+ addDrawableChild( button );
+
+ x += BUTTON_WIDTH + PADDING;
+ }
+ }
+
+ @Override
+ public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
+ {
+ renderBackground( transform );
+
+ // Render the actual texture.
+ RenderSystem.setShaderTexture( 0, BACKGROUND );
+ drawTexture( transform, x, y, 0, 0, innerWidth, PADDING );
+ drawTexture( transform,
+ x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
+ innerWidth, PADDING
+ );
+ drawTexture( transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING );
+
+ messageRenderer.draw( transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040 );
+ super.render( transform, mouseX, mouseY, partialTicks );
+ }
+
+ @Override
+ public void onClose()
+ {
+ exit.run();
+ }
+
+ public static ClickableWidget newButton( Text component, ButtonWidget.PressAction clicked )
+ {
+ return new ButtonWidget( 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, component, clicked );
+ }
+
+ public void disable()
+ {
+ for( ClickableWidget widget : buttons ) widget.active = false;
+ }
+
+ @Nonnull
+ public Screen getOriginalScreen()
+ {
+ return originalScreen;
+ }
+}
diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/ComputerSidebar.java b/src/main/java/dan200/computercraft/client/gui/widgets/ComputerSidebar.java
new file mode 100644
index 000000000..25d87c8dc
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/gui/widgets/ComputerSidebar.java
@@ -0,0 +1,107 @@
+/*
+ * 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.gui.widgets;
+
+import dan200.computercraft.ComputerCraft;
+import dan200.computercraft.client.render.ComputerBorderRenderer;
+import dan200.computercraft.shared.command.text.ChatHelpers;
+import dan200.computercraft.shared.computer.core.ClientComputer;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ClickableWidget;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.TranslatableText;
+import net.minecraft.util.Formatting;
+import net.minecraft.util.Identifier;
+
+import java.util.Arrays;
+import java.util.function.Consumer;
+
+/**
+ * Registers buttons to interact with a computer.
+ */
+public final class ComputerSidebar
+{
+ private static final Identifier TEXTURE = new Identifier( ComputerCraft.MOD_ID, "textures/gui/buttons.png" );
+
+ private static final int TEX_SIZE = 64;
+
+ private static final int ICON_WIDTH = 12;
+ private static final int ICON_HEIGHT = 12;
+ private static final int ICON_MARGIN = 2;
+
+ private static final int ICON_TEX_Y_DIFF = 14;
+
+ private static final int CORNERS_BORDER = 3;
+ private static final int FULL_BORDER = CORNERS_BORDER + ICON_MARGIN;
+
+ private static final int BUTTONS = 2;
+ private static final int HEIGHT = (ICON_HEIGHT + ICON_MARGIN * 2) * BUTTONS + CORNERS_BORDER * 2;
+ public static final int WIDTH = 17;
+
+ private ComputerSidebar()
+ {
+ }
+
+ public static void addButtons( Screen screen, ClientComputer computer, Consumer add, int x, int y )
+ {
+ x += CORNERS_BORDER + 1;
+ y += CORNERS_BORDER + ICON_MARGIN;
+
+ add.accept( new DynamicImageButton(
+ screen, x, y, ICON_WIDTH, ICON_HEIGHT, () -> computer.isOn() ? 15 : 1, 1, ICON_TEX_Y_DIFF,
+ TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
+ () -> computer.isOn() ? Arrays.asList(
+ new TranslatableText( "gui.computercraft.tooltip.turn_off" ),
+ ChatHelpers.coloured( new TranslatableText( "gui.computercraft.tooltip.turn_off.key" ), Formatting.GRAY )
+ ) : Arrays.asList(
+ new TranslatableText( "gui.computercraft.tooltip.turn_on" ),
+ ChatHelpers.coloured( new TranslatableText( "gui.computercraft.tooltip.turn_off.key" ), Formatting.GRAY )
+ )
+ ) );
+
+ y += ICON_HEIGHT + ICON_MARGIN * 2;
+
+ add.accept( new DynamicImageButton(
+ screen, x, y, ICON_WIDTH, ICON_HEIGHT, 29, 1, ICON_TEX_Y_DIFF,
+ TEXTURE, TEX_SIZE, TEX_SIZE, b -> computer.queueEvent( "terminate" ),
+ Arrays.asList(
+ new TranslatableText( "gui.computercraft.tooltip.terminate" ),
+ ChatHelpers.coloured( new TranslatableText( "gui.computercraft.tooltip.terminate.key" ), Formatting.GRAY )
+ )
+ ) );
+ }
+
+ public static void renderBackground( MatrixStack transform, int x, int y )
+ {
+ Screen.drawTexture( transform,
+ x, y, 0, 102, WIDTH, FULL_BORDER,
+ ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
+ );
+
+ Screen.drawTexture( transform,
+ x, y + FULL_BORDER, WIDTH, HEIGHT - FULL_BORDER * 2,
+ 0, 107, WIDTH, 4,
+ ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
+ );
+
+ Screen.drawTexture( transform,
+ x, y + HEIGHT - FULL_BORDER, 0, 111, WIDTH, FULL_BORDER,
+ ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
+ );
+ }
+
+ private static void toggleComputer( ClientComputer computer )
+ {
+ if( computer.isOn() )
+ {
+ computer.shutdown();
+ }
+ else
+ {
+ computer.turnOn();
+ }
+ }
+}
diff --git a/src/main/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java b/src/main/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java
new file mode 100644
index 000000000..4e8751883
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java
@@ -0,0 +1,100 @@
+/*
+ * 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.gui.widgets;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.LiteralText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+/**
+ * Version of {@link net.minecraft.client.gui.widget.TexturedButtonWidget} which allows changing some properties
+ * dynamically.
+ */
+public class DynamicImageButton extends ButtonWidget
+{
+ private final Screen screen;
+ private final Identifier texture;
+ private final IntSupplier xTexStart;
+ private final int yTexStart;
+ private final int yDiffTex;
+ private final int textureWidth;
+ private final int textureHeight;
+ private final Supplier> tooltip;
+
+ public DynamicImageButton(
+ Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
+ Identifier texture, int textureWidth, int textureHeight,
+ PressAction onPress, List tooltip
+ )
+ {
+ this(
+ screen, x, y, width, height, () -> xTexStart, yTexStart, yDiffTex,
+ texture, textureWidth, textureHeight,
+ onPress, () -> tooltip
+ );
+ }
+
+
+ public DynamicImageButton(
+ Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
+ Identifier texture, int textureWidth, int textureHeight,
+ PressAction onPress, Supplier> tooltip
+ )
+ {
+ super( x, y, width, height, LiteralText.EMPTY, onPress );
+ this.screen = screen;
+ this.textureWidth = textureWidth;
+ this.textureHeight = textureHeight;
+ this.xTexStart = xTexStart;
+ this.yTexStart = yTexStart;
+ this.yDiffTex = yDiffTex;
+ this.texture = texture;
+ this.tooltip = tooltip;
+ }
+
+ @Override
+ public void renderButton( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
+ {
+ RenderSystem.setShaderTexture( 0, texture );
+ RenderSystem.disableDepthTest();
+
+ int yTex = yTexStart;
+ if( isHovered() ) yTex += yDiffTex;
+
+ drawTexture( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
+ RenderSystem.enableDepthTest();
+
+ if( isHovered() ) renderToolTip( stack, mouseX, mouseY );
+ }
+
+ @Nonnull
+ @Override
+ public Text getMessage()
+ {
+ List tooltip = this.tooltip.get();
+ return tooltip.isEmpty() ? LiteralText.EMPTY : tooltip.get( 0 );
+ }
+
+ // @Override
+ public void renderToolTip( @Nonnull MatrixStack stack, int mouseX, int mouseY )
+ {
+ List tooltip = this.tooltip.get();
+
+ if( !tooltip.isEmpty() )
+ {
+ screen.renderTooltip( stack, tooltip, mouseX, mouseY );
+ }
+ }
+}
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..62c3d8404 100644
--- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java
+++ b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetTerminal.java
@@ -9,66 +9,84 @@ package dan200.computercraft.client.gui.widgets;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.Terminal;
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.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 BitSet keysDown = new BitSet( 256 );
- private boolean focused;
+ 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 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 )
+ private final BitSet keysDown = new BitSet( 256 );
+
+ 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 charTyped( char ch, int modifiers )
+ {
+ if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
+ {
+ // Queue the "char" event
+ queueEvent( "char", Character.toString( ch ) );
+ }
+
+ return true;
+ }
+
+ private boolean inTermRegion( double mouseX, double mouseY )
+ {
+ return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
}
@Override
public boolean mouseClicked( double mouseX, double mouseY, int button )
{
- ClientComputer computer = this.computer.get();
- if( computer == null || !computer.isColour() || button < 0 || button > 2 )
- {
- return false;
- }
+ if( !inTermRegion( mouseX, mouseY ) ) return false;
+ if( !computer.isColour() || button < 0 || button > 2 ) return false;
Terminal term = computer.getTerminal();
if( term != null )
{
- int charX = (int) (mouseX / FONT_WIDTH);
- int charY = (int) (mouseY / FONT_HEIGHT);
+ int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
+ int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
@@ -85,17 +103,14 @@ public class WidgetTerminal implements Element
@Override
public boolean mouseReleased( double mouseX, double mouseY, int button )
{
- ClientComputer computer = this.computer.get();
- if( computer == null || !computer.isColour() || button < 0 || button > 2 )
- {
- return false;
- }
+ if( !inTermRegion( mouseX, mouseY ) ) return false;
+ if( !computer.isColour() || button < 0 || button > 2 ) return false;
Terminal term = computer.getTerminal();
if( term != null )
{
- int charX = (int) (mouseX / FONT_WIDTH);
- int charY = (int) (mouseY / FONT_HEIGHT);
+ int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
+ int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
@@ -115,17 +130,14 @@ public class WidgetTerminal implements Element
@Override
public boolean mouseDragged( double mouseX, double mouseY, int button, double v2, double v3 )
{
- ClientComputer computer = this.computer.get();
- if( computer == null || !computer.isColour() || button < 0 || button > 2 )
- {
- return false;
- }
+ if( !inTermRegion( mouseX, mouseY ) ) return false;
+ if( !computer.isColour() || button < 0 || button > 2 ) return false;
Terminal term = computer.getTerminal();
if( term != null )
{
- int charX = (int) (mouseX / FONT_WIDTH);
- int charY = (int) (mouseY / FONT_HEIGHT);
+ int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
+ int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
@@ -143,17 +155,14 @@ public class WidgetTerminal implements Element
@Override
public boolean mouseScrolled( double mouseX, double mouseY, double delta )
{
- ClientComputer computer = this.computer.get();
- if( computer == null || !computer.isColour() || delta == 0 )
- {
- return false;
- }
+ if( !inTermRegion( mouseX, mouseY ) ) return false;
+ if( !computer.isColour() || delta == 0 ) return false;
Terminal term = computer.getTerminal();
if( term != null )
{
- int charX = (int) (mouseX / FONT_WIDTH);
- int charY = (int) (mouseY / FONT_HEIGHT);
+ int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
+ int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
@@ -198,7 +207,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,11 +248,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();
- if( computer != null )
- {
- computer.keyDown( key, repeat );
- }
+ computer.keyDown( key, repeat );
}
return true;
@@ -256,11 +261,7 @@ public class WidgetTerminal implements Element
if( key >= 0 && keysDown.get( key ) )
{
keysDown.set( key, false );
- IComputer computer = this.computer.get();
- if( computer != null )
- {
- computer.keyUp( key );
- }
+ computer.keyUp( key );
}
switch( key )
@@ -284,47 +285,26 @@ public class WidgetTerminal implements Element
}
@Override
- public boolean charTyped( char ch, int modifiers )
+ public void onFocusedChanged( boolean focused )
{
- if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
- {
- // Queue the "char" event
- queueEvent( "char", Character.toString( ch ) );
- }
-
- return true;
- }
-
- @Override
- public boolean changeFocus( boolean reversed )
- {
- 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,11 +315,7 @@ public class WidgetTerminal implements Element
private void queueEvent( String event, Object... args )
{
- ClientComputer computer = this.computer.get();
- if( computer != null )
- {
- computer.queueEvent( event, args );
- }
+ computer.queueEvent( event, args );
}
public void update()
@@ -351,50 +327,53 @@ public class WidgetTerminal implements Element
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
{
- ClientComputer computer = this.computer.get();
- if( computer != null )
- {
- computer.shutdown();
- }
+ computer.shutdown();
}
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
{
- ClientComputer computer = this.computer.get();
- if( computer != null )
- {
- computer.reboot();
- }
+ computer.reboot();
}
}
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/gui/widgets/WidgetWrapper.java b/src/main/java/dan200/computercraft/client/gui/widgets/WidgetWrapper.java
deleted file mode 100644
index c805a16ce..000000000
--- a/src/main/java/dan200/computercraft/client/gui/widgets/WidgetWrapper.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.gui.widgets;
-
-import net.minecraft.client.gui.Element;
-
-public class WidgetWrapper implements Element
-{
- private final Element listener;
- private final int x;
- private final int y;
- private final int width;
- private final int height;
-
- public WidgetWrapper( Element listener, int x, int y, int width, int height )
- {
- this.listener = listener;
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- }
-
- @Override
- public boolean mouseClicked( double x, double y, int button )
- {
- double dx = x - this.x, dy = y - this.y;
- return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseClicked( dx, dy, button );
- }
-
- @Override
- public boolean mouseReleased( double x, double y, int button )
- {
- double dx = x - this.x, dy = y - this.y;
- return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseReleased( dx, dy, button );
- }
-
- @Override
- public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
- {
- double dx = x - this.x, dy = y - this.y;
- return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseDragged( dx, dy, button, deltaX, deltaY );
- }
-
- @Override
- public boolean mouseScrolled( double x, double y, double delta )
- {
- double dx = x - this.x, dy = y - this.y;
- return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseScrolled( dx, dy, delta );
- }
-
- @Override
- public boolean keyPressed( int key, int scancode, int modifiers )
- {
- return listener.keyPressed( key, scancode, modifiers );
- }
-
- @Override
- public boolean keyReleased( int key, int scancode, int modifiers )
- {
- return listener.keyReleased( key, scancode, modifiers );
- }
-
- @Override
- public boolean charTyped( char character, int modifiers )
- {
- return listener.charTyped( character, modifiers );
- }
-
- @Override
- public boolean changeFocus( boolean b )
- {
- return listener.changeFocus( b );
- }
-
- @Override
- public boolean isMouseOver( double x, double y )
- {
- double dx = x - this.x, dy = y - this.y;
- return dx >= 0 && dx < width && dy >= 0 && dy < height;
- }
-
- public int getX()
- {
- return x;
- }
-
- public int getY()
- {
- return y;
- }
-
- public int getWidth()
- {
- return width;
- }
-
- public int getHeight()
- {
- return height;
- }
-}
diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java
index fa7c0a8f1..3d22b88ef 100644
--- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java
+++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java
@@ -19,12 +19,11 @@ 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.inventory.ContainerComputer;
+import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
-import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import dan200.computercraft.shared.util.Config;
@@ -35,12 +34,12 @@ 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.rendereregistry.v1.BlockEntityRendererRegistry;
-import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
+import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
+import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
-import net.fabricmc.fabric.mixin.object.builder.ModelPredicateProviderRegistrySpecificAccessor;
-import net.minecraft.client.item.ModelPredicateProvider;
+import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
+import net.minecraft.client.item.UnclampedModelPredicateProvider;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.item.Item;
import net.minecraft.screen.PlayerScreenHandler;
@@ -76,33 +75,32 @@ 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() );
// Setup TESRs
- BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
- BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
- BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
- BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
+ BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
+ BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
+ BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
+ BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
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 );
- EntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
+ EntityRendererRegistry.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
registerItemProperty( "state",
- ( stack, world, player ) -> ItemPocketComputer.getState( stack )
+ ( stack, world, player, integer ) -> ItemPocketComputer.getState( stack )
.ordinal(),
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
registerItemProperty( "state",
- ( stack, world, player ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
+ ( stack, world, player, integer ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
ClientRegistry.onItemColours();
@@ -113,9 +111,11 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
// My IDE doesn't think so, but we do actually need these generics.
private static void registerContainers()
{
- ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
- ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
+ ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
+ ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
GuiComputer::createPocket );
+ ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER_NO_TERM,
+ NoTermComputerScreen::new );
ScreenRegistry.register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new );
ScreenRegistry.register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new );
@@ -127,12 +127,12 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
}
@SafeVarargs
- private static void registerItemProperty( String name, ModelPredicateProvider getter, Supplier extends Item>... items )
+ private static void registerItemProperty( String name, UnclampedModelPredicateProvider getter, Supplier extends Item>... items )
{
Identifier id = new Identifier( ComputerCraft.MOD_ID, name );
for( Supplier extends Item> item : items )
{
- ModelPredicateProviderRegistrySpecificAccessor.callRegister( item.get(), id, getter );
+ FabricModelPredicateProviderRegistry.register( item.get(), id, getter );
}
}
}
diff --git a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java
index 2532e044f..32965f478 100644
--- a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java
@@ -18,9 +18,7 @@ import net.minecraft.client.render.Camera;
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.Matrix4f;
-import net.minecraft.util.math.Vec3d;
+import net.minecraft.util.math.*;
import net.minecraft.util.shape.VoxelShape;
@Environment( EnvType.CLIENT )
@@ -49,17 +47,29 @@ public final class CableHighlightRenderer
state );
Vec3d cameraPos = info.getPos();
+
double xOffset = pos.getX() - cameraPos.getX();
double yOffset = pos.getY() - cameraPos.getY();
double zOffset = pos.getZ() - cameraPos.getZ();
Matrix4f matrix4f = stack.peek()
.getModel();
+ Matrix3f normal = stack.peek().getNormal();
shape.forEachEdge( ( x1, y1, z1, x2, y2, z2 ) -> {
+ float xDelta = (float) (x2 - x1);
+ float yDelta = (float) (y2 - y1);
+ float zDelta = (float) (z2 - z1);
+ float len = MathHelper.sqrt( xDelta * xDelta + yDelta * yDelta + zDelta * zDelta );
+ xDelta = xDelta / len;
+ yDelta = yDelta / len;
+ zDelta = zDelta / len;
+
consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
.color( 0, 0, 0, 0.4f )
+ .normal( normal, xDelta, yDelta, zDelta )
.next();
consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
.color( 0, 0, 0, 0.4f )
+ .normal( normal, xDelta, yDelta, zDelta )
.next();
} );
diff --git a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java
index 65166b05d..c36acd10e 100644
--- a/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/ComputerBorderRenderer.java
@@ -5,16 +5,14 @@
*/
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.RenderLayer;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexConsumer;
-import net.minecraft.client.render.VertexFormats;
+import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Matrix4f;
-import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;
@@ -42,7 +40,8 @@ public class ComputerBorderRenderer
private static final int LIGHT_CORNER_Y = 80;
public static final int LIGHT_HEIGHT = 8;
- private static final float TEX_SCALE = 1 / 256.0f;
+ public static final int TEX_SIZE = 256;
+ private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
static
{
@@ -54,11 +53,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;
@@ -80,31 +82,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( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE );
-
- render( IDENTITY, buffer, x, y, z, width, height );
-
- RenderSystem.enableAlphaTest();
- 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 )
@@ -157,18 +145,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/ItemMapLikeRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java
index 6ecd99254..f1ef584c5 100644
--- a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java
@@ -89,7 +89,7 @@ public abstract class ItemMapLikeRenderer
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) );
transform.scale( 2.0F, 2.0F, 2.0F );
- renderItem( transform, render, stack );
+ renderItem( transform, render, stack, combinedLight );
}
/**
@@ -133,7 +133,7 @@ public abstract class ItemMapLikeRenderer
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) );
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) );
- renderItem( transform, render, stack );
+ renderItem( transform, render, stack, combinedLight );
transform.pop();
}
@@ -144,6 +144,7 @@ public abstract class ItemMapLikeRenderer
* @param transform The matrix transformation stack
* @param render The buffer to render to
* @param stack The stack to render
+ * @param light TODO rebase
*/
- protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack );
+ protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light );
}
diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java
index ec96c0d81..23982f3a9 100644
--- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java
@@ -15,15 +15,12 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.render.BufferBuilder;
-import net.minecraft.client.render.Tessellator;
-import net.minecraft.client.render.VertexConsumerProvider;
-import net.minecraft.client.render.VertexFormats;
+import net.minecraft.client.render.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.Identifier;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3f;
-import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
@@ -41,7 +38,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
}
@Override
- protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack )
+ protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light )
{
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
Terminal terminal = computer == null ? null : computer.getTerminal();
@@ -79,7 +76,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
Matrix4f matrix = transform.peek()
.getModel();
- renderFrame( matrix, family, frameColour, width, height );
+ renderFrame( matrix, render, family, frameColour, light, width, height );
// Render the light
int lightColour = ItemPocketComputer.getLightState( stack );
@@ -91,7 +88,12 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
if( computer != null && terminal != null )
{
- FixedWidthFontRenderer.drawTerminal( matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN );
+ FixedWidthFontRenderer.drawTerminal(
+ matrix, render.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
+ MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN
+ );
+ FixedWidthFontRenderer.drawBlocker( transform.peek().getModel(), render, 0, 0, width, height );
+
}
else
{
@@ -101,24 +103,20 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
transform.pop();
}
- private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height )
+ private static void renderFrame( Matrix4f transform, VertexConsumerProvider render, ComputerFamily family, int colour, int light, int width, int height )
{
RenderSystem.enableBlend();
MinecraftClient.getInstance()
.getTextureManager()
.bindTexture( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) );
+ Identifier texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family );
+
float r = ((colour >>> 16) & 0xFF) / 255.0f;
float g = ((colour >>> 8) & 0xFF) / 255.0f;
float b = (colour & 0xFF) / 255.0f;
- Tessellator tessellator = Tessellator.getInstance();
- BufferBuilder buffer = tessellator.getBuffer();
- buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE );
-
- ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b );
-
- tessellator.draw();
+ ComputerBorderRenderer.render( transform, render.getBuffer( RenderLayer.getText( texture ) ), 0, 0, 0, light, width, height, true, r, g, b );
}
private static void renderLight( Matrix4f transform, int colour, int width, int height )
@@ -131,7 +129,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
- buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR );
+ buffer.begin( VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR );
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
.color( r, g, b, 1.0f )
.next();
diff --git a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java
index e45ec3ef4..3760a6f80 100644
--- a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java
@@ -9,6 +9,7 @@ package dan200.computercraft.client.render;
import dan200.computercraft.shared.media.items.ItemPrintout;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.util.math.Vec3f;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3f;
@@ -31,16 +32,16 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
}
@Override
- protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack )
+ protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light )
{
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( 180f ) );
transform.scale( 0.42f, 0.42f, -0.42f );
transform.translate( -0.5f, -0.48f, 0.0f );
- drawPrintout( transform, render, stack );
+ drawPrintout( transform, render, stack, light );
}
- private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack )
+ private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light )
{
int pages = ItemPrintout.getPageCount( stack );
boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK;
@@ -72,11 +73,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
Matrix4f matrix = transform.peek()
.getModel();
- drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book );
- drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
+ drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light );
+ drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
}
- public boolean renderInFrame( MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack )
+ public boolean renderInFrame( MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack, int light )
{
if( !(stack.getItem() instanceof ItemPrintout) )
{
@@ -89,7 +90,7 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
matrixStack.scale( 0.95f, 0.95f, -0.95f );
matrixStack.translate( -0.5f, -0.5f, 0.0f );
- drawPrintout( matrixStack, consumerProvider, stack );
+ drawPrintout( matrixStack, consumerProvider, stack, light );
return true;
}
diff --git a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java
index ce01b25b6..1556246a1 100644
--- a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java
+++ b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java
@@ -5,7 +5,6 @@
*/
package dan200.computercraft.client.render;
-import dan200.computercraft.fabric.mixin.BakedQuadAccess;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.VertexFormat;
@@ -14,6 +13,7 @@ import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vector4f;
+
import java.util.List;
/**
@@ -57,30 +57,43 @@ public final class ModelTransformer
private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform )
{
int[] vertexData = quad.getVertexData().clone();
- BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), ((BakedQuadAccess) quad).getSprite(), true );
+ BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), quad.getSprite(), true );
int offsetBytes = 0;
for( int v = 0; v < 4; ++v )
{
for( VertexFormatElement element : format.getElements() ) // For each vertex element
{
- int start = offsetBytes / Integer.BYTES;
- if( element.getType() == VertexFormatElement.Type.POSITION && element.getDataType() == VertexFormatElement.DataType.FLOAT ) // When we find a position element
+ if( element.isPosition() &&
+ element.getDataType() == VertexFormatElement.DataType.FLOAT &&
+ element.getLength() == 3 ) // When we find a position element
{
- Vector4f pos = new Vector4f( Float.intBitsToFloat( vertexData[start] ),
- Float.intBitsToFloat( vertexData[start + 1] ),
- Float.intBitsToFloat( vertexData[start + 2] ),
- 1 );
+ for ( int j = 0; j < 4; ++j ) // For each corner of the quad
+ {
+ int start = offsetBytes + j * format.getVertexSize();
+ if ( (start % 4) == 0 )
+ {
+ start = start / 4;
- // Transform the position
- pos.transform( transform );
+ // Extract the position
+ Vector4f pos = new Vector4f(
+ Float.intBitsToFloat( vertexData[start] ),
+ Float.intBitsToFloat( vertexData[start + 1] ),
+ Float.intBitsToFloat( vertexData[start + 2] ),
+ 1
+ );
- // Insert the position
- vertexData[start] = Float.floatToRawIntBits( pos.getX() );
- vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() );
- vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() );
+ // Transform the position
+ pos.transform( transform );
+
+ // Insert the position
+ vertexData[start] = Float.floatToRawIntBits( pos.getX() );
+ vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() );
+ vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() );
+ }
+ }
}
- offsetBytes += element.getByteLength();
+ offsetBytes += element.getLength();
}
}
return copy;
diff --git a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java
index d0117b2ac..d4083c67f 100644
--- a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java
@@ -15,14 +15,10 @@ import net.minecraft.client.MinecraftClient;
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;
-
import static net.minecraft.util.math.Direction.*;
/**
@@ -36,9 +32,7 @@ public final class MonitorHighlightRenderer
{
}
- public static boolean drawHighlight(
- MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState
- )
+ public static boolean drawHighlight( MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState )
{
// Preserve normal behaviour when crouching.
if( entity.isInSneakingPose() )
@@ -49,13 +43,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 +79,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 +134,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 405f056b8..bd14234a0 100644
--- a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java
+++ b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java
@@ -5,180 +5,107 @@
*/
package dan200.computercraft.client.render;
-import com.google.common.base.Strings;
-import com.mojang.blaze3d.platform.GlStateManager;
-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.client.texture.TextureUtil;
-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;
-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;
-
- private static boolean initialised;
- private static boolean ok;
- private static int program;
-
- static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale )
+ public MonitorTextureBufferShader( ResourceFactory factory, String name, VertexFormat format ) throws IOException
{
- MATRIX_BUFFER.rewind();
- transform.writeColumnMajor( MATRIX_BUFFER );
- MATRIX_BUFFER.rewind();
- RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER );
+ super( factory, name, format );
- RenderSystem.glUniform1i( uniformWidth, width );
- RenderSystem.glUniform1i( uniformHeight, height );
+ width = getUniformChecked( "Width" );
+ height = getUniformChecked( "Height" );
+ palette = new GlUniform( "Palette", GlUniform.field_32044 /* UT_FLOAT3 */, 16 * 3, this );
+ updateUniformLocation( palette );
- PALETTE_BUFFER.rewind();
+ GlUniform tbo = getUniformChecked( "Tbo" );
+ if( tbo != null ) tbo.set( TEXTURE_INDEX - GL13.GL_TEXTURE0 );
+ }
+
+ void setupUniform( int width, int height, Palette palette, boolean greyscale )
+ {
+ if( this.width != null ) this.width.set( width );
+ if( this.height != null ) this.height.set( height );
+ setupPalette( palette, greyscale );
+ }
+
+ private void setupPalette( Palette palette, boolean greyscale )
+ {
+ if( this.palette == null ) return;
+
+ 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.useProgram( 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.createProgram();
- GlStateManager.attachShader( program, vertexShader );
- GlStateManager.attachShader( program, fragmentShader );
- GL20.glBindAttribLocation( program, 0, "v_pos" );
-
- GlStateManager.linkProgram( program );
- boolean ok = GlStateManager.getProgram( program, GL20.GL_LINK_STATUS ) != 0;
- String log = GlStateManager.getProgramInfoLog( 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.deleteShader( vertexShader );
- GlStateManager.deleteShader( 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 );
- }
- String contents = TextureUtil.readAllToString( stream );
-
- int shader = GlStateManager.createShader( kind );
-
- GlStateManager.shaderSource( shader, contents );
- GlStateManager.compileShader( shader );
-
- boolean ok = GlStateManager.getShader( shader, GL20.GL_COMPILE_STATUS ) != 0;
- String log = GlStateManager.getShaderInfoLog( 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.getUniformLocation( 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 489506aae..7b8c809a5 100644
--- a/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/PrintoutRenderer.java
@@ -9,10 +9,9 @@ package dan200.computercraft.client.render;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Palette;
-import net.minecraft.client.render.*;
-import net.minecraft.util.Identifier;
+import net.minecraft.client.render.VertexConsumer;
+import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.util.math.Matrix4f;
-import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE;
@@ -39,7 +38,6 @@ public final class PrintoutRenderer
* Size of the leather cover.
*/
public static final int COVER_SIZE = 12;
- private static final Identifier BG = new Identifier( "computercraft", "textures/gui/printout.png" );
private static final float BG_SIZE = 256.0f;
/**
* Width of the extra page texture.
@@ -50,9 +48,9 @@ public final class PrintoutRenderer
private PrintoutRenderer() {}
- public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours )
+ public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours )
{
- VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
+ VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
{
FixedWidthFontRenderer.drawString( transform,
@@ -65,13 +63,14 @@ public final class PrintoutRenderer
Palette.DEFAULT,
false,
0,
- 0 );
+ 0,
+ light );
}
}
- public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours )
+ public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, int light, String[] text, String[] colours )
{
- VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
+ VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
{
FixedWidthFontRenderer.drawString( transform,
@@ -84,16 +83,17 @@ public final class PrintoutRenderer
Palette.DEFAULT,
false,
0,
- 0 );
+ 0,
+ light );
}
}
- public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook )
+ public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook, int light )
{
int leftPages = page;
int rightPages = pages - page - 1;
- VertexConsumer buffer = renderer.getBuffer( Type.TYPE );
+ VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_BACKGROUND );
if( isBook )
{
@@ -103,8 +103,8 @@ public final class PrintoutRenderer
float right = x + X_SIZE + offset - 4;
// Left and right border
- drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
- drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
+ drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
+ drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
// Draw centre panel (just stretched texture, sorry).
drawTexture( transform,
@@ -117,34 +117,35 @@ public final class PrintoutRenderer
COVER_X + COVER_SIZE / 2.0f,
COVER_SIZE,
COVER_SIZE,
- Y_SIZE );
+ Y_SIZE,
+ light );
float borderX = left;
while( borderX < right )
{
double thisWidth = Math.min( right - borderX, X_SIZE );
- drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE );
- drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE );
+ drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE, light );
+ drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE, light );
borderX += thisWidth;
}
}
// Left half
- drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE );
+ drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE, light );
for( int n = 0; n <= leftPages; n++ )
{
drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n,
// Use the left "bold" fold for the outermost page
- n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE );
+ n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE, light );
}
// Right half
- drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE );
+ drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE, light );
for( int n = 0; n <= rightPages; n++ )
{
drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
- X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE );
+ X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE, light );
}
}
@@ -153,57 +154,25 @@ public final class PrintoutRenderer
return (float) (32 * (1 - Math.pow( 1.2, -page )));
}
- private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height )
+ private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light )
{
- buffer.vertex( matrix, x, y + height, z )
- .texture( u / BG_SIZE, (v + height) / BG_SIZE )
- .next();
- buffer.vertex( matrix, x + width, y + height, z )
- .texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE )
- .next();
- buffer.vertex( matrix, x + width, y, z )
- .texture( (u + width) / BG_SIZE, v / BG_SIZE )
- .next();
- buffer.vertex( matrix, x, y, z )
- .texture( u / BG_SIZE, v / BG_SIZE )
- .next();
+ vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light );
+ vertex( buffer, matrix, x + width, y + height, z, (u + width) / BG_SIZE, (v + height) / BG_SIZE, light );
+ vertex( buffer, matrix, x + width, y, z, (u + width) / BG_SIZE, v / BG_SIZE, light );
+ vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
}
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v,
- float tWidth, float tHeight )
+ float tWidth, float tHeight, int light )
{
- buffer.vertex( matrix, x, y + height, z )
- .texture( u / BG_SIZE, (v + tHeight) / BG_SIZE )
- .next();
- buffer.vertex( matrix, x + width, y + height, z )
- .texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE )
- .next();
- buffer.vertex( matrix, x + width, y, z )
- .texture( (u + tWidth) / BG_SIZE, v / BG_SIZE )
- .next();
- buffer.vertex( matrix, x, y, z )
- .texture( u / BG_SIZE, v / BG_SIZE )
- .next();
+ vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light );
+ vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light );
+ vertex( buffer, matrix, x + width, y, z, (u + tWidth) / BG_SIZE, v / BG_SIZE, light );
+ vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
}
- private static final class Type extends RenderPhase
+ private static void vertex( VertexConsumer buffer, Matrix4f matrix, float x, float y, float z, float u, float v, int light )
{
- static final RenderLayer TYPE = RenderLayer.of( "printout_background",
- VertexFormats.POSITION_TEXTURE,
- GL11.GL_QUADS,
- 1024,
- false,
- false,
- // useDelegate, needsSorting
- RenderLayer.MultiPhaseParameters.builder()
- .texture( new RenderPhase.Texture( BG, false, false ) ) // blur, minimap
- .alpha( ONE_TENTH_ALPHA )
- .lightmap( DISABLE_LIGHTMAP )
- .build( false ) );
-
- private Type( String name, Runnable setup, Runnable destroy )
- {
- super( name, setup, destroy );
- }
+ buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).texture( u, v ).light( light ).next();
}
}
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..cabc1c870
--- /dev/null
+++ b/src/main/java/dan200/computercraft/client/render/RenderTypes.java
@@ -0,0 +1,117 @@
+/*
+ * 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 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;
+ public static final RenderLayer PRINTOUT_TEXT = Types.PRINTOUT_TEXT;
+
+ public static final RenderLayer PRINTOUT_BACKGROUND = RenderLayer.getText( new Identifier( "computercraft", "textures/gui/printout.png" ) );
+
+ public static final RenderLayer POSITION_COLOR = Types.POSITION_COLOR;
+
+ @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 )
+ );
+
+ static final RenderLayer PRINTOUT_TEXT = RenderLayer.of(
+ "printout_text", VertexFormats.POSITION_COLOR_TEXTURE_LIGHT, GL_MODE, 1024,
+ false, false, // useDelegate, needsSorting
+ RenderLayer.MultiPhaseParameters.builder()
+ .texture( TERM_FONT_TEXTURE )
+ .shader( RenderPhase.TEXT_SHADER )
+ .lightmap( RenderPhase.ENABLE_LIGHTMAP )
+ .build( false )
+ );
+
+ static final RenderLayer POSITION_COLOR = RenderLayer.of(
+ "position_color", VertexFormats.POSITION_COLOR, VertexFormat.DrawMode.QUADS, 128,
+ false, false, // useDelegate, needsSorting
+ RenderLayer.MultiPhaseParameters.builder()
+ .shader( COLOR_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 bc7ce88d0..6c8c0ab74 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;
@@ -18,17 +20,11 @@ import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.client.gl.VertexBuffer;
import net.minecraft.client.render.*;
-import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
-import net.minecraft.client.util.GlAllocationUtils;
+import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
-import net.minecraft.util.math.AffineTransformation;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.math.Direction;
-import net.minecraft.util.math.Matrix4f;
-import net.minecraft.util.math.Vec3f;
+import net.minecraft.util.math.*;
import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL31;
@@ -36,8 +32,9 @@ import javax.annotation.Nonnull;
import java.nio.ByteBuffer;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
+import static net.minecraft.client.util.GlAllocationUtils.allocateByteBuffer;
-public class TileEntityMonitorRenderer extends BlockEntityRenderer
+public class TileEntityMonitorRenderer implements BlockEntityRenderer
{
/**
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between the monitor frame and contents.
@@ -47,11 +44,10 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
.getMatrix();
private static ByteBuffer tboContents;
- public TileEntityMonitorRenderer( BlockEntityRenderDispatcher rendererDispatcher )
+ public TileEntityMonitorRenderer( BlockEntityRendererFactory.Context context )
{
- super( rendererDispatcher );
+ // super( context );
}
-
@Override
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer,
int lightmapCoord, int overlayLight )
@@ -97,17 +93,6 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
- // Draw the background blocker
- FixedWidthFontRenderer.drawBlocker( transform.peek().getModel(),
- renderer,
- (float) -TileMonitor.RENDER_MARGIN,
- (float) TileMonitor.RENDER_MARGIN,
- (float) (xSize + 2 * TileMonitor.RENDER_MARGIN),
- (float) -(ySize + TileMonitor.RENDER_MARGIN * 2) );
-
- // Set the contents slightly off the surface to prevent z-fighting
- transform.translate( 0.0, 0.0, 0.001 );
-
// Draw the contents
Terminal terminal = originTerminal.getTerminal();
if( terminal != null )
@@ -122,23 +107,22 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
Matrix4f matrix = transform.peek().getModel();
- // Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate
- // render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick
- // for now.
- VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
- FixedWidthFontRenderer.TYPE.startDrawing();
-
- renderTerminal( matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) );
+ renderTerminal( renderer, matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) );
// We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is
// reasonable.
- FixedWidthFontRenderer.drawCursor( matrix, buffer, 0, 0, terminal, !originTerminal.isColour() );
-
- // To go along with sneaky hack above: make sure state changes are undone. I would have thought this would
- // happen automatically after these buffers are drawn, but chests will render weird around monitors without this.
- FixedWidthFontRenderer.TYPE.endDrawing();
+ FixedWidthFontRenderer.drawCursor( matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ), 0, 0, terminal, !originTerminal.isColour() );
transform.pop();
+
+ // Draw the background blocker
+ FixedWidthFontRenderer.drawBlocker(
+ transform.peek().getModel(), renderer,
+ -MARGIN, MARGIN,
+ (float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
+ );
+
+ renderer.getBuffer( RenderLayer.getSolid() );
}
else
{
@@ -154,7 +138,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
transform.pop();
}
- private static void renderTerminal( Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
+ private static void renderTerminal( VertexConsumerProvider renderer, Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
{
Terminal terminal = monitor.getTerminal();
@@ -169,10 +153,6 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
{
case TBO:
{
- if( !MonitorTextureBufferShader.use() )
- {
- return;
- }
int width = terminal.getWidth(), height = terminal.getHeight();
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
@@ -182,7 +162,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
int size = width * height * 3;
if( tboContents == null || tboContents.capacity() < size )
{
- tboContents = GlAllocationUtils.allocateByteBuffer( size );
+ tboContents = allocateByteBuffer( size );
}
ByteBuffer monitorBuffer = tboContents;
@@ -199,32 +179,27 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
}
monitorBuffer.flip();
- GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer );
- GlStateManager.bufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW );
- GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, 0 );
+ GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer );
+ GlStateManager._glBufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW );
+ GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );
}
// Nobody knows what they're doing!
- GlStateManager.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX );
+ int active = GlStateManager._getActiveTexture();
+ RenderSystem.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX );
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture );
- GlStateManager.activeTexture( GL13.GL_TEXTURE0 );
+ RenderSystem.activeTexture( active );
- MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() );
+ MonitorTextureBufferShader shader = RenderTypes.getMonitorTextureBufferShader();
+ shader.setupUniform( width, height, terminal.getPalette(), !monitor.isColour() );
- Tessellator tessellator = Tessellator.getInstance();
- BufferBuilder buffer = tessellator.getBuffer();
- buffer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION );
- buffer.vertex( -xMargin, -yMargin, 0 )
- .next();
- buffer.vertex( -xMargin, pixelHeight + yMargin, 0 )
- .next();
- buffer.vertex( pixelWidth + xMargin, -yMargin, 0 )
- .next();
- buffer.vertex( pixelWidth + xMargin, pixelHeight + yMargin, 0 )
- .next();
- tessellator.draw();
+ VertexConsumer buffer = renderer.getBuffer( RenderTypes.MONITOR_TBO );
+ tboVertex( buffer, matrix, -xMargin, -yMargin );
+ tboVertex( buffer, matrix, -xMargin, pixelHeight + yMargin );
+ tboVertex( buffer, matrix, pixelWidth + xMargin, -yMargin );
+ tboVertex( buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin );
- GlStateManager.useProgram( 0 );
+ renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
break;
}
@@ -234,7 +209,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder builder = tessellator.getBuffer();
- builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() );
+ builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.getDrawMode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.getVertexFormat() );
FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY,
builder,
0,
@@ -250,14 +225,23 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer
vbo.upload( builder );
}
- vbo.bind();
- FixedWidthFontRenderer.TYPE.getVertexFormat()
- .startDrawing( 0L );
- vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() );
- VertexBuffer.unbind();
- FixedWidthFontRenderer.TYPE.getVertexFormat()
- .endDrawing();
+ renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
+
+ RenderTypes.TERMINAL_WITHOUT_DEPTH.startDrawing();
+ vbo.setShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() );
break;
}
}
+
+ private static void tboVertex( VertexConsumer builder, Matrix4f matrix, float x, float y )
+ {
+ // We encode position in the UV, as that's not transformed by the matrix.
+ builder.vertex( matrix, x, y, 0 ).texture( x, y ).next();
+ }
+
+ @Override
+ public int getRenderDistance()
+ {
+ return ComputerCraft.monitorDistance;
+ }
}
diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java
index 67ad4c76a..70284b245 100644
--- a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java
@@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
-
package dan200.computercraft.client.render;
import dan200.computercraft.api.client.TransformedModel;
@@ -21,11 +20,13 @@ import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
+import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.util.math.Vec3f;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
@@ -37,7 +38,7 @@ import javax.annotation.Nonnull;
import java.util.List;
import java.util.Random;
-public class TileEntityTurtleRenderer extends BlockEntityRenderer
+public class TileEntityTurtleRenderer implements BlockEntityRenderer
{
private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" );
private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" );
@@ -46,9 +47,11 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer
private final Random random = new Random( 0 );
- public TileEntityTurtleRenderer( BlockEntityRenderDispatcher renderDispatcher )
+ BlockEntityRenderDispatcher renderer;
+
+ public TileEntityTurtleRenderer( BlockEntityRendererFactory.Context context )
{
- super( renderDispatcher );
+ renderer = context.getRenderDispatcher();
}
public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured )
@@ -76,6 +79,118 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer
return null;
}
+ @Override
+ public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider buffers,
+ int lightmapCoord, int overlayLight )
+ {
+ // Render the label
+ String label = turtle.createProxy()
+ .getLabel();
+ HitResult hit = renderer.crosshairTarget;
+ if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos()
+ .equals( ((BlockHitResult) hit).getBlockPos() ) )
+ {
+ MinecraftClient mc = MinecraftClient.getInstance();
+ TextRenderer font = mc.textRenderer;
+
+ transform.push();
+ transform.translate( 0.5, 1.2, 0.5 );
+ transform.multiply( mc.getEntityRenderDispatcher()
+ .getRotation() );
+ transform.scale( -0.025f, -0.025f, 0.025f );
+
+ Matrix4f matrix = transform.peek()
+ .getModel();
+ int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
+ float width = -font.getWidth( label ) / 2.0f;
+ font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, buffers, true, opacity, lightmapCoord );
+ font.draw( label, width, (float) 0, 0xffffffff, false, matrix, buffers, false, 0, lightmapCoord );
+
+ transform.pop();
+ }
+
+ transform.push();
+
+ // Setup the transform.
+ Vec3d offset = turtle.getRenderOffset( partialTicks );
+ float yaw = turtle.getRenderYaw( partialTicks );
+ transform.translate( offset.x, offset.y, offset.z );
+
+ transform.translate( 0.5f, 0.5f, 0.5f );
+ transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) );
+ if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
+ {
+ // Flip the model
+ transform.scale( 1.0f, -1.0f, 1.0f );
+ }
+ transform.translate( -0.5f, -0.5f, -0.5f );
+
+ // Render the turtle
+ int colour = turtle.getColour();
+ ComputerFamily family = turtle.getFamily();
+ Identifier overlay = turtle.getOverlay();
+
+ VertexConsumer buffer = buffers.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() );
+ renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
+
+ // Render the overlay
+ ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
+ if( overlayModel != null )
+ {
+ renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
+ }
+
+ // Render the upgrades
+ renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
+ renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
+
+ transform.pop();
+ }
+
+ private void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
+ TurtleSide side, float f )
+ {
+ ITurtleUpgrade upgrade = turtle.getUpgrade( side );
+ if( upgrade == null )
+ {
+ return;
+ }
+ transform.push();
+
+ float toolAngle = turtle.getToolRenderAngle( side, f );
+ transform.translate( 0.0f, 0.5f, 0.5f );
+ transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) );
+ transform.translate( 0.0f, -0.5f, -0.5f );
+
+ TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
+ model.push( transform );
+ renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
+ transform.pop();
+
+ transform.pop();
+ }
+
+ private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
+ ModelIdentifier modelLocation, int[] tints )
+ {
+ BakedModelManager modelManager = MinecraftClient.getInstance()
+ .getItemRenderer()
+ .getModels()
+ .getModelManager();
+ renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
+ }
+
+ private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
+ int[] tints )
+ {
+ random.setSeed( 0 );
+ renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
+ for( Direction facing : DirectionUtil.FACINGS )
+ {
+ renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints );
+ }
+ }
+
private static void renderQuads( @Nonnull MatrixStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight,
List quads, int[] tints )
{
@@ -107,117 +222,4 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer
true );
}
}
-
- @Override
- public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer,
- int lightmapCoord, int overlayLight )
- {
- // Render the label
- String label = turtle.createProxy()
- .getLabel();
- HitResult hit = dispatcher.crosshairTarget;
- if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos()
- .equals( ((BlockHitResult) hit).getBlockPos() ) )
- {
- MinecraftClient mc = MinecraftClient.getInstance();
- TextRenderer font = mc.textRenderer;
-
- transform.push();
- transform.translate( 0.5, 1.2, 0.5 );
- transform.multiply( mc.getEntityRenderDispatcher()
- .getRotation() );
- transform.scale( -0.025f, -0.025f, 0.025f );
-
- Matrix4f matrix = transform.peek()
- .getModel();
- int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
- float width = -font.getWidth( label ) / 2.0f;
- font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord );
- font.draw( label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord );
-
- transform.pop();
- }
-
- transform.push();
-
- // Setup the transform.
- Vec3d offset = turtle.getRenderOffset( partialTicks );
- float yaw = turtle.getRenderYaw( partialTicks );
- transform.translate( offset.x, offset.y, offset.z );
-
- transform.translate( 0.5f, 0.5f, 0.5f );
- transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) );
- if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
- {
- // Flip the model
- transform.scale( 1.0f, -1.0f, 1.0f );
- }
- transform.translate( -0.5f, -0.5f, -0.5f );
-
- // Render the turtle
- int colour = turtle.getColour();
- ComputerFamily family = turtle.getFamily();
- Identifier overlay = turtle.getOverlay();
-
- VertexConsumer buffer = renderer.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() );
- renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
-
- // Render the overlay
- ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
- if( overlayModel != null )
- {
- renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
- }
-
- // Render the upgrades
- renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
- renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
-
- transform.pop();
- }
-
- public static void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
- TurtleSide side, float f )
- {
- ITurtleUpgrade upgrade = turtle.getUpgrade( side );
- if( upgrade == null )
- {
- return;
- }
- transform.push();
-
- float toolAngle = turtle.getToolRenderAngle( side, f );
- transform.translate( 0.0f, 0.5f, 0.5f );
- transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) );
- transform.translate( 0.0f, -0.5f, -0.5f );
-
- TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
- model.push( transform );
- TileEntityTurtleRenderer.renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
- transform.pop();
-
- transform.pop();
- }
-
- public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
- ModelIdentifier modelLocation, int[] tints )
- {
- BakedModelManager modelManager = MinecraftClient.getInstance()
- .getItemRenderer()
- .getModels()
- .getModelManager();
- renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
- }
-
- public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
- int[] tints )
- {
- Random random = new Random();
- random.setSeed( 0 );
- renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
- for( Direction facing : DirectionUtil.FACINGS )
- {
- renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints );
- }
- }
}
diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java
index f6803af3e..bc7a6e46b 100644
--- a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java
+++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java
@@ -30,7 +30,7 @@ public class TurtleMultiModel implements BakedModel
private final TransformedModel leftUpgradeModel;
private final TransformedModel rightUpgradeModel;
private List generalQuads = null;
- private Map> faceQuads = new EnumMap<>( Direction.class );
+ private final Map> faceQuads = new EnumMap<>( Direction.class );
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel,
TransformedModel rightUpgradeModel )
@@ -120,9 +120,9 @@ public class TurtleMultiModel implements BakedModel
@Nonnull
@Override
@Deprecated
- public Sprite getSprite()
+ public Sprite getParticleSprite()
{
- return baseModel.getSprite();
+ return baseModel.getParticleSprite();
}
@Nonnull
diff --git a/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java b/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java
index 636cc4b4d..5b113f97a 100644
--- a/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java
+++ b/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java
@@ -6,25 +6,19 @@
package dan200.computercraft.client.render;
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
-import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.minecraft.client.render.VertexConsumerProvider;
-import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer;
+import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import javax.annotation.Nonnull;
public class TurtlePlayerRenderer extends EntityRenderer
-{
- public TurtlePlayerRenderer( EntityRenderDispatcher renderManager )
+{ //FIXME Make sure this isn't an issue. Context was EntityRenderDispatcher.
+ public TurtlePlayerRenderer( EntityRendererFactory.Context context )
{
- super( renderManager );
- }
-
- public TurtlePlayerRenderer( EntityRenderDispatcher entityRenderDispatcher, EntityRendererRegistry.Context context )
- {
- super( entityRenderDispatcher );
+ super( context );
}
@Override
diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java
index e632e4840..dc5ebc934 100644
--- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java
+++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java
@@ -3,7 +3,6 @@
* 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.Objects;
@@ -24,6 +23,7 @@ import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.ModelIdentifier;
+import net.minecraft.util.math.AffineTransformation;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
@@ -55,8 +55,60 @@ public class TurtleSmartItemModel implements BakedModel
.getModel() );
}
+ private static class TurtleModelCombination
+ {
+ final boolean colour;
+ final ITurtleUpgrade leftUpgrade;
+ final ITurtleUpgrade rightUpgrade;
+ final Identifier overlay;
+ final boolean christmas;
+ final boolean flip;
+
+ TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas,
+ boolean flip )
+ {
+ this.colour = colour;
+ this.leftUpgrade = leftUpgrade;
+ this.rightUpgrade = rightUpgrade;
+ this.overlay = overlay;
+ this.christmas = christmas;
+ this.flip = flip;
+ }
+
+ @Override
+ public boolean equals( Object other )
+ {
+ if( other == this )
+ {
+ return true;
+ }
+ if( !(other instanceof TurtleModelCombination otherCombo) )
+ {
+ return false;
+ }
+
+ return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
+ otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 0;
+ result = prime * result + (colour ? 1 : 0);
+ result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
+ result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
+ result = prime * result + (overlay != null ? overlay.hashCode() : 0);
+ result = prime * result + (christmas ? 1 : 0);
+ result = prime * result + (flip ? 1 : 0);
+ return result;
+ }
+ }
+
private final BakedModel familyModel;
private final BakedModel colourModel;
+
private final HashMap cachedModels = new HashMap<>();
private final ModelOverrideList overrides;
@@ -70,8 +122,7 @@ public class TurtleSmartItemModel implements BakedModel
{
@Nonnull
@Override
- public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world,
- @Nullable LivingEntity entity )
+ public BakedModel apply( BakedModel originalModel, ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity, int seed )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );
@@ -80,9 +131,7 @@ public class TurtleSmartItemModel implements BakedModel
Identifier overlay = turtle.getOverlay( stack );
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
String label = turtle.getLabel( stack );
- // TODO make upside down turtle items render properly (currently inivisible)
- //boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm"));
- boolean flip = false;
+ boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
BakedModel model = cachedModels.get( combo );
@@ -143,12 +192,18 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.isBuiltin();
}
- @Nonnull
@Override
@Deprecated
- public Sprite getSprite()
+ public Sprite getParticleSprite()
{
- return familyModel.getSprite();
+ return familyModel.getParticleSprite();
+ }
+
+ @Nonnull
+ @Override
+ public ModelOverrideList getOverrides()
+ {
+ return overrides;
}
@Nonnull
@@ -159,63 +214,4 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.getTransformation();
}
- @Nonnull
- @Override
- public ModelOverrideList getOverrides()
- {
- return overrides;
- }
-
- private static class TurtleModelCombination
- {
- final boolean colour;
- final ITurtleUpgrade leftUpgrade;
- final ITurtleUpgrade rightUpgrade;
- final Identifier overlay;
- final boolean christmas;
- final boolean flip;
-
- TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas,
- boolean flip )
- {
- this.colour = colour;
- this.leftUpgrade = leftUpgrade;
- this.rightUpgrade = rightUpgrade;
- this.overlay = overlay;
- this.christmas = christmas;
- this.flip = flip;
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 0;
- result = prime * result + (colour ? 1 : 0);
- result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
- result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
- result = prime * result + (overlay != null ? overlay.hashCode() : 0);
- result = prime * result + (christmas ? 1 : 0);
- result = prime * result + (flip ? 1 : 0);
- return result;
- }
-
- @Override
- public boolean equals( Object other )
- {
- if( other == this )
- {
- return true;
- }
- if( !(other instanceof TurtleModelCombination) )
- {
- return false;
- }
-
- TurtleModelCombination otherCombo = (TurtleModelCombination) other;
- return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
- otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
- }
- }
-
}
diff --git a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java
index 39c4a2ff3..77203c656 100644
--- a/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java
+++ b/src/main/java/dan200/computercraft/core/apis/ComputerAccess.java
@@ -5,6 +5,7 @@
*/
package dan200.computercraft.core.apis;
+import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.peripheral.IComputerAccess;
@@ -30,6 +31,10 @@ public abstract class ComputerAccess implements IComputerAccess
public void unmountAll()
{
FileSystem fileSystem = environment.getFileSystem();
+ if( !mounts.isEmpty() )
+ {
+ ComputerCraft.log.warn( "Peripheral or API called mount but did not call unmount for {}", mounts );
+ }
for( String mount : mounts )
{
fileSystem.unmount( mount );
diff --git a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java
index 25960c580..1f6ffe08a 100644
--- a/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java
+++ b/src/main/java/dan200/computercraft/core/apis/IAPIEnvironment.java
@@ -62,6 +62,7 @@ public interface IAPIEnvironment
@Nullable
IPeripheral getPeripheral( ComputerSide side );
+ @Nullable
String getLabel();
void setLabel( @Nullable String label );
diff --git a/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java b/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java
index fc1954354..e799c37cd 100644
--- a/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java
+++ b/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java
@@ -96,9 +96,8 @@ public abstract class HandleGeneric
protected static SeekableByteChannel asSeekable( Channel channel )
{
- if( !(channel instanceof SeekableByteChannel) ) return null;
+ if( !(channel instanceof SeekableByteChannel seekable) ) return null;
- SeekableByteChannel seekable = (SeekableByteChannel) channel;
try
{
seekable.position( seekable.position() );
diff --git a/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java b/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java
index cbbaf20c5..ffd895b0b 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/NetworkUtils.java
@@ -20,6 +20,8 @@ import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.timeout.ReadTimeoutException;
+import io.netty.handler.traffic.AbstractTrafficShapingHandler;
+import io.netty.handler.traffic.GlobalTrafficShapingHandler;
import javax.annotation.Nonnull;
import javax.net.ssl.SSLException;
@@ -28,9 +30,7 @@ import javax.net.ssl.TrustManagerFactory;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.KeyStore;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
@@ -38,10 +38,8 @@ import java.util.concurrent.TimeUnit;
*/
public final class NetworkUtils
{
- public static final ExecutorService EXECUTOR = new ThreadPoolExecutor(
- 4, Integer.MAX_VALUE,
- 60L, TimeUnit.SECONDS,
- new SynchronousQueue<>(),
+ public static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(
+ 4,
ThreadUtils.builder( "Network" )
.setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 )
.build()
@@ -52,6 +50,15 @@ public final class NetworkUtils
.build()
);
+ public static final AbstractTrafficShapingHandler SHAPING_HANDLER = new GlobalTrafficShapingHandler(
+ EXECUTOR, ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth
+ );
+
+ static
+ {
+ EXECUTOR.setKeepAliveTime( 60, TimeUnit.SECONDS );
+ }
+
private NetworkUtils()
{
}
@@ -107,8 +114,18 @@ public final class NetworkUtils
}
}
+ public static void reloadConfig()
+ {
+ SHAPING_HANDLER.configure( ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth );
+ }
+
+ public static void reset()
+ {
+ SHAPING_HANDLER.trafficCounter().resetCumulativeTime();
+ }
+
/**
- * Create a {@link InetSocketAddress} from a {@link URI}.
+ * Create a {@link InetSocketAddress} from a {@link java.net.URI}.
*
* Note, this may require a DNS lookup, and so should not be executed on the main CC thread.
*
@@ -184,7 +201,7 @@ public final class NetworkUtils
{
return "Timed out";
}
- else if( cause instanceof SSLHandshakeException || (cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException) )
+ else if( cause instanceof SSLHandshakeException || cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException )
{
return "Could not create a secure connection";
}
diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java
index 955e89d4d..13365b453 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java
@@ -75,7 +75,7 @@ public final class AddressRule
if( this.port != null && this.port != port ) return false;
return predicate.matches( domain )
|| predicate.matches( address )
- || (ipv4Address != null && predicate.matches( ipv4Address ));
+ || ipv4Address != null && predicate.matches( ipv4Address );
}
public static Options apply( Iterable extends AddressRule> rules, String domain, InetSocketAddress socketAddress )
diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java
index 2049575ff..74957b204 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java
@@ -167,6 +167,7 @@ public class HttpRequest extends Resource
}
ChannelPipeline p = ch.pipeline();
+ p.addLast( NetworkUtils.SHAPING_HANDLER );
if( sslContext != null )
{
p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java
index 4ef42ff44..003b3da5f 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java
@@ -100,9 +100,8 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler 0 )
{
@@ -137,9 +136,8 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler
protected void initChannel( SocketChannel ch )
{
ChannelPipeline p = ch.pipeline();
+ p.addLast( NetworkUtils.SHAPING_HANDLER );
if( sslContext != null )
{
p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
}
+ String subprotocol = headers.get( HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL );
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(
- uri, WebSocketVersion.V13, null, true, headers,
+ uri, WebSocketVersion.V13, subprotocol, true, headers,
options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage
);
p.addLast(
new HttpClientCodec(),
new HttpObjectAggregator( 8192 ),
- WebSocketClientCompressionHandler.INSTANCE,
+ WebsocketCompressionHandler.INSTANCE,
new WebsocketHandler( Websocket.this, handshaker, options )
);
}
diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketCompressionHandler.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketCompressionHandler.java
new file mode 100644
index 000000000..e29a87837
--- /dev/null
+++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketCompressionHandler.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.apis.http.websocket;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.handler.codec.compression.ZlibCodecFactory;
+import io.netty.handler.codec.http.websocketx.extensions.WebSocketClientExtensionHandler;
+import io.netty.handler.codec.http.websocketx.extensions.compression.DeflateFrameClientExtensionHandshaker;
+import io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateClientExtensionHandshaker;
+import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
+
+import static io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateServerExtensionHandshaker.MAX_WINDOW_SIZE;
+
+/**
+ * An alternative to {@link WebSocketClientCompressionHandler} which supports the {@literal client_no_context_takeover}
+ * extension. Makes CC slightly more flexible.
+ */
+@ChannelHandler.Sharable
+final class WebsocketCompressionHandler extends WebSocketClientExtensionHandler
+{
+ public static final WebsocketCompressionHandler INSTANCE = new WebsocketCompressionHandler();
+
+ private WebsocketCompressionHandler()
+ {
+ super(
+ new PerMessageDeflateClientExtensionHandshaker(
+ 6, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), MAX_WINDOW_SIZE,
+ true, false
+ ),
+ new DeflateFrameClientExtensionHandshaker( false ),
+ new DeflateFrameClientExtensionHandshaker( true )
+ );
+
+ }
+}
diff --git a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java
index 4916f5fbd..25001e19c 100644
--- a/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java
+++ b/src/main/java/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java
@@ -55,9 +55,8 @@ public class WebsocketHandler extends SimpleChannelInboundHandler