mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 19:46:42 +01:00
Fix some interactions with clouds and reimplement fallthrough logic
This commit is contained in:
parent
cd4b74b2ce
commit
91e84e7551
15 changed files with 223 additions and 199 deletions
|
@ -2,7 +2,7 @@ package com.minelittlepony.unicopia.block;
|
|||
|
||||
import java.util.Random;
|
||||
|
||||
import com.minelittlepony.unicopia.gas.CloudType;
|
||||
import com.minelittlepony.unicopia.gas.GasState;
|
||||
import com.minelittlepony.unicopia.gas.Gas;
|
||||
import com.minelittlepony.unicopia.particles.MagicParticleEffect;
|
||||
|
||||
|
@ -168,8 +168,8 @@ public class GlowingGemBlock extends TorchBlock implements Gas {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
return CloudType.ENCHANTED;
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return GasState.ENCHANTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,7 +8,7 @@ import com.minelittlepony.unicopia.gas.CloudFarmlandBlock;
|
|||
import com.minelittlepony.unicopia.gas.CloudFenceBlock;
|
||||
import com.minelittlepony.unicopia.gas.CloudSlabBlock;
|
||||
import com.minelittlepony.unicopia.gas.CloudStairsBlock;
|
||||
import com.minelittlepony.unicopia.gas.CloudType;
|
||||
import com.minelittlepony.unicopia.gas.GasState;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.structure.CustomSaplingGenerator;
|
||||
|
||||
|
@ -24,15 +24,15 @@ import net.minecraft.util.registry.Registry;
|
|||
|
||||
public interface UBlocks {
|
||||
CloudFarmlandBlock CLOUD_FARMLAND = register(new CloudFarmlandBlock(FabricBlockSettings.of(UMaterials.CLOUD).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.WOOL).build()), "cloud_farmland");
|
||||
CloudBlock CLOUD_BLOCK = register(new CloudBlock(CloudType.NORMAL), "cloud_block");
|
||||
CloudBlock ENCHANTED_CLOUD_BLOCK = register(new CloudBlock(CloudType.ENCHANTED), "enchanted_cloud_block");
|
||||
CloudBlock DENSE_CLOUD_BLOCK = register(new CloudBlock(CloudType.DENSE), "dense_cloud_block");
|
||||
CloudBlock CLOUD_BLOCK = register(new CloudBlock(GasState.NORMAL), "cloud_block");
|
||||
CloudBlock ENCHANTED_CLOUD_BLOCK = register(new CloudBlock(GasState.ENCHANTED), "enchanted_cloud_block");
|
||||
CloudBlock DENSE_CLOUD_BLOCK = register(new CloudBlock(GasState.DENSE), "dense_cloud_block");
|
||||
|
||||
CloudStairsBlock<CloudBlock> CLOUD_STAIRS = register(new CloudStairsBlock<>(CLOUD_BLOCK.getDefaultState(), CloudType.NORMAL.configure().build()), "cloud_stairs");
|
||||
CloudStairsBlock<CloudBlock> CLOUD_STAIRS = register(new CloudStairsBlock<>(CLOUD_BLOCK.getDefaultState(), GasState.NORMAL.configure().build()), "cloud_stairs");
|
||||
|
||||
CloudSlabBlock<CloudBlock> CLOUD_SLAB = register(new CloudSlabBlock<>(CLOUD_BLOCK.getDefaultState(), CloudType.NORMAL.configure().build()), "cloud_slab");
|
||||
CloudSlabBlock<CloudBlock> ENCHANTED_CLOUD_SLAB = register(new CloudSlabBlock<>(ENCHANTED_CLOUD_BLOCK.getDefaultState(), CloudType.ENCHANTED.configure().build()), "enchanted_cloud_slab");
|
||||
CloudSlabBlock<CloudBlock> DENSE_CLOUD_SLAB = register(new CloudSlabBlock<>(ENCHANTED_CLOUD_BLOCK.getDefaultState(), CloudType.DENSE.configure().build()), "dense_cloud_slab");
|
||||
CloudSlabBlock<CloudBlock> CLOUD_SLAB = register(new CloudSlabBlock<>(CLOUD_BLOCK.getDefaultState(), GasState.NORMAL.configure().build()), "cloud_slab");
|
||||
CloudSlabBlock<CloudBlock> ENCHANTED_CLOUD_SLAB = register(new CloudSlabBlock<>(ENCHANTED_CLOUD_BLOCK.getDefaultState(), GasState.ENCHANTED.configure().build()), "enchanted_cloud_slab");
|
||||
CloudSlabBlock<CloudBlock> DENSE_CLOUD_SLAB = register(new CloudSlabBlock<>(ENCHANTED_CLOUD_BLOCK.getDefaultState(), GasState.DENSE.configure().build()), "dense_cloud_slab");
|
||||
|
||||
CloudDoorBlock MISTED_GLASS_DOOR = register(new CloudDoorBlock(), "misted_glass_door");
|
||||
DutchDoorBlock LIBRARY_DOOR = register(new DutchDoorBlock(FabricBlockSettings.of(Material.WOOD).sounds(BlockSoundGroup.WOOD).hardness(3).build()), "library_door");
|
||||
|
@ -43,7 +43,7 @@ public interface UBlocks {
|
|||
|
||||
CloudAnvilBlock CLOUD_ANVIL = register(new CloudAnvilBlock(), "cloud_anvil");
|
||||
|
||||
CloudFenceBlock CLOUD_FENCE = register(new CloudFenceBlock(CloudType.NORMAL), "cloud_fence");
|
||||
CloudFenceBlock CLOUD_FENCE = register(new CloudFenceBlock(GasState.NORMAL), "cloud_fence");
|
||||
|
||||
TallCropBlock ALFALFA_CROPS = register(new TallCropBlock(FabricBlockSettings.of(Material.PLANT).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP).build()), "alfalfa_crops");
|
||||
|
||||
|
|
|
@ -4,12 +4,15 @@ import java.util.Random;
|
|||
|
||||
import com.minelittlepony.unicopia.util.WorldEvent;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.block.FabricBlockSettings;
|
||||
import net.fabricmc.fabric.api.tools.FabricToolTags;
|
||||
import net.minecraft.block.AnvilBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityContext;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
|
@ -17,6 +20,8 @@ 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.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
|
@ -63,16 +68,18 @@ public class CloudAnvilBlock extends AnvilBlock implements Gas {
|
|||
|
||||
@Override
|
||||
public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random rand) {
|
||||
BlockState below = world.getBlockState(pos.down());
|
||||
|
||||
if (below.getBlock() instanceof Gas) {
|
||||
if (((Gas)below.getBlock()).getGasType(below).isDense()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(world.getBlockState(pos.down()).getBlock() instanceof Gas)) {
|
||||
super.scheduledTick(state, world, pos, rand);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment(EnvType.CLIENT)
|
||||
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
|
||||
if (!(world.getBlockState(pos.down()).getBlock() instanceof Gas)) {
|
||||
super.randomDisplayTick(state, world, pos, random);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityCollision(BlockState state, World w, BlockPos pos, Entity entity) {
|
||||
|
@ -81,10 +88,32 @@ public class CloudAnvilBlock extends AnvilBlock implements Gas {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
return super.getOutlineShape(state, view, pos, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!getGasState(state).canTouch(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
return super.getCollisionShape(state, view, pos, context);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
if (!CloudType.NORMAL.canInteract(player)) {
|
||||
if (!GasState.NORMAL.canTouch(player)) {
|
||||
return -1;
|
||||
}
|
||||
return super.calcBlockBreakingDelta(state, player, world, pos);
|
||||
|
@ -92,7 +121,7 @@ public class CloudAnvilBlock extends AnvilBlock implements Gas {
|
|||
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
return CloudType.NORMAL;
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return GasState.NORMAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ import net.minecraft.world.World;
|
|||
|
||||
public class CloudBlock extends Block implements Gas, HoeUtil.Tillable {
|
||||
|
||||
private final CloudType variant;
|
||||
private final GasState variant;
|
||||
|
||||
public CloudBlock(CloudType variant) {
|
||||
public CloudBlock(GasState variant) {
|
||||
super(variant.configure()
|
||||
.ticksRandomly()
|
||||
.build()
|
||||
|
@ -39,29 +39,29 @@ public class CloudBlock extends Block implements Gas, HoeUtil.Tillable {
|
|||
|
||||
@Override
|
||||
public boolean isTranslucent(BlockState state, BlockView world, BlockPos pos) {
|
||||
return getGasType(state).isTranslucent();
|
||||
return getGasState(state).isTranslucent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
return super.getOutlineShape(state, view, pos, context);
|
||||
return VoxelShapes.fullCube();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canTouch(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
return super.getCollisionShape(state, view, pos, context);
|
||||
return collidable ? VoxelShapes.fullCube() : VoxelShapes.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,14 +115,14 @@ public class CloudBlock extends Block implements Gas, HoeUtil.Tillable {
|
|||
@Deprecated
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView worldIn, BlockPos pos) {
|
||||
if (CloudType.NORMAL.canInteract(player)) {
|
||||
if (GasState.NORMAL.canTouch(player)) {
|
||||
return super.calcBlockBreakingDelta(state, player, worldIn, pos);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return variant;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,13 +26,13 @@ public class CloudDoorBlock extends AbstractDoorBlock implements Gas {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
return CloudType.NORMAL;
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return GasState.NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
if (!getCanInteract(state, player)) {
|
||||
if (!getGasState(state).canTouch(player)) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
return super.onUse(state, worldIn, pos, player, hand, hit);
|
||||
|
@ -56,7 +56,7 @@ public class CloudDoorBlock extends AbstractDoorBlock implements Gas {
|
|||
@Deprecated
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView worldIn, BlockPos pos) {
|
||||
if (CloudType.NORMAL.canInteract(player)) {
|
||||
if (GasState.NORMAL.canTouch(player)) {
|
||||
return super.calcBlockBreakingDelta(state, player, worldIn, pos);
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -29,7 +29,7 @@ public class CloudFarmlandBlock extends FarmlandBlock implements Farmland, Gas {
|
|||
Gas cloud = ((Gas)beside.getBlock());
|
||||
|
||||
if (face.getAxis() == Axis.Y || cloud == this) {
|
||||
if (cloud.getGasType(beside) == getGasType(state)) {
|
||||
if (cloud.getGasState(beside) == getGasState(state)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class CloudFarmlandBlock extends FarmlandBlock implements Farmland, Gas {
|
|||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class CloudFarmlandBlock extends FarmlandBlock implements Farmland, Gas {
|
|||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canTouch(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -84,15 +84,15 @@ public class CloudFarmlandBlock extends FarmlandBlock implements Farmland, Gas {
|
|||
@Deprecated
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
if (CloudType.NORMAL.canInteract(player)) {
|
||||
if (GasState.NORMAL.canTouch(player)) {
|
||||
return super.calcBlockBreakingDelta(state, player, world, pos);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
return CloudType.NORMAL;
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return GasState.NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,20 +13,20 @@ import net.minecraft.world.World;
|
|||
|
||||
public class CloudFenceBlock extends FenceBlock implements Gas {
|
||||
|
||||
private final CloudType variant;
|
||||
private final GasState variant;
|
||||
|
||||
public CloudFenceBlock(CloudType variant) {
|
||||
public CloudFenceBlock(GasState variant) {
|
||||
super(variant.configure().build());
|
||||
this.variant = variant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTranslucent(BlockState state, BlockView world, BlockPos pos) {
|
||||
return getGasType(state).isTranslucent();
|
||||
return getGasState(state).isTranslucent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return variant;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class CloudFenceBlock extends FenceBlock implements Gas {
|
|||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class CloudFenceBlock extends FenceBlock implements Gas {
|
|||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canTouch(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class CloudFenceBlock extends FenceBlock implements Gas {
|
|||
@Deprecated
|
||||
@Override
|
||||
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
|
||||
if (CloudType.NORMAL.canInteract(player)) {
|
||||
if (GasState.NORMAL.canTouch(player)) {
|
||||
return super.calcBlockBreakingDelta(state, player, world, pos);
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -2,12 +2,17 @@ package com.minelittlepony.unicopia.gas;
|
|||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public interface CloudInteractionContext {
|
||||
|
||||
static CloudInteractionContext of(Entity entity) {
|
||||
return entity == null ? Impl.EMPTY : new Impl(entity);
|
||||
return entity == null ? empty() : new Impl(entity);
|
||||
}
|
||||
|
||||
static CloudInteractionContext empty() {
|
||||
return Impl.EMPTY;
|
||||
}
|
||||
|
||||
default boolean isPlayer() {
|
||||
|
@ -18,7 +23,15 @@ public interface CloudInteractionContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean canTouch(CloudType type);
|
||||
default ItemStack getHeldStack() {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
default boolean isEmpty() {
|
||||
return this == empty();
|
||||
}
|
||||
|
||||
boolean canTouch(GasState type);
|
||||
|
||||
interface Holder extends CloudInteractionContext {
|
||||
CloudInteractionContext getCloudInteractionContext();
|
||||
|
@ -34,20 +47,39 @@ public interface CloudInteractionContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
default boolean canTouch(CloudType type) {
|
||||
default ItemStack getHeldStack() {
|
||||
return getCloudInteractionContext().getHeldStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean canTouch(GasState type) {
|
||||
return getCloudInteractionContext().canTouch(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isEmpty() {
|
||||
return getCloudInteractionContext().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
class Impl implements CloudInteractionContext {
|
||||
public static final CloudInteractionContext EMPTY = type -> true;
|
||||
private static final CloudInteractionContext EMPTY = type -> true;
|
||||
|
||||
private final boolean isPlayer;
|
||||
private final boolean isPegasis;
|
||||
|
||||
private ItemStack main = ItemStack.EMPTY;
|
||||
|
||||
private Impl(Entity entity) {
|
||||
this.isPlayer = entity instanceof PlayerEntity;
|
||||
this.isPlayer = EquinePredicates.IS_PLAYER.test(entity);
|
||||
this.isPegasis = EquinePredicates.ENTITY_INTERACT_WITH_CLOUD_BLOCKS.test(entity);
|
||||
|
||||
if (entity instanceof LivingEntity) {
|
||||
main = ((LivingEntity)entity).getMainHandStack();
|
||||
if (main.isEmpty()) {
|
||||
main = ((LivingEntity)entity).getOffHandStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,8 +93,13 @@ public interface CloudInteractionContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canTouch(CloudType type) {
|
||||
return type.isTouchable(isPlayer()) || isPegasis();
|
||||
public boolean canTouch(GasState type) {
|
||||
return type.isTouchable(isPlayer(), isPegasis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getHeldStack() {
|
||||
return main;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,15 @@ public class CloudSlabBlock<T extends Block & Gas> extends AbstractSlabBlock<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState blockState) {
|
||||
return modelBlock.getGasType(blockState);
|
||||
public GasState getGasState(BlockState blockState) {
|
||||
return modelBlock.getGasState(blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canTouch(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class CloudSlabBlock<T extends Block & Gas> extends AbstractSlabBlock<T>
|
|||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,15 +21,15 @@ public class CloudStairsBlock<T extends Block & Gas> extends AbstractStairsBlock
|
|||
}
|
||||
|
||||
@Override
|
||||
public CloudType getGasType(BlockState state) {
|
||||
return baseBlock.getGasType(baseBlockState);
|
||||
public GasState getGasState(BlockState state) {
|
||||
return baseBlock.getGasState(baseBlockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class CloudStairsBlock<T extends Block & Gas> extends AbstractStairsBlock
|
|||
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, EntityContext context) {
|
||||
CloudInteractionContext ctx = (CloudInteractionContext)context;
|
||||
|
||||
if (!ctx.canTouch(getGasType(state))) {
|
||||
if (!getGasState(state).canPlace(ctx)) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,156 +1,53 @@
|
|||
package com.minelittlepony.unicopia.gas;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
|
||||
import net.minecraft.block.BedBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.block.FallingBlock;
|
||||
import net.minecraft.block.TorchBlock;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface Gas {
|
||||
|
||||
CloudType getGasType(BlockState blockState);
|
||||
|
||||
default boolean handleRayTraceSpecialCases(World world, BlockPos pos, BlockState state) {
|
||||
if (world.isClient) {
|
||||
PlayerEntity player = MinecraftClient.getInstance().player;
|
||||
|
||||
if (player.abilities.creativeMode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getCanInteract(state, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CloudType type = getGasType(state);
|
||||
|
||||
ItemStack main = player.getMainHandStack();
|
||||
if (main.isEmpty()) {
|
||||
main = player.getOffHandStack();
|
||||
}
|
||||
|
||||
if (!main.isEmpty() && main.getItem() instanceof BlockItem) {
|
||||
Block block = ((BlockItem)main.getItem()).getBlock();
|
||||
BlockState heldState = block.getDefaultState();
|
||||
|
||||
if (block == null || block.isAir(heldState)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block instanceof Gas) {
|
||||
CloudType other = ((Gas)block).getGasType(heldState);
|
||||
|
||||
if (other.canInteract(player)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EquinePredicates.PLAYER_PEGASUS.test(player)) {
|
||||
return type != CloudType.ENCHANTED;
|
||||
}
|
||||
|
||||
if (type == CloudType.NORMAL) {
|
||||
return !isPlacementExcempt(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isPlacementExcempt(Block block) {
|
||||
return block instanceof TorchBlock
|
||||
|| block instanceof BedBlock
|
||||
|| block instanceof ChestBlock;
|
||||
}
|
||||
GasState getGasState(BlockState blockState);
|
||||
|
||||
default boolean applyLanding(Entity entity, float fallDistance) {
|
||||
if (!entity.isSneaking()) {
|
||||
entity.handleFallDamage(fallDistance, 0);
|
||||
|
||||
return false;
|
||||
if (entity.isSneaking()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
entity.handleFallDamage(fallDistance, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean applyRebound(Entity entity) {
|
||||
Vec3d vel = entity.getVelocity();
|
||||
double y = vel.y;
|
||||
double y = entity.getVelocity().y;
|
||||
|
||||
if (!entity.isSneaking() && y < 0) {
|
||||
if (Math.abs(y) >= 0.25) {
|
||||
y = -y * 1.2;
|
||||
} else {
|
||||
y = 0;
|
||||
if (entity.isSneaking() || y >= 0 || Math.abs(y) < 0.25) {
|
||||
return false;
|
||||
}
|
||||
entity.setVelocity(vel.x, y, vel.z);
|
||||
|
||||
entity.setVelocity(entity.getVelocity().multiply(1, -1.2, 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean applyBouncyness(BlockState state, Entity entity) {
|
||||
if (getCanInteract(state, entity)) {
|
||||
if (!getGasState(state).canTouch(entity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec3d vel = entity.getVelocity();
|
||||
double y = vel.y;
|
||||
|
||||
if (!entity.isSneaking() && Math.abs(y) >= 0.25) {
|
||||
y += 0.0155 * (entity.fallDistance < 1 ? 1 : entity.fallDistance);
|
||||
} else {
|
||||
if (entity.isSneaking() || Math.abs(y) < 0.25) {
|
||||
y = 0;
|
||||
} else {
|
||||
y += 0.0155 * Math.max(1, entity.fallDistance);
|
||||
}
|
||||
entity.setVelocity(vel.x, y, vel.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean getCanInteract(BlockState state, Entity e) {
|
||||
if (getGasType(state).canInteract(e)) {
|
||||
if (e instanceof ItemEntity) {
|
||||
// @FUF(reason = "There is no TickEvents.EntityTickEvent. Waiting on mixins...")
|
||||
e.setNoGravity(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether falling sand entities should fall through this block.
|
||||
* @param state Our block state
|
||||
* @param world The current world
|
||||
* @param pos The current position
|
||||
*
|
||||
* @return True to allow blocks to pass.
|
||||
*
|
||||
* @fuf Hacked until we can get mixins to implement a proper hook
|
||||
*/
|
||||
default boolean allowsFallingBlockToPass(BlockState state, BlockView world, BlockPos pos) {
|
||||
if (this.getGasType(state).isDense()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Block above = world.getBlockState(pos.up()).getBlock();
|
||||
return !(above instanceof Gas) && above instanceof FallingBlock;
|
||||
default boolean isSupporting(BlockState state) {
|
||||
return getGasState(state).isDense();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
package com.minelittlepony.unicopia.gas;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.block.UMaterials;
|
||||
import net.fabricmc.fabric.api.block.FabricBlockSettings;
|
||||
import net.minecraft.block.BedBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.block.TorchBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
|
||||
public enum CloudType {
|
||||
public enum GasState {
|
||||
NORMAL,
|
||||
DENSE,
|
||||
ENCHANTED;
|
||||
|
@ -25,11 +32,39 @@ public enum CloudType {
|
|||
return this != NORMAL;
|
||||
}
|
||||
|
||||
public boolean isTouchable(boolean isPlayer) {
|
||||
return this == ENCHANTED || (this == DENSE && isPlayer);
|
||||
public boolean isTouchable(boolean isPlayer, boolean isPegasus) {
|
||||
return isPegasus || this == ENCHANTED || (this == DENSE && isPlayer);
|
||||
}
|
||||
|
||||
public boolean canInteract(Entity e) {
|
||||
return CloudInteractionContext.of(e).canTouch(this);
|
||||
public boolean canTouch(Entity e) {
|
||||
return isTouchable(EquinePredicates.IS_PLAYER.test(e), EquinePredicates.ENTITY_INTERACT_WITH_CLOUD_BLOCKS.test(e));
|
||||
}
|
||||
|
||||
public boolean canTouch(CloudInteractionContext context) {
|
||||
return context.canTouch(this);
|
||||
}
|
||||
|
||||
public boolean canPlace(CloudInteractionContext context) {
|
||||
return context.isEmpty() || canTouch(context) && heldCanTouch(context);
|
||||
}
|
||||
|
||||
private boolean heldCanTouch(CloudInteractionContext context) {
|
||||
ItemStack main = context.getHeldStack();
|
||||
|
||||
if (main.getItem() instanceof BlockItem) {
|
||||
Block block = ((BlockItem)main.getItem()).getBlock();
|
||||
|
||||
if (block instanceof Gas && ((Gas)block).getGasState(block.getDefaultState()).canTouch(context)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this == GasState.NORMAL && (
|
||||
block instanceof TorchBlock
|
||||
|| block instanceof BedBlock
|
||||
|| block instanceof ChestBlock);
|
||||
}
|
||||
|
||||
return main.isEmpty();
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,6 @@ abstract class MixinEntityContextImpl implements CloudInteractionContext.Holder
|
|||
|
||||
@Override
|
||||
public CloudInteractionContext getCloudInteractionContext() {
|
||||
return cloudContext == null ? CloudInteractionContext.Impl.EMPTY : cloudContext;
|
||||
return cloudContext == null ? CloudInteractionContext.empty() : cloudContext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.minelittlepony.unicopia.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.minelittlepony.unicopia.gas.Gas;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FallingBlock;
|
||||
|
||||
@Mixin(FallingBlock.class)
|
||||
abstract class MixinFallingBlock extends Block {
|
||||
MixinFallingBlock() { super(null); }
|
||||
@Inject(method = "canFallThrough(Lnet/minecraft/block/BlockState;)Z",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true)
|
||||
private static void onCanFallThrough(BlockState state, CallbackInfoReturnable<Boolean> info) {
|
||||
if (state.getBlock() instanceof Gas) {
|
||||
info.setReturnValue(!((Gas)state.getBlock()).isSupporting(state));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
"CriterionsRegistry",
|
||||
"MixinBlockItem",
|
||||
"MixinEntityContextImpl",
|
||||
"MixinFallingBlock",
|
||||
"MixinFarmlandBlock",
|
||||
"MixinHoeItem",
|
||||
"MixinItem",
|
||||
|
|
Loading…
Reference in a new issue