Added soggy clouds. Clouds will soak up water when it rains and slowly dry out when the weather is clear

This commit is contained in:
Sollace 2023-10-18 23:15:48 +01:00
parent fa8b1e485c
commit ea94092b2c
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
24 changed files with 357 additions and 70 deletions

View file

@ -5,9 +5,12 @@ import java.util.Collections;
import java.util.List;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.block.cloud.CloudBlock;
import com.minelittlepony.unicopia.block.cloud.CloudPillarBlock;
import com.minelittlepony.unicopia.block.cloud.CloudSlabBlock;
import com.minelittlepony.unicopia.block.cloud.PoreousCloudBlock;
import com.minelittlepony.unicopia.block.cloud.CloudBlock;
import com.minelittlepony.unicopia.block.cloud.SoggyCloudBlock;
import com.minelittlepony.unicopia.block.cloud.SoggyCloudSlabBlock;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
import com.minelittlepony.unicopia.server.world.UTreeGen;
@ -128,11 +131,13 @@ public interface UBlocks {
Block MYSTERIOUS_EGG = register("mysterious_egg", new PileBlock(Settings.copy(Blocks.SLIME_BLOCK), PileBlock.MYSTERIOUS_EGG_SHAPES), ItemGroups.NATURAL);
Block SLIME_PUSTULE = register("slime_pustule", new SlimePustuleBlock(Settings.copy(Blocks.SLIME_BLOCK)), ItemGroups.NATURAL);
Block CLOUD = register("cloud", new CloudBlock(Settings.create().mapColor(MapColor.OFF_WHITE).replaceable().hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true));
Block CLOUD_SLAB = register("cloud_slab", new CloudSlabBlock(Settings.copy(CLOUD), true));
Block DENSE_CLOUD = register("dense_cloud", new CloudBlock(Settings.create().mapColor(MapColor.GRAY).replaceable().hardness(0.5F).resistance(0).sounds(BlockSoundGroup.WOOL), false));
Block DENSE_CLOUD_SLAB = register("dense_cloud_slab", new CloudSlabBlock(Settings.copy(DENSE_CLOUD), false));
Block CLOUD_PILLAR = register("cloud_pillar", new CloudPillarBlock(Settings.create().mapColor(MapColor.GRAY).replaceable().hardness(0.5F).resistance(0).sounds(BlockSoundGroup.WOOL)));
Block CLOUD = register("cloud", new PoreousCloudBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, () -> UBlocks.SOGGY_CLOUD));
Block CLOUD_SLAB = register("cloud_slab", new CloudSlabBlock(Settings.copy(CLOUD), true, () -> UBlocks.SOGGY_CLOUD_SLAB));
SoggyCloudBlock SOGGY_CLOUD = register("soggy_cloud", new SoggyCloudBlock(Settings.copy(CLOUD), () -> UBlocks.CLOUD));
SoggyCloudSlabBlock SOGGY_CLOUD_SLAB = register("soggy_cloud_slab", new SoggyCloudSlabBlock(Settings.copy(CLOUD), () -> UBlocks.CLOUD_SLAB));
Block DENSE_CLOUD = register("dense_cloud", new CloudBlock(Settings.create().mapColor(MapColor.GRAY).hardness(0.5F).resistance(0).sounds(BlockSoundGroup.WOOL), false));
Block DENSE_CLOUD_SLAB = register("dense_cloud_slab", new CloudSlabBlock(Settings.copy(DENSE_CLOUD), false, null));
Block CLOUD_PILLAR = register("cloud_pillar", new CloudPillarBlock(Settings.create().mapColor(MapColor.GRAY).hardness(0.5F).resistance(0).sounds(BlockSoundGroup.WOOL)));
SegmentedCropBlock OATS = register("oats", SegmentedCropBlock.create(11, 5, AbstractBlock.Settings.copy(Blocks.WHEAT), () -> UItems.OAT_SEEDS, null, null));
SegmentedCropBlock OATS_STEM = register("oats_stem", OATS.createNext(5));

View file

@ -4,14 +4,11 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.EquineContext;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.TransparentBlock;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ai.pathing.NavigationType;
import net.minecraft.entity.player.PlayerEntity;
@ -29,7 +26,7 @@ import net.minecraft.world.World;
public class CloudBlock extends TransparentBlock {
private final boolean meltable;
protected final boolean meltable;
public CloudBlock(Settings settings, boolean meltable) {
super((meltable ? settings.ticksRandomly() : settings).nonOpaque());
@ -43,10 +40,6 @@ public class CloudBlock extends TransparentBlock {
if (bounce) {
entity.addVelocity(0, 0.2F, 0);
}
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getTranslucent(),
UBlocks.MYSTERIOUS_EGG, UBlocks.SLIME_PUSTULE,
UBlocks.CLOUD, UBlocks.DENSE_CLOUD, UBlocks.CLOUD_PILLAR
);
}
@Override
@ -150,9 +143,11 @@ public class CloudBlock extends TransparentBlock {
@Override
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
if (meltable && world.getLightLevel(LightType.BLOCK, pos) > 11) {
if (meltable) {
if (world.getLightLevel(LightType.BLOCK, pos) > 11) {
dropStacks(state, world, pos);
world.removeBlock(pos, false);
}
}
}
}

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.EquineContext;
@ -24,8 +26,8 @@ public class CloudSlabBlock extends WaterloggableCloudBlock {
private static final VoxelShape BOTTOM_SHAPE = Block.createCuboidShape(0.0, 0.0, 0.0, 16.0, 8.0, 16.0);
private static final VoxelShape TOP_SHAPE = Block.createCuboidShape(0.0, 8.0, 0.0, 16.0, 16.0, 16.0);
public CloudSlabBlock(Settings settings, boolean meltable) {
super(settings, meltable);
public CloudSlabBlock(Settings settings, boolean meltable, @Nullable Supplier<Soakable> soggyBlock) {
super(settings, meltable, soggyBlock);
}
@Override

View file

@ -0,0 +1,41 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
public class PoreousCloudBlock extends CloudBlock implements Soakable {
@Nullable
private final Supplier<Soakable> soggyBlock;
public PoreousCloudBlock(Settings settings, boolean meltable, @Nullable Supplier<Soakable> soggyBlock) {
super(settings.nonOpaque(), meltable);
this.soggyBlock = soggyBlock;
}
@Nullable
@Override
public BlockState getSoggyState(int moisture) {
return soggyBlock == null ? null : soggyBlock.get().getSoggyState(moisture);
}
@Override
public int getMoisture(BlockState state) {
return 0;
}
@Override
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
if (soggyBlock != null && world.hasRain(pos) && world.isAir(pos.up())) {
world.setBlockState(pos, Soakable.copyProperties(state, soggyBlock.get().getSoggyState(random.nextBetween(1, 5))));
return;
}
super.randomTick(state, world, pos, random);
}
}

View file

@ -0,0 +1,115 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.Arrays;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.state.property.IntProperty;
import net.minecraft.state.property.Property;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Util;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent;
public interface Soakable {
IntProperty MOISTURE = IntProperty.of("moisture", 1, 7);
Direction[] DIRECTIONS = Arrays.stream(Direction.values()).filter(d -> d != Direction.UP).toArray(Direction[]::new);
BlockState getSoggyState(int moisture);
int getMoisture(BlockState state);
static void addMoistureParticles(BlockState state, World world, BlockPos pos, Random random) {
if (random.nextInt(5) == 0) {
world.addParticle(ParticleTypes.DRIPPING_WATER,
pos.getX() + random.nextFloat(),
pos.getY(),
pos.getZ() + random.nextFloat(),
0, 0, 0
);
}
}
static ActionResult tryCollectMoisture(Block dryBlock, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ItemStack stack = player.getStackInHand(hand);
if (stack.getItem() == Items.GLASS_BOTTLE) {
if (!player.isCreative()) {
stack.split(1);
}
if (stack.isEmpty()) {
player.setStackInHand(hand, Items.POTION.getDefaultStack());
} else {
player.giveItemStack(Items.POTION.getDefaultStack());
}
world.playSound(player, player.getX(), player.getY(), player.getZ(), USounds.Vanilla.ITEM_BOTTLE_FILL, SoundCategory.NEUTRAL, 1, 1);
world.emitGameEvent(player, GameEvent.FLUID_PICKUP, pos);
updateMoisture(dryBlock, state, world, pos, state.get(MOISTURE) - 1);
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
static void tickMoisture(Block dryBlock, BlockState state, ServerWorld world, BlockPos pos, Random random) {
int moisture = state.get(MOISTURE);
if (world.hasRain(pos) && world.isAir(pos.up())) {
if (moisture < 7) {
world.setBlockState(pos, state.with(MOISTURE, moisture + 1));
}
} else {
if (moisture > 1) {
BlockPos neighborPos = pos.offset(Util.getRandom(Soakable.DIRECTIONS, random));
BlockState neighborState = world.getBlockState(neighborPos);
if (neighborState.getBlock() instanceof Soakable soakable && soakable.getMoisture(neighborState) < moisture) {
int half = Math.max(1, moisture / 2);
@Nullable
BlockState newNeighborState = soakable.getSoggyState(half);
if (newNeighborState != null) {
updateMoisture(dryBlock, state, world, pos, moisture - half);
world.setBlockState(neighborPos, soakable.getSoggyState(half));
world.emitGameEvent(null, GameEvent.BLOCK_CHANGE, neighborPos);
return;
}
}
}
updateMoisture(dryBlock, state, world, pos, moisture - 1);
}
}
private static void updateMoisture(Block dryBlock, BlockState state, World world, BlockPos pos, int newMoisture) {
if (newMoisture <= 0) {
world.setBlockState(pos, copyProperties(state, dryBlock.getDefaultState()));
} else {
world.setBlockState(pos, state.with(MOISTURE, newMoisture));
}
world.playSound(null, pos, SoundEvents.ENTITY_SALMON_FLOP, SoundCategory.BLOCKS, 1, (float)world.random.nextTriangular(0.5, 0.3F));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
static BlockState copyProperties(BlockState from, BlockState to) {
for (Property property : from.getProperties()) {
to = to.withIfExists(property, from.get(property));
}
return to;
}
}

View file

@ -0,0 +1,57 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.function.Supplier;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
public class SoggyCloudBlock extends CloudBlock implements Soakable {
private final Supplier<Block> dryBlock;
public SoggyCloudBlock(Settings settings, Supplier<Block> dryBlock) {
super(settings.ticksRandomly(), false);
setDefaultState(getDefaultState().with(MOISTURE, 7));
this.dryBlock = dryBlock;
}
@Override
public BlockState getSoggyState(int moisture) {
return getDefaultState().with(MOISTURE, moisture);
}
@Override
public int getMoisture(BlockState state) {
return state.get(MOISTURE);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(MOISTURE);
}
@Override
@Deprecated
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
return Soakable.tryCollectMoisture(dryBlock.get(), state, world, pos, player, hand, hit);
}
@Override
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
Soakable.addMoistureParticles(state, world, pos, random);
}
@Override
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
Soakable.tickMoisture(dryBlock.get(), state, world, pos, random);
}
}

View file

@ -0,0 +1,58 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.function.Supplier;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
public class SoggyCloudSlabBlock extends CloudSlabBlock {
private final Supplier<Block> dryBlock;
public SoggyCloudSlabBlock(Settings settings, Supplier<Block> dryBlock) {
super(settings.ticksRandomly(), false, null);
setDefaultState(getDefaultState().with(MOISTURE, 7));
this.dryBlock = dryBlock;
}
@Override
public BlockState getSoggyState(int moisture) {
return getDefaultState().with(MOISTURE, moisture);
}
@Override
public int getMoisture(BlockState state) {
return state.get(MOISTURE);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(MOISTURE);
}
@Override
@Deprecated
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
return Soakable.tryCollectMoisture(dryBlock.get(), state, world, pos, player, hand, hit);
}
@Override
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
Soakable.addMoistureParticles(state, world, pos, random);
}
@Override
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
Soakable.tickMoisture(dryBlock.get(), state, world, pos, random);
}
}

View file

@ -1,36 +0,0 @@
package com.minelittlepony.unicopia.block.cloud;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.IntProperty;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class StormyCloudBlock extends CloudBlock {
private static final int MAX_CHARGE = 6;
private static final IntProperty CHARGE = IntProperty.of("charge", 0, MAX_CHARGE);
public StormyCloudBlock(Settings settings, boolean meltable) {
super(settings, meltable);
setDefaultState(getDefaultState().with(CHARGE, 0));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(CHARGE);
}
@Override
public void onLandedUpon(World world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
super.onLandedUpon(world, state, pos, entity, fallDistance);
if (state.get(CHARGE) < MAX_CHARGE) {
if (world.random.nextInt(5) == 0) {
world.setBlockState(pos, state.cycle(CHARGE));
}
} else {
}
}
}

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.EquineContext;
@ -20,11 +22,12 @@ import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
public class WaterloggableCloudBlock extends CloudBlock implements Waterloggable {
public class WaterloggableCloudBlock extends PoreousCloudBlock implements Waterloggable {
public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
public WaterloggableCloudBlock(Settings settings, boolean meltable) {
super(settings, meltable);
public WaterloggableCloudBlock(Settings settings, boolean meltable, @Nullable Supplier<Soakable> soggyBlock) {
super(settings, meltable, soggyBlock);
setDefaultState(getDefaultState().with(WATERLOGGED, false));
}
@Override

View file

@ -175,7 +175,8 @@ public interface URenderers {
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getTranslucent(),
UBlocks.MYSTERIOUS_EGG, UBlocks.SLIME_PUSTULE,
UBlocks.CLOUD, UBlocks.DENSE_CLOUD, UBlocks.CLOUD_PILLAR,
UBlocks.CLOUD_SLAB, UBlocks.DENSE_CLOUD_SLAB
UBlocks.CLOUD_SLAB, UBlocks.DENSE_CLOUD_SLAB,
UBlocks.SOGGY_CLOUD, UBlocks.SOGGY_CLOUD_SLAB
);
// for lava boats
BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), Fluids.LAVA, Fluids.FLOWING_LAVA);

View file

@ -1,7 +1,5 @@
package com.minelittlepony.unicopia.item.cloud;
import com.minelittlepony.unicopia.block.cloud.CloudBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
@ -16,6 +14,7 @@ import net.minecraft.util.TypedActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class CloudBlockItem
@ -26,22 +25,17 @@ extends BlockItem {
@Override
public ActionResult useOnBlock(ItemUsageContext context) {
BlockState state = context.getWorld().getBlockState(context.getBlockPos());
if (state.getBlock() instanceof CloudBlock) {
return super.useOnBlock(context);
}
return ActionResult.PASS;
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
Vec3d targetPos = user.getEyePos().add(user.getRotationVec(1).multiply(1, 1.5, 1).normalize().multiply(2));
ItemPlacementContext context = new ItemPlacementContext(user, hand, user.getStackInHand(hand), new BlockHitResult(
user.getEyePos(),
targetPos,
Direction.UP,
BlockPos.ofFloored(user.getEyePos()),
BlockPos.ofFloored(targetPos),
true
));

View file

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "unicopia:block/soggy_cloud" }
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"type=double": { "model": "unicopia:block/soggy_cloud" },
"type=bottom": { "model": "unicopia:block/soggy_cloud_slab" },
"type=top": { "model": "unicopia:block/soggy_cloud_slab_top" }
}
}

View file

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "unicopia:block/cloud" }
}
}

View file

@ -219,6 +219,8 @@
"block.unicopia.cloud": "Cloud",
"block.unicopia.cloud_slab": "Cloud Slab",
"block.unicopia.soggy_cloud": "Soggy Cloud",
"block.unicopia.soggy_cloud_slab": "Soggy Cloud Slab",
"block.unicopia.cloud_pillar": "Cloud Pillar",
"block.unicopia.dense_cloud": "Dense Cloud",
"block.unicopia.dense_cloud_slab": "Dense Cloud Slab",

View file

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"bottom": "unicopia:block/cloud",
"top": "unicopia:block/soggy_cloud_top",
"side": "unicopia:block/soggy_cloud_side"
}
}

View file

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/slab",
"textures": {
"bottom": "unicopia:block/cloud",
"side": "unicopia:block/soggy_cloud_slab_side",
"top": "unicopia:block/soggy_cloud_top"
}
}

View file

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/slab_top",
"textures": {
"bottom": "unicopia:block/cloud",
"side": "unicopia:block/soggy_cloud_slab_side",
"top": "unicopia:block/soggy_cloud_top"
}
}

View file

@ -0,0 +1,3 @@
{
"parent": "unicopia:block/cloud"
}

View file

@ -0,0 +1,3 @@
{
"parent": "unicopia:block/cloud_slab"
}

View file

@ -0,0 +1,3 @@
{
"parent": "unicopia:block/cloud"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB