Added cloud blocks and cloud pillars

This commit is contained in:
Sollace 2023-10-18 18:52:59 +01:00
parent 15071ccd72
commit b9318547db
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
28 changed files with 523 additions and 33 deletions

View file

@ -17,7 +17,14 @@ public interface EquineContext {
return getSpecies().composite(); return getSpecies().composite();
} }
default float getCloudWalkingStrength() {
return 0;
}
static EquineContext of(ShapeContext context) { static EquineContext of(ShapeContext context) {
if (context == ShapeContext.absent()) {
return Unicopia.SIDE.getPony().map(EquineContext.class::cast).orElse(ABSENT);
}
return context instanceof EquineContext c ? c : ABSENT; return context instanceof EquineContext c ? c : ABSENT;
} }

View file

@ -1,12 +1,17 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.EquineContext;
import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CropBlock; import net.minecraft.block.CropBlock;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
@ -102,4 +107,14 @@ public class RockCropBlock extends CropBlock {
protected ItemConvertible getSeedsItem() { protected ItemConvertible getSeedsItem() {
return UItems.PEBBLES; return UItems.PEBBLES;
} }
@Override
@Nullable
public final BlockState getPlacementState(ItemPlacementContext context) {
if (!EquineContext.of(context).getCompositeRace().any(Race::canUseEarth)) {
return null;
}
return super.getPlacementState(context);
}
} }

View file

@ -5,6 +5,8 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.block.cloud.CloudBlock;
import com.minelittlepony.unicopia.block.cloud.CloudPillarBlock;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry; import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
import com.minelittlepony.unicopia.server.world.UTreeGen; import com.minelittlepony.unicopia.server.world.UTreeGen;
@ -125,6 +127,10 @@ public interface UBlocks {
Block MYSTERIOUS_EGG = register("mysterious_egg", new PileBlock(Settings.copy(Blocks.SLIME_BLOCK), PileBlock.MYSTERIOUS_EGG_SHAPES), ItemGroups.NATURAL); 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 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)));
Block DENSE_CLOUD = register("dense_cloud", new CloudBlock(Settings.create().mapColor(MapColor.GRAY).replaceable().hardness(0.5F).resistance(0).sounds(BlockSoundGroup.WOOL)));
Block CLOUD_PILLAR = register("cloud_pillar", new CloudPillarBlock(Settings.create().mapColor(MapColor.GRAY).replaceable().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 = 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)); SegmentedCropBlock OATS_STEM = register("oats_stem", OATS.createNext(5));
SegmentedCropBlock OATS_CROWN = register("oats_crown", OATS_STEM.createNext(5)); SegmentedCropBlock OATS_CROWN = register("oats_crown", OATS_STEM.createNext(5));

View file

@ -0,0 +1,146 @@
package com.minelittlepony.unicopia.block.cloud;
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;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.EmptyBlockView;
import net.minecraft.world.World;
public class CloudBlock extends TransparentBlock {
public CloudBlock(Settings settings) {
super(settings.nonOpaque());
}
@Override
public void onEntityLand(BlockView world, Entity entity) {
boolean bounce = Math.abs(entity.getVelocity().y) > 0.3;
super.onEntityLand(world, entity);
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
public void onLandedUpon(World world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
entity.handleFallDamage(fallDistance, 0, world.getDamageSources().fall());
}
@Override
@Deprecated
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
if (entity instanceof PlayerEntity player && (player.getAbilities().flying || Pony.of(player).getPhysics().isFlying())) {
return;
}
if (entity.getVelocity().y < 0) {
float cloudWalking = EquineContext.of(entity).getCloudWalkingStrength();
if (cloudWalking > 0) {
entity.setVelocity(entity.getVelocity().multiply(1, 1 - cloudWalking, 1));
entity.addVelocity(0, 0.07, 0);
entity.setOnGround(true);
}
entity.setVelocity(entity.getVelocity().multiply(0.9F, 1, 0.9F));
} else {
entity.setVelocity(entity.getVelocity().multiply(0.9F));
}
}
@Override
public final VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
EquineContext equineContext = EquineContext.of(context);
if (!canInteract(state, world, pos, equineContext)) {
return VoxelShapes.empty();
}
return getOutlineShape(state, world, pos, context, equineContext);
}
@Override
@Deprecated
public final VoxelShape getCullingShape(BlockState state, BlockView world, BlockPos pos) {
return getOutlineShape(state, world, pos, ShapeContext.absent(), EquineContext.ABSENT);
}
@Override
@Deprecated
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return this.collidable ? state.getOutlineShape(world, pos, context) : VoxelShapes.empty();
}
@Override
@Nullable
public final BlockState getPlacementState(ItemPlacementContext context) {
EquineContext equineContext = EquineContext.of(context);
if (!canInteract(getDefaultState(), context.getWorld(), context.getBlockPos(), equineContext)) {
return null;
}
return getPlacementState(context, equineContext);
}
@Deprecated
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
EquineContext equineContext = EquineContext.of(context);
if (canInteract(state, context.getWorld(), context.getBlockPos(), equineContext)) {
return canReplace(state, context, equineContext);
}
return true;
}
@Deprecated
@Override
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
if (stateFrom.isOf(this)) {
return true;
}
VoxelShape shape = state.getCullingShape(EmptyBlockView.INSTANCE, BlockPos.ORIGIN);
VoxelShape shapeFrom = stateFrom.getCullingShape(EmptyBlockView.INSTANCE, BlockPos.ORIGIN);
return !shape.isEmpty() && !shapeFrom.isEmpty() && VoxelShapes.isSideCovered(shape, shapeFrom, direction);
}
@Override
@Deprecated
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
return true;
}
protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, EquineContext equineContext) {
return VoxelShapes.fullCube();
}
protected boolean canInteract(BlockState state, BlockView world, BlockPos pos, EquineContext context) {
return context.getCompositeRace().any(Race::canInteractWithClouds);
}
@SuppressWarnings("deprecation")
protected boolean canReplace(BlockState state, ItemPlacementContext context, EquineContext equineContext) {
return super.canReplace(state, context);
}
@Nullable
protected BlockState getPlacementState(ItemPlacementContext placementContext, EquineContext equineContext) {
return super.getPlacementState(placementContext);
}
}

View file

@ -0,0 +1,78 @@
package com.minelittlepony.unicopia.block.cloud;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.EquineContext;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
public class CloudPillarBlock extends CloudBlock {
private static final BooleanProperty NORTH = BooleanProperty.of("north");
private static final BooleanProperty SOUTH = BooleanProperty.of("south");
private static final Map<Direction, BooleanProperty> DIRECTION_PROPERTIES = Map.of(
Direction.UP, NORTH,
Direction.DOWN, SOUTH
);
private static final VoxelShape CORE_SHAPE = Block.createCuboidShape(1, 0, 1, 15, 16, 15);
private static final VoxelShape FOOT_SHAPE = Block.createCuboidShape(0, 0, 0, 16, 5, 16);
private static final VoxelShape CAP_SHAPE = FOOT_SHAPE.offset(0, 11F / 16F, 0);
private static final VoxelShape[] SHAPES = new VoxelShape[] {
CORE_SHAPE,
VoxelShapes.union(CORE_SHAPE, FOOT_SHAPE),
VoxelShapes.union(CORE_SHAPE, CAP_SHAPE),
VoxelShapes.union(CORE_SHAPE, FOOT_SHAPE, CAP_SHAPE)
};
// [0,0] [0,1]
// [1,0] [1,1]
public CloudPillarBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(NORTH, true).with(SOUTH, true));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(NORTH, SOUTH);
}
@Override
protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, EquineContext equineContext) {
return SHAPES[(state.get(NORTH) ? 0 : 2) + (state.get(SOUTH) ? 0 : 1)];
}
@Override
@Nullable
protected BlockState getPlacementState(ItemPlacementContext placementContext, EquineContext equineContext) {
BlockPos pos = placementContext.getBlockPos();
BlockState state = super.getPlacementState(placementContext, equineContext);
for (var property : DIRECTION_PROPERTIES.entrySet()) {
state = state.with(property.getValue(), placementContext.getWorld().getBlockState(pos.offset(property.getKey())).isOf(this));
}
return state;
}
@Deprecated
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
if (direction.getAxis() == Direction.Axis.Y) {
return state.with(DIRECTION_PROPERTIES.get(direction), neighborState.isOf(this));
}
return state;
}
}

View file

@ -0,0 +1,36 @@
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) {
super(settings);
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

@ -172,7 +172,10 @@ public interface URenderers {
}, TintedBlock.REGISTRY.stream().map(Block::asItem).filter(i -> i != Items.AIR).toArray(Item[]::new)); }, TintedBlock.REGISTRY.stream().map(Block::asItem).filter(i -> i != Items.AIR).toArray(Item[]::new));
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), UBlocks.TRANSLUCENT_BLOCKS.stream().toArray(Block[]::new)); BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), UBlocks.TRANSLUCENT_BLOCKS.stream().toArray(Block[]::new));
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getTranslucent(), UBlocks.MYSTERIOUS_EGG, UBlocks.SLIME_PUSTULE); BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getTranslucent(),
UBlocks.MYSTERIOUS_EGG, UBlocks.SLIME_PUSTULE,
UBlocks.CLOUD, UBlocks.DENSE_CLOUD, UBlocks.CLOUD_PILLAR
);
// for lava boats // for lava boats
BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), Fluids.LAVA, Fluids.FLOWING_LAVA); BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), Fluids.LAVA, Fluids.FLOWING_LAVA);

View file

@ -36,6 +36,8 @@ import com.minelittlepony.unicopia.util.*;
import it.unimi.dsi.fastutil.floats.Float2ObjectFunction; import it.unimi.dsi.fastutil.floats.Float2ObjectFunction;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.*; import net.minecraft.entity.*;
import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeInstance; import net.minecraft.entity.attribute.EntityAttributeInstance;
@ -548,6 +550,14 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
}); });
} }
@Override
public float getCloudWalkingStrength() {
Enchantment featherFalling = net.minecraft.enchantment.Enchantments.FEATHER_FALLING;
int maxLevel = featherFalling.getMaxLevel();
int level = EnchantmentHelper.getEquipmentLevel(featherFalling, entity);
return MathHelper.clamp(level / (float)maxLevel, 0, 1);
}
@Override @Override
public void setDirty() {} public void setDirty() {}

View file

@ -1,31 +0,0 @@
package com.minelittlepony.unicopia.item;
import java.util.function.Predicate;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.block.Block;
import net.minecraft.item.AliasedBlockItem;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.ActionResult;
public class RacePredicatedAliasedBlockItem extends AliasedBlockItem {
private Predicate<Race> predicate;
public RacePredicatedAliasedBlockItem(Block block, Settings settings, Predicate<Race> predicate) {
super(block, settings);
this.predicate = predicate;
}
@Override
public ActionResult useOnBlock(ItemUsageContext context) {
Pony pony = Pony.of(context.getPlayer());
if (pony == null || !predicate.test(pony.getObservedSpecies())) {
return ActionResult.FAIL;
}
return super.useOnBlock(context);
}
}

View file

@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.block.UWoodTypes; import com.minelittlepony.unicopia.block.UWoodTypes;
import com.minelittlepony.unicopia.entity.mob.AirBalloonEntity; import com.minelittlepony.unicopia.entity.mob.AirBalloonEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.item.cloud.CloudBlockItem;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry; import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
import com.minelittlepony.unicopia.item.group.UItemGroups; import com.minelittlepony.unicopia.item.group.UItemGroups;
@ -81,7 +82,7 @@ public interface UItems {
Item PINEAPPLE = register("pineapple", new PineappleItem(new Item.Settings().food(UFoodComponents.BANANA).maxDamage(3)), ItemGroups.FOOD_AND_DRINK); Item PINEAPPLE = register("pineapple", new PineappleItem(new Item.Settings().food(UFoodComponents.BANANA).maxDamage(3)), ItemGroups.FOOD_AND_DRINK);
Item PINEAPPLE_CROWN = register("pineapple_crown", new AliasedBlockItem(UBlocks.PINEAPPLE, new Item.Settings()), ItemGroups.NATURAL); Item PINEAPPLE_CROWN = register("pineapple_crown", new AliasedBlockItem(UBlocks.PINEAPPLE, new Item.Settings()), ItemGroups.NATURAL);
Item PEBBLES = register("pebbles", new RacePredicatedAliasedBlockItem(UBlocks.ROCKS, new Item.Settings(), Race::canUseEarth), ItemGroups.NATURAL); Item PEBBLES = register("pebbles", new AliasedBlockItem(UBlocks.ROCKS, new Item.Settings()), ItemGroups.NATURAL);
Item ROCK = register("rock", new HeavyProjectileItem(new Item.Settings(), 3), ItemGroups.NATURAL); Item ROCK = register("rock", new HeavyProjectileItem(new Item.Settings(), 3), ItemGroups.NATURAL);
Item WEIRD_ROCK = register("weird_rock", new BluntWeaponItem(new Item.Settings(), ImmutableMultimap.of( Item WEIRD_ROCK = register("weird_rock", new BluntWeaponItem(new Item.Settings(), ImmutableMultimap.of(
EntityAttributes.GENERIC_LUCK, new EntityAttributeModifier(BluntWeaponItem.LUCK_MODIFIER_ID, "Weapon modifier", 9, EntityAttributeModifier.Operation.ADDITION) EntityAttributes.GENERIC_LUCK, new EntityAttributeModifier(BluntWeaponItem.LUCK_MODIFIER_ID, "Weapon modifier", 9, EntityAttributeModifier.Operation.ADDITION)
@ -143,6 +144,10 @@ public interface UItems {
Item GIANT_BALLOON = register("giant_balloon", new HotAirBalloonItem(new Item.Settings().maxCount(1)), ItemGroups.TOOLS); Item GIANT_BALLOON = register("giant_balloon", new HotAirBalloonItem(new Item.Settings().maxCount(1)), ItemGroups.TOOLS);
Item CLOUD = register("cloud", new CloudBlockItem(UBlocks.CLOUD, new Item.Settings()), ItemGroups.NATURAL);
Item DENSE_CLOUD = register("dense_cloud", new CloudBlockItem(UBlocks.DENSE_CLOUD, new Item.Settings()), ItemGroups.NATURAL);
Item CLOUD_PILLAR = register("cloud_pillar", new CloudBlockItem(UBlocks.CLOUD_PILLAR, new Item.Settings()), ItemGroups.NATURAL);
AmuletItem PEGASUS_AMULET = register("pegasus_amulet", new PegasusAmuletItem(new FabricItemSettings() AmuletItem PEGASUS_AMULET = register("pegasus_amulet", new PegasusAmuletItem(new FabricItemSettings()
.maxCount(1) .maxCount(1)
.maxDamage(890) .maxDamage(890)

View file

@ -0,0 +1,61 @@
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;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
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.world.World;
public class CloudBlockItem
extends BlockItem {
public CloudBlockItem(Block block, Item.Settings settings) {
super(block, settings);
}
@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) {
ItemPlacementContext context = new ItemPlacementContext(user, hand, user.getStackInHand(hand), new BlockHitResult(
user.getEyePos(),
Direction.UP,
BlockPos.ofFloored(user.getEyePos()),
true
));
ActionResult actionResult = place(context);
if (actionResult.isAccepted()) {
return TypedActionResult.success(context.getStack(), world.isClient);
}
return TypedActionResult.pass(user.getStackInHand(hand));
}
@Override
protected boolean canPlace(ItemPlacementContext context, BlockState state) {
return !checkStatePlacement() || state.canPlaceAt(context.getWorld(), context.getBlockPos());
}
}

View file

@ -34,4 +34,9 @@ abstract class MixinEntityShapeContext implements EquineContext {
public Race.Composite getCompositeRace() { public Race.Composite getCompositeRace() {
return equineContext.getCompositeRace(); return equineContext.getCompositeRace();
} }
@Override
public float getCloudWalkingStrength() {
return equineContext.getCloudWalkingStrength();
}
} }

View file

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

View file

@ -0,0 +1,28 @@
{
"multipart": [
{
"apply": {
"model": "unicopia:block/cloud_pillar_middle"
}
},
{
"apply": {
"model": "unicopia:block/cloud_pillar_end",
"uvlock": true,
"x": 180
},
"when": {
"north": false
}
},
{
"apply": {
"model": "unicopia:block/cloud_pillar_end",
"uvlock": true
},
"when": {
"south": false
}
}
]
}

View file

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

View file

@ -217,6 +217,10 @@
"block.unicopia.chiselled_chitin_slab": "Chiselled Chitin Slab", "block.unicopia.chiselled_chitin_slab": "Chiselled Chitin Slab",
"block.unicopia.chiselled_chitin_stairs": "Chiselled Chitin Stairs", "block.unicopia.chiselled_chitin_stairs": "Chiselled Chitin Stairs",
"block.unicopia.cloud": "Cloud",
"block.unicopia.cloud_pillar": "Cloud Pillar",
"block.unicopia.dense_cloud": "Dense Cloud",
"block.unicopia.oats": "Oats", "block.unicopia.oats": "Oats",
"block.unicopia.oats_stem": "Oats", "block.unicopia.oats_stem": "Oats",
"block.unicopia.oats_crown": "Oats", "block.unicopia.oats_crown": "Oats",

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "unicopia:block/cloud"
}
}

View file

@ -0,0 +1,21 @@
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"top": "unicopia:block/cloud_pillar_top",
"side": "unicopia:block/cloud_pillar_side_end"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 5, 16],
"faces": {
"north": {"uv": [0, 11, 16, 16], "texture": "#side"},
"east": {"uv": [0, 11, 16, 16], "texture": "#side"},
"south": {"uv": [0, 11, 16, 16], "texture": "#side"},
"west": {"uv": [0, 11, 16, 16], "texture": "#side"},
"up": {"uv": [0, 0, 16, 16], "texture": "#top"},
"down": {"uv": [0, 0, 16, 16], "texture": "#top", "cullface": "down"}
}
}
]
}

View file

@ -0,0 +1,21 @@
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"top": "unicopia:block/cloud_pillar_top",
"side": "unicopia:block/cloud_pillar_side"
},
"elements": [
{
"from": [1, 0, 1],
"to": [15, 16, 15],
"faces": {
"north": {"uv": [1, 0, 15, 16], "texture": "#side"},
"east": {"uv": [1, 0, 15, 16], "texture": "#side"},
"south": {"uv": [1, 0, 15, 16], "texture": "#side"},
"west": {"uv": [1, 0, 15, 16], "texture": "#side"},
"up": {"uv": [1, 1, 15, 15], "texture": "#top", "cullface": "up"},
"down": {"uv": [1, 1, 15, 15], "texture": "#top", "cullface": "down"}
}
}
]
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "unicopia:block/dense_cloud"
}
}

View file

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

View file

@ -0,0 +1,47 @@
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"top": "unicopia:block/cloud_pillar_top",
"side": "unicopia:block/cloud_pillar_side",
"side_end": "unicopia:block/cloud_pillar_side_end",
"particle": "unicopia:block/cloud_pillar_side"
},
"elements": [
{
"from": [2, 1, 2],
"to": [14, 15, 14],
"faces": {
"north": {"uv": [1, 0, 15, 16], "texture": "#side"},
"east": {"uv": [1, 0, 15, 16], "texture": "#side"},
"south": {"uv": [1, 0, 15, 16], "texture": "#side"},
"west": {"uv": [1, 0, 15, 16], "texture": "#side"},
"up": {"uv": [1, 1, 15, 15], "texture": "#top"},
"down": {"uv": [1, 1, 15, 15], "texture": "#top"}
}
},
{
"from": [0, 0, 0],
"to": [16, 5, 16],
"faces": {
"north": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"east": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"south": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"west": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"up": {"uv": [0, 0, 16, 16], "texture": "#top"},
"down": {"uv": [0, 0, 16, 16], "texture": "#top"}
}
},
{
"from": [0, 11, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"east": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"south": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"west": {"uv": [0, 11, 16, 16], "texture": "#side_end"},
"up": {"uv": [0, 0, 16, 16], "texture": "#top"},
"down": {"uv": [0, 0, 16, 16], "texture": "#top"}
}
}
]
}

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB