diff --git a/src/main/java/io/github/cottonmc/slopetest/block/SlopeTestBlock.java b/src/main/java/io/github/cottonmc/slopetest/block/SlopeTestBlock.java index b4960ad..ba8d5cc 100644 --- a/src/main/java/io/github/cottonmc/slopetest/block/SlopeTestBlock.java +++ b/src/main/java/io/github/cottonmc/slopetest/block/SlopeTestBlock.java @@ -5,27 +5,19 @@ import net.fabricmc.fabric.api.block.FabricBlockSettings; import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.EntityContext; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.BlockItem; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemUsageContext; +import net.minecraft.item.*; import net.minecraft.state.StateFactory; import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.Properties; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; -import net.minecraft.world.World; import javax.annotation.Nullable; -public class SlopeTestBlock extends Block implements BlockEntityProvider { +public class SlopeTestBlock extends TemplateBlock { public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; public static final VoxelShape BASE = VoxelShapes.cuboid(0f, 0f, 0f, 1f, 0.5f, 1f); @@ -36,12 +28,12 @@ public class SlopeTestBlock extends Block implements BlockEntityProvider { public SlopeTestBlock() { super(FabricBlockSettings.of(Material.WOOD).build()); - this.setDefaultState(this.getStateFactory().getDefaultState().with(FACING, Direction.NORTH)); + this.setDefaultState(this.getStateFactory().getDefaultState().with(FACING, Direction.NORTH).with(LIGHT, 0).with(REDSTONE, false)); } @Override protected void appendProperties(StateFactory.Builder builder) { - builder.add(FACING); + builder.add(FACING, LIGHT, REDSTONE); } @Nullable @@ -56,54 +48,6 @@ public class SlopeTestBlock extends Block implements BlockEntityProvider { return getDefaultState().with(FACING, ctx.getPlayerFacing()); } - @Override - public boolean activate(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { - if (world.isClient || !(world.getBlockEntity(pos) instanceof SlopeTestEntity)) return true; - ItemStack stack = player.getStackInHand(hand); - if (stack.getItem() instanceof BlockItem) { - Block block = ((BlockItem)stack.getItem()).getBlock(); - ItemPlacementContext ctx = new ItemPlacementContext(new ItemUsageContext(player, hand, hit)); - BlockState placementState = block.getPlacementState(ctx); - if (placementState.getOutlineShape(world, pos) == VoxelShapes.fullCube() && !(block instanceof BlockEntityProvider)) { - SlopeTestEntity be = (SlopeTestEntity) world.getBlockEntity(pos); - if (be.getRenderedState().getBlock() == Blocks.AIR) { - be.setRenderedState(placementState); - if (!player.abilities.creativeMode) stack.decrement(1); - } - } - } - return true; - } - - @Override - public boolean isOpaque(BlockState state) { - return false; - } - - @Override - public boolean isSimpleFullBlock(BlockState state, BlockView view, BlockPos pos) { - return false; - } - -// @Override -// public BlockRenderType getRenderType(BlockState state) { -// return BlockRenderType.INVISIBLE; -// } - - @Override - public void onBlockRemoved(BlockState state, World world, BlockPos pos, BlockState newState, boolean boolean_1) { - BlockEntity be = world.getBlockEntity(pos); - if (be instanceof SlopeTestEntity) { - SlopeTestEntity slope = (SlopeTestEntity)be; - if (slope.getRenderedState().getBlock() != Blocks.AIR) { - ItemStack stack = new ItemStack(slope.getRenderedState().getBlock()); - ItemEntity entity = new ItemEntity(world, pos.getX(), pos.getY(), pos.getZ(), stack); - world.spawnEntity(entity); - } - } - super.onBlockRemoved(state, world, pos, newState, boolean_1); - } - @Override public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext ctx) { Direction dir = state.get(FACING); diff --git a/src/main/java/io/github/cottonmc/slopetest/block/TemplateBlock.java b/src/main/java/io/github/cottonmc/slopetest/block/TemplateBlock.java new file mode 100644 index 0000000..47222d0 --- /dev/null +++ b/src/main/java/io/github/cottonmc/slopetest/block/TemplateBlock.java @@ -0,0 +1,143 @@ +package io.github.cottonmc.slopetest.block; + +import io.github.cottonmc.slopetest.SlopeTest; +import io.github.cottonmc.slopetest.block.entity.TemplateBlockEntity; +import io.github.cottonmc.slopetest.util.StateContainer; +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.*; +import net.minecraft.state.property.BooleanProperty; +import net.minecraft.state.property.IntProperty; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; + +public abstract class TemplateBlock extends Block implements BlockEntityProvider, StateContainer { + public static final IntProperty LIGHT = IntProperty.of("light", 0, 15); + public static final BooleanProperty REDSTONE = BooleanProperty.of("redstone"); + + public TemplateBlock(Settings settings) { + super(settings); + } + + @Override + public boolean activate(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (world.isClient || !(world.getBlockEntity(pos) instanceof TemplateBlockEntity)) return true; + TemplateBlockEntity be = (TemplateBlockEntity) world.getBlockEntity(pos); + ItemStack stack = player.getStackInHand(hand); + if (stack.getItem() instanceof BlockItem) { + Block block = ((BlockItem)stack.getItem()).getBlock(); + if (block == Blocks.REDSTONE_TORCH) { + be.addRedstone(); + if (!player.abilities.creativeMode) stack.decrement(1); + } + ItemPlacementContext ctx = new ItemPlacementContext(new ItemUsageContext(player, hand, hit)); + BlockState placementState = block.getPlacementState(ctx); + if (placementState.getOutlineShape(world, pos) == VoxelShapes.fullCube() && !(block instanceof BlockEntityProvider)) { + if (be.getRenderedState().getBlock() == Blocks.AIR) { + be.setRenderedState(placementState); + if (!player.abilities.creativeMode) stack.decrement(1); + } + } + } else if (stack.getItem() == Items.GLOWSTONE_DUST) { + be.addGlowstone(); + if (!player.abilities.creativeMode) stack.decrement(1); + } + return true; + } + + @Override + public boolean isOpaque(BlockState state) { + return false; + } + + @Override + public boolean isSimpleFullBlock(BlockState state, BlockView view, BlockPos pos) { + return false; + } + + @Override + public void onBlockRemoved(BlockState state, World world, BlockPos pos, BlockState newState, boolean bool) { + if (newState.getBlock() == SlopeTest.SLOPE) return; + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof TemplateBlockEntity) { + TemplateBlockEntity template = (TemplateBlockEntity)be; + if (template.getRenderedState().getBlock() != Blocks.AIR) { + ItemStack stack = new ItemStack(template.getRenderedState().getBlock()); + ItemEntity entity = new ItemEntity(world, pos.getX(), pos.getY(), pos.getZ(), stack); + world.spawnEntity(entity); + } + if (template.hasRedstone()) { + ItemStack stack = new ItemStack(Items.REDSTONE_TORCH); + ItemEntity entity = new ItemEntity(world, pos.getX(), pos.getY(), pos.getZ(), stack); + world.spawnEntity(entity); + } + if (template.hasGlowstone()) { + ItemStack stack = new ItemStack(Items.GLOWSTONE_DUST); + ItemEntity entity = new ItemEntity(world, pos.getX(), pos.getY(), pos.getZ(), stack); + world.spawnEntity(entity); + } + } + super.onBlockRemoved(state, world, pos, newState, bool); + } + + @Override + public void neighborUpdate(BlockState state, World world, BlockPos pos, Block block, BlockPos posFrom, boolean bool) { + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof TemplateBlockEntity) { + TemplateBlockEntity template = (TemplateBlockEntity)be; + BlockState beState = template.getRenderedState(); + world.setBlockState(pos, state.with(LIGHT, template.hasGlowstone()? 15 : beState.getLuminance()).with(REDSTONE, template.hasRedstone() || beState.emitsRedstonePower())); + } + } + + @Override + public int getLuminance(BlockState state) { + return state.get(LIGHT); + } + + @Override + public boolean emitsRedstonePower(BlockState state) { + return state.get(REDSTONE); + } + + @Override + public int getWeakRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) { + BlockEntity be = view.getBlockEntity(pos); + if (be instanceof TemplateBlockEntity) { + TemplateBlockEntity template = (TemplateBlockEntity)be; + if (template.hasRedstone()) return 15; + BlockState beState = template.getRenderedState(); + return beState.getWeakRedstonePower(view, pos, dir); + } + return 0; + } + + @Override + public int getStrongRedstonePower(BlockState state, BlockView view, BlockPos pos, Direction dir) { + BlockEntity be = view.getBlockEntity(pos); + if (be instanceof TemplateBlockEntity) { + TemplateBlockEntity template = (TemplateBlockEntity)be; + if (template.hasRedstone()) return 15; + BlockState beState = template.getRenderedState(); + return beState.getStrongRedstonePower(view, pos, dir); + } + return 0; + } + + @Override + public BlockState getContainedState(World world, BlockPos pos) { + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof TemplateBlockEntity) return ((TemplateBlockEntity)be).getRenderedState(); + return Blocks.AIR.getDefaultState(); + } +} diff --git a/src/main/java/io/github/cottonmc/slopetest/block/entity/SlopeTestEntity.java b/src/main/java/io/github/cottonmc/slopetest/block/entity/SlopeTestEntity.java index 4a975c5..7568a35 100644 --- a/src/main/java/io/github/cottonmc/slopetest/block/entity/SlopeTestEntity.java +++ b/src/main/java/io/github/cottonmc/slopetest/block/entity/SlopeTestEntity.java @@ -11,62 +11,10 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.world.ClientWorld; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.Direction; -public class SlopeTestEntity extends BlockEntity implements BlockEntityClientSerializable, RenderAttachmentBlockEntity { - private BlockState renderedState = Blocks.AIR.getDefaultState(); - +public class SlopeTestEntity extends TemplateBlockEntity { public SlopeTestEntity() { - super(SlopeTest.SLOPE_ENTITY); + super(SlopeTest.SLOPE_ENTITY, SlopeTest.SLOPE); } - - public BlockState getRenderedState() { - return renderedState; - } - - public void setRenderedState(BlockState state) { - this.renderedState = state; - markDirty(); - } - - @Override - public void fromTag(CompoundTag tag) { - super.fromTag(tag); - renderedState = BlockStateUtil.fromTag(tag); - if (world.isClient) { - ((ClientWorld)world).scheduleBlockRender(pos); - } - } - - @Override - public CompoundTag toTag(CompoundTag tag) { - super.toTag(tag); - BlockStateUtil.toTag(tag, renderedState); - return tag; - } - - @Override - public void fromClientTag(CompoundTag tag) { - fromTag(tag); - } - - @Override - public CompoundTag toClientTag(CompoundTag tag) { - return toTag(tag); - } - - @Override - public void markDirty() { - super.markDirty(); - if (!this.world.isClient) { - for (Object obj : PlayerStream.watching(this).toArray()) { - ServerPlayerEntity player = (ServerPlayerEntity) obj; - player.networkHandler.sendPacket(this.toUpdatePacket()); - } - } - } - - @Override - public BlockState getRenderAttachmentData() { - return renderedState; - } } diff --git a/src/main/java/io/github/cottonmc/slopetest/block/entity/TemplateBlockEntity.java b/src/main/java/io/github/cottonmc/slopetest/block/entity/TemplateBlockEntity.java new file mode 100644 index 0000000..f35a9f0 --- /dev/null +++ b/src/main/java/io/github/cottonmc/slopetest/block/entity/TemplateBlockEntity.java @@ -0,0 +1,102 @@ +package io.github.cottonmc.slopetest.block.entity; + +import io.github.cottonmc.slopetest.util.BlockStateUtil; +import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity; +import net.fabricmc.fabric.api.server.PlayerStream; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.Direction; + +public abstract class TemplateBlockEntity extends BlockEntity implements BlockEntityClientSerializable, RenderAttachmentBlockEntity { + protected BlockState renderedState = Blocks.AIR.getDefaultState(); + protected boolean glowstone = false; + protected boolean redstone = false; + private Block baseBlock; + + public TemplateBlockEntity(BlockEntityType type, Block baseBlock) { + super(type); + this.baseBlock = baseBlock; + } + + public BlockState getRenderedState() { + return renderedState; + } + + public void setRenderedState(BlockState state) { + this.renderedState = state; + markDirty(); + } + + @Override + public void fromTag(CompoundTag tag) { + super.fromTag(tag); + renderedState = BlockStateUtil.fromTag(tag); + glowstone = tag.getBoolean("Glowstone"); + redstone = tag.getBoolean("Redstone"); + if (world != null && world.isClient) { + world.scheduleBlockRender(pos); + } + } + + @Override + public CompoundTag toTag(CompoundTag tag) { + super.toTag(tag); + BlockStateUtil.toTag(tag, renderedState); + tag.putBoolean("Glowstone", glowstone); + tag.putBoolean("Redstone", redstone); + return tag; + } + + @Override + public void fromClientTag(CompoundTag tag) { + fromTag(tag); + } + + @Override + public CompoundTag toClientTag(CompoundTag tag) { + return toTag(tag); + } + + @Override + public void markDirty() { + super.markDirty(); + if (world != null && !world.isClient) { + for (Object obj : PlayerStream.watching(this).toArray()) { + ServerPlayerEntity player = (ServerPlayerEntity) obj; + player.networkHandler.sendPacket(this.toUpdatePacket()); + } + world.updateNeighborsAlways(pos.offset(Direction.UP), baseBlock); + BlockState state = world.getBlockState(pos); + world.updateListeners(pos, state, state, 1); + } + } + + @Override + public BlockState getRenderAttachmentData() { + return renderedState; + } + + public boolean hasGlowstone() { + return glowstone; + } + + public void addGlowstone() { + glowstone = true; + markDirty(); + } + + public boolean hasRedstone() { + return redstone; + } + + public void addRedstone() { + redstone = true; + markDirty(); + } +} diff --git a/src/main/java/io/github/cottonmc/slopetest/model/SlopeModelVariantProvider.java b/src/main/java/io/github/cottonmc/slopetest/model/SlopeModelVariantProvider.java index 0611412..e13f600 100644 --- a/src/main/java/io/github/cottonmc/slopetest/model/SlopeModelVariantProvider.java +++ b/src/main/java/io/github/cottonmc/slopetest/model/SlopeModelVariantProvider.java @@ -3,6 +3,7 @@ package io.github.cottonmc.slopetest.model; import java.util.HashMap; import io.github.cottonmc.slopetest.SlopeTest; +import io.github.cottonmc.slopetest.block.SlopeTestBlock; import net.fabricmc.fabric.api.client.model.ModelProviderContext; import net.fabricmc.fabric.api.client.model.ModelProviderException; import net.fabricmc.fabric.api.client.model.ModelVariantProvider; @@ -10,6 +11,8 @@ import net.minecraft.block.BlockState; import net.minecraft.client.render.block.BlockModels; import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.util.BlockRotation; +import net.minecraft.util.math.Direction; import net.minecraft.util.registry.Registry; public class SlopeModelVariantProvider implements ModelVariantProvider { @@ -25,7 +28,7 @@ public class SlopeModelVariantProvider implements ModelVariantProvider { variants.put(BlockModels.getModelId(state), (SimpleUnbakedModel)() -> new SlopeTestModel(state)); } - variants.put(new ModelIdentifier(Registry.ITEM.getId(SlopeTest.SLOPE.asItem()), "inventory"), (SimpleUnbakedModel)() -> new SlopeTestModel(SlopeTest.SLOPE.getDefaultState())); + variants.put(new ModelIdentifier(Registry.ITEM.getId(SlopeTest.SLOPE.asItem()), "inventory"), (SimpleUnbakedModel)() -> new SlopeTestModel(SlopeTest.SLOPE.getDefaultState().with(SlopeTestBlock.FACING, Direction.SOUTH))); } @Override diff --git a/src/main/java/io/github/cottonmc/slopetest/util/StateContainer.java b/src/main/java/io/github/cottonmc/slopetest/util/StateContainer.java new file mode 100644 index 0000000..dabb4be --- /dev/null +++ b/src/main/java/io/github/cottonmc/slopetest/util/StateContainer.java @@ -0,0 +1,9 @@ +package io.github.cottonmc.slopetest.util; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public interface StateContainer { + BlockState getContainedState(World world, BlockPos pos); +}