Skip to content

Commit

Permalink
Merge pull request #56 from Chailotl/item-acceptor-block
Browse files Browse the repository at this point in the history
Added the item acceptor block
  • Loading branch information
sisby-folk authored Nov 18, 2024
2 parents ad71496 + 788dd8e commit 47fd06d
Show file tree
Hide file tree
Showing 23 changed files with 665 additions and 3 deletions.
8 changes: 7 additions & 1 deletion src/main/java/dev/hephaestus/glowcase/Glowcase.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
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;
Expand Down Expand Up @@ -55,7 +57,6 @@ public class Glowcase implements ModInitializer {
public static final Supplier<BlockItem> PARTICLE_DISPLAY_ITEM = registerItem("particle_display", () -> new BlockItem(PARTICLE_DISPLAY.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<ParticleDisplayBlockEntity>> PARTICLE_DISPLAY_BLOCK_ENTITY = registerBlockEntity("particle_display", () -> BlockEntityType.Builder.create(ParticleDisplayBlockEntity::new, PARTICLE_DISPLAY.get()).build(null));


public static final Supplier<TextBlock> TEXT_BLOCK = registerBlock("text_block", TextBlock::new);
public static final Supplier<BlockItem> TEXT_BLOCK_ITEM = registerItem("text_block", () -> new BlockItem(TEXT_BLOCK.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<TextBlockEntity>> TEXT_BLOCK_ENTITY = registerBlockEntity("text_block", () -> BlockEntityType.Builder.create(TextBlockEntity::new, TEXT_BLOCK.get()).build(null));
Expand All @@ -72,6 +73,10 @@ public class Glowcase implements ModInitializer {
public static final Supplier<BlockItem> OUTLINE_BLOCK_ITEM = registerItem("outline_block", () -> new BlockItem(OUTLINE_BLOCK.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<OutlineBlockEntity>> OUTLINE_BLOCK_ENTITY = registerBlockEntity("outline_block", () -> BlockEntityType.Builder.create(OutlineBlockEntity::new, OUTLINE_BLOCK.get()).build(null));

public static final Supplier<ItemAcceptorBlock> ITEM_ACCEPTOR_BLOCK = registerBlock("item_acceptor_block", ItemAcceptorBlock::new);
public static final Supplier<BlockItem> ITEM_ACCEPTOR_BLOCK_ITEM = registerItem("item_acceptor_block", () -> new BlockItem(ITEM_ACCEPTOR_BLOCK.get(), new Item.Settings()));
public static final Supplier<BlockEntityType<ItemAcceptorBlockEntity>> ITEM_ACCEPTOR_BLOCK_ENTITY = registerBlockEntity("item_acceptor_block", () -> BlockEntityType.Builder.create(ItemAcceptorBlockEntity::new, ITEM_ACCEPTOR_BLOCK.get()).build(null));

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

public static final Supplier<ItemGroup> ITEM_GROUP = registerItemGroup("items", () -> FabricItemGroup.builder()
Expand All @@ -83,6 +88,7 @@ public class Glowcase implements ModInitializer {
entries.add(OUTLINE_BLOCK_ITEM.get());
entries.add(PARTICLE_DISPLAY_ITEM.get());
entries.add(ITEM_DISPLAY_BLOCK_ITEM.get());
entries.add(ITEM_ACCEPTOR_BLOCK_ITEM.get());
entries.add(HYPERLINK_BLOCK_ITEM.get());
entries.add(POPUP_BLOCK_ITEM.get());
entries.add(LOCK_ITEM.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ public void openOutlineBlockEditScreen(BlockPos pos) {
public void openParticleDisplayBlockEditScreen(BlockPos pos) {
//No-op
}

public void openItemAcceptorBlockEditScreen(BlockPos pos) {
//No-op
}
}
3 changes: 3 additions & 0 deletions src/main/java/dev/hephaestus/glowcase/GlowcaseNetworking.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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;
Expand All @@ -19,6 +20,7 @@ public static void init() {
PayloadTypeRegistry.playC2S().register(C2SEditSpriteBlock.ID, C2SEditSpriteBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditOutlineBlock.ID, C2SEditOutlineBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditParticleDisplayBlock.ID, C2SEditParticleDisplayBlock.PACKET_CODEC);
PayloadTypeRegistry.playC2S().register(C2SEditItemAcceptorBlock.ID, C2SEditItemAcceptorBlock.PACKET_CODEC);

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

import dev.hephaestus.glowcase.Glowcase;
import dev.hephaestus.glowcase.block.entity.ItemAcceptorBlockEntity;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.ChestBlockEntity;
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.inventory.Inventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.DirectionProperty;
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.Direction;
import net.minecraft.util.math.random.Random;
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 ItemAcceptorBlock extends GlowcaseBlock implements BlockEntityProvider {
private static final VoxelShape OUTLINE = VoxelShapes.cuboid(0, 0, 0, 1, 1, 1);
public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING;
public static final BooleanProperty POWERED = Properties.POWERED;

public ItemAcceptorBlock() {
super();
this.setDefaultState(this.getDefaultState().with(FACING, Direction.NORTH).with(POWERED, false));
}

@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(FACING, POWERED);
}

@Override
public BlockState getPlacementState(ItemPlacementContext ctx) {
Direction direction = ctx.getSide().getOpposite();
return this.getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing().getOpposite());
}

@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 ItemAcceptorBlockEntity be) {
blockEntityTag.applyToBlockEntity(be, world.getRegistryManager());
}

Glowcase.proxy.openItemAcceptorBlockEditScreen(pos);
}
}

@Override
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
if (!(world.getBlockEntity(pos) instanceof ItemAcceptorBlockEntity be)) return ActionResult.CONSUME;
if (canEditGlowcase(player, pos)) {
if (world.isClient) {
Glowcase.proxy.openItemAcceptorBlockEditScreen(be.getPos());
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}

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

if (!be.isItemAccepted(stack)) {
return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}

if (world.getBlockTickScheduler().isQueued(pos, this) || state.get(POWERED)) {
return ItemActionResult.SKIP_DEFAULT_BLOCK_INTERACTION;
}

if (!world.isClient()) {
// Remove items
ItemStack newStack = stack.copyWithCount(be.count);
stack.decrementUnlessCreative(be.count, player);

// Attempt to insert items
if (getInventoryAt(world, pos.offset(getOutputDirection(world, pos, state))) instanceof Inventory inventory) {
addToFirstFreeSlot(inventory, newStack);
}

// Schedule redstone pulse
world.scheduleBlockTick(pos, this, 2);
}
return ItemActionResult.SUCCESS;
}

private static Inventory getInventoryAt(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
Block block = state.getBlock();

if (block instanceof InventoryProvider inventoryProvider) {
return inventoryProvider.getInventory(state, world, pos);
} else if (state.hasBlockEntity() && world.getBlockEntity(pos) instanceof Inventory inventory) {
if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock chestBlock) {
return ChestBlock.getInventory(chestBlock, state, world, pos, true);
}

return inventory;
}

return null;
}

private ItemStack addToFirstFreeSlot(Inventory inventory, ItemStack stack) {
int i = inventory.getMaxCount(stack);

for (int j = 0; j < inventory.size(); j++) {
ItemStack itemStack = inventory.getStack(j);
if (itemStack.isEmpty() || ItemStack.areItemsAndComponentsEqual(stack, itemStack)) {
int k = Math.min(stack.getCount(), i - itemStack.getCount());
if (k > 0) {
if (itemStack.isEmpty()) {
inventory.setStack(j, stack.split(k));
} else {
stack.decrement(k);
itemStack.increment(k);
}
}

if (stack.isEmpty()) {
break;
}
}
}

return stack;
}

@Override
protected void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
if (state.get(POWERED)) {
world.setBlockState(pos, state.with(POWERED, false), Block.NOTIFY_LISTENERS);
} else {
world.setBlockState(pos, state.with(POWERED, true), Block.NOTIFY_LISTENERS);
world.scheduleBlockTick(pos, this, 4);
}

this.updateNeighbors(world, pos, state);
}

protected void updateNeighbors(World world, BlockPos pos, BlockState state) {
Direction direction = getOutputDirection(world, pos, state);
BlockPos blockPos = pos.offset(direction);
world.updateNeighbor(blockPos, this, pos);
world.updateNeighborsExcept(blockPos, this, direction.getOpposite());
}

@Override
protected boolean emitsRedstonePower(BlockState state) {
return true;
}

@Override
protected int getStrongRedstonePower(BlockState state, BlockView world, BlockPos pos, Direction direction) {
return 0;
}

@Override
protected int getWeakRedstonePower(BlockState state, BlockView world, BlockPos pos, Direction direction) {
return state.get(POWERED) && getOutputDirection(world, pos, state) == direction.getOpposite() ? 15 : 0;
}

@Override
protected void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (!state.isOf(newState.getBlock())) {
if (!world.isClient && state.get(POWERED) && world.getBlockTickScheduler().isQueued(pos, this)) {
this.updateNeighbors(world, pos, state.with(POWERED, false));
}
}
}

public Direction getOutputDirection(BlockView world, BlockPos pos, BlockState state) {
if (world.getBlockEntity(pos) instanceof ItemAcceptorBlockEntity blockEntity) {
return switch (blockEntity.outputDirection) {
case BOTTOM -> Direction.DOWN;
case BACK -> state.get(FACING).getOpposite();
case TOP -> Direction.UP;
};
}

return state.get(FACING).getOpposite();
}

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

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

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

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

0 comments on commit 47fd06d

Please sign in to comment.