Neon cactus growing (WIP) & additional textures

This commit is contained in:
paulevsGitch 2021-04-26 21:51:53 +03:00
parent d897bb09d8
commit 387a430fde
28 changed files with 554 additions and 55 deletions

View file

@ -8,7 +8,8 @@ import ru.betterend.registry.EndPortals;
public class BlockProperties {
public static final EnumProperty<HydraluxShape> HYDRALUX_SHAPE = EnumProperty.create("shape", HydraluxShape.class);
public final static EnumProperty<PedestalState> PEDESTAL_STATE = EnumProperty.create("state", PedestalState.class);
public static final EnumProperty<PedestalState> PEDESTAL_STATE = EnumProperty.create("state", PedestalState.class);
public static final EnumProperty<CactusBottom> CACTUS_BOTTOM = EnumProperty.create("bottom", CactusBottom.class);
public static final EnumProperty<TripleShape> TRIPLE_SHAPE = EnumProperty.create("shape", TripleShape.class);
public static final EnumProperty<PentaShape> PENTA_SHAPE = EnumProperty.create("shape", PentaShape.class);
@ -30,14 +31,16 @@ public class BlockProperties {
public static final IntegerProperty AGE = IntegerProperty.create("age", 0, 3);
public static enum TripleShape implements StringRepresentable {
TOP("top"),
MIDDLE("middle"),
BOTTOM("bottom");
TOP("top", 0),
MIDDLE("middle", 1),
BOTTOM("bottom", 2);
private final String name;
private final int index;
TripleShape(String name) {
TripleShape(String name, int index) {
this.name = name;
this.index = index;
}
@Override
@ -49,6 +52,14 @@ public class BlockProperties {
public String toString() {
return name;
}
public int getIndex() {
return index;
}
public static TripleShape fromIndex(int index) {
return index > 1 ? BOTTOM : index == 1 ? MIDDLE : TOP;
}
}
public static enum PedestalState implements StringRepresentable {
@ -162,4 +173,26 @@ public class BlockProperties {
return light;
}
}
public static enum CactusBottom implements StringRepresentable {
EMPTY("empty"),
SAND("sand"),
MOSS("moss");
private final String name;
CactusBottom(String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
}

View file

@ -1,13 +1,16 @@
package ru.betterend.blocks;
import java.util.EnumMap;
import java.util.Random;
import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
@ -27,14 +30,18 @@ import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import ru.betterend.blocks.BlockProperties.CactusBottom;
import ru.betterend.blocks.BlockProperties.TripleShape;
import ru.betterend.blocks.basis.BlockBaseNotFull;
import ru.betterend.client.render.ERenderLayer;
import ru.betterend.interfaces.IRenderTypeable;
import ru.betterend.registry.EndBlocks;
import ru.betterend.registry.EndTags;
import ru.betterend.util.BlocksHelper;
public class NeonCactusBlock extends BlockBaseNotFull implements SimpleWaterloggedBlock, IRenderTypeable {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
public static final EnumProperty<CactusBottom> CACTUS_BOTTOM = BlockProperties.CACTUS_BOTTOM;
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final DirectionProperty FACING = BlockStateProperties.FACING;
@ -44,20 +51,32 @@ public class NeonCactusBlock extends BlockBaseNotFull implements SimpleWaterlogg
private static final EnumMap<Axis, VoxelShape> SMALL_SHAPES = Maps.newEnumMap(Axis.class);
public NeonCactusBlock() {
super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15));
super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15).randomTicks());
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false).setValue(FACING, Direction.UP).setValue(SHAPE, TripleShape.TOP));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE, WATERLOGGED, FACING);
stateManager.add(SHAPE, CACTUS_BOTTOM, WATERLOGGED, FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
LevelAccessor worldAccess = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState().setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER).setValue(FACING, ctx.getClickedFace());
LevelAccessor world = ctx.getLevel();
BlockPos pos = ctx.getClickedPos();
Direction dir = ctx.getClickedFace();
BlockState down = world.getBlockState(pos.relative(dir.getOpposite()));
BlockState state = this.defaultBlockState().setValue(WATERLOGGED, world.getFluidState(pos).getType() == Fluids.WATER).setValue(FACING, ctx.getClickedFace());
if (down.is(Blocks.END_STONE) || down.is(EndBlocks.ENDSTONE_DUST)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND);
}
else if (down.is(EndBlocks.END_MOSS)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS);
}
else {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY);
}
return state;
}
@Override
@ -80,6 +99,17 @@ public class NeonCactusBlock extends BlockBaseNotFull implements SimpleWaterlogg
if ((Boolean) state.getValue(WATERLOGGED)) {
world.getLiquidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
}
Direction dir = state.getValue(FACING);
BlockState down = world.getBlockState(pos.relative(dir.getOpposite()));
if (down.is(Blocks.END_STONE) || down.is(EndBlocks.ENDSTONE_DUST)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND);
}
else if (down.is(EndBlocks.END_MOSS)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS);
}
else {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY);
}
return state;
}
@ -106,6 +136,87 @@ public class NeonCactusBlock extends BlockBaseNotFull implements SimpleWaterlogg
}
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
Direction dir = state.getValue(FACING);
if (!world.getBlockState(pos.relative(dir)).isAir() || world.getBlockState(pos.above()).is(this)) {
return;
}
int length = getLength(state, world, pos, 10);
if (length < 0 || length > 9) {
return;
}
int horizontal = getHorizontal(state, world, pos, 5);
if (horizontal > random.nextInt(2)) {
dir = Direction.UP;
if (!world.getBlockState(pos.above()).isAir()) {
return;
}
}
BlockState placement = state.setValue(SHAPE, TripleShape.TOP).setValue(CACTUS_BOTTOM, CactusBottom.EMPTY).setValue(WATERLOGGED, false).setValue(FACING, dir);
BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement);
mutateStem(placement, world, pos, 10);
}
private int getLength(BlockState state, ServerLevel world, BlockPos pos, int max) {
int length = 0;
Direction dir = state.getValue(FACING).getOpposite();
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 0; i < max; i++) {
mut.move(dir);
state = world.getBlockState(mut);
if (!state.is(this)) {
if (!state.is(EndTags.END_GROUND)) {
length = -1;
}
break;
}
dir = state.getValue(FACING).getOpposite();
length ++;
}
return length;
}
private int getHorizontal(BlockState state, ServerLevel world, BlockPos pos, int max) {
int count = 0;
Direction dir = state.getValue(FACING).getOpposite();
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 0; i < max; i++) {
mut.move(dir);
state = world.getBlockState(mut);
if (!state.is(this)) {
break;
}
dir = state.getValue(FACING).getOpposite();
if (dir.getStepY() != 0) {
break;
}
count ++;
}
return count;
}
private void mutateStem(BlockState state, ServerLevel world, BlockPos pos, int max) {
Direction dir = state.getValue(FACING).getOpposite();
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 0; i < max; i++) {
mut.move(dir);
state = world.getBlockState(mut);
if (!state.is(this)) {
return;
}
int size = i * 3 / max;
int src = state.getValue(SHAPE).getIndex();
if (src < size) {
TripleShape shape = TripleShape.fromIndex(size);
BlocksHelper.setWithoutUpdate(world, pos, state.setValue(SHAPE, shape));
}
else {
return;
}
}
}
static {
MEDIUM_SHAPES.put(Axis.X, Block.box(0, 2, 2, 16, 14, 14));
MEDIUM_SHAPES.put(Axis.Y, Block.box(2, 0, 2, 14, 16, 14));

View file

@ -1,18 +1,19 @@
package ru.betterend.mixin.common;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagLoader;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import ru.betterend.util.TagHelper;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagLoader;
import ru.betterend.util.TagHelper;
@Mixin(TagLoader.class)
public class TagLoaderMixin {
@Shadow

View file

@ -6,10 +6,13 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import ru.betterend.blocks.BlockProperties;
import ru.betterend.blocks.BlockProperties.CactusBottom;
import ru.betterend.blocks.BlockProperties.TripleShape;
import ru.betterend.registry.EndBlocks;
import ru.betterend.util.BlocksHelper;
@ -31,9 +34,23 @@ public class NeonCactusFeature extends DefaultFeature {
break;
}
int size = (h - i) >> 2;
BlocksHelper.setWithUpdate(world, mut,
EndBlocks.NEON_CACTUS.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, getBySize(size))
.setValue(BlockStateProperties.FACING, Direction.UP));
BlockState state = EndBlocks.NEON_CACTUS.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, getBySize(size)).setValue(BlockStateProperties.FACING, Direction.UP);
if (i == 0) {
BlockState down = world.getBlockState(mut.below());
if (down.is(Blocks.END_STONE) || down.is(EndBlocks.ENDSTONE_DUST)) {
state = state.setValue(BlockProperties.CACTUS_BOTTOM, CactusBottom.SAND);
}
else if (down.is(EndBlocks.END_MOSS)) {
state = state.setValue(BlockProperties.CACTUS_BOTTOM, CactusBottom.MOSS);
}
else {
state = state.setValue(BlockProperties.CACTUS_BOTTOM, CactusBottom.EMPTY);
}
}
else {
state = state.setValue(BlockProperties.CACTUS_BOTTOM, CactusBottom.EMPTY);
}
BlocksHelper.setWithUpdate(world, mut, state);
if (i > 2 && i < (h - 1) && random.nextBoolean()) {
int length = h - i - MHelper.randRange(1, 2, random);
if (length > 0) {

View file

@ -25,8 +25,7 @@ public abstract class WallScatterFeature extends DefaultFeature {
public abstract void generate(WorldGenLevel world, Random random, BlockPos pos, Direction dir);
@Override
public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos center,
NoneFeatureConfiguration featureConfig) {
public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, Random random, BlockPos center, NoneFeatureConfiguration featureConfig) {
int maxY = world.getHeight(Heightmap.Types.WORLD_SURFACE, center.getX(), center.getZ());
int minY = BlocksHelper.upRay(world, new BlockPos(center.getX(), 0, center.getZ()), maxY);
if (maxY < 10 || maxY < minY) {

View file

@ -4,36 +4,32 @@ import java.util.Random;
import ru.betterend.world.biome.EndBiome;
public class BiomeChunk
{
public class BiomeChunk {
protected static final int WIDTH = 16;
private static final int SM_WIDTH = WIDTH >> 1;
private static final int MASK_OFFSET = SM_WIDTH - 1;
protected static final int MASK_WIDTH = WIDTH - 1;
private final EndBiome[][] biomes;
public BiomeChunk(BiomeMap map, Random random, BiomePicker picker)
{
public BiomeChunk(BiomeMap map, Random random, BiomePicker picker) {
EndBiome[][] PreBio = new EndBiome[SM_WIDTH][SM_WIDTH];
biomes = new EndBiome[WIDTH][WIDTH];
for (int x = 0; x < SM_WIDTH; x++)
for (int z = 0; z < SM_WIDTH; z++)
PreBio[x][z] = picker.getBiome(random);
for (int x = 0; x < WIDTH; x++)
for (int z = 0; z < WIDTH; z++)
biomes[x][z] = PreBio[offsetXZ(x, random)][offsetXZ(z, random)].getSubBiome(random);
}
public EndBiome getBiome(int x, int z)
{
public EndBiome getBiome(int x, int z) {
return biomes[x & MASK_WIDTH][z & MASK_WIDTH];
}
private int offsetXZ(int x, Random random)
{
private int offsetXZ(int x, Random random) {
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
}
}