Skip to content

Commit

Permalink
Merge pull request #47 from Chailotl/sprite-block
Browse files Browse the repository at this point in the history
Added the sprite block
  • Loading branch information
sisby-folk authored Aug 31, 2024
2 parents 0df37fc + 5a2adf1 commit a2b9856
Show file tree
Hide file tree
Showing 35 changed files with 391 additions and 7 deletions.
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

0 comments on commit a2b9856

Please sign in to comment.