Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the sprite block #47

Merged
merged 10 commits into from
Aug 31, 2024
7 changes: 7 additions & 0 deletions src/main/java/dev/hephaestus/glowcase/Glowcase.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import dev.hephaestus.glowcase.block.HyperlinkBlock;
import dev.hephaestus.glowcase.block.ItemDisplayBlock;
import dev.hephaestus.glowcase.block.PopupBlock;
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.PopupBlockEntity;
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;
Expand Down Expand Up @@ -52,6 +54,10 @@ public class Glowcase implements ModInitializer {
public static final Supplier<BlockItem> POPUP_BLOCK_ITEM = registerItem("popup_block", () -> new BlockItem(POPUP_BLOCK.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<PopupBlockEntity>> POPUP_BLOCK_ENTITY = registerBlockEntity("popup_block", () -> BlockEntityType.Builder.create(PopupBlockEntity::new, POPUP_BLOCK.get()).build(null));

public static final Supplier<SpriteBlock> SPRITE_BLOCK = registerBlock("sprite_block", SpriteBlock::new);
public static final Supplier<BlockItem> SPRITE_BLOCK_ITEM = registerItem("sprite_block", () -> new BlockItem(SPRITE_BLOCK.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<SpriteBlockEntity>> SPRITE_BLOCK_ENTITY = registerBlockEntity("sprite_block", () -> BlockEntityType.Builder.create(SpriteBlockEntity::new, SPRITE_BLOCK.get()).build(null));

public static final Supplier<ItemGroup> ITEM_GROUP = registerItemGroup("items", () -> FabricItemGroup.builder()
.displayName(Text.translatable("itemGroup.glowcase.items"))
.icon(() -> new ItemStack(Items.GLOWSTONE))
Expand All @@ -60,6 +66,7 @@ public class Glowcase implements ModInitializer {
entries.add(ITEM_DISPLAY_BLOCK_ITEM.get());
entries.add(TEXT_BLOCK_ITEM.get());
entries.add(POPUP_BLOCK_ITEM.get());
entries.add(SPRITE_BLOCK_ITEM.get());
})
.build()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ public void openPopupBlockEditScreen(BlockPos pos) {
public void openPopupBlockViewScreen(BlockPos pos) {
//No-op
}

public void openSpriteBlockEditScreen(BlockPos pos) {
//No-op
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

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 dev.hephaestus.glowcase.packet.C2SEditPopupBlock;
import dev.hephaestus.glowcase.packet.C2SEditSpriteBlock;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;

Expand All @@ -13,10 +14,12 @@ public static void init() {
PayloadTypeRegistry.playC2S().register(C2SEditItemDisplayBlock.ID, C2SEditItemDisplayBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditTextBlock.ID, C2SEditTextBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditPopupBlock.ID, C2SEditPopupBlock.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(C2SEditPopupBlock.ID, C2SEditPopupBlock::receive);
ServerPlayNetworking.registerGlobalReceiver(C2SEditSpriteBlock.ID, C2SEditSpriteBlock::receive);
}
}
84 changes: 84 additions & 0 deletions src/main/java/dev/hephaestus/glowcase/block/SpriteBlock.java
Original file line number Diff line number Diff line change
@@ -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<Block, BlockState> 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<Text> 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));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
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 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);
}

public void setSprite(String newSprite) {
sprite = newSprite;
markDirty();
dispatch();
}

@Override
public void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) {
super.writeNbt(tag, registryLookup);

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.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"})
@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<ClientPlayPacketListener> toUpdatePacket() {
return BlockEntityUpdateS2CPacket.create(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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 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;
Expand All @@ -20,6 +21,7 @@ public void onInitializeClient() {
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);
BlockEntityRendererFactories.register(Glowcase.SPRITE_BLOCK_ENTITY.get(), SpriteBlockEntityRenderer::new);

WorldRenderEvents.AFTER_TRANSLUCENT.register(BakedBlockEntityRenderer.Manager::render);
InvalidateRenderStateCallback.EVENT.register(BakedBlockEntityRenderer.Manager::reset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
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.SpriteBlockEntity;
import dev.hephaestus.glowcase.block.entity.TextBlockEntity;
import dev.hephaestus.glowcase.client.gui.screen.ingame.*;
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.PopupBlockEditScreen;
import dev.hephaestus.glowcase.client.gui.screen.ingame.PopupBlockViewScreen;
import dev.hephaestus.glowcase.client.gui.screen.ingame.SpriteBlockEditScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ConfirmLinkScreen;
import net.minecraft.util.math.BlockPos;
Expand Down Expand Up @@ -55,4 +61,12 @@ public void openPopupBlockViewScreen(BlockPos pos) {
MinecraftClient.getInstance().setScreen(new PopupBlockViewScreen(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));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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.text.TextColor;
import net.minecraft.util.Identifier;

public class SpriteBlockEditScreen extends GlowcaseScreen {
private final SpriteBlockEntity spriteBlockEntity;

private TextFieldWidget spriteWidget;
private ButtonWidget rotationWidget;
private ButtonWidget zOffsetToggle;
private TextFieldWidget colorEntryWidget;

public SpriteBlockEditScreen(SpriteBlockEntity spriteBlockEntity) {
this.spriteBlockEntity = spriteBlockEntity;
}

@Override
public void init() {
super.init();

if (this.client == null) return;

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.rotationWidget = ButtonWidget.builder(Text.literal("Rotate"), (action) -> {
this.spriteBlockEntity.rotation += 45;
if (this.spriteBlockEntity.rotation >= 360) {
this.spriteBlockEntity.rotation = 0;
}
}).dimensions(width / 2 - 75, height / 2 - 25, 150, 20).build();

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.spriteWidget);
this.addDrawableChild(this.rotationWidget);
this.addDrawableChild(this.zOffsetToggle);
this.addDrawableChild(this.colorEntryWidget);
}

@Override
public void close() {
spriteBlockEntity.setSprite(spriteWidget.getText());
C2SEditSpriteBlock.of(spriteBlockEntity).send();
super.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ 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;
if (hitResult instanceof BlockHitResult && ((BlockHitResult) hitResult).getBlockPos().equals(entity.getPos())) {
float scale = 0.025F;
matrices.scale(scale, scale, scale);
matrices.translate(-context.getTextRenderer().getWidth(entity.getText()) / 2F, -4, 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);
context.getTextRenderer().draw(entity.getText(), 0, 0, 0xFFFFFF, true, matrices.peek().getPositionMatrix(), vertexConsumers, TextLayerType.NORMAL, 0, LightmapTextureManager.MAX_LIGHT_COORDINATE);
Expand Down
Loading