Repository: ModFest/glowcase
Pull request #100: Render block model option & text at custom distance
Author: login: dooji2
Created: 2025-04-11T21:59:21Z | Merged: 2025-04-13T18:00:49Z

This PR adds:
- an option to the Item Display block to render the block model (if available)
- only render text from TextBlock if in a certain distance


Diff:
diff --git a/src/main/java/dev/hephaestus/glowcase/block/entity/DisplayBlockEntity.java b/src/main/java/dev/hephaestus/glowcase/block/entity/DisplayBlockEntity.java
index df946930..2824d3ff 100644
--- a/src/main/java/dev/hephaestus/glowcase/block/entity/DisplayBlockEntity.java
+++ b/src/main/java/dev/hephaestus/glowcase/block/entity/DisplayBlockEntity.java
@@ -14,6 +14,7 @@ public abstract class DisplayBlockEntity extends GlowcaseBlockEntity {
 	private Vector3f scale = new Vector3f(1.0F);
 	private float pitch = 0.0F;
 	private float yaw = 0.0F;
+	private boolean renderAsBlock = true;
 
 	public DisplayBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
 		super(type, pos, state);
@@ -24,7 +25,8 @@ public DisplayBlockSettings toSettings() {
 			new Vector3f(offset.x(), offset.y(), offset.z()),
 			new Vector3f(scale.x(), scale.y(), scale.z()),
 			pitch,
-			yaw
+			yaw,
+			renderAsBlock
 		);
 	}
 
@@ -33,6 +35,7 @@ public void loadSettings(DisplayBlockSettings settings) {
 		this.scale.set(settings.scale().x(), settings.scale().y(), settings.scale().z());
 		this.pitch = settings.pitch();
 		this.yaw = settings.yaw();
+		this.renderAsBlock = settings.renderAsBlock();
 		markDirty();
 	}
 
@@ -91,4 +94,13 @@ public void setPitch(float pitch) {
 		this.pitch = pitch;
 		markDirty();
 	}
+
+	public boolean getRenderAsBlock() {
+		return renderAsBlock;
+	}
+
+	public void setRenderAsBlock(boolean renderAsBlock) {
+		this.renderAsBlock = renderAsBlock;
+		markDirty();
+	}
 }
diff --git a/src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java b/src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
index c3fe54b2..4f5866a3 100644
--- a/src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
+++ b/src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
@@ -26,6 +26,7 @@ public class TextBlockEntity extends GlowcaseBlockEntity {
 	public float scale = 1F;
 	public int color = 0xFFFFFF;
 	public boolean renderDirty = true;
+	public float viewDistance = -1.0F;
 
 	public TextBlockEntity(BlockPos pos, BlockState state) {
 		super(Glowcase.TEXT_BLOCK_ENTITY.get(), pos, state);
@@ -42,6 +43,7 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL
 		tag.putString("text_alignment", this.textAlignment.name());
 		tag.putString("z_offset", this.zOffset.name());
 		tag.putString("shadow_type", this.shadowType.name());
+		tag.putFloat("viewDistance", this.viewDistance);
 
 		NbtList lines = tag.getList("lines", 8);
 		for (var text : this.lines) {
@@ -62,6 +64,7 @@ protected void readNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLo
 		this.textAlignment = TextAlignment.valueOf(tag.getString("text_alignment"));
 		this.zOffset = ZOffset.valueOf(tag.getString("z_offset"));
 		this.shadowType = tag.contains("shadow_type") ? ShadowType.valueOf(tag.getString("shadow_type")) : ShadowType.DROP;
+		this.viewDistance = tag.contains("viewDistance") ? tag.getFloat("viewDistance") : -1.0F;
 
 		NbtList lines = tag.getList("lines", 8);
 
diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java
index b10f7a1e..f802ad96 100644
--- a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java
+++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java
@@ -2,12 +2,29 @@
 
 import dev.hephaestus.glowcase.block.entity.DisplayBlockEntity;
 import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock;
+import net.minecraft.client.gui.widget.CheckboxWidget;
+import net.minecraft.text.Text;
 
 public class ItemDisplayEditScreen extends DisplayBlockEditScreen {
+	private CheckboxWidget renderAsBlockWidget;
+
 	public ItemDisplayEditScreen(DisplayBlockEntity displayBlock) {
 		super(displayBlock);
 	}
 
+	@Override
+    public void init() {
+        super.init();
+
+        this.renderAsBlockWidget = CheckboxWidget.builder(Text.translatable("gui.glowcase.render_as_block"), this.client.textRenderer)
+			.checked(this.displayBlock.getRenderAsBlock())
+			.callback((checkbox, checked) -> this.displayBlock.setRenderAsBlock(checked))
+			.pos(20, 197)
+			.build();
+        
+        this.addDrawableChild(this.renderAsBlockWidget);
+    }
+
 	@Override
 	protected void editDisplayBlock() {
 		super.editDisplayBlock();
diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/TextBlockEditScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/TextBlockEditScreen.java
index aa3a390e..fd2198f8 100644
--- a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/TextBlockEditScreen.java
+++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/TextBlockEditScreen.java
@@ -1,5 +1,6 @@
 package dev.hephaestus.glowcase.client.gui.screen.ingame;
 
+import com.google.common.primitives.Floats;
 import com.mojang.blaze3d.platform.GlStateManager;
 import com.mojang.blaze3d.systems.RenderSystem;
 import dev.hephaestus.glowcase.block.entity.TextBlockEntity;
@@ -9,6 +10,7 @@
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.gui.DrawContext;
 import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.tooltip.Tooltip;
 import net.minecraft.client.gui.widget.ButtonWidget;
 import net.minecraft.client.gui.widget.TextFieldWidget;
 import net.minecraft.client.render.BufferBuilder;
@@ -38,6 +40,9 @@ public class TextBlockEditScreen extends TextEditorScreen {
 	private ButtonWidget zOffsetToggle;
 	private ButtonWidget shadowToggle;
 
+	private TextFieldWidget viewDistanceField;
+    private ButtonWidget viewDistanceHelpButton;
+
 	public TextBlockEditScreen(TextBlockEntity textBlockEntity) {
 		this.textBlockEntity = textBlockEntity;
 	}
@@ -125,6 +130,18 @@ public void init() {
 		this.colorPickerWidget = ColorPickerWidget.builder(this,216, 10).size(182, 104).build();
 		this.colorPickerWidget.toggle(false); //start deactivated
 
+        this.viewDistanceField = new TextFieldWidget(this.client.textRenderer, 7, 20 + innerPadding, 83 + innerPadding, 20, Text.empty());
+        this.viewDistanceField.setText(String.valueOf(this.textBlockEntity.viewDistance));
+        this.viewDistanceField.setChangedListener(s -> {
+			if (Floats.tryParse(s) instanceof Float parsed) {
+				this.textBlockEntity.viewDistance = parsed;
+			}
+        });
+
+        this.viewDistanceHelpButton = ButtonWidget.builder(Text.literal("?"), action -> { })
+			.dimensions(7 + (83 + innerPadding) + 5, 20 + innerPadding, 20, 20).build();
+        this.viewDistanceHelpButton.setTooltip(Tooltip.of(Text.translatable("gui.glowcase.screen.text_edit.view_distance")));
+
 		this.addDrawableChild(colorPickerWidget);
 		this.addDrawableChild(increaseSize);
 		this.addDrawableChild(decreaseSize);
@@ -133,6 +150,9 @@ public void init() {
 		this.addDrawableChild(this.zOffsetToggle);
 		this.addDrawableChild(this.colorEntryWidget);
 
+		this.addDrawableChild(this.viewDistanceField);
+		this.addDrawableChild(this.viewDistanceHelpButton);
+
 		addFormattingButtons(280, 20, innerPadding, 20, 2);
 	}
 
@@ -219,6 +239,8 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) {
 	public boolean charTyped(char chr, int keyCode) {
 		if (this.colorEntryWidget.isActive()) {
 			return this.colorEntryWidget.charTyped(chr, keyCode);
+		} else if (this.viewDistanceField.isActive()) {
+			return this.viewDistanceField.charTyped(chr, keyCode);
 		} else {
 			this.selectionManager.insert(chr);
 			return true;
@@ -234,8 +256,17 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
 			} else {
 				return this.colorEntryWidget.keyPressed(keyCode, scanCode, modifiers);
 			}
-		} if(this.colorPickerWidget.active && (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_ESCAPE)) {
-			if(keyCode == GLFW.GLFW_KEY_ENTER) {
+		} else if (this.viewDistanceField.isActive()) {
+			if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
+				this.close();
+				return true;
+			} else {
+				return this.viewDistanceField.keyPressed(keyCode, scanCode, modifiers);
+			}
+		}
+		
+		if (this.colorPickerWidget.active && (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_ESCAPE)) {
+			if (keyCode == GLFW.GLFW_KEY_ENTER) {
 				this.colorPickerWidget.confirmColor();
 			} else {
 				this.colorPickerWidget.cancel();
diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/ItemDisplayBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/ItemDisplayBlockEntityRenderer.java
index 4aaac6c5..2ae0d077 100644
--- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/ItemDisplayBlockEntityRenderer.java
+++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/ItemDisplayBlockEntityRenderer.java
@@ -11,6 +11,7 @@
 import net.minecraft.client.render.model.json.ModelTransformationMode;
 import net.minecraft.client.util.math.MatrixStack;
 import net.minecraft.entity.Entity;
+import net.minecraft.item.BlockItem;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.math.RotationAxis;
@@ -25,15 +26,35 @@ public void render(ItemDisplayBlockEntity entity, float tickDelta, MatrixStack m
 
 		if (camera == null) return;
 
+		boolean renderAsBlock = entity.getRenderAsBlock();
 		matrices.push();
-		matrices.translate(0.5D, 0D, 0.5D);
-		matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180.0F + entity.getYaw()));
-		matrices.translate(entity.getOffset().x(), entity.getOffset().y(), entity.getOffset().z());
-		matrices.translate(0, 0.5, 0);
-		matrices.scale(entity.getScale().x(), entity.getScale().y(), entity.getScale().z());
-		matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(entity.getPitch()));
-		context.getItemRenderer().renderItem(entity.getStack(), ModelTransformationMode.FIXED, light, OverlayTexture.DEFAULT_UV, matrices, vertexConsumers, entity.getWorld(), 0);
+		
+		if (renderAsBlock && entity.getStack().getItem() instanceof BlockItem blockItem) {
+			matrices.translate(0.5D, 0.5D, 0.5D);
 
+			matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180.0F + entity.getYaw()));
+			matrices.translate(entity.getOffset().x(), entity.getOffset().y(), entity.getOffset().z());
+
+			matrices.translate(-0.5D, -0.5D, -0.5D);
+
+			matrices.scale(entity.getScale().x(), entity.getScale().y(), entity.getScale().z());
+			matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(entity.getPitch()));
+
+			MinecraftClient.getInstance().getBlockRenderManager().renderBlockAsEntity(blockItem.getBlock().getDefaultState(), matrices, vertexConsumers, light, overlay);
+		} else {
+			matrices.translate(0.5D, 0D, 0.5D);
+
+			matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180.0F + entity.getYaw()));
+			matrices.translate(entity.getOffset().x(), entity.getOffset().y(), entity.getOffset().z());
+
+			matrices.translate(0D, 0.5D, 0D);
+
+			matrices.scale(entity.getScale().x(), entity.getScale().y(), entity.getScale().z());
+			matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(entity.getPitch()));
+
+			context.getItemRenderer().renderItem(entity.getStack(), ModelTransformationMode.FIXED, light, OverlayTexture.DEFAULT_UV, matrices, vertexConsumers, entity.getWorld(), 0);
+		}
+		
 		matrices.pop();
 
 		if (entity.matchesStack(ItemStack.EMPTY) || BlockEntityRenderUtil.shouldRenderPlaceholder(entity.getPos())) BlockEntityRenderUtil.renderCenteredPlaceholder(entity, ITEM_TEXTURE, 1.0F, RotationAxis.POSITIVE_Y.rotationDegrees(entity.getYaw()), matrices, vertexConsumers);
diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/TextBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/TextBlockEntityRenderer.java
index e94c8075..fec124c8 100644
--- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/TextBlockEntityRenderer.java
+++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/TextBlockEntityRenderer.java
@@ -4,6 +4,7 @@
 import dev.hephaestus.glowcase.block.entity.TextBlockEntity;
 import dev.hephaestus.glowcase.client.GlowcaseRenderLayers;
 import dev.hephaestus.glowcase.client.util.BlockEntityRenderUtil;
+import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.font.TextRenderer;
 import net.minecraft.client.font.TextRenderer.TextLayerType;
 import net.minecraft.client.render.LightmapTextureManager;
@@ -11,6 +12,7 @@
 import net.minecraft.client.render.VertexConsumerProvider;
 import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
 import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.entity.Entity;
 import net.minecraft.state.property.Properties;
 import net.minecraft.util.Identifier;
 import net.minecraft.util.math.RotationAxis;
@@ -18,6 +20,7 @@
 
 public class TextBlockEntityRenderer extends BakedBlockEntityRenderer<TextBlockEntity> {
 	public static Identifier ITEM_TEXTURE = Glowcase.id("textures/item/text_block.png");
+	private boolean wasOutOfRange = false;
 
 	public TextBlockEntityRenderer(BlockEntityRendererFactory.Context context) {
 		super(context);
@@ -30,16 +33,59 @@ public boolean shouldBake(TextBlockEntity entity) {
 
 	@Override
 	public void renderUnbaked(TextBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
+		Entity camera = MinecraftClient.getInstance().getCameraEntity();
+		if (camera != null && entity.viewDistance >= 0) {
+			double dx = camera.getX() - (entity.getPos().getX() + 0.5);
+			double dy = camera.getY() - (entity.getPos().getY() + 0.5);
+			double dz = camera.getZ() - (entity.getPos().getZ() + 0.5);
+
+			if ((dx * dx + dy * dy + dz * dz) > (entity.viewDistance * entity.viewDistance)) {
+				if (!wasOutOfRange) {
+                    entity.renderDirty = true;
+                    wasOutOfRange = true;
+                }
+			} else {
+				if (wasOutOfRange) {
+					entity.renderDirty = true;
+				}
+
+				wasOutOfRange = false;
+			}
+		}
+
 		if (entity.renderDirty) {
 			entity.renderDirty = false;
 			Manager.markForRebuild(entity.getPos());
 		}
+
 		if (entity.getWorld() == null || entity.getWorld().getBlockState(entity.getPos()).isAir()) return;
 		if (entity.lines.stream().allMatch(t -> t.getString().isBlank()) || BlockEntityRenderUtil.shouldRenderPlaceholder(entity.getPos())) BlockEntityRenderUtil.renderPlaceholderWithBlockRotation(entity, ITEM_TEXTURE, 1.0F, matrices, vertexConsumers, entity.zOffset == TextBlockEntity.ZOffset.CENTER ? 0F : entity.zOffset == TextBlockEntity.ZOffset.FRONT ? 0.4F : -0.4F);
 	}
 
 	@Override
 	public void renderBaked(TextBlockEntity entity, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
+		Entity camera = MinecraftClient.getInstance().getCameraEntity();
+		if (camera != null && entity.viewDistance >= 0) {
+			double dx = camera.getX() - (entity.getPos().getX() + 0.5);
+			double dy = camera.getY() - (entity.getPos().getY() + 0.5);
+			double dz = camera.getZ() - (entity.getPos().getZ() + 0.5);
+			
+			if ((dx * dx + dy * dy + dz * dz) > (entity.viewDistance * entity.viewDistance)) {
+				if (!wasOutOfRange) {
+                    entity.renderDirty = true;
+                    wasOutOfRange = true;
+                }
+
+				return;
+			} else {
+                if (wasOutOfRange) {
+					entity.renderDirty = true;
+				}
+
+				wasOutOfRange = false;
+            }
+		}
+		
 		matrices.push();
 		matrices.translate(0.5D, 0.5D, 0.5D);
 
diff --git a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditTextBlock.java b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditTextBlock.java
index ff0bc842..46228707 100644
--- a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditTextBlock.java
+++ b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditTextBlock.java
@@ -27,7 +27,7 @@ public record C2SEditTextBlock(BlockPos pos, TextBlockEntity.TextAlignment align
 	);
 
 	public static C2SEditTextBlock of(TextBlockEntity be) {
-		return new C2SEditTextBlock(be.getPos(), be.textAlignment, be.zOffset, be.shadowType, new TextBlockValues(be.scale, be.color, be.lines));
+		return new C2SEditTextBlock(be.getPos(), be.textAlignment, be.zOffset, be.shadowType, new TextBlockValues(be.scale, be.color, be.lines, be.viewDistance));
 	}
 
 	@Override
@@ -45,16 +45,18 @@ public void receive(ServerWorld world, BlockEntity blockEntity) {
 		be.color = this.values().color();
 		be.zOffset = this.offset();
 		be.shadowType = this.shadowType();
+		be.viewDistance = this.values().viewDistance();
 
 		be.markDirty();
 	}
 
 	// separated for tuple call
-	public record TextBlockValues(float scale, int color, List<Text> lines) {
+	public record TextBlockValues(float scale, int color, List<Text> lines, float viewDistance) {
 		public static final PacketCodec<RegistryByteBuf, TextBlockValues> PACKET_CODEC = PacketCodec.tuple(
 			PacketCodecs.FLOAT, TextBlockValues::scale,
 			PacketCodecs.INTEGER, TextBlockValues::color,
 			PacketCodecs.collection(ArrayList::new, TextCodecs.REGISTRY_PACKET_CODEC), TextBlockValues::lines,
+			PacketCodecs.FLOAT, TextBlockValues::viewDistance,
 			TextBlockValues::new
 		);
 	}
diff --git a/src/main/java/dev/hephaestus/glowcase/util/DisplayBlockSettings.java b/src/main/java/dev/hephaestus/glowcase/util/DisplayBlockSettings.java
index 5fb228c9..6f9eb2ad 100644
--- a/src/main/java/dev/hephaestus/glowcase/util/DisplayBlockSettings.java
+++ b/src/main/java/dev/hephaestus/glowcase/util/DisplayBlockSettings.java
@@ -8,12 +8,13 @@
 import net.minecraft.util.dynamic.Codecs;
 import org.joml.Vector3f;
 
-public record DisplayBlockSettings(Vector3f offset, Vector3f scale, float pitch, float yaw) {
+public record DisplayBlockSettings(Vector3f offset, Vector3f scale, float pitch, float yaw, boolean renderAsBlock) {
 	public static final Codec<DisplayBlockSettings> CODEC = RecordCodecBuilder.create(instance -> instance.group(
 		Codecs.VECTOR_3F.lenientOptionalFieldOf("offset", new Vector3f()).forGetter(DisplayBlockSettings::offset),
 		Codecs.VECTOR_3F.lenientOptionalFieldOf("scale", new Vector3f(1.0F)).forGetter(DisplayBlockSettings::scale),
 		Codec.FLOAT.lenientOptionalFieldOf("pitch", 0F).forGetter(DisplayBlockSettings::pitch),
-		Codec.FLOAT.lenientOptionalFieldOf("yaw", 0F).forGetter(DisplayBlockSettings::yaw)
+		Codec.FLOAT.lenientOptionalFieldOf("yaw", 0F).forGetter(DisplayBlockSettings::yaw),
+		Codec.BOOL.lenientOptionalFieldOf("renderAsBlock", true).forGetter(DisplayBlockSettings::renderAsBlock)
 	).apply(instance, DisplayBlockSettings::new));
 
 	public static final PacketCodec<ByteBuf, DisplayBlockSettings> PACKET_CODEC = PacketCodec.tuple(
@@ -21,14 +22,15 @@ public record DisplayBlockSettings(Vector3f offset, Vector3f scale, float pitch,
 		PacketCodecs.VECTOR3F, DisplayBlockSettings::scale,
 		PacketCodecs.FLOAT, DisplayBlockSettings::pitch,
 		PacketCodecs.FLOAT, DisplayBlockSettings::yaw,
+		PacketCodecs.BOOL, DisplayBlockSettings::renderAsBlock,
 		DisplayBlockSettings::new
 	);
 
 	public DisplayBlockSettings() {
-		this(new Vector3f(), new Vector3f(1.0F), 0F, 0F);
+		this(new Vector3f(), new Vector3f(1.0F), 0F, 0F, true);
 	}
 
 	public boolean isEmpty() {
-		return offset.equals(new Vector3f()) && scale.equals(new Vector3f(1.0F)) && pitch == 0F && yaw == 0F;
+		return offset.equals(new Vector3f()) && scale.equals(new Vector3f(1.0F)) && pitch == 0F && yaw == 0F && renderAsBlock;
 	}
 }
diff --git a/src/main/resources/assets/glowcase/lang/en_us.json b/src/main/resources/assets/glowcase/lang/en_us.json
index c7f4591e..b8e64f8f 100644
--- a/src/main/resources/assets/glowcase/lang/en_us.json
+++ b/src/main/resources/assets/glowcase/lang/en_us.json
@@ -58,6 +58,7 @@
 	"gui.glowcase.x": "X",
 	"gui.glowcase.y": "Y",
 	"gui.glowcase.z": "Z",
+	"gui.glowcase.render_as_block": "Render as block model (if available)",
 	"gui.glowcase.front": "Front",
 	"gui.glowcase.center": "Center",
 	"gui.glowcase.back": "Back",
@@ -87,6 +88,7 @@
 	"gui.glowcase.screen.eink": "Use E-Ink technology",
 	"gui.glowcase.screen.backface": "Render backface",
 	"gui.glowcase.screen.sprite_edit.sprite": "Can be one of the following options:\n\n- The name of a built-in sprite, such as 'arrow'.\n- The ID of an item, such as 'minecraft:iron_sword'.\n- The namespaced path to a texture, such as 'minecraft:textures/item/iron_sword.png'.\n- A mod's icon, by using the mod ID in the special 'mod' namespace, such as 'mod:glowcase'.",
+	"gui.glowcase.screen.text_edit.view_distance": "View Distance\n(-1 is unlimited)\nText is rendered only when the camera is within this radius distance of the block.",
 	"gui.glowcase.screen.stretch": "Stretch image to fill the screen",
 	"gui.glowcase.updated_linked_screen": "Screen Tablet now linked to Screen at [%s].",
 	"gui.glowcase.linking_denied": "No permission to link to a screen.",


Reviews:
user: login: TheEpicBlock
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-13T14:27:25Z
user: login: dooji2
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-13T14:32:40Z
user: login: dooji2
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-13T14:32:48Z
user: login: TheEpicBlock
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-13T14:33:57Z
user: login: dooji2
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-13T14:48:58Z
user: login: TheEpicBlock
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-13T14:50:11Z

Review comments:
diff_hunk: @@ -42,6 +44,9 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL
 		tag.putString("text_alignment", this.textAlignment.name());
 		tag.putString("z_offset", this.zOffset.name());
 		tag.putString("shadow_type", this.shadowType.name());
+		tag.putFloat("viewDistance", this.viewDistance);
+
+		tag.putBoolean("wasOutOfRange", this.wasOutOfRange);
path: src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
user: login: TheEpicBlock
body: Being out of range is a per-client thing. It doesn't make much sense to store this inside the block entity
created_at: 2025-04-13T14:24:05Z
author_association: MEMBER
diff_hunk: @@ -2,12 +2,29 @@
 
 import dev.hephaestus.glowcase.block.entity.DisplayBlockEntity;
 import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock;
+import net.minecraft.client.gui.widget.CheckboxWidget;
+import net.minecraft.text.Text;
 
 public class ItemDisplayEditScreen extends DisplayBlockEditScreen {
+	private CheckboxWidget renderAsBlockWidget;
+
 	public ItemDisplayEditScreen(DisplayBlockEntity displayBlock) {
 		super(displayBlock);
 	}
 
+	@Override
+    public void init() {
+        super.init();
+
+        this.renderAsBlockWidget = CheckboxWidget.builder(Text.translatable("gui.glowcase.render_as_block"), this.client.textRenderer)
path: src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java
user: login: TheEpicBlock
body: This isn't something that blocks this pr, but I do have to wonder at what point it's just easier to use minecraft's display entities for this kind of stuff. Especially since axiom provides such a nice gui, it just seems useless to keep replicating display entity functionality. I guess it's still worth it for the improved (baked) performance
created_at: 2025-04-13T14:26:32Z
author_association: MEMBER
diff_hunk: @@ -87,6 +88,7 @@
 	"gui.glowcase.screen.eink": "Use E-Ink technology",
 	"gui.glowcase.screen.backface": "Render backface",
 	"gui.glowcase.screen.sprite_edit.sprite": "Can be one of the following options:\n\n- The name of a built-in sprite, such as 'arrow'.\n- The ID of an item, such as 'minecraft:iron_sword'.\n- The namespaced path to a texture, such as 'minecraft:textures/item/iron_sword.png'.\n- A mod's icon, by using the mod ID in the special 'mod' namespace, such as 'mod:glowcase'.",
+	"gui.glowcase.screen.text_edit.view_distance": "View Distance\n(Default is 32)\nText is rendered only when the camera is within this radius distance of the block.",
path: src/main/resources/assets/glowcase/lang/en_us.json
user: login: TheEpicBlock
body: View distance should be unlimited by default
created_at: 2025-04-13T14:27:14Z
author_association: MEMBER
diff_hunk: @@ -2,12 +2,29 @@
 
 import dev.hephaestus.glowcase.block.entity.DisplayBlockEntity;
 import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock;
+import net.minecraft.client.gui.widget.CheckboxWidget;
+import net.minecraft.text.Text;
 
 public class ItemDisplayEditScreen extends DisplayBlockEditScreen {
+	private CheckboxWidget renderAsBlockWidget;
+
 	public ItemDisplayEditScreen(DisplayBlockEntity displayBlock) {
 		super(displayBlock);
 	}
 
+	@Override
+    public void init() {
+        super.init();
+
+        this.renderAsBlockWidget = CheckboxWidget.builder(Text.translatable("gui.glowcase.render_as_block"), this.client.textRenderer)
path: src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java
user: login: dooji2
body: hmm true, I mostly added this because lily suggested it, although I think I might make use of it too ^^; I don't have much knowledge on the entity display so my bad, kind of wanted to design a blockbench-looking thing with just item display stuff and I'd make use of it that way
created_at: 2025-04-13T14:32:40Z
author_association: NONE
diff_hunk: @@ -42,6 +44,9 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL
 		tag.putString("text_alignment", this.textAlignment.name());
 		tag.putString("z_offset", this.zOffset.name());
 		tag.putString("shadow_type", this.shadowType.name());
+		tag.putFloat("viewDistance", this.viewDistance);
+
+		tag.putBoolean("wasOutOfRange", this.wasOutOfRange);
path: src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
user: login: dooji2
body: that's true I should probably rethink that lmao
created_at: 2025-04-13T14:32:48Z
author_association: NONE
diff_hunk: @@ -2,12 +2,29 @@
 
 import dev.hephaestus.glowcase.block.entity.DisplayBlockEntity;
 import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock;
+import net.minecraft.client.gui.widget.CheckboxWidget;
+import net.minecraft.text.Text;
 
 public class ItemDisplayEditScreen extends DisplayBlockEditScreen {
+	private CheckboxWidget renderAsBlockWidget;
+
 	public ItemDisplayEditScreen(DisplayBlockEntity displayBlock) {
 		super(displayBlock);
 	}
 
+	@Override
+    public void init() {
+        super.init();
+
+        this.renderAsBlockWidget = CheckboxWidget.builder(Text.translatable("gui.glowcase.render_as_block"), this.client.textRenderer)
path: src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/ItemDisplayEditScreen.java
user: login: TheEpicBlock
body: Yeah this is just a bit of random incomplete rambling on my part
created_at: 2025-04-13T14:33:57Z
author_association: MEMBER
diff_hunk: @@ -42,6 +44,9 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL
 		tag.putString("text_alignment", this.textAlignment.name());
 		tag.putString("z_offset", this.zOffset.name());
 		tag.putString("shadow_type", this.shadowType.name());
+		tag.putFloat("viewDistance", this.viewDistance);
+
+		tag.putBoolean("wasOutOfRange", this.wasOutOfRange);
path: src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
user: login: dooji2
body: can i just keep it in the renderer as a local var? or is the rendered shared across all textblock instances? I moved it to the renderer and it seems to work fine. The main reason I want a wasOutOfRange is so I only rebake once when you're in range and once when you're out, not like every frame xd
created_at: 2025-04-13T14:48:58Z
author_association: NONE
diff_hunk: @@ -42,6 +44,9 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL
 		tag.putString("text_alignment", this.textAlignment.name());
 		tag.putString("z_offset", this.zOffset.name());
 		tag.putString("shadow_type", this.shadowType.name());
+		tag.putFloat("viewDistance", this.viewDistance);
+
+		tag.putBoolean("wasOutOfRange", this.wasOutOfRange);
path: src/main/java/dev/hephaestus/glowcase/block/entity/TextBlockEntity.java
user: login: TheEpicBlock
body: Yeah, I bet that the renderer is the correct location for it. There's one instance per BE
created_at: 2025-04-13T14:50:11Z
author_association: MEMBER

PR comments:
user: login: dooji2
created_at: 2025-04-11T21:59:52Z
body: I need to add the options to the edit screens, will do it tomorrow - and maybe some other stuff
author_association: NONE
user: login: dooji2
created_at: 2025-04-12T17:47:15Z
body: NOTE: the position for the new checkbox is made in mind with the #98 pr
author_association: NONE
user: login: dooji2
created_at: 2025-04-12T21:24:30Z
body: ![2025-04-13_00 24 06](https://github.com/user-attachments/assets/28cb4da8-f0ca-4ada-b433-fba4dc10f95c)

author_association: NONE
user: login: dooji2
created_at: 2025-04-12T21:24:56Z
body: ![2025-04-13_00 24 44](https://github.com/user-attachments/assets/c2100b22-57c6-4fff-9af2-83bc02523e7c)

author_association: NONE