/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.pepsoft.worldpainter.layers.plants; import org.pepsoft.minecraft.Entity; import org.pepsoft.minecraft.Material; import org.pepsoft.minecraft.TileEntity; import org.pepsoft.worldpainter.exporting.MinecraftWorld; import org.pepsoft.worldpainter.objects.WPObject; import javax.vecmath.Point3i; import java.io.Serializable; import java.util.List; import java.util.Map; import static org.pepsoft.minecraft.Block.BLOCKS; import static org.pepsoft.minecraft.Constants.*; import static org.pepsoft.worldpainter.layers.plants.Plant.Category.*; /** * * @author pepijn */ public final class Plant implements WPObject { public Plant(String name, Material material, int height, int maxGrowth, Category category, String iconName) { this.name = name; if (category == CROPS) { // Adjust the material for the specified maximum growth factor: if ((material.blockType == BLK_CARROTS) || (material.blockType == BLK_POTATOES)) { if (maxGrowth == 3) { this.material = Material.get(material.blockType, 7); } else { this.material = Material.get(material.blockType, maxGrowth * 2); } } else { this.material = Material.get(material.blockType, maxGrowth); } } else if (category == Category.NETHER) { this.material = Material.get(BLK_NETHER_WART, maxGrowth + ((maxGrowth > 0) ? 1 : 0)); } else { this.material = material; } this.category = category; this.maxData = maxGrowth; this.iconName = iconName; dimensions = new Point3i(1, 1, height); growth = maxGrowth; } private Plant(Plant plant, int growth) { name = plant.name; category = plant.category; maxData = plant.maxData; iconName = plant.iconName; this.growth = growth; switch (category) { case CACTUS: case SUGAR_CANE: material = plant.material; dimensions = new Point3i(1, 1, Math.min(growth + 1, plant.dimensions.z)); break; case CROPS: if ((plant.material.blockType == BLK_CARROTS) || (plant.material.blockType == BLK_POTATOES)) { if (growth == 3) { material = Material.get(plant.material.blockType, 7); } else { material = Material.get(plant.material.blockType, growth * 2); } } else { material = Material.get(plant.material.blockType, growth); } dimensions = plant.dimensions; break; case NETHER: material = Material.get(BLK_NETHER_WART, growth + ((growth > 0) ? 1 : 0)); dimensions = plant.dimensions; break; default: throw new InternalError(); } } public Category getCategory() { return category; } public int getMaxData() { return maxData; } public boolean isValidFoundation(MinecraftWorld world, int x, int y, int height) { final int blockType = world.getBlockTypeAt(x, y, height); switch (category) { case CACTUS: return (blockType == BLK_SAND) && (! isSolid(world, x - 1, y, height + 1)) && (! isSolid(world, x, y - 1, height + 1)) && (! isSolid(world, x + 1, y, height + 1)) && (! isSolid(world, x, y + 1, height + 1)); case CROPS: return blockType == BLK_TILLED_DIRT; case MUSHROOMS: // If it's dark enough mushrooms can be placed on pretty much // anything return (! BLOCKS[blockType].veryInsubstantial) && (blockType != BLK_GLASS) && (blockType != BLK_ICE); case PLANTS_AND_FLOWERS: return (blockType == BLK_GRASS) || (blockType == BLK_DIRT) || (blockType == BLK_TILLED_DIRT) || ((material.equals(Material.DEAD_SHRUBS)) && ((blockType == BLK_SAND) || (blockType == BLK_HARDENED_CLAY))); case SAPLINGS: return (blockType == BLK_GRASS) || (blockType == BLK_DIRT) || (blockType == BLK_TILLED_DIRT); case SUGAR_CANE: return ((blockType == BLK_GRASS) || (blockType == BLK_DIRT) || (blockType == BLK_SAND) || (blockType == BLK_TILLED_DIRT)) && (isWater(world, x - 1, y, height) || isWater(world, x, y - 1, height) || isWater(world, x + 1, y, height) || isWater(world, x, y + 1, height)); case WATER_PLANTS: // Just check whether the location is flooded; a special case in // the exporter will check for the water surface final int blockAbove = world.getBlockTypeAt(x, y, height + 1); return (blockAbove == BLK_WATER) || (blockAbove == BLK_STATIONARY_WATER); case NETHER: return blockType == BLK_SOUL_SAND; case END: return (blockType == BLK_END_STONE) || (blockType == BLK_CHORUS_PLANT); default: throw new InternalError(); } } public Plant withGrowth(int growth) { if ((maxData == 0) || (growth == this.growth)) { return this; } else { return new Plant(this, growth); } } // WPObject @Override public String getName() { return name; } @Override public void setName(String name) { throw new UnsupportedOperationException("Plant is unmodifiable"); } @Override public Point3i getDimensions() { return dimensions; } @Override public Material getMaterial(int x, int y, int z) { if (z > 0) { switch (category) { case PLANTS_AND_FLOWERS: return UPPER_DOUBLE_HIGH_PLANT; case CACTUS: return Material.CACTUS; case SUGAR_CANE: return Material.SUGAR_CANE; default: throw new UnsupportedOperationException("Don't know what material to provide for category " + category); } } else { return material; } } @Override public boolean getMask(int x, int y, int z) { return true; } @Override public List<Entity> getEntities() { return null; } @Override public List<TileEntity> getTileEntities() { return null; } @Override public Map<String, Serializable> getAttributes() { return null; } @Override public <T extends Serializable> T getAttribute(AttributeKey<T> key) { return key.defaultValue; } @Override public void setAttributes(Map<String, Serializable> attributes) { throw new UnsupportedOperationException("Plant is unmodifiable"); } @Override public <T extends Serializable> void setAttribute(AttributeKey<T> key, T value) { throw new UnsupportedOperationException("Plant is unmodifiable"); } @Override public Point3i getOffset() { return new Point3i(0, 0, 0); } @SuppressWarnings("CloneDoesntCallSuperClone") // Plants are unmodifiable @Override public WPObject clone() { return this; } @Override public String toString() { return name; } private boolean isSolid(MinecraftWorld world, int x, int y, int height) { int blockType = world.getBlockTypeAt(x, y, height); return (blockType == BLK_CACTUS) || (! BLOCKS[blockType].veryInsubstantial); } private boolean isWater(MinecraftWorld world, int x, int y, int height) { final int blockType = world.getBlockTypeAt(x, y, height); return (blockType == BLK_WATER) || (blockType == BLK_STATIONARY_WATER); } public static void main(String[] args) { for (Plant plant: ALL_PLANTS) { System.out.println(plant); } } String getIconName() { return iconName; } private final String name, iconName; private final Point3i dimensions; private final Material material; private final Category category; private final int maxData, growth; private static final Material UPPER_DOUBLE_HIGH_PLANT = Material.get(BLK_LARGE_FLOWERS, 8); public static final Plant TALL_GRASS = new Plant("Tall Grass", Material.get(BLK_TALL_GRASS, 1), 1, 0, PLANTS_AND_FLOWERS, "blocks/tallgrass.png"); public static final Plant FERN = new Plant("Fern", Material.get(BLK_TALL_GRASS, 2), 1, 0, PLANTS_AND_FLOWERS, "blocks/fern.png"); public static final Plant DEAD_SHRUB = new Plant("Dead Shrub", Material.DEAD_SHRUBS, 1, 0, PLANTS_AND_FLOWERS, "blocks/deadbush.png"); public static final Plant DANDELION = new Plant("Dandelion", Material.DANDELION, 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_dandelion.png"); public static final Plant POPPY = new Plant("Poppy", Material.ROSE, 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_rose.png"); public static final Plant BLUE_ORCHID = new Plant("Blue Orchid", Material.get(BLK_ROSE, 1), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_blue_orchid.png"); public static final Plant ALLIUM = new Plant("Allium", Material.get(BLK_ROSE, 2), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_allium.png"); public static final Plant AZURE_BLUET = new Plant("Azure Bluet", Material.get(BLK_ROSE, 3), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_houstonia.png"); public static final Plant TULIP_RED = new Plant("Red Tulip", Material.get(BLK_ROSE, 4), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_tulip_red.png"); public static final Plant TULIP_ORANGE = new Plant("Orange Tulip", Material.get(BLK_ROSE, 5), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_tulip_orange.png"); public static final Plant TULIP_WHITE = new Plant("White Tulip", Material.get(BLK_ROSE, 6), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_tulip_white.png"); public static final Plant TULIP_PINK = new Plant("Pink Tulip", Material.get(BLK_ROSE, 7), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_tulip_pink.png"); public static final Plant OXEYE_DAISY = new Plant("Oxeye Daisy", Material.get(BLK_ROSE, 8), 1, 0, PLANTS_AND_FLOWERS, "blocks/flower_oxeye_daisy.png"); public static final Plant SUNFLOWER = new Plant("Sunflower", Material.get(BLK_LARGE_FLOWERS), 2, 0, PLANTS_AND_FLOWERS, "blocks/double_plant_sunflower_front.png"); public static final Plant LILAC = new Plant("Lilac", Material.get(BLK_LARGE_FLOWERS, 1), 2, 0, PLANTS_AND_FLOWERS, "blocks/double_plant_syringa_top.png"); public static final Plant DOUBLE_TALL_GRASS = new Plant("Double Tall Grass", Material.get(BLK_LARGE_FLOWERS, 2), 2, 0, PLANTS_AND_FLOWERS, "blocks/double_plant_grass_top.png"); public static final Plant LARGE_FERN = new Plant("Large Fern", Material.get(BLK_LARGE_FLOWERS, 3), 2, 0, PLANTS_AND_FLOWERS, "blocks/double_plant_fern_top.png"); public static final Plant ROSE_BUSH = new Plant("Rose Bush", Material.get(BLK_LARGE_FLOWERS, 4), 2, 0, PLANTS_AND_FLOWERS, "blocks/double_plant_rose_top.png"); public static final Plant PEONY = new Plant("Peony", Material.get(BLK_LARGE_FLOWERS, 5), 2, 0, PLANTS_AND_FLOWERS, "blocks/double_plant_paeonia_top.png"); public static final Plant SAPLING_OAK = new Plant("Oak Sapling", Material.get(BLK_SAPLING, DATA_OAK), 1, 0, SAPLINGS, "blocks/sapling_oak.png"); public static final Plant SAPLING_DARK_OAK = new Plant("Dark Oak Sapling", Material.get(BLK_SAPLING, DATA_DARK_OAK), 1, 0, SAPLINGS, "blocks/sapling_roofed_oak.png"); public static final Plant SAPLING_PINE = new Plant("Pine Sapling", Material.get(BLK_SAPLING, DATA_PINE), 1, 0, SAPLINGS, "blocks/sapling_spruce.png"); public static final Plant SAPLING_BIRCH = new Plant("Birch Sapling", Material.get(BLK_SAPLING, DATA_BIRCH), 1, 0, SAPLINGS, "blocks/sapling_birch.png"); public static final Plant SAPLING_JUNGLE = new Plant("Jungle Sapling", Material.get(BLK_SAPLING, DATA_JUNGLE), 1, 0, SAPLINGS, "blocks/sapling_jungle.png"); public static final Plant SAPLING_ACACIA = new Plant("Acacia Sapling", Material.get(BLK_SAPLING, DATA_ACACIA), 1, 0, SAPLINGS, "blocks/sapling_acacia.png"); public static final Plant MUSHROOM_RED = new Plant("Red Mushroom", Material.RED_MUSHROOM, 1, 0, MUSHROOMS, "blocks/mushroom_red.png"); public static final Plant MUSHROOM_BROWN = new Plant("Brown Mushroom", Material.BROWN_MUSHROOM, 1, 0, MUSHROOMS, "blocks/mushroom_brown.png"); public static final Plant WHEAT = new Plant("Wheat", Material.WHEAT, 1, 7, CROPS, "items/wheat.png"); public static final Plant CARROTS = new Plant("Carrots", Material.get(BLK_CARROTS), 1, 3, CROPS, "items/carrot.png"); public static final Plant POTATOES = new Plant("Potatoes", Material.get(BLK_POTATOES), 1, 3, CROPS, "items/potato.png"); public static final Plant PUMPKIN_STEMS = new Plant("Pumpkin Stems", Material.get(BLK_PUMPKIN_STEM), 1, 7, CROPS, "blocks/pumpkin_side.png"); public static final Plant MELON_STEMS = new Plant("Melon Stems", Material.get(BLK_MELON_STEM), 1, 7, CROPS, "blocks/melon_side.png"); public static final Plant BEETROOTS = new Plant("Beetroots", Material.get(BLK_BEETROOTS), 1, 3, CROPS, "items/beetroot.png"); public static final Plant CACTUS = new Plant("Cactus", Material.CACTUS, 3, 2, Category.CACTUS, "blocks/cactus_side.png"); public static final Plant SUGAR_CANE = new Plant("Sugar Cane", Material.SUGAR_CANE, 3, 2, Category.SUGAR_CANE, "items/reeds.png"); public static final Plant LILY_PAD = new Plant("Lily Pad", Material.LILY_PAD, 1, 0, Category.WATER_PLANTS, "blocks/waterlily.png"); public static final Plant NETHER_WART = new Plant("Nether Wart", Material.get(BLK_NETHER_WART), 1, 2, Category.NETHER, "items/nether_wart.png"); public static final Plant CHORUS_PLANT = new Plant("Chorus Plant", Material.get(BLK_CHORUS_FLOWER), 1, 0, Category.END, "blocks/chorus_flower.png"); // The code which uses this assumes there will never be more than 128 // plants. If that ever happens it needs to be overhauled! // IMPORTANT: indices into this array are stored in layer settings! New // entries MUST be added at the end, and the order MUST never be changed! public static final Plant[] ALL_PLANTS = {TALL_GRASS, DOUBLE_TALL_GRASS, FERN, LARGE_FERN, DEAD_SHRUB, DANDELION, POPPY, BLUE_ORCHID, ALLIUM, AZURE_BLUET, TULIP_RED, TULIP_ORANGE, TULIP_WHITE, TULIP_PINK, OXEYE_DAISY, SUNFLOWER, LILAC, ROSE_BUSH, PEONY, SAPLING_OAK, SAPLING_DARK_OAK, SAPLING_PINE, SAPLING_BIRCH, SAPLING_JUNGLE, SAPLING_ACACIA, MUSHROOM_RED, MUSHROOM_BROWN, WHEAT, CARROTS, POTATOES, PUMPKIN_STEMS, MELON_STEMS, CACTUS, SUGAR_CANE, LILY_PAD, BEETROOTS, NETHER_WART, CHORUS_PLANT}; public enum Category {PLANTS_AND_FLOWERS, SAPLINGS, MUSHROOMS, CROPS, SUGAR_CANE, CACTUS, WATER_PLANTS, NETHER, END} }