[Feature] Furniture API

This commit is contained in:
Frank 2023-06-10 23:35:39 +02:00
parent 6b87c96839
commit ad74c71c01
15 changed files with 1475 additions and 0 deletions

View file

@ -0,0 +1,51 @@
package org.betterx.bclib.complexmaterials.set.wood;
import org.betterx.bclib.complexmaterials.ComplexMaterial;
import org.betterx.bclib.complexmaterials.WoodenComplexMaterial;
import org.betterx.bclib.complexmaterials.entry.BlockEntry;
import org.betterx.bclib.complexmaterials.entry.SimpleMaterialSlot;
import org.betterx.bclib.furniture.block.BaseBarStool;
import org.betterx.bclib.recipes.BCLRecipeBuilder;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class BarStool extends SimpleMaterialSlot<WoodenComplexMaterial> {
public BarStool() {
super("bar_stool");
}
public static void makeBarStoolRecipe(ResourceLocation id, Block barStool, Block planks) {
BCLRecipeBuilder.crafting(id, barStool)
.setShape("##", "II", "II")
.addMaterial('#', planks)
.addMaterial('I', Items.STICK)
.setGroup("bar_stool")
.setCategory(RecipeCategory.DECORATIONS)
.build();
}
@Override
protected @NotNull Block createBlock(
WoodenComplexMaterial parentMaterial, BlockBehaviour.Properties settings
) {
return new BaseBarStool(parentMaterial.getBlock(WoodSlots.SLAB));
}
@Override
protected void modifyBlockEntry(WoodenComplexMaterial parentMaterial, @NotNull BlockEntry entry) {
entry.setBlockTags(BlockTags.MINEABLE_WITH_AXE);
}
@Override
protected @Nullable void makeRecipe(ComplexMaterial parentMaterial, ResourceLocation id) {
BarStool.makeBarStoolRecipe(id, parentMaterial.getBlock(suffix), parentMaterial.getBlock(WoodSlots.SLAB));
}
}

View file

@ -0,0 +1,51 @@
package org.betterx.bclib.complexmaterials.set.wood;
import org.betterx.bclib.complexmaterials.ComplexMaterial;
import org.betterx.bclib.complexmaterials.WoodenComplexMaterial;
import org.betterx.bclib.complexmaterials.entry.BlockEntry;
import org.betterx.bclib.complexmaterials.entry.SimpleMaterialSlot;
import org.betterx.bclib.furniture.block.BaseChair;
import org.betterx.bclib.recipes.BCLRecipeBuilder;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Chair extends SimpleMaterialSlot<WoodenComplexMaterial> {
public Chair() {
super("chair");
}
public static void makeChairRecipe(ResourceLocation id, Block chair, Block planks) {
BCLRecipeBuilder.crafting(id, chair)
.setShape("I ", "##", "II")
.addMaterial('#', planks)
.addMaterial('I', Items.STICK)
.setGroup("chair")
.setCategory(RecipeCategory.DECORATIONS)
.build();
}
@Override
protected void modifyBlockEntry(WoodenComplexMaterial parentMaterial, @NotNull BlockEntry entry) {
entry.setBlockTags(BlockTags.MINEABLE_WITH_AXE);
}
@Override
protected @NotNull Block createBlock(
WoodenComplexMaterial parentMaterial, BlockBehaviour.Properties settings
) {
return new BaseChair(parentMaterial.getBlock(WoodSlots.SLAB));
}
@Override
protected @Nullable void makeRecipe(ComplexMaterial parentMaterial, ResourceLocation id) {
Chair.makeChairRecipe(id, parentMaterial.getBlock(suffix), parentMaterial.getBlock(WoodSlots.SLAB));
}
}

View file

@ -0,0 +1,51 @@
package org.betterx.bclib.complexmaterials.set.wood;
import org.betterx.bclib.complexmaterials.ComplexMaterial;
import org.betterx.bclib.complexmaterials.WoodenComplexMaterial;
import org.betterx.bclib.complexmaterials.entry.BlockEntry;
import org.betterx.bclib.complexmaterials.entry.SimpleMaterialSlot;
import org.betterx.bclib.furniture.block.BaseTaburet;
import org.betterx.bclib.recipes.BCLRecipeBuilder;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Taburet extends SimpleMaterialSlot<WoodenComplexMaterial> {
public Taburet() {
super("taburet");
}
public static void makeTaburetRecipe(ResourceLocation id, Block taburet, Block planks) {
BCLRecipeBuilder.crafting(id, taburet)
.setShape("##", "II")
.addMaterial('#', planks)
.addMaterial('I', Items.STICK)
.setGroup("taburet")
.setCategory(RecipeCategory.DECORATIONS)
.build();
}
@Override
protected void modifyBlockEntry(WoodenComplexMaterial parentMaterial, @NotNull BlockEntry entry) {
entry.setBlockTags(BlockTags.MINEABLE_WITH_AXE);
}
@Override
protected @NotNull Block createBlock(
WoodenComplexMaterial parentMaterial, BlockBehaviour.Properties settings
) {
return new BaseTaburet(parentMaterial.getBlock(WoodSlots.SLAB));
}
@Override
protected @Nullable void makeRecipe(ComplexMaterial parentMaterial, ResourceLocation id) {
Taburet.makeTaburetRecipe(id, parentMaterial.getBlock(suffix), parentMaterial.getBlock(WoodSlots.SLAB));
}
}

View file

@ -31,6 +31,9 @@ public class WoodSlots {
public static final String WALL_SIGN = Sign.WALL_SUFFFIX; public static final String WALL_SIGN = Sign.WALL_SUFFFIX;
public static final String WALL_HANGING_SIGN = HangingSign.WALL_SUFFFIX; public static final String WALL_HANGING_SIGN = HangingSign.WALL_SUFFFIX;
public static final String SAPLING = AbstractSaplingSlot.SAPLING_SUFFIX; public static final String SAPLING = AbstractSaplingSlot.SAPLING_SUFFIX;
public static final MaterialSlot<WoodenComplexMaterial> TABURET = new Taburet();
public static final MaterialSlot<WoodenComplexMaterial> CHAIR = new Chair();
public static final MaterialSlot<WoodenComplexMaterial> BAR_STOOL = new BarStool();
} }

View file

@ -0,0 +1,152 @@
package org.betterx.bclib.furniture.block;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.furniture.entity.EntityChair;
import org.betterx.bclib.registry.BaseBlockEntities;
import org.betterx.bclib.util.BlocksHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.List;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractChair extends BaseBlockNotFull {
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
private final float height;
public AbstractChair(Block block, int height) {
super(FabricBlockSettings.copyOf(block).noOcclusion());
this.height = (height - 3F) / 16F;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
return this.defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite());
}
@Override
public InteractionResult use(
BlockState state,
Level world,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hit
) {
if (world.isClientSide) {
return InteractionResult.FAIL;
} else {
if (player.isPassenger() || player.isSpectator())
return InteractionResult.FAIL;
Optional<EntityChair> active = getEntity(world, pos);
EntityChair entity;
if (active.isEmpty()) {
entity = createEntity(state, world, pos);
} else {
entity = active.get();
if (entity.isVehicle())
return InteractionResult.FAIL;
}
if (entity != null) {
float yaw = state.getValue(FACING).getOpposite().toYRot();
player.startRiding(entity, true);
player.setYBodyRot(yaw);
player.setYHeadRot(yaw);
return InteractionResult.SUCCESS;
}
return InteractionResult.FAIL;
}
}
@Nullable
private EntityChair createEntity(BlockState state, Level world, BlockPos pos) {
BCLib.LOGGER.info("Creating Chair at " + pos + ", " + state);
EntityChair entity;
double px = pos.getX() + 0.5;
double py = pos.getY() + height;
double pz = pos.getZ() + 0.5;
float yaw = state.getValue(FACING).getOpposite().toYRot();
entity = BaseBlockEntities.CHAIR.create(world);
entity.moveTo(px, py, pz, yaw, 0);
entity.setNoGravity(true);
entity.setSilent(true);
entity.setInvisible(true);
entity.setYHeadRot(yaw);
entity.setYBodyRot(yaw);
if (!world.addFreshEntity(entity)) {
entity = null;
}
return entity;
}
private Optional<EntityChair> getEntity(Level level, BlockPos pos) {
List<EntityChair> list = level.getEntitiesOfClass(
EntityChair.class,
new AABB(pos),
entity -> true
);
if (list.isEmpty()) return Optional.empty();
return Optional.of(list.get(0));
}
@Override
public BlockState rotate(BlockState state, Rotation rotation) {
return BlocksHelper.rotateHorizontal(state, rotation, FACING);
}
@Override
public BlockState mirror(BlockState state, Mirror mirror) {
return BlocksHelper.mirrorHorizontal(state, mirror, FACING);
}
@Override
public void onPlace(BlockState blockState, Level level, BlockPos blockPos, BlockState blockState2, boolean bl) {
super.onPlace(blockState, level, blockPos, blockState2, bl);
BCLib.LOGGER.info("Created at " + blockPos + ", " + blockState + ", " + blockState2);
if (blockState.hasProperty(BaseChair.TOP)) {
if (blockState.getValue(BaseChair.TOP))
return;
}
createEntity(blockState, level, blockPos);
}
@Override
public void onRemove(BlockState blockState, Level level, BlockPos blockPos, BlockState blockState2, boolean bl) {
super.onRemove(blockState, level, blockPos, blockState2, bl);
// Optional<EntityChair> e = getEntity(level, blockPos);
//
// if (e.isPresent()) {
// BCLib.LOGGER.info("Discarding Chair at " + blockPos);
// e.get().discard();
// }
}
}

View file

@ -0,0 +1,21 @@
package org.betterx.bclib.furniture.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class BaseBarStool extends AbstractChair {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12);
public BaseBarStool(Block block) {
super(block, 15);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
}

View file

@ -0,0 +1,117 @@
package org.betterx.bclib.furniture.block;
import org.betterx.bclib.util.BlocksHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.Collections;
import java.util.List;
public class BaseChair extends AbstractChair {
private static final VoxelShape SHAPE_BOTTOM = box(3, 0, 3, 13, 16, 13);
private static final VoxelShape SHAPE_TOP = box(3, 0, 3, 13, 6, 13);
private static final VoxelShape COLLIDER = box(3, 0, 3, 13, 10, 13);
public static final BooleanProperty TOP = BooleanProperty.create("top");
public BaseChair(Block block) {
super(block, 10);
this.registerDefaultState(getStateDefinition().any().setValue(FACING, Direction.NORTH).setValue(TOP, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(FACING, TOP);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return state.getValue(TOP) ? SHAPE_TOP : SHAPE_BOTTOM;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return state.getValue(TOP) ? Shapes.empty() : COLLIDER;
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
if (state.getValue(TOP))
return true;
BlockState up = world.getBlockState(pos.above());
return up.isAir() || (up.getBlock() == this && up.getValue(TOP));
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
if (!world.isClientSide())
BlocksHelper.setWithUpdate(world, pos.above(), state.setValue(TOP, true));
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (state.getValue(TOP)) {
return world.getBlockState(pos.below()).getBlock() == this ? state : Blocks.AIR.defaultBlockState();
} else {
return world.getBlockState(pos.above()).getBlock() == this ? state : Blocks.AIR.defaultBlockState();
}
}
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder builder) {
if (!state.getValue(TOP))
return Collections.singletonList(new ItemStack(this.asItem()));
else
return Collections.emptyList();
}
@Override
public InteractionResult use(
BlockState state,
Level world,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hit
) {
if (state.getValue(TOP)) {
pos = pos.below();
state = world.getBlockState(pos);
}
return super.use(state, world, pos, player, hand, hit);
}
@Override
public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
if (player.isCreative() && state.getValue(TOP) && world.getBlockState(pos.below()).getBlock() == this) {
world.setBlockAndUpdate(pos.below(), Blocks.AIR.defaultBlockState());
}
super.playerWillDestroy(world, pos, state, player);
}
}

View file

@ -0,0 +1,21 @@
package org.betterx.bclib.furniture.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class BaseTaburet extends AbstractChair {
private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 10, 14);
public BaseTaburet(Block block) {
super(block, 9);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
}

View file

@ -0,0 +1,147 @@
package org.betterx.bclib.furniture.entity;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.furniture.block.AbstractChair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.animal.WaterAnimal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import java.util.List;
import org.jetbrains.annotations.Nullable;
public class EntityChair extends Entity {
public EntityChair(EntityType<? extends EntityChair> type, Level world) {
super(type, world);
}
@Override
protected void defineSynchedData() {
}
protected int getMaxPassengers() {
return 1;
}
@Override
public void tick() {
if (this.level().getBlockState(this.blockPosition()).getBlock() instanceof AbstractChair)
localTick();
else {
BCLib.LOGGER.info("Chair Block was deleted -> ejecting");
this.ejectPassengers();
this.discard();
}
}
protected void localTick() {
super.tick();
List<Entity> pushableEntities = this.level().getEntities(
this,
this.getBoundingBox().inflate(0.7f, -0.01f, 0.7f),
EntitySelector.pushableBy(this)
);
if (!pushableEntities.isEmpty()) {
boolean free = !this.level().isClientSide && !(this.getControllingPassenger() instanceof Player);
for (int j = 0; j < pushableEntities.size(); ++j) {
Entity entity = pushableEntities.get(j);
if (entity.hasPassenger(this)) continue;
if (free
&& this.getPassengers().size() < this.getMaxPassengers()
&& !entity.isPassenger()
//&& entity.getBbWidth() < this.getBbWidth()
&& entity instanceof LivingEntity
&& !(entity instanceof WaterAnimal)
&& !(entity instanceof Player)
) {
entity.startRiding(this);
continue;
}
this.push(entity);
}
}
}
@Override
protected void readAdditionalSaveData(CompoundTag compoundTag) {
}
@Override
protected void addAdditionalSaveData(CompoundTag compoundTag) {
}
@Override
public boolean isAlive() {
return !this.isRemoved();
}
@Override
public Packet<ClientGamePacketListener> getAddEntityPacket() {
return new ClientboundAddEntityPacket(this);
}
@Override
protected boolean canAddPassenger(Entity entity) {
return this.getPassengers().size() < this.getMaxPassengers();
}
@Nullable
@Override
public LivingEntity getControllingPassenger() {
for (Entity e : getPassengers()) {
if (e instanceof LivingEntity le) return le;
}
return null;
}
@Override
public void push(Entity entity) {
//Do nothing. Should not be pushable
}
@Override
public double getPassengersRidingOffset() {
return 0.0;
}
@Override
public double getMyRidingOffset() {
return 0.0;
}
@Override
public InteractionResult interact(Player player, InteractionHand interactionHand) {
if (player.isSecondaryUseActive()) {
return InteractionResult.PASS;
}
if (!this.level().isClientSide) {
return player.startRiding(this) ? InteractionResult.CONSUME : InteractionResult.PASS;
}
return InteractionResult.SUCCESS;
}
public static AttributeSupplier getAttributeContainer() {
return AttributeSupplier.builder().build();
}
@Override
public boolean isPickable() {
return !this.isRemoved();
}
}

View file

@ -0,0 +1,24 @@
package org.betterx.bclib.furniture.renderer;
import org.betterx.bclib.furniture.entity.EntityChair;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(value = EnvType.CLIENT)
public class RenderChair extends EntityRenderer<EntityChair> {
private static final ResourceLocation TEXTURE = new ResourceLocation("minecraft:textures/block/stone.png");
public RenderChair(EntityRendererProvider.Context context) {
super(context);
}
@Override
public ResourceLocation getTextureLocation(EntityChair entity) {
return TEXTURE;
}
}

View file

@ -10,13 +10,20 @@ import org.betterx.bclib.blocks.BaseBarrelBlock;
import org.betterx.bclib.blocks.BaseChestBlock; import org.betterx.bclib.blocks.BaseChestBlock;
import org.betterx.bclib.blocks.BaseFurnaceBlock; import org.betterx.bclib.blocks.BaseFurnaceBlock;
import org.betterx.bclib.blocks.signs.BaseSignBlock; import org.betterx.bclib.blocks.signs.BaseSignBlock;
import org.betterx.bclib.furniture.entity.EntityChair;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
public class BaseBlockEntities { public class BaseBlockEntities {
public static final DynamicBlockEntityType<BaseChestBlockEntity> CHEST = registerBlockEntityType(BCLib.makeID( public static final DynamicBlockEntityType<BaseChestBlockEntity> CHEST = registerBlockEntityType(BCLib.makeID(
"chest"), BaseChestBlockEntity::new); "chest"), BaseChestBlockEntity::new);
@ -26,6 +33,22 @@ public class BaseBlockEntities {
public static final DynamicBlockEntityType<BaseFurnaceBlockEntity> FURNACE = registerBlockEntityType(BCLib.makeID( public static final DynamicBlockEntityType<BaseFurnaceBlockEntity> FURNACE = registerBlockEntityType(BCLib.makeID(
"furnace"), BaseFurnaceBlockEntity::new); "furnace"), BaseFurnaceBlockEntity::new);
public static final EntityType<EntityChair> CHAIR = registerEntity(BCLib.makeID("chair"), FabricEntityTypeBuilder
.create(MobCategory.MISC, EntityChair::new)
.dimensions(EntityDimensions.fixed(0.5F, 0.8F))
.fireImmune()
.disableSummon()
.build());
public static <T extends Entity> EntityType<T> registerEntity(
ResourceLocation id,
EntityType<T> entity
) {
Registry.register(BuiltInRegistries.ENTITY_TYPE, id, entity);
return entity;
}
public static <T extends BlockEntity> DynamicBlockEntityType<T> registerBlockEntityType( public static <T extends BlockEntity> DynamicBlockEntityType<T> registerBlockEntityType(
ResourceLocation typeId, ResourceLocation typeId,
BlockEntitySupplier<? extends T> supplier BlockEntitySupplier<? extends T> supplier

View file

@ -1,6 +1,7 @@
package org.betterx.bclib.registry; package org.betterx.bclib.registry;
import org.betterx.bclib.client.render.BaseChestBlockEntityRenderer; import org.betterx.bclib.client.render.BaseChestBlockEntityRenderer;
import org.betterx.bclib.furniture.renderer.RenderChair;
import org.betterx.bclib.items.boat.BoatTypeOverride; import org.betterx.bclib.items.boat.BoatTypeOverride;
import net.minecraft.client.model.BoatModel; import net.minecraft.client.model.BoatModel;
@ -8,11 +9,14 @@ import net.minecraft.client.model.ChestBoatModel;
import net.minecraft.client.model.ChestRaftModel; import net.minecraft.client.model.ChestRaftModel;
import net.minecraft.client.model.RaftModel; import net.minecraft.client.model.RaftModel;
import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.world.entity.EntityType;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public class BaseBlockEntityRenders { public class BaseBlockEntityRenders {
@ -31,5 +35,20 @@ public class BaseBlockEntityRenders {
() -> type.isRaft ? chestRaftModel : chestBoatModel () -> type.isRaft ? chestRaftModel : chestBoatModel
); );
}); });
registerRender(BaseBlockEntities.CHAIR, RenderChair.class);
}
public static void registerRender(EntityType<?> entity, Class<? extends EntityRenderer<?>> renderer) {
EntityRendererRegistry.register(entity, (context) -> {
EntityRenderer render = null;
try {
render = renderer.getConstructor(context.getClass())
.newInstance(context);
} catch (Exception e) {
e.printStackTrace();
}
return render;
});
} }
} }

View file

@ -0,0 +1,162 @@
{
"__comment": "Designed by Paulevs with Cubik Studio - https://cubik.studio",
"parent": "block/block",
"textures": {
"particle": "#texture"
},
"elements": [
{
"__comment": "Box1",
"from": [ 4, 13, 5 ],
"to": [ 12, 15, 11 ],
"faces": {
"down": { "uv": [ 4, 5, 12, 11 ], "texture": "#texture" },
"up": { "uv": [ 4, 5, 12, 11 ], "texture": "#texture" },
"north": { "uv": [ 4, 1, 12, 3 ], "texture": "#texture" },
"south": { "uv": [ 4, 1, 12, 3 ], "texture": "#texture" },
"west": { "uv": [ 5, 1, 11, 3 ], "texture": "#texture" },
"east": { "uv": [ 5, 1, 11, 3 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 5, 13, 4 ],
"to": [ 11, 15, 5 ],
"faces": {
"down": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" },
"up": { "uv": [ 5, 4, 11, 5 ], "texture": "#texture" },
"north": { "uv": [ 5, 1, 11, 3 ], "texture": "#texture" },
"west": { "uv": [ 4, 1, 5, 3 ], "texture": "#texture" },
"east": { "uv": [ 11, 1, 12, 3 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 5, 13, 11 ],
"to": [ 11, 15, 12 ],
"faces": {
"down": { "uv": [ 5, 4, 11, 5 ], "texture": "#texture" },
"up": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" },
"south": { "uv": [ 5, 1, 11, 3 ], "texture": "#texture" },
"west": { "uv": [ 11, 1, 12, 3 ], "texture": "#texture" },
"east": { "uv": [ 4, 1, 5, 3 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 5, 15, 5 ],
"to": [ 11, 16, 11 ],
"faces": {
"up": { "uv": [ 5, 5, 11, 11 ], "texture": "#cloth" },
"north": { "uv": [ 5, 0, 11, 1 ], "texture": "#cloth" },
"south": { "uv": [ 5, 0, 11, 1 ], "texture": "#cloth" },
"west": { "uv": [ 5, 0, 11, 1 ], "texture": "#cloth" },
"east": { "uv": [ 5, 0, 11, 1 ], "texture": "#cloth" }
}
},
{
"__comment": "Box5",
"from": [ 5.5, 12, 5.5 ],
"to": [ 10.5, 13, 10.5 ],
"faces": {
"down": { "uv": [ 5.5, 5.5, 10.5, 10.5 ], "texture": "#texture" },
"north": { "uv": [ 5.5, 3, 10.5, 4 ], "texture": "#texture" },
"south": { "uv": [ 5.5, 3, 10.5, 4 ], "texture": "#texture" },
"west": { "uv": [ 5.5, 3, 10.5, 4 ], "texture": "#texture" },
"east": { "uv": [ 5.5, 3, 10.5, 4 ], "texture": "#texture" }
}
},
{
"__comment": "Box5",
"from": [ 5, 0, 5 ],
"to": [ 6, 13, 6 ],
"faces": {
"down": { "uv": [ 5, 10, 6, 11 ], "texture": "#texture", "cullface": "down" },
"north": { "uv": [ 1, 5, 14, 6 ], "texture": "#texture", "rotation": 90 },
"south": { "uv": [ 2, 9, 15, 10 ], "texture": "#texture", "rotation": 90 },
"west": { "uv": [ 1, 13, 14, 14 ], "texture": "#texture", "rotation": 90 },
"east": { "uv": [ 2, 9, 15, 10 ], "texture": "#texture", "rotation": 90 }
}
},
{
"__comment": "Box5",
"from": [ 5, 0, 10 ],
"to": [ 6, 13, 11 ],
"faces": {
"down": { "uv": [ 5, 5, 6, 6 ], "texture": "#texture", "cullface": "down" },
"north": { "uv": [ 3, 9, 16, 10 ], "texture": "#texture", "rotation": 90 },
"south": { "uv": [ 3, 13, 16, 14 ], "texture": "#texture", "rotation": 90 },
"west": { "uv": [ 3, 13, 16, 14 ], "texture": "#texture", "rotation": 90 },
"east": { "uv": [ 3, 1, 16, 2 ], "texture": "#texture", "rotation": 90 }
}
},
{
"__comment": "Box5",
"from": [ 10, 0, 10 ],
"to": [ 11, 13, 11 ],
"faces": {
"down": { "uv": [ 10, 5, 11, 6 ], "texture": "#texture", "cullface": "down" },
"north": { "uv": [ 3, 1, 16, 2 ], "texture": "#texture", "rotation": 90 },
"south": { "uv": [ 3, 5, 16, 6 ], "texture": "#texture", "rotation": 90 },
"west": { "uv": [ 3, 13, 16, 14 ], "texture": "#texture", "rotation": 90 },
"east": { "uv": [ 3, 9, 16, 10 ], "texture": "#texture", "rotation": 90 }
}
},
{
"__comment": "Box5",
"from": [ 10, 0, 5 ],
"to": [ 11, 13, 6 ],
"faces": {
"down": { "uv": [ 10, 10, 11, 11 ], "texture": "#texture", "cullface": "down" },
"north": { "uv": [ 3, 13, 16, 14 ], "texture": "#texture", "rotation": 90 },
"south": { "uv": [ 0, 9, 13, 10 ], "texture": "#texture", "rotation": 90 },
"west": { "uv": [ 3, 5, 16, 6 ], "texture": "#texture", "rotation": 90 },
"east": { "uv": [ 0, 1, 13, 2 ], "texture": "#texture", "rotation": 90 }
}
},
{
"__comment": "Box5",
"from": [ 10, 5, 6 ],
"to": [ 11, 6, 10 ],
"faces": {
"down": { "uv": [ 7, 9, 11, 10 ], "texture": "#texture", "rotation": 90 },
"up": { "uv": [ 3, 9, 7, 10 ], "texture": "#texture", "rotation": 90 },
"west": { "uv": [ 3, 5, 7, 6 ], "texture": "#texture" },
"east": { "uv": [ 3, 5, 7, 6 ], "texture": "#texture" }
}
},
{
"__comment": "Box5",
"from": [ 6, 7, 5 ],
"to": [ 10, 8, 6 ],
"faces": {
"down": { "uv": [ 6.5, 9, 10.5, 10 ], "texture": "#texture" },
"up": { "uv": [ 4, 9, 8, 10 ], "texture": "#texture" },
"north": { "uv": [ 2, 9, 6, 10 ], "texture": "#texture" },
"south": { "uv": [ 7, 9, 11, 10 ], "texture": "#texture" }
}
},
{
"__comment": "Box5",
"from": [ 6, 7, 10 ],
"to": [ 10, 8, 11 ],
"faces": {
"down": { "uv": [ 4, 5, 8, 6 ], "texture": "#texture" },
"up": { "uv": [ 6, 9, 10, 10 ], "texture": "#texture" },
"north": { "uv": [ 4, 9, 8, 10 ], "texture": "#texture" },
"south": { "uv": [ 5, 9, 9, 10 ], "texture": "#texture" }
}
},
{
"__comment": "Box5",
"from": [ 5, 5, 6 ],
"to": [ 6, 6, 10 ],
"faces": {
"down": { "uv": [ 7, 9, 11, 10 ], "texture": "#texture", "rotation": 90 },
"up": { "uv": [ 3, 9, 7, 10 ], "texture": "#texture", "rotation": 90 },
"west": { "uv": [ 3, 5, 7, 6 ], "texture": "#texture" },
"east": { "uv": [ 3, 5, 7, 6 ], "texture": "#texture" }
}
}
]
}

View file

@ -0,0 +1,200 @@
{
"__comment": "Designed by Paulevs with Cubik Studio - https://cubik.studio",
"parent": "block/block",
"textures": {
"particle": "#texture"
},
"elements": [
{
"__comment": "Box1",
"from": [ 3, 9, 3 ],
"to": [ 13, 10, 13 ],
"faces": {
"down": { "uv": [ 3, 3, 13, 13 ], "texture": "#texture" },
"up": { "uv": [ 3, 3, 13, 13 ], "texture": "#texture" },
"north": { "uv": [ 3, 6, 13, 7 ], "texture": "#texture" },
"south": { "uv": [ 3, 6, 13, 7 ], "texture": "#texture" },
"west": { "uv": [ 3, 6, 13, 7 ], "texture": "#texture" },
"east": { "uv": [ 3, 6, 13, 7 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 3, 0, 3 ],
"to": [ 5, 9, 5 ],
"faces": {
"down": { "uv": [ 3, 11, 5, 13 ], "texture": "#texture" },
"north": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" },
"south": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" },
"west": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" },
"east": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 3, 16, 3 ],
"to": [ 5, 21, 5 ],
"faces": {
"up": { "uv": [ 3, 3, 5, 5 ], "texture": "#texture" },
"north": { "uv": [ 11, 11, 13, 16 ], "texture": "#texture" },
"west": { "uv": [ 3, 11, 5, 16 ], "texture": "#texture" },
"east": { "uv": [ 11, 11, 13, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 11, 0, 3 ],
"to": [ 13, 9, 5 ],
"faces": {
"down": { "uv": [ 11, 11, 13, 13 ], "texture": "#texture" },
"north": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" },
"south": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" },
"west": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" },
"east": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 11, 16, 3 ],
"to": [ 13, 21, 5 ],
"faces": {
"up": { "uv": [ 11, 3, 13, 5 ], "texture": "#texture" },
"north": { "uv": [ 3, 11, 5, 16 ], "texture": "#texture" },
"west": { "uv": [ 3, 11, 5, 16 ], "texture": "#texture" },
"east": { "uv": [ 11, 11, 13, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 11, 10, 3 ],
"to": [ 13, 16, 5 ],
"faces": {
"north": { "uv": [ 3, 0, 5, 6 ], "texture": "#texture" },
"south": { "uv": [ 11, 0, 13, 6 ], "texture": "#texture" },
"west": { "uv": [ 3, 0, 5, 6 ], "texture": "#texture" },
"east": { "uv": [ 11, 0, 13, 6 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 3, 10, 3 ],
"to": [ 5, 16, 5 ],
"faces": {
"north": { "uv": [ 11, 0, 13, 6 ], "texture": "#texture" },
"south": { "uv": [ 3, 0, 5, 6 ], "texture": "#texture" },
"west": { "uv": [ 3, 0, 5, 6 ], "texture": "#texture" },
"east": { "uv": [ 11, 0, 13, 6 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 3, 0, 11 ],
"to": [ 5, 9, 13 ],
"faces": {
"down": { "uv": [ 3, 3, 5, 5 ], "texture": "#texture" },
"north": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" },
"south": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" },
"west": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" },
"east": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 11, 0, 11 ],
"to": [ 13, 9, 13 ],
"faces": {
"down": { "uv": [ 11, 3, 13, 5 ], "texture": "#texture" },
"north": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" },
"south": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" },
"west": { "uv": [ 11, 7, 13, 16 ], "texture": "#texture" },
"east": { "uv": [ 3, 7, 5, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 3, 14, 4 ],
"to": [ 13, 16, 5 ],
"faces": {
"down": { "uv": [ 3, 11, 13, 12 ], "texture": "#texture" },
"north": { "uv": [ 3, 0, 13, 2 ], "texture": "#texture" },
"south": { "uv": [ 3, 0, 13, 2 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 4, 21, 3 ],
"to": [ 12, 22, 5 ],
"faces": {
"down": { "uv": [ 4, 11, 12, 13 ], "texture": "#texture" },
"up": { "uv": [ 4, 3, 12, 5 ], "texture": "#texture" },
"north": { "uv": [ 4, 10, 12, 11 ], "texture": "#texture" },
"south": { "uv": [ 4, 10, 12, 11 ], "texture": "#texture" },
"west": { "uv": [ 3, 10, 5, 11 ], "texture": "#texture" },
"east": { "uv": [ 11, 10, 13, 11 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 3, 16, 4 ],
"to": [ 13, 21, 5 ],
"faces": {
"up": { "uv": [ 3, 4, 13, 5 ], "texture": "#texture" },
"north": { "uv": [ 3, 11, 13, 16 ], "texture": "#texture" },
"south": { "uv": [ 3, 11, 13, 16 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 4, 8, 4 ],
"to": [ 12, 9, 12 ],
"faces": {
"down": { "uv": [ 4, 4, 12, 12 ], "texture": "#texture" },
"north": { "uv": [ 4, 7, 12, 8 ], "texture": "#texture" },
"south": { "uv": [ 4, 7, 12, 8 ], "texture": "#texture" },
"west": { "uv": [ 4, 7, 12, 8 ], "texture": "#texture" },
"east": { "uv": [ 4, 7, 12, 8 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 5, 20, 3 ],
"to": [ 11, 21, 4 ],
"faces": {
"down": { "uv": [ 5, 12, 11, 13 ], "texture": "#texture" },
"north": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 5, 14, 3 ],
"to": [ 11, 16, 4 ],
"faces": {
"down": { "uv": [ 5, 12, 11, 13 ], "texture": "#texture" },
"up": { "uv": [ 5, 3, 11, 4 ], "texture": "#texture" },
"north": { "uv": [ 5, 0, 11, 2 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 4, 4, 5 ],
"to": [ 5, 5, 11 ],
"faces": {
"down": { "uv": [ 4, 5, 5, 11 ], "texture": "#texture" },
"up": { "uv": [ 4, 5, 5, 11 ], "texture": "#texture" },
"west": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" },
"east": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" }
}
},
{
"__comment": "Box1",
"from": [ 11, 4, 5 ],
"to": [ 12, 5, 11 ],
"faces": {
"down": { "uv": [ 11, 5, 12, 11 ], "texture": "#texture" },
"up": { "uv": [ 11, 5, 12, 11 ], "texture": "#texture" },
"west": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" },
"east": { "uv": [ 5, 11, 11, 12 ], "texture": "#texture" }
}
}
]
}

View file

@ -0,0 +1,433 @@
{
"__comment": "Designed by Paulevs with Cubik Studio - https://cubik.studio",
"parent": "block/block",
"textures": {
"particle": "#texture",
"top": "#texture"
},
"elements": [
{
"__comment": "Box1",
"from": [
2,
8,
2
],
"to": [
14,
10,
14
],
"faces": {
"down": {
"uv": [
2,
2,
14,
14
],
"texture": "#top"
},
"up": {
"uv": [
2,
2,
14,
14
],
"texture": "#top"
},
"north": {
"uv": [
2,
6,
14,
8
],
"texture": "#texture"
},
"south": {
"uv": [
2,
6,
14,
8
],
"texture": "#texture"
},
"west": {
"uv": [
2,
6,
14,
8
],
"texture": "#texture"
},
"east": {
"uv": [
2,
6,
14,
8
],
"texture": "#texture"
}
}
},
{
"__comment": "Box1",
"from": [
3,
0,
3
],
"to": [
5,
8,
5
],
"faces": {
"down": {
"uv": [
3,
11,
5,
13
],
"texture": "#texture",
"cullface": "down"
},
"north": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
},
"south": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
},
"west": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
},
"east": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
}
}
},
{
"__comment": "Box1",
"from": [
11,
0,
3
],
"to": [
13,
8,
5
],
"faces": {
"down": {
"uv": [
11,
11,
13,
13
],
"texture": "#texture",
"cullface": "down"
},
"north": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
},
"south": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
},
"west": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
},
"east": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
}
}
},
{
"__comment": "Box1",
"from": [
11,
0,
11
],
"to": [
13,
8,
13
],
"faces": {
"down": {
"uv": [
11,
3,
13,
5
],
"texture": "#texture",
"cullface": "down"
},
"north": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
},
"south": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
},
"west": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
},
"east": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
}
}
},
{
"__comment": "Box1",
"from": [
3,
0,
11
],
"to": [
5,
8,
13
],
"faces": {
"down": {
"uv": [
3,
3,
5,
5
],
"texture": "#texture",
"cullface": "down"
},
"north": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
},
"south": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
},
"west": {
"uv": [
11,
8,
13,
16
],
"texture": "#texture"
},
"east": {
"uv": [
3,
8,
5,
16
],
"texture": "#texture"
}
}
},
{
"__comment": "Box6",
"from": [
5,
2,
4
],
"to": [
11,
3,
5
],
"faces": {
"down": {
"uv": [
2,
4,
3,
10
],
"texture": "#texture",
"rotation": 90
},
"up": {
"uv": [
2,
4,
3,
10
],
"texture": "#texture",
"rotation": 90
},
"north": {
"uv": [
2,
4,
3,
10
],
"texture": "#texture",
"rotation": 90
},
"south": {
"uv": [
2,
4,
3,
10
],
"texture": "#texture",
"rotation": 90
}
}
},
{
"__comment": "Box6",
"from": [
5,
2,
11
],
"to": [
11,
3,
12
],
"faces": {
"down": {
"uv": [
5,
4,
6,
10
],
"texture": "#texture",
"rotation": 90
},
"up": {
"uv": [
5,
4,
6,
10
],
"texture": "#texture",
"rotation": 90
},
"north": {
"uv": [
5,
4,
6,
10
],
"texture": "#texture",
"rotation": 90
},
"south": {
"uv": [
5,
4,
6,
10
],
"texture": "#texture",
"rotation": 90
}
}
}
]
}