- Base Anvil model fix;

- Some base blocks renamed;
This commit is contained in:
Aleksey 2021-06-11 14:55:54 +03:00
parent 809e913683
commit da1c27a14d
13 changed files with 877 additions and 869 deletions

View file

@ -8,7 +8,7 @@ yarn_mappings=6
loader_version=0.11.3 loader_version=0.11.3
# Mod Properties # Mod Properties
mod_version = 0.1.26 mod_version = 0.1.27
maven_group = ru.bclib maven_group = ru.bclib
archives_base_name = bclib archives_base_name = bclib

View file

@ -1,90 +1,91 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.AnvilBlock; import net.minecraft.world.level.block.AnvilBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import ru.bclib.client.models.BasePatterns; import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.BlockModelProvider; import ru.bclib.client.models.BlockModelProvider;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper; import ru.bclib.client.models.PatternsHelper;
public class BaseAnvilBlock extends AnvilBlock implements BlockModelProvider { public class BaseAnvilBlock extends AnvilBlock implements BlockModelProvider {
private static final IntegerProperty DESTRUCTION = BlockProperties.DESTRUCTION; private static final IntegerProperty DESTRUCTION = BlockProperties.DESTRUCTION;
public BaseAnvilBlock(MaterialColor color) { public BaseAnvilBlock(MaterialColor color) {
super(FabricBlockSettings.copyOf(Blocks.ANVIL).materialColor(color)); super(FabricBlockSettings.copyOf(Blocks.ANVIL).materialColor(color));
} }
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder); super.createBlockStateDefinition(builder);
builder.add(getDestructionProperty()); builder.add(getDestructionProperty());
} }
public IntegerProperty getDestructionProperty() { public IntegerProperty getDestructionProperty() {
return DESTRUCTION; return DESTRUCTION;
} }
@Override @Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack stack = new ItemStack(this); ItemStack stack = new ItemStack(this);
int level = state.getValue(getDestructionProperty()); int level = state.getValue(getDestructionProperty());
stack.getOrCreateTag().putInt("level", level); stack.getOrCreateTag().putInt("level", level);
return Collections.singletonList(stack); return Collections.singletonList(stack);
} }
protected String getTop(ResourceLocation blockId, String block) { protected String getTop(ResourceLocation blockId, String block) {
if (block.contains("item")) { if (block.contains("item")) {
return blockId.getPath() + "_top_0"; return blockId.getPath() + "_top_0";
} }
char last = block.charAt(block.length() - 1); char last = block.charAt(block.length() - 1);
return blockId.getPath() + "_top_" + last; return blockId.getPath() + "_top_" + last;
} }
@Override @Override
public BlockModel getItemModel(ResourceLocation blockId) { public BlockModel getItemModel(ResourceLocation blockId) {
return getBlockModel(blockId, defaultBlockState()); return getBlockModel(blockId, defaultBlockState());
} }
@Override @Override
public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) { public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) {
IntegerProperty destructionProperty = getDestructionProperty(); IntegerProperty destructionProperty = getDestructionProperty();
int destruction = blockState.getValue(destructionProperty); int destruction = blockState.getValue(destructionProperty);
String name = blockId.getPath(); String name = blockId.getPath();
Map<String, String> textures = Maps.newHashMap(); Map<String, String> textures = Maps.newHashMap();
textures.put("%anvil%", name); textures.put("%modid%", blockId.getNamespace());
textures.put("%top%", name + "_top_" + destruction); textures.put("%anvil%", name);
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_ANVIL, textures); textures.put("%top%", name + "_top_" + destruction);
return ModelsHelper.fromPattern(pattern); Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_ANVIL, textures);
} return ModelsHelper.fromPattern(pattern);
}
@Override
public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) { @Override
IntegerProperty destructionProperty = getDestructionProperty(); public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) {
int destruction = blockState.getValue(destructionProperty); IntegerProperty destructionProperty = getDestructionProperty();
String modId = stateId.getNamespace(); int destruction = blockState.getValue(destructionProperty);
String modelId = "block/" + stateId.getPath() + "_top_" + destruction; String modId = stateId.getNamespace();
ResourceLocation modelLocation = new ResourceLocation(modId, modelId); String modelId = "block/" + stateId.getPath() + "_top_" + destruction;
registerBlockModel(stateId, modelLocation, blockState, modelCache); ResourceLocation modelLocation = new ResourceLocation(modId, modelId);
return ModelsHelper.createFacingModel(modelLocation, blockState.getValue(FACING), false, false); registerBlockModel(stateId, modelLocation, blockState, modelCache);
} return ModelsHelper.createFacingModel(modelLocation, blockState.getValue(FACING), false, false);
} }
}

View file

@ -1,149 +1,149 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BonemealableBlock; import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.client.render.ERenderLayer; import ru.bclib.client.render.ERenderLayer;
import ru.bclib.interfaces.IRenderTyped; import ru.bclib.interfaces.IRenderTyped;
import ru.bclib.util.BlocksHelper; import ru.bclib.util.BlocksHelper;
public abstract class DoublePlantBlock extends BaseBlockNotFull implements IRenderTyped, BonemealableBlock { public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements IRenderTyped, BonemealableBlock {
private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12); private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12);
public static final IntegerProperty ROTATION = BlockProperties.ROTATION; public static final IntegerProperty ROTATION = BlockProperties.ROTATION;
public static final BooleanProperty TOP = BooleanProperty.create("top"); public static final BooleanProperty TOP = BooleanProperty.create("top");
public DoublePlantBlock() { public BaseDoublePlantBlock() {
super(FabricBlockSettings.of(Material.PLANT) super(FabricBlockSettings.of(Material.PLANT)
.breakByTool(FabricToolTags.SHEARS) .breakByTool(FabricToolTags.SHEARS)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.WET_GRASS) .sound(SoundType.WET_GRASS)
.noCollission()); .noCollission());
this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false)); this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false));
} }
public DoublePlantBlock(int light) { public BaseDoublePlantBlock(int light) {
super(FabricBlockSettings.of(Material.PLANT) super(FabricBlockSettings.of(Material.PLANT)
.breakByTool(FabricToolTags.SHEARS) .breakByTool(FabricToolTags.SHEARS)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.WET_GRASS) .sound(SoundType.WET_GRASS)
.lightLevel((state) -> state.getValue(TOP) ? light : 0) .lightLevel((state) -> state.getValue(TOP) ? light : 0)
.noCollission()); .noCollission());
this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false)); this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false));
} }
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(TOP, ROTATION); stateManager.add(TOP, ROTATION);
} }
@Override @Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
Vec3 vec3d = state.getOffset(view, pos); Vec3 vec3d = state.getOffset(view, pos);
return SHAPE.move(vec3d.x, vec3d.y, vec3d.z); return SHAPE.move(vec3d.x, vec3d.y, vec3d.z);
} }
@Override @Override
public BlockBehaviour.OffsetType getOffsetType() { public BlockBehaviour.OffsetType getOffsetType() {
return BlockBehaviour.OffsetType.XZ; return BlockBehaviour.OffsetType.XZ;
} }
@Override @Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below()); BlockState down = world.getBlockState(pos.below());
BlockState up = world.getBlockState(pos.above()); BlockState up = world.getBlockState(pos.above());
return state.getValue(TOP) ? down.getBlock() == this : isTerrain(down) && (up.getMaterial().isReplaceable()); return state.getValue(TOP) ? down.getBlock() == this : isTerrain(down) && (up.getMaterial().isReplaceable());
} }
public boolean canStayAt(BlockState state, LevelReader world, BlockPos pos) { public boolean canStayAt(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below()); BlockState down = world.getBlockState(pos.below());
BlockState up = world.getBlockState(pos.above()); BlockState up = world.getBlockState(pos.above());
return state.getValue(TOP) ? down.getBlock() == this : isTerrain(down) && (up.getBlock() == this); return state.getValue(TOP) ? down.getBlock() == this : isTerrain(down) && (up.getBlock() == this);
} }
protected abstract boolean isTerrain(BlockState state); protected abstract boolean isTerrain(BlockState state);
@Override @Override
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canStayAt(state, world, pos)) { if (!canStayAt(state, world, pos)) {
return Blocks.AIR.defaultBlockState(); return Blocks.AIR.defaultBlockState();
} }
else { else {
return state; return state;
} }
} }
@Override @Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (state.getValue(TOP)) { if (state.getValue(TOP)) {
return Lists.newArrayList(); return Lists.newArrayList();
} }
ItemStack tool = builder.getParameter(LootContextParams.TOOL); ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && tool.getItem().is(FabricToolTags.SHEARS) || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { if (tool != null && tool.getItem().is(FabricToolTags.SHEARS) || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Lists.newArrayList(new ItemStack(this)); return Lists.newArrayList(new ItemStack(this));
} }
else { else {
return Lists.newArrayList(); return Lists.newArrayList();
} }
} }
@Override @Override
public ERenderLayer getRenderLayer() { public ERenderLayer getRenderLayer() {
return ERenderLayer.CUTOUT; return ERenderLayer.CUTOUT;
} }
@Override @Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return true; return true;
} }
@Override @Override
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) { public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
return true; return true;
} }
@Override @Override
public void performBonemeal(ServerLevel world, Random random, BlockPos pos, BlockState state) { public void performBonemeal(ServerLevel world, Random random, BlockPos pos, BlockState state) {
ItemEntity item = new ItemEntity(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, new ItemStack(this)); ItemEntity item = new ItemEntity(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, new ItemStack(this));
world.addFreshEntity(item); world.addFreshEntity(item);
} }
@Override @Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) { public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
int rot = world.random.nextInt(4); int rot = world.random.nextInt(4);
BlockState bs = this.defaultBlockState().setValue(ROTATION, rot); BlockState bs = this.defaultBlockState().setValue(ROTATION, rot);
BlocksHelper.setWithoutUpdate(world, pos, bs); BlocksHelper.setWithoutUpdate(world, pos, bs);
BlocksHelper.setWithoutUpdate(world, pos.above(), bs.setValue(TOP, true)); BlocksHelper.setWithoutUpdate(world, pos.above(), bs.setValue(TOP, true));
} }
} }

View file

@ -1,92 +1,93 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.client.models.BasePatterns; import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper; import ru.bclib.client.models.PatternsHelper;
public abstract class BasePathBlock extends BaseBlockNotFull { @SuppressWarnings("deprecation")
private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 15, 16); public class BasePathBlock extends BaseBlockNotFull {
private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 15, 16);
private Block baseBlock;
private Block baseBlock;
public BasePathBlock(Block source) {
super(FabricBlockSettings.copyOf(source).isValidSpawn((state, world, pos, type) -> { return false; })); public BasePathBlock(Block source) {
this.baseBlock = Blocks.DIRT; super(FabricBlockSettings.copyOf(source).isValidSpawn((state, world, pos, type) -> false));
if (source instanceof BaseTerrainBlock) { this.baseBlock = Blocks.DIRT;
BaseTerrainBlock terrain = (BaseTerrainBlock) source; if (source instanceof BaseTerrainBlock) {
this.baseBlock = terrain.getBaseBlock(); BaseTerrainBlock terrain = (BaseTerrainBlock) source;
terrain.setPathBlock(this); this.baseBlock = terrain.getBaseBlock();
} terrain.setPathBlock(this);
} }
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { @Override
ItemStack tool = builder.getParameter(LootContextParams.TOOL); public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { ItemStack tool = builder.getParameter(LootContextParams.TOOL);
return Collections.singletonList(new ItemStack(this)); if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
} return Collections.singletonList(new ItemStack(this));
return Collections.singletonList(new ItemStack(Blocks.END_STONE)); }
} return Collections.singletonList(new ItemStack(Blocks.END_STONE));
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { @Override
return SHAPE; public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
} return SHAPE;
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { @Override
return SHAPE; public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
} return SHAPE;
}
@Override
public BlockModel getItemModel(ResourceLocation blockId) { @Override
return getBlockModel(blockId, defaultBlockState()); public BlockModel getItemModel(ResourceLocation blockId) {
} return getBlockModel(blockId, defaultBlockState());
}
@Override
public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) { @Override
String name = blockId.getPath(); public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) {
ResourceLocation bottomId = Registry.BLOCK.getKey(baseBlock); String name = blockId.getPath();
String bottom = bottomId.getNamespace() + ":block/" + bottomId.getPath(); ResourceLocation bottomId = Registry.BLOCK.getKey(baseBlock);
Map<String, String> textures = Maps.newHashMap(); String bottom = bottomId.getNamespace() + ":block/" + bottomId.getPath();
textures.put("%modid%", blockId.getNamespace()); Map<String, String> textures = Maps.newHashMap();
textures.put("%top%", name + "_top"); textures.put("%modid%", blockId.getNamespace());
textures.put("%side%", name.replace("_path", "") + "_side"); textures.put("%top%", name + "_top");
textures.put("%bottom%", bottom); textures.put("%side%", name.replace("_path", "") + "_side");
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_PATH, textures); textures.put("%bottom%", bottom);
return ModelsHelper.fromPattern(pattern); Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_PATH, textures);
} return ModelsHelper.fromPattern(pattern);
}
@Override
public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) { @Override
ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath()); public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) {
registerBlockModel(stateId, modelId, blockState, modelCache); ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath());
return ModelsHelper.createRandomTopModel(modelId); registerBlockModel(stateId, modelId, blockState, modelCache);
} return ModelsHelper.createRandomTopModel(modelId);
} }
}

View file

@ -1,9 +0,0 @@
package ru.bclib.blocks;
import net.minecraft.world.level.block.Block;
public class BasePressureStonePlateBlock extends BasePressurePlateBlock {
public BasePressureStonePlateBlock(Block source) {
super(Sensitivity.MOBS, source);
}
}

View file

@ -1,9 +0,0 @@
package ru.bclib.blocks;
import net.minecraft.world.level.block.Block;
public class BasePressureWoodenPlateBlock extends BasePressurePlateBlock {
public BasePressureWoodenPlateBlock(Block source) {
super(Sensitivity.EVERYTHING, source);
}
}

View file

@ -1,41 +1,41 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RotatedPillarBlock; import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
public class BaseStripableLogBlock extends BaseRotatedPillarBlock { public class BaseStripableLogBlock extends BaseRotatedPillarBlock {
private final Block striped; private final Block striped;
public BaseStripableLogBlock(MaterialColor color, Block striped) { public BaseStripableLogBlock(MaterialColor color, Block striped) {
super(FabricBlockSettings.copyOf(striped).materialColor(color)); super(FabricBlockSettings.copyOf(striped).materialColor(color));
this.striped = striped; this.striped = striped;
} }
@Override @Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getMainHandItem().getItem().is(FabricToolTags.AXES)) { if (player.getMainHandItem().getItem().is(FabricToolTags.AXES)) {
world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F); world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) { if (!world.isClientSide) {
world.setBlock(pos, striped.defaultBlockState().setValue(RotatedPillarBlock.AXIS, state.getValue(RotatedPillarBlock.AXIS)), 11); world.setBlock(pos, striped.defaultBlockState().setValue(RotatedPillarBlock.AXIS, state.getValue(RotatedPillarBlock.AXIS)), 11);
if (!player.isCreative()) { if (!player.isCreative()) {
player.getMainHandItem().hurt(1, world.random, (ServerPlayer) player); player.getMainHandItem().hurt(1, world.random, (ServerPlayer) player);
} }
} }
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
} }

View file

@ -1,136 +1,137 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SnowLayerBlock; import net.minecraft.world.level.block.SnowLayerBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LayerLightEngine; import net.minecraft.world.level.lighting.LayerLightEngine;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import ru.bclib.client.models.BasePatterns; import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper; import ru.bclib.client.models.PatternsHelper;
import ru.bclib.client.sound.BlockSounds; import ru.bclib.client.sound.BlockSounds;
public class BaseTerrainBlock extends BaseBlock { @SuppressWarnings("deprecation")
public class BaseTerrainBlock extends BaseBlock {
private final Block baseBlock;
private Block pathBlock; private final Block baseBlock;
private Block pathBlock;
public BaseTerrainBlock(Block baseBlock, MaterialColor color) {
super(FabricBlockSettings.copyOf(baseBlock).materialColor(color).sound(BlockSounds.TERRAIN_SOUND).randomTicks()); public BaseTerrainBlock(Block baseBlock, MaterialColor color) {
this.baseBlock = baseBlock; super(FabricBlockSettings.copyOf(baseBlock).materialColor(color).sound(BlockSounds.TERRAIN_SOUND).randomTicks());
} this.baseBlock = baseBlock;
}
public void setPathBlock(Block roadBlock) {
this.pathBlock = roadBlock; public void setPathBlock(Block roadBlock) {
} this.pathBlock = roadBlock;
}
public Block getBaseBlock() {
return baseBlock; public Block getBaseBlock() {
} return baseBlock;
}
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { @Override
if (pathBlock != null && player.getMainHandItem().getItem().is(FabricToolTags.SHOVELS)) { public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
world.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); if (pathBlock != null && player.getMainHandItem().getItem().is(FabricToolTags.SHOVELS)) {
if (!world.isClientSide) { world.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
world.setBlockAndUpdate(pos, pathBlock.defaultBlockState()); if (!world.isClientSide) {
if (!player.isCreative()) { world.setBlockAndUpdate(pos, pathBlock.defaultBlockState());
player.getMainHandItem().hurt(1, world.random, (ServerPlayer) player); if (!player.isCreative()) {
} player.getMainHandItem().hurt(1, world.random, (ServerPlayer) player);
} }
return InteractionResult.SUCCESS; }
} return InteractionResult.SUCCESS;
return InteractionResult.FAIL; }
} return InteractionResult.FAIL;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { @Override
ItemStack tool = builder.getParameter(LootContextParams.TOOL); public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { ItemStack tool = builder.getParameter(LootContextParams.TOOL);
return Collections.singletonList(new ItemStack(this)); if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
} return Collections.singletonList(new ItemStack(this));
return Collections.singletonList(new ItemStack(Blocks.END_STONE)); }
} return Collections.singletonList(new ItemStack(Blocks.END_STONE));
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { @Override
if (random.nextInt(16) == 0 && !canStay(state, world, pos)) { public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
world.setBlockAndUpdate(pos, Blocks.END_STONE.defaultBlockState()); if (random.nextInt(16) == 0 && !canStay(state, world, pos)) {
} world.setBlockAndUpdate(pos, Blocks.END_STONE.defaultBlockState());
} }
}
public boolean canStay(BlockState state, LevelReader worldView, BlockPos pos) {
BlockPos blockPos = pos.above(); public boolean canStay(BlockState state, LevelReader worldView, BlockPos pos) {
BlockState blockState = worldView.getBlockState(blockPos); BlockPos blockPos = pos.above();
if (blockState.is(Blocks.SNOW) && (Integer) blockState.getValue(SnowLayerBlock.LAYERS) == 1) { BlockState blockState = worldView.getBlockState(blockPos);
return true; if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) {
} return true;
else if (blockState.getFluidState().getAmount() == 8) { }
return false; else if (blockState.getFluidState().getAmount() == 8) {
} return false;
else { }
int i = LayerLightEngine.getLightBlockInto(worldView, state, pos, blockState, blockPos, Direction.UP, blockState.getLightBlock(worldView, blockPos)); else {
return i < 5; int i = LayerLightEngine.getLightBlockInto(worldView, state, pos, blockState, blockPos, Direction.UP, blockState.getLightBlock(worldView, blockPos));
} return i < 5;
} }
}
@Override
public BlockModel getItemModel(ResourceLocation blockId) { @Override
return getBlockModel(blockId, defaultBlockState()); public BlockModel getItemModel(ResourceLocation blockId) {
} return getBlockModel(blockId, defaultBlockState());
}
@Override
public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) { @Override
ResourceLocation baseId = Registry.BLOCK.getKey(baseBlock); public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) {
String modId = blockId.getNamespace(); ResourceLocation baseId = Registry.BLOCK.getKey(baseBlock);
String path = blockId.getPath(); String modId = blockId.getNamespace();
String bottom = baseId.getNamespace() + ":block/" + baseId.getPath(); String path = blockId.getPath();
Map<String, String> textures = Maps.newHashMap(); String bottom = baseId.getNamespace() + ":block/" + baseId.getPath();
textures.put("%top%", modId + ":block/" + path + "_top"); Map<String, String> textures = Maps.newHashMap();
textures.put("%side%", modId + ":block/" + path + "_side"); textures.put("%top%", modId + ":block/" + path + "_top");
textures.put("%bottom%", bottom); textures.put("%side%", modId + ":block/" + path + "_side");
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_TOP_SIDE_BOTTOM, textures); textures.put("%bottom%", bottom);
return ModelsHelper.fromPattern(pattern); Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_TOP_SIDE_BOTTOM, textures);
} return ModelsHelper.fromPattern(pattern);
}
@Override
public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) { @Override
ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath()); public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) {
registerBlockModel(stateId, modelId, blockState, modelCache); ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath());
return ModelsHelper.createRandomTopModel(modelId); registerBlockModel(stateId, modelId, blockState, modelCache);
} return ModelsHelper.createRandomTopModel(modelId);
} }
}

View file

@ -1,146 +1,146 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags; import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BonemealableBlock; import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.blocks.BlockProperties.TripleShape; import ru.bclib.blocks.BlockProperties.TripleShape;
import ru.bclib.client.render.ERenderLayer; import ru.bclib.client.render.ERenderLayer;
import ru.bclib.interfaces.IRenderTyped; import ru.bclib.interfaces.IRenderTyped;
import ru.bclib.util.BlocksHelper; import ru.bclib.util.BlocksHelper;
public class VineBlock extends BaseBlockNotFull implements IRenderTyped, BonemealableBlock { public class BaseVineBlock extends BaseBlockNotFull implements IRenderTyped, BonemealableBlock {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE; public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
private static final VoxelShape VOXEL_SHAPE = Block.box(2, 0, 2, 14, 16, 14); private static final VoxelShape VOXEL_SHAPE = Block.box(2, 0, 2, 14, 16, 14);
public VineBlock() { public BaseVineBlock() {
this(0, false); this(0, false);
} }
public VineBlock(int light) { public BaseVineBlock(int light) {
this(light, false); this(light, false);
} }
public VineBlock(int light, boolean bottomOnly) { public BaseVineBlock(int light, boolean bottomOnly) {
super(FabricBlockSettings.of(Material.PLANT) super(FabricBlockSettings.of(Material.PLANT)
.breakByTool(FabricToolTags.SHEARS) .breakByTool(FabricToolTags.SHEARS)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.lightLevel((state) -> bottomOnly ? state.getValue(SHAPE) == TripleShape.BOTTOM ? light : 0 : light) .lightLevel((state) -> bottomOnly ? state.getValue(SHAPE) == TripleShape.BOTTOM ? light : 0 : light)
.noCollission()); .noCollission());
this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, TripleShape.BOTTOM)); this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, TripleShape.BOTTOM));
} }
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE); stateManager.add(SHAPE);
} }
@Override @Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
Vec3 vec3d = state.getOffset(view, pos); Vec3 vec3d = state.getOffset(view, pos);
return VOXEL_SHAPE.move(vec3d.x, vec3d.y, vec3d.z); return VOXEL_SHAPE.move(vec3d.x, vec3d.y, vec3d.z);
} }
@Override @Override
public BlockBehaviour.OffsetType getOffsetType() { public BlockBehaviour.OffsetType getOffsetType() {
return BlockBehaviour.OffsetType.XZ; return BlockBehaviour.OffsetType.XZ;
} }
public boolean canGenerate(BlockState state, LevelReader world, BlockPos pos) { public boolean canGenerate(BlockState state, LevelReader world, BlockPos pos) {
return isSupport(state, world, pos); return isSupport(state, world, pos);
} }
@Override @Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return isSupport(state, world, pos); return isSupport(state, world, pos);
} }
protected boolean isSupport(BlockState state, LevelReader world, BlockPos pos) { protected boolean isSupport(BlockState state, LevelReader world, BlockPos pos) {
BlockState up = world.getBlockState(pos.above()); BlockState up = world.getBlockState(pos.above());
return up.is(this) || up.is(BlockTags.LEAVES) || canSupportCenter(world, pos.above(), Direction.DOWN); return up.is(this) || up.is(BlockTags.LEAVES) || canSupportCenter(world, pos.above(), Direction.DOWN);
} }
@Override @Override
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canSurvive(state, world, pos)) { if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState(); return Blocks.AIR.defaultBlockState();
} }
else { else {
if (world.getBlockState(pos.below()).getBlock() != this) if (world.getBlockState(pos.below()).getBlock() != this)
return state.setValue(SHAPE, TripleShape.BOTTOM); return state.setValue(SHAPE, TripleShape.BOTTOM);
else if (world.getBlockState(pos.above()).getBlock() != this) else if (world.getBlockState(pos.above()).getBlock() != this)
return state.setValue(SHAPE, TripleShape.TOP); return state.setValue(SHAPE, TripleShape.TOP);
return state.setValue(SHAPE, TripleShape.MIDDLE); return state.setValue(SHAPE, TripleShape.MIDDLE);
} }
} }
@Override @Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL); ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && tool.getItem().is(FabricToolTags.SHEARS) || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) { if (tool != null && tool.getItem().is(FabricToolTags.SHEARS) || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Lists.newArrayList(new ItemStack(this)); return Lists.newArrayList(new ItemStack(this));
} }
else { else {
return Lists.newArrayList(); return Lists.newArrayList();
} }
} }
@Override @Override
public ERenderLayer getRenderLayer() { public ERenderLayer getRenderLayer() {
return ERenderLayer.CUTOUT; return ERenderLayer.CUTOUT;
} }
@Override @Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) { public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
while (world.getBlockState(pos).getBlock() == this) { while (world.getBlockState(pos).getBlock() == this) {
pos = pos.below(); pos = pos.below();
} }
return world.getBlockState(pos).isAir(); return world.getBlockState(pos).isAir();
} }
@Override @Override
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) { public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
while (world.getBlockState(pos).getBlock() == this) { while (world.getBlockState(pos).getBlock() == this) {
pos = pos.below(); pos = pos.below();
} }
return world.isEmptyBlock(pos); return world.isEmptyBlock(pos);
} }
@Override @Override
public void performBonemeal(ServerLevel world, Random random, BlockPos pos, BlockState state) { public void performBonemeal(ServerLevel world, Random random, BlockPos pos, BlockState state) {
while (world.getBlockState(pos).getBlock() == this) { while (world.getBlockState(pos).getBlock() == this) {
pos = pos.below(); pos = pos.below();
} }
world.setBlockAndUpdate(pos, defaultBlockState()); world.setBlockAndUpdate(pos, defaultBlockState());
BlocksHelper.setWithoutUpdate(world, pos, defaultBlockState()); BlocksHelper.setWithoutUpdate(world, pos, defaultBlockState());
} }
} }

View file

@ -0,0 +1,9 @@
package ru.bclib.blocks;
import net.minecraft.world.level.block.Block;
public class StonePressurePlateBlock extends BasePressurePlateBlock {
public StonePressurePlateBlock(Block source) {
super(Sensitivity.MOBS, source);
}
}

View file

@ -1,41 +1,41 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RotatedPillarBlock; import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
public class StrippableBarkBlock extends BaseBarkBlock { public class StripableBarkBlock extends BaseBarkBlock {
private final Block striped; private final Block striped;
public StrippableBarkBlock(MaterialColor color, Block striped) { public StripableBarkBlock(MaterialColor color, Block striped) {
super(FabricBlockSettings.copyOf(striped).materialColor(color)); super(FabricBlockSettings.copyOf(striped).materialColor(color));
this.striped = striped; this.striped = striped;
} }
@Override @Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getMainHandItem().getItem().is(FabricToolTags.AXES)) { if (player.getMainHandItem().getItem().is(FabricToolTags.AXES)) {
world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F); world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
if (!world.isClientSide) { if (!world.isClientSide) {
world.setBlock(pos, striped.defaultBlockState().setValue(RotatedPillarBlock.AXIS, state.getValue(RotatedPillarBlock.AXIS)), 11); world.setBlock(pos, striped.defaultBlockState().setValue(RotatedPillarBlock.AXIS, state.getValue(RotatedPillarBlock.AXIS)), 11);
if (!player.isCreative()) { if (!player.isCreative()) {
player.getMainHandItem().hurt(1, world.random, (ServerPlayer) player); player.getMainHandItem().hurt(1, world.random, (ServerPlayer) player);
} }
} }
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
} }

View file

@ -1,155 +1,160 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.MultiVariant; import net.minecraft.client.renderer.block.model.MultiVariant;
import net.minecraft.client.renderer.block.model.Variant; import net.minecraft.client.renderer.block.model.Variant;
import net.minecraft.client.resources.model.BlockModelRotation; import net.minecraft.client.resources.model.BlockModelRotation;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import ru.bclib.blocks.BlockProperties.TripleShape; import ru.bclib.blocks.BlockProperties.TripleShape;
import ru.bclib.client.models.BasePatterns; import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper; import ru.bclib.client.models.PatternsHelper;
public class TripleTerrainBlock extends BaseTerrainBlock { public class TripleTerrainBlock extends BaseTerrainBlock {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE; public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
public TripleTerrainBlock(Block baseBlock, MaterialColor color) { public TripleTerrainBlock(Block baseBlock) {
super(baseBlock, color); super(baseBlock, baseBlock.defaultMaterialColor());
this.registerDefaultState(defaultBlockState().setValue(SHAPE, TripleShape.BOTTOM)); this.registerDefaultState(defaultBlockState().setValue(SHAPE, TripleShape.BOTTOM));
} }
@Override public TripleTerrainBlock(Block baseBlock, MaterialColor color) {
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) { super(baseBlock, color);
stateManager.add(SHAPE); this.registerDefaultState(defaultBlockState().setValue(SHAPE, TripleShape.BOTTOM));
} }
@Override @Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
Direction dir = ctx.getClickedFace(); stateManager.add(SHAPE);
TripleShape shape = dir == Direction.UP ? TripleShape.BOTTOM : dir == Direction.DOWN ? TripleShape.TOP : TripleShape.MIDDLE; }
return defaultBlockState().setValue(SHAPE, shape);
} @Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
@Override Direction dir = ctx.getClickedFace();
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { TripleShape shape = dir == Direction.UP ? TripleShape.BOTTOM : dir == Direction.DOWN ? TripleShape.TOP : TripleShape.MIDDLE;
TripleShape shape = state.getValue(SHAPE); return defaultBlockState().setValue(SHAPE, shape);
if (shape == TripleShape.BOTTOM) { }
return super.use(state, world, pos, player, hand, hit);
} @Override
return InteractionResult.FAIL; public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
} TripleShape shape = state.getValue(SHAPE);
if (shape == TripleShape.BOTTOM) {
@Override return super.use(state, world, pos, player, hand, hit);
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { }
TripleShape shape = state.getValue(SHAPE); return InteractionResult.FAIL;
if (shape == TripleShape.BOTTOM) { }
super.randomTick(state, world, pos, random);
} else if (random.nextInt(16) == 0) { @Override
boolean bottom = canStayBottom(world, pos); public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
if (shape == TripleShape.TOP) { TripleShape shape = state.getValue(SHAPE);
if (!bottom) { if (shape == TripleShape.BOTTOM) {
world.setBlockAndUpdate(pos, Blocks.END_STONE.defaultBlockState()); super.randomTick(state, world, pos, random);
} } else if (random.nextInt(16) == 0) {
} boolean bottom = canStayBottom(world, pos);
else { if (shape == TripleShape.TOP) {
boolean top = canStay(state, world, pos) || isMiddle(world.getBlockState(pos.above())); if (!bottom) {
if (!top && !bottom) { world.setBlockAndUpdate(pos, Blocks.END_STONE.defaultBlockState());
world.setBlockAndUpdate(pos, Blocks.END_STONE.defaultBlockState()); }
} else if (top && !bottom) { }
world.setBlockAndUpdate(pos, state.setValue(SHAPE, TripleShape.BOTTOM)); else {
} else if (!top) { boolean top = canStay(state, world, pos) || isMiddle(world.getBlockState(pos.above()));
world.setBlockAndUpdate(pos, state.setValue(SHAPE, TripleShape.TOP)); if (!top && !bottom) {
} world.setBlockAndUpdate(pos, Blocks.END_STONE.defaultBlockState());
} } else if (top && !bottom) {
} world.setBlockAndUpdate(pos, state.setValue(SHAPE, TripleShape.BOTTOM));
} } else if (!top) {
world.setBlockAndUpdate(pos, state.setValue(SHAPE, TripleShape.TOP));
protected boolean canStayBottom(LevelReader world, BlockPos pos) { }
BlockPos blockPos = pos.below(); }
BlockState blockState = world.getBlockState(blockPos); }
if (isMiddle(blockState)) { }
return true;
} else if (blockState.getFluidState().getAmount() == 8) { protected boolean canStayBottom(LevelReader world, BlockPos pos) {
return false; BlockPos blockPos = pos.below();
} else { BlockState blockState = world.getBlockState(blockPos);
return !blockState.isFaceSturdy(world, blockPos, Direction.UP); if (isMiddle(blockState)) {
} return true;
} } else if (blockState.getFluidState().getAmount() == 8) {
return false;
@Override } else {
public BlockModel getItemModel(ResourceLocation blockId) { return !blockState.isFaceSturdy(world, blockPos, Direction.UP);
return getBlockModel(blockId, defaultBlockState()); }
} }
@Override @Override
public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) { public BlockModel getItemModel(ResourceLocation blockId) {
String path = blockId.getPath(); return getBlockModel(blockId, defaultBlockState());
Optional<String> pattern; }
if (isMiddle(blockState)) {
ResourceLocation topId = new ResourceLocation(blockId.getNamespace(), path + "_top"); @Override
pattern = PatternsHelper.createBlockSimple(topId); public @Nullable BlockModel getBlockModel(ResourceLocation blockId, BlockState blockState) {
} else { String path = blockId.getPath();
Map<String, String> textures = Maps.newHashMap(); Optional<String> pattern;
textures.put("%top%", "betterend:block/" + path + "_top"); if (isMiddle(blockState)) {
textures.put("%side%", "betterend:block/" + path + "_side"); ResourceLocation topId = new ResourceLocation(blockId.getNamespace(), path + "_top");
textures.put("%bottom%", "minecraft:block/end_stone"); pattern = PatternsHelper.createBlockSimple(topId);
pattern = PatternsHelper.createJson(BasePatterns.BLOCK_TOP_SIDE_BOTTOM, textures); } else {
} Map<String, String> textures = Maps.newHashMap();
return ModelsHelper.fromPattern(pattern); textures.put("%top%", "betterend:block/" + path + "_top");
} textures.put("%side%", "betterend:block/" + path + "_side");
textures.put("%bottom%", "minecraft:block/end_stone");
@Override pattern = PatternsHelper.createJson(BasePatterns.BLOCK_TOP_SIDE_BOTTOM, textures);
public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) { }
boolean isMiddle = isMiddle(blockState); return ModelsHelper.fromPattern(pattern);
String middle = isMiddle ? "_middle" : ""; }
ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(),
"block/" + stateId.getPath() + middle); @Override
registerBlockModel(stateId, modelId, blockState, modelCache); public UnbakedModel getModelVariant(ResourceLocation stateId, BlockState blockState, Map<ResourceLocation, UnbakedModel> modelCache) {
if (isMiddle) { boolean isMiddle = isMiddle(blockState);
List<Variant> variants = Lists.newArrayList(); String middle = isMiddle ? "_middle" : "";
for (BlockModelRotation rotation : BlockModelRotation.values()) { ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(),
variants.add(new Variant(modelId, rotation.getRotation(), false, 1)); "block/" + stateId.getPath() + middle);
} registerBlockModel(stateId, modelId, blockState, modelCache);
return new MultiVariant(variants); if (isMiddle) {
} else if (blockState.getValue(SHAPE) == TripleShape.TOP) { List<Variant> variants = Lists.newArrayList();
return new MultiVariant(Lists.newArrayList( for (BlockModelRotation rotation : BlockModelRotation.values()) {
new Variant(modelId, BlockModelRotation.X180_Y0.getRotation(), false, 1), variants.add(new Variant(modelId, rotation.getRotation(), false, 1));
new Variant(modelId, BlockModelRotation.X180_Y90.getRotation(), false, 1), }
new Variant(modelId, BlockModelRotation.X180_Y180.getRotation(), false, 1), return new MultiVariant(variants);
new Variant(modelId, BlockModelRotation.X180_Y270.getRotation(), false, 1) } else if (blockState.getValue(SHAPE) == TripleShape.TOP) {
)); return new MultiVariant(Lists.newArrayList(
} new Variant(modelId, BlockModelRotation.X180_Y0.getRotation(), false, 1),
return ModelsHelper.createRandomTopModel(modelId); new Variant(modelId, BlockModelRotation.X180_Y90.getRotation(), false, 1),
} new Variant(modelId, BlockModelRotation.X180_Y180.getRotation(), false, 1),
new Variant(modelId, BlockModelRotation.X180_Y270.getRotation(), false, 1)
protected boolean isMiddle(BlockState blockState) { ));
return blockState.is(this) && blockState.getValue(SHAPE) == TripleShape.MIDDLE; }
} return ModelsHelper.createRandomTopModel(modelId);
} }
protected boolean isMiddle(BlockState blockState) {
return blockState.is(this) && blockState.getValue(SHAPE) == TripleShape.MIDDLE;
}
}

View file

@ -0,0 +1,9 @@
package ru.bclib.blocks;
import net.minecraft.world.level.block.Block;
public class WoodenPressurePlateBlock extends BasePressurePlateBlock {
public WoodenPressurePlateBlock(Block source) {
super(Sensitivity.EVERYTHING, source);
}
}