2019-01-19 16:52:04 +01:00
package world.bentobox.greenhouses.greenhouse ;
import java.util.Arrays ;
2019-11-01 05:36:05 +01:00
import java.util.EnumMap ;
2019-01-22 00:44:01 +01:00
import java.util.HashSet ;
2019-01-19 16:52:04 +01:00
import java.util.List ;
import java.util.Map ;
import java.util.Optional ;
import java.util.Random ;
2019-01-22 00:44:01 +01:00
import java.util.Set ;
2019-01-19 16:52:04 +01:00
import java.util.TreeMap ;
2021-01-17 17:41:50 +01:00
import java.util.concurrent.CompletableFuture ;
2021-04-19 16:26:43 +02:00
import java.util.concurrent.ThreadLocalRandom ;
2019-01-19 16:52:04 +01:00
import java.util.stream.Collectors ;
2021-01-17 17:41:50 +01:00
import org.bukkit.Bukkit ;
2019-10-18 07:37:27 +02:00
import org.bukkit.Location ;
2019-01-19 16:52:04 +01:00
import org.bukkit.Material ;
2019-07-08 00:45:47 +02:00
import org.bukkit.Particle ;
2020-11-16 00:54:06 +01:00
import org.bukkit.World.Environment ;
2019-01-19 16:52:04 +01:00
import org.bukkit.block.Biome ;
import org.bukkit.block.Block ;
import org.bukkit.block.BlockFace ;
2019-09-20 01:21:43 +02:00
import org.bukkit.block.data.Bisected ;
import org.bukkit.block.data.BlockData ;
2019-10-18 07:37:27 +02:00
import org.bukkit.entity.Entity ;
2019-01-19 16:52:04 +01:00
import org.bukkit.entity.EntityType ;
2020-11-16 00:54:06 +01:00
import org.bukkit.entity.Hoglin ;
import org.bukkit.entity.Piglin ;
2019-10-18 07:37:27 +02:00
import org.bukkit.util.BoundingBox ;
import org.bukkit.util.Vector ;
2019-01-19 16:52:04 +01:00
2020-11-16 00:54:06 +01:00
import com.google.common.base.Enums ;
2020-08-16 21:49:27 +02:00
import com.google.common.collect.ArrayListMultimap ;
import com.google.common.collect.Multimap ;
2019-01-19 16:52:04 +01:00
import world.bentobox.bentobox.util.Util ;
import world.bentobox.greenhouses.Greenhouses ;
2019-01-22 00:44:01 +01:00
import world.bentobox.greenhouses.data.Greenhouse ;
import world.bentobox.greenhouses.managers.GreenhouseManager.GreenhouseResult ;
2021-01-17 17:41:50 +01:00
import world.bentobox.greenhouses.world.AsyncWorldCache ;
2019-01-19 16:52:04 +01:00
2019-01-22 00:44:01 +01:00
public class BiomeRecipe implements Comparable < BiomeRecipe > {
2019-11-01 05:36:05 +01:00
private static final String CHANCE_FOR = " % chance for " ;
2019-05-09 00:21:11 +02:00
private Greenhouses addon ;
2019-01-19 16:52:04 +01:00
private Biome type ;
private Material icon ; // Biome icon for control panel
private int priority ;
private String name ;
private String friendlyName ;
2020-08-23 02:55:38 +02:00
private static final List < BlockFace > ADJ_BLOCKS = Arrays . asList ( BlockFace . DOWN , BlockFace . EAST , BlockFace . NORTH , BlockFace . SOUTH , BlockFace . UP , BlockFace . WEST ) ;
2019-01-19 16:52:04 +01:00
// Content requirements
// Material, Type, Qty. There can be more than one type of material required
2019-11-01 05:36:05 +01:00
private final Map < Material , Integer > requiredBlocks = new EnumMap < > ( Material . class ) ;
2019-01-19 16:52:04 +01:00
// Plants
2019-01-26 17:38:13 +01:00
private final TreeMap < Double , GreenhousePlant > plantTree = new TreeMap < > ( ) ;
2019-01-19 16:52:04 +01:00
// Mobs
// Entity Type, Material to Spawn on, Probability
2019-01-26 17:38:13 +01:00
private final TreeMap < Double , GreenhouseMob > mobTree = new TreeMap < > ( ) ;
2019-01-19 16:52:04 +01:00
// Conversions
// Original Material, Original Type, New Material, New Type, Probability
2020-08-16 21:49:27 +02:00
//private final Map<Material, GreenhouseBlockConversions> conversionBlocks = new EnumMap<>(Material.class);
2021-08-01 08:10:07 +02:00
private final Multimap < Material , GreenhouseBlockConversions > conversionBlocks = ArrayListMultimap . create ( ) ;
2019-01-19 16:52:04 +01:00
private int mobLimit ;
private int waterCoverage ;
private int iceCoverage ;
private int lavaCoverage ;
private String permission = " " ;
2019-01-26 17:38:13 +01:00
private final Random random = new Random ( ) ;
2019-10-12 18:31:51 +02:00
2019-01-19 16:52:04 +01:00
2019-05-09 00:21:11 +02:00
public BiomeRecipe ( ) { }
2019-01-19 16:52:04 +01:00
/ * *
2019-01-26 17:38:13 +01:00
* @param type - biome
* @param priority - priority ( higher is better )
2019-01-19 16:52:04 +01:00
* /
2019-01-22 00:44:01 +01:00
public BiomeRecipe ( Greenhouses addon , Biome type , int priority ) {
2019-01-26 17:38:13 +01:00
this . addon = addon ;
2019-01-19 16:52:04 +01:00
this . type = type ;
this . priority = priority ;
mobLimit = 9 ; // Default
}
2020-08-16 21:49:27 +02:00
2020-01-30 18:52:53 +01:00
private void startupLog ( String message ) {
if ( addon . getSettings ( ) . isStartupLog ( ) ) addon . log ( message ) ;
}
2019-01-19 16:52:04 +01:00
/ * *
* @param oldMaterial - material that will convert
* @param newMaterial - what it will convert to
* @param convChance - percentage chance
* @param localMaterial - what material must be next to it for conversion to happen
* /
public void addConvBlocks ( Material oldMaterial , Material newMaterial , double convChance , Material localMaterial ) {
double probability = Math . min ( convChance / 100 , 1D ) ;
conversionBlocks . put ( oldMaterial , new GreenhouseBlockConversions ( oldMaterial , newMaterial , probability , localMaterial ) ) ;
2020-01-30 18:52:53 +01:00
startupLog ( " " + convChance + CHANCE_FOR + Util . prettifyText ( oldMaterial . toString ( ) ) + " to convert to " + Util . prettifyText ( newMaterial . toString ( ) ) ) ;
2019-01-19 16:52:04 +01:00
}
/ * *
2019-01-26 17:38:13 +01:00
* @param mobType - entity type
2021-04-19 16:26:43 +02:00
* @param mobProbability - relative probability
2019-01-26 17:38:13 +01:00
* @param mobSpawnOn - material to spawn on
2019-10-13 02:09:38 +02:00
* @return true if add is successful
2019-01-19 16:52:04 +01:00
* /
2020-11-16 00:35:59 +01:00
public boolean addMobs ( EntityType mobType , double mobProbability , Material mobSpawnOn ) {
2020-01-30 18:52:53 +01:00
startupLog ( " " + mobProbability + CHANCE_FOR + Util . prettifyText ( mobType . toString ( ) ) + " to spawn on " + Util . prettifyText ( mobSpawnOn . toString ( ) ) + " . " ) ;
2020-11-16 00:35:59 +01:00
double probability = mobProbability / 100 ;
2019-01-22 00:44:01 +01:00
double lastProb = mobTree . isEmpty ( ) ? 0D : mobTree . lastKey ( ) ;
2019-01-19 16:52:04 +01:00
// Add up all the probabilities in the list so far
2019-01-22 00:44:01 +01:00
if ( ( 1D - lastProb ) > = probability ) {
2019-01-19 16:52:04 +01:00
// Add to probability tree
2019-01-22 00:44:01 +01:00
mobTree . put ( lastProb + probability , new GreenhouseMob ( mobType , mobSpawnOn ) ) ;
2019-10-13 02:09:38 +02:00
return true ;
2019-01-19 16:52:04 +01:00
} else {
2021-08-01 08:10:07 +02:00
addon . logError ( " Mob chances add up to > 100% in " + type . toString ( ) + " biome recipe! Skipping " + mobType ) ;
2019-10-13 02:09:38 +02:00
return false ;
2019-01-19 16:52:04 +01:00
}
}
/ * *
* Creates a list of plants that can grow , the probability and what they must grow on .
* Data is drawn from the file biomes . yml
* @param plantMaterial - plant type
* @param plantProbability - probability of growing
* @param plantGrowOn - material on which it must grow
2019-10-13 02:09:38 +02:00
* @return true if add is successful
2019-01-19 16:52:04 +01:00
* /
2020-11-16 00:35:59 +01:00
public boolean addPlants ( Material plantMaterial , double plantProbability , Material plantGrowOn ) {
double probability = plantProbability / 100 ;
2019-01-19 16:52:04 +01:00
// Add up all the probabilities in the list so far
2019-01-22 00:44:01 +01:00
double lastProb = plantTree . isEmpty ( ) ? 0D : plantTree . lastKey ( ) ;
if ( ( 1D - lastProb ) > = probability ) {
2019-01-19 16:52:04 +01:00
// Add to probability tree
2019-01-22 00:44:01 +01:00
plantTree . put ( lastProb + probability , new GreenhousePlant ( plantMaterial , plantGrowOn ) ) ;
2019-01-19 16:52:04 +01:00
} else {
2019-01-26 17:38:13 +01:00
addon . logError ( " Plant chances add up to > 100% in " + type . toString ( ) + " biome recipe! Skipping " + plantMaterial . toString ( ) ) ;
2019-10-13 02:09:38 +02:00
return false ;
2019-01-19 16:52:04 +01:00
}
2020-01-30 18:52:53 +01:00
startupLog ( " " + plantProbability + CHANCE_FOR + Util . prettifyText ( plantMaterial . toString ( ) ) + " to grow on " + Util . prettifyText ( plantGrowOn . toString ( ) ) ) ;
2019-10-13 02:09:38 +02:00
return true ;
2019-01-19 16:52:04 +01:00
}
/ * *
2019-01-26 17:38:13 +01:00
* @param blockMaterial - block material
* @param blockQty - number of blocks required
2019-01-19 16:52:04 +01:00
* /
public void addReqBlocks ( Material blockMaterial , int blockQty ) {
requiredBlocks . put ( blockMaterial , blockQty ) ;
2020-01-30 18:52:53 +01:00
startupLog ( " " + blockMaterial + " x " + blockQty ) ;
2019-01-19 16:52:04 +01:00
}
/ * *
2019-01-25 04:11:59 +01:00
* Checks greenhouse meets recipe requirements .
* @return GreenhouseResult - result
2019-01-22 00:44:01 +01:00
* /
2021-01-17 17:41:50 +01:00
public CompletableFuture < Set < GreenhouseResult > > checkRecipe ( Greenhouse gh ) {
CompletableFuture < Set < GreenhouseResult > > r = new CompletableFuture < > ( ) ;
Bukkit . getScheduler ( ) . runTaskAsynchronously ( addon . getPlugin ( ) , ( ) - > checkRecipeAsync ( r , gh ) ) ;
return r ;
}
/ * *
* Check greenhouse meets recipe requirements . Expected to be run async .
* @param r - future to complete when done
* @param gh - greenhouse
* @return set of results from the check
* /
private Set < GreenhouseResult > checkRecipeAsync ( CompletableFuture < Set < GreenhouseResult > > r , Greenhouse gh ) {
AsyncWorldCache cache = new AsyncWorldCache ( gh . getWorld ( ) ) ;
2019-01-22 00:44:01 +01:00
Set < GreenhouseResult > result = new HashSet < > ( ) ;
long area = gh . getArea ( ) ;
2019-11-01 05:36:05 +01:00
Map < Material , Integer > blockCount = new EnumMap < > ( Material . class ) ;
2021-01-17 17:41:50 +01:00
2019-01-19 16:52:04 +01:00
// Look through the greenhouse and count what is in there
2019-01-22 00:44:01 +01:00
for ( int y = gh . getFloorHeight ( ) ; y < gh . getCeilingHeight ( ) ; y + + ) {
2019-05-09 00:21:11 +02:00
for ( int x = ( int ) ( gh . getBoundingBox ( ) . getMinX ( ) + 1 ) ; x < gh . getBoundingBox ( ) . getMaxX ( ) ; x + + ) {
for ( int z = ( int ) ( gh . getBoundingBox ( ) . getMinZ ( ) + 1 ) ; z < gh . getBoundingBox ( ) . getMaxZ ( ) ; z + + ) {
2021-01-17 17:41:50 +01:00
Material t = cache . getBlockType ( x , y , z ) ;
2019-11-01 05:36:05 +01:00
if ( ! t . equals ( Material . AIR ) ) {
blockCount . putIfAbsent ( t , 0 ) ;
blockCount . merge ( t , 1 , Integer : : sum ) ;
2019-01-19 16:52:04 +01:00
}
}
}
}
// Calculate % water, ice and lava ratios
double waterRatio = ( double ) blockCount . getOrDefault ( Material . WATER , 0 ) / area * 100 ;
double lavaRatio = ( double ) blockCount . getOrDefault ( Material . LAVA , 0 ) / area * 100 ;
int ice = blockCount . entrySet ( ) . stream ( ) . filter ( en - > en . getKey ( ) . equals ( Material . ICE )
| | en . getKey ( ) . equals ( Material . BLUE_ICE )
| | en . getKey ( ) . equals ( Material . PACKED_ICE ) )
. mapToInt ( Map . Entry : : getValue ) . sum ( ) ;
double iceRatio = ( double ) ice / ( double ) area * 100 ;
// Check required ratios - a zero means none of these are allowed, e.g.desert has no water
if ( waterCoverage = = 0 & & waterRatio > 0 ) {
2019-01-22 00:44:01 +01:00
result . add ( GreenhouseResult . FAIL_NO_WATER ) ;
2019-01-19 16:52:04 +01:00
}
if ( lavaCoverage = = 0 & & lavaRatio > 0 ) {
2019-01-22 00:44:01 +01:00
result . add ( GreenhouseResult . FAIL_NO_LAVA ) ;
2019-01-19 16:52:04 +01:00
}
if ( iceCoverage = = 0 & & iceRatio > 0 ) {
2019-01-22 00:44:01 +01:00
result . add ( GreenhouseResult . FAIL_NO_ICE ) ;
2019-01-19 16:52:04 +01:00
}
if ( waterCoverage > 0 & & waterRatio < waterCoverage ) {
2019-01-22 00:44:01 +01:00
result . add ( GreenhouseResult . FAIL_INSUFFICIENT_WATER ) ;
2019-01-19 16:52:04 +01:00
}
if ( lavaCoverage > 0 & & lavaRatio < lavaCoverage ) {
2019-01-22 00:44:01 +01:00
result . add ( GreenhouseResult . FAIL_INSUFFICIENT_LAVA ) ;
2019-01-19 16:52:04 +01:00
}
if ( iceCoverage > 0 & & iceRatio < iceCoverage ) {
2019-01-22 00:44:01 +01:00
result . add ( GreenhouseResult . FAIL_INSUFFICIENT_ICE ) ;
2019-01-19 16:52:04 +01:00
}
// Compare to the required blocks
2019-10-12 03:52:32 +02:00
Map < Material , Integer > missingBlocks = requiredBlocks . entrySet ( ) . stream ( ) . collect ( Collectors . toMap ( Map . Entry : : getKey , e - > e . getValue ( ) - blockCount . getOrDefault ( e . getKey ( ) , 0 ) ) ) ;
2019-01-19 16:52:04 +01:00
// Remove any entries that are 0 or less
missingBlocks . values ( ) . removeIf ( v - > v < = 0 ) ;
2019-10-12 03:52:32 +02:00
if ( ! missingBlocks . isEmpty ( ) ) {
result . add ( GreenhouseResult . FAIL_INSUFFICIENT_BLOCKS ) ;
gh . setMissingBlocks ( missingBlocks ) ;
}
2021-01-17 17:41:50 +01:00
// Return to main thread to complete
Bukkit . getScheduler ( ) . runTask ( addon . getPlugin ( ) , ( ) - > r . complete ( result ) ) ;
2019-01-22 00:44:01 +01:00
return result ;
2019-01-19 16:52:04 +01:00
}
/ * *
2019-01-26 17:38:13 +01:00
* Check if block should be converted
* @param b - block to check
2019-01-19 16:52:04 +01:00
* /
2021-04-19 16:26:43 +02:00
public void convertBlock ( Block b ) {
Material bType = b . getType ( ) ;
// Check if there is a block conversion for this block, as while the rest of the method wont do anything if .get() returns nothing anyway it still seems to be quite expensive
if ( conversionBlocks . keySet ( ) . contains ( bType ) ) {
for ( GreenhouseBlockConversions conversion_option : conversionBlocks . get ( bType ) ) {
// Roll the dice before bothering with checking the surrounding block as I think it's more common for greenhouses to be filled with convertable blocks and thus this dice roll wont be "wasted"
2021-08-01 08:10:07 +02:00
if ( ThreadLocalRandom . current ( ) . nextDouble ( ) < conversion_option . probability ( ) ) {
2021-04-19 16:26:43 +02:00
// Check if any of the adjacent blocks matches the required LocalMaterial, if there are any required LocalMaterials
2021-08-01 08:10:07 +02:00
if ( conversion_option . localMaterial ( ) ! = null ) {
2021-04-19 16:26:43 +02:00
for ( BlockFace adjacent_block : ADJ_BLOCKS ) {
2021-08-01 08:10:07 +02:00
if ( b . getRelative ( adjacent_block ) . getType ( ) = = conversion_option . localMaterial ( ) ) {
b . setType ( conversion_option . newMaterial ( ) ) ;
2021-04-19 16:26:43 +02:00
break ;
}
}
} else {
2021-08-01 08:10:07 +02:00
b . setType ( conversion_option . newMaterial ( ) ) ;
2021-04-19 16:26:43 +02:00
}
}
2020-08-16 21:49:27 +02:00
}
2021-04-19 16:26:43 +02:00
}
2019-01-19 16:52:04 +01:00
}
/ * *
* @return the type
* /
public Biome getBiome ( ) {
return type ;
}
/ * *
* @return true if there are blocks to convert for this biome
* /
public boolean getBlockConvert ( ) {
return ! conversionBlocks . isEmpty ( ) ;
}
/ * *
* @return the friendly name
* /
public String getFriendlyName ( ) {
return friendlyName ;
}
/ * *
* @return the iceCoverage
* /
public int getIceCoverage ( ) {
return iceCoverage ;
}
/ * *
* @return the icon
* /
public Material getIcon ( ) {
return icon ;
}
/ * *
* @return the lavaCoverage
* /
public int getLavaCoverage ( ) {
return lavaCoverage ;
}
/ * *
* @return the mobLimit
* /
public int getMobLimit ( ) {
return mobLimit ;
}
/ * *
* @return the name
* /
public String getName ( ) {
return name ;
}
/ * *
* @return the permission
* /
public String getPermission ( ) {
return permission ;
}
/ * *
* @return the priority
* /
2019-10-13 02:09:38 +02:00
public int getPriority ( ) {
2019-01-19 16:52:04 +01:00
return priority ;
}
2019-01-25 04:11:59 +01:00
/ * *
* Spawn a mob on block b if it makes sense and random change suggests it
* @param b - block
* @return true if a mob was spawned
* /
public boolean spawnMob ( Block b ) {
if ( b . getY ( ) = = 0 ) {
return false ;
}
2019-10-18 07:37:27 +02:00
// Center spawned mob
Location spawnLoc = b . getLocation ( ) . clone ( ) . add ( new Vector ( 0 . 5 , 0 , 0 . 5 ) ) ;
2019-01-25 04:11:59 +01:00
return getRandomMob ( )
// Check if the spawn on block matches, if it exists
2021-08-01 08:10:07 +02:00
. filter ( m - > Optional . of ( m . mobSpawnOn ( ) ) . map ( b . getRelative ( BlockFace . DOWN ) . getType ( ) : : equals ) . orElse ( true ) )
2019-10-18 07:37:27 +02:00
// If spawn occurs, check if it can fit inside greenhouse
. map ( m - > {
2021-08-01 08:10:07 +02:00
Entity entity = b . getWorld ( ) . spawnEntity ( spawnLoc , m . mobType ( ) ) ;
2019-10-18 07:37:27 +02:00
if ( entity ! = null ) {
2020-11-16 00:54:06 +01:00
preventZombie ( entity ) ;
2019-10-18 07:37:27 +02:00
return addon
. getManager ( )
. getMap ( )
. getGreenhouse ( b . getLocation ( ) ) . map ( gh - > {
BoundingBox interior = gh . getBoundingBox ( ) . clone ( ) ;
interior . expand ( - 1 , - 1 , - 1 ) ;
if ( ! interior . contains ( entity . getBoundingBox ( ) ) ) {
entity . remove ( ) ;
return false ;
}
return true ;
} ) . orElse ( false ) ;
}
return false ;
} ) . orElse ( false ) ;
2019-01-25 04:11:59 +01:00
}
2020-11-16 00:54:06 +01:00
/ * *
* Prevent hoglins and piglins from zombifying if they spawn in the overworld
* @param entity - spawned entity
* /
private void preventZombie ( Entity entity ) {
if ( ! entity
. getWorld ( )
. getEnvironment ( )
. equals ( Environment . NORMAL ) | |
! Enums . getIfPresent ( EntityType . class , " PIGLIN " )
. isPresent ( ) ) {
return ;
}
2021-08-01 08:10:07 +02:00
if ( entity instanceof Piglin p ) {
2020-11-16 00:54:06 +01:00
p . setImmuneToZombification ( true ) ;
return ;
}
2021-08-01 08:10:07 +02:00
if ( entity instanceof Hoglin h ) {
2020-11-16 00:54:06 +01:00
h . setImmuneToZombification ( true ) ;
}
}
2019-01-19 16:52:04 +01:00
/ * *
* @return a mob that can spawn in the greenhouse
* /
2019-01-25 04:11:59 +01:00
private Optional < GreenhouseMob > getRandomMob ( ) {
2019-01-19 16:52:04 +01:00
// Return a random mob that can spawn in the biome or empty
Double key = mobTree . ceilingKey ( random . nextDouble ( ) ) ;
return key = = null ? Optional . empty ( ) : Optional . ofNullable ( mobTree . get ( key ) ) ;
}
private Optional < GreenhousePlant > getRandomPlant ( ) {
// Grow a random plant that can grow
2019-01-24 18:18:05 +01:00
double r = random . nextDouble ( ) ;
Double key = plantTree . ceilingKey ( r ) ;
2019-01-19 16:52:04 +01:00
return key = = null ? Optional . empty ( ) : Optional . ofNullable ( plantTree . get ( key ) ) ;
}
/ * *
* @return a list of blocks that are required for this recipe
* /
public List < String > getRecipeBlocks ( ) {
return requiredBlocks . entrySet ( ) . stream ( ) . map ( en - > Util . prettifyText ( en . getKey ( ) . toString ( ) ) + " x " + en . getValue ( ) ) . collect ( Collectors . toList ( ) ) ;
}
/ * *
* @return the waterCoverage
* /
public int getWaterCoverage ( ) {
return waterCoverage ;
}
/ * *
* Plants a plant on block bl if it makes sense .
2019-01-22 00:44:01 +01:00
* @param bl - block
* @return true if successful
2019-01-19 16:52:04 +01:00
* /
2019-01-22 00:44:01 +01:00
public boolean growPlant ( Block bl ) {
2020-08-23 00:22:14 +02:00
if ( ! bl . isEmpty ( ) ) {
2019-01-22 00:44:01 +01:00
return false ;
2019-01-19 16:52:04 +01:00
}
2019-01-22 00:44:01 +01:00
return getRandomPlant ( ) . map ( p - > {
2021-08-01 08:10:07 +02:00
if ( bl . getY ( ) ! = 0 & & Optional . of ( p . plantGrownOn ( ) ) . map ( m - > m . equals ( bl . getRelative ( BlockFace . DOWN ) . getType ( ) ) ) . orElse ( false ) ) {
BlockData dataBottom = p . plantMaterial ( ) . createBlockData ( ) ;
2019-09-20 01:21:43 +02:00
if ( dataBottom instanceof Bisected ) {
( ( Bisected ) dataBottom ) . setHalf ( Bisected . Half . BOTTOM ) ;
2021-08-01 08:10:07 +02:00
BlockData dataTop = p . plantMaterial ( ) . createBlockData ( ) ;
2019-09-20 01:21:43 +02:00
( ( Bisected ) dataTop ) . setHalf ( Bisected . Half . TOP ) ;
if ( bl . getRelative ( BlockFace . UP ) . getType ( ) . equals ( Material . AIR ) ) {
bl . setBlockData ( dataBottom , false ) ;
bl . getRelative ( BlockFace . UP ) . setBlockData ( dataTop , false ) ;
2019-10-13 02:09:38 +02:00
} else {
return false ; // No room
2019-09-20 01:21:43 +02:00
}
} else {
2019-10-12 18:31:51 +02:00
bl . setBlockData ( dataBottom , false ) ;
2019-09-20 01:21:43 +02:00
}
2019-07-08 00:45:47 +02:00
bl . getWorld ( ) . spawnParticle ( Particle . SNOWBALL , bl . getLocation ( ) , 10 , 2 , 2 , 2 ) ;
2019-01-22 00:44:01 +01:00
return true ;
2019-01-19 16:52:04 +01:00
}
2019-01-22 00:44:01 +01:00
return false ;
} ) . orElse ( false ) ;
2019-01-19 16:52:04 +01:00
}
/ * *
2019-01-26 17:38:13 +01:00
* @param friendlyName - set the friendly name
2019-01-19 16:52:04 +01:00
* /
public void setFriendlyName ( String friendlyName ) {
this . friendlyName = friendlyName ;
}
/ * *
2019-01-26 17:38:13 +01:00
* @param iceCoverage the ice coverage to set
2019-01-19 16:52:04 +01:00
* /
2019-01-26 17:38:13 +01:00
public void setIcecoverage ( int iceCoverage ) {
if ( iceCoverage = = 0 ) {
2020-01-30 18:52:53 +01:00
startupLog ( " No Ice Allowed " ) ;
2019-01-26 17:38:13 +01:00
} else if ( iceCoverage > 0 ) {
2020-01-30 18:52:53 +01:00
startupLog ( " Ice > " + iceCoverage + " % " ) ;
2019-01-19 16:52:04 +01:00
}
2019-01-26 17:38:13 +01:00
this . iceCoverage = iceCoverage ;
2019-01-19 16:52:04 +01:00
}
/ * *
* @param icon the icon to set
* /
public void setIcon ( Material icon ) {
this . icon = icon ;
}
/ * *
2019-01-26 17:38:13 +01:00
* @param lavaCoverage the lava coverage to set
2019-01-19 16:52:04 +01:00
* /
2019-01-26 17:38:13 +01:00
public void setLavacoverage ( int lavaCoverage ) {
if ( lavaCoverage = = 0 ) {
2020-01-30 18:52:53 +01:00
startupLog ( " No Lava Allowed " ) ;
2019-01-26 17:38:13 +01:00
} else if ( lavaCoverage > 0 ) {
2020-01-30 18:52:53 +01:00
startupLog ( " Lava > " + lavaCoverage + " % " ) ;
2019-01-19 16:52:04 +01:00
}
2019-01-26 17:38:13 +01:00
this . lavaCoverage = lavaCoverage ;
2019-01-19 16:52:04 +01:00
}
/ * *
* @param mobLimit the mobLimit to set
* /
public void setMobLimit ( int mobLimit ) {
this . mobLimit = mobLimit ;
}
/ * *
* @param name the name to set
* /
public void setName ( String name ) {
this . name = name ;
}
/ * *
* @param permission the permission to set
* /
public void setPermission ( String permission ) {
this . permission = permission ;
}
/ * *
* @param priority the priority to set
* /
public void setPriority ( int priority ) {
this . priority = priority ;
}
/ * *
* @param type the type to set
* /
public void setType ( Biome type ) {
this . type = type ;
}
/ * *
2019-01-26 17:38:13 +01:00
* @param waterCoverage the water coverage to set
2019-01-19 16:52:04 +01:00
* /
2019-01-26 17:38:13 +01:00
public void setWatercoverage ( int waterCoverage ) {
if ( waterCoverage = = 0 ) {
2020-01-30 18:52:53 +01:00
startupLog ( " No Water Allowed " ) ;
2019-01-26 17:38:13 +01:00
} else if ( waterCoverage > 0 ) {
2020-01-30 18:52:53 +01:00
startupLog ( " Water > " + waterCoverage + " % " ) ;
2019-01-19 16:52:04 +01:00
}
2019-01-26 17:38:13 +01:00
this . waterCoverage = waterCoverage ;
2019-01-19 16:52:04 +01:00
}
2019-01-22 00:44:01 +01:00
@Override
public int compareTo ( BiomeRecipe o ) {
return Integer . compare ( o . getPriority ( ) , this . getPriority ( ) ) ;
}
2019-11-01 05:36:05 +01:00
2019-01-25 04:11:59 +01:00
/ * *
* @return true if this recipe has no mobs that may spawn
* /
public boolean noMobs ( ) {
2019-11-01 05:36:05 +01:00
return mobTree . isEmpty ( ) ;
2019-01-25 04:11:59 +01:00
}
/ * *
* @return the mob types that may spawn due to this recipe
* /
public Set < EntityType > getMobTypes ( ) {
2021-08-01 08:10:07 +02:00
return mobTree . values ( ) . stream ( ) . map ( GreenhouseMob : : mobType ) . collect ( Collectors . toSet ( ) ) ;
2019-01-25 04:11:59 +01:00
}
2019-05-09 00:21:11 +02:00
2019-11-01 05:36:05 +01:00
2019-01-19 16:52:04 +01:00
}