From 480d9599ab9284d65a6a0db4de0e312ee6bd86c7 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:35:53 -0400 Subject: [PATCH 01/12] Added the popup block! --- .../dev/hephaestus/glowcase/Glowcase.java | 7 + .../glowcase/GlowcaseCommonProxy.java | 8 + .../glowcase/GlowcaseNetworking.java | 3 + .../hephaestus/glowcase/block/PopupBlock.java | 72 +++++ .../block/entity/PopupBlockEntity.java | 134 ++++++++ .../glowcase/client/GlowcaseClient.java | 2 + .../glowcase/client/GlowcaseClientProxy.java | 21 +- .../screen/ingame/PopupBlockEditScreen.java | 306 ++++++++++++++++++ .../screen/ingame/PopupBlockViewScreen.java | 52 +++ .../entity/PopupBlockEntityRenderer.java | 38 +++ .../glowcase/packet/C2SEditPopupBlock.java | 49 +++ .../glowcase/blockstates/popup_block.json | 7 + .../resources/assets/glowcase/lang/en_us.json | 1 + .../glowcase/models/block/popup_block.json | 5 + .../glowcase/models/item/popup_block.json | 49 +++ .../glowcase/textures/item/popup_block.png | Bin 0 -> 5954 bytes .../data/glowcase/tags/item/items.json | 3 +- 17 files changed, 753 insertions(+), 4 deletions(-) create mode 100644 src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java create mode 100644 src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java create mode 100644 src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java create mode 100644 src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockViewScreen.java create mode 100644 src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java create mode 100644 src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java create mode 100644 src/main/resources/assets/glowcase/blockstates/popup_block.json create mode 100644 src/main/resources/assets/glowcase/models/block/popup_block.json create mode 100644 src/main/resources/assets/glowcase/models/item/popup_block.json create mode 100644 src/main/resources/assets/glowcase/textures/item/popup_block.png diff --git a/src/main/java/dev/hephaestus/glowcase/Glowcase.java b/src/main/java/dev/hephaestus/glowcase/Glowcase.java index 84476b4..286d3c2 100644 --- a/src/main/java/dev/hephaestus/glowcase/Glowcase.java +++ b/src/main/java/dev/hephaestus/glowcase/Glowcase.java @@ -4,9 +4,11 @@ import com.google.common.base.Suppliers; import dev.hephaestus.glowcase.block.HyperlinkBlock; import dev.hephaestus.glowcase.block.ItemDisplayBlock; +import dev.hephaestus.glowcase.block.PopupBlock; import dev.hephaestus.glowcase.block.TextBlock; import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.ItemDisplayBlockEntity; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; import dev.hephaestus.glowcase.block.entity.TextBlockEntity; import dev.hephaestus.glowcase.compat.PolydexCompatibility; import net.fabricmc.api.ModInitializer; @@ -46,6 +48,10 @@ public class Glowcase implements ModInitializer { public static final Supplier TEXT_BLOCK_ITEM = registerItem("text_block", () -> new BlockItem(TEXT_BLOCK.get(), new Item.Settings())); public static final Supplier> TEXT_BLOCK_ENTITY = registerBlockEntity("text_block", () -> BlockEntityType.Builder.create(TextBlockEntity::new, TEXT_BLOCK.get()).build(null)); + public static final Supplier POPUP_BLOCK = registerBlock("popup_block", PopupBlock::new); + public static final Supplier POPUP_BLOCK_ITEM = registerItem("popup_block", () -> new BlockItem(POPUP_BLOCK.get(), new Item.Settings())); + public static final Supplier> POPUP_BLOCK_ENTITY = registerBlockEntity("popup_block", () -> BlockEntityType.Builder.create(PopupBlockEntity::new, POPUP_BLOCK.get()).build(null)); + public static final Supplier ITEM_GROUP = registerItemGroup("items", () -> FabricItemGroup.builder() .displayName(Text.translatable("itemGroup.glowcase.items")) .icon(() -> new ItemStack(Items.GLOWSTONE)) @@ -53,6 +59,7 @@ public class Glowcase implements ModInitializer { entries.add(HYPERLINK_BLOCK_ITEM.get()); entries.add(ITEM_DISPLAY_BLOCK_ITEM.get()); entries.add(TEXT_BLOCK_ITEM.get()); + entries.add(POPUP_BLOCK_ITEM.get()); }) .build() ); diff --git a/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java b/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java index 65ee6c0..bc436a6 100644 --- a/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java +++ b/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java @@ -18,4 +18,12 @@ public void openItemDisplayBlockEditScreen(BlockPos pos) { public void openTextBlockEditScreen(BlockPos pos) { //No-op } + + public void openPopupBlockEditScreen(BlockPos pos) { + //No-op + } + + public void openPopupBlockViewScreen(BlockPos pos) { + //No-op + } } diff --git a/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java b/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java index 8b932a4..6c7eab2 100644 --- a/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java +++ b/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java @@ -2,6 +2,7 @@ import dev.hephaestus.glowcase.packet.C2SEditHyperlinkBlock; import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock; +import dev.hephaestus.glowcase.packet.C2SEditPopupBlock; import dev.hephaestus.glowcase.packet.C2SEditTextBlock; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; @@ -11,9 +12,11 @@ public static void init() { PayloadTypeRegistry.playC2S().register(C2SEditHyperlinkBlock.ID, C2SEditHyperlinkBlock.PACKET_CODEC); PayloadTypeRegistry.playC2S().register(C2SEditItemDisplayBlock.ID, C2SEditItemDisplayBlock.PACKET_CODEC); PayloadTypeRegistry.playC2S().register(C2SEditTextBlock.ID, C2SEditTextBlock.PACKET_CODEC); + PayloadTypeRegistry.playC2S().register(C2SEditPopupBlock.ID, C2SEditPopupBlock.PACKET_CODEC); ServerPlayNetworking.registerGlobalReceiver(C2SEditHyperlinkBlock.ID, C2SEditHyperlinkBlock::receive); ServerPlayNetworking.registerGlobalReceiver(C2SEditItemDisplayBlock.ID, C2SEditItemDisplayBlock::receive); ServerPlayNetworking.registerGlobalReceiver(C2SEditTextBlock.ID, C2SEditTextBlock::receive); + ServerPlayNetworking.registerGlobalReceiver(C2SEditPopupBlock.ID, C2SEditPopupBlock::receive); } } diff --git a/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java b/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java new file mode 100644 index 0000000..3a9812d --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java @@ -0,0 +1,72 @@ +package dev.hephaestus.glowcase.block; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemActionResult; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +public class PopupBlock extends GlowcaseBlock implements BlockEntityProvider { + private static final VoxelShape OUTLINE = VoxelShapes.cuboid(0.25, 0.25, 0.25, 0.75, 0.75, 0.75); + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return OUTLINE; + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new PopupBlockEntity(pos, state); + } + + @Override + public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + if (world.isClient && placer instanceof PlayerEntity player && canEditGlowcase(player, pos)) { + //load any ctrl-picked NBT clientside + NbtComponent blockEntityTag = stack.get(DataComponentTypes.BLOCK_ENTITY_DATA); + if (blockEntityTag != null && world.getBlockEntity(pos) instanceof PopupBlockEntity be) { + blockEntityTag.applyToBlockEntity(be, world.getRegistryManager()); + } + + Glowcase.proxy.openPopupBlockEditScreen(pos); + } + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if (!(world.getBlockEntity(pos) instanceof PopupBlockEntity be)) return ActionResult.CONSUME; + if (world.isClient) { + Glowcase.proxy.openPopupBlockViewScreen(pos); + } + return ActionResult.SUCCESS; + } + + @Override + protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!(world.getBlockEntity(pos) instanceof PopupBlockEntity)) return ItemActionResult.CONSUME; + if (player.getStackInHand(hand).isIn(Glowcase.ITEM_TAG) && canEditGlowcase(player, pos)) { + if (world.isClient) { + Glowcase.proxy.openPopupBlockEditScreen(pos); + } + return ItemActionResult.SUCCESS; + } + return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java b/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java new file mode 100644 index 0000000..33ca336 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java @@ -0,0 +1,134 @@ +package dev.hephaestus.glowcase.block.entity; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.client.render.block.entity.BakedBlockEntityRenderer; +import eu.pb4.placeholders.api.ParserContext; +import eu.pb4.placeholders.api.parsers.NodeParser; +import eu.pb4.placeholders.api.parsers.TagParser; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.registry.RegistryWrapper; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class PopupBlockEntity extends BlockEntity { + public static final NodeParser PARSER = TagParser.DEFAULT; + public List lines = new ArrayList<>(); + public TextBlockEntity.TextAlignment textAlignment = TextBlockEntity.TextAlignment.CENTER; + public int color = 0xFFFFFF; + public boolean renderDirty = true; + + public PopupBlockEntity(BlockPos pos, BlockState state) { + super(Glowcase.POPUP_BLOCK_ENTITY.get(), pos, state); + lines.add(Text.empty()); + } + + @Override + protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { + super.writeNbt(tag, registryLookup); + + tag.putInt("color", this.color); + + tag.putString("text_alignment", this.textAlignment.name()); + + NbtList lines = tag.getList("lines", 8); + for (var text : this.lines) { + lines.add(NbtString.of(Text.Serialization.toJsonString(text, registryLookup))); + } + + tag.put("lines", lines); + } + + @Override + protected void readNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { + super.readNbt(tag, registryLookup); + + this.lines = new ArrayList<>(); + this.color = tag.getInt("color"); + + this.textAlignment = TextBlockEntity.TextAlignment.valueOf(tag.getString("text_alignment")); + + NbtList lines = tag.getList("lines", 8); + + for (NbtElement line : lines) { + if (line.getType() == NbtElement.END_TYPE) break; + this.lines.add(Text.Serialization.fromJson(line.asString(), registryLookup)); + } + + this.renderDirty = true; + } + + public String getRawLine(int i) { + var line = this.lines.get(i); + + if (line.getStyle() == null) { + return line.getString(); + } + + var insert = line.getStyle().getInsertion(); + + if (insert == null) { + return line.getString(); + } + return insert; + } + + public void addRawLine(int i, String string) { + var parsed = PARSER.parseText(string, ParserContext.of()); + + if (parsed.getString().equals(string)) { + this.lines.add(i, Text.literal(string)); + } else { + this.lines.add(i, Text.empty().append(parsed).setStyle(Style.EMPTY.withInsertion(string))); + } + } + + public void setRawLine(int i, String string) { + var parsed = PARSER.parseText(string, ParserContext.of()); + + if (parsed.getString().equals(string)) { + this.lines.set(i, Text.literal(string)); + } else { + this.lines.set(i, Text.empty().append(parsed).setStyle(Style.EMPTY.withInsertion(string))); + } + } + + @SuppressWarnings({"MethodCallSideOnly", "VariableUseSideOnly"}) + @Override + public void markRemoved() { + if (world != null && world.isClient) { + BakedBlockEntityRenderer.Manager.markForRebuild(getPos()); + } + super.markRemoved(); + } + + // standard blockentity boilerplate + + public void dispatch() { + if (world instanceof ServerWorld sworld) sworld.getChunkManager().markForUpdate(pos); + } + + @Override + public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup registryLookup) { + return createNbt(registryLookup); + } + + @Nullable + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.create(this); + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java index 02b4a8e..9332af1 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java +++ b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java @@ -5,6 +5,7 @@ import dev.hephaestus.glowcase.client.render.block.entity.HyperlinkBlockEntityRenderer; import dev.hephaestus.glowcase.client.render.block.entity.ItemDisplayBlockEntityRenderer; import dev.hephaestus.glowcase.client.render.block.entity.TextBlockEntityRenderer; +import dev.hephaestus.glowcase.client.render.block.entity.PopupBlockEntityRenderer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.rendering.v1.InvalidateRenderStateCallback; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; @@ -18,6 +19,7 @@ public void onInitializeClient() { BlockEntityRendererFactories.register(Glowcase.TEXT_BLOCK_ENTITY.get(), TextBlockEntityRenderer::new); BlockEntityRendererFactories.register(Glowcase.HYPERLINK_BLOCK_ENTITY.get(), HyperlinkBlockEntityRenderer::new); BlockEntityRendererFactories.register(Glowcase.ITEM_DISPLAY_BLOCK_ENTITY.get(), ItemDisplayBlockEntityRenderer::new); + BlockEntityRendererFactories.register(Glowcase.POPUP_BLOCK_ENTITY.get(), PopupBlockEntityRenderer::new); WorldRenderEvents.AFTER_TRANSLUCENT.register(BakedBlockEntityRenderer.Manager::render); InvalidateRenderStateCallback.EVENT.register(BakedBlockEntityRenderer.Manager::reset); diff --git a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java index 2cf548d..1157df2 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java +++ b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java @@ -3,10 +3,9 @@ import dev.hephaestus.glowcase.GlowcaseCommonProxy; import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.ItemDisplayBlockEntity; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; import dev.hephaestus.glowcase.block.entity.TextBlockEntity; -import dev.hephaestus.glowcase.client.gui.screen.ingame.HyperlinkBlockEditScreen; -import dev.hephaestus.glowcase.client.gui.screen.ingame.ItemDisplayBlockEditScreen; -import dev.hephaestus.glowcase.client.gui.screen.ingame.TextBlockEditScreen; +import dev.hephaestus.glowcase.client.gui.screen.ingame.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ConfirmLinkScreen; import net.minecraft.util.math.BlockPos; @@ -40,4 +39,20 @@ public void openTextBlockEditScreen(BlockPos pos) { MinecraftClient.getInstance().setScreen(new TextBlockEditScreen(be)); } } + + @Override + public void openPopupBlockEditScreen(BlockPos pos) { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.world != null && client.world.getBlockEntity(pos) instanceof PopupBlockEntity be) { + MinecraftClient.getInstance().setScreen(new PopupBlockEditScreen(be)); + } + } + + @Override + public void openPopupBlockViewScreen(BlockPos pos) { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.world != null && client.world.getBlockEntity(pos) instanceof PopupBlockEntity be) { + MinecraftClient.getInstance().setScreen(new PopupBlockViewScreen(be)); + } + } } diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java new file mode 100644 index 0000000..928ffae --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java @@ -0,0 +1,306 @@ +package dev.hephaestus.glowcase.client.gui.screen.ingame; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; +import dev.hephaestus.glowcase.block.entity.TextBlockEntity; +import dev.hephaestus.glowcase.packet.C2SEditPopupBlock; +import dev.hephaestus.glowcase.packet.C2SEditTextBlock; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.render.*; +import net.minecraft.client.util.SelectionManager; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; + +//TODO: multi-character selection at some point? it may be a bit complex but it'd be nice +public class PopupBlockEditScreen extends GlowcaseScreen { + private final PopupBlockEntity popupBlockEntity; + + private SelectionManager selectionManager; + private int currentRow; + private long ticksSinceOpened = 0; + private ButtonWidget changeAlignment; + private TextFieldWidget colorEntryWidget; + + public PopupBlockEditScreen(PopupBlockEntity popupBlockEntity) { + this.popupBlockEntity = popupBlockEntity; + } + + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + renderDarkening(context); + } + + @Override + public void init() { + super.init(); + + int innerPadding = width / 100; + + this.selectionManager = new SelectionManager( + () -> this.popupBlockEntity.getRawLine(this.currentRow), + (string) -> { + popupBlockEntity.setRawLine(this.currentRow, string); + this.popupBlockEntity.renderDirty = true; + }, + SelectionManager.makeClipboardGetter(this.client), + SelectionManager.makeClipboardSetter(this.client), + (string) -> true); + + this.changeAlignment = ButtonWidget.builder(Text.stringifiedTranslatable("gui.glowcase.alignment", this.popupBlockEntity.textAlignment), action -> { + switch (popupBlockEntity.textAlignment) { + case LEFT -> popupBlockEntity.textAlignment = TextBlockEntity.TextAlignment.CENTER; + case CENTER -> popupBlockEntity.textAlignment = TextBlockEntity.TextAlignment.RIGHT; + case RIGHT -> popupBlockEntity.textAlignment = TextBlockEntity.TextAlignment.LEFT; + } + this.popupBlockEntity.renderDirty = true; + + this.changeAlignment.setMessage(Text.stringifiedTranslatable("gui.glowcase.alignment", this.popupBlockEntity.textAlignment)); + }).dimensions(120 + innerPadding, 0, 160, 20).build(); + + this.colorEntryWidget = new TextFieldWidget(this.client.textRenderer, 280 + innerPadding * 2, 0, 50, 20, Text.empty()); + this.colorEntryWidget.setText("#" + Integer.toHexString(this.popupBlockEntity.color & 0x00FFFFFF)); + this.colorEntryWidget.setChangedListener(string -> { + TextColor.parse(this.colorEntryWidget.getText()).ifSuccess(color -> { + this.popupBlockEntity.color = color == null ? 0xFFFFFFFF : color.getRgb() | 0xFF000000; + this.popupBlockEntity.renderDirty = true; + }); + }); + + this.addDrawableChild(this.changeAlignment); + this.addDrawableChild(this.colorEntryWidget); + } + + @Override + public void tick() { + ++this.ticksSinceOpened; + } + + @Override + public void close() { + C2SEditPopupBlock.of(popupBlockEntity).send(); + super.close(); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + if (this.client != null) { + super.render(context, mouseX, mouseY, delta); + + context.getMatrices().push(); + context.getMatrices().translate(0, 40 + 2 * this.width / 100F, 0); + for (int i = 0; i < this.popupBlockEntity.lines.size(); ++i) { + var text = this.currentRow == i ? Text.literal(this.popupBlockEntity.getRawLine(i)) : this.popupBlockEntity.lines.get(i); + + int lineWidth = this.textRenderer.getWidth(text); + switch (this.popupBlockEntity.textAlignment) { + case LEFT -> context.drawTextWithShadow(client.textRenderer, text, this.width / 10, i * 12, this.popupBlockEntity.color); + case CENTER -> context.drawTextWithShadow(client.textRenderer, text, this.width / 2 - lineWidth / 2, i * 12, this.popupBlockEntity.color); + case RIGHT -> context.drawTextWithShadow(client.textRenderer, text, this.width - this.width / 10 - lineWidth, i * 12, this.popupBlockEntity.color); + } + } + + int caretStart = this.selectionManager.getSelectionStart(); + int caretEnd = this.selectionManager.getSelectionEnd(); + + if (caretStart >= 0) { + String line = this.popupBlockEntity.getRawLine(this.currentRow); + int selectionStart = MathHelper.clamp(Math.min(caretStart, caretEnd), 0, line.length()); + int selectionEnd = MathHelper.clamp(Math.max(caretStart, caretEnd), 0, line.length()); + + String preSelection = line.substring(0, MathHelper.clamp(line.length(), 0, selectionStart)); + int startX = this.client.textRenderer.getWidth(preSelection); + + float push = switch (this.popupBlockEntity.textAlignment) { + case LEFT -> this.width / 10F; + case CENTER -> this.width / 2F - this.textRenderer.getWidth(line) / 2F; + case RIGHT -> this.width - this.width / 10F - this.textRenderer.getWidth(line); + }; + + startX += (int) push; + + + int caretStartY = this.currentRow * 12; + int caretEndY = this.currentRow * 12 + 9; + if (this.ticksSinceOpened / 6 % 2 == 0 && !this.colorEntryWidget.isActive()) { + if (selectionStart < line.length()) { + context.fill(startX, caretStartY, startX + 1, caretEndY, 0xCCFFFFFF); + } else { + context.drawText(client.textRenderer, "_", startX, this.currentRow * 12, 0xFFFFFFFF, false); + } + } + + if (caretStart != caretEnd) { + int endX = startX + this.client.textRenderer.getWidth(line.substring(selectionStart, selectionEnd)); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + RenderSystem.enableColorLogicOp(); + RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE); + bufferBuilder.vertex(context.getMatrices().peek().getPositionMatrix(), startX, caretEndY, 0.0F).color(0, 0, 255, 255); + bufferBuilder.vertex(context.getMatrices().peek().getPositionMatrix(), endX, caretEndY, 0.0F).color(0, 0, 255, 255); + bufferBuilder.vertex(context.getMatrices().peek().getPositionMatrix(), endX, caretStartY, 0.0F).color(0, 0, 255, 255); + bufferBuilder.vertex(context.getMatrices().peek().getPositionMatrix(), startX, caretStartY, 0.0F).color(0, 0, 255, 255); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.disableColorLogicOp(); + } + } + + context.getMatrices().pop(); + } + } + + @Override + public boolean charTyped(char chr, int keyCode) { + if (this.colorEntryWidget.isActive()) { + return this.colorEntryWidget.charTyped(chr, keyCode); + } else { + this.selectionManager.insert(chr); + return true; + } + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (this.colorEntryWidget.isActive()) { + if (keyCode == GLFW.GLFW_KEY_ESCAPE) { + this.close(); + return true; + } else { + return this.colorEntryWidget.keyPressed(keyCode, scanCode, modifiers); + } + } else { + setFocused(null); + if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { + this.popupBlockEntity.addRawLine(this.currentRow + 1, + this.popupBlockEntity.getRawLine(this.currentRow).substring( + MathHelper.clamp(this.selectionManager.getSelectionStart(), 0, this.popupBlockEntity.getRawLine(this.currentRow).length()) + )); + this.popupBlockEntity.setRawLine(this.currentRow, + this.popupBlockEntity.getRawLine(this.currentRow).substring(0, MathHelper.clamp(this.selectionManager.getSelectionStart(), 0, this.popupBlockEntity.getRawLine(this.currentRow).length()) + )); + this.popupBlockEntity.renderDirty = true; + ++this.currentRow; + this.selectionManager.moveCursorToStart(); + return true; + } else if (keyCode == GLFW.GLFW_KEY_UP) { + this.currentRow = Math.max(this.currentRow - 1, 0); + this.selectionManager.putCursorAtEnd(); + return true; + } else if (keyCode == GLFW.GLFW_KEY_DOWN) { + this.currentRow = Math.min(this.currentRow + 1, (this.popupBlockEntity.lines.size() - 1)); + this.selectionManager.putCursorAtEnd(); + return true; + } else if (keyCode == GLFW.GLFW_KEY_BACKSPACE && this.currentRow > 0 && this.popupBlockEntity.lines.size() > 1 && this.selectionManager.getSelectionStart() == 0 && this.selectionManager.getSelectionEnd() == this.selectionManager.getSelectionStart()) { + --this.currentRow; + this.selectionManager.putCursorAtEnd(); + deleteLine(); + return true; + } else if (keyCode == GLFW.GLFW_KEY_DELETE && this.currentRow < this.popupBlockEntity.lines.size() - 1 && this.selectionManager.getSelectionEnd() == this.popupBlockEntity.getRawLine(this.currentRow).length()) { + deleteLine(); + return true; + } else { + try { + boolean val = this.selectionManager.handleSpecialKey(keyCode) || super.keyPressed(keyCode, scanCode, modifiers); + int selectionOffset = this.popupBlockEntity.getRawLine(this.currentRow).length() - this.selectionManager.getSelectionStart(); + + // Find line feed characters and create proper newlines + for (int i = 0; i < this.popupBlockEntity.lines.size(); ++i) { + int lineFeedIndex = this.popupBlockEntity.getRawLine(i).indexOf("\n"); + + if (lineFeedIndex >= 0) { + this.popupBlockEntity.addRawLine(i + 1, + this.popupBlockEntity.getRawLine(i).substring( + MathHelper.clamp(lineFeedIndex + 1, 0, this.popupBlockEntity.getRawLine(i).length()) + )); + this.popupBlockEntity.setRawLine(i, + this.popupBlockEntity.getRawLine(i).substring(0, MathHelper.clamp(lineFeedIndex, 0, this.popupBlockEntity.getRawLine(i).length()) + )); + this.popupBlockEntity.renderDirty = true; + ++this.currentRow; + this.selectionManager.putCursorAtEnd(); + this.selectionManager.moveCursor(-selectionOffset); + } + } + return val; + } catch (StringIndexOutOfBoundsException e) { + e.printStackTrace(); + MinecraftClient.getInstance().setScreen(null); + return false; + } + } + } + } + + private void deleteLine() { + this.popupBlockEntity.setRawLine(this.currentRow, + this.popupBlockEntity.getRawLine(this.currentRow) + this.popupBlockEntity.getRawLine(this.currentRow + 1) + ); + + this.popupBlockEntity.lines.remove(this.currentRow + 1); + this.popupBlockEntity.renderDirty = true; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + int topOffset = (int) (40 + 2 * this.width / 100F); + if (!this.colorEntryWidget.mouseClicked(mouseX, mouseY, button)) { + this.colorEntryWidget.setFocused(false); + } + if (mouseY > topOffset) { + this.currentRow = MathHelper.clamp((int) (mouseY - topOffset) / 12, 0, this.popupBlockEntity.lines.size() - 1); + this.setFocused(null); + String baseContents = this.popupBlockEntity.getRawLine(currentRow); + int baseContentsWidth = this.textRenderer.getWidth(baseContents); + int contentsStart; + int contentsEnd; + switch (this.popupBlockEntity.textAlignment) { + case LEFT -> { + contentsStart = this.width / 10; + contentsEnd = contentsStart + baseContentsWidth; + } + case CENTER -> { + int midpoint = this.width / 2; + int textMidpoint = baseContentsWidth / 2; + contentsStart = midpoint - textMidpoint; + contentsEnd = midpoint + textMidpoint; + } + case RIGHT -> { + contentsEnd = this.width - this.width / 10; + contentsStart = contentsEnd - baseContentsWidth; + } + //even though this is exhaustive, javac won't treat contentsStart and contentsEnd as initialized + //why? who knows! just throw bc this should be impossible + default -> throw new IllegalStateException(":HOW:"); + } + + if (mouseX <= contentsStart) { + this.selectionManager.moveCursorToStart(); + } else if (mouseX >= contentsEnd) { + this.selectionManager.putCursorAtEnd(); + } else { + int lastWidth = 0; + for (int i = 1; i < baseContents.length(); i++) { + String testContents = baseContents.substring(0, i); + int width = this.textRenderer.getWidth(testContents); + int midpointWidth = (width + lastWidth) / 2; + if (mouseX < contentsStart + midpointWidth) { + this.selectionManager.moveCursorTo(i - 1, false); + break; + } else if (mouseX <= contentsStart + width) { + this.selectionManager.moveCursorTo(i, false); + break; + } + lastWidth = width; + } + } + return true; + } else { + return super.mouseClicked(mouseX, mouseY, button); + } + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockViewScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockViewScreen.java new file mode 100644 index 0000000..9ad6fe5 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockViewScreen.java @@ -0,0 +1,52 @@ +package dev.hephaestus.glowcase.client.gui.screen.ingame; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; +import dev.hephaestus.glowcase.block.entity.TextBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.render.*; +import net.minecraft.client.util.SelectionManager; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; + +//TODO: multi-character selection at some point? it may be a bit complex but it'd be nice +public class PopupBlockViewScreen extends GlowcaseScreen { + private final PopupBlockEntity popupBlockEntity; + + public PopupBlockViewScreen(PopupBlockEntity popupBlockEntity) { + this.popupBlockEntity = popupBlockEntity; + } + + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + renderDarkening(context); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + if (this.client != null) { + super.render(context, mouseX, mouseY, delta); + + context.getMatrices().push(); + context.getMatrices().translate(0, 40 + 2 * this.width / 100F, 0); + for (int i = 0; i < this.popupBlockEntity.lines.size(); ++i) { + var text = this.popupBlockEntity.lines.get(i); + + int lineWidth = this.textRenderer.getWidth(text); + switch (this.popupBlockEntity.textAlignment) { + case LEFT -> context.drawTextWithShadow(client.textRenderer, text, this.width / 10, i * 12, this.popupBlockEntity.color); + case CENTER -> context.drawTextWithShadow(client.textRenderer, text, this.width / 2 - lineWidth / 2, i * 12, this.popupBlockEntity.color); + case RIGHT -> context.drawTextWithShadow(client.textRenderer, text, this.width - this.width / 10 - lineWidth, i * 12, this.popupBlockEntity.color); + } + } + + context.getMatrices().pop(); + } + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java new file mode 100644 index 0000000..9ef2d28 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java @@ -0,0 +1,38 @@ +package dev.hephaestus.glowcase.client.render.block.entity; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer.TextLayerType; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.RotationAxis; + +public record PopupBlockEntityRenderer(BlockEntityRendererFactory.Context context) implements BlockEntityRenderer { + private static final MinecraftClient mc = MinecraftClient.getInstance(); + + public static final ItemStack STACK = new ItemStack(Glowcase.POPUP_BLOCK.get()); + + public void render(PopupBlockEntity entity, float f, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + Camera camera = context.getRenderDispatcher().camera; + matrices.push(); + matrices.translate(0.5D, 0.5D, 0.5D); + matrices.scale(0.5F, 0.5F, 0.5F); + float n = -camera.getYaw(); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(n)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); + context.getItemRenderer().renderItem(STACK, ModelTransformationMode.FIXED, light, OverlayTexture.DEFAULT_UV, matrices, vertexConsumers, entity.getWorld(), 0); + + matrices.pop(); + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java new file mode 100644 index 0000000..0001e54 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java @@ -0,0 +1,49 @@ +package dev.hephaestus.glowcase.packet; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; +import dev.hephaestus.glowcase.block.entity.TextBlockEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.text.TextCodecs; +import net.minecraft.util.math.BlockPos; + +import java.util.ArrayList; +import java.util.List; + +public record C2SEditPopupBlock(BlockPos pos, List lines, TextBlockEntity.TextAlignment alignment, int color) implements C2SEditBlockEntity { + public static final Id ID = new Id<>(Glowcase.id("channel.popup_block")); + public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( + BlockPos.PACKET_CODEC, C2SEditPopupBlock::pos, + PacketCodecs.collection(ArrayList::new, TextCodecs.REGISTRY_PACKET_CODEC), C2SEditPopupBlock::lines, + PacketCodecs.BYTE.xmap(index -> TextBlockEntity.TextAlignment.values()[index], textAlignment -> (byte) textAlignment.ordinal()), C2SEditPopupBlock::alignment, + PacketCodecs.INTEGER, C2SEditPopupBlock::color, + C2SEditPopupBlock::new + ); + + public static C2SEditPopupBlock of(PopupBlockEntity be) { + return new C2SEditPopupBlock(be.getPos(), be.lines, be.textAlignment, be.color); + } + + @Override + public Id getId() { + return ID; + } + + @Override + public void receive(ServerWorld world, BlockEntity blockEntity) { + if (!(blockEntity instanceof PopupBlockEntity be)) return; + + be.lines = this.lines(); + be.textAlignment = this.alignment(); + be.color = this.color(); + + be.markDirty(); + be.dispatch(); + } +} diff --git a/src/main/resources/assets/glowcase/blockstates/popup_block.json b/src/main/resources/assets/glowcase/blockstates/popup_block.json new file mode 100644 index 0000000..0858580 --- /dev/null +++ b/src/main/resources/assets/glowcase/blockstates/popup_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "glowcase:block/popup_block" + } + } +} diff --git a/src/main/resources/assets/glowcase/lang/en_us.json b/src/main/resources/assets/glowcase/lang/en_us.json index a32d0e3..0b222cb 100644 --- a/src/main/resources/assets/glowcase/lang/en_us.json +++ b/src/main/resources/assets/glowcase/lang/en_us.json @@ -3,6 +3,7 @@ "block.glowcase.text_block": "Text Block", "block.glowcase.hyperlink_block": "Hyperlink Block", "block.glowcase.item_display_block": "Item Display Block", + "block.glowcase.popup_block": "Popup Block", "gui.glowcase.scale": "Scale: %d", "gui.glowcase.alignment": "Alignment: %s", "gui.glowcase.gives_item": "Gives Item: %s", diff --git a/src/main/resources/assets/glowcase/models/block/popup_block.json b/src/main/resources/assets/glowcase/models/block/popup_block.json new file mode 100644 index 0000000..49f3a0b --- /dev/null +++ b/src/main/resources/assets/glowcase/models/block/popup_block.json @@ -0,0 +1,5 @@ +{ + "textures": { + "particle": "glowcase:item/popup_block" + } +} diff --git a/src/main/resources/assets/glowcase/models/item/popup_block.json b/src/main/resources/assets/glowcase/models/item/popup_block.json new file mode 100644 index 0000000..898e040 --- /dev/null +++ b/src/main/resources/assets/glowcase/models/item/popup_block.json @@ -0,0 +1,49 @@ +{ + "textures": { + "0": "glowcase:item/popup_block", + "particle": "glowcase:item/popup_block" + }, + "elements": [ + { + "from": [ + 2, + 2, + 8 + ], + "to": [ + 14, + 14, + 8 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 8, + 8, + 16 + ] + }, + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#0" + } + } + } + ] +} diff --git a/src/main/resources/assets/glowcase/textures/item/popup_block.png b/src/main/resources/assets/glowcase/textures/item/popup_block.png new file mode 100644 index 0000000000000000000000000000000000000000..9a17e05812c1989e17cf56f4ed0d33ec99faef38 GIT binary patch literal 5954 zcmdT|c|4Tu*B=s5SyEXFLzcvtjTt5eF_!F%tt`!MikWF<>_SOtQI>3F$rd474<$*v z79mNCO0-cz_{r|QhxE|X^Ssade%^oH`}4WycAs;;-*cVoI_JzWN9=9QSBuDsfIy(t zmKLUtz!S{7S1bcQP4kZ41s(!4V;f@-sNzJ}q(dT4NwRRX0f7#Sfk4NBdl~@kHv)n7 z1%p7n$3P(c4kl{A1%_ll zg7G^ZdQ*EH)Eb)Tg(IZO?Ap9c6scXIn8PoDGd-zZSBT$#_$WG4kR#x=iVE(zb6$Wapt0) zjHZNCjIN4RoK|)7(Nx(KO{%mC_1b1*iHAq@2=S}2lbV&esV~m!SI6AZE4b+Ng4nK`R$mpn3c$ybWMrQH5Fz@VM!X@=7lo+{KYxvz#lJto6F>lZ;2CnU?kTA zGT9|q5(!}mFs^SHixL+Xc3HOGLg0L)Sf!Eta{&=!_;caW$ldlrvc^cC6+D5}NNXVvLL;fLScSYdtOeEFJ^_$LL;Z=ZkL$m+kmd81g$$>QsBH!^Ol z?o!>mGD!WZ>Knm|r2^Pvl z5*Lo_H`Us^sUjihcu<oMA^u3 z{&9)%SOMHkiNb<1L2#-pB9CXBHvYCfy?OLMsPqm$pS!0 z{3_=&pK&%h>z(RzMeS)63OVKeq5IT_?e{X1kw=?ID+jL>t z{ZW+*R)>-sA3~Bir{3LLcfacX>*P>1yOh90yW~!lPW4%PzWlQV;)QYf<=$O6Hya&4 zJ9gxk92ToV-DBN*v$C;NV{s%B723~a@ zb>{nAOmMgCHreIk-eszKC1$4;*0^4@<9J!^)bQ9->{8Hvsye+oC7?9m*yu93$`esd zvKfLIJFiH49%5AXV_$CwDbI}d%JGVQ-x})-wR5~l4vR`h$wWYnNefL3QiU4f8bjpRt z?M>|)O6=V0t1AAGc)sz{_@nj~)Qi!WuWjtFAJRX>K5Y2f)|VRapMcy^?xfq~ve8`8 zB2nwZf`=PUd_LjZpxR)m=2@UzkZaqVVUs@I^tEYN3#IkNqp3!zRK65fx{QHfWHX*J zPQH5jO7hjtS2P1n{q~UbVbjowp#Gta-yDaC!8)OjLUsn14fp>?aa>>$KdC?Zboj$$ zz~qhaH{rF@@+B=EH+DYm6`QJ?3Y;`t)gtO9IY0jbfY42|z4 z=`qzYTF2$R^6R#QK23TmQtafCbt3*a;cj{iuHjIF{E>alBQzB3Q}@;G-S4RGS|xQQ zG+*-oz0lL72K9H=cRTK++_6)6uF_|lYRk1Ku}JT_!YZzTCg>-APWYHOohYUfv0d1X zZgnUB?zznO_XiV#>*x>YFX&Od6TQ*BxqE!u``nQazjvW2Ml!{SD+2h(&G>qI^UFBh zWO|l+;<&1Y<`>gyE(%&}Xbz=?Hjzt1`!DTr*yFw@bO=9;`Vf18v%|Gseuu)PYqY3| zLkCt%ZZJT}zcGD&>S}L6SmIRWlB>>wGn(JG(3L^X+ruymc#|2JCr_YD4u` z@BjL-qqsUklPKj0L8+H+4)?yfrDh_w7oF4@_EMsrbhfRMJ8Ro$`=+VOQ?ynz#WLkX za_qop$7=^$D0E9il^V4<=_qBLf2eS1bf~$;K8@NU?V#Q9NOkC+cP%)rk*c09} z(=+_-MnRih*39x{sl!uD)mOk+35vD1#^b~|wc_k6;;b48=H)evOOn3TlDn(c(*IcJ zb8#K@;(AJ@6sbbY|Ed(RT$)fO<6SD_bwSpnWW&yq4erGo-HPN~&dWI$%Hs`qtDfm=q1& zWDRtZCh8PKn>YBnqH;We2bAk*>oog6x}(Lf90i5L-McWDiM?tYnB?EutTU0T}!!Tmm@A&zHf$1Q{sJ5o3VAd19y%c+P~o z$3V%L=Mn5?V-GfAvMFF4Efj2aPF(Lt@ieTso5h=Ft*}OnE{0!nI($ z&=w4BZ2sBQ&+n%-hl>jUy!=@7Z;3hhU={`HNZ~O3*(3@sfWqKzT5v`t{lv2T*}ik( zl1WgCFU1cq;{XeT|8&LjVRD%qALif0@l(Ad8ZMps=bkQE9#6BxloCY$8&jTU-gNHN zct@xYBnrlaO(AfZY&?_ci=9sg`-L@vf&blj#}D4@N@tLnfgE*x=&ul71}x>Gm=d@Y zECPmrL0~8d0)dC4fSkeT=t5v<3=Fo2V%~BIgAI_NWCEA)Z#b6NE@feo>D1tV#qp=* zVg?%qD1F7Z&m(1Lt-0znq_ zm{e{cflV={0V(ir3T~coDQq#bK9tueed+&qo6R8v{I9qA-<8P!)2;rQl_VbmgGM1^ zp$iGQAoy<%X8x=eSH?n_{aQr&WDuQfoI}wfp+dS)&m!;DW+=pFe<$)k}fy{|sELUJCpZ=ggpUu|Qj!TjDR`pBUbk zBxY_Soq*Ykf(1hQRkYOBo*qQ;bu*;{4V}YlRJ_JHhxk?T8<_jw!4@gzVe@&jXgHcH z_IW8Vc>!-g9xaT0ytkjDBZUFXi)>&p{J49y8VJOvXK8AT*R}IYcouNeXq9P_pt7QH z-jlsI@;=WRLO0R-?qM4r_V;BRc9!_6O#392;+p&I{lv#)JA0{AYIxx6^-n06+|Y|D zxP`#IX;Hn1kkMM91GNRm>#x3i#NYIYyuZHgo#|U;*X7=to8p3I496bun_$m8>0wvB z0msdzd~sUdSwwD{@WG=yUcU))tv@$m^ETRTwkKQOb;q0iA z`ZtC}MPdk9yB_eTm9m9c?E~YjX%ik|j~rkT7^jhXC(e|3huDtI6P+ScPQDR6ii0|3 z;$tcA$M<40uGin0Y!+%NNZM=7(XD@-X?7#Rm*6;?A*I~}Y57X?z8gWJ3r(+%4+W1R zpDN693z<&XF=w_<` literal 0 HcmV?d00001 diff --git a/src/main/resources/data/glowcase/tags/item/items.json b/src/main/resources/data/glowcase/tags/item/items.json index 26dc5c1..8d88222 100644 --- a/src/main/resources/data/glowcase/tags/item/items.json +++ b/src/main/resources/data/glowcase/tags/item/items.json @@ -3,6 +3,7 @@ "values": [ "glowcase:hyperlink_block", "glowcase:item_display_block", - "glowcase:text_block" + "glowcase:text_block", + "glowcase:popup_block" ] } From e81bc3c3f6b1bf59bb590252a1444fbadc805d22 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Thu, 29 Aug 2024 20:12:23 -0400 Subject: [PATCH 02/12] Added tooltips for #36 --- .../dev/hephaestus/glowcase/block/PopupBlock.java | 13 +++++++++++++ src/main/resources/assets/glowcase/lang/en_us.json | 5 ++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java b/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java index 3a9812d..122084e 100644 --- a/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java +++ b/src/main/java/dev/hephaestus/glowcase/block/PopupBlock.java @@ -10,8 +10,12 @@ import net.minecraft.component.type.NbtComponent; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.text.Text; import net.minecraft.util.ActionResult; +import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.ItemActionResult; import net.minecraft.util.hit.BlockHitResult; @@ -22,6 +26,8 @@ import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import java.util.List; + public class PopupBlock extends GlowcaseBlock implements BlockEntityProvider { private static final VoxelShape OUTLINE = VoxelShapes.cuboid(0.25, 0.25, 0.25, 0.75, 0.75, 0.75); @@ -69,4 +75,11 @@ protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, Worl } return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; } + + @Override + public void appendTooltip(ItemStack itemStack, Item.TooltipContext context, List tooltip, TooltipType options) { + tooltip.add(Text.translatable("block.glowcase.popup_block.tooltip.0").formatted(Formatting.GRAY)); + tooltip.add(Text.translatable("block.glowcase.generic.tooltip").formatted(Formatting.DARK_GRAY)); + tooltip.add(Text.translatable("block.glowcase.popup_block.tooltip.1").formatted(Formatting.DARK_GRAY)); + } } diff --git a/src/main/resources/assets/glowcase/lang/en_us.json b/src/main/resources/assets/glowcase/lang/en_us.json index 0b222cb..4f4785c 100644 --- a/src/main/resources/assets/glowcase/lang/en_us.json +++ b/src/main/resources/assets/glowcase/lang/en_us.json @@ -15,5 +15,8 @@ "item.glowcase.text_block": "Text Block", "item.glowcase.hyperlink_block": "Hyperlink Block", "gui.glowcase.title": "Title", - "gui.glowcase.url": "URL" + "gui.glowcase.url": "URL", + "block.glowcase.generic.tooltip": "Interact with a glowcase item to edit", + "block.glowcase.popup_block.tooltip.0": "Displays formatted text when interacted", + "block.glowcase.popup_block.tooltip.1": "Supports Placeholder QuickText" } From 295ea9efe0756b14e411e06ebab7478440a61250 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Thu, 29 Aug 2024 21:19:22 -0400 Subject: [PATCH 03/12] Added the sprite block --- .../dev/hephaestus/glowcase/Glowcase.java | 13 +-- .../glowcase/GlowcaseCommonProxy.java | 4 + .../glowcase/GlowcaseNetworking.java | 3 + .../glowcase/block/SpriteBlock.java | 84 ++++++++++++++++++ .../block/entity/SpriteBlockEntity.java | 74 +++++++++++++++ .../glowcase/client/GlowcaseClient.java | 2 + .../glowcase/client/GlowcaseClientProxy.java | 10 +++ .../screen/ingame/SpriteBlockEditScreen.java | 67 ++++++++++++++ .../entity/SpriteBlockEntityRenderer.java | 56 ++++++++++++ .../glowcase/packet/C2SEditSpriteBlock.java | 44 +++++++++ .../glowcase/blockstates/sprite_block.json | 7 ++ .../resources/assets/glowcase/lang/en_us.json | 6 +- .../glowcase/models/item/sprite_block.json | 6 ++ .../glowcase/textures/item/sprite_block.png | Bin 0 -> 215 bytes .../assets/glowcase/textures/sprite/arrow.png | Bin 0 -> 217 bytes .../glowcase/textures/sprite/double_arrow.png | Bin 0 -> 229 bytes .../textures/sprite/double_line_arrow.png | Bin 0 -> 202 bytes .../glowcase/textures/sprite/fancy_arrow.png | Bin 0 -> 247 bytes .../glowcase/textures/sprite/real_arrow.png | Bin 0 -> 195 bytes .../glowcase/textures/sprite/small_arrow.png | Bin 0 -> 196 bytes .../glowcase/textures/sprite/triple_arrow.png | Bin 0 -> 206 bytes .../textures/sprite/triple_line_arrow.png | Bin 0 -> 186 bytes .../glowcase/textures/sprite/wide_arrow.png | Bin 0 -> 191 bytes .../data/glowcase/tags/item/items.json | 3 +- 24 files changed, 372 insertions(+), 7 deletions(-) create mode 100644 src/main/java/dev/hephaestus/glowcase/block/SpriteBlock.java create mode 100644 src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java create mode 100644 src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java create mode 100644 src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java create mode 100644 src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java create mode 100644 src/main/resources/assets/glowcase/blockstates/sprite_block.json create mode 100644 src/main/resources/assets/glowcase/models/item/sprite_block.json create mode 100644 src/main/resources/assets/glowcase/textures/item/sprite_block.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/double_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/double_line_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/fancy_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/real_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/small_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/triple_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/triple_line_arrow.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/wide_arrow.png diff --git a/src/main/java/dev/hephaestus/glowcase/Glowcase.java b/src/main/java/dev/hephaestus/glowcase/Glowcase.java index 84476b4..ce24197 100644 --- a/src/main/java/dev/hephaestus/glowcase/Glowcase.java +++ b/src/main/java/dev/hephaestus/glowcase/Glowcase.java @@ -4,9 +4,11 @@ import com.google.common.base.Suppliers; import dev.hephaestus.glowcase.block.HyperlinkBlock; import dev.hephaestus.glowcase.block.ItemDisplayBlock; +import dev.hephaestus.glowcase.block.SpriteBlock; import dev.hephaestus.glowcase.block.TextBlock; import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.ItemDisplayBlockEntity; +import dev.hephaestus.glowcase.block.entity.SpriteBlockEntity; import dev.hephaestus.glowcase.block.entity.TextBlockEntity; import dev.hephaestus.glowcase.compat.PolydexCompatibility; import net.fabricmc.api.ModInitializer; @@ -15,11 +17,7 @@ import net.minecraft.block.Block; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; +import net.minecraft.item.*; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKeys; @@ -46,6 +44,10 @@ public class Glowcase implements ModInitializer { public static final Supplier TEXT_BLOCK_ITEM = registerItem("text_block", () -> new BlockItem(TEXT_BLOCK.get(), new Item.Settings())); public static final Supplier> TEXT_BLOCK_ENTITY = registerBlockEntity("text_block", () -> BlockEntityType.Builder.create(TextBlockEntity::new, TEXT_BLOCK.get()).build(null)); + public static final Supplier SPRITE_BLOCK = registerBlock("sprite_block", SpriteBlock::new); + public static final Supplier SPRITE_BLOCK_ITEM = registerItem("sprite_block", () -> new BlockItem(SPRITE_BLOCK.get(), new Item.Settings())); + public static final Supplier> SPRITE_BLOCK_ENTITY = registerBlockEntity("sprite_block", () -> BlockEntityType.Builder.create(SpriteBlockEntity::new, SPRITE_BLOCK.get()).build(null)); + public static final Supplier ITEM_GROUP = registerItemGroup("items", () -> FabricItemGroup.builder() .displayName(Text.translatable("itemGroup.glowcase.items")) .icon(() -> new ItemStack(Items.GLOWSTONE)) @@ -53,6 +55,7 @@ public class Glowcase implements ModInitializer { entries.add(HYPERLINK_BLOCK_ITEM.get()); entries.add(ITEM_DISPLAY_BLOCK_ITEM.get()); entries.add(TEXT_BLOCK_ITEM.get()); + entries.add(SPRITE_BLOCK_ITEM.get()); }) .build() ); diff --git a/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java b/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java index 65ee6c0..409d528 100644 --- a/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java +++ b/src/main/java/dev/hephaestus/glowcase/GlowcaseCommonProxy.java @@ -18,4 +18,8 @@ public void openItemDisplayBlockEditScreen(BlockPos pos) { public void openTextBlockEditScreen(BlockPos pos) { //No-op } + + public void openSpriteBlockEditScreen(BlockPos pos) { + //No-op + } } diff --git a/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java b/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java index 8b932a4..d385630 100644 --- a/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java +++ b/src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java @@ -2,6 +2,7 @@ import dev.hephaestus.glowcase.packet.C2SEditHyperlinkBlock; import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock; +import dev.hephaestus.glowcase.packet.C2SEditSpriteBlock; import dev.hephaestus.glowcase.packet.C2SEditTextBlock; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; @@ -11,9 +12,11 @@ public static void init() { PayloadTypeRegistry.playC2S().register(C2SEditHyperlinkBlock.ID, C2SEditHyperlinkBlock.PACKET_CODEC); PayloadTypeRegistry.playC2S().register(C2SEditItemDisplayBlock.ID, C2SEditItemDisplayBlock.PACKET_CODEC); PayloadTypeRegistry.playC2S().register(C2SEditTextBlock.ID, C2SEditTextBlock.PACKET_CODEC); + PayloadTypeRegistry.playC2S().register(C2SEditSpriteBlock.ID, C2SEditSpriteBlock.PACKET_CODEC); ServerPlayNetworking.registerGlobalReceiver(C2SEditHyperlinkBlock.ID, C2SEditHyperlinkBlock::receive); ServerPlayNetworking.registerGlobalReceiver(C2SEditItemDisplayBlock.ID, C2SEditItemDisplayBlock::receive); ServerPlayNetworking.registerGlobalReceiver(C2SEditTextBlock.ID, C2SEditTextBlock::receive); + ServerPlayNetworking.registerGlobalReceiver(C2SEditSpriteBlock.ID, C2SEditSpriteBlock::receive); } } diff --git a/src/main/java/dev/hephaestus/glowcase/block/SpriteBlock.java b/src/main/java/dev/hephaestus/glowcase/block/SpriteBlock.java new file mode 100644 index 0000000..5a80591 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/block/SpriteBlock.java @@ -0,0 +1,84 @@ +package dev.hephaestus.glowcase.block; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.SpriteBlockEntity; +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.Properties; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemActionResult; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class SpriteBlock extends GlowcaseBlock implements BlockEntityProvider { + public SpriteBlock() { + super(); + this.setDefaultState(this.getDefaultState().with(Properties.ROTATION, 0)); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + super.appendProperties(builder); + builder.add(Properties.ROTATION); + } + + @Override + public BlockState getPlacementState(ItemPlacementContext ctx) { + return this.getDefaultState().with(Properties.ROTATION, MathHelper.floor((double) ((180.0F + ctx.getPlayerYaw()) * 16.0F / 360.0F) + 0.5D) & 15); + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new SpriteBlockEntity(pos, state); + } + + @Override + public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + if (world.isClient && placer instanceof PlayerEntity player && canEditGlowcase(player, pos)) { + //load any ctrl-picked NBT clientside + NbtComponent blockEntityTag = stack.get(DataComponentTypes.BLOCK_ENTITY_DATA); + if (blockEntityTag != null && world.getBlockEntity(pos) instanceof SpriteBlockEntity be) { + blockEntityTag.applyToBlockEntity(be, world.getRegistryManager()); + } + + Glowcase.proxy.openSpriteBlockEditScreen(pos); + } + } + + @Override + protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!(world.getBlockEntity(pos) instanceof SpriteBlockEntity be)) return ItemActionResult.CONSUME; + + if (world.isClient && player.getStackInHand(hand).isIn(Glowcase.ITEM_TAG) && canEditGlowcase(player, pos)) { + Glowcase.proxy.openSpriteBlockEditScreen(pos); + } + + return ItemActionResult.SUCCESS; + } + + @Override + public void appendTooltip(ItemStack itemStack, Item.TooltipContext context, List tooltip, TooltipType options) { + tooltip.add(Text.translatable("block.glowcase.sprite_block.tooltip.0").formatted(Formatting.GRAY)); + tooltip.add(Text.translatable("block.glowcase.generic.tooltip").formatted(Formatting.DARK_GRAY)); + tooltip.add(Text.translatable("block.glowcase.sprite_block.tooltip.1").formatted(Formatting.DARK_GRAY)); + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java b/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java new file mode 100644 index 0000000..fba7ba8 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java @@ -0,0 +1,74 @@ +package dev.hephaestus.glowcase.block.entity; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.client.render.block.entity.BakedBlockEntityRenderer; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.registry.RegistryWrapper; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.Nullable; + +public class SpriteBlockEntity extends BlockEntity { + public TextBlockEntity.ZOffset zOffset = TextBlockEntity.ZOffset.CENTER; + public int rotation = 0; + public String sprite = "arrow"; + + public SpriteBlockEntity(BlockPos pos, BlockState state) { + super(Glowcase.SPRITE_BLOCK_ENTITY.get(), pos, state); + } + + public void setSprite(String newSprite) { + sprite = newSprite; + markDirty(); + dispatch(); + } + + @Override + public void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { + super.writeNbt(tag, registryLookup); + + tag.putString("z_offset", this.zOffset.name()); + tag.putInt("rotation", this.rotation); + tag.putString("sprite", this.sprite); + } + + @Override + public void readNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { + super.readNbt(tag, registryLookup); + + this.zOffset = TextBlockEntity.ZOffset.valueOf(tag.getString("z_offset")); + this.rotation = tag.getInt("rotation"); + this.sprite = tag.getString("sprite"); + } + + @SuppressWarnings({"MethodCallSideOnly", "VariableUseSideOnly"}) + @Override + public void markRemoved() { + if (world != null && world.isClient) { + BakedBlockEntityRenderer.Manager.markForRebuild(getPos()); + } + super.markRemoved(); + } + + // standard blockentity boilerplate + + public void dispatch() { + if (world instanceof ServerWorld sworld) sworld.getChunkManager().markForUpdate(pos); + } + + @Override + public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup registryLookup) { + return createNbt(registryLookup); + } + + @Nullable + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.create(this); + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java index 02b4a8e..c70a52e 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java +++ b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java @@ -5,6 +5,7 @@ import dev.hephaestus.glowcase.client.render.block.entity.HyperlinkBlockEntityRenderer; import dev.hephaestus.glowcase.client.render.block.entity.ItemDisplayBlockEntityRenderer; import dev.hephaestus.glowcase.client.render.block.entity.TextBlockEntityRenderer; +import dev.hephaestus.glowcase.client.render.block.entity.SpriteBlockEntityRenderer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.rendering.v1.InvalidateRenderStateCallback; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; @@ -18,6 +19,7 @@ public void onInitializeClient() { BlockEntityRendererFactories.register(Glowcase.TEXT_BLOCK_ENTITY.get(), TextBlockEntityRenderer::new); BlockEntityRendererFactories.register(Glowcase.HYPERLINK_BLOCK_ENTITY.get(), HyperlinkBlockEntityRenderer::new); BlockEntityRendererFactories.register(Glowcase.ITEM_DISPLAY_BLOCK_ENTITY.get(), ItemDisplayBlockEntityRenderer::new); + BlockEntityRendererFactories.register(Glowcase.SPRITE_BLOCK_ENTITY.get(), SpriteBlockEntityRenderer::new); WorldRenderEvents.AFTER_TRANSLUCENT.register(BakedBlockEntityRenderer.Manager::render); InvalidateRenderStateCallback.EVENT.register(BakedBlockEntityRenderer.Manager::reset); diff --git a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java index 2cf548d..765d84b 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java +++ b/src/main/java/dev/hephaestus/glowcase/client/GlowcaseClientProxy.java @@ -3,9 +3,11 @@ import dev.hephaestus.glowcase.GlowcaseCommonProxy; import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.ItemDisplayBlockEntity; +import dev.hephaestus.glowcase.block.entity.SpriteBlockEntity; import dev.hephaestus.glowcase.block.entity.TextBlockEntity; import dev.hephaestus.glowcase.client.gui.screen.ingame.HyperlinkBlockEditScreen; import dev.hephaestus.glowcase.client.gui.screen.ingame.ItemDisplayBlockEditScreen; +import dev.hephaestus.glowcase.client.gui.screen.ingame.SpriteBlockEditScreen; import dev.hephaestus.glowcase.client.gui.screen.ingame.TextBlockEditScreen; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ConfirmLinkScreen; @@ -40,4 +42,12 @@ public void openTextBlockEditScreen(BlockPos pos) { MinecraftClient.getInstance().setScreen(new TextBlockEditScreen(be)); } } + + @Override + public void openSpriteBlockEditScreen(BlockPos pos) { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.world != null && client.world.getBlockEntity(pos) instanceof SpriteBlockEntity be) { + MinecraftClient.getInstance().setScreen(new SpriteBlockEditScreen(be)); + } + } } diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java new file mode 100644 index 0000000..a8cf66b --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java @@ -0,0 +1,67 @@ +package dev.hephaestus.glowcase.client.gui.screen.ingame; + +import dev.hephaestus.glowcase.block.entity.SpriteBlockEntity; +import dev.hephaestus.glowcase.block.entity.TextBlockEntity; +import dev.hephaestus.glowcase.packet.C2SEditSpriteBlock; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +public class SpriteBlockEditScreen extends GlowcaseScreen { + private final SpriteBlockEntity spriteBlockEntity; + + private ButtonWidget zOffsetToggle; + private ButtonWidget rotationWidget; + private TextFieldWidget spriteWidget; + + public SpriteBlockEditScreen(SpriteBlockEntity spriteBlockEntity) { + this.spriteBlockEntity = spriteBlockEntity; + } + + @Override + public void init() { + super.init(); + + if (this.client == null) return; + + this.zOffsetToggle = ButtonWidget.builder(Text.literal(this.spriteBlockEntity.zOffset.name()), action -> { + switch (spriteBlockEntity.zOffset) { + case FRONT -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.CENTER; + case CENTER -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.BACK; + case BACK -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.FRONT; + } + + this.zOffsetToggle.setMessage(Text.literal(this.spriteBlockEntity.zOffset.name())); + //GlowcaseClientNetworking.editArrowBlock(spriteBlockEntity); + }).dimensions(width / 2 - 75, height / 2 - 40, 150, 20).build(); + + this.rotationWidget = ButtonWidget.builder(Text.literal("Rotate"), (action) -> { + this.spriteBlockEntity.rotation += 45; + if (this.spriteBlockEntity.rotation >= 360) { + this.spriteBlockEntity.rotation = 0; + } + //GlowcaseClientNetworking.editArrowBlock(spriteBlockEntity); + }).dimensions(width / 2 - 75, height / 2 - 10, 150, 20).build(); + + this.spriteWidget = new TextFieldWidget(this.client.textRenderer, width / 2 - 75, height / 2 + 20, 150, 20, Text.empty()); + this.spriteWidget.setText(spriteBlockEntity.sprite); + this.spriteWidget.setChangedListener(string -> { + if (Identifier.isPathValid(this.spriteWidget.getText())) { + this.spriteBlockEntity.sprite = this.spriteWidget.getText(); + //this.spriteBlockEntity.renderDirty = true; + } + }); + + this.addDrawableChild(this.zOffsetToggle); + this.addDrawableChild(this.rotationWidget); + this.addDrawableChild(this.spriteWidget); + } + + @Override + public void close() { + spriteBlockEntity.setSprite(spriteWidget.getText()); + C2SEditSpriteBlock.of(spriteBlockEntity).send(); + super.close(); + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java new file mode 100644 index 0000000..0d408a6 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java @@ -0,0 +1,56 @@ +package dev.hephaestus.glowcase.client.render.block.entity; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.SpriteBlockEntity; +import net.minecraft.client.render.*; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.state.property.Properties; +import net.minecraft.util.Colors; +import net.minecraft.util.math.RotationAxis; +import org.joml.Vector3f; + +public record SpriteBlockEntityRenderer(BlockEntityRendererFactory.Context context) implements BlockEntityRenderer { + private static final Vector3f[] vertices = new Vector3f[] { + new Vector3f(-0.5F, -0.5F, 0.0F), + new Vector3f(0.5F, -0.5F, 0.0F), + new Vector3f(0.5F, 0.5F, 0.0F), + new Vector3f(-0.5F, 0.5F, 0.0F) + }; + + public void render(SpriteBlockEntity entity, float f, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + matrices.push(); + matrices.translate(0.5D, 0.5D, 0.5D); + + float rotation = -(entity.getCachedState().get(Properties.ROTATION) * 360) / 16.0F; + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(rotation)); + matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(entity.rotation)); + + switch (entity.zOffset) { + case FRONT -> matrices.translate(0D, 0D, 0.4D); + case BACK -> matrices.translate(0D, 0D, -0.4D); + } + + var entry = matrices.peek(); + var vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getEntityCutout(Glowcase.id("textures/sprite/" + entity.sprite + ".png"))); + + vertex(entry, vertexConsumer, vertices[0], 0, 1); + vertex(entry, vertexConsumer, vertices[1], 1, 1); + vertex(entry, vertexConsumer, vertices[2], 1, 0); + vertex(entry, vertexConsumer, vertices[3], 0, 0); + + matrices.pop(); + } + + private void vertex( + MatrixStack.Entry matrix, VertexConsumer vertexConsumer, Vector3f vertex, float u, float v + ) { + vertexConsumer.vertex(matrix, vertex.x(), vertex.y(), vertex.z()) + .color(Colors.WHITE) + .texture(u, v) + .overlay(OverlayTexture.DEFAULT_UV) + .light(LightmapTextureManager.MAX_LIGHT_COORDINATE) + .normal(0, 1, 0); + } +} diff --git a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java new file mode 100644 index 0000000..893fe57 --- /dev/null +++ b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java @@ -0,0 +1,44 @@ +package dev.hephaestus.glowcase.packet; + +import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.SpriteBlockEntity; +import dev.hephaestus.glowcase.block.entity.TextBlockEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; + +public record C2SEditSpriteBlock(BlockPos pos, TextBlockEntity.ZOffset offset, int rotation, String sprite) implements C2SEditBlockEntity { + public static final Id ID = new Id<>(Glowcase.id("channel.sprite.save")); + public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( + BlockPos.PACKET_CODEC, C2SEditSpriteBlock::pos, + PacketCodecs.INTEGER.xmap(index -> TextBlockEntity.ZOffset.values()[index], TextBlockEntity.ZOffset::ordinal), C2SEditSpriteBlock::offset, + PacketCodecs.INTEGER, C2SEditSpriteBlock::rotation, + PacketCodecs.STRING, C2SEditSpriteBlock::sprite, + C2SEditSpriteBlock::new + ); + + public static C2SEditSpriteBlock of(SpriteBlockEntity be) { + return new C2SEditSpriteBlock(be.getPos(), be.zOffset, be.rotation, be.sprite); + } + + @Override + public Id getId() { + return ID; + } + + @Override + public void receive(ServerWorld world, BlockEntity blockEntity) { + if (!(blockEntity instanceof SpriteBlockEntity be)) return; + + be.zOffset = this.offset(); + be.rotation = this.rotation(); + be.setSprite(this.sprite()); + + be.markDirty(); + be.dispatch(); + } +} diff --git a/src/main/resources/assets/glowcase/blockstates/sprite_block.json b/src/main/resources/assets/glowcase/blockstates/sprite_block.json new file mode 100644 index 0000000..eb3ed52 --- /dev/null +++ b/src/main/resources/assets/glowcase/blockstates/sprite_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "glowcase:block/glowcase_block" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/glowcase/lang/en_us.json b/src/main/resources/assets/glowcase/lang/en_us.json index a32d0e3..927fc28 100644 --- a/src/main/resources/assets/glowcase/lang/en_us.json +++ b/src/main/resources/assets/glowcase/lang/en_us.json @@ -3,6 +3,7 @@ "block.glowcase.text_block": "Text Block", "block.glowcase.hyperlink_block": "Hyperlink Block", "block.glowcase.item_display_block": "Item Display Block", + "block.glowcase.sprite_block": "Sprite Block", "gui.glowcase.scale": "Scale: %d", "gui.glowcase.alignment": "Alignment: %s", "gui.glowcase.gives_item": "Gives Item: %s", @@ -14,5 +15,8 @@ "item.glowcase.text_block": "Text Block", "item.glowcase.hyperlink_block": "Hyperlink Block", "gui.glowcase.title": "Title", - "gui.glowcase.url": "URL" + "gui.glowcase.url": "URL", + "block.glowcase.generic.tooltip": "Interact with a glowcase item to edit", + "block.glowcase.sprite_block.tooltip.0": "Displays a sprite", + "block.glowcase.sprite_block.tooltip.1": "Can be extended with resource packs" } diff --git a/src/main/resources/assets/glowcase/models/item/sprite_block.json b/src/main/resources/assets/glowcase/models/item/sprite_block.json new file mode 100644 index 0000000..fad38b9 --- /dev/null +++ b/src/main/resources/assets/glowcase/models/item/sprite_block.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "glowcase:item/sprite_block" + } +} diff --git a/src/main/resources/assets/glowcase/textures/item/sprite_block.png b/src/main/resources/assets/glowcase/textures/item/sprite_block.png new file mode 100644 index 0000000000000000000000000000000000000000..00b7df6a4a68ad856d2606b69a11a90e59c66912 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}c0G|-o|NsA+o0|i9l9#QH0V(E^Aiv=M{~4~I;svT@;4JWnEM{QfI|Rav zq8eTeKtT^r7sn8d;I%!5LJWo+Oc(##{}TH$Ysp!$E}j*36{#H0n5OJXcyFI*xUpx| zoHM2os!@w(6!3^2Kf$m5$x_t&_}PCArz7|l|7Lzu#JEA%+vp?EOa@O^KbLh*2~7YW C+(J$O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/arrow.png b/src/main/resources/assets/glowcase/textures/sprite/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..02dc5bbdb7aab3f2324069954940fca5b19a69eb GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=Dh+L6~vJ#O${~!8}hF$B+p3w^tpx4k+-rT)gr7{?4@qn+2UT zx;iuOxy3%yUOVOSorcF-xL40^yK3ThH|~aCXS~Di_kUQooYc%`%>H!sk;n~O%b(&O zX3crUd!<|Zo_1^xW@=+GlQqA KpUXO@geCxYdr?3D literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/double_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/double_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..8c8abf1b2f209dd8616bd2285902bef2599d8472 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCils0(?ST|Ns9FWQHEPTnD6>N`m}?|1&(@Zr}yvaTa()7BevL9ROj*tZSW| zK*1@rC-bjlx@m58vbz`y;<1?#pbZhfd43 R?F8Dw;OXk;vd$@?2>?E~OlSZA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/double_line_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/double_line_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..145b649b4b4a1831b7137924e544ad713b17e57b GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCils0(?ST|Ns9FWQHEPTnD6>N`m}?|1&(@Zr}yvaTa()7BevL9ROj*tZSW| zKtX#?7sn6_|Ffqy3Nje*9CFzF|57A_OrUDXoVt>mYH oY-Uc5YBDO982qgse3SEF@4Lyo()!CukZTz{UHx3vIVCg!0AR5`K>z>% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/fancy_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/fancy_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..12ab41bbd5ceff65039c3139a6a75fb2ac21b6a7 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DkxL735kHCP2G*yHKq7!u+B_R2-B1_c3^z_f^2XW9q48>c(}VY-!cVVd(ErfW$XrXBvl zx~Kc#Zkc1+0lOu#raS*9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/real_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/real_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..e3d1cb5d5653f7c824fb4e30f53876533507be16 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=Dh+L6~vJ#O${~!3a+m$B+p3x0f8b4k+-rTzv8O{hd`adR1E* z3}XLmmlT+ia)E&%D>waxWZJewS&^TAJ??9MzNs~9$1R6#JNGZoSD5`}+h)&y2mVW0 n{8YQj7IUp-4gTe~DWM4fOIStc literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/small_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/small_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..af6dcd2c0d206a20b80a1b85b0bf40e12ff5a8ee GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=Dh+L6~vJ#O${~!AMUR$B+p3w^vSc0gZAAeEa|ZPWB#Y!uMZPUE`XQy!RRYH&(Is=zq*@ mTpgNp&@kpNlgpQBCm0^}YX7^Y`RWkR5(ZCKKbLh*2~7armqlLy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/triple_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/triple_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..a9db5b251d54ad874c4293249b7e73e2133c835f GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=Dh+L6~vJ#O${~!DLSt$B+p3w^tmw4k+-rT)gr7{?6P4rnRaf zE05~@yS>7o+pvR;;py8&$zB^D-dR>UbJ^F2w=Qj+yv;nm_^a9lbKbva)1JQaQOK5B w^zn^MenWl2PnNjK;^iRaF@HH34(va}$77rQWWG`i570UWPgg&ebxsLQ00+rTh5!Hn literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/triple_line_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/triple_line_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..fe10c77d658ab9afe865c06e7e9d73aaf90ee55b GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=Dh+K$tP>S|=w^(BIR=F(ktM?G;5n1_d7Hi><%!OZsRFc1-H} z&!af=h14MihrPPH;xgY<=DmEgc)`ZAYu7Wf_U7l=@@l-;ezw>Afc=Hr4Vo2eI{&dT cC}cll5IVa&{dB@Q5uniwp00i_>zopr0F_fcY5)KL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/wide_arrow.png b/src/main/resources/assets/glowcase/textures/sprite/wide_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ea73088cc4114bd0d3f4e951dabc5a19250a6ff3 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=DkxL735kHCP2G7~<*T7!u+B_KG1NgCPgA56_KMHcDz9I89ZJ6T-G@yGywnt<~u$B literal 0 HcmV?d00001 diff --git a/src/main/resources/data/glowcase/tags/item/items.json b/src/main/resources/data/glowcase/tags/item/items.json index 26dc5c1..13dde99 100644 --- a/src/main/resources/data/glowcase/tags/item/items.json +++ b/src/main/resources/data/glowcase/tags/item/items.json @@ -3,6 +3,7 @@ "values": [ "glowcase:hyperlink_block", "glowcase:item_display_block", - "glowcase:text_block" + "glowcase:text_block", + "glowcase:sprite_block" ] } From cbbf76e55923b759113041f0e108e37a67f474ad Mon Sep 17 00:00:00 2001 From: Sisby folk <55819817+sisby-folk@users.noreply.github.com> Date: Fri, 30 Aug 2024 11:33:42 +1000 Subject: [PATCH 04/12] Update en_us.json --- src/main/resources/assets/glowcase/lang/en_us.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/glowcase/lang/en_us.json b/src/main/resources/assets/glowcase/lang/en_us.json index db1187a..10fbdae 100644 --- a/src/main/resources/assets/glowcase/lang/en_us.json +++ b/src/main/resources/assets/glowcase/lang/en_us.json @@ -22,7 +22,7 @@ "block.glowcase.hyperlink_block.tooltip.0": "Opens a URL when interacted", "block.glowcase.item_display_block.tooltip.0": "Gives an item stack when interacted", "block.glowcase.item_display_block.tooltip.1": "Interact with an item stack to set it", - "block.glowcase.item_display_block.tooltip.2": "Interact with the same item to edit" - "block.glowcase.popup_block.tooltip.0": "Displays formatted text when interacted", + "block.glowcase.item_display_block.tooltip.2": "Interact with the same item to edit", + "block.glowcase.popup_block.tooltip.0": "Displays formatted text when interacted", "block.glowcase.popup_block.tooltip.1": "Supports Placeholder QuickText" } From 993639c0429dd7521ca122775e53ec0612d8ded1 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Thu, 29 Aug 2024 21:51:38 -0400 Subject: [PATCH 05/12] A smattering of sprites --- .../assets/glowcase/textures/sprite/checkmark.png | Bin 0 -> 197 bytes .../glowcase/textures/sprite/exclamation.png | Bin 0 -> 173 bytes .../glowcase/textures/sprite/information.png | Bin 0 -> 209 bytes .../glowcase/textures/sprite/interrobang.png | Bin 0 -> 204 bytes .../assets/glowcase/textures/sprite/no_entry.png | Bin 0 -> 208 bytes .../assets/glowcase/textures/sprite/o.png | Bin 0 -> 210 bytes .../assets/glowcase/textures/sprite/question.png | Bin 0 -> 200 bytes .../assets/glowcase/textures/sprite/x.png | Bin 0 -> 241 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/assets/glowcase/textures/sprite/checkmark.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/exclamation.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/information.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/interrobang.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/no_entry.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/o.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/question.png create mode 100644 src/main/resources/assets/glowcase/textures/sprite/x.png diff --git a/src/main/resources/assets/glowcase/textures/sprite/checkmark.png b/src/main/resources/assets/glowcase/textures/sprite/checkmark.png new file mode 100644 index 0000000000000000000000000000000000000000..bc729a9149511e5e77c87cd1eebf2fe6d8a0b829 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc!6;7`#}Etut9_0_2NXDtZ214bI9FosMKOVV zQ+C1WD~j~KGjGk6sfr$I}@0%!|^r>mdKI;Vst0Qwq4bpQYW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/exclamation.png b/src/main/resources/assets/glowcase/textures/sprite/exclamation.png new file mode 100644 index 0000000000000000000000000000000000000000..0cb1c705d0663ccf05f2cfaa579231bc5088681e GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucK_^ca#}Etuc;63a(Py7SZhTn}0r;aj7NHF+qQvd8Uvq}?a O8iS{+pUXO@geCwYmoI|= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/information.png b/src/main/resources/assets/glowcase/textures/sprite/information.png new file mode 100644 index 0000000000000000000000000000000000000000..c50e34b56f75ef19d3515d15f1292313e8e524d8 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}E0G|-o|Ns93nW2X+*8wS}k|4j}{|ryJ8+ZYEoCO|{#S9F5he4R}c>anM zprD(li(`mJaBi0;6N3T=)7Ss=*Kuy(JL@R6vd!v*AB$+&HK)#or4znieJ6G@u`7J5 w#81(CYNvOpKdL<{9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/interrobang.png b/src/main/resources/assets/glowcase/textures/sprite/interrobang.png new file mode 100644 index 0000000000000000000000000000000000000000..1fc52db48d6f2fe084648336820cc8de3c40f7ae GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}E0G|-o|Ns93nW2X+*8wS}k|4j}{|ryJ8+ZYEoCO|{#S9F5he4R}c>anM zprE6ti(`mJaBh#I5Q72-)5rhw{Vr^gvDDa|e2^h|!4ti2Qj=Gocbafo=TRD$V{roa qM}3p4^L3K!I@fPntE3;fcZRHYI>S6=!OA3{VGN$GelF{r5}E+S&pjLf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/no_entry.png b/src/main/resources/assets/glowcase/textures/sprite/no_entry.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ccac716d58e73e0e27a52330fcc137f87b74aa GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}E0G|-o|Ns93nW2X+*8wS}k|4j}{|ryJ8+ZYEoCO|{#S9F5he4R}c>anM zprEU#i(`mJaPGO2f(!~A%nmR1XP!Oyu&2gHOx`7_Y4HtF<$_PrcU{{A-$q}U5noub vFy(+##G$YSYu`nDvc6kysc~aw-U%BI2Zr{z^U@E21~PcM`njxgN@xNAMcYDq literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/o.png b/src/main/resources/assets/glowcase/textures/sprite/o.png new file mode 100644 index 0000000000000000000000000000000000000000..53598416b5795b486bce6906fd07e5f60e2d1100 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}E0G|-o|Ns93nW2X+*8wS}k|4j}{|ryJ8+ZYEoCO|{#S9F5he4R}c>anM zprE^_i(`mJaBq(zAA(QtWtKVi$ xYCr$zXNbGcf-M(2C*9nfZ>rOG#xMbfg|%}S-GN3jc)I$ztaD0e0sz5jLSg^_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/question.png b/src/main/resources/assets/glowcase/textures/sprite/question.png new file mode 100644 index 0000000000000000000000000000000000000000..7dc7c1e1e16e2cfe684114e968d4a515ef41a890 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}E0G|-o|Ns93nW2X+*8wS}k|4j}{|ryJ8+ZYEoCO|{#S9F5he4R}c>anM zprEa%i(`mJaB1&FK864mr=S1l@6$f?=9Ocq*$ihl*Ee!3&J)ELZ2xjE;r+#Cy8psv n{sj}_tPaMloUMML>o;?1AHyk?txFYw1~GWL`njxgN@xNA2gf}w literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/glowcase/textures/sprite/x.png b/src/main/resources/assets/glowcase/textures/sprite/x.png new file mode 100644 index 0000000000000000000000000000000000000000..cc639e6c70e405774b06b21ab2c5fa2b23fa045c GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCils0(?ST|Ns9FWQHEPTnD6>N`m}?|1&(@Zr}yvaTa()7BevL9R^{>!PC{xWt~$(69DctPR#%S literal 0 HcmV?d00001 From 4dc2756c8c818c08be95332dff4f1f42ca03a62c Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:05:08 -0400 Subject: [PATCH 06/12] Update text_block.png --- .../glowcase/textures/item/text_block.png | Bin 214 -> 205 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/glowcase/textures/item/text_block.png b/src/main/resources/assets/glowcase/textures/item/text_block.png index 9b835974e88956facdaa4ebe049ab0c5c2f6e3d5..16b82fbbdecc71582d41e578f44cbe5fe6158363 100644 GIT binary patch delta 159 zcmcb{c$RU3BnLAC1A~SxfAB;_#rgoB5ZC|z|C^he0|g~7TO9*Z%q2m7!TVGd003)AL_t(I zPu-JC4!|G?M5ULK`>(teIs_96HR*5Dz66Jbj%J7?BIOC2>1}>!fJ9?~sflPn%&ZO6 zN)Jy>V2lSPwN{Asj=1ks286}G#&ape)|#4mUZ27W8n;`!XJwF{I>3Zd2A}^-r4@8h W1x$8M9LMee0000 Date: Fri, 30 Aug 2024 21:35:43 -0400 Subject: [PATCH 07/12] Unflipped the hyperlink block entity renderer --- .../client/render/block/entity/HyperlinkBlockEntityRenderer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java index 264cc1a..0fd0eea 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java @@ -30,7 +30,6 @@ public void render(HyperlinkBlockEntity entity, float f, MatrixStack matrices, V float n = -camera.getYaw(); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(n)); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180)); context.getItemRenderer().renderItem(STACK, ModelTransformationMode.FIXED, light, OverlayTexture.DEFAULT_UV, matrices, vertexConsumers, entity.getWorld(), 0); HitResult hitResult = mc.crosshairTarget; From 900713f0814146a907a3510757dc1dce821ad694 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Fri, 30 Aug 2024 23:41:00 -0400 Subject: [PATCH 08/12] It seems this 180 degree roll flip was necessary, just in a different spot --- .../client/render/block/entity/HyperlinkBlockEntityRenderer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java index 0fd0eea..b380aae 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java @@ -36,6 +36,7 @@ public void render(HyperlinkBlockEntity entity, float f, MatrixStack matrices, V if (hitResult instanceof BlockHitResult && ((BlockHitResult) hitResult).getBlockPos().equals(entity.getPos())) { float scale = 0.025F; matrices.scale(scale, scale, scale); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180)); matrices.translate(-context.getTextRenderer().getWidth(entity.getText()) / 2F, -4, scale); // Fixes shadow being rendered in front of actual text matrices.scale(1, 1, -1); From 70e817119b142cc7e0cf869df72b6a95a4aa689b Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Fri, 30 Aug 2024 23:50:42 -0400 Subject: [PATCH 09/12] Fixed text shadow rendering behind hyperlink icon --- .../render/block/entity/HyperlinkBlockEntityRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java index b380aae..066e36f 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/HyperlinkBlockEntityRenderer.java @@ -37,7 +37,7 @@ public void render(HyperlinkBlockEntity entity, float f, MatrixStack matrices, V float scale = 0.025F; matrices.scale(scale, scale, scale); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180)); - matrices.translate(-context.getTextRenderer().getWidth(entity.getText()) / 2F, -4, scale); + matrices.translate(-context.getTextRenderer().getWidth(entity.getText()) / 2F, -4, -scale); // Fixes shadow being rendered in front of actual text matrices.scale(1, 1, -1); context.getTextRenderer().draw(entity.getText(), 0, 0, 0xFFFFFF, true, matrices.peek().getPositionMatrix(), vertexConsumers, TextLayerType.NORMAL, 0, LightmapTextureManager.MAX_LIGHT_COORDINATE); From dff5ca3bfd5e0236b2b8bc3b945e909de7c7bfa6 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Sat, 31 Aug 2024 00:27:49 -0400 Subject: [PATCH 10/12] Added titles to the popup block --- .../block/entity/PopupBlockEntity.java | 3 ++ .../screen/ingame/PopupBlockEditScreen.java | 35 +++++++++++++++---- .../entity/PopupBlockEntityRenderer.java | 11 +++++- .../glowcase/packet/C2SEditPopupBlock.java | 9 +++-- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java b/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java index 33ca336..c33d48c 100644 --- a/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java +++ b/src/main/java/dev/hephaestus/glowcase/block/entity/PopupBlockEntity.java @@ -26,6 +26,7 @@ public class PopupBlockEntity extends BlockEntity { public static final NodeParser PARSER = TagParser.DEFAULT; + public String title = ""; public List lines = new ArrayList<>(); public TextBlockEntity.TextAlignment textAlignment = TextBlockEntity.TextAlignment.CENTER; public int color = 0xFFFFFF; @@ -40,6 +41,7 @@ public PopupBlockEntity(BlockPos pos, BlockState state) { protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { super.writeNbt(tag, registryLookup); + tag.putString("title", this.title); tag.putInt("color", this.color); tag.putString("text_alignment", this.textAlignment.name()); @@ -56,6 +58,7 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL protected void readNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { super.readNbt(tag, registryLookup); + this.title = tag.getString("title"); this.lines = new ArrayList<>(); this.color = tag.getInt("color"); diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java index 928ffae..ce8469f 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java +++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/PopupBlockEditScreen.java @@ -2,10 +2,10 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; import dev.hephaestus.glowcase.block.entity.TextBlockEntity; import dev.hephaestus.glowcase.packet.C2SEditPopupBlock; -import dev.hephaestus.glowcase.packet.C2SEditTextBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.widget.ButtonWidget; @@ -24,6 +24,7 @@ public class PopupBlockEditScreen extends GlowcaseScreen { private SelectionManager selectionManager; private int currentRow; private long ticksSinceOpened = 0; + private TextFieldWidget titleEntryWidget; private ButtonWidget changeAlignment; private TextFieldWidget colorEntryWidget; @@ -52,6 +53,15 @@ public void init() { SelectionManager.makeClipboardSetter(this.client), (string) -> true); + this.titleEntryWidget = new TextFieldWidget(this.client.textRenderer, width / 10, 0, 8 * width / 10, 20, Text.empty()); + this.titleEntryWidget.setMaxLength(HyperlinkBlockEntity.TITLE_MAX_LENGTH); + this.titleEntryWidget.setText(this.popupBlockEntity.title); + this.titleEntryWidget.setPlaceholder(Text.translatable("gui.glowcase.title")); + this.titleEntryWidget.setChangedListener(string -> { + this.popupBlockEntity.title = this.titleEntryWidget.getText(); + this.popupBlockEntity.renderDirty = true; + }); + this.changeAlignment = ButtonWidget.builder(Text.stringifiedTranslatable("gui.glowcase.alignment", this.popupBlockEntity.textAlignment), action -> { switch (popupBlockEntity.textAlignment) { case LEFT -> popupBlockEntity.textAlignment = TextBlockEntity.TextAlignment.CENTER; @@ -61,9 +71,9 @@ public void init() { this.popupBlockEntity.renderDirty = true; this.changeAlignment.setMessage(Text.stringifiedTranslatable("gui.glowcase.alignment", this.popupBlockEntity.textAlignment)); - }).dimensions(120 + innerPadding, 0, 160, 20).build(); + }).dimensions(120 + innerPadding, 20 + innerPadding, 160, 20).build(); - this.colorEntryWidget = new TextFieldWidget(this.client.textRenderer, 280 + innerPadding * 2, 0, 50, 20, Text.empty()); + this.colorEntryWidget = new TextFieldWidget(this.client.textRenderer, 280 + innerPadding * 2, 20 + innerPadding, 50, 20, Text.empty()); this.colorEntryWidget.setText("#" + Integer.toHexString(this.popupBlockEntity.color & 0x00FFFFFF)); this.colorEntryWidget.setChangedListener(string -> { TextColor.parse(this.colorEntryWidget.getText()).ifSuccess(color -> { @@ -72,6 +82,7 @@ public void init() { }); }); + this.addDrawableChild(this.titleEntryWidget); this.addDrawableChild(this.changeAlignment); this.addDrawableChild(this.colorEntryWidget); } @@ -127,7 +138,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { int caretStartY = this.currentRow * 12; int caretEndY = this.currentRow * 12 + 9; - if (this.ticksSinceOpened / 6 % 2 == 0 && !this.colorEntryWidget.isActive()) { + if (this.ticksSinceOpened / 6 % 2 == 0 && !this.titleEntryWidget.isActive() && !this.colorEntryWidget.isActive()) { if (selectionStart < line.length()) { context.fill(startX, caretStartY, startX + 1, caretEndY, 0xCCFFFFFF); } else { @@ -156,7 +167,9 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { @Override public boolean charTyped(char chr, int keyCode) { - if (this.colorEntryWidget.isActive()) { + if (this.titleEntryWidget.isActive()) { + return this.titleEntryWidget.charTyped(chr, keyCode); + } else if (this.colorEntryWidget.isActive()) { return this.colorEntryWidget.charTyped(chr, keyCode); } else { this.selectionManager.insert(chr); @@ -166,7 +179,14 @@ public boolean charTyped(char chr, int keyCode) { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (this.colorEntryWidget.isActive()) { + if (this.titleEntryWidget.isActive()) { + if (keyCode == GLFW.GLFW_KEY_ESCAPE) { + this.close(); + return true; + } else { + return this.titleEntryWidget.keyPressed(keyCode, scanCode, modifiers); + } + } else if (this.colorEntryWidget.isActive()) { if (keyCode == GLFW.GLFW_KEY_ESCAPE) { this.close(); return true; @@ -248,6 +268,9 @@ private void deleteLine() { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { int topOffset = (int) (40 + 2 * this.width / 100F); + if (!this.titleEntryWidget.mouseClicked(mouseX, mouseY, button)) { + this.titleEntryWidget.setFocused(false); + } if (!this.colorEntryWidget.mouseClicked(mouseX, mouseY, button)) { this.colorEntryWidget.setFocused(false); } diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java index 9ef2d28..1c0ffa3 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/PopupBlockEntityRenderer.java @@ -1,7 +1,6 @@ package dev.hephaestus.glowcase.client.render.block.entity; import dev.hephaestus.glowcase.Glowcase; -import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer.TextLayerType; @@ -33,6 +32,16 @@ public void render(PopupBlockEntity entity, float f, MatrixStack matrices, Verte matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); context.getItemRenderer().renderItem(STACK, ModelTransformationMode.FIXED, light, OverlayTexture.DEFAULT_UV, matrices, vertexConsumers, entity.getWorld(), 0); + HitResult hitResult = mc.crosshairTarget; + if (hitResult instanceof BlockHitResult && ((BlockHitResult) hitResult).getBlockPos().equals(entity.getPos())) { + float scale = 0.025F; + matrices.scale(scale, scale, scale); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180)); + matrices.translate(-context.getTextRenderer().getWidth(entity.title) / 2F, -4, -scale); + // Fixes shadow being rendered in front of actual text + matrices.scale(1, 1, -1); + context.getTextRenderer().draw(entity.title, 0, 0, 0xFFFFFF, true, matrices.peek().getPositionMatrix(), vertexConsumers, TextLayerType.NORMAL, 0, LightmapTextureManager.MAX_LIGHT_COORDINATE); + } matrices.pop(); } } diff --git a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java index 0001e54..7732cbc 100644 --- a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java +++ b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditPopupBlock.java @@ -1,6 +1,7 @@ package dev.hephaestus.glowcase.packet; import dev.hephaestus.glowcase.Glowcase; +import dev.hephaestus.glowcase.block.entity.HyperlinkBlockEntity; import dev.hephaestus.glowcase.block.entity.PopupBlockEntity; import dev.hephaestus.glowcase.block.entity.TextBlockEntity; import net.minecraft.block.entity.BlockEntity; @@ -16,10 +17,11 @@ import java.util.ArrayList; import java.util.List; -public record C2SEditPopupBlock(BlockPos pos, List lines, TextBlockEntity.TextAlignment alignment, int color) implements C2SEditBlockEntity { +public record C2SEditPopupBlock(BlockPos pos, String title, List lines, TextBlockEntity.TextAlignment alignment, int color) implements C2SEditBlockEntity { public static final Id ID = new Id<>(Glowcase.id("channel.popup_block")); public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( BlockPos.PACKET_CODEC, C2SEditPopupBlock::pos, + PacketCodecs.STRING, C2SEditPopupBlock::title, PacketCodecs.collection(ArrayList::new, TextCodecs.REGISTRY_PACKET_CODEC), C2SEditPopupBlock::lines, PacketCodecs.BYTE.xmap(index -> TextBlockEntity.TextAlignment.values()[index], textAlignment -> (byte) textAlignment.ordinal()), C2SEditPopupBlock::alignment, PacketCodecs.INTEGER, C2SEditPopupBlock::color, @@ -27,7 +29,7 @@ public record C2SEditPopupBlock(BlockPos pos, List lines, TextBlockEntity. ); public static C2SEditPopupBlock of(PopupBlockEntity be) { - return new C2SEditPopupBlock(be.getPos(), be.lines, be.textAlignment, be.color); + return new C2SEditPopupBlock(be.getPos(), be.title, be.lines, be.textAlignment, be.color); } @Override @@ -39,6 +41,9 @@ public Id getId() { public void receive(ServerWorld world, BlockEntity blockEntity) { if (!(blockEntity instanceof PopupBlockEntity be)) return; + if (this.title().length() <= HyperlinkBlockEntity.TITLE_MAX_LENGTH) { + be.title = this.title(); + } be.lines = this.lines(); be.textAlignment = this.alignment(); be.color = this.color(); From 9cb01f9e5b48aebfab042147ceb9926be2173499 Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:21:29 -0400 Subject: [PATCH 11/12] Added color to sprite block --- .../block/entity/SpriteBlockEntity.java | 15 +++--- .../screen/ingame/SpriteBlockEditScreen.java | 50 +++++++++++-------- .../entity/SpriteBlockEntityRenderer.java | 15 +++--- .../glowcase/packet/C2SEditSpriteBlock.java | 14 +++--- 4 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java b/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java index fba7ba8..9e171ab 100644 --- a/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java +++ b/src/main/java/dev/hephaestus/glowcase/block/entity/SpriteBlockEntity.java @@ -14,9 +14,10 @@ import org.jetbrains.annotations.Nullable; public class SpriteBlockEntity extends BlockEntity { - public TextBlockEntity.ZOffset zOffset = TextBlockEntity.ZOffset.CENTER; - public int rotation = 0; public String sprite = "arrow"; + public int rotation = 0; + public TextBlockEntity.ZOffset zOffset = TextBlockEntity.ZOffset.CENTER; + public int color = 0xFFFFFF; public SpriteBlockEntity(BlockPos pos, BlockState state) { super(Glowcase.SPRITE_BLOCK_ENTITY.get(), pos, state); @@ -32,18 +33,20 @@ public void setSprite(String newSprite) { public void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { super.writeNbt(tag, registryLookup); - tag.putString("z_offset", this.zOffset.name()); - tag.putInt("rotation", this.rotation); tag.putString("sprite", this.sprite); + tag.putInt("rotation", this.rotation); + tag.putString("z_offset", this.zOffset.name()); + tag.putInt("color", this.color); } @Override public void readNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { super.readNbt(tag, registryLookup); - this.zOffset = TextBlockEntity.ZOffset.valueOf(tag.getString("z_offset")); - this.rotation = tag.getInt("rotation"); this.sprite = tag.getString("sprite"); + this.rotation = tag.getInt("rotation"); + this.zOffset = TextBlockEntity.ZOffset.valueOf(tag.getString("z_offset")); + this.color = tag.getInt("color"); } @SuppressWarnings({"MethodCallSideOnly", "VariableUseSideOnly"}) diff --git a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java index a8cf66b..7e21327 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java +++ b/src/main/java/dev/hephaestus/glowcase/client/gui/screen/ingame/SpriteBlockEditScreen.java @@ -6,14 +6,16 @@ import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.text.Text; +import net.minecraft.text.TextColor; import net.minecraft.util.Identifier; public class SpriteBlockEditScreen extends GlowcaseScreen { private final SpriteBlockEntity spriteBlockEntity; - private ButtonWidget zOffsetToggle; - private ButtonWidget rotationWidget; private TextFieldWidget spriteWidget; + private ButtonWidget rotationWidget; + private ButtonWidget zOffsetToggle; + private TextFieldWidget colorEntryWidget; public SpriteBlockEditScreen(SpriteBlockEntity spriteBlockEntity) { this.spriteBlockEntity = spriteBlockEntity; @@ -25,37 +27,43 @@ public void init() { if (this.client == null) return; - this.zOffsetToggle = ButtonWidget.builder(Text.literal(this.spriteBlockEntity.zOffset.name()), action -> { - switch (spriteBlockEntity.zOffset) { - case FRONT -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.CENTER; - case CENTER -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.BACK; - case BACK -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.FRONT; + this.spriteWidget = new TextFieldWidget(this.client.textRenderer, width / 2 - 75, height / 2 - 55, 150, 20, Text.empty()); + this.spriteWidget.setText(spriteBlockEntity.sprite); + this.spriteWidget.setChangedListener(string -> { + if (Identifier.isPathValid(this.spriteWidget.getText())) { + this.spriteBlockEntity.sprite = this.spriteWidget.getText(); } - - this.zOffsetToggle.setMessage(Text.literal(this.spriteBlockEntity.zOffset.name())); - //GlowcaseClientNetworking.editArrowBlock(spriteBlockEntity); - }).dimensions(width / 2 - 75, height / 2 - 40, 150, 20).build(); + }); this.rotationWidget = ButtonWidget.builder(Text.literal("Rotate"), (action) -> { this.spriteBlockEntity.rotation += 45; if (this.spriteBlockEntity.rotation >= 360) { this.spriteBlockEntity.rotation = 0; } - //GlowcaseClientNetworking.editArrowBlock(spriteBlockEntity); - }).dimensions(width / 2 - 75, height / 2 - 10, 150, 20).build(); + }).dimensions(width / 2 - 75, height / 2 - 25, 150, 20).build(); - this.spriteWidget = new TextFieldWidget(this.client.textRenderer, width / 2 - 75, height / 2 + 20, 150, 20, Text.empty()); - this.spriteWidget.setText(spriteBlockEntity.sprite); - this.spriteWidget.setChangedListener(string -> { - if (Identifier.isPathValid(this.spriteWidget.getText())) { - this.spriteBlockEntity.sprite = this.spriteWidget.getText(); - //this.spriteBlockEntity.renderDirty = true; + this.zOffsetToggle = ButtonWidget.builder(Text.literal(this.spriteBlockEntity.zOffset.name()), action -> { + switch (spriteBlockEntity.zOffset) { + case FRONT -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.CENTER; + case CENTER -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.BACK; + case BACK -> spriteBlockEntity.zOffset = TextBlockEntity.ZOffset.FRONT; } + + this.zOffsetToggle.setMessage(Text.literal(this.spriteBlockEntity.zOffset.name())); + }).dimensions(width / 2 - 75, height / 2 + 5, 150, 20).build(); + + this.colorEntryWidget = new TextFieldWidget(this.client.textRenderer, width / 2 - 75, height / 2 + 35, 150, 20, Text.empty()); + this.colorEntryWidget.setText("#" + String.format("%1$06X", this.spriteBlockEntity.color & 0x00FFFFFF)); + this.colorEntryWidget.setChangedListener(string -> { + TextColor.parse(this.colorEntryWidget.getText()).ifSuccess(color -> { + this.spriteBlockEntity.color = color == null ? 0xFFFFFFFF : color.getRgb() | 0xFF000000; + }); }); - this.addDrawableChild(this.zOffsetToggle); - this.addDrawableChild(this.rotationWidget); this.addDrawableChild(this.spriteWidget); + this.addDrawableChild(this.rotationWidget); + this.addDrawableChild(this.zOffsetToggle); + this.addDrawableChild(this.colorEntryWidget); } @Override diff --git a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java index 0d408a6..b23ce31 100644 --- a/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java +++ b/src/main/java/dev/hephaestus/glowcase/client/render/block/entity/SpriteBlockEntityRenderer.java @@ -7,7 +7,6 @@ import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.state.property.Properties; -import net.minecraft.util.Colors; import net.minecraft.util.math.RotationAxis; import org.joml.Vector3f; @@ -35,19 +34,19 @@ public void render(SpriteBlockEntity entity, float f, MatrixStack matrices, Vert var entry = matrices.peek(); var vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getEntityCutout(Glowcase.id("textures/sprite/" + entity.sprite + ".png"))); - vertex(entry, vertexConsumer, vertices[0], 0, 1); - vertex(entry, vertexConsumer, vertices[1], 1, 1); - vertex(entry, vertexConsumer, vertices[2], 1, 0); - vertex(entry, vertexConsumer, vertices[3], 0, 0); + vertex(entry, vertexConsumer, vertices[0], 0, 1, entity.color); + vertex(entry, vertexConsumer, vertices[1], 1, 1, entity.color); + vertex(entry, vertexConsumer, vertices[2], 1, 0, entity.color); + vertex(entry, vertexConsumer, vertices[3], 0, 0, entity.color); matrices.pop(); } private void vertex( - MatrixStack.Entry matrix, VertexConsumer vertexConsumer, Vector3f vertex, float u, float v - ) { + MatrixStack.Entry matrix, VertexConsumer vertexConsumer, Vector3f vertex, float u, float v, + int color) { vertexConsumer.vertex(matrix, vertex.x(), vertex.y(), vertex.z()) - .color(Colors.WHITE) + .color(color) .texture(u, v) .overlay(OverlayTexture.DEFAULT_UV) .light(LightmapTextureManager.MAX_LIGHT_COORDINATE) diff --git a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java index 893fe57..4ba3597 100644 --- a/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java +++ b/src/main/java/dev/hephaestus/glowcase/packet/C2SEditSpriteBlock.java @@ -11,18 +11,19 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; -public record C2SEditSpriteBlock(BlockPos pos, TextBlockEntity.ZOffset offset, int rotation, String sprite) implements C2SEditBlockEntity { +public record C2SEditSpriteBlock(BlockPos pos, String sprite, int rotation, TextBlockEntity.ZOffset offset, int color) implements C2SEditBlockEntity { public static final Id ID = new Id<>(Glowcase.id("channel.sprite.save")); public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( BlockPos.PACKET_CODEC, C2SEditSpriteBlock::pos, - PacketCodecs.INTEGER.xmap(index -> TextBlockEntity.ZOffset.values()[index], TextBlockEntity.ZOffset::ordinal), C2SEditSpriteBlock::offset, - PacketCodecs.INTEGER, C2SEditSpriteBlock::rotation, PacketCodecs.STRING, C2SEditSpriteBlock::sprite, + PacketCodecs.INTEGER, C2SEditSpriteBlock::rotation, + PacketCodecs.INTEGER.xmap(index -> TextBlockEntity.ZOffset.values()[index], TextBlockEntity.ZOffset::ordinal), C2SEditSpriteBlock::offset, + PacketCodecs.INTEGER, C2SEditSpriteBlock::color, C2SEditSpriteBlock::new ); public static C2SEditSpriteBlock of(SpriteBlockEntity be) { - return new C2SEditSpriteBlock(be.getPos(), be.zOffset, be.rotation, be.sprite); + return new C2SEditSpriteBlock(be.getPos(), be.sprite, be.rotation, be.zOffset, be.color); } @Override @@ -34,9 +35,10 @@ public Id getId() { public void receive(ServerWorld world, BlockEntity blockEntity) { if (!(blockEntity instanceof SpriteBlockEntity be)) return; - be.zOffset = this.offset(); - be.rotation = this.rotation(); be.setSprite(this.sprite()); + be.rotation = this.rotation(); + be.zOffset = this.offset(); + be.color = this.color(); be.markDirty(); be.dispatch(); From a3c53e0e78b509e4676a4778e728c9c22294b2eb Mon Sep 17 00:00:00 2001 From: Chai <7232280+Chailotl@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:23:54 -0400 Subject: [PATCH 12/12] Fixed padding issue with the text block hex color input --- .../glowcase/client/gui/screen/ingame/TextBlockEditScreen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ae97861..05af351 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 @@ -89,7 +89,7 @@ public void init() { }).dimensions(120 + innerPadding, 20 + innerPadding, 160, 20).build(); this.colorEntryWidget = new TextFieldWidget(this.client.textRenderer, 280 + innerPadding * 2, 0, 50, 20, Text.empty()); - this.colorEntryWidget.setText("#" + Integer.toHexString(this.textBlockEntity.color & 0x00FFFFFF)); + this.colorEntryWidget.setText("#" + String.format("%1$06X", this.textBlockEntity.color & 0x00FFFFFF)); this.colorEntryWidget.setChangedListener(string -> { TextColor.parse(this.colorEntryWidget.getText()).ifSuccess(color -> { this.textBlockEntity.color = color == null ? 0xFFFFFFFF : color.getRgb() | 0xFF000000;