Added cloud fences and banisters

This commit is contained in:
Sollace 2019-02-04 18:16:17 +02:00
parent 1f259a7e22
commit 79e9b310d3
19 changed files with 428 additions and 76 deletions

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.block.BlockAlfalfa;
import com.minelittlepony.unicopia.block.BlockFruitLeaves;
import com.minelittlepony.unicopia.block.BlockCloud;
import com.minelittlepony.unicopia.block.BlockCloudAnvil;
import com.minelittlepony.unicopia.block.BlockCloudBanister;
import com.minelittlepony.unicopia.block.BlockCloudSlab;
import com.minelittlepony.unicopia.block.BlockCloudStairs;
import com.minelittlepony.unicopia.block.BlockSugar;
@ -12,6 +13,7 @@ import com.minelittlepony.unicopia.block.IColourful;
import com.minelittlepony.unicopia.block.USapling;
import com.minelittlepony.unicopia.block.BlockCloudDoor;
import com.minelittlepony.unicopia.block.BlockCloudFarm;
import com.minelittlepony.unicopia.block.BlockCloudFence;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@ -39,6 +41,9 @@ public class UBlocks {
public static final BlockCloudAnvil anvil = new BlockCloudAnvil(Unicopia.MODID, "anvil");
public static final BlockCloudFence cloud_fence = new BlockCloudFence(Unicopia.MODID, "cloud_fence");
public static final BlockCloudBanister cloud_banister = new BlockCloudBanister(Unicopia.MODID, "cloud_banister");
public static final BlockAlfalfa alfalfa = new BlockAlfalfa(Unicopia.MODID, "alfalfa");
public static final BlockTomatoPlant tomato_plant = new BlockTomatoPlant(Unicopia.MODID, "tomato_plant");
@ -56,7 +61,8 @@ public class UBlocks {
.setUnharvestFruit(w -> new ItemStack(UItems.rotten_apple));
static void init(IForgeRegistry<Block> registry) {
registry.registerAll(cloud, cloud_stairs, cloud_double_slab, cloud_slab, mist_door, anvil, cloud_farmland,
registry.registerAll(cloud, cloud_stairs, cloud_double_slab, cloud_slab, cloud_fence, cloud_banister,
mist_door, anvil, cloud_farmland,
sugar_block,
alfalfa,
tomato_plant,

View file

@ -82,6 +82,9 @@ public class UItems {
public static final Item cloud_farmland = new UItemBlock(UBlocks.cloud_farmland, Unicopia.MODID, "cloud_farmland", INTERACT_WITH_CLOUDS);
public static final Item cloud_fence = new UItemBlock(UBlocks.cloud_fence, Unicopia.MODID, "cloud_fence", INTERACT_WITH_CLOUDS);
public static final Item cloud_banister = new UItemBlock(UBlocks.cloud_banister, Unicopia.MODID, "cloud_banister", INTERACT_WITH_CLOUDS);
public static final Item anvil = new UItemBlock(UBlocks.anvil, Unicopia.MODID, "anvil", INTERACT_WITH_CLOUDS)
.setTranslationKey("cloud_anvil");
@ -193,8 +196,8 @@ public class UItems {
registry.registerAll(
cloud_spawner, dew_drop, cloud_matter, cloud_block,
cloud_stairs, cloud_slab, cloud_farmland,
mist_door, anvil,
cloud_stairs, cloud_slab, cloud_fence, cloud_banister,
cloud_farmland, mist_door, anvil,
bag_of_holding, spell, curse, spellbook, mug,
@ -221,7 +224,8 @@ public class UItems {
tomato, cloudsdale_tomato,
cloud_spawner, cloud_matter, cloud_stairs, cloud_farmland, mist_door, anvil,
cloud_spawner, cloud_matter, cloud_stairs, cloud_fence, cloud_banister,
cloud_farmland, mist_door, anvil,
bag_of_holding, spell, curse, spellbook, mug,
alfalfa_seeds, alfalfa_leaves,

View file

@ -34,13 +34,14 @@ public class BlockCloud extends Block implements ICloudBlock, ITillable {
public BlockCloud(Material material, String domain, String name) {
super(material);
setRegistryName(domain, name);
setTranslationKey(name);
setCreativeTab(CreativeTabs.MISC);
setHardness(0.5f);
setResistance(1.0F);
setSoundType(SoundType.CLOTH);
setRegistryName(domain, name);
setLightOpacity(20);
setTranslationKey(name);
useNeighborBrightness = true;
}
@ -103,35 +104,21 @@ public class BlockCloud extends Block implements ICloudBlock, ITillable {
@Override
public void onFallenUpon(World world, BlockPos pos, Entity entityIn, float fallDistance) {
if (entityIn.isSneaking()) {
if (!applyLanding(entityIn, fallDistance)) {
super.onFallenUpon(world, pos, entityIn, fallDistance);
} else {
entityIn.fall(fallDistance, 0);
}
}
@Override
public void onLanded(World worldIn, Entity entity) {
if (entity.isSneaking()) {
if (!applyRebound(entity)) {
super.onLanded(worldIn, entity);
} else if (entity.motionY < 0) {
if (Math.abs(entity.motionY) >= 0.25) {
entity.motionY = -entity.motionY * 1.2;
} else {
entity.motionY = 0;
}
}
}
@Override
public void onEntityCollision(World w, BlockPos pos, IBlockState state, Entity entity) {
if (getCanInteract(state, entity)) {
if (!entity.isSneaking() && Math.abs(entity.motionY) >= 0.25) {
entity.motionY += 0.0155 * (entity.fallDistance < 1 ? 1 : entity.fallDistance);
} else {
entity.motionY = 0;
}
if (!applyBouncyness(state, entity)) {
super.onEntityCollision(w, pos, state, entity);
}
}
@ -192,10 +179,10 @@ public class BlockCloud extends Block implements ICloudBlock, ITillable {
@Deprecated
@Override
public RayTraceResult collisionRayTrace(IBlockState blockState, World worldIn, BlockPos pos, Vec3d start, Vec3d end) {
if (handleRayTraceSpecialCases(worldIn, pos, blockState)) {
return null;
if (!handleRayTraceSpecialCases(worldIn, pos, blockState)) {
return super.collisionRayTrace(blockState, worldIn, pos, start, end);
}
return super.collisionRayTrace(blockState, worldIn, pos, start, end);
return null;
}
@Override

View file

@ -55,10 +55,8 @@ public class BlockCloudAnvil extends BlockAnvil implements ICloudBlock {
@Override
public void onFallenUpon(World world, BlockPos pos, Entity entityIn, float fallDistance) {
if (entityIn.isSneaking()) {
if (!applyLanding(entityIn, fallDistance)) {
super.onFallenUpon(world, pos, entityIn, fallDistance);
} else {
entityIn.fall(fallDistance, 0);
}
}
@ -84,14 +82,8 @@ public class BlockCloudAnvil extends BlockAnvil implements ICloudBlock {
@Override
public void onLanded(World worldIn, Entity entity) {
if (entity.isSneaking()) {
if (!applyRebound(entity)) {
super.onLanded(worldIn, entity);
} else if (entity.motionY < 0) {
if (Math.abs(entity.motionY) >= 0.25) {
entity.motionY = -entity.motionY * 2;
} else {
entity.motionY = 0;
}
}
}
@ -115,13 +107,7 @@ public class BlockCloudAnvil extends BlockAnvil implements ICloudBlock {
@Override
public void onEntityCollision(World w, BlockPos pos, IBlockState state, Entity entity) {
if (getCanInteract(state, entity)) {
if (!entity.isSneaking() && Math.abs(entity.motionY) >= 0.25) {
entity.motionY += 0.0155 * (entity.fallDistance < 1 ? 1 : entity.fallDistance);
} else {
entity.motionY = 0;
}
if (!applyBouncyness(state, entity)) {
super.onEntityCollision(w, pos, state, entity);
}
}
@ -151,10 +137,10 @@ public class BlockCloudAnvil extends BlockAnvil implements ICloudBlock {
@Deprecated
@Override
public RayTraceResult collisionRayTrace(IBlockState blockState, World worldIn, BlockPos pos, Vec3d start, Vec3d end) {
if (handleRayTraceSpecialCases(worldIn, pos, blockState)) {
return null;
if (!handleRayTraceSpecialCases(worldIn, pos, blockState)) {
return super.collisionRayTrace(blockState, worldIn, pos, start, end);
}
return super.collisionRayTrace(blockState, worldIn, pos, start, end);
return null;
}
@Deprecated

View file

@ -0,0 +1,109 @@
package com.minelittlepony.unicopia.block;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockCloudBanister extends BlockCloudFence {
public static final double l = 11/16D;
public static final double d = 5/16D;
public static final double h = 2/16D;
public static final AxisAlignedBB SOUTH_AABB = new AxisAlignedBB(d, 0, l, l, h, 1);
public static final AxisAlignedBB WEST_AABB = new AxisAlignedBB(0, 0, d, d, h, l);
public static final AxisAlignedBB NORTH_AABB = new AxisAlignedBB(d, 0, 0, l, h, d);
public static final AxisAlignedBB EAST_AABB = new AxisAlignedBB(l, 0, d, 1, h, l);
public static final AxisAlignedBB[] BOUNDING_BOXES = new AxisAlignedBB[] {
new AxisAlignedBB(d, 0, d, l, h, l),
new AxisAlignedBB(d, 0, d, l, h, 1),
new AxisAlignedBB(0, 0, d, l, h, l),
new AxisAlignedBB(0, 0, d, l, h, 1),
new AxisAlignedBB(d, 0, 0, l, h, l),
new AxisAlignedBB(d, 0, 0, l, h, 1),
new AxisAlignedBB(0, 0, 0, l, h, l),
new AxisAlignedBB(0, 0, 0, l, h, 1),
new AxisAlignedBB(d, 0, d, 1, h, l),
new AxisAlignedBB(d, 0, d, 1, h, 1),
new AxisAlignedBB(0, 0, d, 1, h, l),
new AxisAlignedBB(0, 0, d, 1, h, 1),
new AxisAlignedBB(d, 0, 0, 1, h, l),
new AxisAlignedBB(d, 0, 0, 1, h, 1),
new AxisAlignedBB(0, 0, 0, 1, h, l),
new AxisAlignedBB(0, 0, 0, 1, h, 1)
};
public BlockCloudBanister(String domain, String name) {
super(domain, name);
}
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.SOLID;
}
@Deprecated
@Override
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entity, boolean isActualState) {
if (!getCanInteract(state, entity)) {
return;
}
if (!isActualState) {
state = state.getActualState(world, pos);
}
if (state.getValue(NORTH)) {
addCollisionBoxToList(pos, entityBox, collidingBoxes, NORTH_AABB);
}
if (state.getValue(EAST)) {
addCollisionBoxToList(pos, entityBox, collidingBoxes, EAST_AABB);
}
if (state.getValue(SOUTH)) {
addCollisionBoxToList(pos, entityBox, collidingBoxes, SOUTH_AABB);
}
if (state.getValue(WEST)) {
addCollisionBoxToList(pos, entityBox, collidingBoxes, WEST_AABB);
}
}
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
state = getActualState(state, source, pos);
return BOUNDING_BOXES[getBoundingBoxIdx(state)];
}
public static int getBoundingBoxIdx(IBlockState state) {
int i = 0;
if (state.getValue(NORTH)) {
i |= 1 << EnumFacing.NORTH.getHorizontalIndex();
}
if (state.getValue(EAST)) {
i |= 1 << EnumFacing.EAST.getHorizontalIndex();
}
if (state.getValue(SOUTH)) {
i |= 1 << EnumFacing.SOUTH.getHorizontalIndex();
}
if (state.getValue(WEST)) {
i |= 1 << EnumFacing.WEST.getHorizontalIndex();
}
return i;
}
}

View file

@ -80,13 +80,7 @@ public class BlockCloudDoor extends BlockDoor implements ICloudBlock {
@Override
public void onEntityCollision(World w, BlockPos pos, IBlockState state, Entity entity) {
if (getCanInteract(state, entity)) {
if (!entity.isSneaking() && Math.abs(entity.motionY) >= 0.25) {
entity.motionY += 0.0155 * (entity.fallDistance < 1 ? 1 : entity.fallDistance);
} else {
entity.motionY = 0;
}
if (!applyBouncyness(state, entity)) {
super.onEntityCollision(w, pos, state, entity);
}
}
@ -104,10 +98,10 @@ public class BlockCloudDoor extends BlockDoor implements ICloudBlock {
@Deprecated
@Override
public float getPlayerRelativeBlockHardness(IBlockState state, EntityPlayer player, World worldIn, BlockPos pos) {
if (!CloudType.NORMAL.canInteract(player)) {
return -1;
if (CloudType.NORMAL.canInteract(player)) {
return super.getPlayerRelativeBlockHardness(state, player, worldIn, pos);
}
return super.getPlayerRelativeBlockHardness(state, player, worldIn, pos);
return -1;
}
@Override

View file

@ -63,35 +63,21 @@ public class BlockCloudFarm extends UFarmland implements ICloudBlock {
@Override
public void onFallenUpon(World world, BlockPos pos, Entity entityIn, float fallDistance) {
if (entityIn.isSneaking()) {
if (!applyLanding(entityIn, fallDistance)) {
super.onFallenUpon(world, pos, entityIn, fallDistance);
} else {
entityIn.fall(fallDistance, 0);
}
}
@Override
public void onLanded(World worldIn, Entity entity) {
if (entity.isSneaking()) {
if (!applyRebound(entity)) {
super.onLanded(worldIn, entity);
} else if (entity.motionY < 0) {
if (Math.abs(entity.motionY) >= 0.25) {
entity.motionY = -entity.motionY * 1.2;
} else {
entity.motionY = 0;
}
}
}
@Override
public void onEntityCollision(World w, BlockPos pos, IBlockState state, Entity entity) {
if (getCanInteract(state, entity)) {
if (!entity.isSneaking() && Math.abs(entity.motionY) >= 0.25) {
entity.motionY += 0.0155 * (entity.fallDistance < 1 ? 1 : entity.fallDistance);
} else {
entity.motionY = 0;
}
if (!applyBouncyness(state, entity)) {
super.onEntityCollision(w, pos, state, entity);
}
}
@ -104,10 +90,10 @@ public class BlockCloudFarm extends UFarmland implements ICloudBlock {
@Deprecated
@Override
public RayTraceResult collisionRayTrace(IBlockState blockState, World worldIn, BlockPos pos, Vec3d start, Vec3d end) {
if (handleRayTraceSpecialCases(worldIn, pos, blockState)) {
return null;
if (!handleRayTraceSpecialCases(worldIn, pos, blockState)) {
return super.collisionRayTrace(blockState, worldIn, pos, start, end);
}
return super.collisionRayTrace(blockState, worldIn, pos, start, end);
return null;
}
@Deprecated

View file

@ -0,0 +1,122 @@
package com.minelittlepony.unicopia.block;
import java.util.List;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.CloudType;
import com.minelittlepony.unicopia.UMaterials;
import net.minecraft.block.BlockFence;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockCloudFence extends BlockFence implements ICloudBlock {
public BlockCloudFence(String domain, String name) {
super(UMaterials.cloud, UMaterials.cloud.getMaterialMapColor());
setTranslationKey(name);
setRegistryName(domain, name);
setHardness(0.5f);
setResistance(1.0F);
setLightOpacity(20);
setSoundType(SoundType.CLOTH);
useNeighborBrightness = true;
}
@Override
public boolean isTranslucent(IBlockState state) {
return true;
}
@Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
@Override
public boolean isFullCube(IBlockState state) {
return false;
}
@Override
public boolean isAir(IBlockState state, IBlockAccess world, BlockPos pos) {
return allowsFallingBlockToPass(state, world, pos);
}
@Override
public boolean isNormalCube(IBlockState state) {
return false;
}
@Override
public CloudType getCloudMaterialType(IBlockState blockState) {
return CloudType.NORMAL;
}
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.TRANSLUCENT;
}
@Override
public void onFallenUpon(World world, BlockPos pos, Entity entityIn, float fallDistance) {
if (!applyLanding(entityIn, fallDistance)) {
super.onFallenUpon(world, pos, entityIn, fallDistance);
}
}
@Override
public void onLanded(World worldIn, Entity entity) {
if (!applyRebound(entity)) {
super.onLanded(worldIn, entity);
}
}
@Override
public void onEntityCollision(World w, BlockPos pos, IBlockState state, Entity entity) {
if (!applyBouncyness(state, entity)) {
super.onEntityCollision(w, pos, state, entity);
}
}
@Override
public boolean canEntityDestroy(IBlockState state, IBlockAccess world, BlockPos pos, Entity entity) {
return getCanInteract(state, entity) && super.canEntityDestroy(state, world, pos, entity);
}
@Deprecated
public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entity, boolean isActualState) {
if (getCanInteract(state, entity)) {
super.addCollisionBoxToList(state, worldIn, pos, entityBox, collidingBoxes, entity, isActualState);
}
}
@Deprecated
@Override
public float getPlayerRelativeBlockHardness(IBlockState state, EntityPlayer player, World worldIn, BlockPos pos) {
if (CloudType.NORMAL.canInteract(player)) {
return super.getPlayerRelativeBlockHardness(state, player, worldIn, pos);
}
return -1;
}
@Deprecated
@Override
public RayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end) {
if (!handleRayTraceSpecialCases(world, pos, state)) {
return super.collisionRayTrace(state, world, pos, start, end);
}
return null;
}
}

View file

@ -55,6 +55,45 @@ public interface ICloudBlock {
return false;
}
default boolean applyLanding(Entity entity, float fallDistance) {
if (!entity.isSneaking()) {
entity.fall(fallDistance, 0);
return false;
}
return true;
}
default boolean applyRebound(Entity entity) {
if (!entity.isSneaking() && entity.motionY < 0) {
if (Math.abs(entity.motionY) >= 0.25) {
entity.motionY = -entity.motionY * 1.2;
} else {
entity.motionY = 0;
}
return true;
}
return false;
}
default boolean applyBouncyness(IBlockState state, Entity entity) {
if (getCanInteract(state, entity)) {
if (!entity.isSneaking() && Math.abs(entity.motionY) >= 0.25) {
entity.motionY += 0.0155 * (entity.fallDistance < 1 ? 1 : entity.fallDistance);
} else {
entity.motionY = 0;
}
return true;
}
return false;
}
default boolean getCanInteract(IBlockState state, Entity e) {
if (getCloudMaterialType(state).canInteract(e)) {
if (e instanceof EntityItem) {

View file

@ -0,0 +1,18 @@
{
"multipart": [
{ "when": { "north": "false", "south": "false", "east": "false", "west": "false" },
"apply": { "model": "unicopia:cloud_banister" }},
{ "when": { "north": "true" },
"apply": { "model": "unicopia:cloud_banister", "uvlock": true }
},
{ "when": { "east": "true" },
"apply": { "model": "unicopia:cloud_banister", "y": 90, "uvlock": true }
},
{ "when": { "south": "true" },
"apply": { "model": "unicopia:cloud_banister", "y": 180, "uvlock": true }
},
{ "when": { "west": "true" },
"apply": { "model": "unicopia:cloud_banister", "y": 270, "uvlock": true }
}
]
}

View file

@ -0,0 +1,17 @@
{
"multipart": [
{ "apply": { "model": "unicopia:cloud_fence_post" }},
{ "when": { "north": "true" },
"apply": { "model": "unicopia:cloud_fence_side", "uvlock": true }
},
{ "when": { "east": "true" },
"apply": { "model": "unicopia:cloud_fence_side", "y": 90, "uvlock": true }
},
{ "when": { "south": "true" },
"apply": { "model": "unicopia:cloud_fence_side", "y": 180, "uvlock": true }
},
{ "when": { "west": "true" },
"apply": { "model": "unicopia:cloud_fence_side", "y": 270, "uvlock": true }
}
]
}

View file

@ -7,6 +7,8 @@ tile.cloud_slab.packed.name=Dense Cloud Slab
tile.cloud_slab.enchanted.name=Enchanted Cloud Slab
tile.cloud_stairs.name=Cloud Stairs
tile.cloud_fence.name=Cloud Fence
tile.cloud_banister.name=Banister
tile.cloud_farmland.name=Tilled Clouds
tile.apple_leaves.name=Apple Leaves

View file

@ -0,0 +1,20 @@
{
"textures": {
"texture": "unicopia:blocks/cloud_enchanted_top",
"particle": "#texture"
},
"elements": [
{ "from": [ 5, 0, 0 ],
"to": [ 11, 2, 11 ],
"faces": {
"down": { "uv": [ 5, 0, 11, 11 ], "texture": "#texture" },
"up": { "uv": [ 5, 0, 11, 11 ], "texture": "#texture" },
"north": { "uv": [ 5, 0, 11, 2 ], "texture": "#texture" },
"south": { "uv": [ 5, 0, 11, 2 ], "texture": "#texture" },
"west": { "uv": [ 0, 0, 11, 2 ], "texture": "#texture" },
"east": { "uv": [ 0, 0, 11, 2 ], "texture": "#texture" }
},
"__comment": "top bar"
}
]
}

View file

@ -0,0 +1,6 @@
{
"parent": "block/fence_inventory",
"textures": {
"texture": "unicopia:blocks/cloud_normal"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "block/fence_post",
"textures": {
"texture": "unicopia:blocks/cloud_normal"
}
}

View file

@ -0,0 +1,30 @@
{
"textures": {
"texture": "unicopia:blocks/cloud_normal",
"particle": "#texture"
},
"elements": [
{ "from": [ 6, 10, 0 ],
"to": [ 10, 15, 9 ],
"faces": {
"down": { "uv": [ 7, 0, 9, 9 ], "texture": "#texture" },
"up": { "uv": [ 7, 0, 9, 9 ], "texture": "#texture" },
"north": { "uv": [ 7, 1, 9, 4 ], "texture": "#texture", "cullface": "north" },
"west": { "uv": [ 0, 1, 9, 4 ], "texture": "#texture" },
"east": { "uv": [ 0, 1, 9, 4 ], "texture": "#texture" }
},
"__comment": "top bar"
},
{ "from": [ 7, 6, 0 ],
"to": [ 9, 9, 9 ],
"faces": {
"down": { "uv": [ 7, 0, 9, 9 ], "texture": "#texture" },
"up": { "uv": [ 7, 0, 9, 9 ], "texture": "#texture" },
"north": { "uv": [ 7, 7, 9, 10 ], "texture": "#texture", "cullface": "north" },
"west": { "uv": [ 0, 7, 9, 10 ], "texture": "#texture" },
"east": { "uv": [ 0, 7, 9, 10 ], "texture": "#texture" }
},
"__comment": "lower bar"
}
]
}

View file

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

View file

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

View file

@ -0,0 +1,14 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" ",
"BBB",
"B B"
],
"key": {
"B": [
{ "item": "unicopia:cloud_block", "data": 0 }
]
},
"result": { "item": "unicopia:cloud_fence", "count": 3 }
}