WIP commit

This commit is contained in:
tastybento 2019-01-19 07:52:04 -08:00
parent 6dd86e9878
commit 075c9bcc78
32 changed files with 5856 additions and 2 deletions

114
README.md
View File

@ -1,2 +1,112 @@
# Greenhouses
BentoBox Add-on to enable personal biomes in a glass greenhouse
# Greenhouses - an add-on for BentoBox
Greenhouses is a BentoBox add-on to power-up your island world! It enables players to build their own biome greenhouses complete with weather, friendly mob spawning, unique plant growth, and even block erosion!
Greenhouses are made out of glass and must contain the blocks found in the Biome Recipe to be valid. There is a recipe GUI. Once built, the greenhouse can be used to grow plants with bonemeal, and it may spawn biome-specific mobs. If you include a hopper with water in it, snow will form inside the greenhouse when it rains. If you put bonemeal in the hopper, biome-specific plants will grow. Some blocks can also transform over time due to "erosion".
## Features
* Craft your own self-contained biome greenhouse on an island (or elsewhere if you like)
* Greenhouses can grow plants that cannot normally be grown, like sunflowers
* Friendly mobs can spawn if your greenhouse is well designed - need slimes? Build a swamp greenhouse!
* Blocks change in biomes - dirt becomes sand in a desert, dirt becomes clay in a river, for example.
* Greenhouses can run in multiple worlds.
* Easy to use GUI shows greenhouse recipes (/g)
* Admins can fully customize biomes and recipes
## How to Build A Greenhouse (Simple version)
1. Make glass blocks and build a rectangular set of walls with a flat roof.
2. Put a hopper in the wall or roof.
3. Put a door in the wall so you can get in and out.
4. Type /g and read the rules for the greenhouse you want.
5. Exit the GUI and place blocks, water, lava, and ice so that you make your desired biome.
6. Type /g again and click on the biome to make it.
### Once made:
* Use bonemeal to grow small plants on grass blocks immediately in the greenhouse.
* Or place bonemeal in the hopper to have the greenhouse sprinkle bonemeal automatically. Come back later to see what grows!
* Place a bucket of water (or more) in the hopper to cause snow to fall in cold biomes. Snow will fall when it rains in the world. Each snowfall empties one bucket of water.
* Friendly biome-specific mobs may spawn in your greenhouse - the usual rules apply (be more than 24 blocks away).
## FAQ
* Can I use stained glass? Yes, you can. It's pretty.
* Can I fill my greenhouse full of water? Yes. That's an ocean.
* Will a squid spawn there? Maybe... okay, yes it will if it's a big enough ocean.
* How do I place a door high up in the wall if the wall is all glass? Place it on a hopper.
* How do I place a door on a hopper? Crouch and then place it.
* Can I use metal doors? Yes.
* Can I use a trap door? Yes.
* Can I grow swamp flowers with this? Yes. Make a swamp biome and use bonemeal.
* How much bonemeal is used to grow plants? One per successful plant.
* How much water do I need to put into the hopper to make it snow? One bucket of water (just the water) is used up every time it rains. This only happens in cold biomes.
* Can I build a Nether greenhouse? Try it and see... (Actually, you may need permission)
* Can I build greenhouses in the Nether? Yes. You can colonize the nether with them.
* What kind of mobs spawn in the biomes? It's what you would expect, wolves in Cold Taiga, horses on plains, etc.
## Required Plugin
This version of Greenhouses is an add-on for BentoBox and will not run stand-alone!
1. BentoBox - make sure you use the latest version!
## Installation and Configuration
1. Download and install BentoBox if you haven't done so already
2. Download the add-on
3. Place into the BentoBox addon's folder
4. Restart your server
5. The addon will make a data folder called greenhouses. Open that folder.
6. Check **config.yml** and edit to be what you want, note the list of world names.
7. Configure the **biomes.yml** if you wish (advanced).
8. Type **/gadmin reload** in the game to reload the config or restart the server.
9. Done!
To make your first greenhouse, build a glass box and type **/g make** to see what kind of greenhouse you get. Type **/g** to see the recipes.
## Upgrading
Read the file release notes for changes and instructions on how to upgrade.
## Player Commands
* **/greenhouse** or **/g** can be used for short.
* **/greenhouse help** - lists these commands
* **/greenhouse make**: Tries to make a greenhouse by finding the first valid recipe
* **/greenhouse remove**: Removes a greenhouse that you are standing in if you are the owner
* **/greenhouse list**: Lists all the recipes available
* **/greenhouse recipe**: Displays the recipe GUI - clicking on a recipe will try to make a greenhouse
## Admin Commands
* **/gadmin reload** : Reloads config files
* **/gadmin info <player>**: provides info on the player
* **/gadmin info**: provides info on the greenhouse you are in
## Permissions
Permission to use specific biomes can be added in biomes.yml.
For example, the permission for the Nether (Hell) biome is **greenhouses.biome.nether** and is set here:
HELL:
permission: greenhouses.biome.nether
The permission can be anything you like, e.g., a rank permission, **myserver.VIP**.
### General permissions are:
greenhouses.player:
description: Gives access to player commands
default: true
greenhouses.admin:
description: Gives access to admin commands
default: op

205
pom.xml Normal file
View File

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>world.bentobox</groupId>
<artifactId>Greenhouses</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Greenhouses</name>
<description>Greenhouses is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like ASkyBlock or AcidIsland.</description>
<url>https://github.com/BentoBoxWorld/Greenhouses</url>
<inceptionYear>2019</inceptionYear>
<scm>
<connection>scm:git:https://github.com/BentoBoxWorld/Greenhouses.git</connection>
<developerConnection>scm:git:git@github.com:BentoBoxWorld/Greenhouses.git</developerConnection>
<url>https://github.com/BentoBoxWorld/Greenhouses</url>
</scm>
<ciManagement>
<system>jenkins</system>
<url>http://ci.codemc.org/job/BentoBoxWorld/job/Greenhouses</url>
</ciManagement>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/BentoBoxWorld/Greenhouses/issues</url>
</issueManagement>
<distributionManagement>
<snapshotRepository>
<id>codemc-snapshots</id>
<url>https://repo.codemc.org/repository/maven-snapshots</url>
</snapshotRepository>
<repository>
<id>codemc-releases</id>
<url>https://repo.codemc.org/repository/maven-releases</url>
</repository>
</distributionManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<powermock.version>1.7.4</powermock.version>
</properties>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>world.bentobox</groupId>
<artifactId>bentobox</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<defaultGoal>clean package</defaultGoal>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources/locales</directory>
<targetPath>./locales</targetPath>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.1</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>sonar</id>
<properties>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.organization>bentobox-world</sonar.organization>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>5.1</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,193 @@
package world.bentobox.greenhouses;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.ui.Locale;
/**
* @author tastybento
* Provides a memory cache of online player information
* This is the one-stop-shop of player info
*/
public class PlayerCache {
private HashMap<UUID, Players> playerCache = new HashMap<UUID, Players>();
private final Greenhouses plugin;
public PlayerCache(Greenhouses plugin) {
this.plugin = plugin;
playerCache.clear();
// Add any players currently online (handles the /reload condition)
final Collection<? extends Player> serverPlayers = plugin.getServer().getOnlinePlayers();
for (Player p : serverPlayers) {
// Add this player to the online cache
playerCache.put(p.getUniqueId(), new Players(p));
}
}
/**
* Add a player to the cache when they join the server (called in JoinLeaveEvents)
* @param player
*/
public void addPlayer(Player player) {
if (!playerCache.containsKey(player.getUniqueId())) {
playerCache.put(player.getUniqueId(),new Players(player));
}
// Check permission limits on number of greenhouses
int limit = plugin.getMaxGreenhouses(player); // 0 = none allowed. Positive numbers = limit. Negative = unlimited
/*
if (plugin.getPlayerGHouse(player.getUniqueId()) == null) {
return;
}
*/
List<Greenhouse> toBeRemoved = new ArrayList<Greenhouse>();
// Look at how many greenhouses player has and remove any over their limit
int owned = 0;
for (Greenhouse g: plugin.getGreenhouses()) {
if (g.getOwner().equals(player.getUniqueId())) {
owned++;
if (owned <= limit) {
// Allowed
playerCache.get(player.getUniqueId()).incrementGreenhouses();
g.setPlayerName(player.getName());
} else {
// Over the limit
toBeRemoved.add(g);
}
}
}
if (Settings.deleteExtras && limit >= 0) {
// Remove greenhouses
for (Greenhouse g : toBeRemoved) {
plugin.removeGreenhouse(g);
plugin.logger(2,"Removed greenhouse over the limit for " + player.getName());
}
if (toBeRemoved.size() > 0) {
if (limit == 0) {
player.sendMessage(ChatColor.RED + Locale.limitsnoneallowed.replace("[number]",String.valueOf(toBeRemoved.size())));
} else {
player.sendMessage(ChatColor.RED + Locale.limitslimitedto.replace("[limit]", String.valueOf(limit)).replace("[number]",String.valueOf(toBeRemoved.size())));
}
}
}
}
public void removeOnlinePlayer(Player player) {
if (playerCache.containsKey(player.getUniqueId())) {
playerCache.remove(player);
plugin.logger(3,"Removing player from cache: " + player);
}
}
/**
* Removes all players on the server now from cache and saves their info
*/
public void removeAllPlayers() {
playerCache.clear();
}
/*
* Player info query methods
*/
/*
public void setInGreenhouse(Player player, Greenhouse inGreenhouse) {
if (playerCache.containsKey(player.getUniqueId())) {
playerCache.get(player.getUniqueId()).setInGreenhouse(inGreenhouse);
}
}
*/
/**
* @param playerUUID
* @return the greenhouse the player is in or null if no greenhouse
*/
public Greenhouse getInGreenhouse(Player player) {
for (Greenhouse g : plugin.getGreenhouses()) {
if (g.insideGreenhouse(player.getLocation())) {
return g;
}
}
return null;
}
/**
* Increments the player's greenhouse count if permissions allow
* @param player
* @return true if successful, otherwise false
*/
public boolean incGreenhouseCount(Player player) {
// Do a permission check if there are limits
// Check permission limits on number of greenhouses
int limit = plugin.getMaxGreenhouses(player); // 0 = none allowed. Positive numbers = limit. Negative = unlimited
if (limit < 0 || playerCache.get(player.getUniqueId()).getNumberOfGreenhouses() < limit) {
playerCache.get(player.getUniqueId()).incrementGreenhouses();
return true;
}
// At the limit, sorry
return false;
}
/**
* Decrements the number of greenhouses this player has
* @param player
*/
public void decGreenhouseCount(Player player) {
playerCache.get(player.getUniqueId()).decrementGreenhouses();
}
/**
* Decrements by UUID
* @param playerUUID
*/
public void decGreenhouseCount(UUID playerUUID) {
if (playerCache.containsKey(playerUUID)) {
playerCache.get(playerUUID).decrementGreenhouses();
}
}
/**
* Returns true if the player is at their permitted limit of greenhouses otherwise false
* @param player
* @return
*/
public boolean isAtLimit(Player player) {
if (getRemainingGreenhouses(player) == 0) {
return true;
}
return false;
}
/**
* Returns how many greenhouses the player is allowed to make
* @param player
* @return
*/
public int getRemainingGreenhouses(Player player) {
int limit = plugin.getMaxGreenhouses(player);
if (limit < 0) {
return -1;
}
int size = 0;
if (plugin.getPlayerhouses().containsKey(player.getUniqueId())) {
size = plugin.getPlayerhouses().get(player.getUniqueId()).size();
}
int remaining = limit - size;
if (remaining < 0) {
return 0;
} else {
return remaining;
}
}
}

View File

@ -0,0 +1,70 @@
package world.bentobox.greenhouses;
import java.util.UUID;
import org.bukkit.entity.Player;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
/**
* Tracks the following info on the player
* UUID, player name, whether they are in a greenhouse or not and how many greenhouses they have
*/
public class Players {
private UUID uuid;
private Greenhouse inGreenhouse;
private int numberOfGreenhouses;
/**
* @param uuid
* Constructor - initializes the state variables
*
*/
public Players(final Player player) {
this.uuid = player.getUniqueId();
// We do not know if the player is in a greenhouse or not yet
this.inGreenhouse = null;
// We start with the assumption they have no greenhouses yet
this.numberOfGreenhouses = 0;
}
/**
* @return the inGreenhouse
*/
public Greenhouse getInGreenhouse() {
return inGreenhouse;
}
/**
* @param inGreenhouse the inGreenhouse to set
*/
public void setInGreenhouse(Greenhouse inGreenhouse) {
this.inGreenhouse = inGreenhouse;
}
/**
* @return the numberOfGreenhouses
*/
public int getNumberOfGreenhouses() {
return numberOfGreenhouses;
}
public void incrementGreenhouses() {
numberOfGreenhouses++;
}
public void decrementGreenhouses() {
numberOfGreenhouses--;
if (numberOfGreenhouses < 0) {
numberOfGreenhouses = 0;
}
}
/**
* @return the uuid
*/
public UUID getUuid() {
return uuid;
}
}

View File

@ -0,0 +1,25 @@
package world.bentobox.greenhouses;
import java.util.List;
/**
* @author ben
* Where all the settings are
*/
public class Settings {
// General
public static List<String> worldName;
public static double snowChanceGlobal;
public static double snowDensity;
public static long snowSpeed;
public static int plantTick;
public static int iceInfluence;
public static int blockTick;
public static int mobTick;
public static int ecoTick;
public static boolean allowFlowIn;
public static boolean allowFlowOut;
public static boolean deleteExtras;
public static int maxGreenhouses;
}

View File

@ -0,0 +1,434 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.TreeMap;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import world.bentobox.bentobox.util.Util;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.ui.Locale;
public class BiomeRecipe {
private Greenhouses plugin;
private Biome type;
private Material icon; // Biome icon for control panel
private int priority;
private String name;
private String friendlyName;
private final List<BlockFace> ADJ_BLOCKS = Arrays.asList( BlockFace.DOWN, BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.WEST);
// Content requirements
// Material, Type, Qty. There can be more than one type of material required
private Map<Material, Integer> requiredBlocks = new HashMap<>();
// Plants
private TreeMap<Double, GreenhousePlant> plantTree = new TreeMap<>();
// Mobs
// Entity Type, Material to Spawn on, Probability
private TreeMap<Double, GreenhouseMob> mobTree = new TreeMap<>();
// Conversions
// Original Material, Original Type, New Material, New Type, Probability
private Map<Material, GreenhouseBlockConversions> conversionBlocks = new HashMap<>();
private int mobLimit;
private int waterCoverage;
private int iceCoverage;
private int lavaCoverage;
private String permission = "";
private Random random = new Random();
/**
* @param type
* @param priority
*/
public BiomeRecipe(Greenhouses plugin, Biome type, int priority) {
this.plugin = plugin;
this.type = type;
this.priority = priority;
plugin.logger(3,"" + type.toString() + " priority " + priority);
mobLimit = 9; // Default
}
/**
* @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));
plugin.logger(1," " + convChance + "% chance for " + Util.prettifyText(oldMaterial.toString()) + " to convert to " + Util.prettifyText(newMaterial.toString()));
}
/**
* @param mobType
* @param mobProbability
* @param mobSpawnOn
*/
public void addMobs(EntityType mobType, int mobProbability, Material mobSpawnOn) {
plugin.logger(1," " + mobProbability + "% chance for " + Util.prettifyText(mobType.toString()) + " to spawn on " + Util.prettifyText(mobSpawnOn.toString())+ ".");
double probability = ((double)mobProbability/100);
// Add up all the probabilities in the list so far
if ((1D - mobTree.lastKey()) >= probability) {
// Add to probability tree
mobTree.put(mobTree.lastKey() + probability, new GreenhouseMob(mobType, mobSpawnOn));
} else {
plugin.logError("Mob chances add up to > 100% in " + type.toString() + " biome recipe! Skipping " + mobType.toString());
}
}
/**
* 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
*/
public void addPlants(Material plantMaterial, int plantProbability, Material plantGrowOn) {
double probability = ((double)plantProbability/100);
// Add up all the probabilities in the list so far
if ((1D - plantTree.lastKey()) >= probability) {
// Add to probability tree
plantTree.put(plantTree.lastKey() + probability, new GreenhousePlant(plantMaterial, plantGrowOn));
} else {
plugin.logError("Plant chances add up to > 100% in " + type.toString() + " biome recipe! Skipping " + plantMaterial.toString());
}
plugin.logger(1," " + plantProbability + "% chance for " + Util.prettifyText(plantMaterial.toString()) + " to grow on " + Util.prettifyText(plantGrowOn.toString()));
}
/**
* @param blockMaterial
* @param blockQty
*/
public void addReqBlocks(Material blockMaterial, int blockQty) {
requiredBlocks.put(blockMaterial, blockQty);
plugin.logger(1," " + blockMaterial + " x " + blockQty);
}
// Check required blocks
/**
* Checks greenhouse meets recipe requirements. If player is not null, a explanation of
* any failures will be provided.
* @param pos1
* @param pos2
* @param player
* @return true if a cube defined by pos1 and pos2 meet this biome recipe.
*/
public boolean checkRecipe(Location pos1, Location pos2, Player player) {
plugin.logger(3,"Checking for biome " + type.toString());
long area = (pos2.getBlockX()-pos1.getBlockX()-1) * (pos2.getBlockZ()-pos1.getBlockZ()-1);
plugin.logger(3,"area =" + area);
plugin.logger(3,"Pos1 = " + pos1.toString());
plugin.logger(3,"Pos1 = " + pos2.toString());
boolean pass = true;
Map<Material, Integer> blockCount = new HashMap<>();
// Look through the greenhouse and count what is in there
for (int y = pos1.getBlockY(); y<pos2.getBlockY();y++) {
for (int x = pos1.getBlockX()+1;x<pos2.getBlockX();x++) {
for (int z = pos1.getBlockZ()+1;z<pos2.getBlockZ();z++) {
Block b = pos1.getWorld().getBlockAt(x, y, z);
if (!b.getType().equals(Material.AIR)) {
blockCount.putIfAbsent(b.getType(), 0);
blockCount.merge(b.getType(), 1, Integer::sum);
}
}
}
}
// 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;
plugin.logger(3,"water req=" + waterCoverage + " lava req=" + lavaCoverage + " ice req="+iceCoverage);
plugin.logger(3,"waterRatio=" + waterRatio + " lavaRatio=" + lavaRatio + " iceRatio="+iceRatio);
// Check required ratios - a zero means none of these are allowed, e.g.desert has no water
if (waterCoverage == 0 && waterRatio > 0) {
if (player != null) {
player.sendMessage(ChatColor.RED + Locale.recipenowater);
}
pass=false;
}
if (lavaCoverage == 0 && lavaRatio > 0) {
if (player != null) {
player.sendMessage(ChatColor.RED + Locale.recipenolava);
}
pass=false;
}
if (iceCoverage == 0 && iceRatio > 0) {
if (player != null) {
player.sendMessage(ChatColor.RED + Locale.recipenoice);
}
pass=false;
}
if (waterCoverage > 0 && waterRatio < waterCoverage) {
if (player != null) {
player.sendMessage(ChatColor.RED + Locale.recipewatermustbe.replace("[coverage]", String.valueOf(waterCoverage)));
}
pass=false;
}
if (lavaCoverage > 0 && lavaRatio < lavaCoverage) {
if (player != null) {
player.sendMessage(ChatColor.RED + Locale.recipelavamustbe.replace("[coverage]", String.valueOf(lavaCoverage)));
}
pass=false;
}
if (iceCoverage > 0 && iceRatio < iceCoverage) {
if (player != null) {
player.sendMessage(ChatColor.RED + Locale.recipeicemustbe.replace("[coverage]", String.valueOf(iceCoverage)));
}
pass=false;
}
// Compare to the required blocks
Map<Material, Integer> missingBlocks = requiredBlocks.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue() - blockCount.getOrDefault(e.getKey(), 0)));
// Remove any entries that are 0 or less
missingBlocks.values().removeIf(v -> v <= 0);
if (!missingBlocks.isEmpty()) {
pass = false;
}
missingBlocks.forEach((k,v) -> player.sendMessage(ChatColor.RED + Locale.recipemissing + " " + Util.prettifyText(k.toString()) + " x " + v));
return pass;
}
/**
* @param b
*/
public void convertBlock(Block b) {
plugin.logger(3,"try to convert block");
GreenhouseBlockConversions bc = conversionBlocks.get(b.getType());
if (bc == null || random.nextDouble() > bc.getProbability()) {
return;
}
// Check if the block is in the right area, up, down, n,s,e,w
if (ADJ_BLOCKS.stream().map(b::getRelative).map(Block::getType).anyMatch(m -> bc.getLocalMaterial() == null || m == bc.getLocalMaterial())) {
// Convert!
plugin.logger(3,"Convert block");
b.setType(bc.getNewMaterial());
}
}
/**
* @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
*/
public int getPriority() {
return priority;
}
/**
* @return a mob that can spawn in the greenhouse
*/
public Optional<GreenhouseMob> getRandomMob() {
// 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
Double key = plantTree.ceilingKey(random.nextDouble());
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.
* @param bl
* @return
*/
public void growPlant(Block bl) {
if (bl.getType() != Material.AIR) {
return;
}
getRandomPlant().ifPresent(p -> {
if (bl.getY() != 0 && p.getPlantGrownOn().map(m -> m.equals(bl.getRelative(BlockFace.DOWN).getType())).orElse(true)) {
bl.setType(p.getPlantMaterial());
}
});
}
/**
* @param set the friendly name
*/
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
/**
* @param icecoverage the icecoverage to set
*/
public void setIcecoverage(int icecoverage) {
if (icecoverage == 0) {
plugin.logger(1," No Ice Allowed");
} else if (icecoverage > 0) {
plugin.logger(1," Ice > " + icecoverage + "%");
}
this.iceCoverage = icecoverage;
}
/**
* @param icon the icon to set
*/
public void setIcon(Material icon) {
this.icon = icon;
}
/**
* @param lavaCoverage the lavaCoverage to set
*/
public void setLavacoverage(int lavacoverage) {
if (lavacoverage == 0) {
plugin.logger(1," No Lava Allowed");
} else if (lavacoverage > 0) {
plugin.logger(1," Lava > " + lavacoverage + "%");
}
this.lavaCoverage = lavacoverage;
}
/**
* @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;
}
/**
* @param waterCoverage the waterCoverage to set
*/
public void setWatercoverage(int watercoverage) {
if (watercoverage == 0) {
plugin.logger(1," No Water Allowed");
} else if (watercoverage > 0) {
plugin.logger(1," Water > " + watercoverage + "%");
}
this.waterCoverage = watercoverage;
}
}

View File

@ -0,0 +1,144 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.Hopper;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.weather.WeatherChangeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.Settings;
/**
* Monitors the greenhouses and grows things, adds weather etc.
* @author ben
*
*/
public class Ecosystem implements Listener {
private final Greenhouses addon;
private final static List<Biome> SNOWBIOMES = Arrays.stream(Biome.values()).filter(b -> b.name().contains("COLD") || b.name().contains("ICE") || b.name().contains("FROZEN")).collect(Collectors.toList());
private BukkitTask snow;
private List<Greenhouse> snowGlobes = new ArrayList<Greenhouse>();
public Ecosystem(final Greenhouses plugin) {
this.addon = plugin;
}
@EventHandler
public void onWeatherChangeEvent(final WeatherChangeEvent e) {
if (!Settings.worldName.contains(e.getWorld().getName())) {
return;
}
if (e.toWeatherState()) {
// It's raining
addon.logger(3,"It's raining!");
startSnow();
} else {
// It's stopped raining!
addon.logger(3,"Stopped raining!");
if (snow != null)
snow.cancel();
}
}
private void startSnow() {
if (snow != null) {
// Cancel the old snow task
snow.cancel();
}
// Spin off scheduler
snowGlobes.clear();
snow = addon.getServer().getScheduler().runTaskTimer(addon.getPlugin(), () -> {
// Run through each greenhouse - only bother with snow biomes
addon.logger(3,"started scheduler");
// Check all the greenhouses and their hoppers and build a list of snow greenhouses that exist now
List<Greenhouse> toBeRemoved = new ArrayList<Greenhouse>();
for (Greenhouse g : addon.getGreenhouses()) {
addon.logger(3,"Testing greenhouse biome : " + g.getBiome().toString());
if (SNOWBIOMES.contains(g.getBiome())) {
addon.logger(3,"Snow biome found!");
// If it is already on the list, just snow, otherwise check if the hopper has water
if (!snowGlobes.contains(g)) {
Location hopper = g.getRoofHopperLocation();
if (hopper != null) {
addon.logger(3,"Hopper location:" + hopper.toString());
Block b = hopper.getBlock();
// Check the hopper is still there
if (b.getType().equals(Material.HOPPER)) {
Hopper h = (Hopper)b.getState();
addon.logger(3,"Hopper found!");
// Check what is in the hopper
if (h.getInventory().contains(Material.WATER_BUCKET)) {
// Remove the water in the bucket
// We cannot remove an itemstack the easy way because on acid island the bucket is changed to acid
for (ItemStack item : h.getInventory().getContents()) {
if (item != null && item.getType().equals(Material.WATER_BUCKET)) {
// Remove one from this item stack
// Water buckets in theory do no stack...
ItemStack i = item.clone();
i.setAmount(1);
h.getInventory().removeItem(i);
h.getInventory().addItem(new ItemStack(Material.BUCKET));
break;
}
}
// Add to list
snowGlobes.add(g);
}
} else {
// Greenhouse is broken or no longer has a hopper when it should
addon.getLogger().warning("Hopper missing from greenhouse at " + g.getRoofHopperLocation().getBlockX() + " "
+ g.getRoofHopperLocation().getBlockY() + " " + g.getRoofHopperLocation().getBlockZ());
addon.getLogger().warning("Removing greenhouse");
toBeRemoved.add(g);
}
}
}
}
}
if (!snowGlobes.isEmpty()) {
snowOn(snowGlobes);
}
// Remove any greenhouses that need it
for (Greenhouse g : toBeRemoved) {
//UUID owner = g.getOwner();
addon.removeGreenhouse(g);
//plugin.players.save(owner);
}
addon.saveGreenhouses();
}, 0L, (Settings.snowSpeed * 20L)); // Every 30 seconds
}
protected void snowOn(List<Greenhouse> snowGlobes) {
for (Greenhouse g : snowGlobes) {
addon.logger(3,"snowing in a greenhouse");
// Chance of snow
if (Math.random()>Settings.snowChanceGlobal)
return;
g.snow();
}
}
/**
* Removes any greenhouses that are currently in the eco system
* @param g
*/
public void remove(Greenhouse g) {
if (snowGlobes.contains(g))
snowGlobes.remove(g);
}
}

View File

@ -0,0 +1,606 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Hopper;
import org.bukkit.block.data.type.Snow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.Settings;
/**
* Defines a greenhouse
* @author tastybento
*
*/
public class Greenhouse {
private Greenhouses plugin;
private final Location pos1;
private final Location pos2;
private final World world;
private UUID owner;
private String playerName;
private HashMap<String,Object> flags = new HashMap<String,Object>();
private Biome originalBiome;
private Biome greenhouseBiome;
private Location roofHopperLocation;
private int area;
private int heightY;
private int height;
private int groundY;
private BiomeRecipe biomeRecipe;
public Greenhouse(Greenhouses plugin, Location pos1, Location pos2, UUID owner) {
this.plugin = plugin;
this.pos1 = pos1;
this.pos2 = pos2;
int minx = Math.min(pos1.getBlockX(), pos2.getBlockX());
int maxx = Math.max(pos1.getBlockX(), pos2.getBlockX());
int minz = Math.min(pos1.getBlockZ(), pos2.getBlockZ());
int maxz = Math.max(pos1.getBlockZ(), pos2.getBlockZ());
this.area = (maxx-minx - 1) * (maxz-minz -1);
this.heightY = Math.max(pos1.getBlockY(), pos2.getBlockY()); // Should always be pos2 is higher, but just in case
this.groundY = Math.min(pos1.getBlockY(), pos2.getBlockY());
this.height = heightY - groundY;
this.world = pos1.getWorld();
if (pos1.getWorld() == null || pos2.getWorld() == null) {
plugin.getLogger().severe("This greenhouse's world does not exist!");
} else {
if (!pos1.getWorld().equals(pos2.getWorld())) {
plugin.getLogger().severe("Pos 1 and Pos 2 are not in the same world!");
}
}
this.originalBiome = pos1.getBlock().getBiome();
this.greenhouseBiome = pos2.getBlock().getBiome();
this.owner = owner;
this.playerName = "";
flags.put("enterMessage", "");
flags.put("farewellMessage", "");
}
/**
* @return the originalBiome
*/
public Biome getOriginalBiome() {
return originalBiome;
}
/**
* @return the greenhouseBiome
*/
public Biome getBiome() {
return greenhouseBiome;
}
/**
* @param winner.getType() the greenhouseBiome to set
*/
public void setBiomeRecipe(BiomeRecipe winner) {
this.greenhouseBiome = winner.getBiome();
this.biomeRecipe = winner;
}
/**
* @return the greenhouse's biome recipe
*/
public BiomeRecipe getBiomeRecipe() {
return biomeRecipe;
}
public void setBiome(Biome greenhouseBiome2) {
this.greenhouseBiome = greenhouseBiome2;
}
public boolean insideGreenhouse(Location loc) {
if (loc.getWorld().equals(world)) {
plugin.logger(4,"Checking intersection");
Vector v = loc.toVector();
plugin.logger(4,"Pos 1 = " + pos1.toString());
plugin.logger(4,"Pos 2 = " + pos2.toString());
plugin.logger(4,"V = " + v.toString());
boolean i = v.isInAABB(Vector.getMinimum(pos1.toVector(), pos2.toVector()), Vector.getMaximum(pos1.toVector(), pos2.toVector()));
return i;
}
return false;
}
/**
* Check to see if a location is above a greenhouse
* @param loc
* @return
*/
public boolean aboveGreenhouse(Location loc) {
if (loc.getWorld().equals(world)) {
Vector v = loc.toVector();
Vector p1 = new Vector(pos1.getBlockX(),heightY,pos1.getBlockZ());
Vector p2 = new Vector(pos2.getBlockX(),world.getMaxHeight(),pos2.getBlockZ());
boolean i = v.isInAABB(Vector.getMinimum(p1, p2), Vector.getMaximum(p1, p2));
return i;
}
return false;
}
/**
* Returns true if this location is in a greenhouse wall
* @param loc
* @return
*/
public boolean isAWall(Location loc) {
plugin.logger(3,"wall check");
if (loc.getBlockX() == pos1.getBlockX() || loc.getBlockX() == pos2.getBlockX()
|| loc.getBlockZ() == pos1.getBlockZ() || loc.getBlockZ() == pos2.getBlockZ()) {
return true;
}
return false;
}
/**
* @return the pos1
*/
public Location getPos1() {
return new Location (world, pos1.getBlockX(), pos1.getBlockY(), pos1.getBlockZ());
}
/**
* @return the pos2
*/
public Location getPos2() {
return new Location (world, pos2.getBlockX(), pos2.getBlockY(), pos2.getBlockZ());
}
/**
* @return the owner
*/
public UUID getOwner() {
return owner;
}
/**
* @return the flags
*/
public HashMap<String, Object> getFlags() {
return flags;
}
/**
* @param flags the flags to set
*/
public void setFlags(HashMap<String, Object> flags) {
this.flags = flags;
}
/**
* @param owner the owner to set
*/
public void setOwner(UUID owner) {
this.owner = owner;
}
/**
* @return the playerName
*/
public String getPlayerName() {
return playerName;
}
/**
* @param playerName the playerName to set
*/
public void setPlayerName(String playerName) {
//plugin.getLogger().info("DEBUG: setting name to " + playerName);
this.playerName = playerName;
}
/**
* @return the enterMessage
*/
public String getEnterMessage() {
return (String)flags.get("enterMessage");
}
/**
* @return the farewallMessage
*/
public String getFarewellMessage() {
return (String)flags.get("farewellMessage");
}
/**
* @param enterMessage the enterMessage to set
*/
public void setEnterMessage(String enterMessage) {
flags.put("enterMessage",enterMessage);
}
/**
* @param farewallMessage the farewallMessage to set
*/
public void setFarewellMessage(String farewellMessage) {
flags.put("farewellMessage",farewellMessage);
}
public void setOriginalBiome(Biome originalBiome) {
this.originalBiome = originalBiome;
}
public void setRoofHopperLocation(Location roofHopperLoc) {
this.roofHopperLocation = roofHopperLoc;
}
/**
* @return the world
*/
public World getWorld() {
return world;
}
public Location getRoofHopperLocation() {
return roofHopperLocation;
}
/**
* @return the area
*/
public int getArea() {
return area;
}
/**
* @return the heightY
*/
public int getHeightY() {
return heightY;
}
/**
* @return the height
*/
public int getHeight() {
return height;
}
/**
* Reruns the recipe check to see if this greenhouse is still viable
* @return true if okay, otherwise false
*/
public boolean checkEco() {
plugin.logger(3,"Checking the ecology of the greenhouse.");
if (biomeRecipe != null) {
return this.biomeRecipe.checkRecipe(getPos1(), getPos2(), null);
} else {
plugin.logger(3,"BiomeRecipe is null! ");
plugin.getLogger().warning("[Greenhouse info]");
plugin.getLogger().warning("Owner: " + getOwner());
plugin.getLogger().warning("Location :" + getPos1().toString() + " to " + getPos2().toString());
return false;
}
}
/**
* Starts the biome in the greenhouse
* @param teleport - if true will teleport the player away and back to force the biome to change
*/
public void startBiome(boolean teleport) {
setBiomeBlocks(greenhouseBiome, teleport);
}
/**
* Reverts the biome of the greenhouse to the original unless someone is in this greenhouse
* @param to
*/
public void endBiome() {
setBiomeBlocks(originalBiome, false);
}
/**
* Actually set blocks to a biome
* The chunk refresh command has been deprecated and no longer works on 1.8+
* so jumping through hoops to refresh mobs is no longer needed
* If teleport is true, this biome starting is happening during a teleport
* sequence, i.e, gh is being generated or removed
* @param biome
* @param teleport
*/
private void setBiomeBlocks(Biome biome, boolean teleport) {
if (biome == null) {
return;
}
plugin.logger(2,"Biome seting to " + biome.toString());
Set<Pair<Integer, Integer>> chunkCoords = new HashSet<>();
final Set<Chunk> chunks = new HashSet<Chunk>();
for (int x = pos1.getBlockX();x<pos2.getBlockX();x++) {
for (int z = pos1.getBlockZ();z<pos2.getBlockZ();z++) {
Block b = world.getBlockAt(x, groundY, z);
b.setBiome(biome);
if (teleport) {
chunks.add(b.getChunk());
}
if (plugin.getServer().getVersion().contains("(MC: 1.7")) {
chunkCoords.add(new Pair<Integer, Integer>(b.getChunk().getX(), b.getChunk().getZ()));
}
}
}
}
/**
* Spawns friendly mobs according to the type of biome
*/
public void populateGreenhouse() {
if (biomeRecipe == null) {
return;
}
plugin.logger(3,"populating mobs in greenhouse");
// Make sure no players are around
/*
if (plugin.players.getNumberInGreenhouse(this) > 0)
return;
*/
// Quick check - see if any animal is going to spawn
EntityType mob = biomeRecipe.getRandomMob();
if (mob == null) {
return;
}
plugin.logger(3,"Mob ready to spawn in location " + pos1.getBlockX() + "," + pos2.getBlockZ() + " in world " + world.getName());
// Load greenhouse chunks
int numberOfMobs = 0;
Set<Pair> chunkSet = new HashSet<Pair>();
for (int x = (pos1.getBlockX()-15); x < (pos2.getBlockX()+15); x += 16) {
for (int z = (pos1.getBlockZ()-15); z < (pos2.getBlockZ()+15); z += 16) {
Chunk chunk = world.getChunkAt(x/16, z/16);
chunkSet.add(new Pair(x/16,z/16));
chunk.load();
plugin.logger(3, "Chunk = " + (x/16) + "," + (z/16) + " number of entities = " + chunk.getEntities().length);
for (Entity entity : chunk.getEntities()) {
plugin.logger(3,entity.getType().toString());
if (mob.equals(entity.getType())) {
numberOfMobs++;
}
}
}
}
plugin.logger(3,"Mobs in area = " + numberOfMobs);
plugin.logger(3,"Area of greenhouse = " + area);
if (area - (numberOfMobs * biomeRecipe.getMobLimit()) <= 0) {
plugin.logger(3,"Too many mobs already in this greenhouse");
for (Pair pair: chunkSet) {
world.unloadChunkRequest(pair.getLeft(), pair.getRight());
}
return;
}
Material type = biomeRecipe.getMobSpawnOn(mob);
int minx = Math.min(pos1.getBlockX(), pos2.getBlockX());
int maxx = Math.max(pos1.getBlockX(), pos2.getBlockX());
int minz = Math.min(pos1.getBlockZ(), pos2.getBlockZ());
int maxz = Math.max(pos1.getBlockZ(), pos2.getBlockZ());
// Try 10 times
for (int i = 0; i<10; i++) {
int x = Greenhouses.randInt(minx,maxx);
int z = Greenhouses.randInt(minz,maxz);
Block h = getHighestBlockInGreenhouse(x,z);
Block b = h.getRelative(BlockFace.DOWN);
Block a = h.getRelative(BlockFace.UP);
plugin.logger(3,"block found " + h.getType().toString());
plugin.logger(3,"below found " + b.getType().toString());
plugin.logger(3,"above found " + a.getType().toString());
if ((b.getType().equals(type) && h.getType().equals(Material.AIR))
|| (h.getType().equals(type) && a.getType().equals(Material.AIR)) ) {
Location midBlock = new Location(world, h.getLocation().getX()+0.5D, h.getLocation().getY(), h.getLocation().getZ()+0.5D);
Entity e = world.spawnEntity(midBlock, mob);
if (e != null)
plugin.logger(1,"Spawned a "+ Util.prettifyText(mob.toString()) + " on "+ Util.prettifyText(type.toString()) + " at "
+ midBlock.getBlockX() + "," + midBlock.getBlockY() + "," + midBlock.getBlockZ());
break;
}
}
for (Pair pair: chunkSet) {
world.unloadChunkRequest(pair.getLeft(), pair.getRight());
}
}
/**
* Lay down snow in the greenhouse
*/
public void snow() {
// Lay down snow and ice
List<Block> waterToIceBlocks = new ArrayList<Block>();
long water = 0;
int minx = Math.min(pos1.getBlockX(), pos2.getBlockX());
int maxx = Math.max(pos1.getBlockX(), pos2.getBlockX());
int minz = Math.min(pos1.getBlockZ(), pos2.getBlockZ());
int maxz = Math.max(pos1.getBlockZ(), pos2.getBlockZ());
for (int x = minx+1; x < maxx; x++) {
for (int z = minz+1; z < maxz;z++) {
Block b = getHighestBlockInGreenhouse(x,z);
// Display snow particles in air above b and count water blocks
for (int y = pos1.getBlockY(); y < heightY; y++) {
Block airCheck = world.getBlockAt(x, y, z);
if (airCheck.getType().equals(Material.AIR)) {
//).display(0F,0F,0F, 0.1F, 5,
//ParticleEffects.SNOWBALL.send(Bukkit.getOnlinePlayers(),airCheck.getLocation(),0D,0D,0D,1F,5,20);
world.spawnParticle(Particle.SNOWBALL, airCheck.getLocation(), 5);
} else if (airCheck.getType().equals(Material.WATER)) {
water++;
}
}
Block belowB = b.getRelative(BlockFace.DOWN);
if (Math.random()<Settings.snowDensity) {
if (belowB.getType().equals(Material.WATER)) {
// If the recipe requires a certain amount of water, then we need to wait until later to make ice
if (biomeRecipe.getWaterCoverage() > 0) {
waterToIceBlocks.add(belowB);
} else {
belowB.setType(Material.ICE);
}
} else if (belowB.getType().equals(Material.SNOW)) {
Snow snow = (Snow)belowB.getBlockData();
// Increment snow layers
snow.setLayers(Math.min(snow.getLayers() + 1, snow.getMaximumLayers()));
} else if (b.getType().equals(Material.AIR)) {
// Don't put snow on liquids or snow...
if (!belowB.isLiquid() && !belowB.getType().equals(Material.SNOW))
b.setType(Material.SNOW);
}
}
}
}
plugin.logger(3,"water = " + water);
if (biomeRecipe.getWaterCoverage() > 0 && water >0) {
plugin.logger(3,"water coverage required = " + biomeRecipe.getWaterCoverage());
// Check if ice can be made
for (Block toIce: waterToIceBlocks) {
plugin.logger(3,"water ratio = " + ((double)(water-1)/(double)area * 100));
if (((double)(water-1)/(double)area * 100) > biomeRecipe.getWaterCoverage()) {
toIce.setType(Material.ICE);
water--;
} else {
plugin.logger(3,"no more ice allowed");
break;
}
}
}
}
public void growFlowers() {
if (biomeRecipe == null) {
return;
}
Location hopper = roofHopperLocation;
if (hopper != null) {
plugin.logger(3,"Hopper location:" + hopper.toString());
Block b = hopper.getBlock();
// Check the hopper is still there
if (b.getType().equals(Material.HOPPER)) {
Hopper h = (Hopper)b.getState();
plugin.logger(3,"Hopper found!");
// Check what is in the hopper
if (h.getInventory().contains(Material.BONE_MEAL)) {
int total = h.getInventory().all(Material.BONE_MEAL).values().stream().mapToInt(ItemStack::getAmount).sum();
// We need one bonemeal for each flower made
if (total > 0) {
/*
ItemStack remBoneMeal = new ItemStack(Material.INK_SACK);
remBoneMeal.setDurability((short)15);
remBoneMeal.setAmount(1);
*/
// Rewrite to use on bonemeal per flower
plugin.logger(3,"Bonemeal found! Amount = " + total);
// Now go and grow stuff with the set probability
int minx = Math.min(pos1.getBlockX(), pos2.getBlockX());
int maxx = Math.max(pos1.getBlockX(), pos2.getBlockX());
int minz = Math.min(pos1.getBlockZ(), pos2.getBlockZ());
int maxz = Math.max(pos1.getBlockZ(), pos2.getBlockZ());
for (int x = minx+1; x < maxx; x++) {
for (int z = minz+1; z < maxz;z++) {
Block bl = getHighestBlockInGreenhouse(x,z);
//if (Math.random()<Settings.flowerChance) {
plugin.logger(3,"Block is " + bl.getRelative(BlockFace.DOWN).getType().toString());
if (total > 0 && biomeRecipe.growPlant(bl)) {
total --;
plugin.logger(3,"Grew plant, spraying bonemeal");
// Spray the bonemeal
for (int y = bl.getLocation().getBlockY(); y< heightY; y++) {
Block airCheck = world.getBlockAt(x, y, z);
if (airCheck.getType().equals(Material.AIR)) {
world.spawnParticle(Particle.EXPLOSION_NORMAL, airCheck.getLocation(), 5);
//ParticleEffects.EXPLOSION_NORMAL.send(Bukkit.getOnlinePlayers(),airCheck.getLocation(),0D,0D,0D,1F,5,20);
//ParticleEffect.EXPLOSION_NORMAL.display(0F,0F,0F, 0.1F, 5, airCheck.getLocation(), 30D);
}
}
}
}
}
plugin.logger(3,"Bonemeal left = " + total);
// Remove the bonemeal from the hopper
h.getInventory().remove(Material.BONE_MEAL);
h.getInventory().addItem(new ItemStack(Material.BONE_MEAL, total));
}
}
} else {
// Greenhouse is broken or no longer has a hopper when it should
// TODO remove the greenhouse
plugin.logger(3,"Hopper is not there anymore...");
}
}
}
/**
* Converts blocks in the greenhouse over time at a random rate
* Depends on the biome recipe
*/
public void convertBlocks() {
if (biomeRecipe == null) {
return;
}
if (biomeRecipe.getBlockConvert()) {
// Check biome recipe
int minx = Math.min(pos1.getBlockX(), pos2.getBlockX());
int maxx = Math.max(pos1.getBlockX(), pos2.getBlockX());
int minz = Math.min(pos1.getBlockZ(), pos2.getBlockZ());
int maxz = Math.max(pos1.getBlockZ(), pos2.getBlockZ());
for (int x = minx+1; x < maxx; x++) {
for (int z = minz+1; z < maxz;z++) {
for (int y = groundY; y < heightY; y++) {
biomeRecipe.convertBlock(world.getBlockAt(x,y,z));
}
}
}
}
}
/**
* Replaces the getHighestBlock function by only looking within a greenhouse
* @param x
* @param z
* @return Non-solid block just above the highest solid block at x,z - should always be AIR
*/
public Block getHighestBlockInGreenhouse(int x, int z) {
Block bl = world.getBlockAt(x,heightY,z).getRelative(BlockFace.DOWN);
while (bl.getLocation().getBlockY() >= groundY && bl.isEmpty()) {
bl = bl.getRelative(BlockFace.DOWN);
}
return bl.getRelative(BlockFace.UP);
}
}

View File

@ -0,0 +1,42 @@
package world.bentobox.greenhouses.greenhouse;
import org.bukkit.Material;
public class GreenhouseBlockConversions {
private final Material oldMaterial;
private final Material newMaterial;
private final double probability;
private final Material localMaterial;
public GreenhouseBlockConversions(Material oldMaterial, Material newMaterial, double probability, Material localMaterial) {
this.oldMaterial = oldMaterial;
this.newMaterial = newMaterial;
this.probability = probability;
this.localMaterial = localMaterial;
}
/**
* @return the oldMaterial
*/
public Material getOldMaterial() {
return oldMaterial;
}
/**
* @return the newMaterial
*/
public Material getNewMaterial() {
return newMaterial;
}
/**
* @return the probability
*/
public double getProbability() {
return probability;
}
/**
* @return the localMaterial
*/
public Material getLocalMaterial() {
return localMaterial;
}
}

View File

@ -0,0 +1,31 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
public class GreenhouseMob {
private final EntityType mobType;
private final Material mobSpawnOn;
/**
* @param mobType - entity type of mob
* @param mobSpawnOn - material on which it much spawn, or null if any
*/
public GreenhouseMob(EntityType mobType, Material mobSpawnOn) {
this.mobType = mobType;
this.mobSpawnOn = mobSpawnOn;
}
/**
* @return the mobType
*/
public EntityType getMobType() {
return mobType;
}
/**
* @return the mobSpawnOn
*/
public Optional<Material> getMobSpawnOn() {
return Optional.of(mobSpawnOn);
}
}

View File

@ -0,0 +1,32 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.Optional;
import org.bukkit.Material;
public class GreenhousePlant {
private final Material plantMaterial;
private final Material plantGrownOn;
/**
* Describes a recipe plant
* @param plantMaterial - material
* @param plantGrownOn - material on which this grows
*/
public GreenhousePlant(Material plantMaterial,Material plantGrownOn) {
this.plantMaterial = plantMaterial;
this.plantGrownOn = plantGrownOn;
}
/**
* @return the plantMaterial
*/
public Material getPlantMaterial() {
return plantMaterial;
}
/**
* @return the plantGrownOn
*/
public Optional<Material> getPlantGrownOn() {
return Optional.ofNullable(plantGrownOn);
}
}

View File

@ -0,0 +1,234 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.util.Vector;
import world.bentobox.greenhouses.Greenhouses;
/**
* Contains the parameters of a greenhouse roof
* @author tastybento
*
*/
public class Roof {
private int minX;
private int maxX;
private int minZ;
private int maxZ;
private int height;
private boolean roofFound;
private final static List<String> ROOFBLOCKS = Arrays.asList("GLASS","STAINED_GLASS","HOPPER","TRAP_DOOR","IRON_TRAPDOOR","GLOWSTONE");
/**
* Finds a roof from a starting location under the roof and characterizes it
* @param loc
*/
public Roof(Greenhouses plugin, Location loc) {
World world = loc.getWorld();
// This section tries to find a roof block
// Try just going up - this covers every case except if the player is standing under a hole
roofFound = false;
// This does a ever-growing check around the player to find a roof block. It is possible for the player
// to be outside the greenhouse in this situation, so a check is done later to mkae sure the player is inside
//if (!roofFound) {
int roofY = loc.getBlockY();
// If the roof was not found start going around in circles until something is found
// Expand in ever increasing squares around location until a wall block is found
for (int radius = 0; radius < 100; radius++) {
for (int x = loc.getBlockX() - radius; x <= loc.getBlockX() + radius; x++) {
for (int z = loc.getBlockZ() - radius; z <= loc.getBlockZ() + radius; z++) {
if (!((x > loc.getBlockX() - radius && x < loc.getBlockX() + radius)
&& (z > loc.getBlockZ() - radius && z < loc.getBlockZ() + radius))) {
//player.sendBlockChange(new Location(world,x,roofY,z), Material.GLASS, (byte)(radius % 14));
Block b = world.getBlockAt(x,roofY,z);
plugin.logger(3,"Checking column " + x + " " + z );
if (!Walls.isWallBlock(b.getType())) {
// Look up
for (int y = roofY; y < world.getMaxHeight(); y++) {
if (ROOFBLOCKS.contains(world.getBlockAt(x,y,z).getType().name())) {
roofFound = true;
loc = new Location(world,x,y,z);
plugin.logger(3,"Roof block found at " + x + " " + y + " " + z + " of type " + loc.getBlock().getType().toString());
break;
}
}
}
}
if (roofFound) {
break;
}
}
if (roofFound) {
break;
}
}
if (roofFound) {
break;
}
}
//}
// Record the height
this.height = loc.getBlockY();
// Now we have a roof block, find how far we can go NSWE
minX = loc.getBlockX();
maxX = loc.getBlockX();
minZ = loc.getBlockZ();
maxZ = loc.getBlockZ();
expandCoords(loc);
int minx = minX;
int maxx = maxX;
int minz = minZ;
int maxz = maxZ;
// Now we have some idea of the mins and maxes, check each block and see if it goes further
do {
plugin.logger(3, "Roof minx=" + minx);
plugin.logger(3, "Roof maxx=" + maxx);
plugin.logger(3, "Roof minz=" + minz);
plugin.logger(3, "Roof maxz=" + maxz);
minx = minX;
maxx = maxX;
minz = minZ;
maxz = maxZ;
for (int x = minx; x <= maxx; x++) {
for (int z = minz; z <= maxz; z++) {
// This will push out the coords if possible
expandCoords(new Location(world, x, loc.getBlockY(), z));
}
}
// Repeat until nothing changes
} while (minx != minX || maxx != maxX || minz != minZ || maxz != maxZ);
// That's as much as we can do!
}
/**
* This takes any location and tries to go as far as possible in NWSE directions finding contiguous roof blocks
* up to 100 in any direction
* @param height
*/
private void expandCoords(Location height) {
Location maxx = height.clone();
Location minx = height.clone();
Location maxz = height.clone();
Location minz = height.clone();
int limit = 0;
while (ROOFBLOCKS.contains(maxx.getBlock().getType().name()) && limit < 100) {
limit++;
maxx.add(new Vector(1,0,0));
}
if (maxx.getBlockX()-1 > maxX) {
maxX = maxx.getBlockX()-1;
}
while (ROOFBLOCKS.contains(minx.getBlock().getType().name()) && limit < 200) {
limit++;
minx.subtract(new Vector(1,0,0));
}
if (minx.getBlockX() + 1 < minX) {
minX = minx.getBlockX() + 1;
}
while (ROOFBLOCKS.contains(maxz.getBlock().getType().name()) && limit < 300) {
limit++;
maxz.add(new Vector(0,0,1));
}
if (maxz.getBlockZ() - 1 > maxZ) {
maxZ = maxz.getBlockZ() - 1;
}
while (ROOFBLOCKS.contains(minz.getBlock().getType().name()) && limit < 400) {
limit++;
minz.subtract(new Vector(0,0,1));
}
if (minz.getBlockZ() + 1 < minZ) {
minZ = minz.getBlockZ() + 1;
}
}
/**
* @return the minX
*/
public int getMinX() {
return minX;
}
/**
* @param minX the minX to set
*/
public void setMinX(int minX) {
this.minX = minX;
}
/**
* @return the maxX
*/
public int getMaxX() {
return maxX;
}
/**
* @param maxX the maxX to set
*/
public void setMaxX(int maxX) {
this.maxX = maxX;
}
/**
* @return the minZ
*/
public int getMinZ() {
return minZ;
}
/**
* @param minZ the minZ to set
*/
public void setMinZ(int minZ) {
this.minZ = minZ;
}
/**
* @return the maxZ
*/
public int getMaxZ() {
return maxZ;
}
/**
* @param maxZ the maxZ to set
*/
public void setMaxZ(int maxZ) {
this.maxZ = maxZ;
}
/**
* @return the area
*/
public int getArea() {
return (maxX - minX) * (maxZ - minZ);
}
/**
* @return the roofFound
*/
public boolean isRoofFound() {
return roofFound;
}
/**
* @return the height
*/
public int getHeight() {
return height;
}
/**
* Check if roof block
* @param blockType
* @return true if this is a roof block
*/
public boolean isRoofBlock(Material blockType) {
if (ROOFBLOCKS.contains(blockType.name())) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,274 @@
package world.bentobox.greenhouses.greenhouse;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import world.bentobox.greenhouses.Greenhouses;
public class Walls {
private int minX;
private int maxX;
private int minZ;
private int maxZ;
private int floor;
private boolean useRoofMaxX;
private boolean useRoofMinX;
private boolean useRoofMaxZ;
private boolean useRoofMinZ;
private Location roofBlock;
Location roofHopperLoc = null;
public final static List<Material> WALL_BLOCKS = Arrays.stream(Material.values())
.filter(Material::isBlock) // Blocks only, no items
.filter(m -> !m.name().contains("TRAPDOOR")) // No trapdoors
.filter(m -> m.name().contains("DOOR") // All doors
|| m.name().contains("GLASS") // All glass blocks
|| m.equals(Material.HOPPER) // Hoppers
|| m.equals(Material.GLOWSTONE)) // Glowstone
.collect(Collectors.toList());
public Walls(Greenhouses addon, final Player player, Roof roof) {
// The player is under the roof
// Assume the player is inside the greenhouse they are trying to create
Location loc = player.getLocation();
World world = player.getWorld();
// Find the floor - defined as the last y under the roof where there are no wall blocks
int wallBlockCount = 0;
int y = roof.getHeight();
do {
wallBlockCount = 0;
for (int x = roof.getMinX(); x <= roof.getMaxX(); x++) {
for (int z = roof.getMinZ(); z <= roof.getMaxZ(); z++) {
if (WALL_BLOCKS.contains(world.getBlockAt(x, y, z).getType())) {
wallBlockCount++;
}
}
}
} while( y-- > 0 && wallBlockCount > 0);
floor = y + 1;
addon.logger(3,"#1 Floor found at " + floor);
// Now start with the player's x and z location
int radiusMinX = 0;
int radiusMaxX = 0;
int radiusMinZ = 0;
int radiusMaxZ = 0;
boolean stopMinX = false;
boolean stopMaxX = false;
boolean stopMinZ = false;
boolean stopMaxZ = false;
minX = loc.getBlockX();
maxX = loc.getBlockX();
minZ = loc.getBlockZ();
maxZ = loc.getBlockZ();
addon.logger(3,"Starting point = " + loc.getBlockX() + "," + loc.getBlockZ());
addon.logger(3,"roof minX = " + roof.getMinX());
addon.logger(3,"roof maxX = " + roof.getMaxX());
addon.logger(3,"roof minZ = " + roof.getMinZ());
addon.logger(3,"roof maxZ = " + roof.getMaxZ());
do {
addon.logger(3,"wall radiusminX = " + radiusMinX);
addon.logger(3,"wall radius maxX = " + radiusMaxX);
addon.logger(3,"wall radius minZ = " + radiusMinZ);
addon.logger(3,"wall radius maxZ = " + radiusMaxZ);
// Look around player in an ever expanding cube
minX = loc.getBlockX() - radiusMinX;
maxX = loc.getBlockX() + radiusMaxX;
minZ = loc.getBlockZ() - radiusMinZ;
maxZ = loc.getBlockZ() + radiusMaxZ;
y = roof.getHeight() - 1;
for (y = roof.getHeight() - 1; y > floor; y--) {
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
// Only look around outside edge
if (!((x > minX && x < maxX) && (z > minZ && z < maxZ))) {
addon.logger(3,"Checking block " + x + " " + y + " " + z);
// Look at block faces
for (BlockFace bf: BlockFace.values()) {
switch (bf) {
case EAST:
// positive x
if (WALL_BLOCKS.contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMaxX = true;
addon.logger(3,"Wall found, stopping MaxX");
}
break;
case WEST:
// negative x
if (WALL_BLOCKS.contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMinX = true;
addon.logger(3,"Wall found, stopping minX");
}
break;
case NORTH:
// negative Z
if (WALL_BLOCKS.contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMinZ = true;
addon.logger(3,"Wall found, stopping minZ");
}
break;
case SOUTH:
// positive Z
if (WALL_BLOCKS.contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMaxZ = true;
addon.logger(3,"Wall found, stopping maxZ");
}
break;
default:
break;
}
}
}
}
}
}
if (minX < roof.getMinX()) {
addon.logger(3,"minx is less that the roof minX");
stopMinX = true;
}
if (maxX > roof.getMaxX()) {
addon.logger(3,"maxx is > that the roof minX");
stopMaxX = true;
}
if (minZ < roof.getMinZ()) {
addon.logger(3,"minz is less that the roof minz");
stopMinZ = true;
}
if (maxZ > roof.getMaxZ()) {
addon.logger(3,"maxZ is >t the roof maxZ");
stopMaxZ = true;
}
// Expand the edges
if (!stopMinX) {
radiusMinX++;
}
if (!stopMaxX) {
radiusMaxX++;
}
if (!stopMinZ) {
radiusMinZ++;
}
if (!stopMaxZ) {
radiusMaxZ++;
}
} while (!stopMinX || !stopMaxX || !stopMinZ || !stopMaxZ);
// We should have the largest cube we can make now
minX--;
maxX++;
minZ--;
maxZ++;
addon.logger(3,"wall minX = " + minX);
addon.logger(3,"wall maxX = " + maxX);
addon.logger(3,"wall minZ = " + minZ);
addon.logger(3,"wall maxZ = " + maxZ);
// Find the floor again, only looking within the walls
y = roof.getHeight();
do {
wallBlockCount = 0;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
if (WALL_BLOCKS.contains(world.getBlockAt(x, y, z).getType())) {
wallBlockCount++;
}
}
}
} while( y-- > 0 && wallBlockCount > 0);
floor = y + 1;
addon.logger(3,"#2 floor = " + floor);
}
/**
* @return the minXX
*/
public int getMinX() {
return minX;
}
/**
* @return the maxXX
*/
public int getMaxX() {
return maxX;
}
/**
* @return the minZZ
*/
public int getMinZ() {
return minZ;
}
/**
* @return the maxZZ
*/
public int getMaxZ() {
return maxZ;
}
/**
* @return the useRoofMaxX
*/
public boolean useRoofMaxX() {
return useRoofMaxX;
}
/**
* @return the useRoofMinX
*/
public boolean useRoofMinX() {
return useRoofMinX;
}
/**
* @return the useRoofMaxZ
*/
public boolean useRoofMaxZ() {
return useRoofMaxZ;
}
/**
* @return the useRoofMinZ
*/
public boolean useRoofMinZ() {
return useRoofMinZ;
}
/**
* @return the wallBlocks
*/
public List<Material> getWallBlocks() {
return WALL_BLOCKS;
}
public int getArea() {
// Get interior area
return (maxX - minX) * (maxZ - minZ);
}
/**
* @return the roofBlock
*/
public Location getRoofBlock() {
return roofBlock;
}
/**
* @return the roofHopperLoc
*/
public Location getRoofHopperLoc() {
return roofHopperLoc;
}
/**
* @return the floor
*/
public int getFloor() {
return floor;
}
public static boolean isWallBlock(Material blockType) {
return WALL_BLOCKS.contains(blockType);
}
}

View File

@ -0,0 +1,319 @@
package world.bentobox.greenhouses.listeners;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.Settings;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.ui.Locale;
import world.bentobox.greenhouses.util.Util;
/**
* @author tastybento
* This class listens for changes to greenhouses and reacts to them
*/
public class GreenhouseEvents implements Listener {
private final Greenhouses plugin;
private List<Location> blockedPistons = new ArrayList<Location>();
public GreenhouseEvents(final Greenhouses plugin) {
this.plugin = plugin;
}
/**
* Permits water to be placed in the Nether if in a greenhouse and in an acceptable biome
* @param event
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled=true)
public void onPlayerInteract(PlayerInteractEvent event){
Player player = event.getPlayer();
World world = player.getWorld();
// Check we are in the right world
if (!world.getEnvironment().equals(Environment.NETHER) || !Settings.worldName.contains(world.getName())) {
return;
}
if (event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
Biome biome = event.getClickedBlock().getBiome();
if (event.getItem() != null && biome != null) {
// Allow pouring of water if biome is okay
if (event.getItem().getType().equals(Material.WATER_BUCKET) && !biome.equals(Biome.NETHER)
&& !biome.equals(Biome.DESERT) && !biome.equals(Biome.DESERT_HILLS)) {
event.setCancelled(true);
event.getClickedBlock().getRelative(event.getBlockFace()).setType(Material.WATER);
}
}
}
}
/**
* Makes water in the Nether if ice is broken and in a greenhouse
* @param event
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled=true)
public void onIceBreak(BlockBreakEvent event){
Player player = event.getPlayer();
World world = player.getWorld();
// Check we are in the right world
if (!Settings.worldName.contains(world.getName())) {
return;
}
Biome biome = event.getBlock().getBiome();
// Set to water if the biome is okay.
if(event.getBlock().getWorld().getEnvironment() == Environment.NETHER && event.getBlock().getType() == Material.ICE
&& !biome.equals(Biome.NETHER) && !biome.equals(Biome.DESERT) && !biome.equals(Biome.DESERT_HILLS)) {
event.setCancelled(true);
event.getBlock().setType(Material.WATER);
}
}
/**
* Tracks player movement
* @param event
*/
/*
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true)
public void onPlayerMove(PlayerMoveEvent event) {
//plugin.logger(3,event.getEventName());
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
if (plugin.getPlayerGHouse(uuid) == null || plugin.getPlayerGHouse(uuid).isEmpty()) {
return;
}
World world = player.getWorld();
// Check we are in the right world
if (!Settings.worldName.contains(world.getName())) {
plugin.logger(4,"Not in a Greenhouse world");
return;
}
// Did we move a block?
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
boolean result = checkMove(player, event.getFrom(), event.getTo(), uuid);
if (result) {
Location newLoc = event.getFrom();
newLoc.setX(newLoc.getBlockX() + 0.5);
newLoc.setY(newLoc.getBlockY());
newLoc.setZ(newLoc.getBlockZ() + 0.5);
event.setTo(newLoc);
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerTeleport(PlayerTeleportEvent event) {
// Strangely, sometimes these worlds can be null
if (event.getFrom() == null || event.getTo() == null) {
return;
}
// Check if they changed worlds
UUID uuid = event.getPlayer().getUniqueId();
if (plugin.getPlayerGHouse(uuid) == null || plugin.getPlayerGHouse(uuid).isEmpty()) {
return;
}
World fromWorld = event.getFrom().getWorld();
World toWorld = event.getTo().getWorld();
// Check we are in the right world
if (!Settings.worldName.contains(fromWorld.getName()) && !Settings.worldName.contains(toWorld.getName())) {
return;
}
// Did we move a block?
checkMove(event.getPlayer(), event.getFrom(), event.getTo(), uuid);
}
*/
/**
* @param player
* @param from
* @param to
* @return false if the player can move into that area, true if not allowed
*/
/*
private boolean checkMove(Player player, Location from, Location to, UUID uuid) {
Greenhouse fromGreenhouse = null;
Greenhouse toGreenhouse= null;
if (plugin.getGreenhouses().isEmpty()) {
// No greenhouses yet
return false;
}
plugin.logger(4,"Checking greenhouses");
plugin.logger(4,"From : " + from.toString());
plugin.logger(4,"From: " + from.getBlockX() + "," + from.getBlockZ());
plugin.logger(4,"To: " + to.getBlockX() + "," + to.getBlockZ());
for (Greenhouse d: plugin.getPlayerGHouse(uuid)) {
plugin.logger(4,"Greenhouse (" + d.getPos1().getBlockX() + "," + d.getPos1().getBlockZ() + " : " + d.getPos2().getBlockX() + "," + d.getPos2().getBlockZ() + ")");
if (d.insideGreenhouse(to)) {
plugin.logger(4,"To intersects d!");
toGreenhouse = d;
}
if (d.insideGreenhouse(from)) {
plugin.logger(4,"From intersects d!");
fromGreenhouse = d;
}
}
// No greenhouse interaction
if (fromGreenhouse == null && toGreenhouse == null) {
// Clear the greenhouse flag (the greenhouse may have been deleted while they were offline)
plugin.players.setInGreenhouse(player, null);
return false;
} else if (fromGreenhouse == toGreenhouse) {
// Set the greenhouse - needs to be done if the player teleports too (should be done on a teleport event)
plugin.players.setInGreenhouse(player, toGreenhouse);
return false;
}
if (fromGreenhouse != null && toGreenhouse == null) {
// leaving a greenhouse
if (!fromGreenhouse.getFarewellMessage().isEmpty()) {
player.sendMessage(fromGreenhouse.getFarewellMessage());
}
plugin.players.setInGreenhouse(player, null);
//if (plugin.players.getNumberInGreenhouse(fromGreenhouse) == 0) {
// fromGreenhouse.ƒ();
//}
} else if (fromGreenhouse == null && toGreenhouse != null){
// Going into a greenhouse
if (!toGreenhouse.getEnterMessage().isEmpty()) {
player.sendMessage(toGreenhouse.getEnterMessage());
//plugin.visualize(toGreenhouse, player);
}
toGreenhouse.startBiome(false);
plugin.players.setInGreenhouse(player, toGreenhouse);
} else if (fromGreenhouse != null && toGreenhouse != null){
// Leaving one greenhouse and entering another greenhouse immediately
if (!fromGreenhouse.getFarewellMessage().isEmpty()) {
player.sendMessage(fromGreenhouse.getFarewellMessage());
}
plugin.players.setInGreenhouse(player, toGreenhouse);
//if (plugin.players.getNumberInGreenhouse(fromGreenhouse) == 0) {
//fromGreenhouse.endBiome();
//}
toGreenhouse.startBiome(false);
if (!toGreenhouse.getEnterMessage().isEmpty()) {
player.sendMessage(toGreenhouse.getEnterMessage());
}
}
return false;
}
*/
/**
* Checks is broken blocks cause the greenhouse to fail
* @param e
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled=true)
public void onBlockBreak(final BlockBreakEvent e) {
if (!Settings.worldName.contains(e.getPlayer().getWorld().getName())) {
return;
}
plugin.logger(3,"block break");
// Get the greenhouse that this block is in (if any)
Greenhouse g = plugin.getInGreenhouse(e.getBlock().getLocation());
if (g == null) {
// Not in a greenhouse
plugin.logger(3,"not in greenhouse");
return;
}
// Check to see if this causes the greenhouse to break
if ((e.getBlock().getLocation().getBlockY() == g.getHeightY()) || (g.isAWall(e.getBlock().getLocation()))) {
e.getPlayer().sendMessage(ChatColor.RED + Locale.eventbroke.replace("[biome]",Util.prettifyText(g.getOriginalBiome().toString())));
e.getPlayer().sendMessage(ChatColor.RED + Locale.eventfix);
plugin.removeGreenhouse(g);
return;
}
}
/**
* Prevents placing of blocks above the greenhouses
* @param e
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true)
public void onPlayerBlockPlace(final BlockPlaceEvent e) {
if (!Settings.worldName.contains(e.getPlayer().getWorld().getName())) {
return;
}
if (e.getPlayer().getWorld().getEnvironment().equals(Environment.NETHER)) {
return;
}
// If the offending block is not above a greenhouse, forget it!
Greenhouse g = plugin.aboveAGreenhouse(e.getBlock().getLocation());
if (g == null) {
return;
}
e.getPlayer().sendMessage(ChatColor.RED + Locale.eventcannotplace);
e.getPlayer().sendMessage("Greenhouse is at " + g.getPos1() + " to " + g.getPos2());
e.setCancelled(true);
}
/**
* Check to see if anyone is sneaking a block over a greenhouse by using a piston
* @param e
*/
@EventHandler
public void onPistonPush(final BlockPistonExtendEvent e) {
if (!Settings.worldName.contains(e.getBlock().getWorld().getName())) {
return;
}
if (e.getBlock().getWorld().getEnvironment().equals(Environment.NETHER)) {
return;
}
// Check if piston is already extended to avoid the double event effect
Location l = e.getBlock().getLocation();
if (blockedPistons.contains(l)) {
// Cancel the double call
blockedPistons.remove(l);
e.setCancelled(true);
return;
}
plugin.logger(3,"Direction: " + e.getDirection());
plugin.logger(3,"Location of piston block:" + l);
// Pistons can push up to 12 blocks - find the end block + 1
for (int i = 0; i < 13; i++) {
l = l.getBlock().getRelative(e.getDirection()).getLocation();
if (!l.getBlock().getType().isSolid()) {
break;
}
}
plugin.logger(3,"Location of end block + 1:" + l);
// The end block location is now l
if (plugin.aboveAGreenhouse(l) == null) {
return;
}
// Find out who is around the piston
for (Player p : plugin.getServer().getOnlinePlayers()) {
if (Settings.worldName.contains(p.getLocation().getWorld().getName())) {
if (p.getLocation().distanceSquared(e.getBlock().getLocation()) <= 25) {
p.sendMessage(ChatColor.RED + Locale.eventpistonerror);
e.setCancelled(true);
blockedPistons.add(e.getBlock().getLocation());
}
}
}
}
}

View File

@ -0,0 +1,57 @@
package world.bentobox.greenhouses.listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockFromToEvent;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.Settings;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
public class GreenhouseGuard implements Listener {
private final Greenhouses plugin;
public GreenhouseGuard(final Greenhouses plugin) {
this.plugin = plugin;
}
// Stop lava flow or water into or out of a greenhouse
@EventHandler(priority = EventPriority.NORMAL)
public void onFlow(final BlockFromToEvent e) {
// Flow may be allowed anyway
if (Settings.allowFlowIn && Settings.allowFlowOut) {
return;
}
if (!Settings.worldName.isEmpty() && !Settings.worldName.contains(e.getBlock().getWorld().getName())) {
return;
}
// Get To and From Districts
Greenhouse to = plugin.getInGreenhouse(e.getToBlock().getLocation());
Greenhouse from = plugin.getInGreenhouse(e.getBlock().getLocation());
// Scenarios
// 1. inside district or outside - always ok
// 2. inside to outside - allowFlowOut determines
// 3. outside to inside - allowFlowIn determines
if (to == null && from == null) {
return;
}
if (to !=null && from != null && to.equals(from)) {
return;
}
// to or from or both are districts, NOT the same and flow is across a boundary
// if to is a district, flow in is allowed
if (to != null && Settings.allowFlowIn) {
return;
}
// if from is a district, flow may allowed
if (from != null && Settings.allowFlowOut) {
return;
}
// Otherwise cancel - the flow is not allowed
e.setCancelled(true);
}
}

View File

@ -0,0 +1,54 @@
package world.bentobox.greenhouses.listeners;
import java.util.List;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.PlayerCache;
import world.bentobox.greenhouses.ui.Locale;
public class JoinLeaveEvents implements Listener {
private Greenhouses addon;
private PlayerCache players;
public JoinLeaveEvents(Greenhouses greenhouses, PlayerCache onlinePlayers) {
this.addon = greenhouses;
this.players = onlinePlayers;
}
/**
* @param event
*/
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerJoin(final PlayerJoinEvent event) {
Player p = event.getPlayer();
final UUID playerUUID = p.getUniqueId();
// Add player to the cache, and clear any greenhouses over their permitted limit
addon.players.addPlayer(p);
addon.logger(3,"Cached " + p.getName());
// Load any messages for the player
final List<String> messages = addon.getMessages(playerUUID);
if (!messages.isEmpty()) {
addon.getServer().getScheduler().runTaskLater(addon.getPlugin(), () -> {
event.getPlayer().sendMessage(ChatColor.AQUA + Locale.newsheadline);
int i = 1;
for (String message : messages) {
event.getPlayer().sendMessage(i++ + ": " + message);
}
}, 40L);
}
}
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerQuit(final PlayerQuitEvent event) {
players.removeOnlinePlayer(event.getPlayer());
}
}

View File

@ -0,0 +1,195 @@
package world.bentobox.greenhouses.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.util.Util;
import world.bentobox.greenhouses.util.VaultHelper;
/**
* @author tastybento
* Provides a handy control panel
*/
public class ControlPanel implements Listener {
private Greenhouses plugin;
private HashMap<UUID, HashMap<Integer,BiomeRecipe>> biomePanels = new HashMap<UUID, HashMap<Integer,BiomeRecipe>>();
/**
* @param store
*/
public ControlPanel(Greenhouses plugin) {
this.plugin = plugin;
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked(); // The player that clicked the item
Inventory inventory = event.getInventory(); // The inventory that was clicked in
int slot = event.getRawSlot();
HashMap<Integer,BiomeRecipe> panel = biomePanels.get(player.getUniqueId());
if (panel == null) {
// No panel, so just return
return;
}
// Check this is the Greenhouse Biome Panel
if (inventory.getName().equals(ChatColor.translateAlternateColorCodes('&', Locale.controlpaneltitle))) {
//String message = "";
event.setCancelled(true); // Don't let them pick anything up
if (slot < 0) {
player.closeInventory();
return;
}
if (slot == 0) {
player.performCommand("greenhouse info");
player.closeInventory();
return;
}
if (panel.containsKey(slot)) {
BiomeRecipe biomeRecipe = panel.get(slot);
// Sets up a greenhouse
Greenhouse oldg = plugin.players.getInGreenhouse(player);
// Check ownership
if (oldg != null && !oldg.getOwner().equals(player.getUniqueId())) {
player.sendMessage(Locale.errornotyours);
player.closeInventory();
return;
}
if (oldg != null) {
// Player wants to try and change biome
//player.closeInventory(); // Closes the inventory
// error.exists
//player.sendMessage(ChatColor.RED + Locale.erroralreadyexists);
//return;
plugin.removeGreenhouse(oldg);
}
// Check if they are at their limit
if (plugin.players.isAtLimit(player)) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', Locale.infonomore));
} else {
// Make greenhouse
Greenhouse g = plugin.tryToMakeGreenhouse(player, biomeRecipe);
if (g == null) {
player.closeInventory(); // Closes the inventory
//error.norecipe
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return;
}
player.closeInventory(); // Closes the inventory
}
//player.performCommand("greenhouse make");
//player.sendMessage(message);
}
}
}
/**
* Creates a player-specific biome panel based on permissions
* @param player
* @return
*/
public Inventory getPanel(Player player) {
HashMap<Integer, BiomeRecipe> store = new HashMap<Integer,BiomeRecipe>();
// Index 0 is reserved for instructions
int index = 1;
// Run through biomes and add to the inventory if this player is allowed to use them
for (BiomeRecipe br : plugin.getBiomeRecipes()) {
// Gather the info
if (br.getPermission().isEmpty() || VaultHelper.checkPerm(player, br.getPermission())) {
// Add this biome recipe to the list
store.put(index++, br);
}
}
// Now create the panel
//int panelSize = store.size() + 9 - 1;
int panelSize = store.size() + 9;
panelSize -= ( panelSize % 9);
Inventory biomePanel = Bukkit.createInventory(player, panelSize, ChatColor.translateAlternateColorCodes('&', Locale.controlpaneltitle));
// Add the instructions item
ItemStack item = new ItemStack(Material.THIN_GLASS);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(Locale.generalgreenhouses);
List<String> lore = new ArrayList<String>();
lore.addAll(new ArrayList<String>(Arrays.asList(Locale.infowelcome.split("\\|"))));
if (plugin.players.isAtLimit(player)) {
lore.add(ChatColor.translateAlternateColorCodes('&', Locale.infonomore));
} else {
if (plugin.players.getRemainingGreenhouses(player) > 0) {
if (plugin.players.getRemainingGreenhouses(player) == 1) {
lore.addAll(new ArrayList<String>(Arrays.asList(Locale.infoonemore.split("\\|"))));
} else {
String temp = Locale.infoyoucanbuild.replace("[number]", String.valueOf(plugin.players.getRemainingGreenhouses(player)));
lore.addAll(new ArrayList<String>(Arrays.asList(temp.split("\\|"))));
}
} else {
lore.addAll(new ArrayList<String>(Arrays.asList(Locale.infounlimited.split("\\|"))));
}
}
meta.setLore(lore);
item.setItemMeta(meta);
biomePanel.setItem(0, item);
// Now add the biomes
index = 1;
for (BiomeRecipe br : store.values()) {
// Create an itemStack
item = new ItemStack(br.getIcon());
meta = item.getItemMeta();
if (br.getFriendlyName().isEmpty()) {
meta.setDisplayName(Util.prettifyText(br.getBiome().toString()));
} else {
meta.setDisplayName(br.getFriendlyName());
}
lore.clear();
List<String> reqBlocks = br.getRecipeBlocks();
if (reqBlocks.size() > 0) {
lore.add(ChatColor.YELLOW + Locale.recipeminimumblockstitle);
int i = 1;
for (String list : reqBlocks) {
lore.add(Locale.lineColor + (i++) + ": " + list);
}
} else {
lore.add(ChatColor.YELLOW + Locale.recipenootherblocks);
}
if (br.getWaterCoverage() == 0) {
lore.add(Locale.recipenowater);
} else if (br.getWaterCoverage() > 0) {
lore.add(Locale.recipewatermustbe.replace("[coverage]", String.valueOf(br.getWaterCoverage())));
}
if (br.getIceCoverage() == 0) {
lore.add(Locale.recipenoice);
} else if (br.getIceCoverage() > 0) {
lore.add(Locale.recipeicemustbe.replace("[coverage]", String.valueOf(br.getIceCoverage())));
}
if (br.getLavaCoverage() == 0) {
lore.add(Locale.recipenolava);
} else if (br.getLavaCoverage() > 0) {
lore.add(Locale.recipelavamustbe.replace("[coverage]", String.valueOf(br.getLavaCoverage())));
}
meta.setLore(lore);
item.setItemMeta(meta);
biomePanel.setItem(index++,item);
}
// Stash the panel for later use when clicked
biomePanels.put(player.getUniqueId(), store);
return biomePanel;
}
}

View File

@ -0,0 +1,248 @@
package world.bentobox.greenhouses.ui;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.PlayerCache;
import world.bentobox.greenhouses.Settings;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.util.Util;
import world.bentobox.greenhouses.util.VaultHelper;
public class GreenhouseCmd implements CommandExecutor {
public boolean busyFlag = true;
private Greenhouses plugin;
private PlayerCache players;
/**
* Constructor
*
* @param plugin
* @param players
*/
public GreenhouseCmd(Greenhouses plugin, PlayerCache players) {
// Plugin instance
this.plugin = plugin;
this.players = players;
}
/*
* (non-Javadoc)
*
* @see
* org.bukkit.command.CommandExecutor#onCommand(org.bukkit.command.CommandSender
* , org.bukkit.command.Command, java.lang.String, java.lang.String[])
*/
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] split) {
if (!(sender instanceof Player)) {
return false;
}
final Player player = (Player) sender;
// Check we are in the right world
if (!Settings.worldName.contains(player.getWorld().getName())) {
// notavailable
player.sendMessage(ChatColor.RED + Locale.generalnotavailable);
return true;
}
// Basic permissions check to even use /greenhouse
if (!VaultHelper.checkPerm(player, "greenhouses.player")) {
player.sendMessage(ChatColor.RED + Locale.errornoPermission);
return true;
}
/*
* Grab data for this player - may be null or empty
* playerUUID is the unique ID of the player who issued the command
*/
final UUID playerUUID = player.getUniqueId();
switch (split.length) {
// /greenhouse command by itself
case 0:
final Greenhouse greenhouseInNow = players.getInGreenhouse(player);
if (greenhouseInNow==null || greenhouseInNow.getOwner().equals(playerUUID)) {
player.openInventory(plugin.getRecipeInv(player));
return true;
} else {
player.sendMessage(ChatColor.RED + Locale.errornotowner);
return true;
}
case 1:
// /greenhouse <command>
if (split[0].equalsIgnoreCase("help")) {
player.sendMessage(ChatColor.GREEN + Locale.generalgreenhouses +" " + plugin.getDescription().getVersion() + " " + Locale.helphelp + ":");
player.sendMessage(ChatColor.YELLOW + "/" + label + " : " + ChatColor.WHITE + Locale.helpopengui);
player.sendMessage(ChatColor.YELLOW + "/" + label + " make: " + ChatColor.WHITE + Locale.helpmake);
player.sendMessage(ChatColor.YELLOW + "/" + label + " remove: " + ChatColor.WHITE + Locale.helpremove);
player.sendMessage(ChatColor.YELLOW + "/" + label + " info: " + ChatColor.WHITE + Locale.helpinfo);
player.sendMessage(ChatColor.YELLOW + "/" + label + " list: " + ChatColor.WHITE + Locale.helplist);
player.sendMessage(ChatColor.YELLOW + "/" + label + " recipe <number>: " + ChatColor.WHITE + Locale.helprecipe);
return true;
} else if (split[0].equalsIgnoreCase("list")) {
// List all the biomes that can be made
player.sendMessage(ChatColor.GREEN + Locale.listtitle);
player.sendMessage(Locale.listinfo);
int index = 0;
for (BiomeRecipe br : plugin.getBiomeRecipes()) {
if (br.getFriendlyName().isEmpty()) {
player.sendMessage(ChatColor.YELLOW + Integer.toString(index++) + ": " + Util.prettifyText(br.getBiome().toString()));
} else {
player.sendMessage(ChatColor.YELLOW + Integer.toString(index++) + ": " + br.getFriendlyName());
}
}
return true;
} else if (split[0].equalsIgnoreCase("remove")) {
final Greenhouse greenhouseNow = players.getInGreenhouse(player);
if (greenhouseNow != null) {
if (greenhouseNow.getOwner().equals(playerUUID)) {
player.sendMessage(ChatColor.RED + Locale.errorremoving);
plugin.removeGreenhouse(greenhouseNow);
return true;
}
player.sendMessage(ChatColor.RED + Locale.errornotyours);
} else {
player.sendMessage(ChatColor.RED + Locale.errornotinside);
}
return true;
} else if (split[0].equalsIgnoreCase("make")) {
// Sets up a greenhouse
final Greenhouse greenhouseN = players.getInGreenhouse(player);
if (greenhouseN != null) {
// alreadyexists
player.sendMessage(ChatColor.RED + Locale.erroralreadyexists);
return true;
}
// Check if they are at their limit
if (plugin.players.isAtLimit(player)) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', Locale.infonomore));
} else {
// Try to make greenhouse
Greenhouse g = plugin.tryToMakeGreenhouse(player);
if (g == null) {
// norecipe
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
// Greenhouse is made
}
return true;
} else if (split[0].equalsIgnoreCase("info")) {
// Show some instructions on how to make greenhouses
player.sendMessage(ChatColor.GREEN + ChatColor.translateAlternateColorCodes('&', Locale.infotitle));
for (String instructions : Locale.infoinstructions) {
player.sendMessage(ChatColor.GREEN + ChatColor.translateAlternateColorCodes('&', instructions));
}
final Greenhouse greenhouseIn = players.getInGreenhouse(player);
if (greenhouseIn != null) {
player.sendMessage(ChatColor.GOLD + Locale.infoinfo);
// general.biome
player.sendMessage(ChatColor.GREEN + Locale.generalbiome + ": " + Util.prettifyText(greenhouseIn.getBiome().toString()));
if (greenhouseIn.getOwner() != null) {
Player owner = plugin.getServer().getPlayer(greenhouseIn.getOwner());
if (owner != null) {
player.sendMessage(ChatColor.YELLOW + Locale.generalowner + ": " + owner.getDisplayName() + " (" + owner.getName() + ")");
} else {
player.sendMessage(ChatColor.YELLOW + Locale.generalowner + ": " + greenhouseIn.getPlayerName());
}
}
}
return true;
}
break;
case 2:
if (split[0].equalsIgnoreCase("make")) {
// Sets up a greenhouse for a specific biome
if (players.getInGreenhouse(player) != null) {
// alreadyexists
player.sendMessage(ChatColor.RED + Locale.erroralreadyexists);
return true;
}
// Check if they are at their limit
if (plugin.players.isAtLimit(player)) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', Locale.infonomore));
} else {
// Check we are in a greenhouse
try {
if (NumberUtils.isNumber(split[1])) {
int recipeNum = Integer.valueOf(split[1]);
List<BiomeRecipe> recipeList = plugin.getBiomeRecipes();
if (recipeNum < 1 || recipeNum > recipeList.size()) {
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
if (plugin.tryToMakeGreenhouse(player,recipeList.get(recipeNum)) == null) {
// Failed for some reason - maybe permissions
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
}
} catch (Exception e) {
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
}
return true;
} else if (split[0].equalsIgnoreCase("recipe")) {
int recipeNumber = 0;
try {
recipeNumber = Integer.valueOf(split[1]);
} catch (Exception e) {
player.sendMessage(ChatColor.RED + Locale.recipehint);
return true;
}
List<BiomeRecipe> recipeList = plugin.getBiomeRecipes();
if (recipeNumber <1 || recipeNumber > recipeList.size()) {
player.sendMessage(ChatColor.RED + Locale.recipewrongnumber.replace("[size]", String.valueOf(recipeList.size())));
return true;
}
BiomeRecipe br = recipeList.get(recipeNumber-1);
if (br.getFriendlyName().isEmpty()) {
player.sendMessage(ChatColor.GREEN + "[" + Util.prettifyText(br.getBiome().toString()) + " recipe]");
} else {
player.sendMessage(ChatColor.GREEN + "[" + br.getFriendlyName() + " recipe]");
}
player.sendMessage(ChatColor.YELLOW + "Biome: " + Util.prettifyText(br.getBiome().toString()));
if (br.getWaterCoverage() == 0) {
player.sendMessage(Locale.recipenowater);
} else if (br.getWaterCoverage() > 0) {
player.sendMessage(Locale.recipewatermustbe.replace("[coverage]", String.valueOf(br.getWaterCoverage())));
}
if (br.getIceCoverage() == 0) {
player.sendMessage(Locale.recipenoice);
} else if (br.getIceCoverage() > 0) {
player.sendMessage(Locale.recipeicemustbe.replace("[coverage]", String.valueOf(br.getIceCoverage())));
}
if (br.getLavaCoverage() == 0) {
player.sendMessage(Locale.recipenolava);
} else if (br.getLavaCoverage() > 0) {
player.sendMessage(Locale.recipelavamustbe.replace("[coverage]", String.valueOf(br.getLavaCoverage())));
}
List<String> reqBlocks = br.getRecipeBlocks();
if (reqBlocks.size() > 0) {
player.sendMessage(ChatColor.YELLOW + Locale.recipeminimumblockstitle);
int index = 1;
for (String list : reqBlocks) {
player.sendMessage(Locale.lineColor + (index++) + ": " + list);
}
} else {
player.sendMessage(ChatColor.YELLOW + Locale.recipenootherblocks);
}
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,90 @@
package world.bentobox.greenhouses.ui;
import java.util.ArrayList;
import java.util.List;
/**
* @author ben
* All the text strings in the game sent to players
*/
public class Locale {
public static String generalnotavailable;
public static String generalgreenhouses;
public static String generalbiome;
public static String generalowner;
public static String helphelp;
public static String helpmake;
public static String helpremove;
public static String helpinfo;
public static String helplist;
public static String helprecipe;
public static String listtitle;
public static String listinfo;
public static String errorunknownPlayer;
public static String errornoPermission;
public static String errorcommandNotReady;
public static String errorofflinePlayer;
public static String errorunknownCommand;
public static String errormove;
public static String errornotowner;
public static String errorremoving;
public static String errornotyours;
public static String errornotinside;
public static String errortooexpensive;
public static String erroralreadyexists;
public static String errornorecipe;
public static String messagesenter;
public static String messagesleave;
public static String messagesyouarein;
public static String messagesremoved;
public static String messagesremovedmessage;
public static String messagesecolost;
public static String infotitle;
public static List<String> infoinstructions = new ArrayList<String>();
public static String infoinfo;
public static String infonone;
public static String recipehint;
public static String recipewrongnumber;
public static String recipetitle;
public static String recipenowater;
public static String recipenoice;
public static String recipenolava;
public static String recipewatermustbe;
public static String recipeicemustbe;
public static String recipelavamustbe;
public static String recipeminimumblockstitle;
public static String recipenootherblocks;
public static String eventbroke;
public static String eventfix;
public static String eventcannotplace;
public static String eventpistonerror;
public static String createnoroof;
public static String createmissingwall;
public static String createnothingabove;
public static String createholeinroof;
public static String createholeinwall;
public static String createhoppererror;
public static String createdoorerror;
public static String createsuccess;
public static String adminHelpreload;
public static String adminHelpinfo;
public static String reloadconfigReloaded;
public static String admininfoerror;
public static String admininfoerror2;
public static String admininfoflags;
public static String newsheadline;
public static String controlpaneltitle;
public static String recipemissing;
public static String infoyoucanbuild;
public static String infoonemore;
public static String infonomore;
public static String infounlimited;
public static String infowelcome;
public static String helpopengui;
public static String limitsnoneallowed;
public static String limitslimitedto;
public static String lineColor;
}

View File

@ -0,0 +1,110 @@
package world.bentobox.greenhouses.ui.admin;
import java.util.List;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.greenhouses.Greenhouses;
/**
* This class handles commands for admins
*
*/
public class AdminCmd extends CompositeCommand {
public AdminCmd(Greenhouses greenhouses) {
super(greenhouses, "gadmin");
}
@Override
public void setup() {
this.setPermission("greenhouses.admin");
this.setOnlyPlayer(false);
this.setParametersHelp("greenhouses.admin.parameters");
this.setDescription("greenhouses.admin.description");
new GreenhousesAdminReloadCommand(this);
new GreenhousesAdminInfoCommand(this);
}
@Override
public boolean execute(User user, String label, List<String> args) {
return false;
}
/*
case 1:
if (split[0].equalsIgnoreCase("reload")) {
plugin.reloadConfig();
plugin.loadPluginConfig();
plugin.loadBiomeRecipes();
plugin.ecoTick();
sender.sendMessage(ChatColor.YELLOW + Locale.reloadconfigReloaded);
return true;
} else if (split[0].equalsIgnoreCase("info")) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + Locale.admininfoerror);
return true;
}
Player player = (Player)sender;
Greenhouse greenhouse = players.getInGreenhouse(player);
if (greenhouse == null) {
sender.sendMessage(ChatColor.RED + Locale.admininfoerror2);
return true;
}
sender.sendMessage(ChatColor.GREEN + Locale.infoinfo);
sender.sendMessage(ChatColor.GREEN + Locale.generalowner + ":" + greenhouse.getPlayerName());
sender.sendMessage(ChatColor.GREEN + Locale.admininfoflags);
for (String flag : greenhouse.getFlags().keySet()) {
sender.sendMessage(flag + ": " + greenhouse.getFlags().get(flag));
}
return true;
} else {
sender.sendMessage(ChatColor.RED + Locale.errorunknownCommand);
return false;
}
case 2:
if (split[0].equalsIgnoreCase("info")) {
sender.sendMessage(ChatColor.GREEN + Locale.infoinfo);
int index = 0;
boolean found = false;
for (Greenhouse g : plugin.getGreenhouses()) {
if (g.getPlayerName().equalsIgnoreCase(split[1])) {
if (!found)
sender.sendMessage(ChatColor.GREEN + Locale.generalowner + ":" + g.getPlayerName());
found = true;
sender.sendMessage("Greenhouse #" + (++index));
sender.sendMessage("Biome: " + g.getBiome().name());
sender.sendMessage("Recipe: " + g.getBiomeRecipe().getFriendlyName());
sender.sendMessage(g.getWorld().getName());
sender.sendMessage(g.getPos1().getBlockX() + ", " + g.getPos1().getBlockZ() + " to " + g.getPos2().getBlockX() + ", " + g.getPos2().getBlockZ());
sender.sendMessage("Base at " + g.getPos1().getBlockY());
sender.sendMessage("Height = " + g.getHeight());
sender.sendMessage("Area = " + g.getArea());
}
}
if (found) {
if (index == 0) {
sender.sendMessage("Player has no greenhouses.");
} else {
Player player = plugin.getServer().getPlayer(split[1]);
if (player != null) {
sender.sendMessage("Player has " + index + " greenhouses and is allowed to build " + plugin.getMaxGreenhouses(player));
} else {
sender.sendMessage("Player has " + index + " greenhouses. Player is offline.");
}
}
} else {
sender.sendMessage(ChatColor.RED + "Cannot find that player. (May not have logged on recently)");
}
return true;
} else {
sender.sendMessage(ChatColor.RED + Locale.errorunknownCommand);
return false;
}
default:
return false;
}
}*/
}

View File

@ -0,0 +1,45 @@
/**
*
*/
package world.bentobox.greenhouses.ui.admin;
import java.util.List;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
/**
* @author tastybento
*
*/
public class GreenhousesAdminInfoCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public GreenhousesAdminInfoCommand(CompositeCommand parent) {
super(parent, "info");
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,44 @@
/**
*
*/
package world.bentobox.greenhouses.ui.admin;
import java.util.List;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
/**
* @author tastybento
*
*/
public class GreenhousesAdminReloadCommand extends CompositeCommand {
/**
* @param addon
* @param label
* @param aliases
*/
public GreenhousesAdminReloadCommand(CompositeCommand parent) {
super(parent, "reload");
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,62 @@
/**
*
*/
package world.bentobox.greenhouses.ui.user;
import java.util.List;
import org.bukkit.ChatColor;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.ui.Locale;
/**
* @author tastybento
*
*/
public class GhCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public GhCommand(CompositeCommand parent) {
super(parent, "greenhouse", "gh");
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
this.setPermission("greenhouses.command");
this.setOnlyPlayer(true);
this.setParametersHelp("greenhouses.command.parameters");
this.setDescription("greenhouses.command.description");
new InfoCommand(this);
new ListCommand(this);
new MakeCommand(this);
new RecipeCommand(this);
new RemoveCommand(this);
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
final Greenhouse greenhouseInNow = players.getInGreenhouse(player);
if (greenhouseInNow==null || greenhouseInNow.getOwner().equals(playerUUID)) {
player.openInventory(plugin.getRecipeInv(player));
return true;
} else {
player.sendMessage(ChatColor.RED + Locale.errornotowner);
return true;
}
}
}

View File

@ -0,0 +1,45 @@
/**
*
*/
package world.bentobox.greenhouses.ui.user;
import java.util.List;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
/**
* @author tastybento
*
*/
public class InfoCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public InfoCommand(CompositeCommand parent) {
super(parent, "make");
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,62 @@
/**
*
*/
package world.bentobox.greenhouses.ui.user;
import java.util.List;
import org.bukkit.ChatColor;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.ui.Locale;
import world.bentobox.greenhouses.util.Util;
/**
* @author tastybento
*
*/
public class ListCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public ListCommand(CompositeCommand parent) {
super(parent, "list");
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
// List all the biomes that can be made
user.sendMessage(ChatColor.GREEN + Locale.listtitle);
user.sendMessage(Locale.listinfo);
int index = 0;
for (BiomeRecipe br : ((Greenhouses)getAddon()).getBiomeRecipes()) {
if (br.getFriendlyName().isEmpty()) {
user.sendMessage(ChatColor.YELLOW + Integer.toString(index++) + ": " + Util.prettifyText(br.getBiome().toString()));
} else {
user.sendMessage(ChatColor.YELLOW + Integer.toString(index++) + ": " + br.getFriendlyName());
}
}
return true;
}
}

View File

@ -0,0 +1,105 @@
/**
*
*/
package world.bentobox.greenhouses.ui.user;
import java.util.List;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.ChatColor;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.ui.Locale;
/**
* @author tastybento
*
*/
public class MakeCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public MakeCommand(CompositeCommand parent) {
super(parent, "make");
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
// Sets up a greenhouse
final Greenhouse greenhouseN = players.getInGreenhouse(player);
if (greenhouseN != null) {
// alreadyexists
player.sendMessage(ChatColor.RED + Locale.erroralreadyexists);
return true;
}
// Check if they are at their limit
if (plugin.players.isAtLimit(player)) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', Locale.infonomore));
} else {
// Try to make greenhouse
Greenhouse g = plugin.tryToMakeGreenhouse(player);
if (g == null) {
// norecipe
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
// Greenhouse is made
}
return true;
// Second arg
case 2:
if (split[0].equalsIgnoreCase("make")) {
// Sets up a greenhouse for a specific biome
if (players.getInGreenhouse(player) != null) {
// alreadyexists
player.sendMessage(ChatColor.RED + Locale.erroralreadyexists);
return true;
}
// Check if they are at their limit
if (plugin.players.isAtLimit(player)) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', Locale.infonomore));
} else {
// Check we are in a greenhouse
try {
if (NumberUtils.isNumber(split[1])) {
int recipeNum = Integer.valueOf(split[1]);
List<BiomeRecipe> recipeList = plugin.getBiomeRecipes();
if (recipeNum < 1 || recipeNum > recipeList.size()) {
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
if (plugin.tryToMakeGreenhouse(player,recipeList.get(recipeNum)) == null) {
// Failed for some reason - maybe permissions
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
}
} catch (Exception e) {
player.sendMessage(ChatColor.RED + Locale.errornorecipe);
return true;
}
}
return true;
}
}

View File

@ -0,0 +1,95 @@
/**
*
*/
package world.bentobox.greenhouses.ui.user;
import java.util.List;
import org.bukkit.ChatColor;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.ui.Locale;
import world.bentobox.greenhouses.util.Util;
/**
* @author tastybento
*
*/
public class RecipeCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public RecipeCommand(CompositeCommand parent) {
super(parent, "make");
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
// Second arg
int recipeNumber = 0;
try {
recipeNumber = Integer.valueOf(split[1]);
} catch (Exception e) {
player.sendMessage(ChatColor.RED + Locale.recipehint);
return true;
}
List<BiomeRecipe> recipeList = plugin.getBiomeRecipes();
if (recipeNumber <1 || recipeNumber > recipeList.size()) {
player.sendMessage(ChatColor.RED + Locale.recipewrongnumber.replace("[size]", String.valueOf(recipeList.size())));
return true;
}
BiomeRecipe br = recipeList.get(recipeNumber-1);
if (br.getFriendlyName().isEmpty()) {
player.sendMessage(ChatColor.GREEN + "[" + Util.prettifyText(br.getBiome().toString()) + " recipe]");
} else {
player.sendMessage(ChatColor.GREEN + "[" + br.getFriendlyName() + " recipe]");
}
player.sendMessage(ChatColor.YELLOW + "Biome: " + Util.prettifyText(br.getBiome().toString()));
if (br.getWaterCoverage() == 0) {
player.sendMessage(Locale.recipenowater);
} else if (br.getWaterCoverage() > 0) {
player.sendMessage(Locale.recipewatermustbe.replace("[coverage]", String.valueOf(br.getWaterCoverage())));
}
if (br.getIceCoverage() == 0) {
player.sendMessage(Locale.recipenoice);
} else if (br.getIceCoverage() > 0) {
player.sendMessage(Locale.recipeicemustbe.replace("[coverage]", String.valueOf(br.getIceCoverage())));
}
if (br.getLavaCoverage() == 0) {
player.sendMessage(Locale.recipenolava);
} else if (br.getLavaCoverage() > 0) {
player.sendMessage(Locale.recipelavamustbe.replace("[coverage]", String.valueOf(br.getLavaCoverage())));
}
List<String> reqBlocks = br.getRecipeBlocks();
if (reqBlocks.size() > 0) {
player.sendMessage(ChatColor.YELLOW + Locale.recipeminimumblockstitle);
int index = 1;
for (String list : reqBlocks) {
player.sendMessage(Locale.lineColor + (index++) + ": " + list);
}
} else {
player.sendMessage(ChatColor.YELLOW + Locale.recipenootherblocks);
}
return true;
}
}

View File

@ -0,0 +1,61 @@
/**
*
*/
package world.bentobox.greenhouses.ui.user;
import java.util.List;
import org.bukkit.ChatColor;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.greenhouses.Greenhouses;
import world.bentobox.greenhouses.greenhouse.Greenhouse;
import world.bentobox.greenhouses.ui.Locale;
/**
* @author tastybento
*
*/
public class RemoveCommand extends CompositeCommand {
/**
* @param parent
* @param label
* @param aliases
*/
public RemoveCommand(CompositeCommand parent) {
super(parent, "make");
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
final Greenhouse greenhouseNow = ((Greenhouses)getAddon()).getInGreenhouse(user);
if (greenhouseNow != null) {
if (greenhouseNow.getOwner().equals(user.getUniqueId())) {
user.sendMessage(ChatColor.RED + Locale.errorremoving);
plugin.removeGreenhouse(greenhouseNow);
return true;
}
user.sendMessage(ChatColor.RED + Locale.errornotyours);
} else {
user.sendMessage(ChatColor.RED + Locale.errornotinside);
}
return true;
}
}

22
src/main/resources/addon.yml Executable file
View File

@ -0,0 +1,22 @@
name: WelcomeWarps
main: world.bentobox.warps.Warp
version: ${version}
authors: tastybento
softdepend: AcidIsland, BSkyBlock
permissions:
bskyblock.island.warp:
description: Player can use warp or warps commands
default: true
bskyblock.island.addwarp:
description: Player can create a welcome warp sign
default: true
acidisland.island.warp:
description: Player can use warp or warps commands
default: true
acidisland.island.addwarp:
description: Player can create a welcome warp sign
default: true

View File

@ -0,0 +1,198 @@
# This file lists the recipes for the greenhouse biomes
biomes:
# Biome recipe name - can be anything you like, but must be unique
beaches:
# The name of the icon. Can use & for color codes, e.g. &c
friendlyname: "Beach"
# The biome of the recipe. Allows multiple recipes for the same biome.
biome: BEACHES
# The icon is shown in the panel. It must be a Bukkit Material
icon: SAND
# Priority is used if the greenhouse can be more than one biome. The highest
# priority wins
priority: 0
# Contents - The minimum requirement for this biome.
# Format is Material:Type/Durability (optional):Number of blocks
# So SAND:1:1 would require 1 block of red sand (durability of 1 = red sand)
contents: SAND:1
# The number of blocks in the greenhouse that must be water, ice or lava
# Floor area * this % = number of blocks required
watercoverage: 50
# If the value is zero, then NO ice/water/lava is allowed
# If the values are missing, or negative, then ice/water/lava is allowed, but not
# required for the biome.
# icecoverage: 0
# lavacoverage: 0
# Plants that can grow via the hopper/bonemeal system
# Format is:
# Material:Type(optional): % chance:Block type on which it can grow
# Note that with really small greenhouses, melons and pumpkins can change
# grass to dirt, which may break the eco system!
plants:
DEAD_BUSH: 5:SAND
# Mobs that may spawn.
# Format:
# Entity name: % chance:Block on which the mob will spawn
mobs:
SQUID: 10:STATIONARY_WATER
# The minimum number of blocks each mob requires.
# Mobs will not spawn if there is more than 1 per this number of
# blocks in the greenhouse. e.g., in this case only 2 mobs will spawn if the
# greenhouse area is 18 blocks
moblimit: 9
Snowy_beach:
friendlyname: "Snowy beach"
biome: COLD_BEACH
icon: SNOW_BLOCK
priority: 21
contents: SAND:1
watercoverage: 50
icecoverage: 10
ThreeWolfMoon:
friendlyname: "Three Wolf Moon Forest"
# Could do with more wolves, but the magic works with 3.
# If you are using 1.8 or earlier, this biome should be COLD_TAIGA
biome: TAIGA_COLD
icon: SAPLING
priority: 20
contents: LOG:3 LEAVES:3 GRASS:3
icecoverage: 10
plants:
LONG_GRASS:1: 10:GRASS
mobs:
WOLF: 10:SNOW
moblimit: 9
Cold_Rabbit:
friendlyname: "Cold Taiga Forest"
# If you are using 1.8 or earlier, this biome should be COLD_TAIGA
biome: TAIGA_COLD
icon: SAPLING
priority: 20
contents: LOG:3 LEAVES:3 GRASS:3
icecoverage: 10
plants:
LONG_GRASS:1: 10:GRASS
mobs:
RABBIT: 10:SNOW
moblimit: 9
DESERT:
friendlyname: "Desert"
biome: "Desert"
icon: DEAD_BUSH
priority: 3
contents: SAND:1
# No water allowed
watercoverage: 0
# No ice allowed
icecoverage: 0
plants:
DEAD_BUSH: 10:SAND
CACTUS: 10:SAND
# Conversions (see below for another variation)
# Format is:
# Original Block Material:Durability:Chance of change:New Block Material:Durability
# So, for below, regular dirt (durability 0) has a 30% chance of changing into regular sand.
conversions: DIRT:0:30:SAND:0
FOREST:
friendlyname: "Flowery forest"
biome: FOREST
icon: RED_ROSE
priority: 4
contents: LOG:3 LEAVES:4 GRASS:4
plants:
RED_ROSE:8: 2:GRASS
DOUBLE_PLANT:5: 4:GRASS
LONG_GRASS:1: 20:GRASS
HELL:
friendlyname: "&cNether"
biome: HELL
icon: LAVA_BUCKET
priority: 5
contents: NETHERRACK:1
# Lava required, no ice or water allowed
lavacoverage: 21
icecoverage: 0
watercoverage: 0
mobs:
PIG_ZOMBIE: 10:NETHERRACK
moblimit: 9
permission: greenhouses.biome.nether
JUNGLE:
biome: JUNGLE
icon: VINE
priority: 6
contents: GRASS:4 LOG:3:3 LEAVES:3:4
plants:
YELLOW_FLOWER: 20:GRASS
MELON_BLOCK: 10:GRASS
RED_ROSE: 20:GRASS
DOUBLE_PLANT:3: 20:GRASS
LONG_GRASS:2: 20:GRASS
MUSHROOM_ISLAND:
friendlyname: "Mushroom Island"
biome: MUSHROOM_ISLAND
icon: RED_MUSHROOM
priority: 11
contents: MYCEL:2
# Water required at 30%
watercoverage: 30
plants:
BROWN_MUSHROOM: 10:MYCEL
RED_MUSHROOM: 10:MYCEL
mobs:
MUSHROOM_COW: 10:MYCEL
moblimit: 9
OCEAN:
biome: OCEAN
icon: WATER_BUCKET
priority: 8
# Lots of water required!
watercoverage: 95
mobs:
SQUID: 10:STATIONARY_WATER
moblimit: 9
PLAINS:
friendlyname: "Horse Plains"
biome: PLAINS
icon: GRASS
priority: 1
contents: GRASS:3
plants:
LONG_GRASS:1: 10:GRASS
mobs:
HORSE: 10:GRASS
moblimit: 9
RIVER:
friendlyname: "Clay river"
biome: RIVER
icon: CLAY
priority: 10
contents: SAND:1
# 50% water required
watercoverage: 50
# Conversions - in this case, an adjacent block is required to convert
# Format is:
# Original Block:Durability:% chance:New Block:Durability:Adjacent Block:Durability
# So, for below, dirt has a 50% chance of changing into clay if it is next to water!
conversions: DIRT:0:50:CLAY:0:STATIONARY_WATER:0
SAVANNA:
biome: SAVANNA
icon: LEAVES
priority: 11
contents: LOG_2:3 LEAVES_2:4 GRASS:4
plants:
DOUBLE_PLANT:2: 10:GRASS
SWAMPLAND:
friendlyname: "&2Slimy Swamp"
icon: WATER_LILY
priority: 13
contents: GRASS:4 LOG:3 LEAVES:4
# 50% water coverage required
watercoverage: 50
plants:
RED_MUSHROOM: 20:GRASS
BROWN_MUSHROOM: 20:GRASS
WATER_LILY: 5:STATIONARY_WATER
mobs:
SLIME: 5:STATIONARY_WATER
moblimit: 3

View File

@ -0,0 +1,52 @@
greenhouses:
# World Name where Greenhouses will operate
worldName:
- world
- creative
- ASkyBlock
- AcidIsland
# Console message level.
# List the levels of debug or messages you want.
# 0 = no messages except for warnings or severe errors
# 1 = normal messages (default)
# 2 and higher - debug levels - no need to use these unless you want to try debug
debug:
- 1
### Permissions limits
# Set the maximum number of greenhouses a player can build
# using greenhouses.limit.<number>
# This is the default max. -1 is unlimited
maxgreenhouses: -1
# To have extra greenhouses deleted upon login set the following to true
deleteextras: false
### Weather and ecosystem settings
# How often it should snow in the g/h when the weather is raining, in seconds
snowspeed: 30
# Chance of any snow falling in a greenhouse when the snow tick occurs
# (1.0 = always, 0.0 = never)
snowchance: 1
# How many blocks should get snow 1 = all of them, 0 = none, 0.1 = 1 in 10
snowdensity: 0.1
# Biome activity
# How often should greenhouse biomes be checked to make sure they are still valid
ecotick: 5
# How often should plants potentially grow in minutes if bonemeal is in the hopper
planttick: 1
# How often should blocks potentially convert, in minutes
# Example: dirt-> sand in desert greenhouse
blocktick: 2
# How often should mobs be potentially spawned in a greenhouse, in minutes
mobtick: 5
### Default settings for greenhouse actions
# Allow lava or water to flow out of a greenhouse, e.g. through the door, floor
allowflowout: false
# Allow lava or water to flow into a greenhouse, e.g., through the door
allowflowin: false