Skip to content

Commit

Permalink
Entity Display Block
Browse files Browse the repository at this point in the history
  • Loading branch information
Superkat32 committed Nov 26, 2024
1 parent 4ce8414 commit b6f6cc9
Show file tree
Hide file tree
Showing 16 changed files with 573 additions and 36 deletions.
23 changes: 7 additions & 16 deletions src/main/java/dev/hephaestus/glowcase/Glowcase.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,8 @@

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import dev.hephaestus.glowcase.block.HyperlinkBlock;
import dev.hephaestus.glowcase.block.ItemAcceptorBlock;
import dev.hephaestus.glowcase.block.ItemDisplayBlock;
import dev.hephaestus.glowcase.block.OutlineBlock;
import dev.hephaestus.glowcase.block.ParticleDisplayBlock;
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.ItemAcceptorBlockEntity;
import dev.hephaestus.glowcase.block.entity.ItemDisplayBlockEntity;
import dev.hephaestus.glowcase.block.entity.OutlineBlockEntity;
import dev.hephaestus.glowcase.block.entity.ParticleDisplayBlockEntity;
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.block.*;
import dev.hephaestus.glowcase.block.entity.*;
import dev.hephaestus.glowcase.compat.PolydexCompatibility;
import dev.hephaestus.glowcase.item.LockItem;
import net.fabricmc.api.ModInitializer;
Expand Down Expand Up @@ -79,6 +65,10 @@ public class Glowcase implements ModInitializer {

public static final Supplier<Item> LOCK_ITEM = registerItem("lock", () -> new LockItem(new Item.Settings()));

public static final Supplier<EntityDisplayBlock> ENTITY_DISPLAY_BLOCK = registerBlock("entity_display_block", EntityDisplayBlock::new);
public static final Supplier<BlockItem> ENTITY_DISPLAY_BLOCK_ITEM = registerItem("entity_display_block", () -> new BlockItem(ENTITY_DISPLAY_BLOCK.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<EntityDisplayBlockEntity>> ENTITY_DISPLAY_BLOCK_ENTITY = registerBlockEntity("entity_display_block", () -> BlockEntityType.Builder.create(EntityDisplayBlockEntity::new, ENTITY_DISPLAY_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 @@ -87,6 +77,7 @@ public class Glowcase implements ModInitializer {
entries.add(SPRITE_BLOCK_ITEM.get());
entries.add(OUTLINE_BLOCK_ITEM.get());
entries.add(PARTICLE_DISPLAY_ITEM.get());
entries.add(ENTITY_DISPLAY_BLOCK_ITEM.get());
entries.add(ITEM_DISPLAY_BLOCK_ITEM.get());
entries.add(ITEM_ACCEPTOR_BLOCK_ITEM.get());
entries.add(HYPERLINK_BLOCK_ITEM.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@ public void openParticleDisplayBlockEditScreen(BlockPos pos) {
public void openItemAcceptorBlockEditScreen(BlockPos pos) {
//No-op
}

public void openEntityDisplayBlockEditScreen(BlockPos pos) {
//No-op
}
}
11 changes: 3 additions & 8 deletions src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
package dev.hephaestus.glowcase;

import dev.hephaestus.glowcase.packet.C2SEditHyperlinkBlock;
import dev.hephaestus.glowcase.packet.C2SEditItemAcceptorBlock;
import dev.hephaestus.glowcase.packet.C2SEditItemDisplayBlock;
import dev.hephaestus.glowcase.packet.C2SEditOutlineBlock;
import dev.hephaestus.glowcase.packet.C2SEditParticleDisplayBlock;
import dev.hephaestus.glowcase.packet.C2SEditPopupBlock;
import dev.hephaestus.glowcase.packet.C2SEditSpriteBlock;
import dev.hephaestus.glowcase.packet.C2SEditTextBlock;
import dev.hephaestus.glowcase.packet.*;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;

Expand All @@ -21,6 +14,7 @@ public static void init() {
PayloadTypeRegistry.playC2S().register(C2SEditOutlineBlock.ID, C2SEditOutlineBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditParticleDisplayBlock.ID, C2SEditParticleDisplayBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditItemAcceptorBlock.ID, C2SEditItemAcceptorBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditEntityDisplayBlock.ID, C2SEditEntityDisplayBlock.PACKET_CODEC);

ServerPlayNetworking.registerGlobalReceiver(C2SEditHyperlinkBlock.ID, C2SEditHyperlinkBlock::receive);
ServerPlayNetworking.registerGlobalReceiver(C2SEditItemDisplayBlock.ID, C2SEditItemDisplayBlock::receive);
Expand All @@ -30,5 +24,6 @@ public static void init() {
ServerPlayNetworking.registerGlobalReceiver(C2SEditOutlineBlock.ID, C2SEditOutlineBlock::receive);
ServerPlayNetworking.registerGlobalReceiver(C2SEditParticleDisplayBlock.ID, C2SEditParticleDisplayBlock::receive);
ServerPlayNetworking.registerGlobalReceiver(C2SEditItemAcceptorBlock.ID, C2SEditItemAcceptorBlock::receive);
ServerPlayNetworking.registerGlobalReceiver(C2SEditEntityDisplayBlock.ID, C2SEditEntityDisplayBlock::receive);
}
}
115 changes: 115 additions & 0 deletions src/main/java/dev/hephaestus/glowcase/block/EntityDisplayBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package dev.hephaestus.glowcase.block;

import dev.hephaestus.glowcase.Glowcase;
import dev.hephaestus.glowcase.block.entity.EntityDisplayBlockEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
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.SpawnEggItem;
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.ActionResult;
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.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;

import java.util.List;

public class EntityDisplayBlock extends GlowcaseBlock implements BlockEntityProvider {
private static final VoxelShape OUTLINE = VoxelShapes.cuboid(0.25, 0.25, 0.25, 0.75, 0.75, 0.75);

public EntityDisplayBlock() {
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) ((ctx.getPlayerYaw()) * 16.0F / 360.0F) + 0.5D) & 15);
}

@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return OUTLINE;
}

@Override
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
if (!(world.getBlockEntity(pos) instanceof EntityDisplayBlockEntity be)) return ActionResult.CONSUME;

if (be.canGiveTo(player)) {
if (!world.isClient) be.giveTo(player);
return ActionResult.SUCCESS;
}

return ActionResult.CONSUME;
}

@Override
protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!(world.getBlockEntity(pos) instanceof EntityDisplayBlockEntity be)) return ItemActionResult.CONSUME;

if (canEditGlowcase(player, pos)) {
boolean holdingGlowcaseItem = stack.isIn(Glowcase.ITEM_TAG);
boolean holdingSameAsDisplay = ItemStack.areItemsEqual(be.getDisplayedStack(), stack);
boolean isSpawnEgg = stack.getItem() instanceof SpawnEggItem;

if (!be.hasItem() && isSpawnEgg) {
if (!world.isClient) be.setStack(stack);
return ItemActionResult.SUCCESS;
} else if (holdingSameAsDisplay) {
if (world.isClient) Glowcase.proxy.openEntityDisplayBlockEditScreen(pos);
return ItemActionResult.SUCCESS;
} else if (holdingGlowcaseItem) {
if (!world.isClient) be.setStack(ItemStack.EMPTY);
return ItemActionResult.SUCCESS;
}
}

return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}

@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new EntityDisplayBlockEntity(pos, state);
}

@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
return checkType(type, Glowcase.ENTITY_DISPLAY_BLOCK_ENTITY.get(), EntityDisplayBlockEntity::tick);
}

@Override
public void appendTooltip(ItemStack itemStack, Item.TooltipContext context, List<Text> tooltip, TooltipType options) {
tooltip.add(Text.translatable("block.glowcase.entity_display_block.tooltip.0").formatted(Formatting.GRAY));
tooltip.add(Text.translatable("block.glowcase.entity_display_block.tooltip.1").formatted(Formatting.DARK_GRAY));
tooltip.add(Text.translatable("block.glowcase.entity_display_block.tooltip.2").formatted(Formatting.DARK_GRAY));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package dev.hephaestus.glowcase.block.entity;

import dev.hephaestus.glowcase.Glowcase;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.SpawnEggItem;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec2f;
import net.minecraft.world.World;

public class EntityDisplayBlockEntity extends ItemDisplayBlockEntity {

private Entity displayEntity = null;

public boolean tickEntity = false;
public float displayScale = 0.5f;
public boolean shouldEditScale = true;

public EntityDisplayBlockEntity(BlockPos pos, BlockState state) {
super(Glowcase.ENTITY_DISPLAY_BLOCK_ENTITY.get(), pos, state);
}

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

tag.putBoolean("tick_entity", this.tickEntity);
tag.putFloat("display_scale", this.displayScale);
tag.putBoolean("scale_edited", this.shouldEditScale);
}

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

this.tickEntity = tag.getBoolean("tick_entity");
this.displayScale = tag.getFloat("display_scale");
this.shouldEditScale = tag.getBoolean("scale_edited");
}

@Override
public void setStack(ItemStack stack) {
super.setStack(stack);
this.setShouldEditScale(true);
this.clearDisplayEntity();
this.markDirty();
}

public void setShouldEditScale(boolean shouldEditScale) {
this.shouldEditScale = shouldEditScale;
this.markDirty();
}

private void clearDisplayEntity() {
this.displayEntity = null;
}

public Entity getDisplayEntity() {
if (this.displayEntity == null && this.world != null && this.stack.getItem() instanceof SpawnEggItem eggItem) {
this.displayEntity = eggItem.getEntityType(this.stack).create(this.world);
if(shouldEditScale && this.displayEntity != null) {
//make the default scale of the entity the same size as the block,
//but only if the player hasn't edited the scale value themselves
float calcScale = displayEntity.getHeight() >= displayEntity.getWidth() ? 1F / displayEntity.getHeight() : 0.5F;
float roundedScale = (float) Math.round(calcScale / 0.125f) * 0.125f;
if(Math.abs(roundedScale) > 3) {
roundedScale = 0.5f; //just in case
}
this.displayScale = roundedScale;
}
}

return this.displayEntity;
}

public static Vec2f getPitchAndYaw(Entity camera, EntityDisplayBlockEntity entityDisplay, float delta) {
BlockPos pos = entityDisplay.getPos();
float displayScale = entityDisplay.displayScale;
float displayedEntityHeight = entityDisplay.displayEntity == null ? 0 : entityDisplay.displayEntity.getHeight();
double d = pos.getX() - camera.getLerpedPos(delta).x + 0.5;
double e = pos.getY() + (displayScale * displayedEntityHeight - 0.5) - camera.getEyeY() + 0.5;
double f = pos.getZ() - camera.getLerpedPos(delta).z + 0.5;
double g = MathHelper.sqrt((float) (d * d + f * f));

float pitch = (float) ((-MathHelper.atan2(e, g)));
float yaw = (float) (-MathHelper.atan2(f, d) + Math.PI / 2);

return new Vec2f(pitch, yaw);
}

public static void tick(World world, BlockPos blockPos, BlockState state, EntityDisplayBlockEntity blockEntity) {
if(blockEntity.getDisplayEntity() != null) {
++blockEntity.displayEntity.age;
// if(blockEntity.tickEntity) {
// blockEntity.displayEntity.tick();
// }
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dev.hephaestus.glowcase.Glowcase;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
Expand All @@ -20,13 +21,14 @@
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec2f;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

public class ItemDisplayBlockEntity extends BlockEntity implements Inventory {
private ItemStack stack = ItemStack.EMPTY;
protected ItemStack stack = ItemStack.EMPTY;

public RotationType rotationType = RotationType.TRACKING;
public GivesItem givesItem = GivesItem.YES;
Expand All @@ -36,8 +38,12 @@ public class ItemDisplayBlockEntity extends BlockEntity implements Inventory {
public float yaw;
public Set<UUID> givenTo = new HashSet<>();

public ItemDisplayBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}

public ItemDisplayBlockEntity(BlockPos pos, BlockState state) {
super(Glowcase.ITEM_DISPLAY_BLOCK_ENTITY.get(), pos, state);
this(Glowcase.ITEM_DISPLAY_BLOCK_ENTITY.get(), pos, state);
}

@Override
Expand Down Expand Up @@ -202,6 +208,10 @@ public static Vec2f getPitchAndYaw(Entity camera, BlockPos pos, float delta) {
return new Vec2f(pitch, yaw);
}

public static void tick(World world, BlockPos blockPos, BlockState state, ItemDisplayBlockEntity blockEntity) {
//does nothing right now
}

public enum RotationType {
LOCKED, TRACKING, HORIZONTAL, BILLBOARD
}
Expand Down
11 changes: 2 additions & 9 deletions src/main/java/dev/hephaestus/glowcase/client/GlowcaseClient.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
package dev.hephaestus.glowcase.client;

import dev.hephaestus.glowcase.Glowcase;
import dev.hephaestus.glowcase.client.render.block.entity.BakedBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.HyperlinkBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.ItemAcceptorBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.ItemDisplayBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.OutlineBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.ParticleDisplayBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.PopupBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.SpriteBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.TextBlockEntityRenderer;
import dev.hephaestus.glowcase.client.render.block.entity.*;
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 @@ -28,6 +20,7 @@ public void onInitializeClient() {
BlockEntityRendererFactories.register(Glowcase.OUTLINE_BLOCK_ENTITY.get(), OutlineBlockEntityRenderer::new);
BlockEntityRendererFactories.register(Glowcase.PARTICLE_DISPLAY_BLOCK_ENTITY.get(), ParticleDisplayBlockEntityRenderer::new);
BlockEntityRendererFactories.register(Glowcase.ITEM_ACCEPTOR_BLOCK_ENTITY.get(), ItemAcceptorBlockEntityRenderer::new);
BlockEntityRendererFactories.register(Glowcase.ENTITY_DISPLAY_BLOCK_ENTITY.get(), EntityDisplayBlockEntityRenderer::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 @@ -97,4 +97,12 @@ public void openItemAcceptorBlockEditScreen(BlockPos pos) {
MinecraftClient.getInstance().setScreen(new ItemAcceptorBlockEditScreen(be));
}
}

@Override
public void openEntityDisplayBlockEditScreen(BlockPos pos) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.world != null && client.world.getBlockEntity(pos) instanceof EntityDisplayBlockEntity be) {
MinecraftClient.getInstance().setScreen(new EntityDisplayEditScreen(be));
}
}
}
Loading

0 comments on commit b6f6cc9

Please sign in to comment.