Initial commit

This commit is contained in:
Tomás F 2020-05-04 11:47:38 +01:00
commit c0b11d3e34
29 changed files with 1506 additions and 0 deletions

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Tomás F.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

22
README.md Normal file
View File

@ -0,0 +1,22 @@
<p align="center">
<img src="static/header.png" alt="Bees+"/>
</p>
A Spigot (Minecraft server software) plugin that displays useful bee-related information.
<p align="center">
<img src="static/gui.gif" alt="[GUI GIF]"/>
</p>
## Compatibiliy
This plugin is only compatible with Minecraft 1.15+ currently.
## Builds
The latest plugin builds can be found in it's SpigotMC Forum's page [here](https://www.spigotmc.org/resources/beesplus.77224/).
You can also clone this repository and build the plugin with Maven.
Please note that this projects depends on `spigot` and not `spigot-api`
## Metrics
<p align="center">
<img src="https://bstats.org/signatures/bukkit/BeesPlus.svg" alt="[Metrics Graph]"/>
</p>

85
pom.xml Normal file
View File

@ -0,0 +1,85 @@
<?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>com.tomff.beesplus</groupId>
<artifactId>BeesPlus</artifactId>
<version>1.4.2-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>CodeMC</id>
<url>https://repo.codemc.org/repository/maven-public</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.15.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.7</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>plugin.yml</include>
<include>config.yml</include>
<include>locale/*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>com.tomff.beesplus</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,101 @@
package com.tomff.beesplus;
import com.tomff.beesplus.handlers.DamageHandler;
import com.tomff.beesplus.handlers.RightClickHandler;
import com.tomff.beesplus.items.BeeProtectionBoots;
import com.tomff.beesplus.items.BeeProtectionChestplate;
import com.tomff.beesplus.items.BeeProtectionHelmet;
import com.tomff.beesplus.items.BeeProtectionLeggings;
import com.tomff.beesplus.core.UpdateChecker;
import com.tomff.beesplus.core.gui.GuiHandler;
import com.tomff.beesplus.core.gui.GuiManager;
import com.tomff.beesplus.core.items.CustomItemManager;
import com.tomff.beesplus.localization.Localization;
import com.tomff.beesplus.localization.LocalizationWrapper;
import org.bstats.bukkit.Metrics;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.IOException;
import java.util.Locale;
public class BeesPlus extends JavaPlugin {
private GuiManager guiManager;
private CustomItemManager customItemManager;
private LocalizationWrapper localizationWrapper;
@Override
public void onEnable() {
saveDefaultConfig();
String locale = getConfig().getString("locale", Locale.ENGLISH.toLanguageTag());
localizationWrapper = new LocalizationWrapper(this, "locale");
try {
YamlConfiguration localeYamlFile = localizationWrapper.getLocale(locale);
Localization.load(localeYamlFile);
} catch (IOException e) {
getLogger().severe("Invalid locale! Please choose a valid locale.");
disablePlugin();
return;
} catch (InvalidConfigurationException e) {
getLogger().severe(e.getMessage());
getLogger().severe("Locale file corrupted or malformed! Please check your locale file.");
disablePlugin();
return;
} catch (IllegalArgumentException e) {
getLogger().severe(e.getMessage());
getLogger().severe("Error in the locale file! Please check your locale file.");
getLogger().severe("Maybe caused by a typo");
disablePlugin();
return;
}
guiManager = new GuiManager();
getServer().getPluginManager().registerEvents(new GuiHandler(this), this);
getServer().getPluginManager().registerEvents(new RightClickHandler(this), this);
boolean isProtectionSuitEnabled = getConfig().getBoolean("beeprotectionsuit.enabled", true);
if (isProtectionSuitEnabled) {
customItemManager = new CustomItemManager(this);
customItemManager.registerCustomItem("protection_boots", new BeeProtectionBoots());
customItemManager.registerCustomItem("protection_leggings", new BeeProtectionLeggings());
customItemManager.registerCustomItem("protection_chestplate", new BeeProtectionChestplate());
customItemManager.registerCustomItem("protection_helmet", new BeeProtectionHelmet());
customItemManager.registerRecipes();
getServer().getPluginManager().registerEvents(new DamageHandler(this), this);
}
Metrics metrics = new Metrics(this, 7065);
new UpdateChecker(this, 77224).getVersion(version -> {
if (!this.getDescription().getVersion().equalsIgnoreCase(version)) {
getLogger().info("A new update is available: BeesPlus " + version);
}
});
}
private void disablePlugin() {
getServer().getPluginManager().disablePlugin(this);
}
public GuiManager getGuiManager() {
return guiManager;
}
public CustomItemManager getCustomItemManager() {
return customItemManager;
}
}

View File

@ -0,0 +1,33 @@
package com.tomff.beesplus.core;
import com.tomff.beesplus.BeesPlus;
import org.bukkit.Bukkit;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Scanner;
import java.util.function.Consumer;
public class UpdateChecker {
private BeesPlus beesPlus;
private int resourceId;
public UpdateChecker(BeesPlus beesPlus, int resourceId) {
this.beesPlus = beesPlus;
this.resourceId = resourceId;
}
public void getVersion(final Consumer<String> consumer) {
Bukkit.getScheduler().runTaskAsynchronously(beesPlus, () -> {
try (InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream(); Scanner scanner = new Scanner(inputStream)) {
if (scanner.hasNext()) {
consumer.accept(scanner.next());
}
} catch (IOException exception) {
beesPlus.getLogger().info("Unable to query updates: " + exception.getMessage());
}
});
}
}

View File

@ -0,0 +1,46 @@
package com.tomff.beesplus.core.gui;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import java.util.HashMap;
public abstract class Gui {
private final HashMap<Integer, Icon> icons;
private final Inventory inventory;
protected Gui() {
this.icons = new HashMap<>(getSize());
this.inventory = Bukkit.createInventory(null, getSize(), getTitle());
}
public final void fill(Icon icon) {
for (int i = 0; i < getSize(); i++) {
if (!icons.containsKey(i)) {
setIcon(icon, i);
}
}
}
public final void setIcon(Icon icon, int... slots) {
for (int slot : slots) {
icons.put(slot, icon);
inventory.setItem(slot, icon.getItem());
}
}
public Icon getIcon(int slot) {
return icons.get(slot);
}
public Inventory getInventory() {
return inventory;
}
public abstract int getSize();
public abstract String getTitle();
public abstract void buildIcons();
}

View File

@ -0,0 +1,56 @@
package com.tomff.beesplus.core.gui;
import com.tomff.beesplus.BeesPlus;
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 java.util.UUID;
import java.util.function.Consumer;
public class GuiHandler implements Listener {
private final BeesPlus beesPlus;
private final GuiManager guiManager;
public GuiHandler(BeesPlus beesPlus) {
this.beesPlus = beesPlus;
this.guiManager = beesPlus.getGuiManager();
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
Inventory clickedInventory = event.getInventory();
Player player = (Player) event.getWhoClicked();
UUID uuid = player.getUniqueId();
if (guiManager.getOpenedGuis().containsKey(uuid) &&
guiManager.getOpenedGuis().get(uuid).getInventory().equals(clickedInventory)) {
event.setCancelled(true);
ItemStack clickedItem = event.getCurrentItem();
if (clickedItem == null || clickedItem.getType() == Material.AIR) return;
Gui gui = guiManager.getOpenedGuis().get(uuid);
Icon icon = gui.getIcon(event.getRawSlot());
if (icon == null) return;
Consumer<Player> callback = icon.getCallback();
if(callback == null) return;
icon.getCallback().accept(player);
}
}
}

View File

@ -0,0 +1,26 @@
package com.tomff.beesplus.core.gui;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.UUID;
public class GuiManager {
private HashMap<UUID, Gui> openedGuis;
public GuiManager() {
openedGuis = new HashMap<>();
}
public void openGui(Player player, Gui gui) {
openedGuis.put(player.getUniqueId(), gui);
gui.buildIcons();
player.openInventory(gui.getInventory());
}
public HashMap<UUID, Gui> getOpenedGuis() {
return openedGuis;
}
}

View File

@ -0,0 +1,26 @@
package com.tomff.beesplus.core.gui;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.function.Consumer;
public class Icon {
private ItemStack item;
private Consumer<Player> callback;
public Icon(ItemStack item, Consumer<Player> callback) {
this.item = item;
this.callback = callback;
}
public Consumer<Player> getCallback() {
return callback;
}
public ItemStack getItem() {
return item;
}
}

View File

@ -0,0 +1,21 @@
package com.tomff.beesplus.core.items;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
public abstract class CustomItem {
public abstract String[] getRecipe();
public abstract Map<Character, Material> getIngredients();
public abstract String getName();
public abstract Material getMaterial();
public ItemStack getItem() {
return new ItemBuilder(getMaterial())
.setName(getName())
.build();
}
}

View File

@ -0,0 +1,39 @@
package com.tomff.beesplus.core.items;
import com.tomff.beesplus.BeesPlus;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ShapedRecipe;
import java.util.HashMap;
import java.util.Map;
public class CustomItemManager {
private BeesPlus beesPlus;
private Map<String, CustomItem> customItems;
public CustomItemManager(BeesPlus beesPlus) {
this.beesPlus = beesPlus;
this.customItems = new HashMap<>();
}
public Map<String, CustomItem> getCustomItems() {
return customItems;
}
public void registerCustomItem(String id, CustomItem customItem) {
customItems.put(id, customItem);
}
public void registerRecipes() {
customItems.forEach((id, customItem) -> {
NamespacedKey namespacedKey = new NamespacedKey(beesPlus, id);
ShapedRecipe recipe = new ShapedRecipe(namespacedKey, customItem.getItem());
recipe.shape(customItem.getRecipe());
customItem.getIngredients().forEach(recipe::setIngredient);
Bukkit.addRecipe(recipe);
});
}
}

View File

@ -0,0 +1,39 @@
package com.tomff.beesplus.core.items;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays;
public class ItemBuilder {
private ItemStack item;
public ItemBuilder(Material material) {
this.item = new ItemStack(material, 1);
}
public ItemBuilder setName(String name) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
item.setItemMeta(meta);
}
return this;
}
public ItemBuilder setLore(String... lore) {
ItemMeta meta = item.getItemMeta();
meta.setLore(Arrays.asList(lore));
item.setItemMeta(meta);
return this;
}
public ItemStack build() {
return item;
}
}

View File

@ -0,0 +1,143 @@
package com.tomff.beesplus.gui;
import com.tomff.beesplus.core.gui.Gui;
import com.tomff.beesplus.core.gui.Icon;
import com.tomff.beesplus.core.items.ItemBuilder;
import com.tomff.beesplus.localization.Localization;
import net.minecraft.server.v1_15_R1.BlockPosition;
import net.minecraft.server.v1_15_R1.NBTTagCompound;
import net.minecraft.server.v1_15_R1.TileEntityBeehive;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Beehive;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Campfire;
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
import org.bukkit.inventory.ItemStack;
public class BeeHiveInfo extends Gui {
private final Beehive beehive;
private final int[] honeyLevelSlots = {
40, 41, 42,
31, 32, 33,
22, 23, 24,
13, 14, 15
};
public BeeHiveInfo(Beehive beehive) {
this.beehive = beehive;
}
@Override
public int getSize() {
return 6 * 9;
}
@Override
public String getTitle() {
return Localization.get(Localization.BEEHIVE_INFO_GUI_TITLE);
}
private void setHoneyLevelSlots(HoneyLevelIndicators indicator) {
ItemStack empty = new ItemBuilder(Material.AIR).build();
Icon emptyIcon = new Icon(empty, null);
ItemStack level = new ItemBuilder(indicator.getMaterial())
.setName(indicator.getColor() + indicator.getHumanName())
.build();
Icon levelIcon = new Icon(level, null);
for (int slot = 0; slot < indicator.getSlots(); slot++) {
setIcon(levelIcon, honeyLevelSlots[slot]);
}
for (int slot = indicator.getSlots(); slot < 12; slot++) {
setIcon(emptyIcon, honeyLevelSlots[slot]);
}
}
private boolean isSedated(Location location) {
for (int i = 1; i <= 5; i++) {
Block block = location.subtract(0, 1, 0).getBlock();
if (block.getType() == Material.CAMPFIRE && ((Campfire) block.getBlockData()).isLit()) {
return true;
}
}
return false;
}
private int getBeehivePopulation(Beehive beehive) {
CraftWorld craftWorld = (CraftWorld) beehive.getWorld();
TileEntityBeehive beehiveTile = (TileEntityBeehive) craftWorld.getHandle().getTileEntity(new BlockPosition(beehive.getX(), beehive.getY(), beehive.getZ()));
return beehiveTile.j();
}
private int getBeehiveMaxPopulation(Beehive beehive) {
CraftWorld craftWorld = (CraftWorld) beehive.getWorld();
TileEntityBeehive beehiveTile = (TileEntityBeehive) craftWorld.getHandle().getTileEntity(new BlockPosition(beehive.getX(), beehive.getY(), beehive.getZ()));
if (beehiveTile == null) {
return 3;
}
NBTTagCompound nbt = new NBTTagCompound();
beehiveTile.save(nbt);
return nbt.getInt("Bukkit.MaxEntities");
}
@Override
public void buildIcons() {
org.bukkit.block.data.type.Beehive beehiveData = (org.bukkit.block.data.type.Beehive) beehive.getBlockData();
ItemStack honeyLevel = new ItemBuilder(Material.HONEYCOMB)
.setName(Localization.get(Localization.BEEHIVE_INFO_GUI_HONEY_CAPACITY))
.setLore(Localization.get(Localization.BEEHIVE_INFO_GUI_HONEY_CAPACITY_DESC,
beehiveData.getHoneyLevel(), beehiveData.getMaximumHoneyLevel()))
.build();
Icon honeyLevelIcon = new Icon(honeyLevel, null);
setIcon(honeyLevelIcon, 10);
String isSedated = isSedated(beehive.getLocation()) ? Localization.get(Localization.BEEHIVE_INFO_GUI_SEDATED) :
Localization.get(Localization.BEEHIVE_INFO_GUI_NOT_SEDATED);
ItemStack beeCapacity = new ItemBuilder(Material.BEE_NEST)
.setName(Localization.get(Localization.BEEHIVE_INFO_GUI_BEE_CAPACITY))
.setLore(Localization.get(Localization.BEEHIVE_INFO_GUI_BEE_CAPACITY_DESC, getBeehivePopulation(beehive), getBeehiveMaxPopulation(beehive)),
isSedated)
.build();
Icon beeCapacityIcon = new Icon(beeCapacity, null);
setIcon(beeCapacityIcon, 19);
Location flowerLocation = beehive.getFlower();
String[] flowerLocationLore = (flowerLocation != null) ? new String[] {
ChatColor.GREEN + "X: " + ChatColor.GRAY + flowerLocation.getX(),
ChatColor.GREEN + "Y: " + ChatColor.GRAY + flowerLocation.getY(),
ChatColor.GREEN + "Z: " + ChatColor.GRAY + flowerLocation.getZ()
} : Localization.get(Localization.BEEHIVE_INFO_GUI_NO_TARGET_FLOWER_DESC).split("\\|\\|");
ItemStack flower = new ItemBuilder(Material.DANDELION)
.setName(Localization.get(Localization.BEEHIVE_INFO_GUI_FLOWER))
.setLore(flowerLocationLore)
.build();
Icon flowerIcon = new Icon(flower, null);
setIcon(flowerIcon, 37);
HoneyLevelIndicators honeyLevelIndicator = HoneyLevelIndicators.getFromLevel(beehiveData.getHoneyLevel());
setHoneyLevelSlots(honeyLevelIndicator);
ItemStack filler = new ItemBuilder(Material.WHITE_STAINED_GLASS_PANE)
.setName(" ")
.build();
Icon fillerIcon = new Icon(filler, null);
fill(fillerIcon);
}
}

View File

@ -0,0 +1,138 @@
package com.tomff.beesplus.gui;
import com.tomff.beesplus.core.gui.Gui;
import com.tomff.beesplus.core.gui.Icon;
import com.tomff.beesplus.core.items.ItemBuilder;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.*;
import org.bukkit.entity.Bee;
import org.bukkit.inventory.ItemStack;
public class BeeInfo extends Gui {
private final Bee bee;
public BeeInfo(Bee bee) {
this.bee = bee;
}
@Override
public int getSize() {
return 5 * 9;
}
@Override
public String getTitle() {
return Localization.get(Localization.BEE_INFO_GUI_TITLE);
}
@Override
public void buildIcons() {
ItemStack age = new ItemBuilder(Material.OAK_SIGN)
.setName(Localization.get(Localization.BEE_INFO_GUI_AGE))
.setLore(Localization.get(bee.isAdult() ? Localization.BEE_INFO_GUI_AGE_ADULT : Localization.BEE_INFO_GUI_AGE_BABY)
).build();
Icon ageIcon = new Icon(age, null);
setIcon(ageIcon, 4);
Material angerColor = (bee.getAnger() > 0) ? Material.RED_TERRACOTTA : Material.GREEN_TERRACOTTA;
ItemStack anger = new ItemBuilder(angerColor)
.setName(Localization.get(Localization.BEE_INFO_GUI_ANGER))
.setLore(Localization.get(Localization.BEE_INFO_GUI_ANGER_LEVEL_DESC, bee.getAnger()))
.build();
Icon angerIcon = new Icon(anger, null);
setIcon(angerIcon, 11);
Location hiveLocation = bee.getHive();
String[] hiveLocationLore = (hiveLocation != null) ? new String[] {
ChatColor.GREEN + "X: " + ChatColor.GRAY + hiveLocation.getX(),
ChatColor.GREEN + "Y: " + ChatColor.GRAY + hiveLocation.getY(),
ChatColor.GREEN + "Z: " + ChatColor.GRAY + hiveLocation.getZ()
} : Localization.get(Localization.BEE_INFO_GUI_NO_HIVE_DESC).split("\\|\\|");
ItemStack hive = new ItemBuilder(Material.BEE_NEST)
.setName(Localization.get(Localization.BEE_INFO_GUI_HIVE_LOCATION))
.setLore(hiveLocationLore)
.build();
Icon hiveIcon = new Icon(hive, null);
setIcon(hiveIcon, 29);
ItemStack mount = new ItemBuilder(Material.SADDLE)
.setName(Localization.get(Localization.BEE_INFO_GUI_RIDE))
.build();
Icon mountIcon = new Icon(mount, (player) -> {
double distance = player.getLocation().distance(bee.getLocation());
if (!player.hasPermission("beesplus.bee.ride")) {
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 2, 2);
Localization.sendMessage(player, Localization.BEE_INFO_GUI_RIDE_NO_PERMISSION);
return;
}
if (bee.getAnger() > 0) {
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 2, 2);
Localization.sendMessage(player, Localization.BEE_INFO_GUI_RIDE_ANGRY);
return;
}
if (distance <= 6) {
if (bee.getPassengers().size() >= 1) {
Localization.sendMessage(player, Localization.BEE_INFO_GUI_RIDE_ALREADY);
return;
}
player.closeInventory();
bee.addPassenger(player);
String title = Localization.get(Localization.RIDE_BEE_TITLE, player.getName());
String subtitle = Localization.get(Localization.RIDE_BEE_SUBTITLE, player.getName());
player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_FLAP, 10, 1);
player.sendTitle(title, subtitle, 10, 25, 10);
} else {
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 2, 2);
Localization.sendMessage(player, Localization.BEE_INFO_GUI_RIDE_TOO_FAR);
}
});
setIcon(mountIcon, 15);
ItemStack stung = new ItemBuilder(Material.IRON_SWORD)
.setName(Localization.get(Localization.BEE_INFO_GUI_HAS_STUNG))
.setLore(bee.hasStung() ? Localization.get(Localization.TEXT_YES) : Localization.get(Localization.TEXT_NO))
.build();
Icon stungIcon = new Icon(stung, null);
setIcon(stungIcon, 22);
ItemStack nectar = new ItemBuilder(Material.HONEYCOMB)
.setName(Localization.get(Localization.BEE_INFO_GUI_HAS_NECTAR))
.setLore(bee.hasNectar() ? Localization.get(Localization.TEXT_YES) : Localization.get(Localization.TEXT_NO))
.build();
Icon nectarIcon = new Icon(nectar, null);
setIcon(nectarIcon, 33);
ItemStack health = new ItemBuilder(Material.POTION)
.setName(Localization.get(Localization.BEE_INFO_GUI_HEALTH))
.setLore(Localization.get(Localization.BEE_INFO_GUI_HEALTH_DESC, bee.getHealth()))
.build();
Icon healthIcon = new Icon(health, null);
setIcon(healthIcon, 40);
ItemStack filler = new ItemBuilder(Material.WHITE_STAINED_GLASS_PANE)
.setName(" ")
.build();
Icon fillerIcon = new Icon(filler, null);
fill(fillerIcon);
}
}

View File

@ -0,0 +1,57 @@
package com.tomff.beesplus.gui;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import java.util.Arrays;
public enum HoneyLevelIndicators {
EMPTY(0, Material.AIR, null, null, 0),
LOW(1, Material.GREEN_TERRACOTTA, ChatColor.GREEN, Localization.HONEY_LOW, 3),
MEDIUM(2, Material.YELLOW_TERRACOTTA, ChatColor.GOLD, Localization.HONEY_MEDIUM, 6),
HIGH(3, Material.ORANGE_TERRACOTTA, ChatColor.RED, Localization.HONEY_HIGH, 9),
VERY_HIGH(4, Material.RED_TERRACOTTA, ChatColor.DARK_RED, Localization.HONEY_VERY_HIGH, 12);
private final int level;
private final Material material;
private final ChatColor color;
private final Localization localization;
private final int slots;
HoneyLevelIndicators(int level, Material material, ChatColor color, Localization localization, int slots) {
this.level = level;
this.material = material;
this.color = color;
this.localization = localization;
this.slots = slots;
}
public static HoneyLevelIndicators getFromLevel(int level) {
return Arrays.stream(values())
.filter((levelIndicator) -> levelIndicator.level == level)
.findFirst()
.orElse(VERY_HIGH);
}
public int getLevel() {
return level;
}
public ChatColor getColor() {
return color;
}
public int getSlots() {
return slots;
}
public Material getMaterial() {
return material;
}
public String getHumanName() {
return Localization.get(localization);
}
}

View File

@ -0,0 +1,56 @@
package com.tomff.beesplus.handlers;
import com.tomff.beesplus.BeesPlus;
import com.tomff.beesplus.core.items.CustomItem;
import com.tomff.beesplus.core.items.CustomItemManager;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.PlayerInventory;
import java.util.Objects;
import java.util.stream.Stream;
public class DamageHandler implements Listener {
private final CustomItemManager customItemManager;
private final CustomItem helmet;
private final CustomItem chestplate;
private final CustomItem leggings;
private final CustomItem boots;
private final double reduction;
public DamageHandler(BeesPlus beesPlus) {
this.customItemManager = beesPlus.getCustomItemManager();
this.helmet = customItemManager.getCustomItems().get("protection_helmet");
this.chestplate = customItemManager.getCustomItems().get("protection_chestplate");
this.leggings = customItemManager.getCustomItems().get("protection_leggings");
this.boots = customItemManager.getCustomItems().get("protection_boots");
this.reduction = beesPlus.getConfig().getDouble("beeprotectionsuit.reduction", 0.50);
}
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
if (event.getEntity() instanceof Player && event.getDamager() instanceof Bee) {
Player player = (Player) event.getEntity();
PlayerInventory playerInventory = player.getInventory();
if (Stream.of(playerInventory.getArmorContents()).allMatch(Objects::nonNull)) {
if (playerInventory.getHelmet().isSimilar(helmet.getItem()) &&
playerInventory.getChestplate().isSimilar(chestplate.getItem()) &&
playerInventory.getLeggings().isSimilar(leggings.getItem()) &&
playerInventory.getBoots().isSimilar(boots.getItem())) {
event.setDamage(reduction * event.getDamage());
}
}
}
}
}

View File

@ -0,0 +1,106 @@
package com.tomff.beesplus.handlers;
import com.tomff.beesplus.BeesPlus;
import com.tomff.beesplus.gui.BeeHiveInfo;
import com.tomff.beesplus.gui.BeeInfo;
import com.tomff.beesplus.core.gui.GuiManager;
import org.bukkit.EntityEffect;
import org.bukkit.Material;
import org.bukkit.block.Beehive;
import org.bukkit.block.Block;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
public class RightClickHandler implements Listener {
private final BeesPlus beesPlus;
private final GuiManager guiManager;
private final boolean removeAnger;
private final Material[] flowers = {
Material.SUNFLOWER, Material.DANDELION,
Material.POPPY, Material.BLUE_ORCHID,
Material.ALLIUM, Material.ORANGE_TULIP,
Material.PINK_TULIP, Material.RED_TULIP,
Material.WHITE_TULIP, Material.AZURE_BLUET,
Material.LILY_OF_THE_VALLEY, Material.OXEYE_DAISY,
Material.CORNFLOWER
};
public RightClickHandler(BeesPlus beesPlus) {
this.beesPlus = beesPlus;
this.guiManager = beesPlus.getGuiManager();
removeAnger = beesPlus.getConfig().getBoolean("healing.removeanger", true);
}
private boolean isFlower(ItemStack item) {
return Arrays.stream(flowers).anyMatch(flower -> item.getType().equals(flower));
}
@EventHandler
public void onInteraction(PlayerInteractEntityEvent event) {
Player player = event.getPlayer();
Entity target = event.getRightClicked();
if (event.getHand() != EquipmentSlot.HAND) {
return;
}
if (target instanceof Bee) {
Bee bee = (Bee) target;
if (player.isSneaking() && player.hasPermission("beesplus.bee.view")) {
event.setCancelled(true);
guiManager.openGui(player, new BeeInfo(bee));
return;
}
ItemStack itemInHand = player.getInventory().getItemInMainHand();
if (isFlower(itemInHand) && bee.getHealth() < 10 && player.hasPermission("beesplus.bee.heal")) {
event.setCancelled(true);
if (removeAnger) {
bee.setAnger(0);
}
bee.setHealth(bee.getHealth() + 1);
bee.playEffect(EntityEffect.LOVE_HEARTS);
player.getInventory().removeItem(new ItemStack(itemInHand.getType(), 1));
}
}
}
@EventHandler
public void onRightClick(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
Block clickedBlock = event.getClickedBlock();
if (event.getHand() != EquipmentSlot.HAND) {
return;
}
if (action == Action.RIGHT_CLICK_BLOCK && player.isSneaking() && clickedBlock != null) {
if ((clickedBlock.getType().equals(Material.BEEHIVE) || clickedBlock.getType().equals(Material.BEE_NEST)) && player.hasPermission("beesplus.beehive.view")) {
event.setCancelled(true);
Beehive beehive = (Beehive) clickedBlock.getState();
guiManager.openGui(player, new BeeHiveInfo(beehive));
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
import java.util.HashMap;
import java.util.Map;
public class BeeProtectionBoots extends CustomItem {
@Override
public String[] getRecipe() {
return new String[] {
"SSS",
"SBS",
"SSS"
};
}
@Override
public Map<Character, Material> getIngredients() {
Map<Character, Material> ingredients = new HashMap<>();
ingredients.put('S', Material.STRING);
ingredients.put('B', Material.CHAINMAIL_BOOTS);
return ingredients;
}
@Override
public String getName() {
return Localization.get(Localization.BEE_PROTECTION_BOOTS);
}
@Override
public Material getMaterial() {
return Material.CHAINMAIL_BOOTS;
}
}

View File

@ -0,0 +1,39 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
import java.util.HashMap;
import java.util.Map;
public class BeeProtectionChestplate extends CustomItem {
@Override
public String[] getRecipe() {
return new String[] {
"SSS",
"SCS",
"SSS"
};
}
@Override
public Map<Character, Material> getIngredients() {
Map<Character, Material> ingredients = new HashMap<>();
ingredients.put('S', Material.STRING);
ingredients.put('C', Material.CHAINMAIL_CHESTPLATE);
return ingredients;
}
@Override
public String getName() {
return Localization.get(Localization.BEE_PROTECTION_CHESTPLATE);
}
@Override
public Material getMaterial() {
return Material.CHAINMAIL_CHESTPLATE;
}
}

View File

@ -0,0 +1,39 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
import java.util.HashMap;
import java.util.Map;
public class BeeProtectionHelmet extends CustomItem {
@Override
public String[] getRecipe() {
return new String[] {
"SSS",
"SAS",
"SSS"
};
}
@Override
public Map<Character, Material> getIngredients() {
Map<Character, Material> ingredients = new HashMap<>();
ingredients.put('S', Material.STRING);
ingredients.put('A', Material.CHAINMAIL_HELMET);
return ingredients;
}
@Override
public String getName() {
return Localization.get(Localization.BEE_PROTECTION_HELMET);
}
@Override
public Material getMaterial() {
return Material.CHAINMAIL_HELMET;
}
}

View File

@ -0,0 +1,39 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
import java.util.HashMap;
import java.util.Map;
public class BeeProtectionLeggings extends CustomItem {
@Override
public String[] getRecipe() {
return new String[] {
"SSS",
"SLS",
"SSS"
};
}
@Override
public Map<Character, Material> getIngredients() {
Map<Character, Material> ingredients = new HashMap<>();
ingredients.put('S', Material.STRING);
ingredients.put('L', Material.CHAINMAIL_LEGGINGS);
return ingredients;
}
@Override
public String getName() {
return Localization.get(Localization.BEE_PROTECTION_LEGGINGS);
}
@Override
public Material getMaterial() {
return Material.CHAINMAIL_LEGGINGS;
}
}

View File

@ -0,0 +1,101 @@
package com.tomff.beesplus.localization;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.HashMap;
import java.util.Map;
public enum Localization {
TEXT_YES,
TEXT_NO,
BEEHIVE_INFO_GUI_TITLE,
BEEHIVE_INFO_GUI_HONEY_CAPACITY,
BEEHIVE_INFO_GUI_HONEY_CAPACITY_DESC("current", "maximum"),
BEEHIVE_INFO_GUI_BEE_CAPACITY,
BEEHIVE_INFO_GUI_BEE_CAPACITY_DESC("current", "maximum"),
BEEHIVE_INFO_GUI_SEDATED,
BEEHIVE_INFO_GUI_NOT_SEDATED,
BEEHIVE_INFO_GUI_FLOWER,
BEEHIVE_INFO_GUI_NO_TARGET_FLOWER_DESC,
BEE_INFO_GUI_TITLE,
BEE_INFO_GUI_AGE,
BEE_INFO_GUI_AGE_ADULT,
BEE_INFO_GUI_AGE_BABY,
BEE_INFO_GUI_ANGER,
BEE_INFO_GUI_ANGER_LEVEL_DESC("level"),
BEE_INFO_GUI_HIVE_LOCATION,
BEE_INFO_GUI_NO_HIVE_DESC,
BEE_INFO_GUI_RIDE,
BEE_INFO_GUI_RIDE_NO_PERMISSION,
BEE_INFO_GUI_RIDE_ANGRY,
BEE_INFO_GUI_RIDE_ALREADY,
BEE_INFO_GUI_RIDE_TOO_FAR,
BEE_INFO_GUI_HAS_STUNG,
BEE_INFO_GUI_HAS_NECTAR,
BEE_INFO_GUI_HEALTH,
BEE_INFO_GUI_HEALTH_DESC("health"),
RIDE_BEE_TITLE("name"),
RIDE_BEE_SUBTITLE("name"),
BEE_PROTECTION_HELMET,
BEE_PROTECTION_CHESTPLATE,
BEE_PROTECTION_LEGGINGS,
BEE_PROTECTION_BOOTS,
HONEY_LOW,
HONEY_MEDIUM,
HONEY_HIGH,
HONEY_VERY_HIGH;
private final String[] placeholders;
Localization(String... placeholders) {
this.placeholders = placeholders;
}
public String[] getPlaceholders() {
return placeholders;
}
private static final Map<Localization, String> messages = new HashMap<>();
public static void load(YamlConfiguration localeFile) throws IllegalArgumentException {
messages.clear();
localeFile.getValues(false).forEach((key, value) -> {
Localization localeKey = Localization.valueOf(key.toUpperCase());
String message = (String) value;
if (message != null) {
messages.put(localeKey, ChatColor.translateAlternateColorCodes('&', message));
}
});
}
public static String get(Localization localization, Object... objects) {
String message = messages.get(localization);
if (message == null) {
return null;
}
if (objects != null && objects.length != 0 && localization.getPlaceholders() != null && localization.getPlaceholders().length > 0) {
String[] args = localization.getPlaceholders();
for (int i = 0; i < objects.length; i++) {
message = message.replace("%" + args[i] + "%", objects[i].toString());
}
}
return message;
}
public static void sendMessage(CommandSender sender, Localization localization, Object... objects) {
String message = get(localization, objects);
if (message != null) {
sender.sendMessage(message);
}
}
}

View File

@ -0,0 +1,35 @@
package com.tomff.beesplus.localization;
import com.tomff.beesplus.BeesPlus;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
public class LocalizationWrapper {
private final BeesPlus beesPlus;
private final String basePath;
public LocalizationWrapper(BeesPlus beesPlus, String path) {
this.beesPlus = beesPlus;
this.basePath = path;
}
public YamlConfiguration getLocale(String locale) throws IOException, InvalidConfigurationException {
String path = Paths.get(basePath, locale + ".yml").toString();
File localeFile = new File(beesPlus.getDataFolder(), path);
if(!localeFile.exists()) {
beesPlus.saveResource(path, false);
}
YamlConfiguration localeYaml = new YamlConfiguration();
localeYaml.load(localeFile);
return localeYaml;
}
}

View File

@ -0,0 +1,26 @@
# Language Settings
#
# Available locale: en, pt
#
# If you want to create your own, the file name must match the locale name.
# Example:
# - Create es.yml in locale/
# - Set locale: es
#
locale: en
# Protection suit settings
#
# enabled: true or false
# reduction: A 0.5 reduction is a 50% reduction in damage. 0.6 is 60% and so on...
#
beeprotectionsuit:
enabled: true
reduction: 0.50
# Bee healing settings
#
# removeanger: remove anger from bees when they are healed?
#
healing:
removeanger: true

View File

@ -0,0 +1,79 @@
####################
# Yes or no
####################
text_yes: "&aYes"
text_no: "&cNo"
###################
# Beehive GUI
###################
beehive_info_gui_title: "&8Beehive Info"
beehive_info_gui_honey_capacity: "&fHoney Capacity"
beehive_info_gui_honey_capacity_desc: "&aCapacity: &7%current%/%maximum%"
beehive_info_gui_bee_capacity: "&fBee Capacity"
beehive_info_gui_bee_capacity_desc: "&aCapacity: &7%current%/%maximum% bees"
beehive_info_gui_sedated: "&aSedated"
beehive_info_gui_not_sedated: "&cNot sedated"
beehive_info_gui_flower: "&fFlower"
# Use || to a create a new line
beehive_info_gui_no_target_flower_desc: "&aThis hive doesn't||&ahave a target flower!"
honey_low: "Low"
honey_medium: "Medium"
honey_high: "High"
honey_very_high: "Very High"
###################
# Bee GUI
###################
bee_info_gui_title: "&8Bee Info"
bee_info_gui_age: "&fAge"
bee_info_gui_age_adult: "&aAdult"
bee_info_gui_age_baby: "&aBaby"
bee_info_gui_anger: "&fAnger"
# Use %level% as a placeholder for the bee's anger level
bee_info_gui_anger_level_desc: "&aAnger level: &7%level%"
bee_info_gui_hive_location: "&fHive Location"
# Use || to a create a new line
bee_info_gui_no_hive_desc: "&aThis bee doesn't||&ahave a hive!"
bee_info_gui_ride: "&fRide"
bee_info_gui_ride_no_permission: "&cYou don't have permission to ride bees!"
bee_info_gui_ride_angry: "&cYou can't ride angry bees!"
bee_info_gui_ride_already: "&cSomeone else is already riding this bee!"
bee_info_gui_ride_too_far: "&cYou're too far away to ride this bee!"
bee_info_gui_has_stung: "&fHas stung?"
bee_info_gui_has_nectar: "&fHas nectar?"
bee_info_gui_health: "&fHealth"
# Use %health% to represent the bee's health
bee_info_gui_health_desc: "&aHealth: &7%health% ❤"
###################
# Riding a bee title
# Use %name% as a placeholder for the player's name
###################
ride_bee_title: "&6You're now riding"
ride_bee_subtitle: "&6a bee &8%name%&6!"
###################
# Protection suit name
###################
bee_protection_helmet: "&6Bee Protection Helmet"
bee_protection_chestplate: "&6Bee Protection Chestplate"
bee_protection_leggings: "&6Bee Protection Leggings"
bee_protection_boots: "&6Bee Protection Boots"

View File

@ -0,0 +1,79 @@
####################
# Yes or no
####################
text_yes: "&aSim"
text_no: "&cNão"
###################
# Beehive GUI
###################
beehive_info_gui_title: "&8Informação da colmeia"
beehive_info_gui_honey_capacity: "&fCapacidade de mel"
beehive_info_gui_honey_capacity_desc: "&aCapacidade: &7%current%/%maximum%"
beehive_info_gui_bee_capacity: "&fCapacidade de abelhas"
beehive_info_gui_bee_capacity_desc: "&aCapacidade: &7%current%/%maximum% abelhas"
beehive_info_gui_sedated: "&aSedada"
beehive_info_gui_not_sedated: "&cNão sedada"
beehive_info_gui_flower: "&fFlor"
# Use || to switch to a create a new line
beehive_info_gui_no_target_flower_desc: "&aEsta colmeia não||&atem uma flor!"
honey_low: "Baixo"
honey_medium: "Médio"
honey_high: "Alto"
honey_very_high: "Muito alto"
###################
# Bee GUI
###################
bee_info_gui_title: "&8Informação da abelha"
bee_info_gui_age: "&fIdade"
bee_info_gui_age_adult: "&aAdulta"
bee_info_gui_age_baby: "&aBébé"
bee_info_gui_anger: "&fRaiva"
# Use %level% as a placeholder for the bee's anger level
bee_info_gui_anger_level_desc: "&aNível de raiva: &7%level%"
bee_info_gui_hive_location: "&fLocalização da colmeia"
# Use || to a create a new line
bee_info_gui_no_hive_desc: "&aEsta abelha não||&atem uma colmeia!"
bee_info_gui_ride: "&fMontar"
bee_info_gui_ride_no_permission: "&cNão tens permissão para montar abelhas!"
bee_info_gui_ride_angry: "&cNão podes montar abelhas irritadas!"
bee_info_gui_ride_already: "&cAlguem já está a montar esta abelha!"
bee_info_gui_ride_too_far: "&cEstá muito longe para montar a abelha!"
bee_info_gui_has_stung: "&fJá picou?"
bee_info_gui_has_nectar: "&fTem nectar?"
bee_info_gui_health: "&fVida"
# Use %health% to represent the bee's health
bee_info_gui_health_desc: "&aVida: &7%health% ❤"
###################
# Riding a bee title
# Use %name% as a placeholder for the player's name
###################
ride_bee_title: "&6Estás a montar"
ride_bee_subtitle: "&6uma abelha &8%name%&6!"
###################
# Protection suit name
###################
bee_protection_helmet: "&6Proteção contra abelhas"
bee_protection_chestplate: "&6Proteção contra abelhas"
bee_protection_leggings: "&6Proteção contra abelhas"
bee_protection_boots: "&6Proteção contra abelhas"

View File

@ -0,0 +1,15 @@
name: BeesPlus
author: Attlantiz
version: ${project.version}
main: com.tomff.beesplus.BeesPlus
api-version: 1.15
permissions:
beesplus.bee.view:
default: op
beesplus.bee.heal:
default: op
beesplus.bee.ride:
default: op
beesplus.beehive.view:
default: op

BIN
static/gui.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

BIN
static/header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 KiB