abstractify, add support for redstone/luminance

This commit is contained in:
Meredith Espinosa 2019-06-19 13:32:58 -07:00
parent 27fd865f79
commit 9b560e0af7
6 changed files with 265 additions and 116 deletions

View File

@ -5,27 +5,19 @@ import net.fabricmc.fabric.api.block.FabricBlockSettings;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.EntityContext; import net.minecraft.entity.EntityContext;
import net.minecraft.entity.ItemEntity; import net.minecraft.item.*;
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.state.StateFactory; import net.minecraft.state.StateFactory;
import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.DirectionProperty;
import net.minecraft.state.property.Properties; 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.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import javax.annotation.Nullable; 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 DirectionProperty FACING = Properties.HORIZONTAL_FACING;
public static final VoxelShape BASE = VoxelShapes.cuboid(0f, 0f, 0f, 1f, 0.5f, 1f); 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() { public SlopeTestBlock() {
super(FabricBlockSettings.of(Material.WOOD).build()); 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 @Override
protected void appendProperties(StateFactory.Builder<Block, BlockState> builder) { protected void appendProperties(StateFactory.Builder<Block, BlockState> builder) {
builder.add(FACING); builder.add(FACING, LIGHT, REDSTONE);
} }
@Nullable @Nullable
@ -56,54 +48,6 @@ public class SlopeTestBlock extends Block implements BlockEntityProvider {
return getDefaultState().with(FACING, ctx.getPlayerFacing()); 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 @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext ctx) { public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext ctx) {
Direction dir = state.get(FACING); Direction dir = state.get(FACING);

View File

@ -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();
}
}

View File

@ -11,62 +11,10 @@ import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.math.Direction;
public class SlopeTestEntity extends BlockEntity implements BlockEntityClientSerializable, RenderAttachmentBlockEntity { public class SlopeTestEntity extends TemplateBlockEntity {
private BlockState renderedState = Blocks.AIR.getDefaultState();
public SlopeTestEntity() { 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;
} }
} }

View File

@ -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();
}
}

View File

@ -3,6 +3,7 @@ package io.github.cottonmc.slopetest.model;
import java.util.HashMap; import java.util.HashMap;
import io.github.cottonmc.slopetest.SlopeTest; 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.ModelProviderContext;
import net.fabricmc.fabric.api.client.model.ModelProviderException; import net.fabricmc.fabric.api.client.model.ModelProviderException;
import net.fabricmc.fabric.api.client.model.ModelVariantProvider; 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.block.BlockModels;
import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier; import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
public class SlopeModelVariantProvider implements ModelVariantProvider { 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(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 @Override

View File

@ -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);
}