From b9318547db064d935c01c77a8368f6c800a661ce Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Oct 2023 18:52:59 +0100 Subject: [PATCH] Added cloud blocks and cloud pillars --- .../unicopia/EquineContext.java | 7 + .../unicopia/block/RockCropBlock.java | 15 ++ .../unicopia/block/UBlocks.java | 6 + .../unicopia/block/cloud/CloudBlock.java | 146 ++++++++++++++++++ .../block/cloud/CloudPillarBlock.java | 78 ++++++++++ .../block/cloud/StormyCloudBlock.java | 36 +++++ .../unicopia/client/URenderers.java | 5 +- .../unicopia/entity/Living.java | 10 ++ .../item/RacePredicatedAliasedBlockItem.java | 31 ---- .../minelittlepony/unicopia/item/UItems.java | 7 +- .../unicopia/item/cloud/CloudBlockItem.java | 61 ++++++++ .../mixin/MixinEntityShapeContext.java | 5 + .../assets/unicopia/blockstates/cloud.json | 5 + .../unicopia/blockstates/cloud_pillar.json | 28 ++++ .../unicopia/blockstates/dense_cloud.json | 5 + .../resources/assets/unicopia/lang/en_us.json | 4 + .../assets/unicopia/models/block/cloud.json | 6 + .../models/block/cloud_pillar_end.json | 21 +++ .../models/block/cloud_pillar_middle.json | 21 +++ .../unicopia/models/block/dense_cloud.json | 6 + .../assets/unicopia/models/item/cloud.json | 3 + .../unicopia/models/item/cloud_pillar.json | 47 ++++++ .../unicopia/models/item/dense_cloud.json | 3 + .../assets/unicopia/textures/block/cloud.png | Bin 0 -> 6694 bytes .../textures/block/cloud_pillar_side.png | Bin 0 -> 7056 bytes .../textures/block/cloud_pillar_side_end.png | Bin 0 -> 7263 bytes .../textures/block/cloud_pillar_top.png | Bin 0 -> 7090 bytes .../unicopia/textures/block/dense_cloud.png | Bin 0 -> 6926 bytes 28 files changed, 523 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java create mode 100644 src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java create mode 100644 src/main/java/com/minelittlepony/unicopia/block/cloud/StormyCloudBlock.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java create mode 100644 src/main/java/com/minelittlepony/unicopia/item/cloud/CloudBlockItem.java create mode 100644 src/main/resources/assets/unicopia/blockstates/cloud.json create mode 100644 src/main/resources/assets/unicopia/blockstates/cloud_pillar.json create mode 100644 src/main/resources/assets/unicopia/blockstates/dense_cloud.json create mode 100644 src/main/resources/assets/unicopia/models/block/cloud.json create mode 100644 src/main/resources/assets/unicopia/models/block/cloud_pillar_end.json create mode 100644 src/main/resources/assets/unicopia/models/block/cloud_pillar_middle.json create mode 100644 src/main/resources/assets/unicopia/models/block/dense_cloud.json create mode 100644 src/main/resources/assets/unicopia/models/item/cloud.json create mode 100644 src/main/resources/assets/unicopia/models/item/cloud_pillar.json create mode 100644 src/main/resources/assets/unicopia/models/item/dense_cloud.json create mode 100644 src/main/resources/assets/unicopia/textures/block/cloud.png create mode 100644 src/main/resources/assets/unicopia/textures/block/cloud_pillar_side.png create mode 100644 src/main/resources/assets/unicopia/textures/block/cloud_pillar_side_end.png create mode 100644 src/main/resources/assets/unicopia/textures/block/cloud_pillar_top.png create mode 100644 src/main/resources/assets/unicopia/textures/block/dense_cloud.png diff --git a/src/main/java/com/minelittlepony/unicopia/EquineContext.java b/src/main/java/com/minelittlepony/unicopia/EquineContext.java index a28433c4..ed307b09 100644 --- a/src/main/java/com/minelittlepony/unicopia/EquineContext.java +++ b/src/main/java/com/minelittlepony/unicopia/EquineContext.java @@ -17,7 +17,14 @@ public interface EquineContext { return getSpecies().composite(); } + default float getCloudWalkingStrength() { + return 0; + } + 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; } diff --git a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java index 0a9995e5..b89e89b5 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java @@ -1,12 +1,17 @@ package com.minelittlepony.unicopia.block; +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.EquineContext; import com.minelittlepony.unicopia.EquinePredicates; +import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.item.UItems; import net.minecraft.block.BlockState; import net.minecraft.block.CropBlock; import net.minecraft.block.ShapeContext; import net.minecraft.item.ItemConvertible; +import net.minecraft.item.ItemPlacementContext; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; @@ -102,4 +107,14 @@ public class RockCropBlock extends CropBlock { protected ItemConvertible getSeedsItem() { 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); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index d8859c97..b77cefd4 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -5,6 +5,8 @@ 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.item.UItems; import com.minelittlepony.unicopia.item.group.ItemGroupRegistry; 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 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_STEM = register("oats_stem", OATS.createNext(5)); SegmentedCropBlock OATS_CROWN = register("oats_crown", OATS_STEM.createNext(5)); diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java new file mode 100644 index 00000000..0325568d --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -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); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java new file mode 100644 index 00000000..8e85985d --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudPillarBlock.java @@ -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_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 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; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/StormyCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/StormyCloudBlock.java new file mode 100644 index 00000000..232743c3 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/StormyCloudBlock.java @@ -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 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 { + + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index cb118590..c747b2aa 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -172,7 +172,10 @@ public interface URenderers { }, 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.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 BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), Fluids.LAVA, Fluids.FLOWING_LAVA); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 17d53f73..0b721be2 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -36,6 +36,8 @@ import com.minelittlepony.unicopia.util.*; import it.unimi.dsi.fastutil.floats.Float2ObjectFunction; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.*; import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.attribute.EntityAttributeInstance; @@ -548,6 +550,14 @@ public abstract class Living implements Equine, 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 public void setDirty() {} diff --git a/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java b/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java deleted file mode 100644 index f2abdf67..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/RacePredicatedAliasedBlockItem.java +++ /dev/null @@ -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 predicate; - - public RacePredicatedAliasedBlockItem(Block block, Settings settings, Predicate 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); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index 041811ca..dd29fa11 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.block.UBlocks; import com.minelittlepony.unicopia.block.UWoodTypes; import com.minelittlepony.unicopia.entity.mob.AirBalloonEntity; 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.group.ItemGroupRegistry; 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_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 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) @@ -143,6 +144,10 @@ public interface UItems { 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() .maxCount(1) .maxDamage(890) diff --git a/src/main/java/com/minelittlepony/unicopia/item/cloud/CloudBlockItem.java b/src/main/java/com/minelittlepony/unicopia/item/cloud/CloudBlockItem.java new file mode 100644 index 00000000..3a59c0fc --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/cloud/CloudBlockItem.java @@ -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 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()); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityShapeContext.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityShapeContext.java index fbd059ad..93647abb 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityShapeContext.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEntityShapeContext.java @@ -34,4 +34,9 @@ abstract class MixinEntityShapeContext implements EquineContext { public Race.Composite getCompositeRace() { return equineContext.getCompositeRace(); } + + @Override + public float getCloudWalkingStrength() { + return equineContext.getCloudWalkingStrength(); + } } diff --git a/src/main/resources/assets/unicopia/blockstates/cloud.json b/src/main/resources/assets/unicopia/blockstates/cloud.json new file mode 100644 index 00000000..3afda0a3 --- /dev/null +++ b/src/main/resources/assets/unicopia/blockstates/cloud.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "unicopia:block/cloud" } + } +} diff --git a/src/main/resources/assets/unicopia/blockstates/cloud_pillar.json b/src/main/resources/assets/unicopia/blockstates/cloud_pillar.json new file mode 100644 index 00000000..46dafadc --- /dev/null +++ b/src/main/resources/assets/unicopia/blockstates/cloud_pillar.json @@ -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 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/blockstates/dense_cloud.json b/src/main/resources/assets/unicopia/blockstates/dense_cloud.json new file mode 100644 index 00000000..53ceace7 --- /dev/null +++ b/src/main/resources/assets/unicopia/blockstates/dense_cloud.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "unicopia:block/dense_cloud" } + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 88bf1146..1e847754 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -216,6 +216,10 @@ "block.unicopia.chiselled_chitin_hull": "Chiselled Chitin Hull", "block.unicopia.chiselled_chitin_slab": "Chiselled Chitin Slab", "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_stem": "Oats", diff --git a/src/main/resources/assets/unicopia/models/block/cloud.json b/src/main/resources/assets/unicopia/models/block/cloud.json new file mode 100644 index 00000000..73923250 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/cloud.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "unicopia:block/cloud" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/block/cloud_pillar_end.json b/src/main/resources/assets/unicopia/models/block/cloud_pillar_end.json new file mode 100644 index 00000000..d07524e5 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/cloud_pillar_end.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/block/cloud_pillar_middle.json b/src/main/resources/assets/unicopia/models/block/cloud_pillar_middle.json new file mode 100644 index 00000000..a4803ce6 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/cloud_pillar_middle.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/block/dense_cloud.json b/src/main/resources/assets/unicopia/models/block/dense_cloud.json new file mode 100644 index 00000000..e37ff40b --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/dense_cloud.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "unicopia:block/dense_cloud" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/item/cloud.json b/src/main/resources/assets/unicopia/models/item/cloud.json new file mode 100644 index 00000000..7babfca8 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/cloud.json @@ -0,0 +1,3 @@ +{ + "parent": "unicopia:block/cloud" +} diff --git a/src/main/resources/assets/unicopia/models/item/cloud_pillar.json b/src/main/resources/assets/unicopia/models/item/cloud_pillar.json new file mode 100644 index 00000000..2bbe230b --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/cloud_pillar.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/models/item/dense_cloud.json b/src/main/resources/assets/unicopia/models/item/dense_cloud.json new file mode 100644 index 00000000..e7d67c42 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/dense_cloud.json @@ -0,0 +1,3 @@ +{ + "parent": "unicopia:block/dense_cloud" +} diff --git a/src/main/resources/assets/unicopia/textures/block/cloud.png b/src/main/resources/assets/unicopia/textures/block/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..637090c2170033043f7496ae7c7bab2084807b53 GIT binary patch literal 6694 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 F{x2wC*oXiC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/unicopia/textures/block/cloud_pillar_side_end.png b/src/main/resources/assets/unicopia/textures/block/cloud_pillar_side_end.png new file mode 100644 index 0000000000000000000000000000000000000000..9f753ec74312a7049fc31b82ddf89a4529f29f4d GIT binary patch literal 7263 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/unicopia/textures/block/cloud_pillar_top.png b/src/main/resources/assets/unicopia/textures/block/cloud_pillar_top.png new file mode 100644 index 0000000000000000000000000000000000000000..2210ff1ebb4a512f4d50dd93079505df1d01d8ec GIT binary patch literal 7090 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/unicopia/textures/block/dense_cloud.png b/src/main/resources/assets/unicopia/textures/block/dense_cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..8bb716e17e32286117a05faf6e29004db3fdf900 GIT binary patch literal 6926 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 H(l_c~xh=}0 literal 0 HcmV?d00001