diff --git a/src/main/java/com/minelittlepony/unicopia/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/UBlocks.java index 0121dce5..f8c15c5b 100644 --- a/src/main/java/com/minelittlepony/unicopia/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/UBlocks.java @@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.block.BlockCloudAnvil; import com.minelittlepony.unicopia.block.BlockCloudSlab; import com.minelittlepony.unicopia.block.BlockCloudStairs; import com.minelittlepony.unicopia.block.BlockCloudDoor; +import com.minelittlepony.unicopia.block.BlockCloudFarm; import net.minecraft.block.Block; import net.minecraftforge.registries.IForgeRegistry; @@ -13,9 +14,9 @@ import net.minecraftforge.registries.IForgeRegistry; public class UBlocks { public static final BlockCloud cloud = new BlockCloud(UMaterials.cloud, Unicopia.MODID, "cloud_block"); - public static final BlockCloudStairs stairsCloud = new BlockCloudStairs(UBlocks.cloud.getDefaultState(), Unicopia.MODID, "cloud_stairs"); + public static final BlockCloudStairs cloud_stairs = new BlockCloudStairs(UBlocks.cloud.getDefaultState(), Unicopia.MODID, "cloud_stairs"); - public static final BlockCloudSlab cloud_double_slab = new BlockCloudSlab(true, UMaterials.cloud, Unicopia.MODID, "cloud_double_slab"); + public static final BlockCloudSlab double_cloud_slab = new BlockCloudSlab(true, UMaterials.cloud, Unicopia.MODID, "cloud_double_slab"); public static final BlockCloudSlab cloud_slab = new BlockCloudSlab(false, UMaterials.cloud, Unicopia.MODID, "cloud_slab"); public static final BlockCloudDoor mist_door = new BlockCloudDoor(UMaterials.cloud, Unicopia.MODID, "mist_door"); @@ -24,8 +25,10 @@ public class UBlocks { public static final BlockAlfalfa alfalfa = new BlockAlfalfa(Unicopia.MODID, "alfalfa"); + public static final BlockCloudFarm cloud_farmland = new BlockCloudFarm(Unicopia.MODID, "cloud_farmland"); + static void registerBlocks(IForgeRegistry registry) { - registry.registerAll(cloud, stairsCloud, cloud_double_slab, cloud_slab, mist_door, anvil, + registry.registerAll(cloud, cloud_stairs, double_cloud_slab, cloud_slab, mist_door, anvil, cloud_farmland, alfalfa); } } diff --git a/src/main/java/com/minelittlepony/unicopia/UEntities.java b/src/main/java/com/minelittlepony/unicopia/UEntities.java index dcaaae20..b58fd7a7 100644 --- a/src/main/java/com/minelittlepony/unicopia/UEntities.java +++ b/src/main/java/com/minelittlepony/unicopia/UEntities.java @@ -4,15 +4,18 @@ import com.minelittlepony.unicopia.entity.EntityCloud; import com.minelittlepony.unicopia.entity.EntityConstructionCloud; import com.minelittlepony.unicopia.entity.EntityRacingCloud; import com.minelittlepony.unicopia.entity.EntitySpell; +import com.minelittlepony.unicopia.entity.EntityProjectile; import com.minelittlepony.unicopia.entity.EntityWildCloud; import com.minelittlepony.unicopia.render.RenderCloud; import com.minelittlepony.unicopia.render.RenderGem; +import com.minelittlepony.unicopia.render.RenderProjectile; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList.EntityEggInfo; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.common.registry.EntityEntry; +import net.minecraftforge.fml.common.registry.EntityEntryBuilder; import net.minecraftforge.registries.IForgeRegistry; public class UEntities { @@ -20,25 +23,33 @@ public class UEntities { private static final int BRUSHES_CHARTREUSE = 0x7FFF00; static void init(IForgeRegistry registry) { - addEntity(registry, EntityCloud.class, "cloud", true, BRUSHES_ROYALBLUE, BRUSHES_CHARTREUSE); - addEntity(registry, EntityWildCloud.class, "wild_cloud", false, 0, 0); - addEntity(registry, EntityRacingCloud.class, "racing_cloud", false, 0, 0); - addEntity(registry, EntityConstructionCloud.class, "construction_cloud", false, 0, 0); - addEntity(registry, EntitySpell.class, "magic_spell", false, 0, 0); - } - - static void addEntity(IForgeRegistry registry, Class type, String name, boolean egg, int a, int b) { - EntityEntry entry = new EntityEntry(type, name).setRegistryName(Unicopia.MODID, name); - - if (egg) { - entry.setEgg(new EntityEggInfo(new ResourceLocation("unicopia", "cloud"), a, a)); - } - - registry.register(entry); + registry.registerAll( + new Entry(EntityCloud.class, "cloud").withEgg(BRUSHES_ROYALBLUE, BRUSHES_CHARTREUSE), + new Entry(EntityWildCloud.class, "wild_cloud"), + new Entry(EntityRacingCloud.class, "racing_cloud"), + new Entry(EntityConstructionCloud.class, "construction_cloud"), + new Entry(EntitySpell.class, "magic_spell"), + EntityEntryBuilder.create().entity(EntityProjectile.class).name("thrown_item").id(new ResourceLocation(Unicopia.MODID, "thrown_item"), 0).tracker(10, 5, true).build() + ); } static void preInit() { - RenderingRegistry.registerEntityRenderingHandler(EntityCloud.class, manager -> new RenderCloud(manager)); - RenderingRegistry.registerEntityRenderingHandler(EntitySpell.class, manager -> new RenderGem(manager)); + RenderingRegistry.registerEntityRenderingHandler(EntityCloud.class, RenderCloud::new); + RenderingRegistry.registerEntityRenderingHandler(EntitySpell.class, RenderGem::new); + RenderingRegistry.registerEntityRenderingHandler(EntityProjectile.class, RenderProjectile::new); + } + + static class Entry extends EntityEntry { + + public Entry(Class cls, String name) { + super(cls, name); + setRegistryName(Unicopia.MODID, name); + } + + Entry withEgg(int a, int b) { + setEgg(new EntityEggInfo(getRegistryName(), a, b)); + + return this; + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/UItems.java b/src/main/java/com/minelittlepony/unicopia/UItems.java index f81395c3..c347a04d 100644 --- a/src/main/java/com/minelittlepony/unicopia/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/UItems.java @@ -5,6 +5,7 @@ import com.minelittlepony.unicopia.item.ItemCloud; import com.minelittlepony.unicopia.item.ItemCurse; import com.minelittlepony.unicopia.item.ItemOfHolding; import com.minelittlepony.unicopia.item.ItemSpell; +import com.minelittlepony.unicopia.item.ItemTomato; import com.minelittlepony.unicopia.item.UItemBlock; import com.minelittlepony.unicopia.item.UItemMultiTexture; import com.minelittlepony.unicopia.item.UItemSlab; @@ -57,7 +58,7 @@ public class UItems { }, INTERACT_WITH_CLOUDS) .setRegistryName(Unicopia.MODID, "cloud_block"); - public static final Item cloud_stairs = new UItemBlock(UBlocks.stairsCloud, INTERACT_WITH_CLOUDS) + public static final Item cloud_stairs = new UItemBlock(UBlocks.cloud_stairs, INTERACT_WITH_CLOUDS) .setTranslationKey("cloud_stairs") .setRegistryName(Unicopia.MODID, "cloud_stairs"); @@ -70,7 +71,7 @@ public class UItems { .setTranslationKey("mist_door") .setRegistryName(Unicopia.MODID, "mist_door"); - public static final Item cloud_slab = new UItemSlab(UBlocks.cloud_slab, UBlocks.cloud_slab, UBlocks.cloud_double_slab, INTERACT_WITH_CLOUDS) + public static final Item cloud_slab = new UItemSlab(UBlocks.cloud_slab, UBlocks.cloud_slab, UBlocks.double_cloud_slab, INTERACT_WITH_CLOUDS) .setTranslationKey("cloud_slab") .setRegistryName(Unicopia.MODID, "cloud_slab"); @@ -91,6 +92,9 @@ public class UItems { .setTranslationKey("cereal") .setRegistryName(Unicopia.MODID, "cereal"); + public static final ItemTomato tomato = new ItemTomato(Unicopia.MODID, "tomato", 4, 34); + public static final ItemTomato cloudsdale_tomato = new ItemTomato(Unicopia.MODID, "cloudsdale_tomato", 16, 4); + static void registerItems(IForgeRegistry registry) { RegistryLockSpinner.unlock(Item.REGISTRY); @@ -98,12 +102,10 @@ public class UItems { RegistryLockSpinner.lock(Item.REGISTRY); - - registry.registerAll(cloud_spawner, dew_drop, cloud_matter, cloud_block, cloud_stairs, cloud_slab, mist_door, anvil, bag_of_holding, spell, curse, - alfalfa_seeds, alfalfa_leaves, cereal); + alfalfa_seeds, alfalfa_leaves, cereal, tomato); if (UClient.isClientSide()) { registerAllVariants(apple, apple.getVariants()); @@ -121,6 +123,8 @@ public class UItems { registerAllVariants(alfalfa_seeds, "alfalfa_seeds"); registerAllVariants(alfalfa_leaves, "alfalfa_leaves"); registerAllVariants(cereal, "cereal"); + registerAllVariants(tomato, "tomato", "rotten_tomato"); + registerAllVariants(cloudsdale_tomato, "cloudsdale_tomato", "rotten_cloudsdale_tomato"); } registerFuels(); diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index b3bfd28e..58b0798b 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia; import net.minecraft.block.Block; import net.minecraft.block.BlockCrops; +import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; @@ -10,6 +11,8 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import net.minecraftforge.client.event.ColorHandlerEvent; import net.minecraftforge.client.event.EntityViewRenderEvent; import net.minecraftforge.client.event.FOVUpdateEvent; @@ -20,6 +23,7 @@ import net.minecraftforge.event.entity.item.ItemTossEvent; import net.minecraftforge.event.entity.player.PlayerDropsEvent; import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.entity.player.UseHoeEvent; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -27,6 +31,7 @@ import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; @@ -38,6 +43,7 @@ import com.minelittlepony.jumpingcastle.api.IChannel; import com.minelittlepony.jumpingcastle.api.JumpingCastle; import com.minelittlepony.jumpingcastle.api.Target; import com.minelittlepony.unicopia.advancements.UAdvancements; +import com.minelittlepony.unicopia.block.ITillable; import com.minelittlepony.unicopia.client.particle.EntityMagicFX; import com.minelittlepony.unicopia.client.particle.EntityRaindropFX; import com.minelittlepony.unicopia.client.particle.Particles; @@ -193,6 +199,25 @@ public class Unicopia { } } + @SubscribeEvent + public static void onBlockTilled(UseHoeEvent event) { + BlockPos pos = event.getPos(); + World world = event.getWorld(); + + IBlockState state = world.getBlockState(pos); + + if (state.getBlock() instanceof ITillable) { + ITillable farm = ((ITillable)state.getBlock()); + + if (farm.canBeTilled(event.getCurrent(), event.getEntityPlayer(), world, state, pos)) { + + world.setBlockState(pos, farm.getFarmlandState(event.getCurrent(), event.getEntityPlayer(), world, state, pos)); + + event.setResult(Result.ALLOW); + } + } + } + @SubscribeEvent public static void onPlayerTick(TickEvent.PlayerTickEvent event) { if (event.phase == Phase.END) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/BlockAlfalfa.java b/src/main/java/com/minelittlepony/unicopia/block/BlockAlfalfa.java index 71e3e4f4..f3d85d16 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/BlockAlfalfa.java +++ b/src/main/java/com/minelittlepony/unicopia/block/BlockAlfalfa.java @@ -19,6 +19,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.common.EnumPlantType; import net.minecraftforge.common.ForgeHooks; public class BlockAlfalfa extends BlockCrops { @@ -116,19 +117,20 @@ public class BlockAlfalfa extends BlockCrops { int max = getMaxAge(); if (age > max) { - growUpwards(world, pos.up(), world.getBlockState(pos.up()), age - max); + if (!(hasDown && hasTrunk)) { + growUpwards(world, pos.up(), world.getBlockState(pos.up()), age - max); + } age = max; } - boolean hasUp = world.getBlockState(pos.up()).getBlock() == this; if (hasDown && hasUp) { - world.setBlockState(pos, this.withAge(age).withProperty(HALF, Half.MIDDLE)); + world.setBlockState(pos, withAge(age).withProperty(HALF, Half.MIDDLE)); } else if (hasUp) { - world.setBlockState(pos, this.withAge(age).withProperty(HALF, Half.BOTTOM)); + world.setBlockState(pos, withAge(age).withProperty(HALF, Half.BOTTOM)); } else { - world.setBlockState(pos, this.withAge(age).withProperty(HALF, Half.TOP)); + world.setBlockState(pos, withAge(age).withProperty(HALF, Half.TOP)); } } @@ -269,6 +271,11 @@ public class BlockAlfalfa extends BlockCrops { return (Half)state.getValue(HALF); } + @Override + public EnumPlantType getPlantType(IBlockAccess world, BlockPos pos) { + return EnumPlantType.Crop; + } + public static enum Half implements IStringSerializable { TOP, MIDDLE, diff --git a/src/main/java/com/minelittlepony/unicopia/block/BlockCloud.java b/src/main/java/com/minelittlepony/unicopia/block/BlockCloud.java index 68a5d0ba..756a81e0 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/BlockCloud.java +++ b/src/main/java/com/minelittlepony/unicopia/block/BlockCloud.java @@ -5,6 +5,8 @@ import java.util.List; import javax.annotation.Nullable; import com.minelittlepony.unicopia.CloudType; +import com.minelittlepony.unicopia.UBlocks; +import com.minelittlepony.unicopia.player.PlayerSpeciesList; import net.minecraft.block.Block; import net.minecraft.block.SoundType; @@ -25,7 +27,7 @@ import net.minecraft.util.NonNullList; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockCloud extends Block implements ICloudBlock { +public class BlockCloud extends Block implements ICloudBlock, ITillable { public static final PropertyEnum VARIANT = PropertyEnum.create("variant", CloudType.class); @@ -139,9 +141,9 @@ public class BlockCloud extends Block implements ICloudBlock { @Override public float getPlayerRelativeBlockHardness(IBlockState state, EntityPlayer player, World worldIn, BlockPos pos) { if (!CloudType.NORMAL.canInteract(player)) { - return -1; + return super.getPlayerRelativeBlockHardness(state, player, worldIn, pos); } - return super.getPlayerRelativeBlockHardness(state, player, worldIn, pos); + return -1; } @Override @@ -176,4 +178,15 @@ public class BlockCloud extends Block implements ICloudBlock { return (CloudType)blockState.getValue(VARIANT); } + @Override + public boolean canBeTilled(ItemStack hoe, EntityPlayer player, World world, IBlockState state, BlockPos pos) { + return PlayerSpeciesList.instance().getPlayer(player).getPlayerSpecies().canInteractWithClouds() + && ITillable.super.canBeTilled(hoe, player, world, state, pos); + } + + @Override + public IBlockState getFarmlandState(ItemStack hoe, EntityPlayer player, World world, IBlockState state, BlockPos pos) { + return UBlocks.cloud_farmland.getDefaultState(); + } + } diff --git a/src/main/java/com/minelittlepony/unicopia/block/BlockCloudFarm.java b/src/main/java/com/minelittlepony/unicopia/block/BlockCloudFarm.java new file mode 100644 index 00000000..57b548cf --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/BlockCloudFarm.java @@ -0,0 +1,125 @@ +package com.minelittlepony.unicopia.block; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.minelittlepony.unicopia.CloudType; +import com.minelittlepony.unicopia.UBlocks; + +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.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 BlockCloudFarm extends UFarmland implements ICloudBlock { + + public BlockCloudFarm(String domain, String name) { + super(domain, name); + } + + @Override + public boolean isTranslucent(IBlockState state) { + return true; + } + + @Override + public boolean isAir(IBlockState state, IBlockAccess world, BlockPos pos) { + return allowsFallingBlockToPass(state, world, pos); + } + + @Override + public BlockRenderLayer getRenderLayer() { + return BlockRenderLayer.TRANSLUCENT; + } + + @Override + public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) { + + IBlockState beside = world.getBlockState(pos.offset(face)); + + if (beside.getBlock() instanceof ICloudBlock) { + ICloudBlock cloud = ((ICloudBlock)beside.getBlock()); + + if ((face == EnumFacing.DOWN || face == EnumFacing.UP || cloud == this)) { + if (cloud.getCloudMaterialType(beside) == getCloudMaterialType(state)) { + return true; + } + } + } + + return super.doesSideBlockRendering(state, world, pos, face); + } + + @Override + public void onFallenUpon(World world, BlockPos pos, Entity entityIn, float fallDistance) { + if (entityIn.isSneaking()) { + super.onFallenUpon(world, pos, entityIn, fallDistance); + } else { + entityIn.fall(fallDistance, 0); + } + } + + @Override + public void onLanded(World worldIn, Entity entity) { + if (entity.isSneaking()) { + 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; + } + + 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 collidingBoxes, @Nullable Entity entity, boolean p_185477_7_) { + if (getCanInteract(state, entity)) { + super.addCollisionBoxToList(state, worldIn, pos, entityBox, collidingBoxes, entity, p_185477_7_); + } + } + + @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; + } + + + @Override + public CloudType getCloudMaterialType(IBlockState blockState) { + return CloudType.NORMAL; + } + + @Override + protected IBlockState getDirtState(World world, BlockPos pos, IBlockState state) { + return UBlocks.cloud.getDefaultState(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/block/ITillable.java b/src/main/java/com/minelittlepony/unicopia/block/ITillable.java new file mode 100644 index 00000000..57d7750f --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/ITillable.java @@ -0,0 +1,24 @@ +package com.minelittlepony.unicopia.block; + +import javax.annotation.Nonnull; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * Blocks that can be turned into farmland when tilled. + */ +public interface ITillable { + /** + * Gets the farmland/tilled state for this block when attacked by a hoe. + */ + @Nonnull + IBlockState getFarmlandState(ItemStack hoe, EntityPlayer player, World world, IBlockState state, BlockPos pos); + + default boolean canBeTilled(ItemStack hoe, EntityPlayer player, World world, IBlockState state, BlockPos pos) { + return world.isAirBlock(pos.up()); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/block/UFarmland.java b/src/main/java/com/minelittlepony/unicopia/block/UFarmland.java new file mode 100644 index 00000000..16d3cbb0 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/block/UFarmland.java @@ -0,0 +1,127 @@ +package com.minelittlepony.unicopia.block; + +import java.util.Random; + +import com.minelittlepony.util.PosHelper; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockFarmland; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +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; +import net.minecraftforge.common.EnumPlantType; +import net.minecraftforge.common.IPlantable; + +public abstract class UFarmland extends BlockFarmland { + + public UFarmland(String domain, String name) { + setTranslationKey(name); + setRegistryName(domain, name); + } + + @Override + public void updateTick(World world, BlockPos pos, IBlockState state, Random rand) { + int i = state.getValue(MOISTURE); + + if (!hasWater(world, pos) && !world.isRainingAt(pos.up())) { + if (i > 0) { + world.setBlockState(pos, state.withProperty(MOISTURE, i - 1), 2); + } else if (!hasCrops(world, pos)) { + turnToDirt(world, pos, state); + } + } else if (i < 7) { + world.setBlockState(pos, state.withProperty(MOISTURE, 7), 2); + } + } + + @Override + public void onFallenUpon(World world, BlockPos pos, Entity entity, float fallDistance) { + if (shouldTrample(world, pos, entity, fallDistance)) { + turnToDirt(world, pos, world.getBlockState(pos)); + } + + entity.fall(fallDistance, 1); + } + + @Override + public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos) { + if (shouldTurnToDirt(world, pos, state)) { + turnToDirt(world, pos, state); + } + } + + @Override + public void onBlockAdded(World world, BlockPos pos, IBlockState state) { + if (shouldTurnToDirt(world, pos, state)) { + turnToDirt(world, pos, state); + } + } + + public boolean hasCrops(World worldIn, BlockPos pos) { + Block block = worldIn.getBlockState(pos.up()).getBlock(); + return block instanceof IPlantable + && canSustainPlant(worldIn.getBlockState(pos), worldIn, pos, EnumFacing.UP, (IPlantable)block); + } + + public boolean hasWater(World world, BlockPos pos) { + return PosHelper.inRegion(pos.add(-4, 0, -4), pos.add(4, 1, 4)).anyMatch(p -> { + return world.getBlockState(p).getMaterial() == Material.WATER; + }); + } + + @Override + public boolean canSustainPlant(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing direction, IPlantable plantable) { + return super.canSustainPlant(state, world, pos, direction, plantable) + || plantable.getPlantType(world, pos.offset(direction)) == EnumPlantType.Crop; + } + + /** + * Determines if this farmland should be trampled when an entity walks on it. + */ + public boolean shouldTrample(World world, BlockPos pos, Entity entity, float fallDistance) { + return !world.isRemote && entity.canTrample(world, this, pos, fallDistance); + } + + /** + * Determines if this farmland meets all the conditions for turning into dirt. + */ + public boolean shouldTurnToDirt(World world, BlockPos pos, IBlockState state) { + return world.getBlockState(pos.up()).getMaterial().isSolid(); + } + + /** + * Turns this farmland into dirt or its dirt equivalent. + */ + public void turnToDirt(World world, BlockPos pos, IBlockState state) { + world.setBlockState(pos, getDirtState(world, pos, state)); + + AxisAlignedBB bounds = getUpdateCollissionBounds(world, pos, state); + + if (bounds != null) { + // Update entity positions so they don't fall through the block + for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bounds)) { + + double offset = Math.min(bounds.maxY - bounds.minY, bounds.maxY - entity.getEntityBoundingBox().minY); + + entity.setPositionAndUpdate(entity.posX, entity.posY + offset + 0.001D, entity.posZ); + } + } + } + + protected AxisAlignedBB getUpdateCollissionBounds(World world, BlockPos pos, IBlockState state) { + return field_194405_c.offset(pos); + } + + /** + * Gets the state used to represent this block as a piece of dirt. + */ + protected IBlockState getDirtState(World world, BlockPos pos, IBlockState state) { + return Blocks.DIRT.getDefaultState(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java new file mode 100644 index 00000000..170e8ef3 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityProjectile.java @@ -0,0 +1,121 @@ +package com.minelittlepony.unicopia.entity; + +import com.minelittlepony.unicopia.item.ITossable; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IProjectile; +import net.minecraft.entity.projectile.EntitySnowball; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; + +public class EntityProjectile extends EntitySnowball { + + private static final DataParameter ITEM = EntityDataManager + .createKey(EntityProjectile.class, DataSerializers.ITEM_STACK); + private static final DataParameter DAMAGE = EntityDataManager + .createKey(EntityProjectile.class, DataSerializers.FLOAT); + + public EntityProjectile(World world) { + super(world); + } + + public EntityProjectile(World world, double x, double y, double z) { + super(world, x, y, z); + } + + public EntityProjectile(World world, EntityLivingBase thrower) { + super(world, thrower); + } + + @Override + protected void entityInit() { + getDataManager().register(ITEM, ItemStack.EMPTY); + getDataManager().register(DAMAGE, (float)0); + } + + public ItemStack getItem() { + ItemStack stack = getDataManager().get(ITEM); + + return stack == null ? ItemStack.EMPTY : stack; + } + + public void setItem(ItemStack stack) { + getDataManager().set(ITEM, stack); + getDataManager().setDirty(ITEM); + } + + public void setThrowDamage(float damage) { + getDataManager().set(DAMAGE, Math.max(0, damage)); + } + + public float getThrowDamage() { + return getDataManager().get(DAMAGE); + } + + @Override + public void readEntityFromNBT(NBTTagCompound compound) { + super.readEntityFromNBT(compound); + + ItemStack itemstack = new ItemStack(compound.getCompoundTag("Item")); + + if (itemstack.isEmpty()) { + setDead(); + } else { + setItem(itemstack); + } + } + + @Override + public void handleStatusUpdate(byte id) { + if (id == 3) { + ItemStack stack = getItem(); + + for (int i = 0; i < 8; i++) { + world.spawnParticle(EnumParticleTypes.ITEM_CRACK, posX, posY, posZ, 0, 0, 0, Item.getIdFromItem(stack.getItem()), stack.getMetadata()); + } + } + } + + @Override + public void writeEntityToNBT(NBTTagCompound compound) { + super.writeEntityToNBT(compound); + + ItemStack itemstack = this.getItem(); + + if (!itemstack.isEmpty()) { + compound.setTag("Item", itemstack.writeToNBT(new NBTTagCompound())); + } + } + + @Override + protected void onImpact(RayTraceResult result) { + if (result.entityHit != this && !(result.entityHit instanceof IProjectile)) { + if (result.typeOfHit == RayTraceResult.Type.BLOCK) { + Item item = getItem().getItem(); + + if (item instanceof ITossable) { + ((ITossable)item).onImpact(world, result.getBlockPos(), world.getBlockState(result.getBlockPos())); + } + } + + if (result.entityHit != null) { + result.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, getThrower()), getThrowDamage()); + } + + + + if (!world.isRemote) { + world.setEntityState(this, (byte)3); + setDead(); + } + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/ITossable.java b/src/main/java/com/minelittlepony/unicopia/item/ITossable.java new file mode 100644 index 00000000..ad32e5e1 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ITossable.java @@ -0,0 +1,105 @@ +package com.minelittlepony.unicopia.item; + +import com.minelittlepony.unicopia.entity.EntityProjectile; + +import net.minecraft.block.BlockDispenser; +import net.minecraft.block.state.IBlockState; +import net.minecraft.dispenser.BehaviorDefaultDispenseItem; +import net.minecraft.dispenser.IBehaviorDispenseItem; +import net.minecraft.dispenser.IBlockSource; +import net.minecraft.dispenser.IPosition; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.stats.StatList; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public interface ITossable { + IBehaviorDispenseItem dispenserBehavior = new ITossable.DispenserBehaviour(); + + boolean canBeThrown(ItemStack stack); + + void onImpact(World world, BlockPos pos, IBlockState state); + + default Item setDispenseable() { + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject((Item)(Object)this, dispenserBehavior); + + return (Item)(Object)this; + } + + default SoundEvent getThrowSound(ItemStack stack) { + return SoundEvents.ENTITY_SNOWBALL_THROW; + } + + default int getThrowDamage(ItemStack stack) { + return 0; + } + + default void toss(World world, ItemStack itemstack, EntityPlayer player) { + if (!player.capabilities.isCreativeMode) { + itemstack.shrink(1); + } + + world.playSound(null, player.posX, player.posY, player.posZ, getThrowSound(itemstack), SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); + + if (!world.isRemote) { + EntityProjectile projectile = new EntityProjectile(world, player); + + projectile.setItem(itemstack); + projectile.setThrowDamage(getThrowDamage(itemstack)); + projectile.shoot(player, player.rotationPitch, player.rotationYaw, 0, 1.5F, 1); + + world.spawnEntity(projectile); + } + + player.addStat(StatList.getObjectUseStats(itemstack.getItem())); + } + + default ItemStack toss(World world, IPosition pos, EnumFacing facing, ItemStack stack, float velocity, float inaccuracy) { + EntityProjectile iprojectile = new EntityProjectile(world, pos.getX(), pos.getY(), pos.getZ()); + + iprojectile.setItem(stack); + iprojectile.setThrowDamage(getThrowDamage(stack)); + + iprojectile.shoot(facing.getXOffset(), facing.getYOffset() + 0.1F, facing.getZOffset(), velocity, inaccuracy); + + world.spawnEntity(iprojectile); + + stack.shrink(1); + + return stack; + } + + class DispenserBehaviour extends BehaviorDefaultDispenseItem { + @Override + public ItemStack dispenseStack(IBlockSource source, ItemStack stack) { + ITossable tossable = (ITossable)stack.getItem(); + + if (tossable.canBeThrown(stack)) { + return shootStack(source, stack); + } + + return super.dispenseStack(source, stack); + } + + public ItemStack shootStack(IBlockSource source, ItemStack stack) { + return ((ITossable)stack.getItem()).toss(source.getWorld(), + BlockDispenser.getDispensePosition(source), + (EnumFacing)source.getBlockState().getValue(BlockDispenser.FACING), + stack, getProjectileInaccuracy(), getProjectileVelocity()); + } + + protected float getProjectileInaccuracy() { + return 6.0F; + } + + protected float getProjectileVelocity() { + return 1.1F; + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemApple.java b/src/main/java/com/minelittlepony/unicopia/item/ItemApple.java index c7ad6dcf..f90a9559 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemApple.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemApple.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.item; import java.util.Random; -import com.minelittlepony.unicopia.UItems; import com.minelittlepony.util.MagicalDamageSource; import com.minelittlepony.util.vector.VecHelper; @@ -63,20 +62,25 @@ public class ItemApple extends ItemFood { @Override public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { RayTraceResult mop = VecHelper.getObjectMouseOver(player, 5, 0); + if (mop != null && mop.typeOfHit == RayTraceResult.Type.ENTITY) { ItemStack stack = player.getHeldItem(hand); + if (canFeedTo(stack, mop.entityHit)) { return onFedTo(stack, player, mop.entityHit); } } + return super.onItemRightClick(world, player, hand); } @Override protected void onFoodEaten(ItemStack stack, World w, EntityPlayer player) { super.onFoodEaten(stack, w, player); + if (isZapApple(stack)) { player.attackEntityFrom(MagicalDamageSource.create("zap"), 120); + w.addWeatherEffect(new EntityLightningBolt(w, player.posX, player.posY, player.posZ, false)); } } @@ -92,7 +96,11 @@ public class ItemApple extends ItemFood { public ActionResult onFedTo(ItemStack stack, EntityPlayer player, Entity e) { e.onStruckByLightning(new EntityLightningBolt(e.world, e.posX, e.posY, e.posZ, false)); - if (!player.capabilities.isCreativeMode) stack.shrink(1); + + if (!player.capabilities.isCreativeMode) { + stack.shrink(1); + } + return new ActionResult(EnumActionResult.SUCCESS, stack); } @@ -103,7 +111,9 @@ public class ItemApple extends ItemFood { public ItemApple setSubTypes(String... types) { subTypes = types; variants = new String[subTypes.length * 2]; + setTranslationKey(variants[0] = types[0]); + for (int i = 1; i < variants.length; i++) { variants[i] = variants[0] + (i % subTypes.length != 0 ? "_" + subTypes[i % subTypes.length] : ""); } @@ -123,7 +133,7 @@ public class ItemApple extends ItemFood { public void getSubItems(CreativeTabs tab, NonNullList items) { if (isInCreativeTab(tab)) { for (int i = 0; i < subTypes.length; i++) { - items.add(new ItemStack(UItems.apple, 1, i)); + items.add(new ItemStack(this, 1, i)); } } } @@ -131,23 +141,22 @@ public class ItemApple extends ItemFood { @Override public EnumRarity getRarity(ItemStack stack) { int meta = stack.getMetadata(); - if (meta == getZapAppleMetadata()) return EnumRarity.EPIC; - if (meta >= subTypes.length) return EnumRarity.RARE; + + if (meta == getZapAppleMetadata()) { + return EnumRarity.EPIC; + } + + if (meta >= subTypes.length) { + return EnumRarity.RARE; + } + return EnumRarity.COMMON; } - /*public String getItemStackDisplayName(ItemStack stack) { - String result = super.getItemStackDisplayName(stack); - if (stack.getMetadata() >= subTypes.length) { - return ChatColor.ITALIC + result; - } - return result; - }*/ - @Override public String getTranslationKey(ItemStack stack) { - int meta = stack.getMetadata() % subTypes.length; - if (meta < 0) meta = 0; + int meta = Math.max(0, stack.getMetadata() % subTypes.length); + return super.getTranslationKey(stack) + (meta > 0 ? "." + subTypes[meta] : ""); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java b/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java new file mode 100644 index 00000000..b63eef11 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemTomato.java @@ -0,0 +1,91 @@ +package com.minelittlepony.unicopia.item; + +import com.minelittlepony.unicopia.player.PlayerSpeciesList; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemFood; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class ItemTomato extends ItemFood implements ITossable { + + public ItemTomato(String domain, String name, int heal, int sat) { + super(heal, sat, false); + + setTranslationKey(name); + setRegistryName(domain, name); + + setDispenseable(); + } + + @Override + public void getSubItems(CreativeTabs tab, NonNullList items) { + if (isInCreativeTab(tab)) { + items.add(new ItemStack(this, 1, 0)); + items.add(new ItemStack(this, 1, 1)); + } + } + + @Override + public String getTranslationKey(ItemStack stack) { + return super.getTranslationKey(stack) + (canBeThrown(stack) ? ".rotten" : ""); + } + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack itemstack = player.getHeldItem(hand); + + if (canBeThrown(itemstack) && !player.canEat(false)) { + toss(world, itemstack, player); + + return new ActionResult(EnumActionResult.SUCCESS, itemstack); + } + + return super.onItemRightClick(world, player, hand); + } + + public boolean canBeThrown(ItemStack stack) { + return stack.getMetadata() > 0; + } + + protected boolean isSickening(ItemStack stack, EntityPlayer player) { + return canBeThrown(stack) + && !PlayerSpeciesList.instance().getPlayer(player).getPlayerSpecies().canUseEarth(); + } + + @Override + protected void onFoodEaten(ItemStack stack, World worldIn, EntityPlayer player) { + + PotionEffect effect = player.getActivePotionEffect(MobEffects.NAUSEA); + + if (isSickening(stack, player)) { + int duration = 7000; + + if (effect != null) { + duration += Math.max(0, effect.getDuration()); + } + + player.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, duration, 4)); + } else if (effect != null) { + player.removePotionEffect(MobEffects.NAUSEA); + } + + super.onFoodEaten(stack, worldIn, player); + } + + @Override + public void onImpact(World world, BlockPos pos, IBlockState state) { + if (!world.isRemote && state.getMaterial() == Material.GLASS) { + world.destroyBlock(pos, true); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java index c4cccce3..6dd52685 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java @@ -60,12 +60,11 @@ class PlayerGravityDelegate implements IUpdatable, IGravity, InbtS entity.fallDistance = 0; - float exhaustion = (0.2F * ticksInAir++) / 90; + float exhaustion = (0.5F * ticksInAir++) / 70; if (entity.isSprinting()) { exhaustion *= 3.11F; } - exhaustion *= (1 - flightExperience/MAXIMUM_FLIGHT_EXPERIENCE); entity.addExhaustion(exhaustion); diff --git a/src/main/java/com/minelittlepony/unicopia/render/RenderProjectile.java b/src/main/java/com/minelittlepony/unicopia/render/RenderProjectile.java new file mode 100644 index 00000000..0ef0a90c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/render/RenderProjectile.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.render; + +import com.minelittlepony.unicopia.entity.EntityProjectile; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.entity.RenderSnowball; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +public class RenderProjectile extends RenderSnowball { + + public RenderProjectile(RenderManager renderManager) { + super(renderManager, Items.POTIONITEM, Minecraft.getMinecraft().getRenderItem()); + } + + @Override + public ItemStack getStackToRender(EntityProjectile entity) { + return entity.getItem(); + } +} diff --git a/src/main/java/com/minelittlepony/util/PosHelper.java b/src/main/java/com/minelittlepony/util/PosHelper.java index 2d04ce3e..4bbd81c9 100644 --- a/src/main/java/com/minelittlepony/util/PosHelper.java +++ b/src/main/java/com/minelittlepony/util/PosHelper.java @@ -2,9 +2,13 @@ package com.minelittlepony.util; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Stream; + +import com.google.common.collect.Streams; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.MutableBlockPos; public class PosHelper { @@ -22,4 +26,11 @@ public class PosHelper { } return false; } + + /** + * Creates a stream of mutable block positions ranging from the beginning position to end. + */ + public static Stream inRegion(BlockPos from, BlockPos to) { + return Streams.stream(BlockPos.getAllInBoxMutable(from, to)); + } } diff --git a/src/main/resources/assets/unicopia/blockstates/cloud_farmland.json b/src/main/resources/assets/unicopia/blockstates/cloud_farmland.json new file mode 100644 index 00000000..00a1aa0e --- /dev/null +++ b/src/main/resources/assets/unicopia/blockstates/cloud_farmland.json @@ -0,0 +1,12 @@ +{ + "variants": { + "moisture=0": { "model": "unicopia:farmland/dry" }, + "moisture=1": { "model": "unicopia:farmland/dry" }, + "moisture=2": { "model": "unicopia:farmland/dry" }, + "moisture=3": { "model": "unicopia:farmland/dry" }, + "moisture=4": { "model": "unicopia:farmland/dry" }, + "moisture=5": { "model": "unicopia:farmland/dry" }, + "moisture=6": { "model": "unicopia:farmland/dry" }, + "moisture=7": { "model": "unicopia:farmland/wet" } + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index 89b3445a..eeb09fc5 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -45,6 +45,10 @@ item.apple.rotten.name=Rotten Apple item.apple.zap.name=Zap Apple item.apple.zap_cooked.name=Cooked Zap Apple +item.tomato.name=Tomato +item.tomato.rotten.name=Rotten Tomato +item.tomato.cloud.name=Cloudsdale Tomato + item.alfalfa_leaves.name=Alfalfa item.alfalfa_seeds.name=Grain diff --git a/src/main/resources/assets/unicopia/models/block/farmland/dry.json b/src/main/resources/assets/unicopia/models/block/farmland/dry.json new file mode 100644 index 00000000..bc3335a5 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/farmland/dry.json @@ -0,0 +1,8 @@ +{ + "parent": "block/farmland", + "textures": { + "particle": "unicopia:blocks/cloud_normal", + "dirt": "unicopia:blocks/cloud_normal", + "top": "unicopia:blocks/cloud_farmland_dry" + } +} diff --git a/src/main/resources/assets/unicopia/models/block/farmland/wet.json b/src/main/resources/assets/unicopia/models/block/farmland/wet.json new file mode 100644 index 00000000..025ed2f1 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/block/farmland/wet.json @@ -0,0 +1,8 @@ +{ + "parent": "block/farmland", + "textures": { + "particle": "unicopia:blocks/cloud_normal", + "dirt": "unicopia:blocks/cloud_normal", + "top": "unicopia:blocks/cloud_farmland_wet" + } +} diff --git a/src/main/resources/assets/unicopia/models/item/cloudsdale_tomato.json b/src/main/resources/assets/unicopia/models/item/cloudsdale_tomato.json new file mode 100644 index 00000000..cfc42301 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/cloudsdale_tomato.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "unicopia:items/tomato" + } +} diff --git a/src/main/resources/assets/unicopia/models/item/rotten_cloudsdale_tomato.json b/src/main/resources/assets/unicopia/models/item/rotten_cloudsdale_tomato.json new file mode 100644 index 00000000..83747491 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/rotten_cloudsdale_tomato.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "unicopia:items/rotten_tomato" + } +} diff --git a/src/main/resources/assets/unicopia/models/item/rotten_tomato.json b/src/main/resources/assets/unicopia/models/item/rotten_tomato.json new file mode 100644 index 00000000..83747491 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/rotten_tomato.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "unicopia:items/rotten_tomato" + } +} diff --git a/src/main/resources/assets/unicopia/models/item/tomato.json b/src/main/resources/assets/unicopia/models/item/tomato.json new file mode 100644 index 00000000..cfc42301 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/tomato.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "unicopia:items/tomato" + } +} diff --git a/src/main/resources/assets/unicopia/textures/blocks/cloud_farmland_dry.png b/src/main/resources/assets/unicopia/textures/blocks/cloud_farmland_dry.png new file mode 100644 index 00000000..b0ccfd33 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/blocks/cloud_farmland_dry.png differ diff --git a/src/main/resources/assets/unicopia/textures/blocks/cloud_farmland_wet.png b/src/main/resources/assets/unicopia/textures/blocks/cloud_farmland_wet.png new file mode 100644 index 00000000..1bbad680 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/blocks/cloud_farmland_wet.png differ diff --git a/src/main/resources/assets/unicopia/textures/items/rotten_tomato.png b/src/main/resources/assets/unicopia/textures/items/rotten_tomato.png new file mode 100644 index 00000000..07466582 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/items/rotten_tomato.png differ diff --git a/src/main/resources/assets/unicopia/textures/items/tomato.png b/src/main/resources/assets/unicopia/textures/items/tomato.png new file mode 100644 index 00000000..b6309238 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/items/tomato.png differ